diff options
Diffstat (limited to 'usr/src/lib')
514 files changed, 55223 insertions, 35018 deletions
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index bae90c4045..9162656666 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -73,6 +73,7 @@ SUBDIRS += \ libcommputil \ libresolv \ libresolv2 .WAIT \ + libresolv2_joy .WAIT \ libw .WAIT \ libintl .WAIT \ ../cmd/sgs/librtld_db \ @@ -85,6 +86,8 @@ SUBDIRS += \ librt \ libadm \ libctf \ + libbrand .WAIT \ + libzonecfg .WAIT \ libdtrace \ libdtrace_jni \ libcurses \ @@ -111,6 +114,7 @@ SUBDIRS += \ libcryptoutil \ libinetutil \ libipadm \ + libipd \ libipmp \ libiscsit \ libkmf \ @@ -159,7 +163,8 @@ SUBDIRS += \ librdc \ libinstzones \ libpkg \ - libpcidb + libpcidb \ + libumem_trampoline SUBDIRS += \ passwdutil \ @@ -187,7 +192,6 @@ $(CLOSED_BUILD)SUBDIRS += \ $(CLOSED)/lib/libike SUBDIRS += \ nsswitch \ - print \ libuutil \ libscf \ libinetsvc \ @@ -205,10 +209,10 @@ SUBDIRS += \ libwrap \ libxcurses \ libxcurses2 \ - libbrand .WAIT \ - libzonecfg \ + libzdoor \ libzoneinfo \ libzonestat \ + libsmartsshd \ libtsnet \ libtsol \ gss_mechs/mech_spnego \ @@ -223,7 +227,6 @@ SUBDIRS += \ raidcfg_plugins \ cfgadm_plugins \ libmail \ - lvm \ libsmedia \ libipp \ libdiskmgt \ @@ -240,10 +243,7 @@ SUBDIRS += \ libzfs_core \ libzfs \ libbe \ - pylibbe \ libzfs_jni \ - pyzfs \ - pysolaris \ libmapid \ brand \ policykit \ @@ -304,9 +304,6 @@ fm: \ # NOWAIT_SUBDIRS= $(SUBDIRS:.WAIT=) -DCSUBDIRS = \ - lvm - MSGSUBDIRS= \ abi \ auditd_plugins \ @@ -362,12 +359,11 @@ MSGSUBDIRS= \ libwanbootutil \ libzfs \ libzonecfg \ - lvm \ + libzdoor \ + libsmartsshd \ madv \ mpss \ pam_modules \ - pyzfs \ - pysolaris \ rpcsec_gss \ libreparse MSGSUBDIRS += \ @@ -415,6 +411,7 @@ HDRSUBDIRS= \ libfstyp \ libgen \ libipadm \ + libipd \ libipsecutil \ libinetsvc \ libinetutil \ @@ -486,7 +483,6 @@ HDRSUBDIRS= \ libzonestat \ hal \ policykit \ - lvm \ pkcs11 \ passwdutil \ ../cmd/sendmail/libmilter \ @@ -574,7 +570,7 @@ gss_mechs/mech_krb5: libgss libnsl libsocket libresolv pkcs11 libadt_jni: libbsm libast: libsocket libadutils: libldap5 libresolv libsocket libnsl -nsswitch: libadutils libidmap +nsswitch: libadutils libidmap libresolv2_joy libbe: libzfs libbsm: libtsol libcmd: libsum libast libsocket libnsl @@ -628,6 +624,8 @@ libpool: libnvpair libexacct libpp: libast libzonecfg: libc libsocket libnsl libuuid libnvpair libsysevent libsec \ libbrand libpool libscf +libzdoor: libc libzonecfg libcontract +libsmartsshd: libc libcontract libproc: ../cmd/sgs/librtld_db ../cmd/sgs/libelf libctf libsaveargs libproject: libpool libproc libsecdb libtermcap: libcurses @@ -643,8 +641,6 @@ librestart: libuutil libscf libsaveargs: libdisasm ../cmd/sgs/libdl: ../cmd/sgs/libconv ../cmd/sgs/libelf: ../cmd/sgs/libconv -pkcs11: libcryptoutil -print: libldap5 udapl/udapl_tavor: udapl/libdat libzfs: libdevid libgen libnvpair libuutil \ libadm libavl libefi libidmap libmd libzfs_core @@ -669,9 +665,6 @@ sun_fc: libdevinfo libsysevent libnvpair libsun_ima: libdevinfo libsysevent libnsl sun_sas: libdevinfo libsysevent libnvpair libkstat libdevid libgrubmgmt: libdevinfo libzfs libfstyp -pylibbe: libbe libzfs -pyzfs: libnvpair libzfs -pysolaris: libsec libidmap libreparse: libnvpair libhotplug: libnvpair cfgadm_plugins: libhotplug diff --git a/usr/src/lib/Makefile.astmsg b/usr/src/lib/Makefile.astmsg index 096805e825..ff8202d03a 100644 --- a/usr/src/lib/Makefile.astmsg +++ b/usr/src/lib/Makefile.astmsg @@ -47,8 +47,8 @@ MSGLIBNAME= $(LIBRARY:.a=) ASTMSGCATALOG= $(ROOT)/usr/lib/locale/C/LC_MESSAGES/$(MSGLIBNAME) $(DO_BUILD_AST_CATALOGS)ASTMSGCC= \ - PATH="/usr/ast/bin/:/bin:/usr/bin" \ - /usr/bin/ksh93 /usr/ast/bin/msgcc >>msgcc.out 2>&1 + PATH="$(ASTBINDIR):/bin:/usr/bin" \ + /usr/bin/ksh93 $(MSGCC) >>msgcc.out 2>&1 ASTMSGS= $(OBJECTS:%.o=msgs/%.mso) diff --git a/usr/src/lib/brand/Makefile b/usr/src/lib/brand/Makefile index 05bfc54764..db59df2efc 100644 --- a/usr/src/lib/brand/Makefile +++ b/usr/src/lib/brand/Makefile @@ -30,7 +30,7 @@ include ../../Makefile.master # Build everything in parallel; use .WAIT for dependencies .PARALLEL: -SUBDIRS= shared .WAIT sn1 solaris10 ipkg labeled $($(MACH)_SUBDIRS) +SUBDIRS= shared .WAIT sn1 sngl solaris10 ipkg labeled $($(MACH)_SUBDIRS) MSGSUBDIRS= solaris10 shared $($(MACH)_MSGSUBDIRS) all := TARGET= all diff --git a/usr/src/lib/brand/shared/zone/common.ksh b/usr/src/lib/brand/shared/zone/common.ksh index 52441d814a..463ba7a51a 100644 --- a/usr/src/lib/brand/shared/zone/common.ksh +++ b/usr/src/lib/brand/shared/zone/common.ksh @@ -333,10 +333,12 @@ post_unpack() # # Check if the image was created with a valid libc.so.1. # - hwcap=`moe -v -32 $ZONEROOT/lib/libc.so.1 2>&1` - if (( $? != 0 )); then - vlog "$f_hwcap_info" "$hwcap" - fail_fatal "$f_sanity_hwcap" + if [[ -f $ZONEROOT/lib/libc.so.1 ]]; then + hwcap=`moe -v -32 $ZONEROOT/lib/libc.so.1 2>&1` + if (( $? != 0 )); then + vlog "$f_hwcap_info" "$hwcap" + fail_fatal "$f_sanity_hwcap" + fi fi ( cd "$ZONEROOT" && \ @@ -1003,41 +1005,36 @@ install_image() return 0 } -# Setup i18n output -TEXTDOMAIN="SUNW_OST_OSCMD" -export TEXTDOMAIN - -e_cannot_wrap=$(gettext "%s: error: wrapper file already exists") -e_baddir=$(gettext "Invalid '%s' directory within the zone") -e_badfile=$(gettext "Invalid '%s' file within the zone") -e_path_abs=$(gettext "Pathname specified to -a '%s' must be absolute.") -e_not_found=$(gettext "%s: error: file or directory not found.") -e_install_abort=$(gettext "Installation aborted.") -e_not_readable=$(gettext "Cannot read directory '%s'") -e_not_dir=$(gettext "Error: must be a directory") -e_unknown_archive=$(gettext "Error: Unknown archive format. Must be a flash archive, a cpio archive (can also be gzipped or bzipped), a pax XUSTAR archive, or a level 0 ufsdump archive.") -e_absolute_archive=$(gettext "Error: archive contains absolute paths instead of relative paths.") -e_mismatch_archive=$(gettext "Error: the archive top-level directory (%s) does not match the zonepath (%s).") -e_tmpfile=$(gettext "Unable to create temporary file") -e_root_full=$(gettext "Zonepath root %s exists and contains data; remove or move aside prior to install.") -f_mkdir=$(gettext "Unable to create directory %s.") -f_chmod=$(gettext "Unable to chmod directory %s.") -f_chown=$(gettext "Unable to chown directory %s.") -f_hwcap_info=$(gettext "HWCAP: %s\n") -f_sanity_hwcap=$(gettext \ -"The image was created with an incompatible libc.so.1 hwcap lofs mount.\n"\ +e_cannot_wrap="%s: error: wrapper file already exists" +e_baddir="Invalid '%s' directory within the zone" +e_badfile="Invalid '%s' file within the zone" +e_path_abs="Pathname specified to -a '%s' must be absolute." +e_not_found="%s: error: file or directory not found." +e_install_abort="Installation aborted." +e_not_readable="Cannot read directory '%s'" +e_not_dir="Error: must be a directory" +e_unknown_archive="Error: Unknown archive format. Must be a flash archive, a cpio archive (can also be gzipped or bzipped), a pax XUSTAR archive, or a level 0 ufsdump archive." +e_absolute_archive="Error: archive contains absolute paths instead of relative paths." +e_mismatch_archive="Error: the archive top-level directory (%s) does not match the zonepath (%s)." +e_tmpfile="Unable to create temporary file" +e_root_full="Zonepath root %s exists and contains data; remove or move aside prior to install." +f_mkdir="Unable to create directory %s." +f_chmod="Unable to chmod directory %s." +f_chown="Unable to chown directory %s." +f_hwcap_info="HWCAP: %s\n" +f_sanity_hwcap="The image was created with an incompatible libc.so.1 hwcap lofs mount.\n"\ " The zone will not boot on this platform. See the zone's\n"\ -" documentation for the recommended way to create the archive.") +" documentation for the recommended way to create the archive." -m_analyse_archive=$(gettext "Analysing the archive") +m_analyse_archive="Analysing the archive" -not_readable=$(gettext "Cannot read file '%s'") -not_flar=$(gettext "Input is not a flash archive") -bad_flar=$(gettext "Flash archive is a corrupt") -bad_zfs_flar=$(gettext "Flash archive contains a ZFS send stream.\n\tRecreate the flar using the -L option with cpio or pax.") -f_unpack_failed=$(gettext "Unpacking the archive failed") -unknown_archiver=$(gettext "Archiver %s is not supported") -cmd_not_exec=$(gettext "Required command '%s' not executable!") +not_readable="Cannot read file '%s'" +not_flar="Input is not a flash archive" +bad_flar="Flash archive is a corrupt" +bad_zfs_flar="Flash archive contains a ZFS send stream.\n\tRecreate the flar using the -L option with cpio or pax." +f_unpack_failed="Unpacking the archive failed" +unknown_archiver="Archiver %s is not supported" +cmd_not_exec="Required command '%s' not executable!" # # Exit values used by the script, as #defined in <sys/zone.h> diff --git a/usr/src/lib/brand/shared/zone/uninstall.ksh b/usr/src/lib/brand/shared/zone/uninstall.ksh index 468a7ed92f..923363c864 100644 --- a/usr/src/lib/brand/shared/zone/uninstall.ksh +++ b/usr/src/lib/brand/shared/zone/uninstall.ksh @@ -35,31 +35,31 @@ bname=`basename $0` # # error messages # -m_usage=$(gettext "Usage: %s: [-hFn]") - -m_1_zfs_promote=$(gettext "promoting '%s'.") -m_1_zfs_destroy=$(gettext "destroying '%s'.") -m_2_zfs_rename=$(gettext "renaming '%s' to '%s'.") -m_3_zfs_set=$(gettext "setting property %s='%s' for '%s'.") -m_rm_r=$(gettext "recursively deleting '%s'.") -m_rm=$(gettext "deleting '%s'.") - -w_no_ds=$(gettext "Warning: no zonepath dataset found.") - -f_usage_err=$(gettext "Error: invalid usage") -f_abort=$(gettext "Error: internal error detected, aborting.") -f_1_zfs_promote=$(gettext "Error: promoting ZFS dataset '%s'.") -f_2_zfs_rename=$(gettext "Error: renaming ZFS dataset '%s' to '%s'.") -f_3_zfs_set=$(gettext "Error: setting ZFS propery %s='%s' for '%s'.") -f_1_zfs_destroy=$(gettext "Error: destroying ZFS dataset.") -f_2_zfs_get=$(gettext "Error: reading ZFS dataset property '%s' from '%s'.") -f_user_snap=$(gettext "Error: user snapshot(s) detected.") -f_stray_snap=$(gettext "Error: uncloned snapshot(s) detected.") -f_stray_clone=$(gettext "Error: cloned zone datasets found outsize of zone.") -f_rm_snap=$(gettext "Error: please delete snapshot(s) and retry uninstall.") -f_rm_clone=$(gettext "Error: please delete clone(s) and retry uninstall.") -f_iu_clone=$(gettext "Error: cloned zone dataset(s) in use.") -f_dis_clone=$(gettext "Error: please stop using clone(s) and retry uninstall.") +m_usage="Usage: %s: [-hFn]" + +m_1_zfs_promote="promoting '%s'." +m_1_zfs_destroy="destroying '%s'." +m_2_zfs_rename="renaming '%s' to '%s'." +m_3_zfs_set="setting property %s='%s' for '%s'." +m_rm_r="recursively deleting '%s'." +m_rm="deleting '%s'." + +w_no_ds="Warning: no zonepath dataset found." + +f_usage_err="Error: invalid usage" +f_abort="Error: internal error detected, aborting." +f_1_zfs_promote="Error: promoting ZFS dataset '%s'." +f_2_zfs_rename="Error: renaming ZFS dataset '%s' to '%s'." +f_3_zfs_set="Error: setting ZFS propery %s='%s' for '%s'." +f_1_zfs_destroy="Error: destroying ZFS dataset." +f_2_zfs_get="Error: reading ZFS dataset property '%s' from '%s'." +f_user_snap="Error: user snapshot(s) detected." +f_stray_snap="Error: uncloned snapshot(s) detected." +f_stray_clone="Error: cloned zone datasets found outsize of zone." +f_rm_snap="Error: please delete snapshot(s) and retry uninstall." +f_rm_clone="Error: please delete clone(s) and retry uninstall." +f_iu_clone="Error: cloned zone dataset(s) in use." +f_dis_clone="Error: please stop using clone(s) and retry uninstall." # # functions diff --git a/usr/src/lib/brand/sngl/Makefile b/usr/src/lib/brand/sngl/Makefile new file mode 100644 index 0000000000..780acc21e1 --- /dev/null +++ b/usr/src/lib/brand/sngl/Makefile @@ -0,0 +1,51 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2012, Joyent, Inc. All rights reserved. +# + +default: all + +include Makefile.sngl + +# Build everything in parallel; use .WAIT for dependencies +.PARALLEL: + +SUBDIRS = sngl_brand zone +MSGSUBDIRS = zone + +all := TARGET= all +install := TARGET= install +clean := TARGET= clean +clobber := TARGET= clobber +lint := TARGET= lint +_msg := TARGET= _msg + +.KEEP_STATE: + +all install clean clobber lint: $(SUBDIRS) + +_msg: $(MSGSUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/lib/brand/sngl/Makefile.sngl b/usr/src/lib/brand/sngl/Makefile.sngl new file mode 100644 index 0000000000..0c7a280696 --- /dev/null +++ b/usr/src/lib/brand/sngl/Makefile.sngl @@ -0,0 +1,28 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2012 Joyent, Inc. All rights reserved. +# + +BRAND = sngl + +include $(SRC)/lib/brand/Makefile.brand + diff --git a/usr/src/lib/brand/sngl/sngl_brand/Makefile b/usr/src/lib/brand/sngl/sngl_brand/Makefile new file mode 100644 index 0000000000..4b667e1fa8 --- /dev/null +++ b/usr/src/lib/brand/sngl/sngl_brand/Makefile @@ -0,0 +1,47 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include $(SRC)/lib/Makefile.lib + +default: all + +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install +lint := TARGET= lint +_msg := TARGET= _msg + +.KEEP_STATE: + +all install clean clobber lint _msg: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: diff --git a/usr/src/lib/brand/sngl/sngl_brand/Makefile.com b/usr/src/lib/brand/sngl/sngl_brand/Makefile.com new file mode 100644 index 0000000000..070a03dcb5 --- /dev/null +++ b/usr/src/lib/brand/sngl/sngl_brand/Makefile.com @@ -0,0 +1,76 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, Joyent, Inc. All rights reserved. +# + +LIBRARY = sngl_brand.a +VERS = .1 +COBJS = sngl_brand.o +ASOBJS = crt.o handler.o runexe.o brand_util.o +OBJECTS = $(COBJS) + +include ../../Makefile.sngl +include $(SRC)/lib/Makefile.lib + +SRCDIR = ../common +UTSBASE = $(SRC)/uts + +LIBS = $(DYNLIB) +CSRCS = $(COBJS:%o=../common/%c) +SHAREDOBJS = $(ASOBJS:%o=$(ISAOBJDIR)/%o) +SRCS = $(CSRCS) + +# +# Note that the architecture specific makefiles MUST update DYNFLAGS to +# explicitly specify an interpreter for the brand emulation library so that we +# use /lib/ld.so.1 or /lib/64/ld.so.1, which in a sngl zone is the system +# linker. +# +# Note that since the linker is used to setup processes before libc is loaded, +# it makes system calls directly (ie avoiding libc), and it makes these system +# calls before our library has been initialized. Since our library hasn't been +# initialized yet, there's no way for us to intercept and emulate any of those +# system calls. Luckily we don't have to. +# +# Note that we make sure to link our brand emulation library to libmapmalloc. +# This is required because in most cases there will be two copies of libc in +# the same process and we don't want them to fight over the heap. So for our +# brand library we link against libmapmalloc so that if we (our or copy of +# libc) try to allocate any memory it will be done via mmap() instead of brk(). +# +CPPFLAGS += -D_REENTRANT -U_ASM \ + -I. -I$(BRAND_SHARED)/brand/sys -I$(UTSBASE)/common/brand/sngl +CFLAGS += $(CCVERBOSE) +DYNFLAGS += $(DYNFLAGS_$(CLASS)) +DYNFLAGS += $(BLOCAL) $(ZNOVERSION) -Wl,-e_start +LDLIBS += -lc -lmapmalloc + +$(LIBS):= PICS += $(SHAREDOBJS) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include $(SRC)/lib/Makefile.targ diff --git a/usr/src/lib/brand/sngl/sngl_brand/amd64/Makefile b/usr/src/lib/brand/sngl/sngl_brand/amd64/Makefile new file mode 100644 index 0000000000..d019eaf841 --- /dev/null +++ b/usr/src/lib/brand/sngl/sngl_brand/amd64/Makefile @@ -0,0 +1,48 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, Joyent, Inc. All rights reserved. +# + +ISAOBJDIR = $(BRAND_SHARED)/brand/amd64/pics/ + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 + +CPPFLAGS += -I$(BRAND_SHARED)/brand/amd64 + +# +# see ../Makefile.com for why we MUST explicity make ld.so.1 our interpreter +# +DYNFLAGS += -Wl,-I/lib/64/ld.so.1 +CPPFLAGS += -D_SYSCALL32 + +# Note that we also set the runtime path for the emulation library to point +# into /system. This is an attempt to ensure that our brand library get's the +# native version of libmapmallc. +# +DYNFLAGS += -R/lib/64 -R/system/usr/lib/64 + +CLEANFILES += $(DYNLIB) +CLOBBERFILES += $(ROOTLIBS64) + +install: all $(ROOTLIBS64) diff --git a/usr/src/lib/print/mod_ipp/mapfile b/usr/src/lib/brand/sngl/sngl_brand/common/mapfile-vers index ffdec222b5..29800204f8 100644 --- a/usr/src/lib/print/mod_ipp/mapfile +++ b/usr/src/lib/brand/sngl/sngl_brand/common/mapfile-vers @@ -24,10 +24,6 @@ # # -# $Id: mapfile 149 2006-04-25 16:55:01Z njacobs $ -# - -# # MAPFILE HEADER START # # WARNING: STOP NOW. DO NOT MODIFY THIS FILE. @@ -43,10 +39,10 @@ $mapfile_version 2 -SYMBOL_VERSION SUNWprivate_1.0 { - global: - ipp_module; - +# +# Scope everything local -- our .init section is our only public interface. +# +SYMBOL_SCOPE { local: *; }; diff --git a/usr/src/lib/brand/sngl/sngl_brand/common/sngl_brand.c b/usr/src/lib/brand/sngl/sngl_brand/common/sngl_brand.c new file mode 100644 index 0000000000..d2b8d8702d --- /dev/null +++ b/usr/src/lib/brand/sngl/sngl_brand/common/sngl_brand.c @@ -0,0 +1,429 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2012, Joyent, Inc. All rights reserved. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <unistd.h> +#include <sys/brand.h> +#include <sys/syscall.h> +#include <sys/systm.h> +#include <sys/stat.h> +#include <libgen.h> +#include <sys/auxv.h> + +#include <sngl_brand.h> +#include <brand_misc.h> + +/* + * See usr/src/lib/brand/shared/brand/common/brand_util.c for general + * emulation notes. + */ + +#define CONF32_PATH "/system/usr/lib/brand/sngl/ld.sys.config" +#define CONF64_PATH "/system/usr/lib/brand/sngl/ld.sys64.config" + +brand_sysent_table_t brand_sysent_table[]; + +static boolean_t is_sys = B_FALSE; +static boolean_t is_crle = B_FALSE; + +typedef struct { + char *mnt_name; + dev_t mnt_id; +} sys_mnt_dev_t; + +/* + * The brand platform mounts several GZ file systems into the zone. We know + * which ones can actually be on seperate file systems, so we only stat those + * when checking for system commands. This reduces the number of stats needed + * when we start up. + */ +static sys_mnt_dev_t sys_mounts[] = { + {"/system/usr", 0}, + {"/lib", 0}, + {NULL, 0} +}; + +/* + * If this is a /sytem binary and ld.so is opening the default config file, + * then redirect so it opens the /system config file instead. We need to do it + * this way, instead of setting one of the LD_CONFIG env vars, since those + * are ignored for secure binaries. + * + * We don't redirect if we're crle so that it can still be used on the default + * config files. + */ +int +sngl_open(sysret_t *rval, char *path, int oflag, mode_t mode) +{ + char tstr[MAXPATHLEN]; + + if (is_sys && !is_crle) { + /* Get a copy of the path we're trying to open */ + bzero(tstr, sizeof (tstr)); + (void) brand_uucopystr(path, tstr, sizeof (tstr)); + + if (strcmp(tstr, "/var/ld/ld.config") == 0) + return (__systemcall(rval, SYS_open + 1024, + CONF32_PATH, oflag, mode)); + + if (strcmp(tstr, "/var/ld/64/ld.config") == 0) + return (__systemcall(rval, SYS_open + 1024, + CONF64_PATH, oflag, mode)); + } + + return (__systemcall(rval, SYS_open + 1024, path, oflag, mode)); +} + +/*ARGSUSED*/ +int +brand_init(int argc, char *argv[], char *envp[]) +{ + ulong_t ldentry; + int i; + uintptr_t *p; + auxv_t *ap; + struct stat64 buf; + char *bname; + + brand_pre_init(); + + /* + * Check if we're trying to run a system binary. + * + * We haven't installed our emulation table yet, so its safe to make + * system calls directly. + * + * First, get the /system devices, then stat the executable to see if + * its on one of the /system devs. + */ + for (i = 0; sys_mounts[i].mnt_name != NULL; i++) { + if (stat64(sys_mounts[i].mnt_name, &buf) != -1) + sys_mounts[i].mnt_id = buf.st_dev; + } + + /* Find the aux vector on the stack. */ + p = (uintptr_t *)envp; + while (*p != NULL) + p++; + p++; + + /* Find AT_SUN_EXECNAME */ + for (ap = (auxv_t *)p; ap->a_type != AT_NULL; ap++) { + if (ap->a_type != AT_SUN_EXECNAME) + continue; + if (stat64(ap->a_un.a_ptr, &buf) != -1) { + for (i = 0; sys_mounts[i].mnt_name != NULL; i++) { + if (sys_mounts[i].mnt_id == buf.st_dev) { + is_sys = B_TRUE; + bname = basename(ap->a_un.a_ptr); + if (strcmp("crle", bname) == 0) + is_crle = B_TRUE; + break; + } + } + } + break; + } + + ldentry = brand_post_init(SNGL_VERSION, argc, argv, envp); + + brand_runexe(argv, ldentry); + /*NOTREACHED*/ + brand_abort(0, "brand_runexe() returned"); + return (-1); +} + +/* + * This table must have at least NSYSCALL entries in it. + * + * The second parameter of each entry in the brand_sysent_table + * contains the number of parameters and flags that describe the + * syscall return value encoding. See the block comments at the + * top of this file for more information about the syscall return + * value flags and when they should be used. + */ +brand_sysent_table_t brand_sysent_table[] = { + NOSYS, /* 0 */ + NOSYS, /* 1 */ + NOSYS, /* 2 */ + NOSYS, /* 3 */ + NOSYS, /* 4 */ + EMULATE(sngl_open, 3 | RV_DEFAULT), /* 5 */ + NOSYS, /* 6 */ + NOSYS, /* 7 */ + NOSYS, /* 8 */ + NOSYS, /* 9 */ + NOSYS, /* 10 */ + NOSYS, /* 11 */ + NOSYS, /* 12 */ + NOSYS, /* 13 */ + NOSYS, /* 14 */ + NOSYS, /* 15 */ + NOSYS, /* 16 */ + NOSYS, /* 17 */ + NOSYS, /* 18 */ + NOSYS, /* 19 */ + NOSYS, /* 20 */ + NOSYS, /* 21 */ + NOSYS, /* 22 */ + NOSYS, /* 23 */ + NOSYS, /* 24 */ + NOSYS, /* 25 */ + NOSYS, /* 26 */ + NOSYS, /* 27 */ + NOSYS, /* 28 */ + NOSYS, /* 29 */ + NOSYS, /* 30 */ + NOSYS, /* 31 */ + NOSYS, /* 32 */ + NOSYS, /* 33 */ + NOSYS, /* 34 */ + NOSYS, /* 35 */ + NOSYS, /* 36 */ + NOSYS, /* 37 */ + NOSYS, /* 38 */ + NOSYS, /* 39 */ + NOSYS, /* 40 */ + NOSYS, /* 41 */ + NOSYS, /* 42 */ + NOSYS, /* 43 */ + NOSYS, /* 44 */ + NOSYS, /* 45 */ + NOSYS, /* 46 */ + NOSYS, /* 47 */ + NOSYS, /* 48 */ + NOSYS, /* 49 */ + NOSYS, /* 50 */ + NOSYS, /* 51 */ + NOSYS, /* 52 */ + NOSYS, /* 53 */ + NOSYS, /* 54 */ + NOSYS, /* 55 */ + NOSYS, /* 56 */ + NOSYS, /* 57 */ + NOSYS, /* 58 */ + NOSYS, /* 59 */ + NOSYS, /* 60 */ + NOSYS, /* 61 */ + NOSYS, /* 62 */ + NOSYS, /* 63 */ + NOSYS, /* 64 */ + NOSYS, /* 65 */ + NOSYS, /* 66 */ + NOSYS, /* 67 */ + NOSYS, /* 68 */ + NOSYS, /* 69 */ + NOSYS, /* 70 */ + NOSYS, /* 71 */ + NOSYS, /* 72 */ + NOSYS, /* 73 */ + NOSYS, /* 74 */ + NOSYS, /* 75 */ + NOSYS, /* 76 */ + NOSYS, /* 77 */ + NOSYS, /* 78 */ + NOSYS, /* 79 */ + NOSYS, /* 80 */ + NOSYS, /* 81 */ + NOSYS, /* 82 */ + NOSYS, /* 83 */ + NOSYS, /* 84 */ + NOSYS, /* 85 */ + NOSYS, /* 86 */ + NOSYS, /* 87 */ + NOSYS, /* 88 */ + NOSYS, /* 89 */ + NOSYS, /* 90 */ + NOSYS, /* 91 */ + NOSYS, /* 92 */ + NOSYS, /* 93 */ + NOSYS, /* 94 */ + NOSYS, /* 95 */ + NOSYS, /* 96 */ + NOSYS, /* 97 */ + NOSYS, /* 98 */ + NOSYS, /* 99 */ + NOSYS, /* 100 */ + NOSYS, /* 101 */ + NOSYS, /* 102 */ + NOSYS, /* 103 */ + NOSYS, /* 104 */ + NOSYS, /* 105 */ + NOSYS, /* 106 */ + NOSYS, /* 107 */ + NOSYS, /* 108 */ + NOSYS, /* 109 */ + NOSYS, /* 110 */ + NOSYS, /* 111 */ + NOSYS, /* 112 */ + NOSYS, /* 113 */ + NOSYS, /* 114 */ + NOSYS, /* 115 */ + NOSYS, /* 116 */ + NOSYS, /* 117 */ + NOSYS, /* 118 */ + NOSYS, /* 119 */ + NOSYS, /* 120 */ + NOSYS, /* 121 */ + NOSYS, /* 122 */ + NOSYS, /* 123 */ + NOSYS, /* 124 */ + NOSYS, /* 125 */ + NOSYS, /* 126 */ + NOSYS, /* 127 */ + NOSYS, /* 128 */ + NOSYS, /* 129 */ + NOSYS, /* 130 */ + NOSYS, /* 131 */ + NOSYS, /* 132 */ + NOSYS, /* 133 */ + NOSYS, /* 134 */ + NOSYS, /* 135 */ + NOSYS, /* 136 */ + NOSYS, /* 137 */ + NOSYS, /* 138 */ + NOSYS, /* 139 */ + NOSYS, /* 140 */ + NOSYS, /* 141 */ + NOSYS, /* 142 */ + NOSYS, /* 143 */ + NOSYS, /* 144 */ + NOSYS, /* 145 */ + NOSYS, /* 146 */ + NOSYS, /* 147 */ + NOSYS, /* 148 */ + NOSYS, /* 149 */ + NOSYS, /* 150 */ + NOSYS, /* 151 */ + NOSYS, /* 152 */ + NOSYS, /* 153 */ + NOSYS, /* 154 */ + NOSYS, /* 155 */ + NOSYS, /* 156 */ + NOSYS, /* 157 */ + NOSYS, /* 158 */ + NOSYS, /* 159 */ + NOSYS, /* 160 */ + NOSYS, /* 161 */ + NOSYS, /* 162 */ + NOSYS, /* 163 */ + NOSYS, /* 164 */ + NOSYS, /* 165 */ + NOSYS, /* 166 */ + NOSYS, /* 167 */ + NOSYS, /* 168 */ + NOSYS, /* 169 */ + NOSYS, /* 170 */ + NOSYS, /* 171 */ + NOSYS, /* 172 */ + NOSYS, /* 173 */ + NOSYS, /* 174 */ + NOSYS, /* 175 */ + NOSYS, /* 176 */ + NOSYS, /* 177 */ + NOSYS, /* 178 */ + NOSYS, /* 179 */ + NOSYS, /* 180 */ + NOSYS, /* 181 */ + NOSYS, /* 182 */ + NOSYS, /* 183 */ + NOSYS, /* 184 */ + NOSYS, /* 185 */ + NOSYS, /* 186 */ + NOSYS, /* 187 */ + NOSYS, /* 188 */ + NOSYS, /* 189 */ + NOSYS, /* 190 */ + NOSYS, /* 191 */ + NOSYS, /* 192 */ + NOSYS, /* 193 */ + NOSYS, /* 194 */ + NOSYS, /* 195 */ + NOSYS, /* 196 */ + NOSYS, /* 197 */ + NOSYS, /* 198 */ + NOSYS, /* 199 */ + NOSYS, /* 200 */ + NOSYS, /* 201 */ + NOSYS, /* 202 */ + NOSYS, /* 203 */ + NOSYS, /* 204 */ + NOSYS, /* 205 */ + NOSYS, /* 206 */ + NOSYS, /* 207 */ + NOSYS, /* 208 */ + NOSYS, /* 209 */ + NOSYS, /* 210 */ + NOSYS, /* 211 */ + NOSYS, /* 212 */ + NOSYS, /* 213 */ + NOSYS, /* 214 */ + NOSYS, /* 215 */ + NOSYS, /* 216 */ + NOSYS, /* 217 */ + NOSYS, /* 218 */ + NOSYS, /* 219 */ + NOSYS, /* 220 */ + NOSYS, /* 221 */ + NOSYS, /* 222 */ + NOSYS, /* 223 */ + NOSYS, /* 224 */ + NOSYS, /* 225 */ + NOSYS, /* 226 */ + NOSYS, /* 227 */ + NOSYS, /* 228 */ + NOSYS, /* 229 */ + NOSYS, /* 230 */ + NOSYS, /* 231 */ + NOSYS, /* 232 */ + NOSYS, /* 233 */ + NOSYS, /* 234 */ + NOSYS, /* 235 */ + NOSYS, /* 236 */ + NOSYS, /* 237 */ + NOSYS, /* 238 */ + NOSYS, /* 239 */ + NOSYS, /* 240 */ + NOSYS, /* 241 */ + NOSYS, /* 242 */ + NOSYS, /* 243 */ + NOSYS, /* 244 */ + NOSYS, /* 245 */ + NOSYS, /* 246 */ + NOSYS, /* 247 */ + NOSYS, /* 248 */ + NOSYS, /* 249 */ + NOSYS, /* 250 */ + NOSYS, /* 251 */ + NOSYS, /* 252 */ + NOSYS, /* 253 */ + NOSYS, /* 254 */ + NOSYS /* 255 */ +}; diff --git a/usr/src/lib/brand/sngl/sngl_brand/i386/Makefile b/usr/src/lib/brand/sngl/sngl_brand/i386/Makefile new file mode 100644 index 0000000000..a0c4927252 --- /dev/null +++ b/usr/src/lib/brand/sngl/sngl_brand/i386/Makefile @@ -0,0 +1,46 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012, Joyent, Inc. All rights reserved. +# + +ISAOBJDIR = $(BRAND_SHARED)/brand/i386/pics + +include ../Makefile.com + +CPPFLAGS += -I$(BRAND_SHARED)/brand/i386 + +# +# see ../Makefile.com for why we explicity make ld.so.1 our interpreter +# +DYNFLAGS += -Wl,-I/lib/ld.so.1 + +# Note that we also set the runtime path for the emulation library to point +# into /system. This is an attempt to ensure that our brand library get's the +# native version of libmapmallc. +# +DYNFLAGS += -R/lib -R/system/usr/lib + +CLEANFILES += $(DYNLIB) +CLOBBERFILES += $(ROOTLIBS) + +install: all $(ROOTLIBS) diff --git a/usr/src/lib/print/libpapi-dynamic/Makefile b/usr/src/lib/brand/sngl/zone/Makefile index b92d620b10..42785deab3 100644 --- a/usr/src/lib/print/libpapi-dynamic/Makefile +++ b/usr/src/lib/brand/sngl/zone/Makefile @@ -18,39 +18,36 @@ # # CDDL HEADER END # + # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" +# Copyright 2012 Joyent, Inc. All rights reserved. # -include ../../Makefile.lib +PROGS = sinstall +XMLDOCS= config.xml platform.xml +CLOBBERFILES= $(ROOTPROGS) $(ROOTXMLDOCS) -#HDRS = papi.h -#HDRDIR = common -SUBDIRS = $(MACH) -#$(BUILD64)SUBDIRS += $(MACH64) - -all := TARGET = all -clean := TARGET = clean -clobber := TARGET = clobber -install := TARGET = install -lint := TARGET = lint +include $(SRC)/cmd/Makefile.cmd +include ../Makefile.sngl .KEEP_STATE: -all clean clobber install: .WAIT $(SUBDIRS) - -lint: # $(SUBDIRS) +all: $(PROGS) -install_h: # $(ROOTHDRS) +POFILES = +POFILE = -check: # $(CHECKHDRS) +install: $(PROGS) $(ROOTPROGS) $(ROOTXMLDOCS) + crle -c $(ROOTBRANDDIR)/ld.sys.config \ + -l /lib:/system/usr/lib \ + -s /lib/secure:/system/usr/lib/secure + crle -64 -c $(ROOTBRANDDIR)/ld.sys64.config \ + -l /lib/64:/system/usr/lib/64 \ + -s /lib/secure/64:/system/usr/lib/secure/64 -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) +lint: -FRC: +clean: + -$(RM) $(PROGS) -include ../../Makefile.targ +include $(SRC)/cmd/Makefile.targ diff --git a/usr/src/lib/brand/sngl/zone/config.xml b/usr/src/lib/brand/sngl/zone/config.xml new file mode 100644 index 0000000000..421400e82a --- /dev/null +++ b/usr/src/lib/brand/sngl/zone/config.xml @@ -0,0 +1,112 @@ +<?xml version="1.0"?> + +<!-- + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License (the "License"). + You may not use this file except in compliance with the License. + + You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + or http://www.opensolaris.org/os/licensing. + See the License for the specific language governing permissions + and limitations under the License. + + When distributing Covered Code, include this CDDL HEADER in each + file and include the License file at usr/src/OPENSOLARIS.LICENSE. + If applicable, add the following below this CDDL HEADER, with the + fields enclosed by brackets "[]" replaced with your own identifying + information: Portions Copyright [yyyy] [name of copyright owner] + + CDDL HEADER END + + Copyright 2012 Joyent, Inc. All rights reserved. + Use is subject to license terms. + + DO NOT EDIT THIS FILE. +--> + +<!DOCTYPE brand PUBLIC "-//Joyent Inc//DTD Brands//EN" + "file:///usr/share/lib/xml/dtd/brand.dtd.1"> + +<brand name="sngl"> + <modname>sngl_brand</modname> + + <initname>/system/sbin/init</initname> + <login_cmd>/system/usr/bin/login -z %Z %u</login_cmd> + <forcedlogin_cmd>/system/usr/bin/login -z %Z -f %u</forcedlogin_cmd> + <user_cmd>/system/usr/bin/getent passwd %u</user_cmd> + + <install>/usr/lib/brand/sngl/sinstall -z %z -R %R</install> + <installopts>R:t:U:q:z:</installopts> + <boot></boot> + <halt></halt> + <verify_cfg></verify_cfg> + <verify_adm></verify_adm> + <postclone></postclone> + <postinstall></postinstall> + <attach>/bin/true</attach> + <detach>/bin/true</detach> + <clone></clone> + <uninstall>/usr/lib/brand/joyent/juninstall -z %z -R %R</uninstall> + <prestatechange>/usr/lib/brand/joyent/prestate %z %R</prestatechange> + <poststatechange>/usr/lib/brand/joyent/poststate %z %R</poststatechange> + <query>/usr/lib/brand/joyent/query %z %R</query> + + <privilege set="default" name="contract_event" /> + <privilege set="default" name="contract_identity" /> + <privilege set="default" name="contract_observer" /> + <privilege set="default" name="dtrace_proc" /> + <privilege set="default" name="dtrace_user" /> + <privilege set="default" name="file_chown" /> + <privilege set="default" name="file_chown_self" /> + <privilege set="default" name="file_dac_execute" /> + <privilege set="default" name="file_dac_read" /> + <privilege set="default" name="file_dac_search" /> + <privilege set="default" name="file_dac_write" /> + <privilege set="default" name="file_owner" /> + <privilege set="default" name="file_setid" /> + <privilege set="default" name="ipc_dac_read" /> + <privilege set="default" name="ipc_dac_write" /> + <privilege set="default" name="ipc_owner" /> + <privilege set="default" name="net_bindmlp" /> + <privilege set="default" name="net_icmpaccess" /> + <privilege set="default" name="net_mac_aware" /> + <privilege set="default" name="net_observability" /> + <privilege set="default" name="net_privaddr" /> + <privilege set="default" name="net_rawaccess" ip-type="exclusive" /> + <privilege set="default" name="proc_chroot" /> + <privilege set="default" name="sys_audit" /> + <privilege set="default" name="proc_audit" /> + <privilege set="default" name="proc_lock_memory" /> + <privilege set="default" name="proc_owner" /> + <privilege set="default" name="proc_prioup" /> + <privilege set="default" name="proc_setid" /> + <privilege set="default" name="proc_taskid" /> + <privilege set="default" name="sys_acct" /> + <privilege set="default" name="sys_admin" /> + <privilege set="default" name="sys_ip_config" ip-type="exclusive" /> + <privilege set="default" name="sys_iptun_config" ip-type="exclusive" /> + <privilege set="default" name="sys_mount" /> + <privilege set="default" name="sys_nfs" /> + <privilege set="default" name="sys_resource" /> + <privilege set="default" name="sys_ppp_config" ip-type="exclusive" /> + + <privilege set="prohibited" name="dtrace_kernel" /> + <privilege set="prohibited" name="proc_zone" /> + <privilege set="prohibited" name="sys_config" /> + <privilege set="prohibited" name="sys_devices" /> + <privilege set="prohibited" name="sys_ip_config" ip-type="shared" /> + <privilege set="prohibited" name="sys_linkdir" /> + <privilege set="prohibited" name="sys_net_config" /> + <privilege set="prohibited" name="sys_res_config" /> + <privilege set="prohibited" name="sys_suser_compat" /> + <privilege set="prohibited" name="xvm_control" /> + <privilege set="prohibited" name="virt_manage" /> + <privilege set="prohibited" name="sys_ppp_config" ip-type="shared" /> + + <privilege set="required" name="proc_exec" /> + <privilege set="required" name="proc_fork" /> + <privilege set="required" name="sys_ip_config" ip-type="exclusive" /> + <privilege set="required" name="sys_mount" /> +</brand> diff --git a/usr/src/lib/brand/sngl/zone/platform.xml b/usr/src/lib/brand/sngl/zone/platform.xml new file mode 100644 index 0000000000..d9313f8b5c --- /dev/null +++ b/usr/src/lib/brand/sngl/zone/platform.xml @@ -0,0 +1,160 @@ +<?xml version="1.0"?> + +<!-- + CDDL HEADER START + + The contents of this file are subject to the terms of the + Common Development and Distribution License (the "License"). + You may not use this file except in compliance with the License. + + You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + or http://www.opensolaris.org/os/licensing. + See the License for the specific language governing permissions + and limitations under the License. + + When distributing Covered Code, include this CDDL HEADER in each + file and include the License file at usr/src/OPENSOLARIS.LICENSE. + If applicable, add the following below this CDDL HEADER, with the + fields enclosed by brackets "[]" replaced with your own identifying + information: Portions Copyright [yyyy] [name of copyright owner] + + CDDL HEADER END + + Copyright (c) 2012 Joyent, Inc. All rights reserved. + Use is subject to license terms. + + DO NOT EDIT THIS FILE. +--> + +<!DOCTYPE platform PUBLIC "-//Joyent Inc//Zones Platform//EN" + "file:///usr/share/lib/xml/dtd/zone_platform.dtd.1"> + +<platform name="sngl" allow-exclusive-ip="true"> + + <!-- Global filesystems to mount when booting the zone --> + <global_mount special="/dev" directory="/dev" type="dev" + opt="attrdir=%R/root/dev"/> + + <global_mount special="/lib" directory="/lib" + opt="ro,nodevices" type="lofs" /> + <global_mount special="%P/manifests/joyent" + directory="/lib/svc/manifest" + opt="ro,nodevices" type="lofs" /> + <global_mount special="%R/site" directory="/lib/svc/manifest/site" + opt="nodevices" type="lofs" /> + <global_mount special="/sbin" directory="/sbin" + opt="ro,nodevices" type="lofs" /> + <global_mount special="/lib" directory="/system/lib" + opt="ro,nodevices" type="lofs" /> + <global_mount special="/sbin" directory="/system/sbin" + opt="ro,nodevices" type="lofs" /> + <global_mount special="/usr" directory="/system/usr" + opt="ro,nodevices" type="lofs" /> + + <!-- Local filesystems to mount when booting the zone --> + <mount special="/proc" directory="/proc" type="proc" /> + <mount special="ctfs" directory="/system/contract" type="ctfs" /> + <mount special="mnttab" directory="/etc/mnttab" type="mntfs" /> + <mount special="objfs" directory="/system/object" type="objfs" /> + <mount special="lxproc" directory="/system/lxproc" type="lxproc" /> + <mount special="swap" directory="/etc/svc/volatile" type="tmpfs" /> + + <!-- Devices to create under /dev --> + <device match="arp" /> + <device match="bpf" /> + <device match="conslog" /> + <device match="cpu/self/cpuid" /> + <device match="crypto" /> + <device match="cryptoadm" /> + <device match="dsk" /> + <device match="dtrace/*" /> + <device match="dtrace/provider/*" /> + <device match="fd" /> + <device match="ipnet" /> + <device match="kstat" /> + <device match="lo0" /> + <device match="lofictl" /> + <device match="lofi" /> + <device match="log" /> + <device match="logindmux" /> + <device match="nsmb" /> + <device match="net/*" /> + <device match="null" /> + <device match="openprom" arch="sparc" /> + <device match="poll" /> + <device match="pool" /> + <device match="ptmx" /> + <device match="pts/*" /> + <device match="random" /> + <device match="rdsk" /> + <device match="rlofi" /> + <device match="rmt" /> + <device match="sad/user" /> + <device match="svvslo0" /> + <device match="svvslo1" /> + <device match="svvslo2" /> + <device match="svvslo3" /> + <device match="swap" /> + <device match="sysevent" /> + <device match="tap" /> + <device match="tcp" /> + <device match="tcp6" /> + <device match="term" /> + <device match="ticlts" /> + <device match="ticots" /> + <device match="ticotsord" /> + <device match="tty" /> + <device match="tun" /> + <device match="udp" /> + <device match="udp6" /> + <device match="urandom" /> + <device match="zero" /> + <device match="zfs" /> + <device match="zvol/dsk/%P/%z/*" /> + <device match="zvol/rdsk/%P/%z/*" /> + + <!-- Devices to create in exclusive IP zone only --> + <device match="dld" ip-type="exclusive" /> + <device match="icmp" ip-type="exclusive" /> + <device match="icmp6" ip-type="exclusive" /> + <device match="ip" ip-type="exclusive" /> + <device match="ip6" ip-type="exclusive" /> + <device match="ipauth" ip-type="exclusive" /> + <device match="ipd" ip-type="exclusive" /> + <device match="ipf" ip-type="exclusive" /> + <device match="ipl" ip-type="exclusive" /> + <device match="iplookup" ip-type="exclusive" /> + <device match="ipmpstub" ip-type="exclusive" /> + <device match="ipnat" ip-type="exclusive" /> + <device match="ipscan" ip-type="exclusive" /> + <device match="ipsecah" ip-type="exclusive" /> + <device match="ipsecesp" ip-type="exclusive" /> + <device match="ipstate" ip-type="exclusive" /> + <device match="ipsync" ip-type="exclusive" /> + <device match="keysock" ip-type="exclusive" /> + <device match="rawip" ip-type="exclusive" /> + <device match="rawip6" ip-type="exclusive" /> + <device match="rts" ip-type="exclusive" /> + <device match="sad/admin" ip-type="exclusive" /> + <device match="sctp" ip-type="exclusive" /> + <device match="sctp6" ip-type="exclusive" /> + <device match="spdsock" ip-type="exclusive" /> + <device match="sppp" ip-type="exclusive" /> + <device match="sppptun" ip-type="exclusive" /> + <device match="vni" ip-type="exclusive" /> + + <!-- Renamed devices to create under /dev --> + <device match="zcons/%z/zoneconsole" name="zconsole" /> + + <!-- Symlinks to create under /dev --> + <symlink source="console" target="zconsole" /> + <symlink source="dtremote" target="/dev/null" /> + <symlink source="msglog" target="zconsole" /> + <symlink source="stderr" target="./fd/2" /> + <symlink source="stdin" target="./fd/0" /> + <symlink source="stdout" target="./fd/1" /> + <symlink source="syscon" target="zconsole" /> + <symlink source="sysmsg" target="zconsole" /> + <symlink source="systty" target="zconsole" /> + +</platform> diff --git a/usr/src/lib/brand/sngl/zone/sinstall.sh b/usr/src/lib/brand/sngl/zone/sinstall.sh new file mode 100644 index 0000000000..d0633a7525 --- /dev/null +++ b/usr/src/lib/brand/sngl/zone/sinstall.sh @@ -0,0 +1,118 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright (c) 2012, Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +unset LD_LIBRARY_PATH +PATH=/usr/bin:/usr/sbin +export PATH + +. /usr/lib/brand/shared/common.ksh +. /usr/lib/brand/joyent/common.ksh + +ZONENAME="" +ZONEPATH="" +# Default to 10GB diskset quota +ZQUOTA=10 + +while getopts "R:t:U:q:z:" opt +do + case "$opt" in + R) ZONEPATH="$OPTARG";; + t) TMPLZONE="$OPTARG";; + # UUID is only used in the postinstall script + U) UUID="$OPTARG";; + q) ZQUOTA="$OPTARG";; + z) ZONENAME="$OPTARG";; + *) printf "$m_usage\n" + exit $ZONE_SUBPROC_USAGE;; + esac +done +shift OPTIND-1 + +if [[ -n $(zonecfg -z "${ZONENAME}" info attr name=transition \ + | grep "value: receiving:") ]]; then + + # Here we're doing an install for a received zone, the dataset should have + # already been created. + exit $ZONE_SUBPROC_OK +fi + +if [[ -z $ZONEPATH || -z $ZONENAME ]]; then + print -u2 "Brand error: No zone path or name" + exit $ZONE_SUBPROC_USAGE +fi + +# The install requires a template zone. +if [[ -z $TMPLZONE ]]; then + print -u2 "Brand error: a zone template is required" + exit $ZONE_SUBPROC_USAGE +fi + +# The dataset quota must be a number. +case $ZQUOTA in *[!0-9]*) + print -u2 "Brand error: The quota $ZQUOTA is not a number" + exit $ZONE_SUBPROC_USAGE;; +esac + +ZROOT=$ZONEPATH/root + +# Get the dataset of the parent directory of the zonepath. +dname=${ZONEPATH%/*} +bname=${ZONEPATH##*/} +PDS_NAME=`mount | nawk -v p=$dname '{if ($1 == p) print $3}'` +[ -z "$PDS_NAME" ] && \ + print -u2 "Brand error: missing parent ZFS dataset for $dname" + +# We expect that zoneadm was invoked with '-x nodataset', so it won't have +# created the dataset. + +QUOTA_ARG= +if [[ ${ZQUOTA} != "0" ]]; then + QUOTA_ARG="-o quota=${ZQUOTA}g" +fi + +# New imgadm renames the dataset's snapshot at import to @final for us +# and when it exists, we use that. However, when it does not exist we +# still use the old method of creating a zones/<uuid>@<uuid> snapshot +# so we can support old datasets. +exists=$(zfs list -Ho name ${PDS_NAME}/${TMPLZONE}@final 2>&1) +if [[ $? == 0 && ${exists} == "${PDS_NAME}/${TMPLZONE}@final" ]]; then + zfs clone -F ${QUOTA_ARG} ${PDS_NAME}/${TMPLZONE}@final \ + ${PDS_NAME}/${bname} || fatal "failed to clone zone dataset" +elif [[ ${exists} =~ "dataset does not exist" ]]; then + zfs snapshot ${PDS_NAME}/${TMPLZONE}@${bname} + zfs clone -F ${QUOTA_ARG} ${PDS_NAME}/${TMPLZONE}@${bname} \ + ${PDS_NAME}/${bname} || fatal "failed to clone zone dataset" +else + fatal "Unable to determine snapshot for ${PDS_NAME}/${TMPLZONE}" +fi + +if [ ! -d ${ZONEPATH}/config ]; then + mkdir -p ${ZONEPATH}/config + chmod 755 ${ZONEPATH}/config +fi + +final_setup + +exit $ZONE_SUBPROC_OK diff --git a/usr/src/lib/efcode/interpreter/Makefile b/usr/src/lib/efcode/interpreter/Makefile index 82c44bbdc2..d7475b45bb 100644 --- a/usr/src/lib/efcode/interpreter/Makefile +++ b/usr/src/lib/efcode/interpreter/Makefile @@ -39,7 +39,8 @@ CERRWARN += -_gcc=-Wno-uninitialized LDFLAGS += -R/usr/lib/efcode/$(MACH64) -M mapfile64 LIBS = fcode.so fcdriver.so -$(PROG) := LDLIBS += -L/usr/lib/efcode/$(MACH64) $(LIBS:%=$(EFCODEDIR64)/%) +$(PROG) := LDLIBS += -L$(ADJUNCT_PROTO)/usr/lib/efcode/$(MACH64) \ + $(LIBS:%=$(EFCODEDIR64)/%) all: $(PROG) diff --git a/usr/src/lib/fm/libldom/Makefile.com b/usr/src/lib/fm/libldom/Makefile.com index 931961fe4a..859a177363 100644 --- a/usr/src/lib/fm/libldom/Makefile.com +++ b/usr/src/lib/fm/libldom/Makefile.com @@ -38,7 +38,7 @@ SRCDIR = ../sparc LIBS = $(DYNLIB) $(LINTLIB) CPPFLAGS += -I. -I$(SRC)/uts/sun4v -I$(ROOT)/usr/platform/sun4v/include \ - -I/usr/include/libxml2 -I/usr/sfw/include + -I$(ADJUNCT_PROTO)/usr/include/libxml2 CFLAGS += $(CCVERBOSE) $(C_BIGPICFLAGS) CFLAGS64 += $(CCVERBOSE) $(C_BIGPICFLAGS) diff --git a/usr/src/lib/fm/topo/libtopo/Makefile.com b/usr/src/lib/fm/topo/libtopo/Makefile.com index 0b7dc59c6d..56871dd6d4 100644 --- a/usr/src/lib/fm/topo/libtopo/Makefile.com +++ b/usr/src/lib/fm/topo/libtopo/Makefile.com @@ -74,7 +74,7 @@ SRCDIR = ../common CLEANFILES += $(SRCDIR)/topo_error.c $(SRCDIR)/topo_tables.c -CPPFLAGS += -I../common -I/usr/include/libxml2 -I. +CPPFLAGS += -I../common -I$(ADJUNCT_PROTO)/usr/include/libxml2 -I. CFLAGS += $(CCVERBOSE) $(C_BIGPICFLAGS) CFLAGS += -D_POSIX_PTHREAD_SEMANTICS CFLAGS64 += $(CCVERBOSE) $(C_BIGPICFLAGS) diff --git a/usr/src/lib/fm/topo/libtopo/common/libtopo.h b/usr/src/lib/fm/topo/libtopo/common/libtopo.h index 9b7102f882..3ea35cdddd 100644 --- a/usr/src/lib/fm/topo/libtopo/common/libtopo.h +++ b/usr/src/lib/fm/topo/libtopo/common/libtopo.h @@ -137,6 +137,8 @@ extern boolean_t topo_method_supported(tnode_t *, const char *, topo_version_t); extern int topo_node_facility(topo_hdl_t *, tnode_t *, const char *, uint32_t, topo_faclist_t *, int *); +extern int topo_node_child_walk(topo_hdl_t *, tnode_t *, topo_walk_cb_t, + void *, int *); /* * Node flags: denotes type of node diff --git a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers index 1cde0dee1f..b81f4fd7c6 100644 --- a/usr/src/lib/fm/topo/libtopo/common/mapfile-vers +++ b/usr/src/lib/fm/topo/libtopo/common/mapfile-vers @@ -126,6 +126,7 @@ SYMBOL_VERSION SUNWprivate { topo_node_asru; topo_node_asru_set; topo_node_bind; + topo_node_child_walk; topo_node_facility; topo_node_facbind; topo_node_flags; diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h index 1c3a92f804..7b29adad69 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h +++ b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #ifndef _TOPO_HC_H @@ -115,6 +116,10 @@ extern "C" { #define TOPO_PGROUP_BINDING "binding" #define TOPO_BINDING_OCCUPANT "occupant-path" +#define TOPO_BINDING_DRIVER "driver" +#define TOPO_BINDING_DEVCTL "devctl" +#define TOPO_BINDING_ENCLOSURE "enclosure" +#define TOPO_BINDING_SLOT "slot" #define TOPO_PGROUP_STORAGE "storage" #define TOPO_STORAGE_INITIATOR_PORT "initiator-port" diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_node.c b/usr/src/lib/fm/topo/libtopo/common/topo_node.c index 553bc851f0..00b828c49c 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_node.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_node.c @@ -837,3 +837,55 @@ topo_node_walk_init(topo_hdl_t *thp, topo_mod_t *mod, tnode_t *node, return (wp); } + +/* + * Walk the direct children of the given node. + */ +int +topo_node_child_walk(topo_hdl_t *thp, tnode_t *pnode, topo_walk_cb_t cb_f, + void *arg, int *errp) +{ + int ret = TOPO_WALK_TERMINATE; + tnode_t *cnode; + + topo_node_hold(pnode); + + /* + * First Child: + */ + topo_node_lock(pnode); + cnode = topo_child_first(pnode); + topo_node_unlock(pnode); + + if (cnode == NULL) { + *errp = ETOPO_WALK_EMPTY; + ret = TOPO_WALK_ERR; + goto out; + } + + while (cnode != NULL) { + int iret; + + /* + * Call the walker callback: + */ + topo_node_hold(cnode); + iret = cb_f(thp, cnode, arg); + topo_node_rele(cnode); + if (iret != TOPO_WALK_NEXT) { + ret = iret; + break; + } + + /* + * Next child: + */ + topo_node_lock(pnode); + cnode = topo_child_next(pnode, cnode); + topo_node_unlock(pnode); + } + +out: + topo_node_rele(pnode); + return (ret); +} diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_xml.c b/usr/src/lib/fm/topo/libtopo/common/topo_xml.c index 9e4c18c250..f26d5f6ef9 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_xml.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_xml.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include <libxml/parser.h> @@ -1376,16 +1377,10 @@ fac_enum_process(topo_mod_t *mp, xmlNodePtr pn, tnode_t *ptn) if ((fprov = xmlGetProp(cn, (xmlChar *)Provider)) == NULL) goto fenumdone; - - if (xmlStrcmp(fprov, (xmlChar *)"fac_prov_ipmi") != 0) { - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, - "Invalid provider specified: %s\n", fprov); - goto fenumdone; - } - /* - * Invoke enum entry point in fac provider which will cause the - * facility enumeration node method to be registered. + * Invoke enum entry point in facility provider which will + * cause the facility enumeration node method to be + * registered. */ if (fac_enum_run(mp, ptn, (const char *)fprov) != 0) { topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, @@ -1440,12 +1435,6 @@ fac_process(topo_mod_t *mp, xmlNodePtr pn, tf_rdata_t *rd, tnode_t *ptn) xmlStrcmp(ftype, (xmlChar *)Indicator) != 0) goto facdone; - if (xmlStrcmp(provider, (xmlChar *)"fac_prov_ipmi") != 0) { - topo_dprintf(mp->tm_hdl, TOPO_DBG_XML, "fac_process: " - "Invalid provider attr value: %s\n", provider); - goto facdone; - } - if ((ntn = topo_node_facbind(mp, ptn, (char *)fname, (char *)ftype)) == NULL) goto facdone; @@ -1463,8 +1452,9 @@ fac_process(topo_mod_t *mp, xmlNodePtr pn, tf_rdata_t *rd, tnode_t *ptn) } } /* - * Invoke enum entry point in fac_prov_ipmi module, which will - * cause the provider methods to be registered on this node + * Invoke enum entry point in the facility provider module, + * which will cause the provider methods to be registered on + * this node */ if (fac_enum_run(mp, ntn, (const char *)provider) != 0) { topo_dprintf(mp->tm_hdl, TOPO_DBG_ERR, "fac_process: " diff --git a/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-1101/Joyent-Compute-Platform-1101-disk-hc-topology.xmlgenksh b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-1101/Joyent-Compute-Platform-1101-disk-hc-topology.xmlgenksh new file mode 100755 index 0000000000..000742db71 --- /dev/null +++ b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-1101/Joyent-Compute-Platform-1101-disk-hc-topology.xmlgenksh @@ -0,0 +1,95 @@ +#!/bin/ksh +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2013, Joyent, Inc. All rights reserved. +# + +function do_node +{ + cat <<EOF + <node instance='${1}'> + <propgroup name='protocol' version='1' name-stability='Private' + data-stability='Private'> + <propval name='label' type='string' value='${2}' /> + </propgroup> + <propgroup name='binding' version='1' name-stability='Private' + data-stability='Private'> + <propval name='driver' type='string' value='mpt_sas' /> + <propval name='devctl' type='string' value='${3}' /> + <propval name='enclosure' type='uint32' value='${4}' /> + <propval name='slot' type='uint32' value='${5}' /> + </propgroup> + </node> +EOF +} + + +cat <<EOF +<topology name='disk' scheme='hc'> + <range name='bay' min='0' max='15'> + <facility name='fail' type='indicator' provider='fac_prov_mptsas' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='0' /> + <propmethod name='mptsas_led_mode' version='0' propname='mode' + proptype='uint32' mutable='1'> + </propmethod> + </propgroup> + </facility> + <facility name='ident' type='indicator' provider='fac_prov_mptsas' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='1' /> + <propmethod name='mptsas_led_mode' version='0' propname='mode' + proptype='uint32' mutable='1'> + </propmethod> + </propgroup> + </facility> + <facility name='ok2rm' type='indicator' provider='fac_prov_mptsas' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='2' /> + <propmethod name='mptsas_led_mode' version='0' propname='mode' + proptype='uint32' mutable='1'> + </propmethod> + </propgroup> + </facility> +EOF + +enclosure=1 +bay=0 +slot=0 +devctl='/devices/pci@0,0/pci8086,3c02@1/pci15d9,691@0:devctl' +while (( slot <= 7 )); do + do_node $bay "Front Disk $bay" "$devctl" $enclosure $slot + (( bay = bay + 1 )) + (( slot = slot + 1 )) +done + +slot=0 +devctl='/devices/pci@0,0/pci8086,3c06@2,2/pci15d9,691@0:devctl' +while (( slot <= 7 )); do + do_node $bay "Front Disk $bay" "$devctl" $enclosure $slot + (( bay = bay + 1 )) + (( slot = slot + 1 )) +done + +cat <<EOF + <dependents grouping='children'> + <range name='disk' min='0' max='0'> + <enum-method name='disk' version='1' /> + </range> + </dependents> + </range> +</topology> +EOF diff --git a/usr/src/lib/print/libipp-listener/Makefile b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-1101/Makefile index b92d620b10..072ea71be7 100644 --- a/usr/src/lib/print/libipp-listener/Makefile +++ b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-1101/Makefile @@ -18,39 +18,24 @@ # # CDDL HEADER END # + # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright (c) 2013, Joyent, Inc. All rights reserved. # -# ident "%Z%%M% %I% %E% SMI" -# - -include ../../Makefile.lib - -#HDRS = papi.h -#HDRDIR = common -SUBDIRS = $(MACH) -#$(BUILD64)SUBDIRS += $(MACH64) - -all := TARGET = all -clean := TARGET = clean -clobber := TARGET = clobber -install := TARGET = install -lint := TARGET = lint - -.KEEP_STATE: - -all clean clobber install: .WAIT $(SUBDIRS) - -lint: # $(SUBDIRS) - -install_h: # $(ROOTHDRS) -check: # $(CHECKHDRS) +# NOTE: The name of the xml file we are building is 'platform' +# specific, but its build is structured as 'arch' specific since +# 'uname -i' on all x86 platforms returns i86pc. -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) +ARCH = i86pc +CLASS = arch +DTDFILE = topology.dtd.1 +TOPOFILE = Joyent-Compute-Platform-1101-disk-hc-topology.xml +SRCDIR = ../Joyent,Joyent-Compute-Platform-1101 -FRC: +PLATFORM = Joyent-Compute-Platform-1101 +TOPOBASE = ../i86pc/i86pc-hc-topology.xml -include ../../Makefile.targ +include ../Makefile.map diff --git a/usr/src/lib/fm/topo/maps/Makefile b/usr/src/lib/fm/topo/maps/Makefile index de6d9f5e0f..a01b016ebe 100644 --- a/usr/src/lib/fm/topo/maps/Makefile +++ b/usr/src/lib/fm/topo/maps/Makefile @@ -48,7 +48,8 @@ i386_SUBDIRS = i86pc \ SUNW,Netra-X4200-M2 \ SUNW,Sun-Fire-X4500 \ SUNW,Sun-Fire-X4540 \ - SUNW,Sun-Fire-X4600-M2 + SUNW,Sun-Fire-X4600-M2 \ + Joyent,Joyent-Compute-Platform-1101 SUBDIRS = $($(MACH)_SUBDIRS) diff --git a/usr/src/lib/fm/topo/maps/Makefile.map b/usr/src/lib/fm/topo/maps/Makefile.map index b72cd29d74..25577f6b26 100644 --- a/usr/src/lib/fm/topo/maps/Makefile.map +++ b/usr/src/lib/fm/topo/maps/Makefile.map @@ -22,12 +22,12 @@ # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright (c) 2013, Joyent, Inc. All rights reserved. # -# ident "%Z%%M% %I% %E% SMI" .KEEP_STATE: .SUFFIXES: -.SUFFIXES: .xml .xmlgen $(SUFFIXES) +.SUFFIXES: .xml .xmlgen .xmlgenksh $(SUFFIXES) MODCLASS = maps @@ -54,6 +54,11 @@ install:= FILEMODE = 0444 $(RM) $@ $(CAT) ../common/xmlgen-header.xml > $@ $(PERL) $< >> $@ + +.xmlgenksh.xml: + $(RM) $@ + $(CAT) ../common/xmlgen-header-new.xml > $@ + $(KSH93) $< >> $@ %.xml: ../common/%.xml $(RM) $@ diff --git a/usr/src/lib/fm/topo/maps/common/xmlgen-header-new.xml b/usr/src/lib/fm/topo/maps/common/xmlgen-header-new.xml new file mode 100644 index 0000000000..14cf1ff1e8 --- /dev/null +++ b/usr/src/lib/fm/topo/maps/common/xmlgen-header-new.xml @@ -0,0 +1,2 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> diff --git a/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml b/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml index 54021a7a5f..fda43bca6c 100644 --- a/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml +++ b/usr/src/lib/fm/topo/maps/i86pc/i86pc-legacy-hc-topology.xml @@ -2,6 +2,7 @@ <!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> <!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2013, Joyent, Inc. All rights reserved. CDDL HEADER START @@ -151,6 +152,18 @@ Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. </range> </set> + <set type='product' setlist='Joyent-Compute-Platform-1101|Joyent-Compute-Platform-1102'> + <range name='psu' min='0' max='1'> + <enum-method name='ipmi' version='1' /> + </range> + <range name='fan' min='0' max='100'> + <enum-method name='ipmi' version='1' /> + </range> + <range name='bay' min='0' max='15'> + <propmap name='Joyent-Compute-Platform-1101-disk' /> + </range> + </set> + <set type='product' setlist='default'> <range name='psu' min='0' max='100'> <enum-method name='ipmi' version='1' /> diff --git a/usr/src/lib/fm/topo/modules/common/Makefile b/usr/src/lib/fm/topo/modules/common/Makefile index 0b0f965a70..fa38496755 100644 --- a/usr/src/lib/fm/topo/modules/common/Makefile +++ b/usr/src/lib/fm/topo/modules/common/Makefile @@ -23,11 +23,11 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#pragma ident "%Z%%M% %I% %E% SMI" SUBDIRS = \ disk \ fac_prov_ipmi \ + fac_prov_mptsas \ ipmi \ ses \ xfp diff --git a/usr/src/lib/fm/topo/modules/common/disk/Makefile b/usr/src/lib/fm/topo/modules/common/disk/Makefile index b4821a6a82..4b4c965050 100644 --- a/usr/src/lib/fm/topo/modules/common/disk/Makefile +++ b/usr/src/lib/fm/topo/modules/common/disk/Makefile @@ -22,14 +22,15 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#pragma ident "%Z%%M% %I% %E% SMI" MODULE = disk CLASS = common -MODULESRCS = disk.c disk_common.c +MODULESRCS = disk.c disk_common.c disk_mptsas.c include ../../Makefile.plugin +CPPFLAGS += -I$(SRC)/uts/common + LDLIBS += -ldevinfo -ldevid -lcfgadm -ldiskstatus diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk.c b/usr/src/lib/fm/topo/modules/common/disk/disk.c index 427402c934..ec53198906 100644 --- a/usr/src/lib/fm/topo/modules/common/disk/disk.c +++ b/usr/src/lib/fm/topo/modules/common/disk/disk.c @@ -21,6 +21,9 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ #include <strings.h> #include <devid.h> @@ -33,6 +36,7 @@ #include <fm/libdiskstatus.h> #include <sys/fm/protocol.h> #include "disk.h" +#include "disk_drivers.h" static int disk_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t, topo_instance_t, void *, void *); @@ -43,13 +47,38 @@ static const topo_modops_t disk_ops = static const topo_modinfo_t disk_info = {DISK, FM_FMRI_SCHEME_HC, DISK_VERSION, &disk_ops}; +static int +disk_declare_driver(topo_mod_t *mod, tnode_t *baynode, topo_list_t *dlistp, + char *driver) +{ + int err; + + if (strcmp("mpt_sas", driver) == 0) { + char *sas_address = NULL; + tnode_t *child = NULL; + + if ((err = disk_mptsas_find_disk(mod, baynode, + &sas_address)) != 0) + return (err); + + err = disk_declare_addr(mod, baynode, dlistp, + sas_address, &child); + topo_mod_strfree(mod, sas_address); + + return (err); + } + + topo_mod_dprintf(mod, "unknown disk driver '%s'\n", driver); + return (-1); +} + /*ARGSUSED*/ static int disk_enum(topo_mod_t *mod, tnode_t *baynode, const char *name, topo_instance_t min, topo_instance_t max, void *arg, void *notused) { - char *device; + char *device, *driver; int err; nvlist_t *fmri; topo_list_t *dlistp = topo_mod_getspecific(mod); @@ -75,6 +104,22 @@ disk_enum(topo_mod_t *mod, tnode_t *baynode, nvlist_free(fmri); /* + * For internal storage, first check to see if we need to + * request more detail from an HBA driver. + */ + if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING, + TOPO_BINDING_DRIVER, &driver, &err) == 0) { + err = disk_declare_driver(mod, baynode, dlistp, driver); + + topo_mod_strfree(mod, driver); + return (err); + } else if (err != ETOPO_PROP_NOENT) { + topo_mod_dprintf(mod, "disk_enum: " + "binding error %s\n", topo_strerror(err)); + return (-1); + } + + /* * For internal storage, get the path to the occupant from the * binding group of the bay node */ diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk.h b/usr/src/lib/fm/topo/modules/common/disk/disk.h index 3fabc4c334..e61a54974b 100644 --- a/usr/src/lib/fm/topo/modules/common/disk/disk.h +++ b/usr/src/lib/fm/topo/modules/common/disk/disk.h @@ -22,6 +22,9 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ #ifndef _DISK_H #define _DISK_H @@ -54,6 +57,15 @@ extern "C" { */ #define TOPO_PGROUP_BINDING "binding" #define TOPO_BINDING_OCCUPANT "occupant-path" +#define TOPO_BINDING_DRIVER "driver" + +/* + * The binding group required in platform specific xml that describes 'bay' + * nodes containing disks attached to an HBA using the 'mpt_sas' driver. + */ +#define TOPO_BINDING_DEVCTL "devctl" +#define TOPO_BINDING_ENCLOSURE "enclosure" +#define TOPO_BINDING_SLOT "slot" /* * device node information. diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk_drivers.h b/usr/src/lib/fm/topo/modules/common/disk/disk_drivers.h new file mode 100644 index 0000000000..6851e2fe27 --- /dev/null +++ b/usr/src/lib/fm/topo/modules/common/disk/disk_drivers.h @@ -0,0 +1,31 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + +#ifndef _DISK_DRIVERS_H +#define _DISK_DRIVERS_H + +#include <fm/topo_mod.h> +#include <libdevinfo.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int disk_mptsas_find_disk(topo_mod_t *, tnode_t *, char **); + +#ifdef __cplusplus +} +#endif + +#endif /* _DISK_DRIVERS_H */ diff --git a/usr/src/lib/fm/topo/modules/common/disk/disk_mptsas.c b/usr/src/lib/fm/topo/modules/common/disk/disk_mptsas.c new file mode 100644 index 0000000000..db853c6695 --- /dev/null +++ b/usr/src/lib/fm/topo/modules/common/disk/disk_mptsas.c @@ -0,0 +1,120 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stropts.h> +#include <string.h> +#include <strings.h> + +#include <fm/topo_mod.h> +#include <fm/topo_list.h> + +#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_type.h> +#include <sys/scsi/adapters/mpt_sas/mpi/mpi2.h> +#include <sys/scsi/adapters/mpt_sas/mpi/mpi2_init.h> +#include <sys/scsi/adapters/mpt_sas/mptsas_ioctl.h> + +#include "disk.h" +#include "disk_drivers.h" + +static int +get_sas_address(topo_mod_t *mod, char *devctl, uint32_t enclosure, + uint32_t slot, char **sas_address) +{ + int fd, err, i; + mptsas_get_disk_info_t gdi; + mptsas_disk_info_t *di; + size_t disz; + + bzero(&gdi, sizeof (gdi)); + + if ((fd = open(devctl, O_RDWR)) == -1) { + topo_mod_dprintf(mod, "could not open '%s' for ioctl: %s\n", + devctl, strerror(errno)); + return (-1); + } + + if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) { + topo_mod_dprintf(mod, "ioctl 1 on '%s' failed: %s\n", devctl, + strerror(errno)); + (void) close(fd); + return (-1); + } + + gdi.DiskInfoArraySize = disz = sizeof (mptsas_disk_info_t) * + gdi.DiskCount; + gdi.PtrDiskInfoArray = di = topo_mod_alloc(mod, disz); + if (di == NULL) { + topo_mod_dprintf(mod, "memory allocation failed\n"); + (void) close(fd); + return (-1); + } + + if (ioctl(fd, MPTIOCTL_GET_DISK_INFO, &gdi) == -1) { + topo_mod_dprintf(mod, "ioctl 2 on '%s' failed: %s\n", devctl, + strerror(errno)); + topo_mod_free(mod, di, disz); + (void) close(fd); + return (-1); + } + + err = -1; + for (i = 0; i < gdi.DiskCount; i++) { + if (di[i].Enclosure == enclosure && di[i].Slot == slot) { + char sas[17]; /* 16 hex digits and NUL */ + (void) snprintf(sas, 17, "%llx", di[i].SasAddress); + topo_mod_dprintf(mod, "found mpt_sas disk (%d/%d) " + "with adddress %s\n", enclosure, slot, sas); + *sas_address = topo_mod_strdup(mod, sas); + err = 0; + break; + } + } + + topo_mod_free(mod, di, disz); + (void) close(fd); + return (err); +} + +int +disk_mptsas_find_disk(topo_mod_t *mod, tnode_t *baynode, char **sas_address) +{ + char *devctl = NULL; + uint32_t enclosure, slot; + int err; + + /* + * Get the required properties from the node. These come from + * the static XML mapping. + */ + if (topo_prop_get_string(baynode, TOPO_PGROUP_BINDING, + TOPO_BINDING_DEVCTL, &devctl, &err) != 0 || + topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING, + TOPO_BINDING_ENCLOSURE, &enclosure, &err) != 0 || + topo_prop_get_uint32(baynode, TOPO_PGROUP_BINDING, + TOPO_BINDING_SLOT, &slot, &err) != 0) { + if (devctl != NULL) + topo_mod_strfree(mod, devctl); + topo_mod_dprintf(mod, "bay node was missing mpt_sas binding " + "properties\n"); + return (-1); + } + + return (get_sas_address(mod, devctl, enclosure, slot, sas_address)); + +} diff --git a/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/Makefile b/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/Makefile new file mode 100644 index 0000000000..31838e1bc0 --- /dev/null +++ b/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/Makefile @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# Copyright (c) 2013, Joyent, Inc. All rights reserved. +# + +MODULE = fac_prov_mptsas +CLASS = common + +MODULESRCS = fac_prov_mptsas.c + +include ../../Makefile.plugin + +CPPFLAGS += -I$(SRC)/uts/common diff --git a/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/fac_prov_mptsas.c b/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/fac_prov_mptsas.c new file mode 100644 index 0000000000..a49a131811 --- /dev/null +++ b/usr/src/lib/fm/topo/modules/common/fac_prov_mptsas/fac_prov_mptsas.c @@ -0,0 +1,244 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> +#include <strings.h> +#include <limits.h> +#include <alloca.h> +#include <errno.h> +#include <libnvpair.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <sys/fm/protocol.h> +#include <fm/libtopo.h> +#include <fm/topo_mod.h> + +#include "sys/scsi/adapters/mpt_sas/mptsas_ioctl.h" + +#define TOPO_METH_MPTSAS_LED_MODE_VERSION 0 + +static int fac_prov_mptsas_enum(topo_mod_t *, tnode_t *, const char *, + topo_instance_t, topo_instance_t, void *, void *); + +/* + * mpt_sas facility provider methods + */ +static int mptsas_led_mode(topo_mod_t *, tnode_t *, topo_version_t, + nvlist_t *, nvlist_t **); + +const topo_modops_t mptsas_ops = { fac_prov_mptsas_enum, NULL }; + +const topo_modinfo_t mptsas_info = + { "mpt_sas facility provider", FM_FMRI_SCHEME_HC, TOPO_VERSION, + &mptsas_ops }; + +static const topo_method_t mptsas_fac_methods[] = { + { "mptsas_led_mode", TOPO_PROP_METH_DESC, + TOPO_METH_MPTSAS_LED_MODE_VERSION, + TOPO_STABILITY_INTERNAL, mptsas_led_mode }, + { NULL } +}; + +/*ARGSUSED*/ +int +_topo_init(topo_mod_t *mod, topo_version_t version) +{ + if (getenv("TOPOFACMPTSASDEBUG") != NULL) + topo_mod_setdebug(mod); + + return (topo_mod_register(mod, &mptsas_info, TOPO_VERSION)); +} + +void +_topo_fini(topo_mod_t *mod) +{ + topo_mod_unregister(mod); +} + +static int +do_led_control(topo_mod_t *mod, char *devctl, uint16_t enclosure, + uint16_t slot, uint8_t led, uint32_t *ledmode, boolean_t set) +{ + int fd; + mptsas_led_control_t lc; + + bzero(&lc, sizeof (lc)); + + lc.Command = set ? MPTSAS_LEDCTL_FLAG_SET : MPTSAS_LEDCTL_FLAG_GET; + lc.Enclosure = enclosure; + lc.Slot = slot; + lc.Led = led; + lc.LedStatus = *ledmode; + + if ((fd = open(devctl, (set ? O_RDWR : O_RDONLY))) == -1) { + topo_mod_dprintf(mod, "devctl open failed: %s", + strerror(errno)); + return (-1); + } + + if (ioctl(fd, MPTIOCTL_LED_CONTROL, &lc) == -1) { + if (errno == ENOENT) { + /* + * If there is not presently a target attached for + * a particular enclosure/slot pair then the driver + * does not track LED status for this bay. Assume + * all LEDs are off. + */ + lc.LedStatus = 0; + } else { + topo_mod_dprintf(mod, "led control ioctl failed: %s", + strerror(errno)); + (void) close(fd); + return (-1); + } + } + + *ledmode = lc.LedStatus ? TOPO_LED_STATE_ON : TOPO_LED_STATE_OFF; + + (void) close(fd); + return (0); +} + +static int +mptsas_led_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers, + nvlist_t *in, nvlist_t **nvout) +{ + int err, ret = 0; + tnode_t *pnode = topo_node_parent(node); + uint32_t type, ledmode = 0; + nvlist_t *pargs, *nvl; + char *driver = NULL, *devctl = NULL; + uint32_t enclosure, slot; + uint8_t mptsas_led; + boolean_t set; + + if (vers > TOPO_METH_MPTSAS_LED_MODE_VERSION) + return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); + + if (topo_prop_get_string(pnode, TOPO_PGROUP_BINDING, + TOPO_BINDING_DRIVER, &driver, &err) != 0 || + strcmp("mpt_sas", driver) != 0) { + topo_mod_dprintf(mod, "%s: Facility driver was not mpt_sas", + __func__); + ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL); + goto out; + } + if (topo_prop_get_uint32(node, TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE, + &type, &err) != 0) { + topo_mod_dprintf(mod, "%s: Failed to lookup %s property " + "(%s)", __func__, TOPO_FACILITY_TYPE, topo_strerror(err)); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + switch (type) { + case (TOPO_LED_TYPE_SERVICE): + mptsas_led = MPTSAS_LEDCTL_LED_FAIL; + break; + case (TOPO_LED_TYPE_LOCATE): + mptsas_led = MPTSAS_LEDCTL_LED_IDENT; + break; + case (TOPO_LED_TYPE_OK2RM): + mptsas_led = MPTSAS_LEDCTL_LED_OK2RM; + break; + default: + topo_mod_dprintf(mod, "%s: Invalid LED type: 0x%x\n", __func__, + type); + return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); + } + if (topo_prop_get_string(pnode, TOPO_PGROUP_BINDING, + TOPO_BINDING_DEVCTL, &devctl, &err) != 0 || + topo_prop_get_uint32(pnode, TOPO_PGROUP_BINDING, + TOPO_BINDING_ENCLOSURE, &enclosure, &err) != 0 || + topo_prop_get_uint32(pnode, TOPO_PGROUP_BINDING, + TOPO_BINDING_SLOT, &slot, &err) != 0) { + topo_mod_dprintf(mod, "%s: Facility was missing mpt_sas binding" + " properties\n", __func__); + ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL); + goto out; + } + + if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) && + nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) { + /* + * Set the LED mode + */ + set = B_TRUE; + if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL, + &ledmode)) != 0) { + topo_mod_dprintf(mod, "%s: Failed to lookup %s nvpair " + "(%s)\n", __func__, TOPO_PROP_VAL_VAL, + strerror(ret)); + ret = topo_mod_seterrno(mod, EMOD_NVL_INVAL); + goto out; + } + topo_mod_dprintf(mod, "%s: Setting LED mode to %s\n", __func__, + ledmode ? "ON" : "OFF"); + } else { + /* + * Get the LED mode + */ + set = B_FALSE; + topo_mod_dprintf(mod, "%s: Getting LED mode\n", __func__); + } + + if (do_led_control(mod, devctl, enclosure, slot, mptsas_led, &ledmode, + set) != 0) { + topo_mod_dprintf(mod, "%s: do_led_control failed", __func__); + ret = topo_mod_seterrno(mod, EMOD_UNKNOWN); + goto out; + } + + if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || + nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 || + nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) { + topo_mod_dprintf(mod, "%s: Failed to allocate 'out' nvlist\n", + __func__); + nvlist_free(nvl); + ret = topo_mod_seterrno(mod, EMOD_NOMEM); + goto out; + } + *nvout = nvl; + +out: + if (driver != NULL) + topo_mod_strfree(mod, driver); + if (devctl != NULL) + topo_mod_strfree(mod, devctl); + return (ret); +} + +/*ARGSUSED*/ +static int +fac_prov_mptsas_enum(topo_mod_t *mod, tnode_t *rnode, const char *name, + topo_instance_t min, topo_instance_t max, void *arg, void *unused) +{ + if (topo_node_flags(rnode) == TOPO_NODE_FACILITY) { + if (topo_method_register(mod, rnode, mptsas_fac_methods) != 0) { + topo_mod_dprintf(mod, "%s: topo_method_register() " + "failed: %s", __func__, topo_mod_errmsg(mod)); + return (-1); + } + return (0); + } + + topo_mod_dprintf(mod, "%s: unexpected node flags %x", __func__, + topo_node_flags(rnode)); + return (-1); +} diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/Makefile.com b/usr/src/lib/krb5/plugins/preauth/pkinit/Makefile.com index 8449d22e24..07fcb2bbf7 100644 --- a/usr/src/lib/krb5/plugins/preauth/pkinit/Makefile.com +++ b/usr/src/lib/krb5/plugins/preauth/pkinit/Makefile.com @@ -70,7 +70,7 @@ CERRWARN += -_gcc=-Wno-unused-function CFLAGS += $(CCVERBOSE) -I.. DYNFLAGS += $(KRUNPATH) $(KMECHLIB) -znodelete -LDLIBS += -L $(ROOTLIBDIR) -lcrypto -lc +LDLIBS += -L $(ROOTLIBDIR) -lsunw_crypto -lc ROOTLIBDIR= $(ROOT)/usr/lib/krb5/plugins/preauth diff --git a/usr/src/lib/libbe/common/be_list.c b/usr/src/lib/libbe/common/be_list.c index b9c7882d18..e669f24cc8 100644 --- a/usr/src/lib/libbe/common/be_list.c +++ b/usr/src/lib/libbe/common/be_list.c @@ -25,6 +25,7 @@ /* * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + * Copyright 2011 Joyent, Inc. All rights reserved. */ #include <assert.h> @@ -872,7 +873,7 @@ be_get_node_data( } (void) zpool_get_prop(zphp, ZPOOL_PROP_BOOTFS, prop_buf, ZFS_MAXPROPLEN, - NULL); + NULL, B_FALSE); if (be_has_grub() && (be_default_grub_bootfs(rpool, &grub_default_bootfs) == BE_SUCCESS) && grub_default_bootfs != NULL) diff --git a/usr/src/lib/libbrand/Makefile.com b/usr/src/lib/libbrand/Makefile.com index cd7d83371a..0fceb70aac 100644 --- a/usr/src/lib/libbrand/Makefile.com +++ b/usr/src/lib/libbrand/Makefile.com @@ -34,7 +34,7 @@ include ../../Makefile.lib LIBS= $(DYNLIB) $(LINTLIB) LDLIBS += -lc $(LINTLIB) := SRCS= $(SRCDIR)/$(LINTSRC) -CPPFLAGS += -I/usr/include/libxml2 -I$(SRCDIR) -D_REENTRANT +CPPFLAGS += -I$(ADJUNCT_PROTO)/usr/include/libxml2 -I$(SRCDIR) -D_REENTRANT $(DYNLIB) := LDLIBS += -lxml2 SRCDIR= ../common diff --git a/usr/src/lib/libbrand/common/libbrand.c b/usr/src/lib/libbrand/common/libbrand.c index 5034715a7e..baaaf33120 100644 --- a/usr/src/lib/libbrand/common/libbrand.c +++ b/usr/src/lib/libbrand/common/libbrand.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent, Inc. All rights reserved. */ #include <assert.h> @@ -60,6 +61,7 @@ #define DTD_ELEM_FORCELOGIN_CMD ((const xmlChar *) "forcedlogin_cmd") #define DTD_ELEM_MODNAME ((const xmlChar *) "modname") #define DTD_ELEM_MOUNT ((const xmlChar *) "mount") +#define DTD_ELEM_RESTARTINIT ((const xmlChar *) "restartinit") #define DTD_ELEM_POSTATTACH ((const xmlChar *) "postattach") #define DTD_ELEM_POSTCLONE ((const xmlChar *) "postclone") #define DTD_ELEM_POSTINSTALL ((const xmlChar *) "postinstall") @@ -319,6 +321,7 @@ i_substitute_tokens(const char *sbuf, char *dbuf, int dbuf_size, const char *curr_zone) { int dst, src; + static char *env_pool = NULL; /* * Walk through the characters, substituting values as needed. @@ -335,6 +338,13 @@ i_substitute_tokens(const char *sbuf, char *dbuf, int dbuf_size, case '%': dst += strlcpy(dbuf + dst, "%", dbuf_size - dst); break; + case 'P': + if (env_pool == NULL) + env_pool = getenv("_ZONEADMD_ZPOOL"); + if (env_pool == NULL) + break; + dst += strlcpy(dbuf + dst, env_pool, dbuf_size - dst); + break; case 'R': if (zonepath == NULL) break; @@ -509,6 +519,21 @@ brand_get_initname(brand_handle_t bh, char *buf, size_t len) buf, len, DTD_ELEM_INITNAME, B_FALSE, B_FALSE)); } +boolean_t +brand_restartinit(brand_handle_t bh) +{ + struct brand_handle *bhp = (struct brand_handle *)bh; + char val[80]; + + if (brand_get_value(bhp, NULL, NULL, NULL, NULL, + val, 80, DTD_ELEM_RESTARTINIT, B_FALSE, B_FALSE) != 0) + return (B_TRUE); + + if (strcmp(val, "false") == 0) + return (B_FALSE); + return (B_TRUE); +} + int brand_get_login_cmd(brand_handle_t bh, const char *username, char *buf, size_t len) diff --git a/usr/src/lib/libbrand/common/libbrand.h b/usr/src/lib/libbrand/common/libbrand.h index 19231604a5..1ca9e9f36d 100644 --- a/usr/src/lib/libbrand/common/libbrand.h +++ b/usr/src/lib/libbrand/common/libbrand.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent, Inc. All rights reserved. */ #ifndef _LIBBRAND_H @@ -57,6 +58,7 @@ extern int brand_get_detach(brand_handle_t, const char *, const char *, extern int brand_get_halt(brand_handle_t, const char *, const char *, char *, size_t); extern int brand_get_initname(brand_handle_t, char *, size_t); +extern boolean_t brand_restartinit(brand_handle_t); extern int brand_get_install(brand_handle_t, const char *, const char *, char *, size_t); extern int brand_get_installopts(brand_handle_t, char *, size_t); diff --git a/usr/src/lib/libbrand/common/mapfile-vers b/usr/src/lib/libbrand/common/mapfile-vers index 7b961c3c18..9bf21d2d26 100644 --- a/usr/src/lib/libbrand/common/mapfile-vers +++ b/usr/src/lib/libbrand/common/mapfile-vers @@ -20,6 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, Joyent, Inc. All rights reserved. # # @@ -76,6 +77,7 @@ SYMBOL_VERSION SUNWprivate { brand_platform_iter_gmounts; brand_platform_iter_link; brand_platform_iter_mounts; + brand_restartinit; local: *; }; diff --git a/usr/src/lib/libbrand/dtd/brand.dtd.1 b/usr/src/lib/libbrand/dtd/brand.dtd.1 index 15542102db..89719a6ae6 100644 --- a/usr/src/lib/libbrand/dtd/brand.dtd.1 +++ b/usr/src/lib/libbrand/dtd/brand.dtd.1 @@ -21,6 +21,7 @@ CDDL HEADER END Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2011, Joyent, Inc. All rights reserved. DO NOT EDIT THIS FILE. --> @@ -188,6 +189,19 @@ <!ATTLIST initname> <!-- + restartinit + + Boolean indicating that the program specified by the initname attr + should be restarted, or not, if it exits. By default, the init program + will be restarted if this attribute is not provided. Specifying false + for this attr will prevent that. + + It has no attributes. +--> +<!ELEMENT restartinit (#PCDATA) > +<!ATTLIST restartinit> + +<!-- login_cmd Path to the initial login binary that should be executed when @@ -605,8 +619,8 @@ directory in which the configuration file is stored. --> -<!ELEMENT brand (modname?, initname, login_cmd, forcedlogin_cmd, - user_cmd, install, +<!ELEMENT brand (modname?, initname, restartinit?, login_cmd, + forcedlogin_cmd, user_cmd, install, installopts?, boot?, sysboot?, halt?, verify_cfg?, verify_adm?, postattach?, postclone?, postinstall?, predetach?, attach?, detach?, clone?, diff --git a/usr/src/lib/libbsm/common/adt.c b/usr/src/lib/libbsm/common/adt.c index 8c7b299e32..4cf0dd7566 100644 --- a/usr/src/lib/libbsm/common/adt.c +++ b/usr/src/lib/libbsm/common/adt.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2013, Joyent, Inc. All rights reserved. */ #include <bsm/adt.h> @@ -702,7 +703,37 @@ adt_get_hostIP(const char *hostname, au_tid_addr_t *p_term) int tries = 3; char msg[512]; int eai_err; + struct ifaddrlist al; + int family; + boolean_t found = B_FALSE; + /* + * getaddrinfo can take a long time to timeout if it can't map the + * hostname to an IP address so try to get an IP address from a local + * interface first. + */ + family = AF_INET6; + if (adt_get_local_address(family, &al) == 0) { + found = B_TRUE; + } else { + family = AF_INET; + if (adt_get_local_address(family, &al) == 0) + found = B_TRUE; + } + + if (found) { + if (family == AF_INET) { + p_term->at_type = AU_IPv4; + (void) memcpy(p_term->at_addr, &al.addr.addr, AU_IPv4); + } else { + p_term->at_type = AU_IPv6; + (void) memcpy(p_term->at_addr, &al.addr.addr6, AU_IPv6); + } + + return (0); + } + + /* Now try getaddrinfo */ while ((tries-- > 0) && ((eai_err = getaddrinfo(hostname, NULL, NULL, &ai)) != 0)) { /* @@ -739,7 +770,9 @@ adt_get_hostIP(const char *hostname, au_tid_addr_t *p_term) } freeaddrinfo(ai); return (0); - } else if (auditstate & (AUC_AUDITING | AUC_NOSPACE)) { + } + + if (auditstate & (AUC_AUDITING | AUC_NOSPACE)) { auditinfo_addr_t audit_info; /* @@ -747,58 +780,23 @@ adt_get_hostIP(const char *hostname, au_tid_addr_t *p_term) * kernel audit context */ if (auditon(A_GETKAUDIT, (caddr_t)&audit_info, - sizeof (audit_info)) < 0) { - adt_write_syslog("unable to get kernel audit context", - errno); - goto try_interface; + sizeof (audit_info)) >= 0) { + adt_write_syslog("setting Audit IP address to kernel", + 0); + *p_term = audit_info.ai_termid; + return (0); } - adt_write_syslog("setting Audit IP address to kernel", 0); - *p_term = audit_info.ai_termid; - return (0); + adt_write_syslog("unable to get kernel audit context", errno); } -try_interface: - { - struct ifaddrlist al; - int family; - char ntop[INET6_ADDRSTRLEN]; - - /* - * getaddrinfo has failed to map the hostname - * to an IP address, try to get an IP address - * from a local interface. If none up, default - * to loopback. - */ - family = AF_INET6; - if (adt_get_local_address(family, &al) != 0) { - family = AF_INET; - - if (adt_get_local_address(family, &al) != 0) { - adt_write_syslog("adt_get_local_address " - "failed, no Audit IP address available, " - "faking loopback and error", - errno); - IN_SET_LOOPBACK_ADDR( - (struct sockaddr_in *)&(al.addr.addr)); - (void) memcpy(p_term->at_addr, &al.addr.addr, - AU_IPv4); - p_term->at_type = AU_IPv4; - return (-1); - } - } - if (family == AF_INET) { - p_term->at_type = AU_IPv4; - (void) memcpy(p_term->at_addr, &al.addr.addr, AU_IPv4); - } else { - p_term->at_type = AU_IPv6; - (void) memcpy(p_term->at_addr, &al.addr.addr6, AU_IPv6); - } - (void) snprintf(msg, sizeof (msg), "mapping %s to %s", - hostname, inet_ntop(family, &(al.addr), ntop, - sizeof (ntop))); - adt_write_syslog(msg, 0); - return (0); - } + /* No mapping, default to loopback. */ + errno = ENETDOWN; + adt_write_syslog("adt_get_local_address failed, no Audit IP address " + "available, faking loopback and error", errno); + IN_SET_LOOPBACK_ADDR((struct sockaddr_in *)&(al.addr.addr)); + (void) memcpy(p_term->at_addr, &al.addr.addr, AU_IPv4); + p_term->at_type = AU_IPv4; + return (-1); } /* @@ -2093,8 +2091,8 @@ adt_selected(struct adt_event_state *event, au_event_t actual_id, int status) } /* - * Can't map the host name to an IP address in - * adt_get_hostIP. Get something off an interface + * Before trying to map the host name to an IP address in + * adt_get_hostIP, get something off an interface * to act as the hosts IP address for auditing. */ diff --git a/usr/src/lib/libc/amd64/Makefile b/usr/src/lib/libc/amd64/Makefile index 9ddd748eb6..396c536387 100644 --- a/usr/src/lib/libc/amd64/Makefile +++ b/usr/src/lib/libc/amd64/Makefile @@ -20,6 +20,7 @@ # # # Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, Joyent, Inc. All rights reserved. # # Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2011 Nexenta Systems, Inc. All rights reserved. @@ -798,6 +799,7 @@ THREADSOBJS= \ assfail.o \ cancel.o \ door_calls.o \ + tmem.o \ pthr_attr.o \ pthr_barrier.o \ pthr_cond.o \ diff --git a/usr/src/lib/libc/i386/Makefile.com b/usr/src/lib/libc/i386/Makefile.com index 31a7bc945f..d5826d8e45 100644 --- a/usr/src/lib/libc/i386/Makefile.com +++ b/usr/src/lib/libc/i386/Makefile.com @@ -21,6 +21,7 @@ # # Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. +# Copyright (c) 2012, Joyent, Inc. All rights reserved. # # Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Use is subject to license terms. @@ -840,6 +841,7 @@ THREADSOBJS= \ assfail.o \ cancel.o \ door_calls.o \ + tmem.o \ pthr_attr.o \ pthr_barrier.o \ pthr_cond.o \ diff --git a/usr/src/lib/libc/inc/thr_inlines.h b/usr/src/lib/libc/inc/thr_inlines.h index f7cdc6a6bd..66d811f25b 100644 --- a/usr/src/lib/libc/inc/thr_inlines.h +++ b/usr/src/lib/libc/inc/thr_inlines.h @@ -47,17 +47,19 @@ extern __GNU_INLINE ulwp_t * _curthread(void) { -#if defined(__amd64) ulwp_t *__value; - __asm__ __volatile__("movq %%fs:0, %0" : "=r" (__value)); + __asm__ __volatile__( +#if defined(__amd64) + "movq %%fs:0, %0\n\t" #elif defined(__i386) - ulwp_t *__value; - __asm__ __volatile__("movl %%gs:0, %0" : "=r" (__value)); + "movl %%gs:0, %0\n\t" #elif defined(__sparc) - register ulwp_t *__value __asm__("g7"); + ".register %%g7, #scratch\n\t" + "mov %%g7, %0\n\t" #else #error "port me" #endif + : "=r" (__value)); return (__value); } diff --git a/usr/src/lib/libc/inc/thr_uberdata.h b/usr/src/lib/libc/inc/thr_uberdata.h index 42c08049b2..5f67e760e2 100644 --- a/usr/src/lib/libc/inc/thr_uberdata.h +++ b/usr/src/lib/libc/inc/thr_uberdata.h @@ -22,6 +22,9 @@ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ #ifndef _THR_UBERDATA_H #define _THR_UBERDATA_H @@ -488,6 +491,28 @@ typedef struct { #endif /* _SYSCALL32 */ /* + * As part of per-thread caching libumem (ptcumem), we add a small amount to the + * thread's uberdata to facilitate it. The tm_roots are the roots of linked + * lists which is used by libumem to chain together allocations. tm_size is used + * to track the total amount of data stored across those linked lists. + */ +#define NTMEMBASE 16 + +typedef struct { + size_t tm_size; + void *tm_roots[NTMEMBASE]; +} tumem_t; + +#ifdef _SYSCALL32 +typedef struct { + uint32_t tm_size; + caddr32_t tm_roots[NTMEMBASE]; +} tumem32_t; +#endif + +typedef void (*tmem_func_t)(void *, int); + +/* * Maximum number of read locks allowed for one thread on one rwlock. * This could be as large as INT_MAX, but the SUSV3 test suite would * take an inordinately long time to complete. This is big enough. @@ -653,6 +678,7 @@ typedef struct ulwp { #if defined(sparc) void *ul_unwind_ret; /* used only by _ex_clnup_handler() */ #endif + tumem_t ul_tmem; /* used only by umem */ } ulwp_t; #define ul_cursig ul_cp.s.cursig /* deferred signal number */ @@ -1083,6 +1109,7 @@ typedef struct ulwp32 { #if defined(sparc) caddr32_t ul_unwind_ret; /* used only by _ex_clnup_handler() */ #endif + tumem32_t ul_tmem; /* used only by umem */ } ulwp32_t; #define REPLACEMENT_SIZE32 ((size_t)&((ulwp32_t *)NULL)->ul_sigmask) @@ -1205,6 +1232,7 @@ extern ulwp_t *find_lwp(thread_t); extern void finish_init(void); extern void update_sched(ulwp_t *); extern void queue_alloc(void); +extern void tmem_exit(void); extern void tsd_exit(void); extern void tsd_free(ulwp_t *); extern void tls_setup(void); diff --git a/usr/src/lib/libc/port/gen/getlogin.c b/usr/src/lib/libc/port/gen/getlogin.c index a3d7b4cf3b..e96d294fd0 100644 --- a/usr/src/lib/libc/port/gen/getlogin.c +++ b/usr/src/lib/libc/port/gen/getlogin.c @@ -27,7 +27,9 @@ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2013 Joyent, Inc. All rights reserved. + */ #pragma weak _getlogin = getlogin #pragma weak _getlogin_r = getlogin_r @@ -35,6 +37,7 @@ #include "lint.h" #include <sys/types.h> #include <sys/stat.h> +#include <sys/sysmacros.h> #include <fcntl.h> #include <string.h> #include <stdlib.h> @@ -51,40 +54,55 @@ * XXX - _POSIX_LOGIN_NAME_MAX limits the length of a login name. The utmpx * interface provides for a 32 character login name, but for the sake of * compatibility, we are still using the old utmp-imposed limit. + * + * If you want the full name, use the Consolidation Private getxlogin(). */ -/* - * POSIX.1c Draft-6 version of the function getlogin_r. - * It was implemented by Solaris 2.3. - */ -char * -getlogin_r(char *answer, int namelen) +static int +generic_getlogin(char *answer, int namelen, boolean_t truncate) { int uf; off64_t me; struct futmpx ubuf; - if (namelen < _POSIX_LOGIN_NAME_MAX) { - errno = ERANGE; - return (NULL); - } - if ((me = (off64_t)ttyslot()) < 0) - return (NULL); + return (-1); if ((uf = open64(UTMPX_FILE, 0)) < 0) - return (NULL); + return (-1); (void) lseek64(uf, me * sizeof (ubuf), SEEK_SET); if (read(uf, &ubuf, sizeof (ubuf)) != sizeof (ubuf)) { (void) close(uf); - return (NULL); + return (-1); } (void) close(uf); if (ubuf.ut_user[0] == '\0') + return (-1); + if (strnlen(ubuf.ut_user, sizeof (ubuf.ut_user)) >= namelen && + !truncate) { + errno = ERANGE; + return (-1); + } + (void) strlcpy(answer, ubuf.ut_user, namelen); + + return (0); +} + +/* + * POSIX.1c Draft-6 version of the function getlogin_r. + * It was implemented by Solaris 2.3. + */ +char * +getlogin_r(char *answer, int namelen) +{ + if (namelen < _POSIX_LOGIN_NAME_MAX) { + errno = ERANGE; return (NULL); - (void) strncpy(&answer[0], &ubuf.ut_user[0], - _POSIX_LOGIN_NAME_MAX - 1); - answer[_POSIX_LOGIN_NAME_MAX - 1] = '\0'; - return (&answer[0]); + } + + if (generic_getlogin(answer, _POSIX_LOGIN_NAME_MAX, B_TRUE) == 0) + return (answer); + + return (NULL); } /* @@ -98,7 +116,7 @@ __posix_getlogin_r(char *name, int namelen) int oerrno = errno; errno = 0; - if (getlogin_r(name, namelen) == NULL) { + if (getlogin_r(name, namelen) != 0) { if (errno == 0) nerrno = EINVAL; else @@ -111,9 +129,28 @@ __posix_getlogin_r(char *name, int namelen) char * getlogin(void) { - char *answer = tsdalloc(_T_LOGIN, _POSIX_LOGIN_NAME_MAX, NULL); + struct futmpx fu; + char *answer = tsdalloc(_T_LOGIN, + MAX(sizeof (fu.ut_user), _POSIX_LOGIN_NAME_MAX), NULL); if (answer == NULL) return (NULL); return (getlogin_r(answer, _POSIX_LOGIN_NAME_MAX)); } + +char * +getxlogin(void) +{ + struct futmpx fu; + char *answer = tsdalloc(_T_LOGIN, + MAX(sizeof (fu.ut_user), _POSIX_LOGIN_NAME_MAX), NULL); + + if (answer == NULL) + return (NULL); + + if (generic_getlogin(answer, + MAX(sizeof (fu.ut_user), _POSIX_LOGIN_NAME_MAX), B_FALSE) != 0) + return (NULL); + + return (answer); +} diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers index d6907e359d..ae0034931d 100644 --- a/usr/src/lib/libc/port/mapfile-vers +++ b/usr/src/lib/libc/port/mapfile-vers @@ -24,6 +24,7 @@ # Copyright 2010 Nexenta Systems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright (c) 2012, Joyent, Inc. All rights reserved. # Copyright (c) 2012 by Delphix. All rights reserved. # Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. @@ -2743,6 +2744,7 @@ $endif getvmusage; __getwchar_xpg5; __getwc_xpg5; + getxlogin; gtty; __idmap_flush_kcache; __idmap_reg; @@ -2888,6 +2890,9 @@ $endif thr_wait_mutator; _thr_wait_mutator; __tls_get_addr; + _tmem_get_base; + _tmem_get_nentries; + _tmem_set_cleanup; tpool_create; tpool_dispatch; tpool_destroy; diff --git a/usr/src/lib/libc/port/sys/zone.c b/usr/src/lib/libc/port/sys/zone.c index 4a4c70043d..182a7f22f7 100644 --- a/usr/src/lib/libc/port/sys/zone.c +++ b/usr/src/lib/libc/port/sys/zone.c @@ -22,6 +22,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2011 Joyent Inc. All rights reserved. */ #include "lint.h" @@ -39,7 +40,8 @@ zoneid_t zone_create(const char *name, const char *root, const struct priv_set *privs, const char *rctls, size_t rctlsz, const char *zfs, size_t zfssz, - int *extended_error, int match, int doi, const bslabel_t *label, int flags) + int *extended_error, int match, int doi, const bslabel_t *label, int flags, + zoneid_t req_zoneid) { zone_def zd; priv_data_t *d; @@ -59,6 +61,7 @@ zone_create(const char *name, const char *root, const struct priv_set *privs, zd.doi = doi; zd.label = label; zd.flags = flags; + zd.zoneid = req_zoneid; return ((zoneid_t)syscall(SYS_zone, ZONE_CREATE, &zd)); } diff --git a/usr/src/lib/libc/port/threads/thr.c b/usr/src/lib/libc/port/threads/thr.c index ae55fbddf5..b5d848449d 100644 --- a/usr/src/lib/libc/port/threads/thr.c +++ b/usr/src/lib/libc/port/threads/thr.c @@ -22,6 +22,9 @@ /* * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ #include "lint.h" #include "thr_uberdata.h" @@ -771,6 +774,7 @@ _thrp_exit() } lmutex_unlock(&udp->link_lock); + tmem_exit(); /* deallocate tmem allocations */ tsd_exit(); /* deallocate thread-specific data */ tls_exit(); /* deallocate thread-local storage */ heldlock_exit(); /* deal with left-over held locks */ diff --git a/usr/src/lib/libc/port/threads/tmem.c b/usr/src/lib/libc/port/threads/tmem.c new file mode 100644 index 0000000000..00203de593 --- /dev/null +++ b/usr/src/lib/libc/port/threads/tmem.c @@ -0,0 +1,85 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ + +#include "lint.h" +#include "thr_uberdata.h" + +/* + * This file implements the private interface with libumem for per-thread + * caching umem (ptcumem). For the full details on how tcumem works and how + * these functions work, see section 8.4 of the big theory statement in + * lib/libumem/common/umem.c. + */ +static tmem_func_t tmem_cleanup = NULL; + +uintptr_t +_tmem_get_base(void) +{ + return ((uintptr_t)&curthread->ul_tmem - (uintptr_t)curthread); +} + +int +_tmem_get_nentries(void) +{ + return (NTMEMBASE); +} + +void +_tmem_set_cleanup(tmem_func_t f) +{ + tmem_cleanup = f; +} + +/* + * This is called by _thrp_exit() to clean up any per-thread allocations that + * are still hanging around and haven't been cleaned up. + */ +void +tmem_exit(void) +{ + int ii; + void *buf, *next; + tumem_t *tp = &curthread->ul_tmem; + + + if (tp->tm_size == 0) + return; + + /* + * Since we have something stored here, we need to ensure we declared a + * clean up handler. If we haven't that's broken and our single private + * consumer should be shot. + */ + if (tmem_cleanup == NULL) + abort(); + for (ii = 0; ii < NTMEMBASE; ii++) { + buf = tp->tm_roots[ii]; + while (buf != NULL) { + next = *(void **)buf; + tmem_cleanup(buf, ii); + buf = next; + } + } +} diff --git a/usr/src/lib/libc/sparc/Makefile.com b/usr/src/lib/libc/sparc/Makefile.com index cc6bae0df4..4840990414 100644 --- a/usr/src/lib/libc/sparc/Makefile.com +++ b/usr/src/lib/libc/sparc/Makefile.com @@ -21,6 +21,7 @@ # # Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. +# Copyright (c) 2012, Joyent, Inc. All rights reserved. # # Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Use is subject to license terms. @@ -875,6 +876,7 @@ THREADSOBJS= \ assfail.o \ cancel.o \ door_calls.o \ + tmem.o \ pthr_attr.o \ pthr_barrier.o \ pthr_cond.o \ diff --git a/usr/src/lib/libc/sparc/crt/_rtld.c b/usr/src/lib/libc/sparc/crt/_rtld.c index a9e9c6d98a..843cfe03a5 100644 --- a/usr/src/lib/libc/sparc/crt/_rtld.c +++ b/usr/src/lib/libc/sparc/crt/_rtld.c @@ -62,6 +62,15 @@ #define SYSCONFIG (*(funcs[SYSCONFIG_F])) /* + * GCC will not emit unused static functions unless specifically told it must + */ +#ifdef __GNUC__ +#define __USED __attribute__((used)) +#else +#define __USED +#endif + +/* * Alias ld.so entry point -- receives a bootstrap structure and a vector * of strings. The vector is "well-known" to us, and consists of pointers * to string constants. This aliasing bootstrap requires no relocation in diff --git a/usr/src/lib/libc/sparcv9/Makefile.com b/usr/src/lib/libc/sparcv9/Makefile.com index 54b3258fe9..669e06395c 100644 --- a/usr/src/lib/libc/sparcv9/Makefile.com +++ b/usr/src/lib/libc/sparcv9/Makefile.com @@ -21,6 +21,7 @@ # # Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. +# Copyright (c) 2012, Joyent, Inc. All rights reserved. # # Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Use is subject to license terms. @@ -822,6 +823,7 @@ THREADSOBJS= \ assfail.o \ cancel.o \ door_calls.o \ + tmem.o \ pthr_attr.o \ pthr_barrier.o \ pthr_cond.o \ diff --git a/usr/src/lib/libctf/common/mapfile-vers b/usr/src/lib/libctf/common/mapfile-vers index c218edc37c..0873de319e 100644 --- a/usr/src/lib/libctf/common/mapfile-vers +++ b/usr/src/lib/libctf/common/mapfile-vers @@ -60,6 +60,7 @@ SYMBOL_VERSION SUNWprivate_1.2 { ctf_add_union; ctf_add_volatile; ctf_create; + ctf_delete_type; ctf_discard; ctf_enum_value; ctf_label_info; diff --git a/usr/src/lib/libdiskmgt/common/disks_private.h b/usr/src/lib/libdiskmgt/common/disks_private.h index 0f782bc383..5e44ba437a 100644 --- a/usr/src/lib/libdiskmgt/common/disks_private.h +++ b/usr/src/lib/libdiskmgt/common/disks_private.h @@ -109,6 +109,7 @@ typedef struct disk { int rpm; int wide; int cd_rom; + int solid_state; } disk_t; typedef struct descriptor { diff --git a/usr/src/lib/libdiskmgt/common/drive.c b/usr/src/lib/libdiskmgt/common/drive.c index 825348ce9f..f1b2d49961 100644 --- a/usr/src/lib/libdiskmgt/common/drive.c +++ b/usr/src/lib/libdiskmgt/common/drive.c @@ -350,6 +350,7 @@ static int get_io_kstats(kstat_ctl_t *kc, char *diskname, static int get_kstat_vals(kstat_t *ksp, nvlist_t *stats); static char *get_err_attr_name(char *kstat_name); static int get_rpm(disk_t *dp, int fd); +static int get_solidstate(disk_t *dp, int fd); static int update_stat64(nvlist_t *stats, char *attr, uint64_t value); static int update_stat32(nvlist_t *stats, char *attr, @@ -943,6 +944,16 @@ get_attrs(disk_t *diskp, int fd, char *opath, nvlist_t *attrs) } } + if (diskp->solid_state < 0) { + diskp->solid_state = get_solidstate(diskp, fd); + } + + if (diskp->solid_state > 0) { + if (nvlist_add_boolean(attrs, DM_SOLIDSTATE) != 0) { + return (ENOMEM); + } + } + return (0); } @@ -1197,6 +1208,31 @@ get_rpm(disk_t *dp, int fd) return (rpm); } +static int +get_solidstate(disk_t *dp, int fd) +{ + int opened_here = 0; + int solid_state = -1; + + /* We may have already opened the device. */ + if (fd < 0) { + fd = drive_open_disk(dp, NULL, 0); + opened_here = 1; + } + + if (fd >= 0) { + if (ioctl(fd, DKIOCSOLIDSTATE, &solid_state) < 0) { + solid_state = -1; + } + } + + if (opened_here) { + (void) close(fd); + } + + return (solid_state); +} + /* * ******** the rest of this is uscsi stuff for the drv type ******** */ diff --git a/usr/src/lib/libdiskmgt/common/findevs.c b/usr/src/lib/libdiskmgt/common/findevs.c index 9728eab65e..19089e8531 100644 --- a/usr/src/lib/libdiskmgt/common/findevs.c +++ b/usr/src/lib/libdiskmgt/common/findevs.c @@ -997,6 +997,7 @@ create_disk(char *deviceid, char *kernel_name, struct search_args *args) diskp->cd_rom = 0; diskp->rpm = 0; + diskp->solid_state = -1; type = di_minor_nodetype(args->minor); prod_id = get_str_prop(PROD_ID_PROP, args->node); diff --git a/usr/src/lib/libdiskmgt/common/libdiskmgt.h b/usr/src/lib/libdiskmgt/common/libdiskmgt.h index d075746122..2c42f6e8cc 100644 --- a/usr/src/lib/libdiskmgt/common/libdiskmgt.h +++ b/usr/src/lib/libdiskmgt/common/libdiskmgt.h @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #ifndef _LIBDISKMGT_H @@ -35,6 +36,144 @@ extern "C" { /* + * Disk Management Library + * + * This library provides a common way to gather information about a system's + * disks, controllers, and related components. + * + * + * THREADS + * ------- + * + * In general all of the functions are thread safe, however there are some + * specific considerations for getting events. The dm_get_event function may + * block the calling thread if no event is currently available. If another + * thread calls dm_get_event while a thread is already blocked in this function, + * the second thread will also block. When an event arrives and multiple + * threads are waiting for events, it is undefined which thread will be + * unblocked and receive the event. If a callback is used for handling events, + * this is equivalent to the dm_get_event function, so mixing callbacks and + * dm_get_event is also nondeterministic. + * + * + * ERRORS + * ------ + * + * In general all of the functions take an errno pointer. This is an integer + * that will contain 0 if the function succeeded or contains an errno (see + * errno.h) if there was an error. If the function returns some data, that + * return data will generally be null if an error occured (see the API comment + * for the specific function for details). Many of the functions take a + * descriptor and provide more information for that descriptor. These functions + * may return an error if the object was removed between the call which obtained + * the descriptor and the call to get more information about the object (errno + * will be ENODEV). Only a few of the possible errno values will be returned; + * typically: + * EPERM not super-user + * ENOMEM not enough memory + * ENODEV no such device + * EINVAL invalid argument + * ENOENT no event queue has been created + * + * Many of the functions require the application to be running as root in order + * to get complete information. EPERM will be returned if the application is + * not running as root. However, not all of the functions have this requirement + * (i.e. event handling). + * + * It is possible for the system to run out of memory while receiving events. + * Since event receipt is asyncronous from the dm_get_event call there may not + * be a thread waiting when the event occurs and ENOMEM is detected. In this + * case the event will be lost. The first call to dm_get_event following this + * condition will immediately return ENOMEM, even if events are queued. + * Subsequent calls can return events. The dm_get_event call will clear the + * pending ENOMEM condition. There is no way to know how many events were lost + * when this situation occurs. If a thread is waiting when the event arrives + * and the ENOMEM condition occurs, the call will also return with ENOMEM. + * There is no way to determine if the system ran out of memory before the + * dm_get_event call or while the thread was blocked in the dm_get_event call + * since both conditions cause dm_get_event to return ENOMEM. + * + * + * MEMORY MANAGEMENT + * ----------------- + * + * Most of the functions that return data are returning memory that has been + * allocated and must be freed by the application when no longer needed. The + * application should call the proper free function to free the memory. Most of + * the functions return either a nvlist or an array of descriptors. The normal + * nvlist function (nvlist_free; see libnvpair(3LIB)) can be used to free the + * simple nvlists. Other functions are provided to free the more complex data + * structures. + * + * The following list shows the functions that return allocated memory and the + * corresponding function to free the memory: + * dm_get_descriptors dm_free_descriptors + * dm_get_associated_descriptors dm_free_descriptors + * dm_get_descriptor_by_name dm_free_descriptor + * dm_get_name dm_free_name + * dm_get_attributes nvlist_free + * dm_get_stats nvlist_free + * dm_get_event nvlist_free + * + * + * EVENTS + * ------ + * + * Event information is returned as a nvlist. It may be possible to return more + * information about events over time, especially information about what has + * changed. However, that may not always be the case, so by using an nvlist we + * have a very generic event indication. At a minimum the event will return the + * name of the device, the type of device (see dm_desc_type_t) and the type of + * event. The event type is a string which can currently be; add, remove, + * change. + * + * If a drive goes up or down this could be returned as event type "change". + * The application could get the drive information to see that the "status" + * attribute has changed value (ideally the event would include an attribute + * with the name of the changed attribute as the value). Although the API can + * return events for all drive related changes, events will not necessarily be + * delivered for all changes unless the system generates those events. + * + * + * Controller/HBAs + * --------------- + * + * In general the API means "the parent node of the drive in the device tree" + * where the word "controller" is used. This can actually be either the HBA or + * the drive controller depending on the type of the drive. + * + * Drives can be connected to their controller(s) in three different ways: + * single controller + * multiple controllers + * multiple controllers with mpxio + * These cases will lead to different information being available for the + * configuration. The two interesting cases are multi-path with and without + * mpxio. With mpxio the drive will have a unique name and a single controller + * (scsi_vhci). The physical controllers, the paths to the drive, can be + * obtained by calling dm_get_associated_descriptors with a drive descriptor and + * a type of DM_PATH. This will only return these physical paths when MPXIO, or + * possibly some future similar feature, is controlling the drive. + * + * Without mpxio the drive does not have a unique public name (in all cases the + * alias(es) of the drive can be determined by calling + * dm_get_associated_descriptors to get the DM_ALIAS descriptors. There will be + * more than one controller returned from dm_get_associated_descriptors when + * called with a type of DM_CONTROLLER. The controllers for each of the aliases + * will be returned in the same order as the aliases descriptors. For example, + * a drive with two paths has the aliases c5t3d2 and c7t1d0. There will be two + * controllers returned; the first corresponds to c5 and the second corresponds + * to c7. + * + * In the multi-path, non-mpxio case the drive has more than one alias. + * Although most of the drive attributes are represented on the drive (see + * dm_get_attributes) there can be some different attributes for the different + * aliases for the drive. Use dm_get_associated_descriptors to get the DM_ALIAS + * descriptors which can then be used to obtain these attributes. Use of this + * algorithm is not restricted to the multi-path, non-mpxio case. For example, + * it can be used to get the target/lun for a SCSI drive with a single path. + */ + +/* * Holds all the data regarding the device. * Private to libdiskmgt. Must use dm_xxx functions to set/get data. */ @@ -50,6 +189,17 @@ typedef enum { DM_WHO_ZPOOL_SPARE } dm_who_type_t; +/* + * The API uses a "descriptor" to identify the managed objects such as drives, + * controllers, media, slices, partitions, paths and buses. The descriptors are + * opaque and are only returned or used as parameters to the other functions in + * the API. The descriptor definition is a typedef to dm_descriptor_t. + * + * Applications call either the dm_get_descriptors or + * dm_get_associated_descriptors function to obtain a list of descriptors of a + * specific type. The application specifies the desired type from the following + * enumeration: + */ typedef enum { DM_DRIVE = 0, DM_CONTROLLER, @@ -61,6 +211,31 @@ typedef enum { DM_BUS } dm_desc_type_t; +/* + * These descriptors are associated with each other in the following way: + * + * alias partition + * _ \ / | + * / \ \ / | + * \ / \ / | + * bus --- controller --- drive --- media | + * | / \ | + * | / \ | + * | / \ | + * path slice + * + * The dm_get_associated_descriptors function can be used get the descriptors + * associated with a given descriptor. The dm_get_associated_types function can + * be used to find the types that can be associated with a given type. + * + * The attributes and values for these objects are described using a list of + * name/value pairs (see libnvpair(3LIB) and the specific comments for each + * function in the API section of this document). + * + * Drives and media have a type which are defined as the following enumerations. + * There could be additional types added to these enumerations as new drive and + * media types are supported by the system. + */ typedef enum { DM_DT_UNKNOWN = 0, @@ -102,6 +277,11 @@ typedef enum { #define DM_FILTER_END -1 +/* + * The dm_get_stats function takes a stat_type argument for the specific sample + * to get for the descriptor. The following enums specify the drive and slice + * stat types. + */ /* drive stat name */ typedef enum { DM_DRV_STAT_PERFORMANCE = 0, @@ -147,6 +327,7 @@ typedef enum { #define DM_PRODUCT_ID "product_id" #define DM_REMOVABLE "removable" /* also in media */ #define DM_RPM "rpm" +#define DM_SOLIDSTATE "solid_state" #define DM_STATUS "status" #define DM_SYNC_SPEED "sync_speed" #define DM_TEMPERATURE "temperature" diff --git a/usr/src/lib/libdladm/common/libdladm.h b/usr/src/lib/libdladm/common/libdladm.h index f0811ae5df..1cfb927a41 100644 --- a/usr/src/lib/libdladm/common/libdladm.h +++ b/usr/src/lib/libdladm/common/libdladm.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent, Inc. All rights reserved. */ #ifndef _LIBDLADM_H @@ -71,6 +72,10 @@ extern "C" { * - DLADM_OPT_BOOT: * Bypass check functions during boot (used by pool property since pools * can come up after link properties are set) + * + * - DLADM_OPT_TRANSIENT: + * Indicates that the link assigned to a zone is transient and will be + * removed when the zone shuts down. */ #define DLADM_OPT_ACTIVE 0x00000001 #define DLADM_OPT_PERSIST 0x00000002 @@ -81,6 +86,7 @@ extern "C" { #define DLADM_OPT_VLAN 0x00000040 #define DLADM_OPT_NOREFRESH 0x00000080 #define DLADM_OPT_BOOT 0x00000100 +#define DLADM_OPT_TRANSIENT 0x00000200 #define DLADM_WALK_TERMINATE 0 #define DLADM_WALK_CONTINUE -1 diff --git a/usr/src/lib/libdladm/common/libdllink.c b/usr/src/lib/libdladm/common/libdllink.c index 8a3c5759ee..303885e929 100644 --- a/usr/src/lib/libdladm/common/libdllink.c +++ b/usr/src/lib/libdladm/common/libdllink.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #include <sys/types.h> @@ -386,10 +387,14 @@ dladm_linkduplex2str(link_duplex_t duplex, char *buf) /* * Case 1: rename an existing link1 to a link2 that does not exist. * Result: <linkid1, link2> + * The zonename parameter is used to allow us to create a VNIC in the global + * zone which is assigned to a non-global zone. Since there is a race condition + * in the create process if two VNICs have the same name, we need to rename it + * after it has been assigned to the zone. */ static dladm_status_t i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1, - const char *link1, const char *link2, uint32_t flags) + const char *link1, const char *link2, uint32_t flags, const char *zonename) { dld_ioc_rename_t dir; dladm_status_t status = DLADM_STATUS_OK; @@ -402,6 +407,10 @@ i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1, dir.dir_linkid1 = linkid1; dir.dir_linkid2 = DATALINK_INVALID_LINKID; (void) strlcpy(dir.dir_link, link2, MAXLINKNAMELEN); + if (zonename != NULL) + dir.dir_zoneinit = B_TRUE; + else + dir.dir_zoneinit = B_FALSE; if (ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir) < 0) { status = dladm_errno2status(errno); @@ -412,6 +421,7 @@ i_dladm_rename_link_c1(dladm_handle_t handle, datalink_id_t linkid1, status = dladm_remap_datalink_id(handle, linkid1, link2); if (status != DLADM_STATUS_OK && (flags & DLADM_OPT_ACTIVE)) { (void) strlcpy(dir.dir_link, link1, MAXLINKNAMELEN); + dir.dir_zoneinit = B_FALSE; (void) ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir); } return (status); @@ -508,6 +518,7 @@ i_dladm_rename_link_c2(dladm_handle_t handle, datalink_id_t linkid1, */ dir.dir_linkid1 = linkid1; dir.dir_linkid2 = linkid2; + dir.dir_zoneinit = B_FALSE; if (ioctl(dladm_dld_fd(handle), DLDIOC_RENAME, &dir) < 0) status = dladm_errno2status(errno); @@ -617,7 +628,8 @@ done: } dladm_status_t -dladm_rename_link(dladm_handle_t handle, const char *link1, const char *link2) +dladm_rename_link(dladm_handle_t handle, const char *zonename, + const char *link1, const char *link2) { datalink_id_t linkid1 = DATALINK_INVALID_LINKID; datalink_id_t linkid2 = DATALINK_INVALID_LINKID; @@ -627,11 +639,11 @@ dladm_rename_link(dladm_handle_t handle, const char *link1, const char *link2) boolean_t remphy2 = B_FALSE; dladm_status_t status; - (void) dladm_name2info(handle, link1, &linkid1, &flags1, &class1, - &media1); - if ((dladm_name2info(handle, link2, &linkid2, &flags2, &class2, - &media2) == DLADM_STATUS_OK) && (class2 == DATALINK_CLASS_PHYS) && - (flags2 == DLADM_OPT_PERSIST)) { + (void) dladm_zname2info(handle, zonename, link1, &linkid1, &flags1, + &class1, &media1); + if ((dladm_zname2info(handle, zonename, link2, &linkid2, &flags2, + &class2, &media2) == DLADM_STATUS_OK) && + (class2 == DATALINK_CLASS_PHYS) && (flags2 == DLADM_OPT_PERSIST)) { /* * see whether link2 is a removed physical link. */ @@ -645,7 +657,7 @@ dladm_rename_link(dladm_handle_t handle, const char *link1, const char *link2) * does not exist. */ status = i_dladm_rename_link_c1(handle, linkid1, link1, - link2, flags1); + link2, flags1, zonename); } else if (remphy2) { /* * case 2: rename an available link to a REMOVED diff --git a/usr/src/lib/libdladm/common/libdllink.h b/usr/src/lib/libdladm/common/libdllink.h index a2830b5e37..a858e78aa3 100644 --- a/usr/src/lib/libdladm/common/libdllink.h +++ b/usr/src/lib/libdladm/common/libdllink.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #ifndef _LIBDLLINK_H @@ -121,7 +122,7 @@ extern dladm_status_t dladm_info(dladm_handle_t, datalink_id_t, dladm_attr_t *); extern dladm_status_t dladm_rename_link(dladm_handle_t, const char *, - const char *); + const char *, const char *); extern dladm_status_t dladm_set_linkprop(dladm_handle_t, datalink_id_t, const char *, char **, uint_t, uint_t); @@ -170,6 +171,9 @@ extern dladm_status_t dladm_up_datalink_id(dladm_handle_t, datalink_id_t); extern dladm_status_t dladm_name2info(dladm_handle_t, const char *, datalink_id_t *, uint32_t *, datalink_class_t *, uint32_t *); +extern dladm_status_t dladm_zname2info(dladm_handle_t, const char *, + const char *, datalink_id_t *, uint32_t *, + datalink_class_t *, uint32_t *); extern dladm_status_t dladm_datalink_id2info(dladm_handle_t, datalink_id_t, uint32_t *, datalink_class_t *, uint32_t *, char *, size_t); diff --git a/usr/src/lib/libdladm/common/libdlmgmt.c b/usr/src/lib/libdladm/common/libdlmgmt.c index 4b0753417c..c9c7906934 100644 --- a/usr/src/lib/libdladm/common/libdlmgmt.c +++ b/usr/src/lib/libdladm/common/libdlmgmt.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #include <door.h> @@ -528,12 +529,24 @@ dladm_getnext_conf_linkprop(dladm_handle_t handle, dladm_conf_t conf, } /* - * Get the link ID that is associated with the given name. + * Get the link ID that is associated with the given name in the current zone. */ dladm_status_t dladm_name2info(dladm_handle_t handle, const char *link, datalink_id_t *linkidp, uint32_t *flagp, datalink_class_t *classp, uint32_t *mediap) { + return (dladm_zname2info(handle, NULL, link, linkidp, flagp, classp, + mediap)); +} + +/* + * Get the link ID that is associated with the given zone/name pair. + */ +dladm_status_t +dladm_zname2info(dladm_handle_t handle, const char *zonename, const char *link, + datalink_id_t *linkidp, uint32_t *flagp, datalink_class_t *classp, + uint32_t *mediap) +{ dlmgmt_door_getlinkid_t getlinkid; dlmgmt_getlinkid_retval_t retval; datalink_id_t linkid; @@ -542,6 +555,10 @@ dladm_name2info(dladm_handle_t handle, const char *link, datalink_id_t *linkidp, getlinkid.ld_cmd = DLMGMT_CMD_GETLINKID; (void) strlcpy(getlinkid.ld_link, link, MAXLINKNAMELEN); + if (zonename != NULL) + getlinkid.ld_zoneid = getzoneidbyname(zonename); + else + getlinkid.ld_zoneid = -1; if ((status = dladm_door_call(handle, &getlinkid, sizeof (getlinkid), &retval, &sz)) != DLADM_STATUS_OK) { diff --git a/usr/src/lib/libdladm/common/libdlvnic.c b/usr/src/lib/libdladm/common/libdlvnic.c index 6dba8d6fad..1a866dcb06 100644 --- a/usr/src/lib/libdladm/common/libdlvnic.c +++ b/usr/src/lib/libdladm/common/libdlvnic.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent Inc. All rights reserved. */ #include <stdio.h> @@ -537,27 +538,35 @@ dladm_vnic_create(dladm_handle_t handle, const char *vnic, datalink_id_t linkid, vnic_created = B_TRUE; /* Save vnic configuration and its properties */ - if (!(flags & DLADM_OPT_PERSIST)) - goto done; + if (flags & DLADM_OPT_PERSIST) { + status = dladm_vnic_persist_conf(handle, name, &attr, class); + if (status == DLADM_STATUS_OK) + conf_set = B_TRUE; + } - status = dladm_vnic_persist_conf(handle, name, &attr, class); - if (status != DLADM_STATUS_OK) - goto done; - conf_set = B_TRUE; +done: + if (status == DLADM_STATUS_OK && proplist != NULL) { + uint32_t flg; + + flg = (flags & DLADM_OPT_PERSIST) ? + DLADM_OPT_PERSIST : DLADM_OPT_ACTIVE; - if (proplist != NULL) { for (i = 0; i < proplist->al_count; i++) { dladm_arg_info_t *aip = &proplist->al_info[i]; + if (strcmp(aip->ai_name, "zone") == 0 && + flags & DLADM_OPT_TRANSIENT) + flg |= DLADM_OPT_TRANSIENT; + else + flg &= ~DLADM_OPT_TRANSIENT; + status = dladm_set_linkprop(handle, vnic_id, - aip->ai_name, aip->ai_val, aip->ai_count, - DLADM_OPT_PERSIST); + aip->ai_name, aip->ai_val, aip->ai_count, flg); if (status != DLADM_STATUS_OK) break; } } -done: if (status != DLADM_STATUS_OK) { if (conf_set) (void) dladm_remove_conf(handle, vnic_id); diff --git a/usr/src/lib/libdladm/common/linkprop.c b/usr/src/lib/libdladm/common/linkprop.c index 229a5fd83f..d46054e686 100644 --- a/usr/src/lib/libdladm/common/linkprop.c +++ b/usr/src/lib/libdladm/common/linkprop.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #include <stdlib.h> @@ -151,11 +152,13 @@ static pd_getf_t get_zone, get_autopush, get_rate_mod, get_rate, get_bridge_pvid, get_protection, get_rxrings, get_txrings, get_cntavail, get_allowedips, get_allowedcids, get_pool, - get_rings_range, get_linkmode_prop; + get_rings_range, get_linkmode_prop, + get_promisc_filtered; static pd_setf_t set_zone, set_rate, set_powermode, set_radio, set_public_prop, set_resource, set_stp_prop, - set_bridge_forward, set_bridge_pvid; + set_bridge_forward, set_bridge_pvid, + set_promisc_filtered; static pd_checkf_t check_zone, check_autopush, check_rate, check_hoplimit, check_encaplim, check_uint32, check_maxbw, check_cpus, @@ -363,6 +366,8 @@ static link_attr_t link_attr[] = { { MAC_PROP_IB_LINKMODE, sizeof (uint32_t), "linkmode"}, + { MAC_PROP_VN_PROMISC_FILTERED, sizeof (boolean_t), "promisc-filtered"}, + { MAC_PROP_PRIVATE, 0, "driver-private"} }; @@ -417,6 +422,11 @@ static val_desc_t link_protect_vals[] = { { "dhcp-nospoof", MPT_DHCPNOSPOOF }, }; +static val_desc_t link_promisc_filtered_vals[] = { + { "off", B_FALSE }, + { "on", B_TRUE }, +}; + static val_desc_t dladm_wlan_radio_vals[] = { { "on", DLADM_WLAN_RADIO_ON }, { "off", DLADM_WLAN_RADIO_OFF } @@ -682,6 +692,12 @@ static prop_desc_t prop_table[] = { set_resource, NULL, get_protection, check_prop, 0, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE }, + { "promisc-filtered", { "on", 1 }, + link_promisc_filtered_vals, VALCNT(link_promisc_filtered_vals), + set_promisc_filtered, NULL, get_promisc_filtered, check_prop, 0, + DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE }, + + { "allowed-ips", { "--", 0 }, NULL, 0, set_resource, NULL, get_allowedips, check_allowedips, PD_CHECK_ALLOC, @@ -1513,6 +1529,9 @@ set_zone(dladm_handle_t handle, prop_desc_t *pdp, datalink_id_t linkid, if (zid_new == zid_old) return (DLADM_STATUS_OK); + if (flags & DLADM_OPT_TRANSIENT) + dzp->diz_transient = B_TRUE; + if ((status = set_public_prop(handle, pdp, linkid, vdp, val_cnt, flags, media)) != DLADM_STATUS_OK) return (status); @@ -4583,3 +4602,50 @@ get_linkmode_prop(dladm_handle_t handle, prop_desc_t *pdp, *val_cnt = 1; return (DLADM_STATUS_OK); } + +/*ARGSUSED*/ +static dladm_status_t +get_promisc_filtered(dladm_handle_t handle, prop_desc_t *pdp, + datalink_id_t linkid, char **prop_val, uint_t *val_cnt, + datalink_media_t media, uint_t flags, uint_t *perm_flags) +{ + char *s; + dladm_status_t status; + boolean_t filt; + + status = i_dladm_get_public_prop(handle, linkid, pdp->pd_name, flags, + perm_flags, &filt, sizeof (filt)); + if (status != DLADM_STATUS_OK) + return (status); + + if (filt != 0) + s = link_promisc_filtered_vals[1].vd_name; + else + s = link_promisc_filtered_vals[0].vd_name; + (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s", s); + + *val_cnt = 1; + return (DLADM_STATUS_OK); +} + +/* ARGSUSED */ +static dladm_status_t +set_promisc_filtered(dladm_handle_t handle, prop_desc_t *pdp, + datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt, uint_t flags, + datalink_media_t media) +{ + dld_ioc_macprop_t *dip; + dladm_status_t status = DLADM_STATUS_OK; + + dip = i_dladm_buf_alloc_by_name(0, linkid, pdp->pd_name, + 0, &status); + + if (dip == NULL) + return (status); + + (void) memcpy(dip->pr_val, &vdp->vd_val, dip->pr_valsize); + status = i_dladm_macprop(handle, dip, B_TRUE); + + free(dip); + return (status); +} diff --git a/usr/src/lib/libdladm/common/mapfile-vers b/usr/src/lib/libdladm/common/mapfile-vers index b781c93aff..3eaeea656e 100644 --- a/usr/src/lib/libdladm/common/mapfile-vers +++ b/usr/src/lib/libdladm/common/mapfile-vers @@ -20,6 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, Joyent Inc. All rights reserved. # # @@ -134,6 +135,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { dladm_remap_datalink_id; dladm_up_datalink_id; dladm_name2info; + dladm_zname2info; dladm_datalink_id2info; dladm_walk_datalink_id; dladm_create_conf; diff --git a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java index 366d83476b..6983e279fa 100644 --- a/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java +++ b/usr/src/lib/libdns_sd/java/com/apple/dnssd/DNSSDRecordRegistrar.java @@ -5,9 +5,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,9 +25,6 @@ Re-licensed mDNSResponder daemon source code under Apache License, Version 2.0 Revision 1.1 2006/06/20 23:00:12 rpantos <rdar://problem/3839132> Java needs to implement DNSServiceRegisterRecord equivalent - -ident "%Z%%M% %I% %E% SMI" - */ @@ -38,7 +35,7 @@ package com.apple.dnssd; public interface DNSSDRecordRegistrar extends DNSSDService { - /** Register an independent {@link DNSRecord}.<P> + /** Register an independent {@link DNSRecord}.<P> @param flags Possible values are SHARED or UNIQUE (see flag type definitions for details). <P> @@ -55,25 +52,22 @@ public interface DNSSDRecordRegistrar extends DNSSDService as defined in nameser.h. <P> @param rrclass - The class of the resource record, as defined in nameser.h + The class of the resource record, as defined in nameser.h (usually 1 for the Internet class). <P> - @param rData + @param rdata The new rdata as it is to appear in the DNS record. <P> @param ttl The time to live of the resource record, in seconds. Pass 0 to use a default value. <P> - @param listener - This object will get called when the service is registered. - <P> @return A {@link DNSSDService} that can be used to abort the record registration. @throws SecurityException If a security manager is present and denies <tt>RuntimePermission("getDNSSDInstance")</tt>. @see RuntimePermission */ - public DNSRecord registerRecord( int flags, int ifIndex, String fullname, int rrtype, + public DNSRecord registerRecord( int flags, int ifIndex, String fullname, int rrtype, int rrclass, byte[] rdata, int ttl) throws DNSSDException; -} +} diff --git a/usr/src/lib/libdtrace/Makefile.com b/usr/src/lib/libdtrace/Makefile.com index 8952f8db06..d92d33dff7 100644 --- a/usr/src/lib/libdtrace/Makefile.com +++ b/usr/src/lib/libdtrace/Makefile.com @@ -131,7 +131,7 @@ CERRWARN += -_gcc=-Wno-uninitialized CERRWARN += -_gcc=-Wno-switch YYCFLAGS = -LDLIBS += -lgen -lproc -lrtld_db -lnsl -lsocket -lctf -lelf -lc +LDLIBS += -lgen -lproc -lrtld_db -lnsl -lsocket -lctf -lelf -lc -lzonecfg DRTILDLIBS = $(LDLIBS.lib) -lc yydebug := YYCFLAGS += -DYYDEBUG diff --git a/usr/src/lib/libdtrace/common/dt_cc.c b/usr/src/lib/libdtrace/common/dt_cc.c index 9661ad9d0b..f4b0509b4a 100644 --- a/usr/src/lib/libdtrace/common/dt_cc.c +++ b/usr/src/lib/libdtrace/common/dt_cc.c @@ -2149,7 +2149,7 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path) (void) snprintf(fname, sizeof (fname), "%s/%s", path, dp->d_name); - if ((fp = fopen(fname, "r")) == NULL) { + if ((fp = fopen(fname, "rF")) == NULL) { dt_dprintf("skipping library %s: %s\n", fname, strerror(errno)); continue; @@ -2171,12 +2171,15 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path) dt_dprintf("skipping library %s, already processed " "library with the same name: %s", dp->d_name, dld->dtld_library); + (void) fclose(fp); continue; } dtp->dt_filetag = fname; - if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0) + if (dt_lib_depend_add(dtp, &dtp->dt_lib_dep, fname) != 0) { + (void) fclose(fp); return (-1); /* preserve dt_errno */ + } rv = dt_compile(dtp, DT_CTX_DPROG, DTRACE_PROBESPEC_NAME, NULL, @@ -2184,8 +2187,10 @@ dt_load_libs_dir(dtrace_hdl_t *dtp, const char *path) if (rv != NULL && dtp->dt_errno && (dtp->dt_errno != EDT_COMPILER || - dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND))) + dtp->dt_errtag != dt_errtag(D_PRAGMA_DEPEND))) { + (void) fclose(fp); return (-1); /* preserve dt_errno */ + } if (dtp->dt_errno) dt_dprintf("error parsing library %s: %s\n", diff --git a/usr/src/lib/libdtrace/common/dt_cg.c b/usr/src/lib/libdtrace/common/dt_cg.c index 3103106d27..28db9b2262 100644 --- a/usr/src/lib/libdtrace/common/dt_cg.c +++ b/usr/src/lib/libdtrace/common/dt_cg.c @@ -476,7 +476,7 @@ dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst, if (!dt_node_is_scalar(dst)) return; /* not a scalar */ if (dstsize == srcsize && - ((src->dn_flags ^ dst->dn_flags) & DT_NF_SIGNED) != 0) + ((src->dn_flags ^ dst->dn_flags) & DT_NF_SIGNED) == 0) return; /* not narrowing or changing signed-ness */ if (dstsize > srcsize && (src->dn_flags & DT_NF_SIGNED) == 0) return; /* nothing to do in this case */ diff --git a/usr/src/lib/libdtrace/common/dt_dof.c b/usr/src/lib/libdtrace/common/dt_dof.c index 04c4c89cdb..c1f5dc827e 100644 --- a/usr/src/lib/libdtrace/common/dt_dof.c +++ b/usr/src/lib/libdtrace/common/dt_dof.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -482,7 +483,7 @@ dof_add_probe(dt_idhash_t *dhp, dt_ident_t *idp, void *data) return (0); } -static void +static int dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp) { dtrace_hdl_t *dtp = ddo->ddo_hdl; @@ -493,8 +494,12 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp) size_t sz; id_t i; - if (pvp->pv_flags & DT_PROVIDER_IMPL) - return; /* ignore providers that are exported by dtrace(7D) */ + if (pvp->pv_flags & DT_PROVIDER_IMPL) { + /* + * ignore providers that are exported by dtrace(7D) + */ + return (0); + } nxr = dt_popcb(pvp->pv_xrefs, pvp->pv_xrmax); dofs = alloca(sizeof (dof_secidx_t) * (nxr + 1)); @@ -521,6 +526,9 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp) (void) dt_idhash_iter(pvp->pv_probes, dof_add_probe, ddo); + if (dt_buf_len(&ddo->ddo_probes) == 0) + return (dt_set_errno(dtp, EDT_NOPROBES)); + dofpv.dofpv_probes = dof_add_lsect(ddo, NULL, DOF_SECT_PROBES, sizeof (uint64_t), 0, sizeof (dof_probe_t), dt_buf_len(&ddo->ddo_probes)); @@ -575,6 +583,8 @@ dof_add_provider(dt_dof_t *ddo, const dt_provider_t *pvp) sizeof (dof_secidx_t), 0, sizeof (dof_secidx_t), sizeof (dof_secidx_t) * (nxr + 1)); } + + return (0); } static int @@ -818,8 +828,10 @@ dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags) */ if (flags & DTRACE_D_PROBES) { for (pvp = dt_list_next(&dtp->dt_provlist); - pvp != NULL; pvp = dt_list_next(pvp)) - dof_add_provider(ddo, pvp); + pvp != NULL; pvp = dt_list_next(pvp)) { + if (dof_add_provider(ddo, pvp) != 0) + return (NULL); + } } /* diff --git a/usr/src/lib/libdtrace/common/dt_error.c b/usr/src/lib/libdtrace/common/dt_error.c index 9c1cbd73bc..f7ad28ebae 100644 --- a/usr/src/lib/libdtrace/common/dt_error.c +++ b/usr/src/lib/libdtrace/common/dt_error.c @@ -26,6 +26,7 @@ /* * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include <strings.h> @@ -108,7 +109,8 @@ static const struct { { EDT_BADSTACKPC, "Invalid stack program counter size" }, { EDT_BADAGGVAR, "Invalid aggregation variable identifier" }, { EDT_OVERSION, "Client requested deprecated version of library" }, - { EDT_ENABLING_ERR, "Failed to enable probe" } + { EDT_ENABLING_ERR, "Failed to enable probe" }, + { EDT_NOPROBES, "No probe sites found for declared provider" } }; static const int _dt_nerr = sizeof (_dt_errlist) / sizeof (_dt_errlist[0]); diff --git a/usr/src/lib/libdtrace/common/dt_impl.h b/usr/src/lib/libdtrace/common/dt_impl.h index fa4c66540d..6420524701 100644 --- a/usr/src/lib/libdtrace/common/dt_impl.h +++ b/usr/src/lib/libdtrace/common/dt_impl.h @@ -25,7 +25,7 @@ */ /* - * Copyright (c) 2011, Joyent, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. */ @@ -260,6 +260,7 @@ struct dtrace_hdl { uint_t dt_droptags; /* boolean: set via -xdroptags */ uint_t dt_active; /* boolean: set once tracing is active */ uint_t dt_stopped; /* boolean: set once tracing is stopped */ + uint_t dt_optset; /* boolean: set once options have been set */ processorid_t dt_beganon; /* CPU that executed BEGIN probe (if any) */ processorid_t dt_endedon; /* CPU that executed END probe (if any) */ uint_t dt_oflags; /* dtrace open-time options (see dtrace.h) */ @@ -512,7 +513,8 @@ enum { EDT_BADSTACKPC, /* invalid stack program counter size */ EDT_BADAGGVAR, /* invalid aggregation variable identifier */ EDT_OVERSION, /* client is requesting deprecated version */ - EDT_ENABLING_ERR /* failed to enable probe */ + EDT_ENABLING_ERR, /* failed to enable probe */ + EDT_NOPROBES /* no probes sites for declared provider */ }; /* diff --git a/usr/src/lib/libdtrace/common/dt_open.c b/usr/src/lib/libdtrace/common/dt_open.c index dd83370ee8..af3bc17b2c 100644 --- a/usr/src/lib/libdtrace/common/dt_open.c +++ b/usr/src/lib/libdtrace/common/dt_open.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, Joyent, Inc. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. */ @@ -110,9 +110,10 @@ #define DT_VERS_1_8 DT_VERSION_NUMBER(1, 8, 0) #define DT_VERS_1_8_1 DT_VERSION_NUMBER(1, 8, 1) #define DT_VERS_1_9 DT_VERSION_NUMBER(1, 9, 0) -#define DT_VERS_1_9_1 DT_VERSION_NUMBER(1, 9, 1) -#define DT_VERS_LATEST DT_VERS_1_9_1 -#define DT_VERS_STRING "Sun D 1.9.1" +#define DT_VERS_1_10 DT_VERSION_NUMBER(1, 10, 0) +#define DT_VERS_1_11 DT_VERSION_NUMBER(1, 11, 0) +#define DT_VERS_LATEST DT_VERS_1_11 +#define DT_VERS_STRING "Sun D 1.11" const dt_version_t _dtrace_versions[] = { DT_VERS_1_0, /* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */ @@ -133,7 +134,8 @@ const dt_version_t _dtrace_versions[] = { DT_VERS_1_8, /* D API 1.8 */ DT_VERS_1_8_1, /* D API 1.8.1 */ DT_VERS_1_9, /* D API 1.9 */ - DT_VERS_1_9_1, /* D API 1.9.1 */ + DT_VERS_1_10, /* D API 1.10 */ + DT_VERS_1_11, /* D API 1.11 */ 0 }; @@ -247,6 +249,8 @@ static const dt_ident_t _dtrace_globals[] = { &dt_idops_func, "uint64_t(uint64_t)" }, { "htons", DT_IDENT_FUNC, 0, DIF_SUBR_HTONS, DT_ATTR_EVOLCMN, DT_VERS_1_3, &dt_idops_func, "uint16_t(uint16_t)" }, +{ "getf", DT_IDENT_FUNC, 0, DIF_SUBR_GETF, DT_ATTR_STABCMN, DT_VERS_1_10, + &dt_idops_func, "file_t *(int)" }, { "gid", DT_IDENT_SCALAR, 0, DIF_VAR_GID, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "gid_t" }, { "id", DT_IDENT_SCALAR, 0, DIF_VAR_ID, DT_ATTR_STABCMN, DT_VERS_1_0, @@ -261,6 +265,8 @@ static const dt_ident_t _dtrace_globals[] = { DT_VERS_1_5, &dt_idops_func, "string(int, void *)" }, { "ipl", DT_IDENT_SCALAR, 0, DIF_VAR_IPL, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_type, "uint_t" }, +{ "json", DT_IDENT_FUNC, 0, DIF_SUBR_JSON, DT_ATTR_STABCMN, DT_VERS_1_11, + &dt_idops_func, "string(const char *, const char *)" }, { "jstack", DT_IDENT_ACTFUNC, 0, DT_ACT_JSTACK, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_func, "stack(...)" }, { "lltostr", DT_IDENT_FUNC, 0, DIF_SUBR_LLTOSTR, DT_ATTR_STABCMN, DT_VERS_1_0, @@ -375,6 +381,8 @@ static const dt_ident_t _dtrace_globals[] = { &dt_idops_func, "string(const char *, const char *)" }, { "strtok", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOK, DT_ATTR_STABCMN, DT_VERS_1_1, &dt_idops_func, "string(const char *, const char *)" }, +{ "strtoll", DT_IDENT_FUNC, 0, DIF_SUBR_STRTOLL, DT_ATTR_STABCMN, DT_VERS_1_11, + &dt_idops_func, "int64_t(const char *, [int])" }, { "substr", DT_IDENT_FUNC, 0, DIF_SUBR_SUBSTR, DT_ATTR_STABCMN, DT_VERS_1_1, &dt_idops_func, "string(const char *, int, [int])" }, { "sum", DT_IDENT_AGGFUNC, 0, DTRACEAGG_SUM, DT_ATTR_STABCMN, DT_VERS_1_0, diff --git a/usr/src/lib/libdtrace/common/dt_options.c b/usr/src/lib/libdtrace/common/dt_options.c index cc3ae7b9d3..71bd508ecd 100644 --- a/usr/src/lib/libdtrace/common/dt_options.c +++ b/usr/src/lib/libdtrace/common/dt_options.c @@ -25,6 +25,7 @@ */ /* + * Copyright (c) 2011, Joyent, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. */ @@ -40,6 +41,8 @@ #include <alloca.h> #include <errno.h> #include <fcntl.h> +#include <zone.h> +#include <libzonecfg.h> #include <dt_impl.h> #include <dt_string.h> @@ -836,6 +839,44 @@ dt_opt_bufresize(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) return (0); } +/*ARGSUSED*/ +static int +dt_opt_zone(dtrace_hdl_t *dtp, const char *arg, uintptr_t option) +{ + zoneid_t z, did; + + if (arg == NULL) + return (dt_set_errno(dtp, EDT_BADOPTVAL)); + + /* + * If the specified zone is currently running, we'll query the kernel + * for its debugger ID. If it doesn't appear to be running, we'll look + * for it for among all installed zones (thereby allowing a zdefs + * enabling against a halted zone). + */ + if ((z = getzoneidbyname(arg)) != -1) { + if (zone_getattr(z, ZONE_ATTR_DID, &did, sizeof (did)) < 0) + return (dt_set_errno(dtp, EDT_BADOPTVAL)); + } else { + zone_dochandle_t handle; + + if ((handle = zonecfg_init_handle()) == NULL) + return (dt_set_errno(dtp, errno)); + + if (zonecfg_get_handle(arg, handle) != Z_OK) { + zonecfg_fini_handle(handle); + return (dt_set_errno(dtp, EDT_BADOPTVAL)); + } + + did = zonecfg_get_did(handle); + zonecfg_fini_handle(handle); + } + + dtp->dt_options[DTRACEOPT_ZONE] = did; + + return (0); +} + int dt_options_load(dtrace_hdl_t *dtp) { @@ -969,6 +1010,7 @@ static const dt_option_t _dtrace_rtoptions[] = { { "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE }, { "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE }, { "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES }, + { "zone", dt_opt_zone, DTRACEOPT_ZONE }, { "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL }, { NULL } }; @@ -1046,9 +1088,41 @@ dtrace_setopt(dtrace_hdl_t *dtp, const char *opt, const char *val) if (dtp->dt_active) return (dt_set_errno(dtp, EDT_ACTIVE)); + /* + * If our options had been previously ioctl'd down, + * clear dt_optset to indicate that a run-time option + * has since been set. + */ + dtp->dt_optset = B_FALSE; + return (op->o_func(dtp, val, op->o_option)); } } return (dt_set_errno(dtp, EDT_BADOPTNAME)); } + +int +dtrace_setopts(dtrace_hdl_t *dtp) +{ + void *dof; + int err; + + if (dtp->dt_optset) + return (0); + + if ((dof = dtrace_getopt_dof(dtp)) == NULL) + return (-1); /* dt_errno has been set for us */ + + if ((err = dt_ioctl(dtp, DTRACEIOC_ENABLE, dof)) == -1) + (void) dt_set_errno(dtp, errno); + + dtrace_dof_destroy(dtp, dof); + + if (err == -1) + return (-1); + + dtp->dt_optset = B_TRUE; + + return (0); +} diff --git a/usr/src/lib/libdtrace/common/dt_program.c b/usr/src/lib/libdtrace/common/dt_program.c index 7d725bd0af..e4f9d8dd1c 100644 --- a/usr/src/lib/libdtrace/common/dt_program.c +++ b/usr/src/lib/libdtrace/common/dt_program.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Joyent, Inc. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved. */ @@ -154,6 +155,14 @@ dtrace_program_exec(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, void *dof; int n, err; + /* + * If we have not yet ioctl'd down our options DOF, we'll do that + * before enabling any probes (some options will affect which probes + * we match). + */ + if (dtrace_setopts(dtp) != 0) + return (-1); + dtrace_program_info(dtp, pgp, pip); if ((dof = dtrace_dof_create(dtp, pgp, DTRACE_D_STRIP)) == NULL) diff --git a/usr/src/lib/libdtrace/common/dt_work.c b/usr/src/lib/libdtrace/common/dt_work.c index 97a7f62d69..c330394027 100644 --- a/usr/src/lib/libdtrace/common/dt_work.c +++ b/usr/src/lib/libdtrace/common/dt_work.c @@ -25,7 +25,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2011, Joyent, Inc. All rights reserved. + */ #include <dt_impl.h> #include <stddef.h> @@ -164,13 +166,22 @@ dtrace_status(dtrace_hdl_t *dtp) int dtrace_go(dtrace_hdl_t *dtp) { - void *dof; - int err; - if (dtp->dt_active) return (dt_set_errno(dtp, EINVAL)); /* + * In most cases, we will have already ioctl'd down our options DOF + * by this point -- but if a libdtrace does a dtrace_setopt() after + * calling dtrace_program_exec() but before calling dtrace_go(), + * dt_optset will be cleared and we need to ioctl down the options + * DOF now. + */ + if (dtrace_setopts(dtp) != 0 && + (dtp->dt_errno != ENOTTY || dtp->dt_vector == NULL)) { + return (-1); + } + + /* * If a dtrace:::ERROR program and callback are registered, enable the * program before we start tracing. If this fails for a vector open * with ENOTTY, we permit dtrace_go() to succeed so that vector clients @@ -178,19 +189,10 @@ dtrace_go(dtrace_hdl_t *dtp) * though they do not provide support for the DTRACEIOC_ENABLE ioctl. */ if (dtp->dt_errprog != NULL && - dtrace_program_exec(dtp, dtp->dt_errprog, NULL) == -1 && ( - dtp->dt_errno != ENOTTY || dtp->dt_vector == NULL)) - return (-1); /* dt_errno has been set for us */ - - if ((dof = dtrace_getopt_dof(dtp)) == NULL) + dtrace_program_exec(dtp, dtp->dt_errprog, NULL) == -1 && + (dtp->dt_errno != ENOTTY || dtp->dt_vector == NULL)) return (-1); /* dt_errno has been set for us */ - err = dt_ioctl(dtp, DTRACEIOC_ENABLE, dof); - dtrace_dof_destroy(dtp, dof); - - if (err == -1 && (errno != ENOTTY || dtp->dt_vector == NULL)) - return (dt_set_errno(dtp, errno)); - if (dt_ioctl(dtp, DTRACEIOC_GO, &dtp->dt_beganon) == -1) { if (errno == EACCES) return (dt_set_errno(dtp, EDT_DESTRUCTIVE)); diff --git a/usr/src/lib/libdtrace/common/dtrace.h b/usr/src/lib/libdtrace/common/dtrace.h index 87df1ca440..d3031d8c4c 100644 --- a/usr/src/lib/libdtrace/common/dtrace.h +++ b/usr/src/lib/libdtrace/common/dtrace.h @@ -81,6 +81,7 @@ extern const char *dtrace_subrstr(dtrace_hdl_t *, int); extern int dtrace_setopt(dtrace_hdl_t *, const char *, const char *); extern int dtrace_getopt(dtrace_hdl_t *, const char *, dtrace_optval_t *); +extern int dtrace_setopts(dtrace_hdl_t *); extern void dtrace_update(dtrace_hdl_t *); extern int dtrace_ctlfd(dtrace_hdl_t *); diff --git a/usr/src/lib/libdtrace/common/io.d.in b/usr/src/lib/libdtrace/common/io.d.in index cb1e32cffe..5f676b9546 100644 --- a/usr/src/lib/libdtrace/common/io.d.in +++ b/usr/src/lib/libdtrace/common/io.d.in @@ -23,7 +23,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ #pragma D depends_on module unix #pragma D depends_on provider io @@ -197,9 +199,7 @@ translator fileinfo_t < struct file *F > { fi_oflags = F == NULL ? 0 : F->f_flag + (int)@FOPEN@; }; -inline fileinfo_t fds[int fd] = xlate <fileinfo_t> ( - fd >= 0 && fd < curthread->t_procp->p_user.u_finfo.fi_nfiles ? - curthread->t_procp->p_user.u_finfo.fi_list[fd].uf_file : NULL); +inline fileinfo_t fds[int fd] = xlate <fileinfo_t> (getf(fd)); #pragma D attributes Stable/Stable/Common fds #pragma D binding "1.1" fds diff --git a/usr/src/lib/libgrubmgmt/common/libgrub_fs.c b/usr/src/lib/libgrubmgmt/common/libgrub_fs.c index 28a47deabb..ff2884b6b3 100644 --- a/usr/src/lib/libgrubmgmt/common/libgrub_fs.c +++ b/usr/src/lib/libgrubmgmt/common/libgrub_fs.c @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2011 Joyent, Inc. All rights reserved. */ /* * Copyright 2013 Nexenta Systems, Inc. All rights reserved. @@ -161,7 +163,8 @@ get_zfs_root(zfs_handle_t *zfh, grub_fs_t *fs, grub_root_t *root) sizeof (root->gr_physpath))) == 0 && (ret = zpool_get_prop(zph, ZPOOL_PROP_BOOTFS, root->gr_fs[GRBM_ZFS_BOOTFS].gfs_dev, - sizeof (root->gr_fs[GRBM_ZFS_BOOTFS].gfs_dev), NULL)) == 0) { + sizeof (root->gr_fs[GRBM_ZFS_BOOTFS].gfs_dev), NULL, + B_FALSE)) == 0) { (void) strlcpy(root->gr_fs[GRBM_ZFS_TOPFS].gfs_dev, name, sizeof (root->gr_fs[GRBM_ZFS_TOPFS].gfs_dev)); diff --git a/usr/src/lib/libipd/Makefile b/usr/src/lib/libipd/Makefile new file mode 100644 index 0000000000..feab972218 --- /dev/null +++ b/usr/src/lib/libipd/Makefile @@ -0,0 +1,42 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2012 Joyent, Inc. All rights reserved. +# + +include ../Makefile.lib + +HDRS = libipd.h +HDRDIR = common +SUBDIRS = $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +all clean clobber install lint: $(SUBDIRS) + +install_h: $(ROOTHDRS) + +check: $(CHECKHDRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +FRC: + +include ../Makefile.targ diff --git a/usr/src/lib/libipd/Makefile.com b/usr/src/lib/libipd/Makefile.com new file mode 100644 index 0000000000..f118aa6cc3 --- /dev/null +++ b/usr/src/lib/libipd/Makefile.com @@ -0,0 +1,36 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2012 Joyent, Inc. All rights reserved. +# + +include ../../Makefile.lib + +LIBRARY = libipd.a +VERS = .1 +OBJECTS = libipd.o + +include ../../Makefile.lib + +LIBS = $(DYNLIB) $(LINTLIB) +LDLIBS += -lc +CPPFLAGS += -I../common + +SRCDIR = ../common + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include ../../Makefile.targ diff --git a/usr/src/lib/libipd/amd64/Makefile b/usr/src/lib/libipd/amd64/Makefile new file mode 100644 index 0000000000..0ff7206916 --- /dev/null +++ b/usr/src/lib/libipd/amd64/Makefile @@ -0,0 +1,19 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2012 Joyent, Inc. All rights reserved. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/libipd/common/libipd.c b/usr/src/lib/libipd/common/libipd.c new file mode 100644 index 0000000000..c580fdf61e --- /dev/null +++ b/usr/src/lib/libipd/common/libipd.c @@ -0,0 +1,303 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdarg.h> + +#include <libipd.h> +#include <sys/ipd.h> + +__thread ipd_errno_t ipd_errno = 0; +__thread char ipd_errmsg[512]; + +struct ipd_stat { + uint_t is_nzones; + zoneid_t *is_zoneids; + struct ipd_config *is_configs; +}; + +static ipd_errno_t +xlate_errno(int e) +{ + switch (e) { + case 0: + return (EIPD_NOERROR); + case ENOMEM: + case EAGAIN: + return (EIPD_NOMEM); + case ERANGE: + return (EIPD_RANGE); + case EPERM: + return (EIPD_PERM); + case EFAULT: + return (EIPD_FAULT); + case ENOTTY: + return (EIPD_INTERNAL); + default: + return (EIPD_UNKNOWN); + } +} + +const char * +ipd_strerror(ipd_errno_t e) +{ + switch (e) { + case EIPD_NOERROR: + return ("no error"); + case EIPD_NOMEM: + return ("out of memory"); + case EIPD_ZC_NOENT: + return ("zone does not exist or is not using ipd"); + case EIPD_RANGE: + return ("argument out of range"); + case EIPD_PERM: + return ("permission denied"); + case EIPD_FAULT: + return ("bad pointer"); + case EIPD_INTERNAL: + return ("internal library error"); + case EIPD_UNKNOWN: + default: + return ("unknown error"); + } +} + +static int +ipd_set_errno(ipd_errno_t e, const char *fmt, ...) +{ + va_list ap; + + ipd_errno = e; + if (fmt != NULL) { + va_start(ap, fmt); + (void) vsnprintf(ipd_errmsg, sizeof (ipd_errmsg), fmt, ap); + va_end(ap); + } else { + (void) strlcpy(ipd_errmsg, + ipd_strerror(e), sizeof (ipd_errmsg)); + } + + return (-1); +} + +int +ipd_open(const char *path) +{ + int fd; + + if (path == NULL) + path = IPD_DEV_PATH; + + fd = open(path, O_RDWR); + if (fd < 0) { + return (ipd_set_errno(xlate_errno(errno), + "unable to open %s: %s", path, strerror(errno))); + } + + return (fd); +} + +int +ipd_close(int fd) +{ + (void) close(fd); + return (0); +} + +int +ipd_status_read(int fd, ipd_stathdl_t *ispp) +{ + struct ipd_stat *isp = NULL; + ipd_ioc_list_t ipil; + uint_t rzones; + uint_t i; + + bzero(&ipil, sizeof (ipil)); + if (ioctl(fd, IPDIOC_LIST, &ipil) != 0) { + return (ipd_set_errno(xlate_errno(errno), + "unable to retrieve ipd zone list: %s", strerror(errno))); + } + + for (;;) { + if ((rzones = ipil.ipil_nzones) == 0) + break; + + ipil.ipil_info = + malloc(sizeof (ipd_ioc_info_t) * ipil.ipil_nzones); + if (ipil.ipil_info == NULL) + return (ipd_set_errno(EIPD_NOMEM, NULL)); + + if (ioctl(fd, IPDIOC_LIST, &ipil) != 0) { + free(ipil.ipil_info); + return (ipd_set_errno(xlate_errno(errno), + "unable to retrieve ipd zone list: %s", + strerror(errno))); + } + + if (ipil.ipil_nzones <= rzones) + break; + + free(ipil.ipil_info); + } + + if ((isp = malloc(sizeof (struct ipd_stat))) == NULL) { + free(ipil.ipil_info); + return (ipd_set_errno(EIPD_NOMEM, NULL)); + } + + isp->is_nzones = ipil.ipil_nzones; + + if (isp->is_nzones == 0) { + isp->is_zoneids = NULL; + isp->is_configs = NULL; + *ispp = isp; + return (0); + } + + isp->is_zoneids = malloc(sizeof (zoneid_t) * ipil.ipil_nzones); + if (isp->is_zoneids == NULL) { + free(ipil.ipil_info); + free(isp); + return (ipd_set_errno(EIPD_NOMEM, NULL)); + } + isp->is_configs = malloc(sizeof (struct ipd_config) * ipil.ipil_nzones); + if (isp->is_configs == NULL) { + free(ipil.ipil_info); + free(isp->is_zoneids); + free(isp); + return (ipd_set_errno(EIPD_NOMEM, NULL)); + } + + for (i = 0; i < isp->is_nzones; i++) { + isp->is_zoneids[i] = ipil.ipil_info[i].ipii_zoneid; + + isp->is_configs[i].ic_corrupt = ipil.ipil_info[i].ipii_corrupt; + isp->is_configs[i].ic_drop = ipil.ipil_info[i].ipii_drop; + isp->is_configs[i].ic_delay = ipil.ipil_info[i].ipii_delay; + + isp->is_configs[i].ic_mask = + ((!!isp->is_configs[i].ic_corrupt) * IPDM_CORRUPT) | + ((!!isp->is_configs[i].ic_drop) * IPDM_DROP) | + ((!!isp->is_configs[i].ic_delay) * IPDM_DELAY); + } + + *ispp = isp; + return (0); +} + +void +ipd_status_foreach_zone(const ipd_stathdl_t hdl, ipd_status_cb_f f, void *arg) +{ + const struct ipd_stat *isp = hdl; + uint_t i; + + for (i = 0; i < isp->is_nzones; i++) + f(isp->is_zoneids[i], &isp->is_configs[i], arg); +} + +int +ipd_status_get_config(const ipd_stathdl_t hdl, zoneid_t z, ipd_config_t **icpp) +{ + const struct ipd_stat *isp = hdl; + uint_t i; + + for (i = 0; i < isp->is_nzones; i++) { + if (isp->is_zoneids[i] == z) { + *icpp = &isp->is_configs[i]; + return (0); + } + } + + return (ipd_set_errno(EIPD_ZC_NOENT, + "zone %d does not exist or has no ipd configuration", z)); +} + +void +ipd_status_free(ipd_stathdl_t hdl) +{ + struct ipd_stat *isp = hdl; + + if (isp != NULL) { + free(isp->is_zoneids); + free(isp->is_configs); + } + free(isp); +} + +int +ipd_ctl(int fd, zoneid_t z, const ipd_config_t *icp) +{ + ipd_ioc_perturb_t ipip; + + bzero(&ipip, sizeof (ipd_ioc_perturb_t)); + ipip.ipip_zoneid = z; + + if (icp->ic_mask & IPDM_CORRUPT) { + if (icp->ic_corrupt == 0) + ipip.ipip_arg |= IPD_CORRUPT; + } + if (icp->ic_mask & IPDM_DELAY) { + if (icp->ic_delay == 0) + ipip.ipip_arg |= IPD_DELAY; + } + if (icp->ic_mask & IPDM_DROP) { + if (icp->ic_drop == 0) + ipip.ipip_arg |= IPD_DROP; + } + + if (ipip.ipip_arg != 0 && ioctl(fd, IPDIOC_REMOVE, &ipip) != 0) { + return (ipd_set_errno(xlate_errno(errno), + "unable to remove cleared ipd settings: %s", + strerror(errno))); + } + + if ((icp->ic_mask & IPDM_CORRUPT) && icp->ic_corrupt != 0) { + ipip.ipip_zoneid = z; + ipip.ipip_arg = icp->ic_corrupt; + if (ioctl(fd, IPDIOC_CORRUPT, &ipip) != 0) { + return (ipd_set_errno(xlate_errno(errno), + "unable to set corruption rate to %d: %s", + ipip.ipip_arg, strerror(errno))); + } + } + if ((icp->ic_mask & IPDM_DELAY) && icp->ic_delay != 0) { + ipip.ipip_zoneid = z; + ipip.ipip_arg = icp->ic_delay; + if (ioctl(fd, IPDIOC_DELAY, &ipip) != 0) { + return (ipd_set_errno(xlate_errno(errno), + "unable to set delay time to %d: %s", + ipip.ipip_arg, strerror(errno))); + } + } + if ((icp->ic_mask & IPDM_DROP) && icp->ic_drop != 0) { + ipip.ipip_zoneid = z; + ipip.ipip_arg = icp->ic_drop; + if (ioctl(fd, IPDIOC_DROP, &ipip) != 0) { + return (ipd_set_errno(xlate_errno(errno), + "unable to set drop probability to %d: %s", + ipip.ipip_arg, strerror(errno))); + } + } + + return (0); +} diff --git a/usr/src/lib/libipd/common/libipd.h b/usr/src/lib/libipd/common/libipd.h new file mode 100644 index 0000000000..ebf56aea1e --- /dev/null +++ b/usr/src/lib/libipd/common/libipd.h @@ -0,0 +1,74 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _LIBIPD_H +#define _LIBIPD_H + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Bitmask values for ic_mask. + */ +#define IPDM_CORRUPT 0x1000 +#define IPDM_DELAY 0x2000 +#define IPDM_DROP 0x4000 + +typedef enum ipd_errno { + EIPD_NOERROR = 0, + EIPD_NOMEM, + EIPD_ZC_NOENT, + EIPD_RANGE, + EIPD_PERM, + EIPD_FAULT, + EIPD_INTERNAL, + EIPD_UNKNOWN +} ipd_errno_t; + +typedef struct ipd_config { + uint32_t ic_mask; + uint32_t ic_corrupt; + uint32_t ic_drop; + uint32_t ic_delay; +} ipd_config_t; + +struct ipd_stat; +typedef struct ipd_stat *ipd_stathdl_t; + +typedef void (*ipd_status_cb_f)(zoneid_t, const ipd_config_t *, void *); + +extern __thread ipd_errno_t ipd_errno; +extern __thread char ipd_errmsg[]; + +extern const char *ipd_strerror(ipd_errno_t); +extern int ipd_open(const char *); +extern int ipd_close(int); +extern int ipd_status_read(int, ipd_stathdl_t *); +extern void ipd_status_foreach_zone(const ipd_stathdl_t, + ipd_status_cb_f, void *); +extern int ipd_status_get_config(const ipd_stathdl_t, + zoneid_t, ipd_config_t **); +extern void ipd_status_free(ipd_stathdl_t); +extern int ipd_ctl(int, zoneid_t, const ipd_config_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBIPD_H */ diff --git a/usr/src/lib/libipd/common/llib-lipd b/usr/src/lib/libipd/common/llib-lipd new file mode 100644 index 0000000000..79a3521301 --- /dev/null +++ b/usr/src/lib/libipd/common/llib-lipd @@ -0,0 +1,20 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* LINTLIBRARY */ +/* PROTOLIB1 */ + +#include <libipd.h> diff --git a/usr/src/lib/libipd/common/mapfile-vers b/usr/src/lib/libipd/common/mapfile-vers new file mode 100644 index 0000000000..fec8c56859 --- /dev/null +++ b/usr/src/lib/libipd/common/mapfile-vers @@ -0,0 +1,46 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2011 <contributor>. All rights reserved. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# + +$mapfile_version 2 + +SYMBOL_VERSION SUNWprivate_1.1 { + global: + ipd_errno; + ipd_errmsg; + ipd_strerror; + ipd_open; + ipd_close; + ipd_status_read; + ipd_status_foreach_zone; + ipd_status_get_config; + ipd_status_free; + ipd_ctl; + local: + *; +}; diff --git a/usr/src/lib/libipd/i386/Makefile b/usr/src/lib/libipd/i386/Makefile new file mode 100644 index 0000000000..6a668fb98f --- /dev/null +++ b/usr/src/lib/libipd/i386/Makefile @@ -0,0 +1,18 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2012 Joyent, Inc. All rights reserved. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libkmf/ber_der/Makefile.com b/usr/src/lib/libkmf/ber_der/Makefile.com index e056b6cfa7..6654e7cfde 100644 --- a/usr/src/lib/libkmf/ber_der/Makefile.com +++ b/usr/src/lib/libkmf/ber_der/Makefile.com @@ -43,8 +43,10 @@ $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) CFLAGS += $(CCVERBOSE) -xCC CFLAGS64 += $(CCVERBOSE) -xCC -CPPFLAGS += -I/usr/include/libxml2 -I$(INCDIR) -I../../include -CPPFLAGS64 += -I/usr/include/libxml2 -I$(INCDIR) -I../../include +CPPFLAGS += -I$(ADJUNCT_PROTO)/usr/include/libxml2 \ + -I$(INCDIR) -I../../include +CPPFLAGS64 += -I$(ADJUNCT_PROTO)/usr/include/libxml2 \ + -I$(INCDIR) -I../../include LDLIBS += -lc CERRWARN += -_gcc=-Wno-unused-label diff --git a/usr/src/lib/libkmf/libkmf/Makefile.com b/usr/src/lib/libkmf/libkmf/Makefile.com index 4091ae09c1..a704d1e5a8 100644 --- a/usr/src/lib/libkmf/libkmf/Makefile.com +++ b/usr/src/lib/libkmf/libkmf/Makefile.com @@ -63,7 +63,8 @@ LDLIBS6 += $(BERDERLIB64) $(CRYPTOUTILLIB64) -lmd -lpkcs11 -lnsl -lsocket -lc $(DYNLIB) := LDLIBS += -lxml2 $(DYNLIB64) := LDLIBS64 += -lxml2 -CPPFLAGS += -I$(INCDIR) -I/usr/include/libxml2 -I../../ber_der/inc -I$(SRCDIR) +CPPFLAGS += -I$(INCDIR) -I$(ADJUNCT_PROTO)/usr/include/libxml2 \ + -I../../ber_der/inc -I$(SRCDIR) CERRWARN += -_gcc=-Wno-parentheses CERRWARN += -_gcc=-Wno-switch diff --git a/usr/src/lib/libkmf/plugins/kmf_nss/Makefile.com b/usr/src/lib/libkmf/plugins/kmf_nss/Makefile.com index a3ab702811..3b5f23aa92 100644 --- a/usr/src/lib/libkmf/plugins/kmf_nss/Makefile.com +++ b/usr/src/lib/libkmf/plugins/kmf_nss/Makefile.com @@ -34,19 +34,21 @@ include $(SRC)/lib/Makefile.lib MPSDIR= /usr/lib/mps KMFINC= -I../../../include -I../../../ber_der/inc -NSSINC= -I/usr/include/mps +NSSINC= -I$(ADJUNCT_PROTO)/usr/include/mps BERLIB= -lkmf -lkmfberder BERLIB64= $(BERLIB) -NSSLIBS= $(BERLIB) -L$(MPSDIR) -R$(MPSDIR) -lnss3 -lnspr4 -lsmime3 -lc -NSSLIBS64= $(BERLIB64) -L$(MPSDIR)/$(MACH64) -R$(MPSDIR)/$(MACH64) -lnss3 -lnspr4 -lsmime3 -lc +NSSLIBS= $(BERLIB) -L$(ADJUNCT_PROTO)$(MPSDIR) -R$(MPSDIR) \ + -lnss3 -lnspr4 -lsmime3 -lc +NSSLIBS64= $(BERLIB64) -L$(ADJUNCT_PROTO)$(MPSDIR)/$(MACH64) \ + -R$(MPSDIR)/$(MACH64) -lnss3 -lnspr4 -lsmime3 -lc SRCDIR= ../common INCDIR= ../../include CFLAGS += $(CCVERBOSE) CPPFLAGS += -D_REENTRANT $(KMFINC) $(NSSINC) \ - -I$(SFWDIR)/include -I$(INCDIR) -I/usr/include/libxml2 + -I$(INCDIR) -I$(ADJUNCT_PROTO)/usr/include/libxml2 PICS= $(OBJECTS:%=pics/%) diff --git a/usr/src/lib/libkmf/plugins/kmf_openssl/Makefile.com b/usr/src/lib/libkmf/plugins/kmf_openssl/Makefile.com index e44eb0a87c..50e298bc09 100644 --- a/usr/src/lib/libkmf/plugins/kmf_openssl/Makefile.com +++ b/usr/src/lib/libkmf/plugins/kmf_openssl/Makefile.com @@ -37,18 +37,18 @@ KMFINC= -I../../../include -I../../../ber_der/inc BERLIB= -lkmf -lkmfberder BERLIB64= $(BERLIB) -OPENSSLLIBS= $(BERLIB) -lcrypto -lcryptoutil -lc -OPENSSLLIBS64= $(BERLIB64) -lcrypto -lcryptoutil -lc +OPENSSLLIBS= $(BERLIB) -lsunw_crypto -lcryptoutil -lc +OPENSSLLIBS64= $(BERLIB64) -lsunw_crypto -lcryptoutil -lc -LINTSSLLIBS = $(BERLIB) -lcrypto -lcryptoutil -lc -LINTSSLLIBS64 = $(BERLIB64) -lcrypto -lcryptoutil -lc +LINTSSLLIBS = $(BERLIB) -lsunw_crypto -lcryptoutil -lc +LINTSSLLIBS64 = $(BERLIB64) -lsunw_crypto -lcryptoutil -lc SRCDIR= ../common INCDIR= ../../include CFLAGS += $(CCVERBOSE) CPPFLAGS += -D_REENTRANT $(KMFINC) \ - -I$(INCDIR) -I/usr/include/libxml2 + -I$(INCDIR) -I$(ADJUNCT_PROTO)/usr/include/libxml2 CERRWARN += -_gcc=-Wno-unused-label CERRWARN += -_gcc=-Wno-unused-value diff --git a/usr/src/lib/libkmf/plugins/kmf_pkcs11/Makefile.com b/usr/src/lib/libkmf/plugins/kmf_pkcs11/Makefile.com index ae97ef8e8f..0b69e23fd6 100644 --- a/usr/src/lib/libkmf/plugins/kmf_pkcs11/Makefile.com +++ b/usr/src/lib/libkmf/plugins/kmf_pkcs11/Makefile.com @@ -49,7 +49,8 @@ SRCS = \ CFLAGS += $(CCVERBOSE) -CPPFLAGS += -D_REENTRANT $(KMFINC) -I$(INCDIR) -I/usr/include/libxml2 -I$(BIGNUMDIR) +CPPFLAGS += -D_REENTRANT $(KMFINC) -I$(INCDIR) \ + -I$(ADJUNCT_PROTO)/usr/include/libxml2 -I$(BIGNUMDIR) LINTFLAGS64 += -errchk=longptr64 CERRWARN += -_gcc=-Wno-unused-label diff --git a/usr/src/lib/libkvm/common/kvm.c b/usr/src/lib/libkvm/common/kvm.c index d3a5dbd81c..c71c4db31b 100644 --- a/usr/src/lib/libkvm/common/kvm.c +++ b/usr/src/lib/libkvm/common/kvm.c @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ #include <kvm.h> #include <stdio.h> @@ -34,6 +36,7 @@ #include <limits.h> #include <fcntl.h> #include <strings.h> +#include <errno.h> #include <sys/mem.h> #include <sys/stat.h> #include <sys/mman.h> @@ -55,12 +58,15 @@ struct _kvmd { proc_t *kvm_practive; pid_t kvm_pid; char kvm_namelist[MAXNAMELEN + 1]; + boolean_t kvm_namelist_core; proc_t kvm_proc; }; #define PREAD (ssize_t (*)(int, void *, size_t, offset_t))pread64 #define PWRITE (ssize_t (*)(int, void *, size_t, offset_t))pwrite64 +static int kvm_nlist_core(kvm_t *kd, struct nlist nl[], const char *err); + static kvm_t * fail(kvm_t *kd, const char *err, const char *message, ...) { @@ -164,9 +170,15 @@ kvm_open(const char *namelist, const char *corefile, const char *swapfile, (void) strncpy(kd->kvm_namelist, namelist, MAXNAMELEN); - if (kvm_nlist(kd, nl) == -1) - return (fail(kd, err, "%s is not a %d-bit kernel namelist", - namelist, DUMP_WORDSIZE)); + if (kvm_nlist(kd, nl) == -1) { + if (kd->kvm_corefd == -1) { + return (fail(kd, err, "%s is not a %d-bit " + "kernel namelist", namelist, DUMP_WORDSIZE)); + } + + if (kvm_nlist_core(kd, nl, err) == -1) + return (NULL); /* fail() already called */ + } kd->kvm_kas = (struct as *)nl[0].n_value; kd->kvm_practive = (proc_t *)nl[1].n_value; @@ -186,16 +198,85 @@ kvm_close(kvm_t *kd) (void) close(kd->kvm_kmemfd); if (kd->kvm_memfd != -1) (void) close(kd->kvm_memfd); + if (kd->kvm_namelist_core) + (void) unlink(kd->kvm_namelist); free(kd); return (0); } +const char * +kvm_namelist(kvm_t *kd) +{ + return (kd->kvm_namelist); +} + int kvm_nlist(kvm_t *kd, struct nlist nl[]) { return (nlist(kd->kvm_namelist, nl)); } +/* + * If we don't have a name list, try to dig it out of the kernel crash dump. + * (The symbols have been present in the dump, uncompressed, for nearly a + * decade as of this writing -- and it is frankly surprising that the archaic + * notion of a disjoint symbol table managed to survive that change.) + */ +static int +kvm_nlist_core(kvm_t *kd, struct nlist nl[], const char *err) +{ + dumphdr_t *dump = &kd->kvm_dump; + char *msg = "couldn't extract symbols from dump"; + char *template = "/tmp/.libkvm.kvm_nlist_core.pid%d.XXXXXX"; + int fd, rval; + + if (dump->dump_ksyms_size != dump->dump_ksyms_csize) { + (void) fail(kd, err, "%s: kernel symbols are compressed", msg); + return (-1); + } + + if (dump->dump_ksyms + dump->dump_ksyms_size > kd->kvm_coremapsize) { + (void) fail(kd, err, "%s: kernel symbols not mapped", msg); + return (-1); + } + + /* + * Beause this temporary file may be left as a turd if the caller + * does not properly call kvm_close(), we make sure that it clearly + * indicates its origins. + */ + (void) snprintf(kd->kvm_namelist, MAXNAMELEN, template, getpid()); + + if ((fd = mkstemp(kd->kvm_namelist)) == -1) { + (void) fail(kd, err, "%s: couldn't create temporary " + "symbols file: %s", msg, strerror(errno)); + return (-1); + } + + kd->kvm_namelist_core = B_TRUE; + + do { + rval = write(fd, (caddr_t)((uintptr_t)kd->kvm_core + + (uintptr_t)dump->dump_ksyms), dump->dump_ksyms_size); + } while (rval < dump->dump_ksyms_size && errno == EINTR); + + if (rval < dump->dump_ksyms_size) { + (void) fail(kd, err, "%s: couldn't write to temporary " + "symbols file: %s", msg, strerror(errno)); + (void) close(fd); + return (-1); + } + + (void) close(fd); + + if (kvm_nlist(kd, nl) == -1) { + (void) fail(kd, err, "%s: symbols not valid", msg); + return (-1); + } + + return (0); +} + static offset_t kvm_lookup(kvm_t *kd, struct as *as, uint64_t addr) { diff --git a/usr/src/lib/libkvm/common/mapfile-vers b/usr/src/lib/libkvm/common/mapfile-vers index 34ccee8093..091c1cbd08 100644 --- a/usr/src/lib/libkvm/common/mapfile-vers +++ b/usr/src/lib/libkvm/common/mapfile-vers @@ -20,6 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, Joyent, Inc. All rights reserved. # # @@ -60,6 +61,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { global: kvm_aread; kvm_awrite; + kvm_namelist; kvm_physaddr; kvm_pread; kvm_pwrite; diff --git a/usr/src/lib/libkvm/kvm.h b/usr/src/lib/libkvm/kvm.h index ec2bd2a7c2..348b0c2e38 100644 --- a/usr/src/lib/libkvm/kvm.h +++ b/usr/src/lib/libkvm/kvm.h @@ -24,11 +24,13 @@ * All rights reserved. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + #ifndef _KVM_H #define _KVM_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <nlist.h> #include <sys/user.h> @@ -67,6 +69,7 @@ extern proc_t *kvm_nextproc(kvm_t *); extern int kvm_setproc(kvm_t *); extern user_t *kvm_getu(kvm_t *, struct proc *); extern int kvm_getcmd(kvm_t *, proc_t *, user_t *, char ***, char ***); +extern const char *kvm_namelist(kvm_t *); #else diff --git a/usr/src/lib/libldap5/Makefile.com b/usr/src/lib/libldap5/Makefile.com index 9c28fae337..ee48739eea 100644 --- a/usr/src/lib/libldap5/Makefile.com +++ b/usr/src/lib/libldap5/Makefile.com @@ -57,7 +57,7 @@ OBJECTS= $(BEROBJS) $(LDAPOBJS) $(SSLDAPOBJS) $(PRLDAPOBJS) \ include ../../Makefile.lib NSS_LIBS= -lnspr4 -lplc4 -lnss3 -lssl3 -NSS_HDRS= /usr/include/mps +NSS_HDRS= $(ADJUNCT_PROTO)/usr/include/mps NSS_LDPATH= /usr/lib/mps NSS_LDPATH64= $(NSS_LDPATH)/64 diff --git a/usr/src/lib/libldap5/amd64/Makefile b/usr/src/lib/libldap5/amd64/Makefile index 680f2fb7c6..abf5a7d5f8 100644 --- a/usr/src/lib/libldap5/amd64/Makefile +++ b/usr/src/lib/libldap5/amd64/Makefile @@ -10,7 +10,7 @@ PR_MDUSOBJS = os_SunOS_x86.o include ../Makefile.com include ../../Makefile.lib.64 -LDLIBS += -L$(NSS_LDPATH64) $(NSS_LIBS) +LDLIBS += -L$(ADJUNCT_PROTO)$(NSS_LDPATH64) $(NSS_LIBS) DYNFLAGS += -R$(NSS_LDPATH64) all: $(LIBS) diff --git a/usr/src/lib/libldap5/i386/Makefile b/usr/src/lib/libldap5/i386/Makefile index d0eba36ca2..b9e154c6fc 100644 --- a/usr/src/lib/libldap5/i386/Makefile +++ b/usr/src/lib/libldap5/i386/Makefile @@ -11,7 +11,7 @@ PR_MDUSOBJS = os_SunOS_x86.o include ../Makefile.com -LDLIBS += -L$(NSS_LDPATH) $(NSS_LIBS) +LDLIBS += -L$(ADJUNCT_PROTO)$(NSS_LDPATH) $(NSS_LIBS) DYNFLAGS += -R$(NSS_LDPATH) all: $(LIBS) diff --git a/usr/src/lib/libldap5/sparc/Makefile b/usr/src/lib/libldap5/sparc/Makefile index e5e0562484..dcfe21adce 100644 --- a/usr/src/lib/libldap5/sparc/Makefile +++ b/usr/src/lib/libldap5/sparc/Makefile @@ -11,7 +11,7 @@ PR_MDUSOBJS = os_SunOS.o include ../Makefile.com -LDLIBS += -L$(NSS_LDPATH) $(NSS_LIBS) +LDLIBS += -L$(ADJUNCT_PROTO)$(NSS_LDPATH) $(NSS_LIBS) DYNFLAGS += -R$(NSS_LDPATH) diff --git a/usr/src/lib/libldap5/sparcv9/Makefile b/usr/src/lib/libldap5/sparcv9/Makefile index e1ac900b72..b3b78410e5 100644 --- a/usr/src/lib/libldap5/sparcv9/Makefile +++ b/usr/src/lib/libldap5/sparcv9/Makefile @@ -12,7 +12,7 @@ PR_MDUSOBJS = os_SunOS.o include ../Makefile.com include ../../Makefile.lib.64 -LDLIBS += -L$(NSS_LDPATH64) $(NSS_LIBS) +LDLIBS += -L$(ADJUNCT_PROTO)$(NSS_LDPATH64) $(NSS_LIBS) DYNFLAGS += -R$(NSS_LDPATH64) all: $(LIBS) diff --git a/usr/src/lib/libnisdb/db_mindex3.cc b/usr/src/lib/libnisdb/db_mindex3.cc index 886487f8c5..28182544a4 100644 --- a/usr/src/lib/libnisdb/db_mindex3.cc +++ b/usr/src/lib/libnisdb/db_mindex3.cc @@ -282,7 +282,7 @@ entriesFromLDAPthread(void *voidarg) { /* Lock to prevent removal */ (void) __nis_lock_db_table(arg->tableName, 1, 0, - "entriesFromLDAPthread"); + (char *)"entriesFromLDAPthread"); /* * It's possible that the db_mindex for the table has changed, @@ -314,7 +314,7 @@ entriesFromLDAPthread(void *voidarg) { stat = entriesFromLDAPreal(arg); (void) __nis_ulock_db_table(arg->tableName, 1, 0, - "entriesFromLDAPthread"); + (char *)"entriesFromLDAPthread"); freeQuery(arg->q); if (arg->dirObj != 0) diff --git a/usr/src/lib/libnisdb/db_table.cc b/usr/src/lib/libnisdb/db_table.cc index 2995f1a9c9..8044148355 100644 --- a/usr/src/lib/libnisdb/db_table.cc +++ b/usr/src/lib/libnisdb/db_table.cc @@ -599,7 +599,7 @@ db_table::setEntryExp(entryp where, entry_obj *obj, int initialLoad) { if (o != 0) { __nis_buffer_t b = {0, 0}; - bp2buf(myself, &b, "%s.%s", + bp2buf(myself, &b, (char *)"%s.%s", o->zo_name, o->zo_domain); t = getObjMapping(b.buf, 0, 1, 0, 0); sfree(b.buf); @@ -967,7 +967,7 @@ db_table::setEnumMode(long enumNum) { if (stat != DB_SUCCESS) { enumMode.flag = 0; enumCount.flag = 0; - logmsg(MSG_NOTIMECHECK, LOG_ERR, + logmsg(MSG_NOTIMECHECK, LOG_ERR, (char *) "%s: No memory for enum check array; entry removal disabled", myself); } diff --git a/usr/src/lib/libnisdb/nis_db.cc b/usr/src/lib/libnisdb/nis_db.cc index 2908cc99b0..b27889b147 100644 --- a/usr/src/lib/libnisdb/nis_db.cc +++ b/usr/src/lib/libnisdb/nis_db.cc @@ -527,7 +527,7 @@ dbFindObject(char *objName, db_status *statP) { /* If not the root dir, find the directory where the entry lives */ sfree(table); - name = entryName(myself, objName, &table); + name = entryName((char *)myself, objName, &table); if (name == 0 || table == 0) { sfree(name); RETSTAT(0, DB_MEMORY_LIMIT); @@ -737,7 +737,7 @@ dbDeleteObj(char *objName) { nod->objType = o->zo_data.zo_type; nis_destroy_object(o); - nod->objName = sdup(myself, T, objName); + nod->objName = sdup((char *)myself, T, objName); if (nod->objName == 0) { sfree(nod); return (DB_MEMORY_LIMIT); @@ -789,7 +789,7 @@ dbTouchObj(char *objName) { sfree(table); table = 0; - ent = entryName(myself, objName, &table); + ent = entryName((char *)myself, objName, &table); if (ent == 0 || table == 0) { sfree(ent); return (DB_MEMORY_LIMIT); @@ -989,7 +989,7 @@ dbRefreshObj(char *name, nis_object *o) { int lstat; /* Find parent */ - ent = entryName(myself, objName, &table); + ent = entryName((char *)myself, objName, &table); if (ent == 0 || table == 0) { sfree(b.buf); sfree(objTable); diff --git a/usr/src/lib/libnvpair/Makefile.com b/usr/src/lib/libnvpair/Makefile.com index 6a21376eb3..056d967554 100644 --- a/usr/src/lib/libnvpair/Makefile.com +++ b/usr/src/lib/libnvpair/Makefile.com @@ -23,6 +23,7 @@ # Use is subject to license terms. # # Copyright (c) 2012 by Delphix. All rights reserved. +# Copyright (c) 2013, Joyent, Inc. All rights reserved. # LIBRARY= libnvpair.a @@ -32,13 +33,15 @@ OBJECTS= libnvpair.o \ nvpair_alloc_system.o \ nvpair_alloc_fixed.o \ nvpair.o \ - fnvpair.o + fnvpair.o \ + nvpair_json.o include ../../Makefile.lib include ../../Makefile.rootfs SRCS= ../libnvpair.c \ ../nvpair_alloc_system.c \ + ../nvpair_json.c \ $(SRC)/common/nvpair/nvpair_alloc_fixed.c \ $(SRC)/common/nvpair/nvpair.c \ $(SRC)/common/nvpair/fnvpair.c @@ -54,7 +57,13 @@ LINTFLAGS64 += -erroff=E_BAD_PTR_CAST_ALIGN # turn off warning caused by lint bug: not understanding SCNi8 "hhi" LINTFLAGS += -erroff=E_BAD_FORMAT_STR2 +LINTFLAGS += -erroff=E_INVALID_TOKEN_IN_DEFINE_MACRO +LINTFLAGS += -erroff=E_RET_INT_IMPLICITLY +LINTFLAGS += -erroff=E_FUNC_USED_VAR_ARG2 LINTFLAGS64 += -erroff=E_BAD_FORMAT_STR2 +LINTFLAGS64 += -erroff=E_INVALID_TOKEN_IN_DEFINE_MACRO +LINTFLAGS64 += -erroff=E_RET_INT_IMPLICITLY +LINTFLAGS64 += -erroff=E_FUNC_USED_VAR_ARG2 CERRWARN += -_gcc=-Wno-type-limits CERRWARN += -_gcc=-Wno-parentheses diff --git a/usr/src/lib/libnvpair/libnvpair.h b/usr/src/lib/libnvpair/libnvpair.h index 4c2615d924..b05669e506 100644 --- a/usr/src/lib/libnvpair/libnvpair.h +++ b/usr/src/lib/libnvpair/libnvpair.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #ifndef _LIBNVPAIR_H @@ -46,6 +47,7 @@ extern int nvpair_value_match_regex(nvpair_t *, int, char *, regex_t *, char **); extern void nvlist_print(FILE *, nvlist_t *); +extern int nvlist_print_json(FILE *, nvlist_t *); extern void dump_nvlist(nvlist_t *, int); /* diff --git a/usr/src/lib/libnvpair/mapfile-vers b/usr/src/lib/libnvpair/mapfile-vers index a014835447..0403964e05 100644 --- a/usr/src/lib/libnvpair/mapfile-vers +++ b/usr/src/lib/libnvpair/mapfile-vers @@ -21,6 +21,7 @@ # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2012 by Delphix. All rights reserved. +# Copyright (c) 2013, Joyent, Inc. All rights reserved. # # @@ -244,6 +245,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { nvlist_add_hrtime; nvlist_lookup_hrtime; nvlist_print; + nvlist_print_json; nvlist_prt; nvlist_prtctl_alloc; nvlist_prtctl_free; diff --git a/usr/src/lib/libnvpair/nvpair_json.c b/usr/src/lib/libnvpair/nvpair_json.c new file mode 100644 index 0000000000..77348041ab --- /dev/null +++ b/usr/src/lib/libnvpair/nvpair_json.c @@ -0,0 +1,400 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <wchar.h> +#include <sys/debug.h> + +#include "libnvpair.h" + +#define FPRINTF(fp, ...) \ + do { \ + if (fprintf(fp, __VA_ARGS__) < 0) \ + return (-1); \ + } while (0) + +/* + * When formatting a string for JSON output we must escape certain characters, + * as described in RFC4627. This applies to both member names and + * DATA_TYPE_STRING values. + * + * This function will only operate correctly if the following conditions are + * met: + * + * 1. The input String is encoded in the current locale. + * + * 2. The current locale includes the Basic Multilingual Plane (plane 0) + * as defined in the Unicode standard. + * + * The output will be entirely 7-bit ASCII (as a subset of UTF-8) with all + * representable Unicode characters included in their escaped numeric form. + */ +static int +nvlist_print_json_string(FILE *fp, const char *input) +{ + mbstate_t mbr; + wchar_t c; + size_t sz; + + bzero(&mbr, sizeof (mbr)); + + FPRINTF(fp, "\""); + while ((sz = mbrtowc(&c, input, MB_CUR_MAX, &mbr)) > 0) { + switch (c) { + case '"': + FPRINTF(fp, "\\\""); + break; + case '\n': + FPRINTF(fp, "\\n"); + break; + case '\r': + FPRINTF(fp, "\\r"); + break; + case '\\': + FPRINTF(fp, "\\\\"); + break; + case '\f': + FPRINTF(fp, "\\f"); + break; + case '\t': + FPRINTF(fp, "\\t"); + break; + case '\b': + FPRINTF(fp, "\\b"); + break; + default: + if ((c >= 0x00 && c <= 0x1f) || + (c > 0x7f && c <= 0xffff)) { + /* + * Render both Control Characters and Unicode + * characters in the Basic Multilingual Plane + * as JSON-escaped multibyte characters. + */ + FPRINTF(fp, "\\u%04x", 0xffff & c); + } else if (c >= 0x20 && c <= 0x7f) { + /* + * Render other 7-bit ASCII characters directly + * and drop other, unrepresentable characters. + */ + FPRINTF(fp, "%c", 0xff & c); + } + break; + } + input += sz; + } + + if (sz == (size_t)-1 || sz == (size_t)-2) { + /* + * We last read an invalid multibyte character sequence, + * so return an error. + */ + return (-1); + } + + FPRINTF(fp, "\""); + return (0); +} + +/* + * Dump a JSON-formatted representation of an nvlist to the provided FILE *. + * This routine does not output any new-lines or additional whitespace other + * than that contained in strings, nor does it call fflush(3C). + */ +int +nvlist_print_json(FILE *fp, nvlist_t *nvl) +{ + nvpair_t *curr; + boolean_t first = B_TRUE; + + FPRINTF(fp, "{"); + + for (curr = nvlist_next_nvpair(nvl, NULL); curr; + curr = nvlist_next_nvpair(nvl, curr)) { + data_type_t type = nvpair_type(curr); + + if (!first) + FPRINTF(fp, ","); + else + first = B_FALSE; + + if (nvlist_print_json_string(fp, nvpair_name(curr)) == -1) + return (-1); + FPRINTF(fp, ":"); + + switch (type) { + case DATA_TYPE_STRING: { + char *string = fnvpair_value_string(curr); + if (nvlist_print_json_string(fp, string) == -1) + return (-1); + break; + } + + case DATA_TYPE_BOOLEAN: { + FPRINTF(fp, "true"); + break; + } + + case DATA_TYPE_BOOLEAN_VALUE: { + FPRINTF(fp, "%s", fnvpair_value_boolean_value(curr) == + B_TRUE ? "true" : "false"); + break; + } + + case DATA_TYPE_BYTE: { + FPRINTF(fp, "%hhu", fnvpair_value_byte(curr)); + break; + } + + case DATA_TYPE_INT8: { + FPRINTF(fp, "%hhd", fnvpair_value_int8(curr)); + break; + } + + case DATA_TYPE_UINT8: { + FPRINTF(fp, "%hhu", fnvpair_value_uint8_t(curr)); + break; + } + + case DATA_TYPE_INT16: { + FPRINTF(fp, "%hd", fnvpair_value_int16(curr)); + break; + } + + case DATA_TYPE_UINT16: { + FPRINTF(fp, "%hu", fnvpair_value_uint16(curr)); + break; + } + + case DATA_TYPE_INT32: { + FPRINTF(fp, "%d", fnvpair_value_int32(curr)); + break; + } + + case DATA_TYPE_UINT32: { + FPRINTF(fp, "%u", fnvpair_value_uint32(curr)); + break; + } + + case DATA_TYPE_INT64: { + FPRINTF(fp, "%lld", fnvpair_value_int64(curr)); + break; + } + + case DATA_TYPE_UINT64: { + FPRINTF(fp, "%llu", fnvpair_value_uint64(curr)); + break; + } + + case DATA_TYPE_HRTIME: { + hrtime_t val; + VERIFY0(nvpair_value_hrtime(curr, &val)); + FPRINTF(fp, "%llu", val); + break; + } + + case DATA_TYPE_DOUBLE: { + double val; + VERIFY0(nvpair_value_double(curr, &val)); + FPRINTF(fp, "%f", val); + break; + } + + case DATA_TYPE_NVLIST: { + if (nvlist_print_json(fp, + fnvpair_value_nvlist(curr)) == -1) + return (-1); + break; + } + + case DATA_TYPE_STRING_ARRAY: { + char **val; + uint_t valsz, i; + VERIFY0(nvpair_value_string_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + if (nvlist_print_json_string(fp, val[i]) == -1) + return (-1); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_NVLIST_ARRAY: { + nvlist_t **val; + uint_t valsz, i; + VERIFY0(nvpair_value_nvlist_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + if (nvlist_print_json(fp, val[i]) == -1) + return (-1); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_BOOLEAN_ARRAY: { + boolean_t *val; + uint_t valsz, i; + VERIFY0(nvpair_value_boolean_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + FPRINTF(fp, val[i] == B_TRUE ? + "true" : "false"); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_BYTE_ARRAY: { + uchar_t *val; + uint_t valsz, i; + VERIFY0(nvpair_value_byte_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + FPRINTF(fp, "%hhu", val[i]); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_UINT8_ARRAY: { + uint8_t *val; + uint_t valsz, i; + VERIFY0(nvpair_value_uint8_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + FPRINTF(fp, "%hhu", val[i]); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_INT8_ARRAY: { + int8_t *val; + uint_t valsz, i; + VERIFY0(nvpair_value_int8_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + FPRINTF(fp, "%hd", val[i]); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_UINT16_ARRAY: { + uint16_t *val; + uint_t valsz, i; + VERIFY0(nvpair_value_uint16_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + FPRINTF(fp, "%hu", val[i]); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_INT16_ARRAY: { + int16_t *val; + uint_t valsz, i; + VERIFY0(nvpair_value_int16_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + FPRINTF(fp, "%hhd", val[i]); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_UINT32_ARRAY: { + uint32_t *val; + uint_t valsz, i; + VERIFY0(nvpair_value_uint32_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + FPRINTF(fp, "%u", val[i]); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_INT32_ARRAY: { + int32_t *val; + uint_t valsz, i; + VERIFY0(nvpair_value_int32_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + FPRINTF(fp, "%d", val[i]); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_UINT64_ARRAY: { + uint64_t *val; + uint_t valsz, i; + VERIFY0(nvpair_value_uint64_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + FPRINTF(fp, "%llu", val[i]); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_INT64_ARRAY: { + int64_t *val; + uint_t valsz, i; + VERIFY0(nvpair_value_int64_array(curr, &val, &valsz)); + FPRINTF(fp, "["); + for (i = 0; i < valsz; i++) { + if (i > 0) + FPRINTF(fp, ","); + FPRINTF(fp, "%lld", val[i]); + } + FPRINTF(fp, "]"); + break; + } + + case DATA_TYPE_UNKNOWN: + return (-1); + } + } + + FPRINTF(fp, "}"); + return (0); +} diff --git a/usr/src/lib/libpkg/Makefile.com b/usr/src/lib/libpkg/Makefile.com index 8f56a61423..0106d8288f 100644 --- a/usr/src/lib/libpkg/Makefile.com +++ b/usr/src/lib/libpkg/Makefile.com @@ -64,7 +64,7 @@ $(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) LIBS = $(DYNLIB) $(LINTLIB) -LDLIBS += -lc -lssl -lwanboot -lcrypto -lscf -ladm +LDLIBS += -lc -lsunw_ssl -lwanboot -lsunw_crypto -lscf -ladm CFLAGS += $(CCVERBOSE) CERRWARN += -_gcc=-Wno-unused-label diff --git a/usr/src/lib/libpool/Makefile.com b/usr/src/lib/libpool/Makefile.com index 493e442d0d..13b8a05cc1 100644 --- a/usr/src/lib/libpool/Makefile.com +++ b/usr/src/lib/libpool/Makefile.com @@ -48,7 +48,8 @@ SRCDIR = ../common $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) CFLAGS += $(CCVERBOSE) -CPPFLAGS += -D_REENTRANT -D_FILE_OFFSET_BITS=64 -I/usr/include/libxml2 +CPPFLAGS += -D_REENTRANT -D_FILE_OFFSET_BITS=64 \ + -I$(ADJUNCT_PROTO)/usr/include/libxml2 CERRWARN += -_gcc=-Wno-parentheses CERRWARN += -_gcc=-Wno-switch diff --git a/usr/src/lib/libproc/common/Pzone.c b/usr/src/lib/libproc/common/Pzone.c index c478b41624..31319674b2 100644 --- a/usr/src/lib/libproc/common/Pzone.c +++ b/usr/src/lib/libproc/common/Pzone.c @@ -24,6 +24,9 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ #include <assert.h> #include <dlfcn.h> #include <errno.h> @@ -792,9 +795,10 @@ Pfindmap(struct ps_prochandle *P, map_info_t *mptr, char *s, size_t n) (strcmp(mptr->map_pmap.pr_mapname, "a.out") == 0) || ((fptr != NULL) && (fptr->file_lname != NULL) && (strcmp(fptr->file_lname, "a.out") == 0))) { - (void) Pexecname(P, buf, sizeof (buf)); - (void) strlcpy(s, buf, n); - return (s); + if (Pexecname(P, buf, sizeof (buf)) != NULL) { + (void) strlcpy(s, buf, n); + return (s); + } } /* Try /proc first to get the real object name */ diff --git a/usr/src/lib/libproject/common/setproject.c b/usr/src/lib/libproject/common/setproject.c index e24a8b78c6..ef208845a1 100644 --- a/usr/src/lib/libproject/common/setproject.c +++ b/usr/src/lib/libproject/common/setproject.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ @@ -199,9 +200,7 @@ rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr, int flags) int count = 0; char *tmp; int local_act; - rctlblk_t *rlast; rctlblk_t *rnext; - rctlblk_t *rtmp; int teardown_basic = 0; int teardown_priv = 0; @@ -358,44 +357,35 @@ rctl_set(char *ctl_name, char *val, struct ps_prochandle *Pr, int flags) /* teardown rctls if required */ if (!project_entity) { - if ((rlast = (rctlblk_t *)malloc(rctlblk_size())) == NULL) { - free(ablk); - return (SETFAILED); - } if ((rnext = (rctlblk_t *)malloc(rctlblk_size())) == NULL) { free(ablk); - free(rlast); return (SETFAILED); } +restart: if (pr_getrctl(Pr, ctl_name, NULL, rnext, RCTL_FIRST) == 0) { - while (1) { if ((rctlblk_get_privilege(rnext) == RCPRIV_PRIVILEGED) && (teardown_priv == 1)) { (void) pr_setrctl(Pr, ctl_name, NULL, rnext, RCTL_DELETE); + goto restart; } if ((rctlblk_get_privilege(rnext) == RCPRIV_BASIC) && (teardown_basic == 1)) { (void) pr_setrctl(Pr, ctl_name, NULL, rnext, RCTL_DELETE); + goto restart; } - rtmp = rnext; - rnext = rlast; - rlast = rtmp; - if (pr_getrctl(Pr, ctl_name, rlast, rnext, + if (pr_getrctl(Pr, ctl_name, rnext, rnext, RCTL_NEXT) == -1) break; } - } free(rnext); - free(rlast); - } /* set rctls */ diff --git a/usr/src/lib/libresolv2_joy/Makefile b/usr/src/lib/libresolv2_joy/Makefile new file mode 100644 index 0000000000..052dfdd092 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/Makefile @@ -0,0 +1,76 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. +# + + +include ../../Makefile.master +include ../Makefile.lib + +$(ROOTSVCMETHOD) := FILEMODE = 0555 + +SUBDIRS= include $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install +lint := TARGET= lint +_msg := TARGET= _msg + +LIBRARY= libresolv_joy.a +TEXT_DOMAIN= SUNW_OST_OSLIB +XGETFLAGS= -a +POFILE= $(LIBRARY:.a=.po) +POFILES= generic.po + +SED= sed +GREP= grep + +.KEEP_STATE: + +all clean clobber lint: $(SUBDIRS) + +install: $(SUBDIRS) + +check: $(CHECKHDRS) $(CHKMANIFEST) + +_msg: $(MSGDOMAIN) $(POFILE) + $(RM) $(MSGDOMAIN)/$(POFILE) + $(CP) $(POFILE) $(MSGDOMAIN) + +$(POFILE): $(POFILES) + $(RM) $@ + $(CAT) $(POFILES) > $@ + +$(POFILES): + $(RM) messages.po + $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]* + $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ + $(RM) messages.po + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET); echo + +FRC: + diff --git a/usr/src/lib/libresolv2_joy/Makefile.com b/usr/src/lib/libresolv2_joy/Makefile.com new file mode 100644 index 0000000000..bbabcbcede --- /dev/null +++ b/usr/src/lib/libresolv2_joy/Makefile.com @@ -0,0 +1,162 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# + +LIBRARY= libresolv_joy.a +VERS= .2 + +BSDOBJS= daemon.o putenv.o strcasecmp.o strsep.o \ + ftruncate.o readv.o strdup.o strtoul.o \ + gettimeofday.o setenv.o strerror.o utimes.o \ + mktemp.o setitimer.o strpbrk.o writev.o + +DSTOBJS= dst_api.o support.o hmac_link.o + +# inet_addr, inet_pton, inet_ntop, and inet_ntoa removed due to overlap with +# libnsl +INETOBJS= inet_net_pton.o inet_neta.o inet_lnaof.o \ + inet_netof.o nsap_addr.o inet_makeaddr.o \ + inet_network.o inet_net_ntop.o inet_cidr_ntop.o \ + inet_cidr_pton.o inet_data.o + +# build only the IRS objects that the ISC libbind's make would +IRSTHROBJS= gethostent_r.o getnetent_r.o getnetgrent_r.o \ + getprotoent_r.o getservent_r.o +IRSOBJS= ${IRSTHROBJS} \ + dns.o dns_ho.o dns_nw.o dns_pr.o \ + dns_sv.o gai_strerror.o gen.o gen_ho.o \ + gen_ng.o gen_nw.o gen_pr.o gen_sv.o \ + getaddrinfo.o gethostent.o getnameinfo.o getnetent.o \ + getnetgrent.o getprotoent.o getservent.o hesiod.o \ + irp.o irp_ho.o irp_ng.o irp_nw.o \ + irp_pr.o irp_sv.o irpmarshall.o irs_data.o \ + lcl.o lcl_ho.o lcl_ng.o lcl_nw.o \ + lcl_pr.o lcl_sv.o nis.o nul_ng.o \ + util.o + +ISCOBJS= assertions.o base64.o bitncmp.o ctl_clnt.o \ + ctl_p.o ctl_srvr.o ev_connects.o ev_files.o \ + ev_streams.o ev_timers.o ev_waits.o eventlib.o \ + heap.o hex.o logging.o memcluster.o \ + movefile.o tree.o + +NAMESEROBJS= ns_date.o ns_name.o ns_netint.o ns_parse.o \ + ns_print.o ns_samedomain.o ns_sign.o ns_ttl.o \ + ns_verify.o ns_rdata.o ns_newmsg.o + +RESOLVOBJS= herror.o mtctxres.o res_comp.o res_data.o \ + res_debug.o res_findzonecut.o res_init.o \ + res_mkquery.o res_mkupdate.o res_query.o res_send.o \ + res_sendsigned.o res_update.o + +SUNWOBJS= sunw_mtctxres.o sunw_updrec.o sunw_wrappers.o + +OBJECTS= $(BSDOBJS) $(DSTOBJS) $(INETOBJS) $(IRSOBJS) $(ISCOBJS) \ + $(NAMESEROBJS) $(RESOLVOBJS) $(SUNWOBJS) + +# include library definitions +include ../../Makefile.lib + +# install this library in the root filesystem +include ../../Makefile.rootfs + +# CC -v complains about things we aren't going to change in the ISC code +CCVERBOSE= + +SRCDIR = ../common +SRCS= $(BSDOBJS:%.o=../common/bsd/%.c) \ + $(DSTOBJS:%.o=../common/dst/%.c) \ + $(INETOBJS:%.o=../common/inet/%.c) \ + $(IRSOBJS:%.o=../common/irs/%.c) \ + $(ISCOBJS:%.o=../common/isc/%.c) \ + $(NAMESEROBJS:%.o=../common/nameser/%.c) \ + $(RESOLVOBJS:%.o=../common/resolv/%.c) \ + $(SUNWOBJS:%.o=../common/sunw/%.c) + +LIBS = $(DYNLIB) $(LINTLIB) + +$(LINTLIB):= SRCS = ../common/llib-lresolv_joy + +# Local Libresolv definitions + +SOLCOMPAT = -Dsocket=_socket +CRYPTFLAGS= -DHMAC_MD5 -DUSE_MD5 + +LOCFLAGS += $(CRYPTFLAGS) +LOCFLAGS += -D_SYS_STREAM_H -D_REENTRANT -DSVR4 -DSUNW_OPTIONS \ + $(SOLCOMPAT) -I../include -I../../common/inc + +CPPFLAGS += $(LOCFLAGS) + +CERRWARN += -_gcc=-Wno-implicit-function-declaration + +DYNFLAGS += $(ZNODELETE) + +LDLIBS += -lsocket -lnsl -lc -lmd + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +# include library targets +include ../../Makefile.targ + +pics/%.o: ../common/bsd/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/dst/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/inet/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/irs/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/isc/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/nameser/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/resolv/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +pics/%.o: ../common/sunw/%.c + $(COMPILE.c) -o $@ $< + $(POST_PROCESS_O) + +# install rule for lint library target +$(ROOTLINTDIR)/%: ../common/% + $(INS.file) diff --git a/usr/src/lib/libresolv2_joy/THIRDPARTYLICENSE b/usr/src/lib/libresolv2_joy/THIRDPARTYLICENSE new file mode 100644 index 0000000000..719d77fea2 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/THIRDPARTYLICENSE @@ -0,0 +1,185 @@ + * Copyright (c) 1995-1999 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. + + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + + * 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 (c) 1983, 1990, 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. + +/* Copyright (C) RSA Data Security, Inc. created 1986-1987, 1990, + 1992-1994, 1996. This is an + unpublished work protected as such under copyright law. This work + contains proprietary, confidential, and trade secret information of + RSA Data Security, Inc. Use, disclosure or reproduction without the + express written authorization of RSA Data Security, Inc. is + prohibited. + */ + + DNSSAFE LICENSE TERMS + + This BIND software includes the DNSsafe software from RSA Data + Security, Inc., which is copyrighted software that can only be + distributed under the terms of this license agreement. + + The DNSsafe software cannot be used or distributed separately from the + BIND software. You only have the right to use it or distribute it as + a bundled, integrated product. + + The DNSsafe software can ONLY be used to provide authentication for + resource records in the Domain Name System, as specified in RFC 2065 + and successors. You cannot modify the BIND software to use the + DNSsafe software for other purposes, or to make its cryptographic + functions available to end-users for other uses. + + If you modify the DNSsafe software itself, you cannot modify its + documented API, and you must grant RSA Data Security the right to use, + modify, and distribute your modifications, including the right to use + any patents or other intellectual property that your modifications + depend upon. + + You must not remove, alter, or destroy any of RSA's copyright notices + or license information. When distributing the software to the Federal + Government, it must be licensed to them as "commercial computer + software" protected under 48 CFR 12.212 of the FAR, or 48 CFR + 227.7202.1 of the DFARS. + + You must not violate United States export control laws by distributing + the DNSsafe software or information about it, when such distribution + is prohibited by law. + + THE DNSSAFE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY + WHATSOEVER. RSA HAS NO OBLIGATION TO SUPPORT, CORRECT, UPDATE OR + MAINTAIN THE RSA SOFTWARE. RSA DISCLAIMS ALL WARRANTIES, EXPRESS, + IMPLIED OR STATUTORY, AS TO ANY MATTER WHATSOEVER, INCLUDING ALL + IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY RIGHTS. + + If you desire to use DNSsafe in ways that these terms do not permit, + please contact RSA Data Security, Inc., 100 Marine Parkway, Redwood + City, California 94065, USA, to discuss alternate licensing + arrangements. + + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * 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 TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS 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 THE SOFTWARE. + + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by WIDE Project and + * its contributors. + * 4. 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. diff --git a/usr/src/lib/libresolv2_joy/THIRDPARTYLICENSE.descrip b/usr/src/lib/libresolv2_joy/THIRDPARTYLICENSE.descrip new file mode 100644 index 0000000000..67315d8f33 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/THIRDPARTYLICENSE.descrip @@ -0,0 +1 @@ +BIND SOFTWARE diff --git a/usr/src/lib/print/libipp-core/sparc/Makefile b/usr/src/lib/libresolv2_joy/amd64/Makefile index 3b985583a4..2e8cdecf75 100644 --- a/usr/src/lib/print/libipp-core/sparc/Makefile +++ b/usr/src/lib/libresolv2_joy/amd64/Makefile @@ -26,5 +26,6 @@ # include ../Makefile.com +include ../../Makefile.lib.64 -install: all $(ROOTLIBS) $(ROOTLINKS) # $(ROOTLINT) +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libresolv2_joy/common/bsd/daemon.c b/usr/src/lib/libresolv2_joy/common/bsd/daemon.c new file mode 100644 index 0000000000..54ff83b753 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/daemon.c @@ -0,0 +1,81 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: daemon.c,v 1.2 2005/04/27 04:56:10 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1990, 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. + */ + +#include "port_before.h" + +#include <fcntl.h> +#include <paths.h> +#include <unistd.h> + +#include "port_after.h" + +#ifndef NEED_DAEMON +int __bind_daemon__; +#else + +int +daemon(int nochdir, int noclose) { + int fd; + + switch (fork()) { + case -1: + return (-1); + case 0: + break; + default: + _exit(0); + } + + if (setsid() == -1) + return (-1); + + if (!nochdir) + (void)chdir("/"); + + if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { + (void)dup2(fd, STDIN_FILENO); + (void)dup2(fd, STDOUT_FILENO); + (void)dup2(fd, STDERR_FILENO); + if (fd > 2) + (void)close (fd); + } + return (0); +} +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/ftruncate.c b/usr/src/lib/libresolv2_joy/common/bsd/ftruncate.c new file mode 100644 index 0000000000..5ac4ebac9b --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/ftruncate.c @@ -0,0 +1,64 @@ +#ifndef LINT +static const char rcsid[] = "$Id: ftruncate.c,v 1.3 2005/04/27 18:16:45 sra Exp $"; +#endif + +/*! \file + * \brief + * ftruncate - set file size, BSD Style + * + * shortens or enlarges the file as neeeded + * uses some undocumented locking call. It is known to work on SCO unix, + * other vendors should try. + * The #error directive prevents unsupported OSes + */ + +#include "port_before.h" + +#if defined(M_UNIX) +#define OWN_FTRUNCATE +#include <stdio.h> +#ifdef _XOPEN_SOURCE +#undef _XOPEN_SOURCE +#endif +#ifdef _POSIX_SOURCE +#undef _POSIX_SOURCE +#endif + +#include <fcntl.h> + +#include "port_after.h" + +int +__ftruncate(int fd, long wantsize) { + long cursize; + + /* determine current file size */ + if ((cursize = lseek(fd, 0L, 2)) == -1) + return (-1); + + /* maybe lengthen... */ + if (cursize < wantsize) { + if (lseek(fd, wantsize - 1, 0) == -1 || + write(fd, "", 1) == -1) { + return (-1); + } + return (0); + } + + /* maybe shorten... */ + if (wantsize < cursize) { + struct flock fl; + + fl.l_whence = 0; + fl.l_len = 0; + fl.l_start = wantsize; + fl.l_type = F_WRLCK; + return (fcntl(fd, F_FREESP, &fl)); + } + return (0); +} +#endif + +#ifndef OWN_FTRUNCATE +int __bindcompat_ftruncate; +#endif diff --git a/usr/src/lib/libresolv2_joy/common/bsd/gettimeofday.c b/usr/src/lib/libresolv2_joy/common/bsd/gettimeofday.c new file mode 100644 index 0000000000..2926a3575e --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/gettimeofday.c @@ -0,0 +1,62 @@ +#ifndef LINT +static const char rcsid[] = "$Id: gettimeofday.c,v 1.4 2005/04/27 04:56:11 sra Exp $"; +#endif + +#include "port_before.h" +#include <stdio.h> +#include <syslog.h> +#include <sys/time.h> +#include "port_after.h" + +#if !defined(NEED_GETTIMEOFDAY) +/*% + * gettimeofday() occasionally returns invalid tv_usec on some platforms. + */ +#define MILLION 1000000 +#undef gettimeofday + +int +isc__gettimeofday(struct timeval *tp, struct timezone *tzp) { + int res; + + res = gettimeofday(tp, tzp); + if (res < 0) + return (res); + if (tp == NULL) + return (res); + if (tp->tv_usec < 0) { + do { + tp->tv_usec += MILLION; + tp->tv_sec--; + } while (tp->tv_usec < 0); + goto log; + } else if (tp->tv_usec > MILLION) { + do { + tp->tv_usec -= MILLION; + tp->tv_sec++; + } while (tp->tv_usec > MILLION); + goto log; + } + return (res); + log: + syslog(LOG_ERR, "gettimeofday: tv_usec out of range\n"); + return (res); +} +#else +int +gettimeofday(struct timeval *tvp, struct _TIMEZONE *tzp) { + time_t clock, time(time_t *); + + if (time(&clock) == (time_t) -1) + return (-1); + if (tvp) { + tvp->tv_sec = clock; + tvp->tv_usec = 0; + } + if (tzp) { + tzp->tz_minuteswest = 0; + tzp->tz_dsttime = 0; + } + return (0); +} +#endif /*NEED_GETTIMEOFDAY*/ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/mktemp.c b/usr/src/lib/libresolv2_joy/common/bsd/mktemp.c new file mode 100644 index 0000000000..001b24b58f --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/mktemp.c @@ -0,0 +1,156 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: mktemp.c,v 1.2 2005/04/27 04:56:11 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987, 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. + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> + +#include "port_after.h" + +#if (!defined(NEED_MKTEMP)) && (!defined(NEED_MKSTEMP)) +int __mktemp_unneeded__; +#else + +static int gettemp(char *path, int *doopen); + +#ifdef NEED_MKSTEMP +mkstemp(char *path) { + int fd; + + return (gettemp(path, &fd) ? fd : -1); +} +#endif + +#ifdef NEED_MKTEMP +char * +mktemp(char *path) { + return(gettemp(path, (int *)NULL) ? path : (char *)NULL); +} +#endif + +static int +gettemp(char *path, int *doopen) { + char *start, *trv; + struct stat sbuf; + u_int pid; + + pid = getpid(); + for (trv = path; *trv; ++trv); /*%< extra X's get set to 0's */ + while (*--trv == 'X') { + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* + * check the target directory; if you have six X's and it + * doesn't exist this runs for a *very* long time. + */ + for (start = trv + 1;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + if (stat(path, &sbuf)) + return(0); + if (!S_ISDIR(sbuf.st_mode)) { + errno = ENOTDIR; + return(0); + } + *trv = '/'; + break; + } + } + + for (;;) { + if (doopen) { + if ((*doopen = + open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) + return(1); + if (errno != EEXIST) + return(0); + } + else if (stat(path, &sbuf)) + return(errno == ENOENT ? 1 : 0); + + /* tricky little algorithm for backward compatibility */ + for (trv = start;;) { + if (!*trv) + return(0); + if (*trv == 'z') + *trv++ = 'a'; + else { + if (isdigit(*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /*NOTREACHED*/ +} + +#endif /*NEED_MKTEMP*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/putenv.c b/usr/src/lib/libresolv2_joy/common/bsd/putenv.c new file mode 100644 index 0000000000..2dcbc57e6c --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/putenv.c @@ -0,0 +1,27 @@ +#ifndef LINT +static const char rcsid[] = "$Id: putenv.c,v 1.2 2005/04/27 04:56:11 sra Exp $"; +#endif + +#include "port_before.h" +#include "port_after.h" + +/*% + * To give a little credit to Sun, SGI, + * and many vendors in the SysV world. + */ + +#if !defined(NEED_PUTENV) +int __bindcompat_putenv; +#else +int +putenv(char *str) { + char *tmp; + + for (tmp = str; *tmp && (*tmp != '='); tmp++) + ; + + return (setenv(str, tmp, 1)); +} +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/readv.c b/usr/src/lib/libresolv2_joy/common/bsd/readv.c new file mode 100644 index 0000000000..5fa691a92f --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/readv.c @@ -0,0 +1,39 @@ +#ifndef LINT +static const char rcsid[] = "$Id: readv.c,v 1.2 2005/04/27 04:56:11 sra Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/stat.h> +#include <sys/socket.h> + +#include "port_after.h" + +#ifndef NEED_READV +int __bindcompat_readv; +#else + +int +__readv(fd, vp, vpcount) + int fd; + const struct iovec *vp; + int vpcount; +{ + int count = 0; + + while (vpcount-- > 0) { + int bytes = read(fd, vp->iov_base, vp->iov_len); + + if (bytes < 0) + return (-1); + count += bytes; + if (bytes != vp->iov_len) + break; + vp++; + } + return (count); +} +#endif /* NEED_READV */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/setenv.c b/usr/src/lib/libresolv2_joy/common/bsd/setenv.c new file mode 100644 index 0000000000..baf00f6ff2 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/setenv.c @@ -0,0 +1,151 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)setenv.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: setenv.c,v 1.2 2005/04/27 04:56:11 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987, 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. + */ + +#include "port_before.h" + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#include "port_after.h" + +#if !defined(NEED_SETENV) +int __bindcompat_setenv; +#else + +extern char **environ; + +static char *findenv(const char *name, int *offset); + +/*% + * setenv -- + * Set the value of the environmental variable "name" to be + * "value". If rewrite is set, replace any current value. + */ +setenv(const char *name, const char *value, int rewrite) { + extern char **environ; + static int alloced; /*%< if allocated space before */ + char *c; + int l_value, offset; + + if (*value == '=') /*%< no `=' in value */ + ++value; + l_value = strlen(value); + if ((c = findenv(name, &offset))) { /*%< find if already exists */ + if (!rewrite) + return (0); + if (strlen(c) >= l_value) { /*%< old larger; copy over */ + while (*c++ = *value++); + return (0); + } + } else { /*%< create new slot */ + int cnt; + char **p; + + for (p = environ, cnt = 0; *p; ++p, ++cnt); + if (alloced) { /*%< just increase size */ + environ = (char **)realloc((char *)environ, + (size_t)(sizeof(char *) * (cnt + 2))); + if (!environ) + return (-1); + } + else { /*%< get new space */ + alloced = 1; /*%< copy old entries into it */ + p = malloc((size_t)(sizeof(char *) * (cnt + 2))); + if (!p) + return (-1); + memcpy(p, environ, cnt * sizeof(char *)); + environ = p; + } + environ[cnt + 1] = NULL; + offset = cnt; + } + for (c = (char *)name; *c && *c != '='; ++c); /*%< no `=' in name */ + if (!(environ[offset] = /*%< name + `=' + value */ + malloc((size_t)((int)(c - name) + l_value + 2)))) + return (-1); + for (c = environ[offset]; (*c = *name++) && *c != '='; ++c); + for (*c++ = '='; *c++ = *value++;); + return (0); +} + +/*% + * unsetenv(name) -- + * Delete environmental variable "name". + */ +void +unsetenv(const char *name) { + char **p; + int offset; + + while (findenv(name, &offset)) /*%< if set multiple times */ + for (p = &environ[offset];; ++p) + if (!(*p = *(p + 1))) + break; +} + +/*% + * findenv -- + * Returns pointer to value associated with name, if any, else NULL. + * Sets offset to be the offset of the name/value combination in the + * environmental array, for use by setenv(3) and unsetenv(3). + * Explicitly removes '=' in argument name. + * + * This routine *should* be a static; don't use it. + */ +static char * +findenv(const char *name, int *offset) { + const char *np; + char **p, *c; + int len; + + if (name == NULL || environ == NULL) + return (NULL); + for (np = name; *np && *np != '='; ++np) + continue; + len = np - name; + for (p = environ; (c = *p) != NULL; ++p) + if (strncmp(c, name, len) == 0 && c[len] == '=') { + *offset = p - environ; + return (c + len + 1); + } + return (NULL); +} +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/setitimer.c b/usr/src/lib/libresolv2_joy/common/bsd/setitimer.c new file mode 100644 index 0000000000..67881d7ca8 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/setitimer.c @@ -0,0 +1,29 @@ +#ifndef LINT +static const char rcsid[] = "$Id: setitimer.c,v 1.2 2005/04/27 04:56:12 sra Exp $"; +#endif + +#include "port_before.h" + +#include <sys/time.h> + +#include "port_after.h" + +/*% + * Setitimer emulation routine. + */ +#ifndef NEED_SETITIMER +int __bindcompat_setitimer; +#else + +int +__setitimer(int which, const struct itimerval *value, + struct itimerval *ovalue) +{ + if (alarm(value->it_value.tv_sec) >= 0) + return (0); + else + return (-1); +} +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/strcasecmp.c b/usr/src/lib/libresolv2_joy/common/bsd/strcasecmp.c new file mode 100644 index 0000000000..0c9f0dccf0 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/strcasecmp.c @@ -0,0 +1,124 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strcasecmp.c,v 1.2 2005/04/27 04:56:12 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1987, 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. + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/cdefs.h> + +#include <string.h> + +#include "port_after.h" + +#ifndef NEED_STRCASECMP +int __strcasecmp_unneeded__; +#else + +/*% + * This array is designed for mapping upper and lower case letter + * together for a case independent comparison. The mappings are + * based upon ascii character sequences. + */ +static const u_char charmap[] = { + 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, + 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, + 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, + 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, + 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, + 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, + 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, + 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, + 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, + 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, + 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, + 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, + 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, + 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, + 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, + 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, + 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, + 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, + 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, + 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, + 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, + 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, + 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 +}; + +int +strcasecmp(const char *s1, const char *s2) { + const u_char *cm = charmap, + *us1 = (const u_char *)s1, + *us2 = (const u_char *)s2; + + while (cm[*us1] == cm[*us2++]) + if (*us1++ == '\0') + return (0); + return (cm[*us1] - cm[*--us2]); +} + +int +strncasecmp(const char *s1, const char *s2, size_t n) { + if (n != 0) { + const u_char *cm = charmap, + *us1 = (const u_char *)s1, + *us2 = (const u_char *)s2; + + do { + if (cm[*us1] != cm[*us2++]) + return (cm[*us1] - cm[*--us2]); + if (*us1++ == '\0') + break; + } while (--n != 0); + } + return (0); +} + +#endif /*NEED_STRCASECMP*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/strdup.c b/usr/src/lib/libresolv2_joy/common/bsd/strdup.c new file mode 100644 index 0000000000..a8d31e9587 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/strdup.c @@ -0,0 +1,20 @@ +#include "port_before.h" + +#include <stdlib.h> + +#include "port_after.h" + +#ifndef NEED_STRDUP +int __bind_strdup_unneeded; +#else +char * +strdup(const char *src) { + char *dst = malloc(strlen(src) + 1); + + if (dst) + strcpy(dst, src); + return (dst); +} +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/strerror.c b/usr/src/lib/libresolv2_joy/common/bsd/strerror.c new file mode 100644 index 0000000000..5973e63d5b --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/strerror.c @@ -0,0 +1,94 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strerror.c,v 1.6 2008/02/18 03:49:08 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 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. + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/types.h> + +#include <string.h> + +#include "port_after.h" + +#ifndef NEED_STRERROR +int __strerror_unneeded__; +#else + +#ifdef USE_SYSERROR_LIST +extern int sys_nerr; +extern char *sys_errlist[]; +#endif + +const char * +isc_strerror(int num) { +#define UPREFIX "Unknown error: " + static char ebuf[40] = UPREFIX; /*%< 64-bit number + slop */ + u_int errnum; + char *p, *t; +#ifndef USE_SYSERROR_LIST + const char *ret; +#endif + char tmp[40]; + + errnum = num; /*%< convert to unsigned */ +#ifdef USE_SYSERROR_LIST + if (errnum < (u_int)sys_nerr) + return (sys_errlist[errnum]); +#else +#undef strerror + ret = strerror(num); /*%< call strerror() in libc */ + if (ret != NULL) + return(ret); +#endif + + /* Do this by hand, so we don't include stdio(3). */ + t = tmp; + do { + *t++ = "0123456789"[errnum % 10]; + } while (errnum /= 10); + for (p = ebuf + sizeof(UPREFIX) - 1;;) { + *p++ = *--t; + if (t <= tmp) + break; + } + return (ebuf); +} + +#endif /*NEED_STRERROR*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/strpbrk.c b/usr/src/lib/libresolv2_joy/common/bsd/strpbrk.c new file mode 100644 index 0000000000..4c12d88e1c --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/strpbrk.c @@ -0,0 +1,70 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strpbrk.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strpbrk.c,v 1.2 2005/04/27 04:56:12 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * 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. + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/cdefs.h> + +#include <string.h> + +#include "port_after.h" + +#ifndef NEED_STRPBRK +int __strpbrk_unneeded__; +#else + +/*% + * Find the first occurrence in s1 of a character in s2 (excluding NUL). + */ +char * +strpbrk(const char *s1, const char *s2) { + const char *scanp; + int c, sc; + + while ((c = *s1++) != 0) { + for (scanp = s2; (sc = *scanp++) != 0;) + if (sc == c) + return ((char *)(s1 - 1)); + } + return (NULL); +} + +#endif /*NEED_STRPBRK*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/strsep.c b/usr/src/lib/libresolv2_joy/common/bsd/strsep.c new file mode 100644 index 0000000000..c7969f0028 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/strsep.c @@ -0,0 +1,88 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "strsep.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strsep.c,v 1.2 2005/04/27 04:56:12 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1990, 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. + */ + +#include "port_before.h" +#include <sys/cdefs.h> +#include <string.h> +#include <stdio.h> +#include "port_after.h" + +#ifndef NEED_STRSEP +int __strsep_unneeded__; +#else + +/*% + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +char * +strsep(char **stringp, const char *delim) { + char *s; + const char *spanp; + int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} + +#endif /*NEED_STRSEP*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/strtoul.c b/usr/src/lib/libresolv2_joy/common/bsd/strtoul.c new file mode 100644 index 0000000000..b37ff72729 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/strtoul.c @@ -0,0 +1,119 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: strtoul.c,v 1.4 2008/02/18 03:49:08 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Copyright (c) 1990, 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. + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifndef NEED_STRTOUL +int __strtoul_unneeded__; +#else + +/*% + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +u_long +strtoul(const char *nptr, char **endptr, int base) { + const char *s = nptr; + u_long acc, cutoff; + int neg, c, any, cutlim; + + neg = 0; + + /* + * See strtol for comments as to the logic used. + */ + do { + c = *(const unsigned char *)s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (u_long)ULONG_MAX / (u_long)base; + cutlim = (u_long)ULONG_MAX % (u_long)base; + for (acc = 0, any = 0;; c = *(const unsigned char*)s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + DE_CONST((any ? s - 1 : nptr), *endptr); + return (acc); +} + +#endif /*NEED_STRTOUL*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/utimes.c b/usr/src/lib/libresolv2_joy/common/bsd/utimes.c new file mode 100644 index 0000000000..2f65cffe25 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/utimes.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1997,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <utime.h> + +#include "port_after.h" + +#ifndef NEED_UTIMES +int __bind_utimes_unneeded; +#else + +int +__utimes(char *filename, struct timeval *tvp) { + struct utimbuf utb; + + utb.actime = (time_t)tvp[0].tv_sec; + utb.modtime = (time_t)tvp[1].tv_sec; + return (utime(filename, &utb)); +} + +#endif /* NEED_UTIMES */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/bsd/writev.c b/usr/src/lib/libresolv2_joy/common/bsd/writev.c new file mode 100644 index 0000000000..65baa71cfc --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/bsd/writev.c @@ -0,0 +1,89 @@ +#ifndef LINT +static const char rcsid[] = "$Id: writev.c,v 1.3 2005/04/27 04:56:13 sra Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/stat.h> +#include <sys/socket.h> + +#include "port_after.h" + +#ifndef NEED_WRITEV +int __bindcompat_writev; +#else + +#ifdef _CRAY +#define OWN_WRITEV +int +__writev(int fd, struct iovec *iov, int iovlen) +{ + struct stat statbuf; + + if (fstat(fd, &statbuf) < 0) + return (-1); + + /* + * Allow for atomic writes to network. + */ + if (statbuf.st_mode & S_IFSOCK) { + struct msghdr mesg; + + memset(&mesg, 0, sizeof(mesg)); + mesg.msg_name = 0; + mesg.msg_namelen = 0; + mesg.msg_iov = iov; + mesg.msg_iovlen = iovlen; + mesg.msg_accrights = 0; + mesg.msg_accrightslen = 0; + return (sendmsg(fd, &mesg, 0)); + } else { + struct iovec *tv; + int i, rcode = 0, count = 0; + + for (i = 0, tv = iov; i <= iovlen; tv++) { + rcode = write(fd, tv->iov_base, tv->iov_len); + + if (rcode < 0) + break; + + count += rcode; + } + + if (count == 0) + return (rcode); + else + return (count); + } +} + +#else /*_CRAY*/ + +int +__writev(fd, vp, vpcount) + int fd; + const struct iovec *vp; + int vpcount; +{ + int count = 0; + + while (vpcount-- > 0) { + int written = write(fd, vp->iov_base, vp->iov_len); + + if (written < 0) + return (-1); + count += written; + if (written != vp->iov_len) + break; + vp++; + } + return (count); +} + +#endif /*_CRAY*/ + +#endif /*NEED_WRITEV*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/dst/dst_api.c b/usr/src/lib/libresolv2_joy/common/dst/dst_api.c new file mode 100644 index 0000000000..a3e48077ad --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/dst/dst_api.c @@ -0,0 +1,1048 @@ +#ifndef LINT +static const char rcsid[] = "$Header: /proj/cvs/prod/libbind/dst/dst_api.c,v 1.17 2007/09/24 17:18:25 each Exp $"; +#endif + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * 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 TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS 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 THE SOFTWARE. + */ +/* + * This file contains the interface between the DST API and the crypto API. + * This is the only file that needs to be changed if the crypto system is + * changed. Exported functions are: + * void dst_init() Initialize the toolkit + * int dst_check_algorithm() Function to determines if alg is suppored. + * int dst_compare_keys() Function to compare two keys for equality. + * int dst_sign_data() Incremental signing routine. + * int dst_verify_data() Incremental verify routine. + * int dst_generate_key() Function to generate new KEY + * DST_KEY *dst_read_key() Function to retrieve private/public KEY. + * void dst_write_key() Function to write out a key. + * DST_KEY *dst_dnskey_to_key() Function to convert DNS KEY RR to a DST + * KEY structure. + * int dst_key_to_dnskey() Function to return a public key in DNS + * format binary + * DST_KEY *dst_buffer_to_key() Converst a data in buffer to KEY + * int *dst_key_to_buffer() Writes out DST_KEY key matterial in buffer + * void dst_free_key() Releases all memory referenced by key structure + */ + +#include "port_before.h" +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <memory.h> +#include <ctype.h> +#include <time.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include "dst_internal.h" +#include "port_after.h" + +/* static variables */ +static int done_init = 0; +dst_func *dst_t_func[DST_MAX_ALGS]; +const char *key_file_fmt_str = "Private-key-format: v%s\nAlgorithm: %d (%s)\n"; +const char *dst_path = ""; + +/* internal I/O functions */ +static DST_KEY *dst_s_read_public_key(const char *in_name, + const u_int16_t in_id, int in_alg); +static int dst_s_read_private_key_file(char *name, DST_KEY *pk_key, + u_int16_t in_id, int in_alg); +static int dst_s_write_public_key(const DST_KEY *key); +static int dst_s_write_private_key(const DST_KEY *key); + +/* internal function to set up data structure */ +static DST_KEY *dst_s_get_key_struct(const char *name, const int alg, + const int flags, const int protocol, + const int bits); + +/*% + * dst_init + * This function initializes the Digital Signature Toolkit. + * Right now, it just checks the DSTKEYPATH environment variable. + * Parameters + * none + * Returns + * none + */ +void +dst_init() +{ + char *s; + int len; + + if (done_init != 0) + return; + done_init = 1; + + s = getenv("DSTKEYPATH"); + len = 0; + if (s) { + struct stat statbuf; + + len = strlen(s); + if (len > PATH_MAX) { + EREPORT(("%s is longer than %d characters, ignoring\n", + s, PATH_MAX)); + } else if (stat(s, &statbuf) != 0 || !S_ISDIR(statbuf.st_mode)) { + EREPORT(("%s is not a valid directory\n", s)); + } else { + char *tmp; + tmp = (char *) malloc(len + 2); + memcpy(tmp, s, len + 1); + if (tmp[strlen(tmp) - 1] != '/') { + tmp[strlen(tmp) + 1] = 0; + tmp[strlen(tmp)] = '/'; + } + dst_path = tmp; + } + } + memset(dst_t_func, 0, sizeof(dst_t_func)); + /* first one is selected */ + dst_hmac_md5_init(); +} + +/*% + * dst_check_algorithm + * This function determines if the crypto system for the specified + * algorithm is present. + * Parameters + * alg 1 KEY_RSA + * 3 KEY_DSA + * 157 KEY_HMAC_MD5 + * future algorithms TBD and registered with IANA. + * Returns + * 1 - The algorithm is available. + * 0 - The algorithm is not available. + */ +int +dst_check_algorithm(const int alg) +{ + return (dst_t_func[alg] != NULL); +} + +/*% + * dst_s_get_key_struct + * This function allocates key structure and fills in some of the + * fields of the structure. + * Parameters: + * name: the name of the key + * alg: the algorithm number + * flags: the dns flags of the key + * protocol: the dns protocol of the key + * bits: the size of the key + * Returns: + * NULL if error + * valid pointer otherwise + */ +static DST_KEY * +dst_s_get_key_struct(const char *name, const int alg, const int flags, + const int protocol, const int bits) +{ + DST_KEY *new_key = NULL; + + if (dst_check_algorithm(alg)) /*%< make sure alg is available */ + new_key = (DST_KEY *) malloc(sizeof(*new_key)); + if (new_key == NULL) + return (NULL); + + memset(new_key, 0, sizeof(*new_key)); + new_key->dk_key_name = strdup(name); + if (new_key->dk_key_name == NULL) { + free(new_key); + return (NULL); + } + new_key->dk_alg = alg; + new_key->dk_flags = flags; + new_key->dk_proto = protocol; + new_key->dk_KEY_struct = NULL; + new_key->dk_key_size = bits; + new_key->dk_func = dst_t_func[alg]; + return (new_key); +} + +/*% + * dst_compare_keys + * Compares two keys for equality. + * Parameters + * key1, key2 Two keys to be compared. + * Returns + * 0 The keys are equal. + * non-zero The keys are not equal. + */ + +int +dst_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + if (key1 == key2) + return (0); + if (key1 == NULL || key2 == NULL) + return (4); + if (key1->dk_alg != key2->dk_alg) + return (1); + if (key1->dk_key_size != key2->dk_key_size) + return (2); + if (key1->dk_id != key2->dk_id) + return (3); + return (key1->dk_func->compare(key1, key2)); +} + +/*% + * dst_sign_data + * An incremental signing function. Data is signed in steps. + * First the context must be initialized (SIG_MODE_INIT). + * Then data is hashed (SIG_MODE_UPDATE). Finally the signature + * itself is created (SIG_MODE_FINAL). This function can be called + * once with INIT, UPDATE and FINAL modes all set, or it can be + * called separately with a different mode set for each step. The + * UPDATE step can be repeated. + * Parameters + * mode A bit mask used to specify operation(s) to be performed. + * SIG_MODE_INIT 1 Initialize digest + * SIG_MODE_UPDATE 2 Add data to digest + * SIG_MODE_FINAL 4 Generate signature + * from signature + * SIG_MODE_ALL (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL + * data Data to be signed. + * len The length in bytes of data to be signed. + * in_key Contains a private key to sign with. + * KEY structures should be handled (created, converted, + * compared, stored, freed) by the DST. + * signature + * The location to which the signature will be written. + * sig_len Length of the signature field in bytes. + * Return + * 0 Successfull INIT or Update operation + * >0 success FINAL (sign) operation + * <0 failure + */ + +int +dst_sign_data(const int mode, DST_KEY *in_key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + DUMP(data, mode, len, "dst_sign_data()"); + + if (mode & SIG_MODE_FINAL && + (in_key->dk_KEY_struct == NULL || signature == NULL)) + return (MISSING_KEY_OR_SIGNATURE); + + if (in_key->dk_func && in_key->dk_func->sign) + return (in_key->dk_func->sign(mode, in_key, context, data, len, + signature, sig_len)); + return (UNKNOWN_KEYALG); +} + +/*% + * dst_verify_data + * An incremental verify function. Data is verified in steps. + * First the context must be initialized (SIG_MODE_INIT). + * Then data is hashed (SIG_MODE_UPDATE). Finally the signature + * is verified (SIG_MODE_FINAL). This function can be called + * once with INIT, UPDATE and FINAL modes all set, or it can be + * called separately with a different mode set for each step. The + * UPDATE step can be repeated. + * Parameters + * mode Operations to perform this time. + * SIG_MODE_INIT 1 Initialize digest + * SIG_MODE_UPDATE 2 add data to digest + * SIG_MODE_FINAL 4 verify signature + * SIG_MODE_ALL + * (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL) + * data Data to pass through the hash function. + * len Length of the data in bytes. + * in_key Key for verification. + * signature Location of signature. + * sig_len Length of the signature in bytes. + * Returns + * 0 Verify success + * Non-Zero Verify Failure + */ + +int +dst_verify_data(const int mode, DST_KEY *in_key, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + DUMP(data, mode, len, "dst_verify_data()"); + if (mode & SIG_MODE_FINAL && + (in_key->dk_KEY_struct == NULL || signature == NULL)) + return (MISSING_KEY_OR_SIGNATURE); + + if (in_key->dk_func == NULL || in_key->dk_func->verify == NULL) + return (UNSUPPORTED_KEYALG); + return (in_key->dk_func->verify(mode, in_key, context, data, len, + signature, sig_len)); +} + +/*% + * dst_read_private_key + * Access a private key. First the list of private keys that have + * already been read in is searched, then the key accessed on disk. + * If the private key can be found, it is returned. If the key cannot + * be found, a null pointer is returned. The options specify required + * key characteristics. If the private key requested does not have + * these characteristics, it will not be read. + * Parameters + * in_keyname The private key name. + * in_id The id of the private key. + * options DST_FORCE_READ Read from disk - don't use a previously + * read key. + * DST_CAN_SIGN The key must be useable for signing. + * DST_NO_AUTHEN The key must be useable for authentication. + * DST_STANDARD Return any key + * Returns + * NULL If there is no key found in the current directory or + * this key has not been loaded before. + * !NULL Success - KEY structure returned. + */ + +DST_KEY * +dst_read_key(const char *in_keyname, const u_int16_t in_id, + const int in_alg, const int type) +{ + char keyname[PATH_MAX]; + DST_KEY *dg_key = NULL, *pubkey = NULL; + + if (!dst_check_algorithm(in_alg)) { /*%< make sure alg is available */ + EREPORT(("dst_read_private_key(): Algorithm %d not suppored\n", + in_alg)); + return (NULL); + } + if ((type & (DST_PUBLIC | DST_PRIVATE)) == 0) + return (NULL); + if (in_keyname == NULL) { + EREPORT(("dst_read_private_key(): Null key name passed in\n")); + return (NULL); + } else if (strlen(in_keyname) >= sizeof(keyname)) { + EREPORT(("dst_read_private_key(): keyname too big\n")); + return (NULL); + } else + strcpy(keyname, in_keyname); + + /* before I read in the public key, check if it is allowed to sign */ + if ((pubkey = dst_s_read_public_key(keyname, in_id, in_alg)) == NULL) + return (NULL); + + if (type == DST_PUBLIC) + return pubkey; + + if (!(dg_key = dst_s_get_key_struct(keyname, pubkey->dk_alg, + pubkey->dk_flags, pubkey->dk_proto, + 0))) + return (dg_key); + /* Fill in private key and some fields in the general key structure */ + if (dst_s_read_private_key_file(keyname, dg_key, pubkey->dk_id, + pubkey->dk_alg) == 0) + dg_key = dst_free_key(dg_key); + + (void)dst_free_key(pubkey); + return (dg_key); +} + +int +dst_write_key(const DST_KEY *key, const int type) +{ + int pub = 0, priv = 0; + + if (key == NULL) + return (0); + if (!dst_check_algorithm(key->dk_alg)) { /*%< make sure alg is available */ + EREPORT(("dst_write_key(): Algorithm %d not suppored\n", + key->dk_alg)); + return (UNSUPPORTED_KEYALG); + } + if ((type & (DST_PRIVATE|DST_PUBLIC)) == 0) + return (0); + + if (type & DST_PUBLIC) + if ((pub = dst_s_write_public_key(key)) < 0) + return (pub); + if (type & DST_PRIVATE) + if ((priv = dst_s_write_private_key(key)) < 0) + return (priv); + return (priv+pub); +} + +/*% + * dst_write_private_key + * Write a private key to disk. The filename will be of the form: + * K<key->dk_name>+<key->dk_alg+><key-d>k_id.><private key suffix>. + * If there is already a file with this name, an error is returned. + * + * Parameters + * key A DST managed key structure that contains + * all information needed about a key. + * Return + * >= 0 Correct behavior. Returns length of encoded key value + * written to disk. + * < 0 error. + */ + +static int +dst_s_write_private_key(const DST_KEY *key) +{ + u_char encoded_block[RAW_KEY_SIZE]; + char file[PATH_MAX]; + int len; + FILE *fp; + + /* First encode the key into the portable key format */ + if (key == NULL) + return (-1); + if (key->dk_KEY_struct == NULL) + return (0); /*%< null key has no private key */ + if (key->dk_func == NULL || key->dk_func->to_file_fmt == NULL) { + EREPORT(("dst_write_private_key(): Unsupported operation %d\n", + key->dk_alg)); + return (-5); + } else if ((len = key->dk_func->to_file_fmt(key, (char *)encoded_block, + sizeof(encoded_block))) <= 0) { + EREPORT(("dst_write_private_key(): Failed encoding private RSA bsafe key %d\n", len)); + return (-8); + } + /* Now I can create the file I want to use */ + dst_s_build_filename(file, key->dk_key_name, key->dk_id, key->dk_alg, + PRIVATE_KEY, PATH_MAX); + + /* Do not overwrite an existing file */ + if ((fp = dst_s_fopen(file, "w", 0600)) != NULL) { + int nn; + if ((nn = fwrite(encoded_block, 1, len, fp)) != len) { + EREPORT(("dst_write_private_key(): Write failure on %s %d != %d errno=%d\n", + file, len, nn, errno)); + fclose(fp); + return (-5); + } + fclose(fp); + } else { + EREPORT(("dst_write_private_key(): Can not create file %s\n" + ,file)); + return (-6); + } + memset(encoded_block, 0, len); + return (len); +} + +/*% +* + * dst_read_public_key + * Read a public key from disk and store in a DST key structure. + * Parameters + * in_name K<in_name><in_id>.<public key suffix> is the + * filename of the key file to be read. + * Returns + * NULL If the key does not exist or no name is supplied. + * NON-NULL Initialized key structure if the key exists. + */ + +static DST_KEY * +dst_s_read_public_key(const char *in_name, const u_int16_t in_id, int in_alg) +{ + int flags, proto, alg, len, dlen; + int c; + char name[PATH_MAX], enckey[RAW_KEY_SIZE], *notspace; + u_char deckey[RAW_KEY_SIZE]; + FILE *fp; + + if (in_name == NULL) { + EREPORT(("dst_read_public_key(): No key name given\n")); + return (NULL); + } + if (dst_s_build_filename(name, in_name, in_id, in_alg, PUBLIC_KEY, + PATH_MAX) == -1) { + EREPORT(("dst_read_public_key(): Cannot make filename from %s, %d, and %s\n", + in_name, in_id, PUBLIC_KEY)); + return (NULL); + } + /* + * Open the file and read it's formatted contents up to key + * File format: + * domain.name [ttl] [IN] KEY <flags> <protocol> <algorithm> <key> + * flags, proto, alg stored as decimal (or hex numbers FIXME). + * (FIXME: handle parentheses for line continuation.) + */ + if ((fp = dst_s_fopen(name, "r", 0)) == NULL) { + EREPORT(("dst_read_public_key(): Public Key not found %s\n", + name)); + return (NULL); + } + /* Skip domain name, which ends at first blank */ + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + /* Skip blank to get to next field */ + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + + /* Skip optional TTL -- if initial digit, skip whole word. */ + if (isdigit(c)) { + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + } + /* Skip optional "IN" */ + if (c == 'I' || c == 'i') { + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + } + /* Locate and skip "KEY" */ + if (c != 'K' && c != 'k') { + EREPORT(("\"KEY\" doesn't appear in file: %s", name)); + return NULL; + } + while ((c = getc(fp)) != EOF) + if (isspace(c)) + break; + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + ungetc(c, fp); /*%< return the charcter to the input field */ + /* Handle hex!! FIXME. */ + + if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) { + EREPORT(("dst_read_public_key(): Can not read flag/proto/alg field from %s\n" + ,name)); + return (NULL); + } + /* read in the key string */ + fgets(enckey, sizeof(enckey), fp); + + /* If we aren't at end-of-file, something is wrong. */ + while ((c = getc(fp)) != EOF) + if (!isspace(c)) + break; + if (!feof(fp)) { + EREPORT(("Key too long in file: %s", name)); + return NULL; + } + fclose(fp); + + if ((len = strlen(enckey)) <= 0) + return (NULL); + + /* discard \n */ + enckey[--len] = '\0'; + + /* remove leading spaces */ + for (notspace = (char *) enckey; isspace((*notspace)&0xff); len--) + notspace++; + + dlen = b64_pton(notspace, deckey, sizeof(deckey)); + if (dlen < 0) { + EREPORT(("dst_read_public_key: bad return from b64_pton = %d", + dlen)); + return (NULL); + } + /* store key and info in a key structure that is returned */ +/* return dst_store_public_key(in_name, alg, proto, 666, flags, deckey, + dlen);*/ + return dst_buffer_to_key(in_name, alg, flags, proto, deckey, dlen); +} + +/*% + * dst_write_public_key + * Write a key to disk in DNS format. + * Parameters + * key Pointer to a DST key structure. + * Returns + * 0 Failure + * 1 Success + */ + +static int +dst_s_write_public_key(const DST_KEY *key) +{ + FILE *fp; + char filename[PATH_MAX]; + u_char out_key[RAW_KEY_SIZE]; + char enc_key[RAW_KEY_SIZE]; + int len = 0; + int mode; + + memset(out_key, 0, sizeof(out_key)); + if (key == NULL) { + EREPORT(("dst_write_public_key(): No key specified \n")); + return (0); + } else if ((len = dst_key_to_dnskey(key, out_key, sizeof(out_key)))< 0) + return (0); + + /* Make the filename */ + if (dst_s_build_filename(filename, key->dk_key_name, key->dk_id, + key->dk_alg, PUBLIC_KEY, PATH_MAX) == -1) { + EREPORT(("dst_write_public_key(): Cannot make filename from %s, %d, and %s\n", + key->dk_key_name, key->dk_id, PUBLIC_KEY)); + return (0); + } + /* XXX in general this should be a check for symmetric keys */ + mode = (key->dk_alg == KEY_HMAC_MD5) ? 0600 : 0644; + /* create public key file */ + if ((fp = dst_s_fopen(filename, "w+", mode)) == NULL) { + EREPORT(("DST_write_public_key: open of file:%s failed (errno=%d)\n", + filename, errno)); + return (0); + } + /*write out key first base64 the key data */ + if (key->dk_flags & DST_EXTEND_FLAG) + b64_ntop(&out_key[6], len - 6, enc_key, sizeof(enc_key)); + else + b64_ntop(&out_key[4], len - 4, enc_key, sizeof(enc_key)); + fprintf(fp, "%s IN KEY %d %d %d %s\n", + key->dk_key_name, + key->dk_flags, key->dk_proto, key->dk_alg, enc_key); + fclose(fp); + return (1); +} + +/*% + * dst_dnskey_to_public_key + * This function converts the contents of a DNS KEY RR into a DST + * key structure. + * Paramters + * len Length of the RDATA of the KEY RR RDATA + * rdata A pointer to the the KEY RR RDATA. + * in_name Key name to be stored in key structure. + * Returns + * NULL Failure + * NON-NULL Success. Pointer to key structure. + * Caller's responsibility to free() it. + */ + +DST_KEY * +dst_dnskey_to_key(const char *in_name, const u_char *rdata, const int len) +{ + DST_KEY *key_st; + int alg ; + int start = DST_KEY_START; + + if (rdata == NULL || len <= DST_KEY_ALG) /*%< no data */ + return (NULL); + alg = (u_int8_t) rdata[DST_KEY_ALG]; + if (!dst_check_algorithm(alg)) { /*%< make sure alg is available */ + EREPORT(("dst_dnskey_to_key(): Algorithm %d not suppored\n", + alg)); + return (NULL); + } + + if (in_name == NULL) + return (NULL); + + if ((key_st = dst_s_get_key_struct(in_name, alg, 0, 0, 0)) == NULL) + return (NULL); + + key_st->dk_id = dst_s_dns_key_id(rdata, len); + key_st->dk_flags = dst_s_get_int16(rdata); + key_st->dk_proto = (u_int16_t) rdata[DST_KEY_PROT]; + if (key_st->dk_flags & DST_EXTEND_FLAG) { + u_int32_t ext_flags; + ext_flags = (u_int32_t) dst_s_get_int16(&rdata[DST_EXT_FLAG]); + key_st->dk_flags = key_st->dk_flags | (ext_flags << 16); + start += 2; + } + /* + * now point to the begining of the data representing the encoding + * of the key + */ + if (key_st->dk_func && key_st->dk_func->from_dns_key) { + if (key_st->dk_func->from_dns_key(key_st, &rdata[start], + len - start) > 0) + return (key_st); + } else + EREPORT(("dst_dnskey_to_public_key(): unsuppored alg %d\n", + alg)); + + SAFE_FREE(key_st); + return (key_st); +} + +/*% + * dst_public_key_to_dnskey + * Function to encode a public key into DNS KEY wire format + * Parameters + * key Key structure to encode. + * out_storage Location to write the encoded key to. + * out_len Size of the output array. + * Returns + * <0 Failure + * >=0 Number of bytes written to out_storage + */ + +int +dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage, + const int out_len) +{ + u_int16_t val; + int loc = 0; + int enc_len = 0; + if (key == NULL) + return (-1); + + if (!dst_check_algorithm(key->dk_alg)) { /*%< make sure alg is available */ + EREPORT(("dst_key_to_dnskey(): Algorithm %d not suppored\n", + key->dk_alg)); + return (UNSUPPORTED_KEYALG); + } + memset(out_storage, 0, out_len); + val = (u_int16_t)(key->dk_flags & 0xffff); + dst_s_put_int16(out_storage, val); + loc += 2; + + out_storage[loc++] = (u_char) key->dk_proto; + out_storage[loc++] = (u_char) key->dk_alg; + + if (key->dk_flags > 0xffff) { /*%< Extended flags */ + val = (u_int16_t)((key->dk_flags >> 16) & 0xffff); + dst_s_put_int16(&out_storage[loc], val); + loc += 2; + } + if (key->dk_KEY_struct == NULL) + return (loc); + if (key->dk_func && key->dk_func->to_dns_key) { + enc_len = key->dk_func->to_dns_key(key, + (u_char *) &out_storage[loc], + out_len - loc); + if (enc_len > 0) + return (enc_len + loc); + else + return (-1); + } else + EREPORT(("dst_key_to_dnskey(): Unsupported ALG %d\n", + key->dk_alg)); + return (-1); +} + +/*% + * dst_buffer_to_key + * Function to encode a string of raw data into a DST key + * Parameters + * alg The algorithm (HMAC only) + * key A pointer to the data + * keylen The length of the data + * Returns + * NULL an error occurred + * NON-NULL the DST key + */ +DST_KEY * +dst_buffer_to_key(const char *key_name, /*!< name of the key */ + const int alg, /*!< algorithm */ + const int flags, /*!< dns flags */ + const int protocol, /*!< dns protocol */ + const u_char *key_buf, /*!< key in dns wire fmt */ + const int key_len) /*!< size of key */ +{ + + DST_KEY *dkey = NULL; + int dnslen; + u_char dns[2048]; + + if (!dst_check_algorithm(alg)) { /*%< make sure alg is available */ + EREPORT(("dst_buffer_to_key(): Algorithm %d not suppored\n", alg)); + return (NULL); + } + + dkey = dst_s_get_key_struct(key_name, alg, flags, protocol, -1); + + if (dkey == NULL || dkey->dk_func == NULL || + dkey->dk_func->from_dns_key == NULL) + return (dst_free_key(dkey)); + + if (dkey->dk_func->from_dns_key(dkey, key_buf, key_len) < 0) { + EREPORT(("dst_buffer_to_key(): dst_buffer_to_hmac failed\n")); + return (dst_free_key(dkey)); + } + + dnslen = dst_key_to_dnskey(dkey, dns, sizeof(dns)); + dkey->dk_id = dst_s_dns_key_id(dns, dnslen); + return (dkey); +} + +int +dst_key_to_buffer(DST_KEY *key, u_char *out_buff, int buf_len) +{ + int len; + /* this function will extrac the secret of HMAC into a buffer */ + if (key == NULL) + return (0); + if (key->dk_func != NULL && key->dk_func->to_dns_key != NULL) { + len = key->dk_func->to_dns_key(key, out_buff, buf_len); + if (len < 0) + return (0); + return (len); + } + return (0); +} + +/*% + * dst_s_read_private_key_file + * Function reads in private key from a file. + * Fills out the KEY structure. + * Parameters + * name Name of the key to be read. + * pk_key Structure that the key is returned in. + * in_id Key identifier (tag) + * Return + * 1 if everthing works + * 0 if there is any problem + */ + +static int +dst_s_read_private_key_file(char *name, DST_KEY *pk_key, u_int16_t in_id, + int in_alg) +{ + int cnt, alg, len, major, minor, file_major, file_minor; + int ret, id; + char filename[PATH_MAX]; + u_char in_buff[RAW_KEY_SIZE], *p; + FILE *fp; + int dnslen; + u_char dns[2048]; + + if (name == NULL || pk_key == NULL) { + EREPORT(("dst_read_private_key_file(): No key name given\n")); + return (0); + } + /* Make the filename */ + if (dst_s_build_filename(filename, name, in_id, in_alg, PRIVATE_KEY, + PATH_MAX) == -1) { + EREPORT(("dst_read_private_key(): Cannot make filename from %s, %d, and %s\n", + name, in_id, PRIVATE_KEY)); + return (0); + } + /* first check if we can find the key file */ + if ((fp = dst_s_fopen(filename, "r", 0)) == NULL) { + EREPORT(("dst_s_read_private_key_file: Could not open file %s in directory %s\n", + filename, dst_path[0] ? dst_path : + (char *) getcwd(NULL, PATH_MAX - 1))); + return (0); + } + /* now read the header info from the file */ + if ((cnt = fread(in_buff, 1, sizeof(in_buff), fp)) < 5) { + fclose(fp); + EREPORT(("dst_s_read_private_key_file: error reading file %s (empty file)\n", + filename)); + return (0); + } + /* decrypt key */ + fclose(fp); + if (memcmp(in_buff, "Private-key-format: v", 20) != 0) + goto fail; + len = cnt; + p = in_buff; + + if (!dst_s_verify_str((const char **) (void *)&p, + "Private-key-format: v")) { + EREPORT(("dst_s_read_private_key_file(): Not a Key file/Decrypt failed %s\n", name)); + goto fail; + } + /* read in file format */ + sscanf((char *)p, "%d.%d", &file_major, &file_minor); + sscanf(KEY_FILE_FORMAT, "%d.%d", &major, &minor); + if (file_major < 1) { + EREPORT(("dst_s_read_private_key_file(): Unknown keyfile %d.%d version for %s\n", + file_major, file_minor, name)); + goto fail; + } else if (file_major > major || file_minor > minor) + EREPORT(( + "dst_s_read_private_key_file(): Keyfile %s version higher than mine %d.%d MAY FAIL\n", + name, file_major, file_minor)); + + while (*p++ != '\n') ; /*%< skip to end of line */ + + if (!dst_s_verify_str((const char **) (void *)&p, "Algorithm: ")) + goto fail; + + if (sscanf((char *)p, "%d", &alg) != 1) + goto fail; + while (*p++ != '\n') ; /*%< skip to end of line */ + + if (pk_key->dk_key_name && !strcmp(pk_key->dk_key_name, name)) + SAFE_FREE2(pk_key->dk_key_name, strlen(pk_key->dk_key_name)); + pk_key->dk_key_name = (char *) strdup(name); + + /* allocate and fill in key structure */ + if (pk_key->dk_func == NULL || pk_key->dk_func->from_file_fmt == NULL) + goto fail; + + ret = pk_key->dk_func->from_file_fmt(pk_key, (char *)p, &in_buff[len] - p); + if (ret < 0) + goto fail; + + dnslen = dst_key_to_dnskey(pk_key, dns, sizeof(dns)); + id = dst_s_dns_key_id(dns, dnslen); + + /* Make sure the actual key tag matches the input tag used in the filename + */ + if (id != in_id) { + EREPORT(("dst_s_read_private_key_file(): actual tag of key read %d != input tag used to build filename %d.\n", id, in_id)); + goto fail; + } + pk_key->dk_id = (u_int16_t) id; + pk_key->dk_alg = alg; + memset(in_buff, 0, cnt); + return (1); + + fail: + memset(in_buff, 0, cnt); + return (0); +} + +/*% + * Generate and store a public/private keypair. + * Keys will be stored in formatted files. + * + * Parameters + & + *\par name Name of the new key. Used to create key files + *\li K<name>+<alg>+<id>.public and K<name>+<alg>+<id>.private. + *\par bits Size of the new key in bits. + *\par exp What exponent to use: + *\li 0 use exponent 3 + *\li non-zero use Fermant4 + *\par flags The default value of the DNS Key flags. + *\li The DNS Key RR Flag field is defined in RFC2065, + * section 3.3. The field has 16 bits. + *\par protocol + *\li Default value of the DNS Key protocol field. + *\li The DNS Key protocol field is defined in RFC2065, + * section 3.4. The field has 8 bits. + *\par alg What algorithm to use. Currently defined: + *\li KEY_RSA 1 + *\li KEY_DSA 3 + *\li KEY_HMAC 157 + *\par out_id The key tag is returned. + * + * Return + *\li NULL Failure + *\li non-NULL the generated key pair + * Caller frees the result, and its dk_name pointer. + */ +DST_KEY * +dst_generate_key(const char *name, const int bits, const int exp, + const int flags, const int protocol, const int alg) +{ + DST_KEY *new_key = NULL; + int dnslen; + u_char dns[2048]; + + if (name == NULL) + return (NULL); + + if (!dst_check_algorithm(alg)) { /*%< make sure alg is available */ + EREPORT(("dst_generate_key(): Algorithm %d not suppored\n", alg)); + return (NULL); + } + + new_key = dst_s_get_key_struct(name, alg, flags, protocol, bits); + if (new_key == NULL) + return (NULL); + if (bits == 0) /*%< null key we are done */ + return (new_key); + if (new_key->dk_func == NULL || new_key->dk_func->generate == NULL) { + EREPORT(("dst_generate_key_pair():Unsupported algorithm %d\n", + alg)); + return (dst_free_key(new_key)); + } + if (new_key->dk_func->generate(new_key, exp) <= 0) { + EREPORT(("dst_generate_key_pair(): Key generation failure %s %d %d %d\n", + new_key->dk_key_name, new_key->dk_alg, + new_key->dk_key_size, exp)); + return (dst_free_key(new_key)); + } + + dnslen = dst_key_to_dnskey(new_key, dns, sizeof(dns)); + if (dnslen != UNSUPPORTED_KEYALG) + new_key->dk_id = dst_s_dns_key_id(dns, dnslen); + else + new_key->dk_id = 0; + + return (new_key); +} + +/*% + * Release all data structures pointed to by a key structure. + * + * Parameters + *\li f_key Key structure to be freed. + */ + +DST_KEY * +dst_free_key(DST_KEY *f_key) +{ + + if (f_key == NULL) + return (f_key); + if (f_key->dk_func && f_key->dk_func->destroy) + f_key->dk_KEY_struct = + f_key->dk_func->destroy(f_key->dk_KEY_struct); + else { + EREPORT(("dst_free_key(): Unknown key alg %d\n", + f_key->dk_alg)); + } + if (f_key->dk_KEY_struct) { + free(f_key->dk_KEY_struct); + f_key->dk_KEY_struct = NULL; + } + if (f_key->dk_key_name) + SAFE_FREE(f_key->dk_key_name); + SAFE_FREE(f_key); + return (NULL); +} + +/*% + * Return the maximim size of signature from the key specified in bytes + * + * Parameters + *\li key + * + * Returns + * \li bytes + */ +int +dst_sig_size(DST_KEY *key) { + switch (key->dk_alg) { + case KEY_HMAC_MD5: + return (16); + case KEY_HMAC_SHA1: + return (20); + case KEY_RSA: + return (key->dk_key_size + 7) / 8; + case KEY_DSA: + return (40); + default: + EREPORT(("dst_sig_size(): Unknown key alg %d\n", key->dk_alg)); + return -1; + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/dst/dst_internal.h b/usr/src/lib/libresolv2_joy/common/dst/dst_internal.h new file mode 100644 index 0000000000..e9bc6fc08d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/dst/dst_internal.h @@ -0,0 +1,155 @@ +#ifndef DST_INTERNAL_H +#define DST_INTERNAL_H + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * 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 TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS 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 THE SOFTWARE. + */ +#include <limits.h> +#include <sys/param.h> +#if (!defined(BSD)) || (BSD < 199306) +# include <sys/bitypes.h> +#else +# include <sys/types.h> +#endif + +#ifndef PATH_MAX +# ifdef POSIX_PATH_MAX +# define PATH_MAX POSIX_PATH_MAX +# else +# define PATH_MAX 255 /*%< this is the value of POSIX_PATH_MAX */ +# endif +#endif + +typedef struct dst_key { + char *dk_key_name; /*%< name of the key */ + int dk_key_size; /*%< this is the size of the key in bits */ + int dk_proto; /*%< what protocols this key can be used for */ + int dk_alg; /*%< algorithm number from key record */ + u_int32_t dk_flags; /*%< and the flags of the public key */ + u_int16_t dk_id; /*%< identifier of the key */ + void *dk_KEY_struct; /*%< pointer to key in crypto pkg fmt */ + struct dst_func *dk_func; /*%< point to cryptto pgk specific function table */ +} DST_KEY; +#define HAS_DST_KEY + +#include <isc/dst.h> +/* + * define what crypto systems are supported for RSA, + * BSAFE is prefered over RSAREF; only one can be set at any time + */ +#if defined(BSAFE) && defined(RSAREF) +# error "Cannot have both BSAFE and RSAREF defined" +#endif + +/* Declare dst_lib specific constants */ +#define KEY_FILE_FORMAT "1.2" + +/* suffixes for key file names */ +#define PRIVATE_KEY "private" +#define PUBLIC_KEY "key" + +/* error handling */ +#ifdef REPORT_ERRORS +#define EREPORT(str) printf str +#else +#define EREPORT(str) (void)0 +#endif + +/* use our own special macro to FRRE memory */ + +#ifndef SAFE_FREE +#define SAFE_FREE(a) \ +do{if(a != NULL){memset(a,0, sizeof(*a)); free(a); a=NULL;}} while (0) +#define SAFE_FREE2(a,s) if (a != NULL && (long)s > 0){memset(a,0, s);free(a); a=NULL;} +#endif + +typedef struct dst_func { + int (*sign)(const int mode, DST_KEY *key, void **context, + const u_int8_t *data, const int len, + u_int8_t *signature, const int sig_len); + int (*verify)(const int mode, DST_KEY *key, void **context, + const u_int8_t *data, const int len, + const u_int8_t *signature, const int sig_len); + int (*compare)(const DST_KEY *key1, const DST_KEY *key2); + int (*generate)(DST_KEY *key, int parms); + void *(*destroy)(void *key); + /* conversion functions */ + int (*to_dns_key)(const DST_KEY *key, u_int8_t *out, + const int out_len); + int (*from_dns_key)(DST_KEY *key, const u_int8_t *str, + const int str_len); + int (*to_file_fmt)(const DST_KEY *key, char *out, + const int out_len); + int (*from_file_fmt)(DST_KEY *key, const char *out, + const int out_len); + +} dst_func; + +extern dst_func *dst_t_func[DST_MAX_ALGS]; +extern const char *key_file_fmt_str; +extern const char *dst_path; + +#ifndef DST_HASH_SIZE +#define DST_HASH_SIZE 20 /*%< RIPEMD160 and SHA-1 are 20 bytes MD5 is 16 */ +#endif + +int dst_bsafe_init(void); + +int dst_rsaref_init(void); + +int dst_hmac_md5_init(void); + +int dst_cylink_init(void); + +int dst_eay_dss_init(void); + +/* from higher level support routines */ +int dst_s_calculate_bits( const u_int8_t *str, const int max_bits); +int dst_s_verify_str( const char **buf, const char *str); + + +/* conversion between dns names and key file names */ +size_t dst_s_filename_length( const char *name, const char *suffix); +int dst_s_build_filename( char *filename, const char *name, + u_int16_t id, int alg, const char *suffix, + size_t filename_length); + +FILE *dst_s_fopen (const char *filename, const char *mode, int perm); + +/*% + * read and write network byte order into u_int?_t + * all of these should be retired + */ +u_int16_t dst_s_get_int16( const u_int8_t *buf); +void dst_s_put_int16( u_int8_t *buf, const u_int16_t val); + +u_int32_t dst_s_get_int32( const u_int8_t *buf); +void dst_s_put_int32( u_int8_t *buf, const u_int32_t val); + +#ifdef DUMP +# undef DUMP +# define DUMP(a,b,c,d) dst_s_dump(a,b,c,d) +#else +# define DUMP(a,b,c,d) +#endif +void +dst_s_dump(const int mode, const u_char *data, const int size, + const char *msg); + + + +#endif /* DST_INTERNAL_H */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/dst/hmac_link.c b/usr/src/lib/libresolv2_joy/common/dst/hmac_link.c new file mode 100644 index 0000000000..23925e4269 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/dst/hmac_link.c @@ -0,0 +1,491 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#ifdef HMAC_MD5 +#ifndef LINT +static const char rcsid[] = "$Header: /proj/cvs/prod/libbind/dst/hmac_link.c,v 1.8 2007/09/24 17:18:25 each Exp $"; +#endif +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * 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 TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS 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 THE SOFTWARE. + */ + +/*% + * This file contains an implementation of the HMAC-MD5 algorithm. + */ +#include "port_before.h" + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <memory.h> +#include <sys/param.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include "dst_internal.h" + +#ifdef USE_MD5 +# ifndef HAVE_MD5 +# include "md5.h" +# else +# ifdef SOLARIS2 +# include <sys/md5.h> +# endif +# endif +# ifndef _MD5_H_ +# define _MD5_H_ 1 /*%< make sure we do not include rsaref md5.h file */ +# endif +#endif + +#include "port_after.h" + + +#define HMAC_LEN 64 +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5c +#define MD5_LEN 16 + + +typedef struct hmackey { + u_char hk_ipad[64], hk_opad[64]; +} HMAC_Key; + + +/************************************************************************** + * dst_hmac_md5_sign + * Call HMAC signing functions to sign a block of data. + * There are three steps to signing, INIT (initialize structures), + * UPDATE (hash (more) data), FINAL (generate a signature). This + * routine performs one or more of these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * priv_key key to use for signing. + * context the context to be used in this digest + * data data to be signed. + * len length in bytes of data. + * signature location to store signature. + * sig_len size of the signature location + * returns + * N Success on SIG_MODE_FINAL = returns signature length in bytes + * 0 Success on SIG_MODE_INIT and UPDATE + * <0 Failure + */ + +static int +dst_hmac_md5_sign(const int mode, DST_KEY *d_key, void **context, + const u_char *data, const int len, + u_char *signature, const int sig_len) +{ + HMAC_Key *key; + int sign_len = 0; + MD5_CTX *ctx = NULL; + + if (d_key == NULL || d_key->dk_KEY_struct == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + ctx = (MD5_CTX *) malloc(sizeof(*ctx)); + else if (context) + ctx = (MD5_CTX *) *context; + if (ctx == NULL) + return (-1); + + key = (HMAC_Key *) d_key->dk_KEY_struct; + + if (mode & SIG_MODE_INIT) { + MD5Init(ctx); + MD5Update(ctx, key->hk_ipad, HMAC_LEN); + } + + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) + MD5Update(ctx, data, len); + + if (mode & SIG_MODE_FINAL) { + if (signature == NULL || sig_len < MD5_LEN) + return (SIGN_FINAL_FAILURE); + MD5Final(signature, ctx); + + /* perform outer MD5 */ + MD5Init(ctx); + MD5Update(ctx, key->hk_opad, HMAC_LEN); + MD5Update(ctx, signature, MD5_LEN); + MD5Final(signature, ctx); + sign_len = MD5_LEN; + SAFE_FREE(ctx); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (sign_len); +} + + +/************************************************************************** + * dst_hmac_md5_verify() + * Calls HMAC verification routines. There are three steps to + * verification, INIT (initialize structures), UPDATE (hash (more) data), + * FINAL (generate a signature). This routine performs one or more of + * these steps. + * Parameters + * mode SIG_MODE_INIT, SIG_MODE_UPDATE and/or SIG_MODE_FINAL. + * dkey key to use for verify. + * data data signed. + * len length in bytes of data. + * signature signature. + * sig_len length in bytes of signature. + * returns + * 0 Success + * <0 Failure + */ + +static int +dst_hmac_md5_verify(const int mode, DST_KEY *d_key, void **context, + const u_char *data, const int len, + const u_char *signature, const int sig_len) +{ + HMAC_Key *key; + MD5_CTX *ctx = NULL; + + if (d_key == NULL || d_key->dk_KEY_struct == NULL) + return (-1); + + if (mode & SIG_MODE_INIT) + ctx = (MD5_CTX *) malloc(sizeof(*ctx)); + else if (context) + ctx = (MD5_CTX *) *context; + if (ctx == NULL) + return (-1); + + key = (HMAC_Key *) d_key->dk_KEY_struct; + if (mode & SIG_MODE_INIT) { + MD5Init(ctx); + MD5Update(ctx, key->hk_ipad, HMAC_LEN); + } + if ((mode & SIG_MODE_UPDATE) && (data && len > 0)) + MD5Update(ctx, data, len); + + if (mode & SIG_MODE_FINAL) { + u_char digest[MD5_LEN]; + if (signature == NULL || key == NULL || sig_len != MD5_LEN) + return (VERIFY_FINAL_FAILURE); + MD5Final(digest, ctx); + + /* perform outer MD5 */ + MD5Init(ctx); + MD5Update(ctx, key->hk_opad, HMAC_LEN); + MD5Update(ctx, digest, MD5_LEN); + MD5Final(digest, ctx); + + SAFE_FREE(ctx); + if (memcmp(digest, signature, MD5_LEN) != 0) + return (VERIFY_FINAL_FAILURE); + } + else { + if (context == NULL) + return (-1); + *context = (void *) ctx; + } + return (0); +} + + +/************************************************************************** + * dst_buffer_to_hmac_md5 + * Converts key from raw data to an HMAC Key + * This function gets in a pointer to the data + * Parameters + * hkey the HMAC key to be filled in + * key the key in raw format + * keylen the length of the key + * Return + * 0 Success + * <0 Failure + */ +static int +dst_buffer_to_hmac_md5(DST_KEY *dkey, const u_char *key, const int keylen) +{ + int i; + HMAC_Key *hkey = NULL; + MD5_CTX ctx; + int local_keylen = keylen; + u_char tk[MD5_LEN]; + + if (dkey == NULL || key == NULL || keylen < 0) + return (-1); + + if ((hkey = (HMAC_Key *) malloc(sizeof(HMAC_Key))) == NULL) + return (-2); + + memset(hkey->hk_ipad, 0, sizeof(hkey->hk_ipad)); + memset(hkey->hk_opad, 0, sizeof(hkey->hk_opad)); + + /* if key is longer than HMAC_LEN bytes reset it to key=MD5(key) */ + if (keylen > HMAC_LEN) { + MD5Init(&ctx); + MD5Update(&ctx, key, keylen); + MD5Final(tk, &ctx); + memset((void *) &ctx, 0, sizeof(ctx)); + key = tk; + local_keylen = MD5_LEN; + } + /* start out by storing key in pads */ + memcpy(hkey->hk_ipad, key, local_keylen); + memcpy(hkey->hk_opad, key, local_keylen); + + /* XOR key with hk_ipad and opad values */ + for (i = 0; i < HMAC_LEN; i++) { + hkey->hk_ipad[i] ^= HMAC_IPAD; + hkey->hk_opad[i] ^= HMAC_OPAD; + } + dkey->dk_key_size = local_keylen; + dkey->dk_KEY_struct = (void *) hkey; + return (1); +} + + +/************************************************************************** + * dst_hmac_md5_key_to_file_format + * Encodes an HMAC Key into the portable file format. + * Parameters + * hkey HMAC KEY structure + * buff output buffer + * buff_len size of output buffer + * Return + * 0 Failure - null input hkey + * -1 Failure - not enough space in output area + * N Success - Length of data returned in buff + */ + +static int +dst_hmac_md5_key_to_file_format(const DST_KEY *dkey, char *buff, + const int buff_len) +{ + char *bp; + int len, i, key_len; + u_char key[HMAC_LEN]; + HMAC_Key *hkey; + + if (dkey == NULL || dkey->dk_KEY_struct == NULL) + return (0); + /* + * Using snprintf() would be so much simpler here. + */ + if (buff == NULL || + buff_len <= (int)(strlen(key_file_fmt_str) + + strlen(KEY_FILE_FORMAT) + 4)) + return (-1); /*%< no OR not enough space in output area */ + hkey = (HMAC_Key *) dkey->dk_KEY_struct; + memset(buff, 0, buff_len); /*%< just in case */ + /* write file header */ + sprintf(buff, key_file_fmt_str, KEY_FILE_FORMAT, KEY_HMAC_MD5, "HMAC"); + + bp = buff + strlen(buff); + + memset(key, 0, HMAC_LEN); + for (i = 0; i < HMAC_LEN; i++) + key[i] = hkey->hk_ipad[i] ^ HMAC_IPAD; + for (i = HMAC_LEN - 1; i >= 0; i--) + if (key[i] != 0) + break; + key_len = i + 1; + + if (buff_len - (bp - buff) < 6) + return (-1); + strcat(bp, "Key: "); + bp += strlen("Key: "); + + len = b64_ntop(key, key_len, bp, buff_len - (bp - buff)); + if (len < 0) + return (-1); + bp += len; + if (buff_len - (bp - buff) < 2) + return (-1); + *(bp++) = '\n'; + *bp = '\0'; + + return (bp - buff); +} + + +/************************************************************************** + * dst_hmac_md5_key_from_file_format + * Converts contents of a key file into an HMAC key. + * Parameters + * hkey structure to put key into + * buff buffer containing the encoded key + * buff_len the length of the buffer + * Return + * n >= 0 Foot print of the key converted + * n < 0 Error in conversion + */ + +static int +dst_hmac_md5_key_from_file_format(DST_KEY *dkey, const char *buff, + const int buff_len) +{ + const char *p = buff, *eol; + u_char key[HMAC_LEN+1]; /* b64_pton needs more than 64 bytes do decode + * it should probably be fixed rather than doing + * this + */ + u_char *tmp; + int key_len, len; + + if (dkey == NULL) + return (-2); + if (buff == NULL || buff_len < 0) + return (-1); + + memset(key, 0, sizeof(key)); + + if (!dst_s_verify_str(&p, "Key: ")) + return (-3); + + eol = strchr(p, '\n'); + if (eol == NULL) + return (-4); + len = eol - p; + tmp = malloc(len + 2); + if (tmp == NULL) + return (-5); + memcpy(tmp, p, len); + *(tmp + len) = 0x0; + key_len = b64_pton((char *)tmp, key, HMAC_LEN+1); /*%< see above */ + SAFE_FREE2(tmp, len + 2); + + if (dst_buffer_to_hmac_md5(dkey, key, key_len) < 0) { + return (-6); + } + return (0); +} + +/*% + * dst_hmac_md5_to_dns_key() + * function to extract hmac key from DST_KEY structure + * intput: + * in_key: HMAC-MD5 key + * output: + * out_str: buffer to write ot + * out_len: size of output buffer + * returns: + * number of bytes written to output buffer + */ +static int +dst_hmac_md5_to_dns_key(const DST_KEY *in_key, u_char *out_str, + const int out_len) +{ + + HMAC_Key *hkey; + int i; + + if (in_key == NULL || in_key->dk_KEY_struct == NULL || + out_len <= in_key->dk_key_size || out_str == NULL) + return (-1); + + hkey = (HMAC_Key *) in_key->dk_KEY_struct; + for (i = 0; i < in_key->dk_key_size; i++) + out_str[i] = hkey->hk_ipad[i] ^ HMAC_IPAD; + return (i); +} + +/************************************************************************** + * dst_hmac_md5_compare_keys + * Compare two keys for equality. + * Return + * 0 The keys are equal + * NON-ZERO The keys are not equal + */ + +static int +dst_hmac_md5_compare_keys(const DST_KEY *key1, const DST_KEY *key2) +{ + HMAC_Key *hkey1 = (HMAC_Key *) key1->dk_KEY_struct; + HMAC_Key *hkey2 = (HMAC_Key *) key2->dk_KEY_struct; + return memcmp(hkey1->hk_ipad, hkey2->hk_ipad, HMAC_LEN); +} + +/************************************************************************** + * dst_hmac_md5_free_key_structure + * Frees all (none) dynamically allocated structures in hkey + */ + +static void * +dst_hmac_md5_free_key_structure(void *key) +{ + HMAC_Key *hkey = key; + SAFE_FREE(hkey); + return (NULL); +} + + +/*************************************************************************** + * dst_hmac_md5_generate_key + * Creates a HMAC key of size size with a maximum size of 63 bytes + * generating a HMAC key larger than 63 bytes makes no sense as that key + * is digested before use. + */ + +static int +dst_hmac_md5_generate_key(DST_KEY *key, const int nothing) +{ + (void)key; + (void)nothing; + return (-1); +} + +/*% + * dst_hmac_md5_init() Function to answer set up function pointers for HMAC + * related functions + */ +int +dst_hmac_md5_init() +{ + if (dst_t_func[KEY_HMAC_MD5] != NULL) + return (1); + dst_t_func[KEY_HMAC_MD5] = malloc(sizeof(struct dst_func)); + if (dst_t_func[KEY_HMAC_MD5] == NULL) + return (0); + memset(dst_t_func[KEY_HMAC_MD5], 0, sizeof(struct dst_func)); + dst_t_func[KEY_HMAC_MD5]->sign = dst_hmac_md5_sign; + dst_t_func[KEY_HMAC_MD5]->verify = dst_hmac_md5_verify; + dst_t_func[KEY_HMAC_MD5]->compare = dst_hmac_md5_compare_keys; + dst_t_func[KEY_HMAC_MD5]->generate = dst_hmac_md5_generate_key; + dst_t_func[KEY_HMAC_MD5]->destroy = dst_hmac_md5_free_key_structure; + dst_t_func[KEY_HMAC_MD5]->to_dns_key = dst_hmac_md5_to_dns_key; + dst_t_func[KEY_HMAC_MD5]->from_dns_key = dst_buffer_to_hmac_md5; + dst_t_func[KEY_HMAC_MD5]->to_file_fmt = dst_hmac_md5_key_to_file_format; + dst_t_func[KEY_HMAC_MD5]->from_file_fmt = dst_hmac_md5_key_from_file_format; + return (1); +} + +#else +#define dst_hmac_md5_init __dst_hmac_md5_init + +int +dst_hmac_md5_init(){ + return (0); +} +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/dst/support.c b/usr/src/lib/libresolv2_joy/common/dst/support.c new file mode 100644 index 0000000000..8f827667d6 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/dst/support.c @@ -0,0 +1,342 @@ +static const char rcsid[] = "$Header: /proj/cvs/prod/libbind/dst/support.c,v 1.6 2005/10/11 00:10:13 marka Exp $"; + + +/* + * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. + * + * 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 TRUSTED INFORMATION SYSTEMS + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * TRUSTED INFORMATION SYSTEMS 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 THE SOFTWARE. + */ + +#include "port_before.h" + +#include <stdio.h> +#include <unistd.h> +#include <memory.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include "dst_internal.h" + +#include "port_after.h" + +/*% + * dst_s_verify_str() + * Validate that the input string(*str) is at the head of the input + * buffer(**buf). If so, move the buffer head pointer (*buf) to + * the first byte of data following the string(*str). + * Parameters + * buf Input buffer. + * str Input string. + * Return + * 0 *str is not the head of **buff + * 1 *str is the head of **buff, *buf is is advanced to + * the tail of **buf. + */ + +int +dst_s_verify_str(const char **buf, const char *str) +{ + int b, s; + if (*buf == NULL) /*%< error checks */ + return (0); + if (str == NULL || *str == '\0') + return (1); + + b = strlen(*buf); /*%< get length of strings */ + s = strlen(str); + if (s > b || strncmp(*buf, str, s)) /*%< check if same */ + return (0); /*%< not a match */ + (*buf) += s; /*%< advance pointer */ + return (1); +} + +/*% + * dst_s_calculate_bits + * Given a binary number represented in a u_char[], determine + * the number of significant bits used. + * Parameters + * str An input character string containing a binary number. + * max_bits The maximum possible significant bits. + * Return + * N The number of significant bits in str. + */ + +int +dst_s_calculate_bits(const u_char *str, const int max_bits) +{ + const u_char *p = str; + u_char i, j = 0x80; + int bits; + for (bits = max_bits; *p == 0x00 && bits > 0; p++) + bits -= 8; + for (i = *p; (i & j) != j; j >>= 1) + bits--; + return (bits); +} + +/*% + * calculates a checksum used in dst for an id. + * takes an array of bytes and a length. + * returns a 16 bit checksum. + */ +u_int16_t +dst_s_id_calc(const u_char *key, const int keysize) +{ + u_int32_t ac; + const u_char *kp = key; + int size = keysize; + + if (!key || (keysize <= 0)) + return (0xffffU); + + for (ac = 0; size > 1; size -= 2, kp += 2) + ac += ((*kp) << 8) + *(kp + 1); + + if (size > 0) + ac += ((*kp) << 8); + ac += (ac >> 16) & 0xffff; + + return (ac & 0xffff); +} + +/*% + * dst_s_dns_key_id() Function to calculate DNSSEC footprint from KEY record + * rdata + * Input: + * dns_key_rdata: the raw data in wire format + * rdata_len: the size of the input data + * Output: + * the key footprint/id calculated from the key data + */ +u_int16_t +dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len) +{ + if (!dns_key_rdata) + return 0; + + /* compute id */ + if (dns_key_rdata[3] == KEY_RSA) /*%< Algorithm RSA */ + return dst_s_get_int16((const u_char *) + &dns_key_rdata[rdata_len - 3]); + else if (dns_key_rdata[3] == KEY_HMAC_MD5) + /* compatibility */ + return 0; + else + /* compute a checksum on the key part of the key rr */ + return dst_s_id_calc(dns_key_rdata, rdata_len); +} + +/*% + * dst_s_get_int16 + * This routine extracts a 16 bit integer from a two byte character + * string. The character string is assumed to be in network byte + * order and may be unaligned. The number returned is in host order. + * Parameter + * buf A two byte character string. + * Return + * The converted integer value. + */ + +u_int16_t +dst_s_get_int16(const u_char *buf) +{ + register u_int16_t a = 0; + a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1])); + return (a); +} + +/*% + * dst_s_get_int32 + * This routine extracts a 32 bit integer from a four byte character + * string. The character string is assumed to be in network byte + * order and may be unaligned. The number returned is in host order. + * Parameter + * buf A four byte character string. + * Return + * The converted integer value. + */ + +u_int32_t +dst_s_get_int32(const u_char *buf) +{ + register u_int32_t a = 0; + a = ((u_int32_t)(buf[0] << 24)) | ((u_int32_t)(buf[1] << 16)) | + ((u_int32_t)(buf[2] << 8)) | ((u_int32_t)(buf[3])); + return (a); +} + +/*% + * dst_s_put_int16 + * Take a 16 bit integer and store the value in a two byte + * character string. The integer is assumed to be in network + * order and the string is returned in host order. + * + * Parameters + * buf Storage for a two byte character string. + * val 16 bit integer. + */ + +void +dst_s_put_int16(u_int8_t *buf, const u_int16_t val) +{ + buf[0] = (u_int8_t)(val >> 8); + buf[1] = (u_int8_t)(val); +} + +/*% + * dst_s_put_int32 + * Take a 32 bit integer and store the value in a four byte + * character string. The integer is assumed to be in network + * order and the string is returned in host order. + * + * Parameters + * buf Storage for a four byte character string. + * val 32 bit integer. + */ + +void +dst_s_put_int32(u_int8_t *buf, const u_int32_t val) +{ + buf[0] = (u_int8_t)(val >> 24); + buf[1] = (u_int8_t)(val >> 16); + buf[2] = (u_int8_t)(val >> 8); + buf[3] = (u_int8_t)(val); +} + +/*% + * dst_s_filename_length + * + * This function returns the number of bytes needed to hold the + * filename for a key file. '/', '\' and ':' are not allowed. + * form: K<keyname>+<alg>+<id>.<suffix> + * + * Returns 0 if the filename would contain either '\', '/' or ':' + */ +size_t +dst_s_filename_length(const char *name, const char *suffix) +{ + if (name == NULL) + return (0); + if (strrchr(name, '\\')) + return (0); + if (strrchr(name, '/')) + return (0); + if (strrchr(name, ':')) + return (0); + if (suffix == NULL) + return (0); + if (strrchr(suffix, '\\')) + return (0); + if (strrchr(suffix, '/')) + return (0); + if (strrchr(suffix, ':')) + return (0); + return (1 + strlen(name) + 6 + strlen(suffix)); +} + +/*% + * dst_s_build_filename () + * Builds a key filename from the key name, it's id, and a + * suffix. '\', '/' and ':' are not allowed. fA filename is of the + * form: K<keyname><id>.<suffix> + * form: K<keyname>+<alg>+<id>.<suffix> + * + * Returns -1 if the conversion fails: + * if the filename would be too long for space allotted + * if the filename would contain a '\', '/' or ':' + * Returns 0 on success + */ + +int +dst_s_build_filename(char *filename, const char *name, u_int16_t id, + int alg, const char *suffix, size_t filename_length) +{ + u_int32_t my_id; + if (filename == NULL) + return (-1); + memset(filename, 0, filename_length); + if (name == NULL) + return (-1); + if (suffix == NULL) + return (-1); + if (filename_length < 1 + strlen(name) + 4 + 6 + 1 + strlen(suffix)) + return (-1); + my_id = id; + sprintf(filename, "K%s+%03d+%05d.%s", name, alg, my_id, + (const char *) suffix); + if (strrchr(filename, '/')) + return (-1); + if (strrchr(filename, '\\')) + return (-1); + if (strrchr(filename, ':')) + return (-1); + return (0); +} + +/*% + * dst_s_fopen () + * Open a file in the dst_path directory. If perm is specified, the + * file is checked for existence first, and not opened if it exists. + * Parameters + * filename File to open + * mode Mode to open the file (passed directly to fopen) + * perm File permission, if creating a new file. + * Returns + * NULL Failure + * NON-NULL (FILE *) of opened file. + */ +FILE * +dst_s_fopen(const char *filename, const char *mode, int perm) +{ + FILE *fp; + char pathname[PATH_MAX]; + + if (strlen(filename) + strlen(dst_path) >= sizeof(pathname)) + return (NULL); + + if (*dst_path != '\0') { + strcpy(pathname, dst_path); + strcat(pathname, filename); + } else + strcpy(pathname, filename); + + fp = fopen(pathname, mode); + if (perm) + chmod(pathname, perm); + return (fp); +} + +void +dst_s_dump(const int mode, const u_char *data, const int size, + const char *msg) +{ + UNUSED(data); + + if (size > 0) { +#ifdef LONG_TEST + static u_char scratch[1000]; + int n ; + n = b64_ntop(data, scratch, size, sizeof(scratch)); + printf("%s: %x %d %s\n", msg, mode, n, scratch); +#else + printf("%s,%x %d\n", msg, mode, size); +#endif + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/inet_cidr_ntop.c b/usr/src/lib/libresolv2_joy/common/inet/inet_cidr_ntop.c new file mode 100644 index 0000000000..bf960a8acc --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/inet_cidr_ntop.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 1.7 2006/10/11 02:18:18 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static char * +inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size); +static char * +inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size); + +/*% + * char * + * inet_cidr_ntop(af, src, bits, dst, size) + * convert network address from network to presentation format. + * "src"'s size is determined from its "af". + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * 192.5.5.1/28 has a nonzero host part, which means it isn't a network + * as called for by inet_net_ntop() but it can be a host address with + * an included netmask. + * author: + * Paul Vixie (ISC), October 1998 + */ +char * +inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) { + switch (af) { + case AF_INET: + return (inet_cidr_ntop_ipv4(src, bits, dst, size)); + case AF_INET6: + return (inet_cidr_ntop_ipv6(src, bits, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } +} + +static int +decoct(const u_char *src, int bytes, char *dst, size_t size) { + char *odst = dst; + char *t; + int b; + + for (b = 1; b <= bytes; b++) { + if (size < sizeof "255.") + return (0); + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b != bytes) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + return (dst - odst); +} + +/*% + * static char * + * inet_cidr_ntop_ipv4(src, bits, dst, size) + * convert IPv4 network address from network to presentation format. + * "src"'s size is determined from its "af". + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), October 1998 + */ +static char * +inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) { + char *odst = dst; + size_t len = 4; + size_t b; + size_t bytes; + + if ((bits < -1) || (bits > 32)) { + errno = EINVAL; + return (NULL); + } + + /* Find number of significant bytes in address. */ + if (bits == -1) + len = 4; + else + for (len = 1, b = 1 ; b < 4U; b++) + if (*(src + b)) + len = b + 1; + + /* Format whole octets plus nonzero trailing octets. */ + bytes = (((bits <= 0) ? 1 : bits) + 7) / 8; + if (len > bytes) + bytes = len; + b = decoct(src, bytes, dst, size); + if (b == 0U) + goto emsgsize; + dst += b; + size -= b; + + if (bits != -1) { + /* Format CIDR /width. */ + if (size < sizeof "/32") + goto emsgsize; + dst += SPRINTF((dst, "/%u", bits)); + } + + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} + +static char * +inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) { + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"]; + char *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + if ((bits < -1) || (bits > 128)) { + errno = EINVAL; + return (NULL); + } + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + best.len = 0; + cur.base = -1; + cur.len = 0; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && (best.len == 6 || + (best.len == 7 && words[7] != 0x0001) || + (best.len == 5 && words[5] == 0xffff))) { + int n; + + if (src[15] || bits == -1 || bits > 120) + n = 4; + else if (src[14] || bits > 112) + n = 3; + else + n = 2; + n = decoct(src+12, n, tp, sizeof tmp - (tp - tmp)); + if (n == 0) { + errno = EMSGSIZE; + return (NULL); + } + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%x", words[i])); + } + + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp = '\0'; + + if (bits != -1) + tp += SPRINTF((tp, "/%u", bits)); + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = EMSGSIZE; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/inet_cidr_pton.c b/usr/src/lib/libresolv2_joy/common/inet/inet_cidr_pton.c new file mode 100644 index 0000000000..07652af463 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/inet_cidr_pton.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_cidr_pton.c,v 1.6 2005/04/27 04:56:19 sra Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <isc/assertions.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static int inet_cidr_pton_ipv4 __P((const char *src, u_char *dst, + int *bits, int ipv6)); +static int inet_cidr_pton_ipv6 __P((const char *src, u_char *dst, + int *bits)); + +static int getbits(const char *, int ipv6); + +/*% + * int + * inet_cidr_pton(af, src, dst, *bits) + * convert network address from presentation to network format. + * accepts inet_pton()'s input for this "af" plus trailing "/CIDR". + * "dst" is assumed large enough for its "af". "bits" is set to the + * /CIDR prefix length, which can have defaults (like /32 for IPv4). + * return: + * -1 if an error occurred (inspect errno; ENOENT means bad format). + * 0 if successful conversion occurred. + * note: + * 192.5.5.1/28 has a nonzero host part, which means it isn't a network + * as called for by inet_net_pton() but it can be a host address with + * an included netmask. + * author: + * Paul Vixie (ISC), October 1998 + */ +int +inet_cidr_pton(int af, const char *src, void *dst, int *bits) { + switch (af) { + case AF_INET: + return (inet_cidr_pton_ipv4(src, dst, bits, 0)); + case AF_INET6: + return (inet_cidr_pton_ipv6(src, dst, bits)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} + +static const char digits[] = "0123456789"; + +static int +inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits, int ipv6) { + const u_char *odst = dst; + int n, ch, tmp, bits; + size_t size = 4; + + /* Get the mantissa. */ + while (ch = *src++, (isascii(ch) && isdigit(ch))) { + tmp = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + tmp *= 10; + tmp += n; + if (tmp > 255) + goto enoent; + } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); + if (size-- == 0U) + goto emsgsize; + *dst++ = (u_char) tmp; + if (ch == '\0' || ch == '/') + break; + if (ch != '.') + goto enoent; + } + + /* Get the prefix length if any. */ + bits = -1; + if (ch == '/' && dst > odst) { + bits = getbits(src, ipv6); + if (bits == -2) + goto enoent; + } else if (ch != '\0') + goto enoent; + + /* Prefix length can default to /32 only if all four octets spec'd. */ + if (bits == -1) { + if (dst - odst == 4) + bits = ipv6 ? 128 : 32; + else + goto enoent; + } + + /* If nothing was written to the destination, we found no address. */ + if (dst == odst) + goto enoent; + + /* If prefix length overspecifies mantissa, life is bad. */ + if (((bits - (ipv6 ? 96 : 0)) / 8) > (dst - odst)) + goto enoent; + + /* Extend address to four octets. */ + while (size-- > 0U) + *dst++ = 0; + + *pbits = bits; + return (0); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static int +inet_cidr_pton_ipv6(const char *src, u_char *dst, int *pbits) { + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + int bits; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + bits = -1; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } else if (*src == '\0') { + return (0); + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_cidr_pton_ipv4(curtok, tp, &bits, 1) == 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /*%< '\\0' was seen by inet_pton4(). */ + } + if (ch == '/') { + bits = getbits(src, 1); + if (bits == -2) + goto enoent; + break; + } + goto enoent; + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + goto emsgsize; + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + goto enoent; + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + + memcpy(dst, tmp, NS_IN6ADDRSZ); + + *pbits = bits; + return (0); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static int +getbits(const char *src, int ipv6) { + int bits = 0; + char *cp, ch; + + if (*src == '\0') /*%< syntax */ + return (-2); + do { + ch = *src++; + cp = strchr(digits, ch); + if (cp == NULL) /*%< syntax */ + return (-2); + bits *= 10; + bits += cp - digits; + if (bits == 0 && *src != '\0') /*%< no leading zeros */ + return (-2); + if (bits > (ipv6 ? 128 : 32)) /*%< range error */ + return (-2); + } while (*src != '\0'); + + return (bits); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/inet_data.c b/usr/src/lib/libresolv2_joy/common/inet/inet_data.c new file mode 100644 index 0000000000..58b8c4342d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/inet_data.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_data.c,v 1.4 2005/04/27 04:56:19 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" + +const struct in6_addr isc_in6addr_any = IN6ADDR_ANY_INIT; +const struct in6_addr isc_in6addr_loopback = IN6ADDR_LOOPBACK_INIT; + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/inet_lnaof.c b/usr/src/lib/libresolv2_joy/common/inet/inet_lnaof.c new file mode 100644 index 0000000000..70ac409512 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/inet_lnaof.c @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "port_after.h" + +/*% + * Return the local network address portion of an + * internet address; handles class a/b/c network + * number formats. + */ +u_long +inet_lnaof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return ((i)&IN_CLASSA_HOST); + else if (IN_CLASSB(i)) + return ((i)&IN_CLASSB_HOST); + else + return ((i)&IN_CLASSC_HOST); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/inet_makeaddr.c b/usr/src/lib/libresolv2_joy/common/inet/inet_makeaddr.c new file mode 100644 index 0000000000..c56cb3eaeb --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/inet_makeaddr.c @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "port_after.h" + +/*% + * Formulate an Internet address from network + host. Used in + * building addresses stored in the ifnet structure. + */ +struct in_addr +inet_makeaddr(net, host) + u_long net, host; +{ + struct in_addr a; + + if (net < 128U) + a.s_addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); + else if (net < 65536U) + a.s_addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); + else if (net < 16777216L) + a.s_addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); + else + a.s_addr = net | host; + a.s_addr = htonl(a.s_addr); + return (a); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/inet_net_ntop.c b/usr/src/lib/libresolv2_joy/common/inet/inet_net_ntop.c new file mode 100644 index 0000000000..fb28e3cbe5 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/inet_net_ntop.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.5 2006/06/20 02:50:14 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static char * inet_net_ntop_ipv4 __P((const u_char *src, int bits, + char *dst, size_t size)); +static char * inet_net_ntop_ipv6 __P((const u_char *src, int bits, + char *dst, size_t size)); + +/*% + * char * + * inet_net_ntop(af, src, bits, dst, size) + * convert network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_net_ntop(af, src, bits, dst, size) + int af; + const void *src; + int bits; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_net_ntop_ipv4(src, bits, dst, size)); + case AF_INET6: + return (inet_net_ntop_ipv6(src, bits, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } +} + +/*% + * static char * + * inet_net_ntop_ipv4(src, bits, dst, size) + * convert IPv4 network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), July 1996 + */ +static char * +inet_net_ntop_ipv4(src, bits, dst, size) + const u_char *src; + int bits; + char *dst; + size_t size; +{ + char *odst = dst; + char *t; + u_int m; + int b; + + if (bits < 0 || bits > 32) { + errno = EINVAL; + return (NULL); + } + + if (bits == 0) { + if (size < sizeof "0") + goto emsgsize; + *dst++ = '0'; + size--; + *dst = '\0'; + } + + /* Format whole octets. */ + for (b = bits / 8; b > 0; b--) { + if (size <= sizeof "255.") + goto emsgsize; + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b > 1) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + + /* Format partial octet. */ + b = bits % 8; + if (b > 0) { + if (size <= sizeof ".255") + goto emsgsize; + t = dst; + if (dst != odst) + *dst++ = '.'; + m = ((1 << b) - 1) << (8 - b); + dst += SPRINTF((dst, "%u", *src & m)); + size -= (size_t)(dst - t); + } + + /* Format CIDR /width. */ + if (size <= sizeof "/32") + goto emsgsize; + dst += SPRINTF((dst, "/%u", bits)); + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} + +/*% + * static char * + * inet_net_ntop_ipv6(src, bits, fakebits, dst, size) + * convert IPv6 network number from network to presentation format. + * generates CIDR style result always. Picks the shortest representation + * unless the IP is really IPv4. + * always prints specified number of bits (bits). + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0x11110000 in its fourth octet. + * author: + * Vadim Kogan (UCB), June 2001 + * Original version (IPv4) by Paul Vixie (ISC), July 1996 + */ + +static char * +inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) { + u_int m; + int b; + int p; + int zero_s, zero_l, tmp_zero_s, tmp_zero_l; + int i; + int is_ipv4 = 0; + unsigned char inbuf[16]; + char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")]; + char *cp; + int words; + u_char *s; + + if (bits < 0 || bits > 128) { + errno = EINVAL; + return (NULL); + } + + cp = outbuf; + + if (bits == 0) { + *cp++ = ':'; + *cp++ = ':'; + *cp = '\0'; + } else { + /* Copy src to private buffer. Zero host part. */ + p = (bits + 7) / 8; + memcpy(inbuf, src, p); + memset(inbuf + p, 0, 16 - p); + b = bits % 8; + if (b != 0) { + m = ~0 << (8 - b); + inbuf[p-1] &= m; + } + + s = inbuf; + + /* how many words need to be displayed in output */ + words = (bits + 15) / 16; + if (words == 1) + words = 2; + + /* Find the longest substring of zero's */ + zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0; + for (i = 0; i < (words * 2); i += 2) { + if ((s[i] | s[i+1]) == 0) { + if (tmp_zero_l == 0) + tmp_zero_s = i / 2; + tmp_zero_l++; + } else { + if (tmp_zero_l && zero_l < tmp_zero_l) { + zero_s = tmp_zero_s; + zero_l = tmp_zero_l; + tmp_zero_l = 0; + } + } + } + + if (tmp_zero_l && zero_l < tmp_zero_l) { + zero_s = tmp_zero_s; + zero_l = tmp_zero_l; + } + + if (zero_l != words && zero_s == 0 && ((zero_l == 6) || + ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) || + ((zero_l == 7 && s[14] != 0 && s[15] != 1))))) + is_ipv4 = 1; + + /* Format whole words. */ + for (p = 0; p < words; p++) { + if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) { + /* Time to skip some zeros */ + if (p == zero_s) + *cp++ = ':'; + if (p == words - 1) + *cp++ = ':'; + s++; + s++; + continue; + } + + if (is_ipv4 && p > 5 ) { + *cp++ = (p == 6) ? ':' : '.'; + cp += SPRINTF((cp, "%u", *s++)); + /* we can potentially drop the last octet */ + if (p != 7 || bits > 120) { + *cp++ = '.'; + cp += SPRINTF((cp, "%u", *s++)); + } + } else { + if (cp != outbuf) + *cp++ = ':'; + cp += SPRINTF((cp, "%x", *s * 256 + s[1])); + s += 2; + } + } + } + /* Format CIDR /width. */ + sprintf(cp, "/%u", bits); + if (strlen(outbuf) + 1 > size) + goto emsgsize; + strcpy(dst, outbuf); + + return (dst); + +emsgsize: + errno = EMSGSIZE; + return (NULL); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/inet_net_pton.c b/usr/src/lib/libresolv2_joy/common/inet/inet_net_pton.c new file mode 100644 index 0000000000..8d8bfb1f64 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/inet_net_pton.c @@ -0,0 +1,407 @@ +/* + * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1996, 1998, 1999, 2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_net_pton.c,v 1.10 2008/11/14 02:36:51 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <isc/assertions.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/*% + * static int + * inet_net_pton_ipv4(src, dst, size) + * convert IPv4 network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not an IPv4 network specification. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +static int +inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) { + static const char xdigits[] = "0123456789abcdef"; + static const char digits[] = "0123456789"; + int n, ch, tmp = 0, dirty, bits; + const u_char *odst = dst; + + ch = *src++; + if (ch == '0' && (src[0] == 'x' || src[0] == 'X') + && isascii((unsigned char)(src[1])) + && isxdigit((unsigned char)(src[1]))) { + /* Hexadecimal: Eat nybble string. */ + if (size <= 0U) + goto emsgsize; + dirty = 0; + src++; /*%< skip x or X. */ + while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) { + if (isupper(ch)) + ch = tolower(ch); + n = strchr(xdigits, ch) - xdigits; + INSIST(n >= 0 && n <= 15); + if (dirty == 0) + tmp = n; + else + tmp = (tmp << 4) | n; + if (++dirty == 2) { + if (size-- <= 0U) + goto emsgsize; + *dst++ = (u_char) tmp; + dirty = 0; + } + } + if (dirty) { /*%< Odd trailing nybble? */ + if (size-- <= 0U) + goto emsgsize; + *dst++ = (u_char) (tmp << 4); + } + } else if (isascii(ch) && isdigit(ch)) { + /* Decimal: eat dotted digit string. */ + for (;;) { + tmp = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + tmp *= 10; + tmp += n; + if (tmp > 255) + goto enoent; + } while ((ch = *src++) != '\0' && + isascii(ch) && isdigit(ch)); + if (size-- <= 0U) + goto emsgsize; + *dst++ = (u_char) tmp; + if (ch == '\0' || ch == '/') + break; + if (ch != '.') + goto enoent; + ch = *src++; + if (!isascii(ch) || !isdigit(ch)) + goto enoent; + } + } else + goto enoent; + + bits = -1; + if (ch == '/' && isascii((unsigned char)(src[0])) && + isdigit((unsigned char)(src[0])) && dst > odst) { + /* CIDR width specifier. Nothing can follow it. */ + ch = *src++; /*%< Skip over the /. */ + bits = 0; + do { + n = strchr(digits, ch) - digits; + INSIST(n >= 0 && n <= 9); + bits *= 10; + bits += n; + if (bits > 32) + goto enoent; + } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch)); + if (ch != '\0') + goto enoent; + } + + /* Firey death and destruction unless we prefetched EOS. */ + if (ch != '\0') + goto enoent; + + /* If nothing was written to the destination, we found no address. */ + if (dst == odst) + goto enoent; + /* If no CIDR spec was given, infer width from net class. */ + if (bits == -1) { + if (*odst >= 240) /*%< Class E */ + bits = 32; + else if (*odst >= 224) /*%< Class D */ + bits = 8; + else if (*odst >= 192) /*%< Class C */ + bits = 24; + else if (*odst >= 128) /*%< Class B */ + bits = 16; + else /*%< Class A */ + bits = 8; + /* If imputed mask is narrower than specified octets, widen. */ + if (bits < ((dst - odst) * 8)) + bits = (dst - odst) * 8; + /* + * If there are no additional bits specified for a class D + * address adjust bits to 4. + */ + if (bits == 8 && *odst == 224) + bits = 4; + } + /* Extend network to cover the actual mask. */ + while (bits > ((dst - odst) * 8)) { + if (size-- <= 0U) + goto emsgsize; + *dst++ = '\0'; + } + return (bits); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static int +getbits(const char *src, int *bitsp) { + static const char digits[] = "0123456789"; + int n; + int val; + char ch; + + val = 0; + n = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if (pch != NULL) { + if (n++ != 0 && val == 0) /*%< no leading zeros */ + return (0); + val *= 10; + val += (pch - digits); + if (val > 128) /*%< range */ + return (0); + continue; + } + return (0); + } + if (n == 0) + return (0); + *bitsp = val; + return (1); +} + +static int +getv4(const char *src, u_char *dst, int *bitsp) { + static const char digits[] = "0123456789"; + u_char *odst = dst; + int n; + u_int val; + char ch; + + val = 0; + n = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + pch = strchr(digits, ch); + if (pch != NULL) { + if (n++ != 0 && val == 0) /*%< no leading zeros */ + return (0); + val *= 10; + val += (pch - digits); + if (val > 255) /*%< range */ + return (0); + continue; + } + if (ch == '.' || ch == '/') { + if (dst - odst > 3) /*%< too many octets? */ + return (0); + *dst++ = val; + if (ch == '/') + return (getbits(src, bitsp)); + val = 0; + n = 0; + continue; + } + return (0); + } + if (n == 0) + return (0); + if (dst - odst > 3) /*%< too many octets? */ + return (0); + *dst++ = val; + return (1); +} + +static int +inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) { + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + int digits; + int bits; + size_t bytes; + int words; + int ipv4; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + goto enoent; + curtok = src; + saw_xdigit = 0; + val = 0; + digits = 0; + bits = -1; + ipv4 = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (++digits > 4) + goto enoent; + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + goto enoent; + colonp = tp; + continue; + } else if (*src == '\0') + goto enoent; + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + digits = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + getv4(curtok, tp, &bits) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + ipv4 = 1; + break; /*%< '\\0' was seen by inet_pton4(). */ + } + if (ch == '/' && getbits(src, &bits) > 0) + break; + goto enoent; + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + goto enoent; + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (bits == -1) + bits = 128; + + words = (bits + 15) / 16; + if (words < 2) + words = 2; + if (ipv4) + words = 8; + endp = tmp + 2 * words; + + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + goto enoent; + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + goto enoent; + + bytes = (bits + 7) / 8; + if (bytes > size) + goto emsgsize; + memcpy(dst, tmp, bytes); + return (bits); + + enoent: + errno = ENOENT; + return (-1); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +/*% + * int + * inet_net_pton(af, src, dst, size) + * convert network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not a valid network specification. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +inet_net_pton(int af, const char *src, void *dst, size_t size) { + switch (af) { + case AF_INET: + return (inet_net_pton_ipv4(src, dst, size)); + case AF_INET6: + return (inet_net_pton_ipv6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (-1); + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/inet_neta.c b/usr/src/lib/libresolv2_joy/common/inet/inet_neta.c new file mode 100644 index 0000000000..63a6c201a4 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/inet_neta.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: inet_neta.c,v 1.3 2005/04/27 04:56:20 sra Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/*% + * char * + * inet_neta(src, dst, size) + * format a u_long network number into presentation format. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * format of ``src'' is as for inet_network(). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_neta(src, dst, size) + u_long src; + char *dst; + size_t size; +{ + char *odst = dst; + char *tp; + + while (src & 0xffffffff) { + u_char b = (src & 0xff000000) >> 24; + + src <<= 8; + if (b) { + if (size < sizeof "255.") + goto emsgsize; + tp = dst; + dst += SPRINTF((dst, "%u", b)); + if (src != 0L) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - tp); + } + } + if (dst == odst) { + if (size < sizeof "0.0.0.0") + goto emsgsize; + strcpy(dst, "0.0.0.0"); + } + return (odst); + + emsgsize: + errno = EMSGSIZE; + return (NULL); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/inet_netof.c b/usr/src/lib/libresolv2_joy/common/inet/inet_netof.c new file mode 100644 index 0000000000..c228e3d818 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/inet_netof.c @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "port_after.h" + +/*% + * Return the network number from an internet + * address; handles class a/b/c network #'s. + */ +u_long +inet_netof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); + else if (IN_CLASSB(i)) + return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); + else + return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/inet_network.c b/usr/src/lib/libresolv2_joy/common/inet/inet_network.c new file mode 100644 index 0000000000..47976cff68 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/inet_network.c @@ -0,0 +1,106 @@ +/* + * 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ctype.h> + +#include "port_after.h" + +/*% + * Internet network address interpretation routine. + * The library routines call this routine to interpret + * network numbers. + */ +u_long +inet_network(cp) + register const char *cp; +{ + register u_long val, base, n, i; + register char c; + u_long parts[4], *pp = parts; + int digit; + +again: + val = 0; base = 10; digit = 0; + if (*cp == '0') + digit = 1, base = 8, cp++; + if (*cp == 'x' || *cp == 'X') + base = 16, cp++; + while ((c = *cp) != 0) { + if (isdigit((unsigned char)c)) { + if (base == 8U && (c == '8' || c == '9')) + return (INADDR_NONE); + val = (val * base) + (c - '0'); + cp++; + digit = 1; + continue; + } + if (base == 16U && isxdigit((unsigned char)c)) { + val = (val << 4) + + (c + 10 - (islower((unsigned char)c) ? 'a' : 'A')); + cp++; + digit = 1; + continue; + } + break; + } + if (!digit) + return (INADDR_NONE); + if (pp >= parts + 4 || val > 0xffU) + return (INADDR_NONE); + if (*cp == '.') { + *pp++ = val, cp++; + goto again; + } + if (*cp && !isspace(*cp&0xff)) + return (INADDR_NONE); + *pp++ = val; + n = pp - parts; + if (n > 4U) + return (INADDR_NONE); + for (val = 0, i = 0; i < n; i++) { + val <<= 8; + val |= parts[i] & 0xff; + } + return (val); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/inet/nsap_addr.c b/usr/src/lib/libresolv2_joy/common/inet/nsap_addr.c new file mode 100644 index 0000000000..a9972e6e32 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/inet/nsap_addr.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nsap_addr.c,v 1.5 2005/07/28 06:51:48 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <resolv_joy.h> +#include <resolv_mt.h> + +#include "port_after.h" + +static char +xtob(int c) { + return (c - (((c >= '0') && (c <= '9')) ? '0' : '7')); +} + +u_int +inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) { + u_char c, nib; + u_int len = 0; + + if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X')) + return (0); + ascii += 2; + + while ((c = *ascii++) != '\0' && len < (u_int)maxlen) { + if (c == '.' || c == '+' || c == '/') + continue; + if (!isascii(c)) + return (0); + if (islower(c)) + c = toupper(c); + if (isxdigit(c)) { + nib = xtob(c); + c = *ascii++; + if (c != '\0') { + c = toupper(c); + if (isxdigit(c)) { + *binary++ = (nib << 4) | xtob(c); + len++; + } else + return (0); + } + else + return (0); + } + else + return (0); + } + return (len); +} + +char * +inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) { + int nib; + int i; + char *tmpbuf = inet_nsap_ntoa_tmpbuf; + char *start; + + if (ascii) + start = ascii; + else { + ascii = tmpbuf; + start = tmpbuf; + } + + *ascii++ = '0'; + *ascii++ = 'x'; + + if (binlen > 255) + binlen = 255; + + for (i = 0; i < binlen; i++) { + nib = *binary >> 4; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + nib = *binary++ & 0x0f; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + if (((i % 2) == 0 && (i + 1) < binlen)) + *ascii++ = '.'; + } + *ascii = '\0'; + return (start); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/dns.c b/usr/src/lib/libresolv2_joy/common/irs/dns.c new file mode 100644 index 0000000000..7c50320ae7 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/dns.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns.c,v 1.5 2006/03/09 23:57:56 marka Exp $"; +#endif + +/*! \file + * \brief + * dns.c --- this is the top-level accessor function for the dns + */ + +#include "port_before.h" + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <resolv_joy.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* forward */ + +static void dns_close(struct irs_acc *); +static struct __res_state * dns_res_get(struct irs_acc *); +static void dns_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* public */ + +struct irs_acc * +irs_dns_acc(const char *options) { + struct irs_acc *acc; + struct dns_p *dns; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(dns = memget(sizeof *dns))) { + errno = ENOMEM; + memput(acc, sizeof *acc); + return (NULL); + } + memset(dns, 0x5e, sizeof *dns); + dns->res = NULL; + dns->free_res = NULL; + if (hesiod_init(&dns->hes_ctx) < 0) { + /* + * We allow the dns accessor class to initialize + * despite hesiod failing to initialize correctly, + * since dns host queries don't depend on hesiod. + */ + dns->hes_ctx = NULL; + } + acc->private = dns; +#ifdef WANT_IRS_GR + acc->gr_map = irs_dns_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_dns_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_dns_sv; + acc->pr_map = irs_dns_pr; + acc->ho_map = irs_dns_ho; + acc->nw_map = irs_dns_nw; + acc->ng_map = irs_nul_ng; + acc->res_get = dns_res_get; + acc->res_set = dns_res_set; + acc->close = dns_close; + return (acc); +} + +/* methods */ +static struct __res_state * +dns_res_get(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + + if (dns->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + dns_res_set(this, res, free); + } + + if ((dns->res->options & RES_INIT) == 0U && + res_ninit(dns->res) < 0) + return (NULL); + + return (dns->res); +} + +static void +dns_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct dns_p *dns = (struct dns_p *)this->private; + + if (dns->res && dns->free_res) { + res_nclose(dns->res); + (*dns->free_res)(dns->res); + } + dns->res = res; + dns->free_res = free_res; +} + +static void +dns_close(struct irs_acc *this) { + struct dns_p *dns; + + dns = (struct dns_p *)this->private; + if (dns->res && dns->free_res) + (*dns->free_res)(dns->res); + if (dns->hes_ctx) + hesiod_end(dns->hes_ctx); + memput(dns, sizeof *dns); + memput(this, sizeof *this); +} + diff --git a/usr/src/lib/libresolv2_joy/common/irs/dns_ho.c b/usr/src/lib/libresolv2_joy/common/irs/dns_ho.c new file mode 100644 index 0000000000..67812717fb --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/dns_ho.c @@ -0,0 +1,1143 @@ +/* + * Portions Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 1996-2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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 (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. + */ + +/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ +/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_ho.c,v 1.23 2008/11/14 02:36:51 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 + +#define MAXPACKET (65535) /*%< Maximum TCP message size */ +#define BOUNDS_CHECK(ptr, count) \ + if ((ptr) + (count) > eom) { \ + had_error++; \ + continue; \ + } else (void)0 + +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +struct dns_res_target { + struct dns_res_target *next; + querybuf qbuf; /*%< query buffer */ + u_char *answer; /*%< buffer to put answer */ + int anslen; /*%< size of answer buffer */ + int qclass, qtype; /*%< class and type of query */ + int action; /*%< condition whether query is really issued */ + char qname[MAXDNAME +1]; /*%< domain name */ +#if 0 + int n; /*%< result length */ +#endif +}; +enum {RESTGT_DOALWAYS, RESTGT_AFTERFAILURE, RESTGT_IGNORE}; +enum {RESQRY_SUCCESS, RESQRY_FAIL}; + +struct pvt { + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES]; + char hostbuf[8*1024]; + u_char host_addr[16]; /*%< IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +typedef union { + int32_t al; + char ac; +} align; + +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 }; +/* Note: the IPv6 loopback address is in the "tunnel" space */ +static const u_char v6local[] = { 0,0, 0,1 }; /*%< last 4 bytes of IPv6 addr */ +/* Forwards. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static void map_v4v6_hostent(struct hostent *hp, char **bp, + char *ep); +static void addrsort(res_state, char **, int); +static struct hostent * gethostans(struct irs_ho *this, + const u_char *ansbuf, int anslen, + const char *qname, int qtype, + int af, int size, + struct addrinfo **ret_aip, + const struct addrinfo *pai); +static int add_hostent(struct pvt *pvt, char *bp, char **hap, + struct addrinfo *ai); +static int init(struct irs_ho *this); + +/* Exports. */ + +struct irs_ho * +irs_dns_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp = NULL; + int n, size; + char tmp[NS_MAXDNAME]; + const char *cp; + struct addrinfo ai; + struct dns_res_target *q, *p; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + q = memget(sizeof(*q)); + if (q == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = ENOMEM; + goto cleanup; + } + memset(q, 0, sizeof(*q)); + + switch (af) { + case AF_INET: + size = INADDRSZ; + q->qclass = C_IN; + q->qtype = T_A; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + case AF_INET6: + size = IN6ADDRSZ; + q->qclass = C_IN; + q->qtype = T_AAAA; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + default: + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + hp = NULL; + goto cleanup; + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_nquery() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, + tmp, sizeof tmp))) + name = cp; + + for (p = q; p; p = p->next) { + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = af; + if ((hp = gethostans(this, p->answer, n, name, p->qtype, + af, size, NULL, + (const struct addrinfo *)&ai)) != NULL) + goto cleanup; /*%< no more loop is necessary */ + querystate = RESQRY_FAIL; + continue; + } + + cleanup: + if (q != NULL) + memput(q, sizeof(*q)); + return(hp); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) +{ + struct pvt *pvt = (struct pvt *)this->private; + const u_char *uaddr = addr; + char *qp; + struct hostent *hp = NULL; + struct addrinfo ai; + struct dns_res_target *q, *q2, *p; + int n, size, i; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + q = memget(sizeof(*q)); + q2 = memget(sizeof(*q2)); + if (q == NULL || q2 == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = ENOMEM; + goto cleanup; + } + memset(q, 0, sizeof(*q)); + memset(q2, 0, sizeof(*q2)); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + (!memcmp(uaddr, tunnelled, sizeof tunnelled) && + memcmp(&uaddr[sizeof tunnelled], v6local, sizeof(v6local))))) { + /* Unmap. */ + addr = (const char *)addr + sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + q->qclass = C_IN; + q->qtype = T_PTR; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + case AF_INET6: + size = IN6ADDRSZ; + q->qclass = C_IN; + q->qtype = T_PTR; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->next = q2; + q->action = RESTGT_DOALWAYS; + q2->qclass = C_IN; + q2->qtype = T_PTR; + q2->answer = q2->qbuf.buf; + q2->anslen = sizeof(q2->qbuf); + if ((pvt->res->options & RES_NO_NIBBLE2) != 0U) + q2->action = RESTGT_IGNORE; + else + q2->action = RESTGT_AFTERFAILURE; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + hp = NULL; + goto cleanup; + } + if (size > len) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + hp = NULL; + goto cleanup; + } + switch (af) { + case AF_INET: + qp = q->qname; + (void) sprintf(qp, "%u.%u.%u.%u.in-addr.arpa", + (uaddr[3] & 0xff), + (uaddr[2] & 0xff), + (uaddr[1] & 0xff), + (uaddr[0] & 0xff)); + break; + case AF_INET6: + if (q->action != RESTGT_IGNORE) { + const char *nibsuff = res_get_nibblesuffix(pvt->res); + qp = q->qname; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + i = SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + if (i != 4) + abort(); + qp += i; + } + if (strlen(q->qname) + strlen(nibsuff) + 1 > + sizeof q->qname) { + errno = ENAMETOOLONG; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + hp = NULL; + goto cleanup; + } + strcpy(qp, nibsuff); /* (checked) */ + } + if (q2->action != RESTGT_IGNORE) { + const char *nibsuff2 = res_get_nibblesuffix2(pvt->res); + qp = q2->qname; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + i = SPRINTF((qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf)); + if (i != 4) + abort(); + qp += i; + } + if (strlen(q2->qname) + strlen(nibsuff2) + 1 > + sizeof q2->qname) { + errno = ENAMETOOLONG; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + hp = NULL; + goto cleanup; + } + strcpy(qp, nibsuff2); /* (checked) */ + } + break; + default: + abort(); + } + + for (p = q; p; p = p->next) { + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nquery(pvt->res, p->qname, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + + memset(&ai, 0, sizeof(ai)); + ai.ai_family = af; + hp = gethostans(this, p->answer, n, p->qname, T_PTR, af, size, + NULL, (const struct addrinfo *)&ai); + if (!hp) { + querystate = RESQRY_FAIL; + continue; + } + + memcpy(pvt->host_addr, addr, len); + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + if (af == AF_INET && (pvt->res->options & RES_USE_INET6)) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + pvt->host.h_addrtype = AF_INET6; + pvt->host.h_length = IN6ADDRSZ; + } + + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + goto cleanup; /*%< no more loop is necessary. */ + } + hp = NULL; /*%< H_ERRNO was set by subroutines */ + cleanup: + if (q != NULL) + memput(q, sizeof(*q)); + if (q2 != NULL) + memput(q2, sizeof(*q2)); + return(hp); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + + UNUSED(this); + + return (NULL); +} + +static void +ho_rewind(struct irs_ho *this) { + + UNUSED(this); + + /* NOOP */ +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +/* XXX */ +extern struct addrinfo *addr2addrinfo __P((const struct addrinfo *, + const char *)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + int n; + char tmp[NS_MAXDNAME]; + const char *cp; + struct dns_res_target *q, *q2, *p; + struct addrinfo sentinel, *cur; + int querystate = RESQRY_FAIL; + + if (init(this) == -1) + return (NULL); + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + q = memget(sizeof(*q)); + q2 = memget(sizeof(*q2)); + if (q == NULL || q2 == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = ENOMEM; + goto cleanup; + } + memset(q, 0, sizeof(*q2)); + memset(q2, 0, sizeof(*q2)); + + switch (pai->ai_family) { + case AF_UNSPEC: + /* prefer IPv6 */ + q->qclass = C_IN; + q->qtype = T_AAAA; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->next = q2; + q->action = RESTGT_DOALWAYS; + q2->qclass = C_IN; + q2->qtype = T_A; + q2->answer = q2->qbuf.buf; + q2->anslen = sizeof(q2->qbuf); + q2->action = RESTGT_DOALWAYS; + break; + case AF_INET: + q->qclass = C_IN; + q->qtype = T_A; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + case AF_INET6: + q->qclass = C_IN; + q->qtype = T_AAAA; + q->answer = q->qbuf.buf; + q->anslen = sizeof(q->qbuf); + q->action = RESTGT_DOALWAYS; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /*%< better error? */ + goto cleanup; + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_nquery() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = res_hostalias(pvt->res, name, + tmp, sizeof tmp))) + name = cp; + + for (p = q; p; p = p->next) { + struct addrinfo *ai; + + switch(p->action) { + case RESTGT_DOALWAYS: + break; + case RESTGT_AFTERFAILURE: + if (querystate == RESQRY_SUCCESS) + continue; + break; + case RESTGT_IGNORE: + continue; + } + + if ((n = res_nsearch(pvt->res, name, p->qclass, p->qtype, + p->answer, p->anslen)) < 0) { + querystate = RESQRY_FAIL; + continue; + } + (void)gethostans(this, p->answer, n, name, p->qtype, + pai->ai_family, /*%< XXX: meaningless */ + 0, &ai, pai); + if (ai) { + querystate = RESQRY_SUCCESS; + cur->ai_next = ai; + while (cur->ai_next) + cur = cur->ai_next; + } else + querystate = RESQRY_FAIL; + } + + cleanup: + if (q != NULL) + memput(q, sizeof(*q)); + if (q2 != NULL) + memput(q2, sizeof(*q2)); + return(sentinel.ai_next); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private. */ + +static struct hostent * +gethostans(struct irs_ho *this, + const u_char *ansbuf, int anslen, const char *qname, int qtype, + int af, int size, /*!< meaningless for addrinfo cases */ + struct addrinfo **ret_aip, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, ancount, qdcount, n, haveanswer, had_error; + int error = NETDB_SUCCESS; + int (*name_ok)(const char *); + const HEADER *hp; + const u_char *eom; + const u_char *eor; + const u_char *cp; + const char *tname; + const char *hname; + char *bp, *ep, **ap, **hap; + char tbuf[MAXDNAME+1]; + struct addrinfo sentinel, *cur, ai; + + if (pai == NULL) abort(); + if (ret_aip != NULL) + *ret_aip = NULL; + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + tname = qname; + eom = ansbuf + 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; + case T_PTR: + name_ok = res_dnok; + break; + default: + abort(); + } + + pvt->host.h_addrtype = af; + pvt->host.h_length = size; + hname = pvt->host.h_name = NULL; + + /* + * Find first satisfactory answer. + */ + if (ansbuf + HFIXEDSZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + hp = (const HEADER *)ansbuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + bp = pvt->hostbuf; + ep = pvt->hostbuf + sizeof(pvt->hostbuf); + cp = ansbuf + HFIXEDSZ; + if (qdcount != 1) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + n = dn_expand(ansbuf, eom, cp, bp, ep - bp); + if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + cp += n + QFIXEDSZ; + if (cp > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { + /* res_nsend() 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) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->host.h_name = bp; + hname = bp; + bp += n; + /* The qname can be abbreviated, but hname is now absolute. */ + qname = pvt->host.h_name; + } + ap = pvt->host_aliases; + *ap = NULL; + pvt->host.h_aliases = pvt->host_aliases; + hap = pvt->h_addr_ptrs; + *hap = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + haveanswer = 0; + had_error = 0; + while (ancount-- > 0 && cp < eom && !had_error) { + n = dn_expand(ansbuf, eom, cp, bp, ep - bp); + if (n < 0 || !maybe_ok(pvt->res, bp, name_ok)) { + had_error++; + continue; + } + cp += n; /*%< name */ + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + type = ns_get16(cp); + cp += INT16SZ; /*%< type */ + class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /*%< class, TTL */ + n = ns_get16(cp); + cp += INT16SZ; /*%< len */ + BOUNDS_CHECK(cp, n); + if (class != C_IN) { + cp += n; + continue; + } + eor = cp + n; + if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && + type == T_CNAME) { + if (haveanswer) { + int level = LOG_CRIT; +#ifdef LOG_SECURITY + level |= LOG_SECURITY; +#endif + syslog(level, + "gethostans: possible attempt to exploit buffer overflow while looking up %s", + *qname ? qname : "."); + } + n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); + if (n < 0 || !maybe_ok(pvt->res, tbuf, name_ok)) { + had_error++; + continue; + } + cp += n; + /* Store alias. */ + if (ap >= &pvt->host_aliases[MAXALIASES-1]) + continue; + *ap++ = bp; + n = strlen(bp) + 1; /*%< for the \\0 */ + bp += n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /*%< for the \\0 */ + if (n > (ep - bp) || n > MAXHOSTNAMELEN) { + had_error++; + continue; + } + strcpy(bp, tbuf); /* (checked) */ + pvt->host.h_name = bp; + hname = bp; + bp += n; + continue; + } + if (qtype == T_PTR && type == T_CNAME) { + n = dn_expand(ansbuf, eor, cp, tbuf, sizeof tbuf); + if (n < 0 || !maybe_dnok(pvt->res, tbuf)) { + had_error++; + continue; + } + cp += n; +#ifdef RES_USE_DNAME + if ((pvt->res->options & RES_USE_DNAME) != 0U) +#endif + { + /* + * We may be able to check this regardless + * of the USE_DNAME bit, but we add the check + * for now since the DNAME support is + * experimental. + */ + if (ns_samename(tname, bp) != 1) + continue; + } + /* Get canonical name. */ + n = strlen(tbuf) + 1; /*%< for the \\0 */ + if (n > (ep - bp)) { + had_error++; + continue; + } + strcpy(bp, tbuf); /* (checked) */ + tname = bp; + bp += n; + continue; + } + if (qtype == T_ANY) { + if (!(type == T_A || type == T_AAAA)) { + cp += n; + continue; + } + } else if (type != qtype) { + cp += n; + continue; + } + switch (type) { + case T_PTR: + if (ret_aip != NULL) { + /* addrinfo never needs T_PTR */ + cp += n; + continue; + } + if (ns_samename(tname, bp) != 1) { + cp += n; + continue; + } + n = dn_expand(ansbuf, eor, cp, bp, ep - bp); + if (n < 0 || !maybe_hnok(pvt->res, bp) || + n >= MAXHOSTNAMELEN) { + had_error++; + break; + } + cp += n; + if (!haveanswer) { + pvt->host.h_name = bp; + hname = bp; + } + else if (ap < &pvt->host_aliases[MAXALIASES-1]) + *ap++ = bp; + else + n = -1; + if (n != -1) { + n = strlen(bp) + 1; /*%< for the \\0 */ + bp += n; + } + break; + case T_A: + case T_AAAA: + if (ns_samename(hname, bp) != 1) { + cp += n; + continue; + } + if (type == T_A && n != INADDRSZ) { + cp += n; + continue; + } + if (type == T_AAAA && n != IN6ADDRSZ) { + cp += n; + continue; + } + + /* make addrinfo. don't overwrite constant PAI */ + ai = *pai; + ai.ai_family = (type == T_AAAA) ? AF_INET6 : AF_INET; + cur->ai_next = addr2addrinfo( + (const struct addrinfo *)&ai, + (const char *)cp); + if (cur->ai_next == NULL) + had_error++; + + if (!haveanswer) { + int nn; + + nn = strlen(bp) + 1; /*%< for the \\0 */ + if (nn >= MAXHOSTNAMELEN) { + cp += n; + had_error++; + continue; + } + pvt->host.h_name = bp; + hname = bp; + bp += nn; + } + /* Ensure alignment. */ + bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & + ~(sizeof(align) - 1)); + /* Avoid overflows. */ + if (bp + n > &pvt->hostbuf[sizeof(pvt->hostbuf) - 1]) { + had_error++; + continue; + } + if (ret_aip) { /*%< need addrinfo. keep it. */ + while (cur->ai_next) + cur = cur->ai_next; + } else if (cur->ai_next) { /*%< need hostent */ + struct addrinfo *aip = cur->ai_next; + + for (aip = cur->ai_next; aip; + aip = aip->ai_next) { + int m; + + m = add_hostent(pvt, bp, hap, aip); + if (m < 0) { + had_error++; + break; + } + if (m == 0) + continue; + if (hap < &pvt->h_addr_ptrs[MAXADDRS]) + hap++; + *hap = NULL; + bp += m; + } + + freeaddrinfo(cur->ai_next); + cur->ai_next = NULL; + } + cp += n; + break; + default: + abort(); + } + if (!had_error) + haveanswer++; + } + if (haveanswer) { + if (ret_aip == NULL) { + *ap = NULL; + *hap = NULL; + + if (pvt->res->nsort && hap != pvt->h_addr_ptrs && + qtype == T_A) + addrsort(pvt->res, pvt->h_addr_ptrs, + hap - pvt->h_addr_ptrs); + if (pvt->host.h_name == NULL) { + n = strlen(qname) + 1; /*%< for the \\0 */ + if (n > (ep - bp) || n >= MAXHOSTNAMELEN) + goto no_recovery; + strcpy(bp, qname); /* (checked) */ + pvt->host.h_name = bp; + bp += n; + } + if (pvt->res->options & RES_USE_INET6) + map_v4v6_hostent(&pvt->host, &bp, ep); + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); + } else { + if ((pai->ai_flags & AI_CANONNAME) != 0) { + if (pvt->host.h_name == NULL) { + sentinel.ai_next->ai_canonname = + strdup(qname); + } + else { + sentinel.ai_next->ai_canonname = + strdup(pvt->host.h_name); + } + } + *ret_aip = sentinel.ai_next; + return(NULL); + } + } + no_recovery: + if (sentinel.ai_next) { + /* this should be impossible, but check it for safety */ + freeaddrinfo(sentinel.ai_next); + } + if (error == NETDB_SUCCESS) + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + else + RES_SET_H_ERRNO(pvt->res, error); + return(NULL); +} + +static int +add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai) +{ + int addrlen; + char *addrp; + const char **tap; + char *obp = bp; + + switch(ai->ai_addr->sa_family) { + case AF_INET6: + addrlen = IN6ADDRSZ; + addrp = (char *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; + break; + case AF_INET: + addrlen = INADDRSZ; + addrp = (char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr; + break; + default: + return(-1); /*%< abort? */ + } + + /* Ensure alignment. */ + bp = (char *)(((u_long)bp + (sizeof(align) - 1)) & + ~(sizeof(align) - 1)); + /* Avoid overflows. */ + if (bp + addrlen > &pvt->hostbuf[sizeof(pvt->hostbuf) - 1]) + return(-1); + if (hap >= &pvt->h_addr_ptrs[MAXADDRS]) + return(0); /*%< fail, but not treat it as an error. */ + /* Suppress duplicates. */ + for (tap = (const char **)pvt->h_addr_ptrs; + *tap != NULL; + tap++) + if (memcmp(*tap, addrp, addrlen) == 0) + break; + if (*tap != NULL) + return (0); + + memcpy(*hap = bp, addrp, addrlen); + return((bp + addrlen) - obp); +} + +static void +map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) { + char **ap; + + if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) + return; + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + for (ap = hp->h_addr_list; *ap; ap++) { + int i = (u_long)*bpp % sizeof(align); + + if (i != 0) + i = sizeof(align) - i; + + if ((ep - *bpp) < (i + IN6ADDRSZ)) { + /* Out of memory. Truncate address list here. */ + *ap = NULL; + return; + } + *bpp += i; + map_v4v6_address(*ap, *bpp); + *ap = *bpp; + *bpp += IN6ADDRSZ; + } +} + +static void +addrsort(res_state statp, char **ap, int num) { + int i, j, needsort = 0, aval[MAXADDRS]; + char **p; + + p = ap; + for (i = 0; i < num; i++, p++) { + for (j = 0 ; (unsigned)j < statp->nsort; j++) + if (statp->sort_list[j].addr.s_addr == + (((struct in_addr *)(*p))->s_addr & + statp->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++; + } +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0U) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} diff --git a/usr/src/lib/libresolv2_joy/common/irs/dns_nw.c b/usr/src/lib/libresolv2_joy/common/irs/dns_nw.c new file mode 100644 index 0000000000..e9acfd39c7 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/dns_nw.c @@ -0,0 +1,591 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_nw.c,v 1.12 2005/04/27 04:56:22 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 + +#define MAXPACKET (64*1024) + +struct pvt { + struct nwent net; + char * ali[MAXALIASES]; + char buf[BUFSIZ+1]; + struct __res_state * res; + void (*free_res)(void *); +}; + +typedef union { + long al; + char ac; +} align; + +enum by_what { by_addr, by_name }; + +/* Forwards. */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static struct nwent * get1101byaddr(struct irs_nw *, u_char *, int); +static struct nwent * get1101byname(struct irs_nw *, const char *); +static struct nwent * get1101answer(struct irs_nw *, + u_char *ansbuf, int anslen, + enum by_what by_what, + int af, const char *name, + const u_char *addr, int addrlen); +static struct nwent * get1101mask(struct irs_nw *this, struct nwent *); +static int make1101inaddr(const u_char *, int, char *, int); +static void normalize_name(char *name); +static int init(struct irs_nw *this); + +/* Exports. */ + +struct irs_nw * +irs_dns_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods. */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + + if (init(this) == -1) + return (NULL); + + switch (af) { + case AF_INET: + return (get1101byname(this, name)); + default: + (void)NULL; + } + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + + if (init(this) == -1) + return (NULL); + + switch (af) { + case AF_INET: + return (get1101byaddr(this, net, len)); + default: + (void)NULL; + } + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = EAFNOSUPPORT; + return (NULL); +} + +static struct nwent * +nw_next(struct irs_nw *this) { + + UNUSED(this); + + return (NULL); +} + +static void +nw_rewind(struct irs_nw *this) { + UNUSED(this); + /* NOOP */ +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +/* Private. */ + +static struct nwent * +get1101byname(struct irs_nw *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + u_char *ansbuf; + int anslen; + struct nwent *result; + + ansbuf = memget(MAXPACKET); + if (ansbuf == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + anslen = res_nsearch(pvt->res, name, C_IN, T_PTR, ansbuf, MAXPACKET); + if (anslen < 0) { + memput(ansbuf, MAXPACKET); + return (NULL); + } + result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_name, + AF_INET, name, NULL, 0)); + memput(ansbuf, MAXPACKET); + return (result); +} + +static struct nwent * +get1101byaddr(struct irs_nw *this, u_char *net, int len) { + struct pvt *pvt = (struct pvt *)this->private; + char qbuf[sizeof "255.255.255.255.in-addr.arpa"]; + struct nwent *result; + u_char *ansbuf; + int anslen; + + if (len < 1 || len > 32) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + if (make1101inaddr(net, len, qbuf, sizeof qbuf) < 0) + return (NULL); + ansbuf = memget(MAXPACKET); + if (ansbuf == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + anslen = res_nquery(pvt->res, qbuf, C_IN, T_PTR, ansbuf, MAXPACKET); + if (anslen < 0) { + memput(ansbuf, MAXPACKET); + return (NULL); + } + result = get1101mask(this, get1101answer(this, ansbuf, anslen, by_addr, + AF_INET, NULL, net, len)); + memput(ansbuf, MAXPACKET); + return (result); +} + +static struct nwent * +get1101answer(struct irs_nw *this, + u_char *ansbuf, int anslen, enum by_what by_what, + int af, const char *name, const u_char *addr, int addrlen) +{ + struct pvt *pvt = (struct pvt *)this->private; + int type, class, ancount, qdcount, haveanswer; + char *bp, *ep, **ap; + u_char *cp, *eom; + HEADER *hp; + + /* Initialize, and parse header. */ + eom = ansbuf + anslen; + if (ansbuf + HFIXEDSZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + hp = (HEADER *)ansbuf; + cp = ansbuf + HFIXEDSZ; + qdcount = ntohs(hp->qdcount); + while (qdcount-- > 0) { + int n = dn_skipname(cp, eom); + cp += n + QFIXEDSZ; + if (n < 0 || cp > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + } + ancount = ntohs(hp->ancount); + if (!ancount) { + if (hp->aa) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + else + RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); + return (NULL); + } + + /* Prepare a return structure. */ + bp = pvt->buf; + ep = pvt->buf + sizeof(pvt->buf); + pvt->net.n_name = NULL; + pvt->net.n_aliases = pvt->ali; + pvt->net.n_addrtype = af; + pvt->net.n_addr = NULL; + pvt->net.n_length = addrlen; + + /* Save input key if given. */ + switch (by_what) { + case by_name: + if (name != NULL) { + int n = strlen(name) + 1; + + if (n > (ep - bp)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->net.n_name = strcpy(bp, name); /* (checked) */ + bp += n; + } + break; + case by_addr: + if (addr != NULL && addrlen != 0) { + int n = addrlen / 8 + ((addrlen % 8) != 0); + + if (INADDRSZ > (ep - bp)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + memset(bp, 0, INADDRSZ); + memcpy(bp, addr, n); + pvt->net.n_addr = bp; + bp += INADDRSZ; + } + break; + default: + abort(); + } + + /* Parse the answer, collect aliases. */ + ap = pvt->ali; + haveanswer = 0; + while (--ancount >= 0 && cp < eom) { + int n = dn_expand(ansbuf, eom, cp, bp, ep - bp); + + cp += n; /*%< Owner */ + if (n < 0 || !maybe_dnok(pvt->res, bp) || + cp + 3 * INT16SZ + INT32SZ > eom) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + GETSHORT(type, cp); /*%< Type */ + GETSHORT(class, cp); /*%< Class */ + cp += INT32SZ; /*%< TTL */ + GETSHORT(n, cp); /*%< RDLENGTH */ + if (class == C_IN && type == T_PTR) { + int nn; + + nn = dn_expand(ansbuf, eom, cp, bp, ep - bp); + if (nn < 0 || !maybe_hnok(pvt->res, bp) || nn != n) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + normalize_name(bp); + switch (by_what) { + case by_addr: { + if (pvt->net.n_name == NULL) + pvt->net.n_name = bp; + else if (ns_samename(pvt->net.n_name, bp) == 1) + break; + else + *ap++ = bp; + nn = strlen(bp) + 1; + bp += nn; + haveanswer++; + break; + } + case by_name: { + u_int b1, b2, b3, b4; + + if (pvt->net.n_addr != NULL || + sscanf(bp, "%u.%u.%u.%u.in-addr.arpa", + &b1, &b2, &b3, &b4) != 4) + break; + if ((ep - bp) < INADDRSZ) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + return (NULL); + } + pvt->net.n_addr = bp; + *bp++ = b4; + *bp++ = b3; + *bp++ = b2; + *bp++ = b1; + pvt->net.n_length = INADDRSZ * 8; + haveanswer++; + } + } + } + cp += n; /*%< RDATA */ + } + if (!haveanswer) { + RES_SET_H_ERRNO(pvt->res, TRY_AGAIN); + return (NULL); + } + *ap = NULL; + + return (&pvt->net); +} + +static struct nwent * +get1101mask(struct irs_nw *this, struct nwent *nwent) { + struct pvt *pvt = (struct pvt *)this->private; + char qbuf[sizeof "255.255.255.255.in-addr.arpa"], owner[MAXDNAME]; + int anslen, type, class, ancount, qdcount; + u_char *ansbuf, *cp, *eom; + HEADER *hp; + + if (!nwent) + return (NULL); + if (make1101inaddr(nwent->n_addr, nwent->n_length, qbuf, sizeof qbuf) + < 0) { + /* "First, do no harm." */ + return (nwent); + } + + ansbuf = memget(MAXPACKET); + if (ansbuf == NULL) { + errno = ENOMEM; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + /* Query for the A RR that would hold this network's mask. */ + anslen = res_nquery(pvt->res, qbuf, C_IN, T_A, ansbuf, MAXPACKET); + if (anslen < HFIXEDSZ) { + memput(ansbuf, MAXPACKET); + return (nwent); + } + + /* Initialize, and parse header. */ + hp = (HEADER *)ansbuf; + cp = ansbuf + HFIXEDSZ; + eom = ansbuf + anslen; + qdcount = ntohs(hp->qdcount); + while (qdcount-- > 0) { + int n = dn_skipname(cp, eom); + cp += n + QFIXEDSZ; + if (n < 0 || cp > eom) { + memput(ansbuf, MAXPACKET); + return (nwent); + } + } + ancount = ntohs(hp->ancount); + + /* Parse the answer, collect aliases. */ + while (--ancount >= 0 && cp < eom) { + int n = dn_expand(ansbuf, eom, cp, owner, sizeof owner); + + if (n < 0 || !maybe_dnok(pvt->res, owner)) + break; + cp += n; /*%< Owner */ + if (cp + 3 * INT16SZ + INT32SZ > eom) + break; + GETSHORT(type, cp); /*%< Type */ + GETSHORT(class, cp); /*%< Class */ + cp += INT32SZ; /*%< TTL */ + GETSHORT(n, cp); /*%< RDLENGTH */ + if (cp + n > eom) + break; + if (n == INADDRSZ && class == C_IN && type == T_A && + ns_samename(qbuf, owner) == 1) { + /* This A RR indicates the actual netmask. */ + int nn, mm; + + nwent->n_length = 0; + for (nn = 0; nn < INADDRSZ; nn++) + for (mm = 7; mm >= 0; mm--) + if (cp[nn] & (1 << mm)) + nwent->n_length++; + else + break; + } + cp += n; /*%< RDATA */ + } + memput(ansbuf, MAXPACKET); + return (nwent); +} + +static int +make1101inaddr(const u_char *net, int bits, char *name, int size) { + int n, m; + char *ep; + + ep = name + size; + + /* Zero fill any whole bytes left out of the prefix. */ + for (n = (32 - bits) / 8; n > 0; n--) { + if (ep - name < (int)(sizeof "0.")) + goto emsgsize; + m = SPRINTF((name, "0.")); + name += m; + } + + /* Format the partial byte, if any, within the prefix. */ + if ((n = bits % 8) != 0) { + if (ep - name < (int)(sizeof "255.")) + goto emsgsize; + m = SPRINTF((name, "%u.", + net[bits / 8] & ~((1 << (8 - n)) - 1))); + name += m; + } + + /* Format the whole bytes within the prefix. */ + for (n = bits / 8; n > 0; n--) { + if (ep - name < (int)(sizeof "255.")) + goto emsgsize; + m = SPRINTF((name, "%u.", net[n - 1])); + name += m; + } + + /* Add the static text. */ + if (ep - name < (int)(sizeof "in-addr.arpa")) + goto emsgsize; + (void) SPRINTF((name, "in-addr.arpa")); + return (0); + + emsgsize: + errno = EMSGSIZE; + return (-1); +} + +static void +normalize_name(char *name) { + char *t; + + /* Make lower case. */ + for (t = name; *t; t++) + if (isascii((unsigned char)*t) && isupper((unsigned char)*t)) + *t = tolower((*t)&0xff); + + /* Remove trailing dots. */ + while (t > name && t[-1] == '.') + *--t = '\0'; +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0U) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/dns_p.h b/usr/src/lib/libresolv2_joy/common/irs/dns_p.h new file mode 100644 index 0000000000..d85ae2a238 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/dns_p.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: dns_p.h,v 1.4 2005/04/27 04:56:22 sra Exp $ + */ + +#ifndef _DNS_P_H_INCLUDED +#define _DNS_P_H_INCLUDED + +#define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \ + (ok)(nm) != 0) +#define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok) +#define maybe_dnok(res, dn) maybe_ok((res), (dn), res_dnok) + +/*% + * Object state. + */ +struct dns_p { + void *hes_ctx; + struct __res_state *res; + void (*free_res) __P((void *)); +}; + +/* + * Methods. + */ + +extern struct irs_gr * irs_dns_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_dns_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_dns_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_dns_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_dns_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_dns_nw __P((struct irs_acc *)); + +#endif /*_DNS_P_H_INCLUDED*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/dns_pr.c b/usr/src/lib/libresolv2_joy/common/irs/dns_pr.c new file mode 100644 index 0000000000..c281be432c --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/dns_pr.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_pr.c,v 1.5 2005/04/27 04:56:22 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Types. */ + +struct pvt { + struct dns_p * dns; + struct protoent proto; + char * prbuf; +}; + +/* Forward. */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static struct protoent * pr_next(struct irs_pr *); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); +static struct __res_state * pr_res_get(struct irs_pr *); +static void pr_res_set(struct irs_pr *, + struct __res_state *, + void (*)(void *)); + +static struct protoent * parse_hes_list(struct irs_pr *, char **); + +/* Public. */ + +struct irs_pr * +irs_dns_pr(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct pvt *pvt; + struct irs_pr *pr; + + if (!dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(pr = memget(sizeof *pr))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + pvt->dns = dns; + pr->private = pvt; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->close = pr_close; + pr->minimize = pr_minimize; + pr->res_get = pr_res_get; + pr->res_set = pr_res_set; + return (pr); +} + +/* Methods. */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->proto.p_aliases) + free(pvt->proto.p_aliases); + if (pvt->prbuf) + free(pvt->prbuf); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct protoent *proto; + char **hes_list; + + if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "protocol"))) + return (NULL); + + proto = parse_hes_list(this, hes_list); + hesiod_free_list(dns->hes_ctx, hes_list); + return (proto); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int num) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct protoent *proto; + char numstr[16]; + char **hes_list; + + sprintf(numstr, "%d", num); + if (!(hes_list = hesiod_resolve(dns->hes_ctx, numstr, "protonum"))) + return (NULL); + + proto = parse_hes_list(this, hes_list); + hesiod_free_list(dns->hes_ctx, hes_list); + return (proto); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +pr_rewind(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +static void +pr_minimize(struct irs_pr *this) { + UNUSED(this); + /* NOOP */ +} + +static struct __res_state * +pr_res_get(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +pr_res_set(struct irs_pr *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} + +/* Private. */ + +static struct protoent * +parse_hes_list(struct irs_pr *this, char **hes_list) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **cpp, **new; + int num = 0; + int max = 0; + + for (cpp = hes_list; *cpp; cpp++) { + cp = *cpp; + + /* Strip away comments, if any. */ + if ((p = strchr(cp, '#'))) + *p = 0; + + /* Skip blank lines. */ + p = cp; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + continue; + + /* OK, we've got a live one. Let's parse it for real. */ + if (pvt->prbuf) + free(pvt->prbuf); + pvt->prbuf = strdup(cp); + + p = pvt->prbuf; + pvt->proto.p_name = p; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->proto.p_proto = atoi(p); + while (*p && !isspace((unsigned char)*p)) + p++; + if (*p) + *p++ = '\0'; + + while (*p) { + if ((num + 1) >= max || !pvt->proto.p_aliases) { + max += 10; + new = realloc(pvt->proto.p_aliases, + max * sizeof(char *)); + if (!new) { + errno = ENOMEM; + goto cleanup; + } + pvt->proto.p_aliases = new; + } + pvt->proto.p_aliases[num++] = p; + while (*p && !isspace((unsigned char)*p)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->proto.p_aliases) + pvt->proto.p_aliases = malloc(sizeof(char *)); + if (!pvt->proto.p_aliases) + goto cleanup; + pvt->proto.p_aliases[num] = NULL; + return (&pvt->proto); + } + + cleanup: + if (pvt->proto.p_aliases) { + free(pvt->proto.p_aliases); + pvt->proto.p_aliases = NULL; + } + if (pvt->prbuf) { + free(pvt->prbuf); + pvt->prbuf = NULL; + } + return (NULL); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/dns_sv.c b/usr/src/lib/libresolv2_joy/common/irs/dns_sv.c new file mode 100644 index 0000000000..1001dc1051 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/dns_sv.c @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: dns_sv.c,v 1.5 2005/04/27 04:56:23 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Definitions */ + +struct pvt { + struct dns_p * dns; + struct servent serv; + char * svbuf; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward. */ + +static void sv_close(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, + const char *, const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static struct servent * sv_next(struct irs_sv *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +#ifdef SV_RES_SETGET +static struct __res_state * sv_res_get(struct irs_sv *); +static void sv_res_set(struct irs_sv *, + struct __res_state *, + void (*)(void *)); +#endif + +static struct servent * parse_hes_list(struct irs_sv *, + char **, const char *); + +/* Public */ + +struct irs_sv * +irs_dns_sv(struct irs_acc *this) { + struct dns_p *dns = (struct dns_p *)this->private; + struct irs_sv *sv; + struct pvt *pvt; + + if (!dns || !dns->hes_ctx) { + errno = ENODEV; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->dns = dns; + if (!(sv = memget(sizeof *sv))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + sv->private = pvt; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->next = sv_next; + sv->rewind = sv_rewind; + sv->close = sv_close; + sv->minimize = sv_minimize; +#ifdef SV_RES_SETGET + sv->res_get = sv_res_get; + sv->res_set = sv_res_set; +#else + sv->res_get = NULL; /*%< sv_res_get; */ + sv->res_set = NULL; /*%< sv_res_set; */ +#endif + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->serv.s_aliases) + free(pvt->serv.s_aliases); + if (pvt->svbuf) + free(pvt->svbuf); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct servent *s; + char **hes_list; + + if (!(hes_list = hesiod_resolve(dns->hes_ctx, name, "service"))) + return (NULL); + + s = parse_hes_list(this, hes_list, proto); + hesiod_free_list(dns->hes_ctx, hes_list); + return (s); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + struct servent *s; + char portstr[16]; + char **hes_list; + + sprintf(portstr, "%d", ntohs(port)); + if (!(hes_list = hesiod_resolve(dns->hes_ctx, portstr, "port"))) + return (NULL); + + s = parse_hes_list(this, hes_list, proto); + hesiod_free_list(dns->hes_ctx, hes_list); + return (s); +} + +static struct servent * +sv_next(struct irs_sv *this) { + UNUSED(this); + errno = ENODEV; + return (NULL); +} + +static void +sv_rewind(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +/* Private */ + +static struct servent * +parse_hes_list(struct irs_sv *this, char **hes_list, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **cpp, **new; + int proto_len; + int num = 0; + int max = 0; + + for (cpp = hes_list; *cpp; cpp++) { + cp = *cpp; + + /* Strip away comments, if any. */ + if ((p = strchr(cp, '#'))) + *p = 0; + + /* Check to make sure the protocol matches. */ + p = cp; + while (*p && !isspace((unsigned char)*p)) + p++; + if (!*p) + continue; + if (proto) { + proto_len = strlen(proto); + if (strncasecmp(++p, proto, proto_len) != 0) + continue; + if (p[proto_len] && !isspace(p[proto_len]&0xff)) + continue; + } + /* OK, we've got a live one. Let's parse it for real. */ + if (pvt->svbuf) + free(pvt->svbuf); + pvt->svbuf = strdup(cp); + + p = pvt->svbuf; + pvt->serv.s_name = p; + while (*p && !isspace(*p&0xff)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_proto = p; + while (*p && !isspace(*p&0xff)) + p++; + if (!*p) + continue; + *p++ = '\0'; + + pvt->serv.s_port = htons((u_short) atoi(p)); + while (*p && !isspace(*p&0xff)) + p++; + if (*p) + *p++ = '\0'; + + while (*p) { + if ((num + 1) >= max || !pvt->serv.s_aliases) { + max += 10; + new = realloc(pvt->serv.s_aliases, + max * sizeof(char *)); + if (!new) { + errno = ENOMEM; + goto cleanup; + } + pvt->serv.s_aliases = new; + } + pvt->serv.s_aliases[num++] = p; + while (*p && !isspace(*p&0xff)) + p++; + if (*p) + *p++ = '\0'; + } + if (!pvt->serv.s_aliases) + pvt->serv.s_aliases = malloc(sizeof(char *)); + if (!pvt->serv.s_aliases) + goto cleanup; + pvt->serv.s_aliases[num] = NULL; + return (&pvt->serv); + } + + cleanup: + if (pvt->serv.s_aliases) { + free(pvt->serv.s_aliases); + pvt->serv.s_aliases = NULL; + } + if (pvt->svbuf) { + free(pvt->svbuf); + pvt->svbuf = NULL; + } + return (NULL); +} + +static void +sv_minimize(struct irs_sv *this) { + UNUSED(this); + /* NOOP */ +} + +#ifdef SV_RES_SETGET +static struct __res_state * +sv_res_get(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + return (__hesiod_res_get(dns->hes_ctx)); +} + +static void +sv_res_set(struct irs_sv *this, struct __res_state * res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct dns_p *dns = pvt->dns; + + __hesiod_res_set(dns->hes_ctx, res, free_res); +} +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/gai_strerror.c b/usr/src/lib/libresolv2_joy/common/irs/gai_strerror.c new file mode 100644 index 0000000000..9ca1c4bfe1 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/gai_strerror.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2001 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#include <port_before.h> +#include <netdb.h> +#include <port_after.h> + +#ifdef DO_PTHREADS +#include <pthread.h> +#include <stdlib.h> +#endif + +static const char *gai_errlist[] = { + "no error", + "address family not supported for name",/*%< EAI_ADDRFAMILY */ + "temporary failure", /*%< EAI_AGAIN */ + "invalid flags", /*%< EAI_BADFLAGS */ + "permanent failure", /*%< EAI_FAIL */ + "address family not supported", /*%< EAI_FAMILY */ + "memory failure", /*%< EAI_MEMORY */ + "no address", /*%< EAI_NODATA */ + "unknown name or service", /*%< EAI_NONAME */ + "service not supported for socktype", /*%< EAI_SERVICE */ + "socktype not supported", /*%< EAI_SOCKTYPE */ + "system failure", /*%< EAI_SYSTEM */ + "bad hints", /*%< EAI_BADHINTS */ + "bad protocol", /*%< EAI_PROTOCOL */ + "unknown error" /*%< Must be last. */ +}; + +static const int gai_nerr = (sizeof(gai_errlist)/sizeof(*gai_errlist)); + +#define EAI_BUFSIZE 128 + +const char * +gai_strerror(int ecode) { +#ifndef DO_PTHREADS + static char buf[EAI_BUFSIZE]; +#else /* DO_PTHREADS */ +#ifndef LIBBIND_MUTEX_INITIALIZER +#define LIBBIND_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#endif + static pthread_mutex_t lock = LIBBIND_MUTEX_INITIALIZER; + static pthread_key_t key; + static int once = 0; + char *buf; +#endif + + if (ecode >= 0 && ecode < (gai_nerr - 1)) + return (gai_errlist[ecode]); + +#ifdef DO_PTHREADS + if (!once) { + if (pthread_mutex_lock(&lock) != 0) + goto unknown; + if (!once) { + if (pthread_key_create(&key, free) != 0) { + (void)pthread_mutex_unlock(&lock); + goto unknown; + } + once = 1; + } + if (pthread_mutex_unlock(&lock) != 0) + goto unknown; + } + + buf = pthread_getspecific(key); + if (buf == NULL) { + buf = malloc(EAI_BUFSIZE); + if (buf == NULL) + goto unknown; + if (pthread_setspecific(key, buf) != 0) { + free(buf); + goto unknown; + } + } +#endif + /* + * XXX This really should be snprintf(buf, EAI_BUFSIZE, ...). + * It is safe until message catalogs are used. + */ + sprintf(buf, "%s: %d", gai_errlist[gai_nerr - 1], ecode); + return (buf); + +#ifdef DO_PTHREADS + unknown: + return ("unknown error"); +#endif +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/gen.c b/usr/src/lib/libresolv2_joy/common/irs/gen.c new file mode 100644 index 0000000000..7da01f5b09 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/gen.c @@ -0,0 +1,459 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen.c,v 1.7 2005/04/27 04:56:23 sra Exp $"; +#endif + +/*! \file + * \brief + * this is the top level dispatcher + * + * The dispatcher is implemented as an accessor class; it is an + * accessor class that calls other accessor classes, as controlled by a + * configuration file. + * + * A big difference between this accessor class and others is that the + * map class initializers are NULL, and the map classes are already + * filled in with method functions that will do the right thing. + */ + +/* Imports */ + +#include "port_before.h" + +#include <isc/assertions.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +#ifdef SUNW_HOSTS_FALLBACK +extern int __res_no_hosts_fallback(void); +#endif /* SUNW_HOSTS_FALLBACK */ + +/* Definitions */ + +struct nameval { + const char * name; + int val; +}; + +static const struct nameval acc_names[irs_nacc+1] = { + { "local", irs_lcl }, + { "dns", irs_dns }, + { "nis", irs_nis }, + { "irp", irs_irp }, + { NULL, irs_nacc } +}; + +typedef struct irs_acc *(*accinit) __P((const char *options)); + +static const accinit accs[irs_nacc+1] = { + irs_lcl_acc, + irs_dns_acc, +#ifdef WANT_IRS_NIS + irs_nis_acc, +#else + NULL, +#endif + irs_irp_acc, + NULL +}; + +static const struct nameval map_names[irs_nmap+1] = { + { "group", irs_gr }, + { "passwd", irs_pw }, + { "services", irs_sv }, + { "protocols", irs_pr }, + { "hosts", irs_ho }, + { "networks", irs_nw }, + { "netgroup", irs_ng }, + { NULL, irs_nmap } +}; + +static const struct nameval option_names[] = { + { "merge", IRS_MERGE }, + { "continue", IRS_CONTINUE }, + { NULL, 0 } +}; + +/* Forward */ + +static void gen_close(struct irs_acc *); +static struct __res_state * gen_res_get(struct irs_acc *); +static void gen_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); +static int find_name(const char *, const struct nameval nv[]); +static void init_map_rules(struct gen_p *, const char *conf_file); +static struct irs_rule *release_rule(struct irs_rule *); +static int add_rule(struct gen_p *, + enum irs_map_id, enum irs_acc_id, + const char *); + +/* Public */ + +struct irs_acc * +irs_gen_acc(const char *options, const char *conf_file) { + struct irs_acc *acc; + struct gen_p *irs; + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(irs = memget(sizeof *irs))) { + errno = ENOMEM; + memput(acc, sizeof *acc); + return (NULL); + } + memset(irs, 0x5e, sizeof *irs); + irs->options = strdup(options); + irs->res = NULL; + irs->free_res = NULL; + memset(irs->accessors, 0, sizeof irs->accessors); + memset(irs->map_rules, 0, sizeof irs->map_rules); + init_map_rules(irs, conf_file); + acc->private = irs; +#ifdef WANT_IRS_GR + acc->gr_map = irs_gen_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_gen_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_gen_sv; + acc->pr_map = irs_gen_pr; + acc->ho_map = irs_gen_ho; + acc->nw_map = irs_gen_nw; + acc->ng_map = irs_gen_ng; + acc->res_get = gen_res_get; + acc->res_set = gen_res_set; + acc->close = gen_close; + return (acc); +} + +/* Methods */ + +static struct __res_state * +gen_res_get(struct irs_acc *this) { + struct gen_p *irs = (struct gen_p *)this->private; + + if (irs->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + gen_res_set(this, res, free); + } + + if (((irs->res->options & RES_INIT) == 0U) && res_ninit(irs->res) < 0) + return (NULL); + + return (irs->res); +} + +static void +gen_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct gen_p *irs = (struct gen_p *)this->private; +#if 0 + struct irs_rule *rule; + struct irs_ho *ho; + struct irs_nw *nw; +#endif + + if (irs->res && irs->free_res) { + res_nclose(irs->res); + (*irs->free_res)(irs->res); + } + + irs->res = res; + irs->free_res = free_res; + +#if 0 + for (rule = irs->map_rules[irs_ho]; rule; rule = rule->next) { + ho = rule->inst->ho; + + (*ho->res_set)(ho, res, NULL); + } + for (rule = irs->map_rules[irs_nw]; rule; rule = rule->next) { + nw = rule->inst->nw; + + (*nw->res_set)(nw, res, NULL); + } +#endif +} + +static void +gen_close(struct irs_acc *this) { + struct gen_p *irs = (struct gen_p *)this->private; + int n; + + /* Search rules. */ + for (n = 0; n < irs_nmap; n++) + while (irs->map_rules[n] != NULL) + irs->map_rules[n] = release_rule(irs->map_rules[n]); + + /* Access methods. */ + for (n = 0; n < irs_nacc; n++) { + /* Map objects. */ + if (irs->accessors[n].gr != NULL) + (*irs->accessors[n].gr->close)(irs->accessors[n].gr); + if (irs->accessors[n].pw != NULL) + (*irs->accessors[n].pw->close)(irs->accessors[n].pw); + if (irs->accessors[n].sv != NULL) + (*irs->accessors[n].sv->close)(irs->accessors[n].sv); + if (irs->accessors[n].pr != NULL) + (*irs->accessors[n].pr->close)(irs->accessors[n].pr); + if (irs->accessors[n].ho != NULL) + (*irs->accessors[n].ho->close)(irs->accessors[n].ho); + if (irs->accessors[n].nw != NULL) + (*irs->accessors[n].nw->close)(irs->accessors[n].nw); + if (irs->accessors[n].ng != NULL) + (*irs->accessors[n].ng->close)(irs->accessors[n].ng); + /* Enclosing accessor. */ + if (irs->accessors[n].acc != NULL) + (*irs->accessors[n].acc->close)(irs->accessors[n].acc); + } + + /* The options string was strdup'd. */ + free((void*)irs->options); + + if (irs->res && irs->free_res) + (*irs->free_res)(irs->res); + + /* The private data container. */ + memput(irs, sizeof *irs); + + /* The object. */ + memput(this, sizeof *this); +} + +/* Private */ + +static int +find_name(const char *name, const struct nameval names[]) { + int n; + + for (n = 0; names[n].name != NULL; n++) + if (strcmp(name, names[n].name) == 0) + return (names[n].val); + return (-1); +} + +static struct irs_rule * +release_rule(struct irs_rule *rule) { + struct irs_rule *next = rule->next; + + memput(rule, sizeof *rule); + return (next); +} + +static int +add_rule(struct gen_p *irs, + enum irs_map_id map, enum irs_acc_id acc, + const char *options) +{ + struct irs_rule **rules, *last, *tmp, *new; + struct irs_inst *inst; + const char *cp; + int n; + +#ifndef WANT_IRS_GR + if (map == irs_gr) + return (-1); +#endif +#ifndef WANT_IRS_PW + if (map == irs_pw) + return (-1); +#endif +#ifndef WANT_IRS_NIS + if (acc == irs_nis) + return (-1); +#endif + new = memget(sizeof *new); + if (new == NULL) + return (-1); + memset(new, 0x5e, sizeof *new); + new->next = NULL; + + new->inst = &irs->accessors[acc]; + + new->flags = 0; + cp = options; + while (cp && *cp) { + char option[50], *next; + + next = strchr(cp, ','); + if (next) + n = next++ - cp; + else + n = strlen(cp); + if ((size_t)n > sizeof option - 1) + n = sizeof option - 1; + strncpy(option, cp, n); + option[n] = '\0'; + + n = find_name(option, option_names); + if (n >= 0) + new->flags |= n; + + cp = next; + } + + rules = &irs->map_rules[map]; + for (last = NULL, tmp = *rules; + tmp != NULL; + last = tmp, tmp = tmp->next) + (void)NULL; + if (last == NULL) + *rules = new; + else + last->next = new; + + /* Try to instantiate map accessors for this if necessary & approp. */ + inst = &irs->accessors[acc]; + if (inst->acc == NULL && accs[acc] != NULL) + inst->acc = (*accs[acc])(irs->options); + if (inst->acc != NULL) { + if (inst->gr == NULL && inst->acc->gr_map != NULL) + inst->gr = (*inst->acc->gr_map)(inst->acc); + if (inst->pw == NULL && inst->acc->pw_map != NULL) + inst->pw = (*inst->acc->pw_map)(inst->acc); + if (inst->sv == NULL && inst->acc->sv_map != NULL) + inst->sv = (*inst->acc->sv_map)(inst->acc); + if (inst->pr == NULL && inst->acc->pr_map != NULL) + inst->pr = (*inst->acc->pr_map)(inst->acc); + if (inst->ho == NULL && inst->acc->ho_map != NULL) + inst->ho = (*inst->acc->ho_map)(inst->acc); + if (inst->nw == NULL && inst->acc->nw_map != NULL) + inst->nw = (*inst->acc->nw_map)(inst->acc); + if (inst->ng == NULL && inst->acc->ng_map != NULL) + inst->ng = (*inst->acc->ng_map)(inst->acc); + } + + return (0); +} + +static void +default_map_rules(struct gen_p *irs) { + /* Install time honoured and proved BSD style rules as default. */ + add_rule(irs, irs_gr, irs_lcl, ""); + add_rule(irs, irs_pw, irs_lcl, ""); + add_rule(irs, irs_sv, irs_lcl, ""); + add_rule(irs, irs_pr, irs_lcl, ""); +#ifdef SUNW_HOSTS_FALLBACK + if (__res_no_hosts_fallback()) + add_rule(irs, irs_ho, irs_dns, ""); + else { + add_rule(irs, irs_ho, irs_dns, "continue"); + add_rule(irs, irs_ho, irs_lcl, ""); + } +#else /* SUNW_HOSTS_FALLBACK */ + add_rule(irs, irs_ho, irs_dns, "continue"); + add_rule(irs, irs_ho, irs_lcl, ""); +#endif /* SUNW_HOSTS_FALLBACK */ + add_rule(irs, irs_nw, irs_dns, "continue"); + add_rule(irs, irs_nw, irs_lcl, ""); + add_rule(irs, irs_ng, irs_lcl, ""); +} + +static void +init_map_rules(struct gen_p *irs, const char *conf_file) { + char line[1024], pattern[40], mapname[20], accname[20], options[100]; + FILE *conf; + +#ifdef SUNW_HOSTS_FALLBACK + if (__res_no_hosts_fallback()) { + default_map_rules(irs); + return; + } +#endif /* SUNW_HOSTS_FALLBACK */ + + if (conf_file == NULL) + conf_file = _PATH_IRS_CONF ; + + /* A conf file of "" means compiled in defaults. Irpd wants this */ + if (conf_file[0] == '\0' || (conf = fopen(conf_file, "r")) == NULL) { + default_map_rules(irs); + return; + } + (void) sprintf(pattern, "%%%lus %%%lus %%%lus\n", + (unsigned long)sizeof mapname, + (unsigned long)sizeof accname, + (unsigned long)sizeof options); + while (fgets(line, sizeof line, conf)) { + enum irs_map_id map; + enum irs_acc_id acc; + char *tmp; + int n; + + for (tmp = line; + isascii((unsigned char)*tmp) && + isspace((unsigned char)*tmp); + tmp++) + (void)NULL; + if (*tmp == '#' || *tmp == '\n' || *tmp == '\0') + continue; + n = sscanf(tmp, pattern, mapname, accname, options); + if (n < 2) + continue; + if (n < 3) + options[0] = '\0'; + + n = find_name(mapname, map_names); + INSIST(n < irs_nmap); + if (n < 0) + continue; + map = (enum irs_map_id) n; + + n = find_name(accname, acc_names); + INSIST(n < irs_nacc); + if (n < 0) + continue; + acc = (enum irs_acc_id) n; + + add_rule(irs, map, acc, options); + } + fclose(conf); +} diff --git a/usr/src/lib/libresolv2_joy/common/irs/gen_ho.c b/usr/src/lib/libresolv2_joy/common/irs/gen_ho.c new file mode 100644 index 0000000000..8e41d7d610 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/gen_ho.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: gen_ho.c,v 1.5 2006/03/09 23:57:56 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <stdlib.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Definitions */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct irs_ho * ho; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forwards */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static int init(struct irs_ho *this); + +/* Exports */ + +struct irs_ho * +irs_gen_ho(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_ho *ho; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + pvt->rules = accpvt->map_rules[irs_ho]; + pvt->rule = pvt->rules; + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byname)(ho, name); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * The value TRY_AGAIN can mean that the service + * is not available, or just that this particular name + * cannot be resolved now. We use the errno ECONNREFUSED + * to distinguish. If a lookup sets that errno when + * H_ERRNO is TRY_AGAIN, we continue to try other lookup + * functions, otherwise we return the TRY_AGAIN error. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byname2)(ho, name, af); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct hostent *rval; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + rval = (*ho->byaddr)(ho, addr, len, af); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *rval; + struct irs_ho *ho; + + while (pvt->rule) { + ho = pvt->rule->inst->ho; + rval = (*ho->next)(ho); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + ho = pvt->rule->inst->ho; + (*ho->rewind)(ho); + } + } + return (NULL); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ho *ho; + + pvt->rule = pvt->rules; + if (pvt->rule) { + ho = pvt->rule->inst->ho; + (*ho->rewind)(ho); + } +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res) + res_nclose(pvt->res); + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ho *ho = rule->inst->ho; + + (*ho->minimize)(ho); + } +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ho *ho = rule->inst->ho; + + (*ho->res_set)(ho, pvt->res, NULL); + } +} + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct addrinfo *rval = NULL; + struct irs_ho *ho; + int therrno = NETDB_INTERNAL; + int softerror = 0; + + if (init(this) == -1) + return (NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + ho = rule->inst->ho; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + errno = 0; + if (ho->addrinfo == NULL) /*%< for safety */ + continue; + rval = (*ho->addrinfo)(ho, name, pai); + if (rval != NULL) + return (rval); + if (softerror == 0 && + pvt->res->res_h_errno != HOST_NOT_FOUND && + pvt->res->res_h_errno != NETDB_INTERNAL) { + softerror = 1; + therrno = pvt->res->res_h_errno; + } + if (rule->flags & IRS_CONTINUE) + continue; + /* + * See the comments in ho_byname() explaining + * the interpretation of TRY_AGAIN and ECONNREFUSED. + */ + if (pvt->res->res_h_errno != TRY_AGAIN || + errno != ECONNREFUSED) + break; + } + if (softerror != 0 && pvt->res->res_h_errno == HOST_NOT_FOUND) + RES_SET_H_ERRNO(pvt->res, therrno); + return (NULL); +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + + if (((pvt->res->options & RES_INIT) == 0U) && + (res_ninit(pvt->res) == -1)) + return (-1); + + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/gen_ng.c b/usr/src/lib/libresolv2_joy/common/irs/gen_ng.c new file mode 100644 index 0000000000..e3c874ee68 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/gen_ng.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_ng.c,v 1.3 2005/04/27 04:56:23 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + char * curgroup; +}; + +/* Forward */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +/* Public */ + +struct irs_ng * +irs_gen_ng(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_ng]; + pvt->rule = pvt->rules; + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ng_minimize(this); + if (pvt->curgroup) + free(pvt->curgroup); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ng *ng; + + while (pvt->rule) { + ng = pvt->rule->inst->ng; + if ((*ng->next)(ng, host, user, domain) == 1) + return (1); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + ng = pvt->rule->inst->ng; + (*ng->rewind)(ng, pvt->curgroup); + } + } + return (0); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *user, const char *host, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct irs_ng *ng; + int rval; + + rval = 0; + for (rule = pvt->rules; rule; rule = rule->next) { + ng = rule->inst->ng; + rval = (*ng->test)(ng, name, user, host, domain); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_ng *ng; + + pvt->rule = pvt->rules; + if (pvt->rule) { + if (pvt->curgroup) + free(pvt->curgroup); + pvt->curgroup = strdup(group); + ng = pvt->rule->inst->ng; + (*ng->rewind)(ng, pvt->curgroup); + } +} + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_ng *ng = rule->inst->ng; + + (*ng->minimize)(ng); + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/gen_nw.c b/usr/src/lib/libresolv2_joy/common/irs/gen_nw.c new file mode 100644 index 0000000000..12bd0e0f6d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/gen_nw.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_nw.c,v 1.4 2005/04/27 04:56:23 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv_joy.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void nw_close(struct irs_nw*); +static struct nwent * nw_next(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static int init(struct irs_nw *this); + +/* Public */ + +struct irs_nw * +irs_gen_nw(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + pvt->rules = accpvt->map_rules[irs_nw]; + pvt->rule = pvt->rules; + nw->private = pvt; + nw->close = nw_close; + nw->next = nw_next; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + while (pvt->rule) { + nw = pvt->rule->inst->nw; + rval = (*nw->next)(nw); + if (rval) + return (rval); + if (!(pvt->rules->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + nw = pvt->rule->inst->nw; + (*nw->rewind)(nw); + } + } + return (NULL); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + nw = rule->inst->nw; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + rval = (*nw->byname)(nw, name, type); + if (rval != NULL) + return (rval); + if (pvt->res->res_h_errno != TRY_AGAIN && + !(rule->flags & IRS_CONTINUE)) + break; + } + return (NULL); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct nwent *rval; + struct irs_nw *nw; + + if (init(this) == -1) + return(NULL); + + for (rule = pvt->rules; rule; rule = rule->next) { + nw = rule->inst->nw; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + rval = (*nw->byaddr)(nw, net, length, type); + if (rval != NULL) + return (rval); + if (pvt->res->res_h_errno != TRY_AGAIN && + !(rule->flags & IRS_CONTINUE)) + break; + } + return (NULL); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_nw *nw; + + pvt->rule = pvt->rules; + if (pvt->rule) { + nw = pvt->rule->inst->nw; + (*nw->rewind)(nw); + } +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res) + res_nclose(pvt->res); + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_nw *nw = rule->inst->nw; + + (*nw->minimize)(nw); + } +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_nw *nw = rule->inst->nw; + + (*nw->res_set)(nw, pvt->res, NULL); + } +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0U) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/gen_p.h b/usr/src/lib/libresolv2_joy/common/irs/gen_p.h new file mode 100644 index 0000000000..1adc5909bb --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/gen_p.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: gen_p.h,v 1.3 2005/04/27 04:56:23 sra Exp $ + */ + +/*! \file + * Notes: + * We hope to create a complete set of thread-safe entry points someday, + * which will mean a set of getXbyY() functions that take as an argument + * a pointer to the map class, which will have a pointer to the private + * data, which will be used preferentially to the static variables that + * are necessary to support the "classic" interface. This "classic" + * interface will then be reimplemented as stubs on top of the thread + * safe modules, and will keep the map class pointers as their only + * static data. HOWEVER, we are not there yet. So while we will call + * the just-barely-converted map class methods with map class pointers, + * right now they probably all still use statics. We're not fooling + * anybody, and we're not trying to (yet). + */ + +#ifndef _GEN_P_H_INCLUDED +#define _GEN_P_H_INCLUDED + +/*% + * These are the access methods. + */ +enum irs_acc_id { + irs_lcl, /*%< Local. */ + irs_dns, /*%< DNS or Hesiod. */ + irs_nis, /*%< Sun NIS ("YP"). */ + irs_irp, /*%< IR protocol. */ + irs_nacc +}; + +/*% + * These are the map types. + */ +enum irs_map_id { + irs_gr, /*%< "group" */ + irs_pw, /*%< "passwd" */ + irs_sv, /*%< "services" */ + irs_pr, /*%< "protocols" */ + irs_ho, /*%< "hosts" */ + irs_nw, /*%< "networks" */ + irs_ng, /*%< "netgroup" */ + irs_nmap +}; + +/*% + * This is an accessor instance. + */ +struct irs_inst { + struct irs_acc *acc; + struct irs_gr * gr; + struct irs_pw * pw; + struct irs_sv * sv; + struct irs_pr * pr; + struct irs_ho * ho; + struct irs_nw * nw; + struct irs_ng * ng; +}; + +/*% + * This is a search rule for some map type. + */ +struct irs_rule { + struct irs_rule * next; + struct irs_inst * inst; + int flags; +}; +#define IRS_MERGE 0x0001 /*%< Don't stop if acc. has data? */ +#define IRS_CONTINUE 0x0002 /*%< Don't stop if acc. has no data? */ +/* + * This is the private data for a search access class. + */ +struct gen_p { + char * options; + struct irs_rule * map_rules[(int)irs_nmap]; + struct irs_inst accessors[(int)irs_nacc]; + struct __res_state * res; + void (*free_res) __P((void *)); +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_gen_acc __P((const char *, const char *conf_file)); +extern struct irs_gr * irs_gen_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_gen_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_gen_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_gen_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_gen_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_gen_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_gen_ng __P((struct irs_acc *)); + +#endif /*_IRS_P_H_INCLUDED*/ diff --git a/usr/src/lib/libresolv2_joy/common/irs/gen_pr.c b/usr/src/lib/libresolv2_joy/common/irs/gen_pr.c new file mode 100644 index 0000000000..9fd32c4dd9 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/gen_pr.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_pr.c,v 1.3 2005/04/27 04:56:24 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv_joy.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void pr_close(struct irs_pr*); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); +static struct __res_state * pr_res_get(struct irs_pr *); +static void pr_res_set(struct irs_pr *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_pr * +irs_gen_pr(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x5e, sizeof *pr); + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_pr]; + pvt->rule = pvt->rules; + pr->private = pvt; + pr->close = pr_close; + pr->next = pr_next; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + pr->res_get = pr_res_get; + pr->res_set = pr_res_set; + return (pr); +} + +/* Methods */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *rval; + struct irs_pr *pr; + + while (pvt->rule) { + pr = pvt->rule->inst->pr; + rval = (*pr->next)(pr); + if (rval) + return (rval); + if (!(pvt->rules->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + pr = pvt->rule->inst->pr; + (*pr->rewind)(pr); + } + } + return (NULL); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct protoent *rval; + struct irs_pr *pr; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pr = rule->inst->pr; + rval = (*pr->byname)(pr, name); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct protoent *rval; + struct irs_pr *pr; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + pr = rule->inst->pr; + rval = (*pr->bynumber)(pr, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_pr *pr; + + pvt->rule = pvt->rules; + if (pvt->rule) { + pr = pvt->rule->inst->pr; + (*pr->rewind)(pr); + } +} + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pr *pr = rule->inst->pr; + + (*pr->minimize)(pr); + } +} + +static struct __res_state * +pr_res_get(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + pr_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +pr_res_set(struct irs_pr *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_pr *pr = rule->inst->pr; + + if (pr->res_set) + (*pr->res_set)(pr, pvt->res, NULL); + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/gen_sv.c b/usr/src/lib/libresolv2_joy/common/irs/gen_sv.c new file mode 100644 index 0000000000..93b70e57ec --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/gen_sv.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gen_sv.c,v 1.3 2005/04/27 04:56:24 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "gen_p.h" + +/* Types */ + +struct pvt { + struct irs_rule * rules; + struct irs_rule * rule; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +static struct __res_state * sv_res_get(struct irs_sv *); +static void sv_res_set(struct irs_sv *, + struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_sv * +irs_gen_sv(struct irs_acc *this) { + struct gen_p *accpvt = (struct gen_p *)this->private; + struct irs_sv *sv; + struct pvt *pvt; + + if (!(sv = memget(sizeof *sv))) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if (!(pvt = memget(sizeof *pvt))) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->rules = accpvt->map_rules[irs_sv]; + pvt->rule = pvt->rules; + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = sv_res_get; + sv->res_set = sv_res_set; + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *rval; + struct irs_sv *sv; + + while (pvt->rule) { + sv = pvt->rule->inst->sv; + rval = (*sv->next)(sv); + if (rval) + return (rval); + if (!(pvt->rule->flags & IRS_CONTINUE)) + break; + pvt->rule = pvt->rule->next; + if (pvt->rule) { + sv = pvt->rule->inst->sv; + (*sv->rewind)(sv); + } + } + return (NULL); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct servent *rval; + struct irs_sv *sv; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + sv = rule->inst->sv; + rval = (*sv->byname)(sv, name, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + struct servent *rval; + struct irs_sv *sv; + + rval = NULL; + for (rule = pvt->rules; rule; rule = rule->next) { + sv = rule->inst->sv; + rval = (*sv->byport)(sv, port, proto); + if (rval || !(rule->flags & IRS_CONTINUE)) + break; + } + return (rval); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_sv *sv; + + pvt->rule = pvt->rules; + if (pvt->rule) { + sv = pvt->rule->inst->sv; + (*sv->rewind)(sv); + } +} + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_sv *sv = rule->inst->sv; + + (*sv->minimize)(sv); + } +} + +static struct __res_state * +sv_res_get(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + sv_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +sv_res_set(struct irs_sv *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + struct irs_rule *rule; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; + + for (rule = pvt->rules; rule != NULL; rule = rule->next) { + struct irs_sv *sv = rule->inst->sv; + + if (sv->res_set) + (*sv->res_set)(sv, pvt->res, NULL); + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/getaddrinfo.c b/usr/src/lib/libresolv2_joy/common/irs/getaddrinfo.c new file mode 100644 index 0000000000..19bbbea854 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/getaddrinfo.c @@ -0,0 +1,1253 @@ +/* $KAME: getaddrinfo.c,v 1.14 2001/01/06 09:41:15 jinmei 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. + */ + +/*! \file + * Issues to be discussed: + *\li Thread safe-ness must be checked. + *\li 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. + *\li IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 + * says to use inet_aton() to convert IPv4 numeric to binary (allows + * classful form as a result). + * current code - disallow classful form for IPv4 (due to use of inet_pton). + *\li freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is + * invalid. + * current code - SEGV on freeaddrinfo(NULL) + * Note: + *\li 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(). + *\li 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? + *\li (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? + * \par Additional Issue: + * 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: + * \li The code makes use of following calls when asked to resolver with + * ai_family = PF_UNSPEC: + *\code getipnodebyname(host, AF_INET6); + * getipnodebyname(host, AF_INET); + *\endcode + * \li This will result in the following queries if the node is configure to + * prefer /etc/hosts than DNS: + *\code + * lookup /etc/hosts for IPv6 address + * lookup DNS for IPv6 address + * lookup /etc/hosts for IPv4 address + * lookup DNS for IPv4 address + *\endcode + * which may not meet people's requirement. + * \li 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. + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <netinet/in.h> + +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <netdb.h> +#include <resolv_joy.h> +#include <string.h> +#include <stdlib.h> +#include <stddef.h> +#include <ctype.h> +#include <unistd.h> +#include <stdio.h> +#include <errno.h> + +#include <stdarg.h> + +#include <irs.h> +#include <isc/assertions.h> + +#include "port_after.h" + +#include "irs_data.h" + +#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; + int a_scoped; +} afdl [] = { + {PF_INET6, sizeof(struct in6_addr), + sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr), + in6_addrany, in6_loopback, 1}, + {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) +}; + +static const struct explore explore[] = { +#if 0 + { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, +#endif + { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, + { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, + { -1, 0, 0, NULL, 0 }, +}; + +#define PTON_MAX 16 + +static int str_isnumber __P((const char *)); +static int explore_fqdn __P((const struct addrinfo *, const char *, + const char *, struct addrinfo **)); +static int explore_copy __P((const struct addrinfo *, const struct addrinfo *, + 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 struct addrinfo *copy_ai __P((const struct addrinfo *)); +static int get_portmatch __P((const struct addrinfo *, const char *)); +static int get_port __P((const struct addrinfo *, const char *, int)); +static const struct afd *find_afd __P((int)); +static int addrconfig __P((int)); +static int ip6_str2scopeid __P((char *, struct sockaddr_in6 *, + u_int32_t *scopeidp)); +static struct net_data *init __P((void)); + +struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *)); +struct addrinfo *addr2addrinfo __P((const struct addrinfo *, + const char *)); + +#if 0 +static const 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 */ + "Unknown error", /*%< EAI_MAX */ +}; +#endif + +/* XXX macros that make external reference is BAD. */ + +#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) \ +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) \ +do { \ + /* external reference: pai, error and label free */ \ + error = get_canonname(pai, (ai), (str)); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +#ifndef SOLARIS2 +#define SETERROR(err) \ +do { \ + /* external reference: error, and label bad */ \ + error = (err); \ + goto bad; \ + /*NOTREACHED*/ \ +} while (/*CONSTCOND*/0) +#else +#define SETERROR(err) \ +do { \ + /* external reference: error, and label bad */ \ + error = (err); \ + if (error == error) \ + goto bad; \ +} while (/*CONSTCOND*/0) +#endif + + +#define MATCH_FAMILY(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC))) +#define MATCH(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) + +#if 0 /*%< bind8 has its own version */ +char * +gai_strerror(ecode) + int ecode; +{ + if (ecode < 0 || ecode > EAI_MAX) + ecode = EAI_MAX; + return ai_errlist[ecode]; +} +#endif + +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; + errno = 0; + (void)strtoul(p, &ep, 10); + if (errno == 0 && 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, ai0, *afai = NULL; + 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; +#if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9) + /* + * clear _ai_pad to preserve binary + * compatibility with previously compiled 64-bit + * applications in a pre-SUSv3 environment by + * guaranteeing the upper 32-bits are empty. + */ + pai->_ai_pad = 0; +#endif + pai->ai_addrlen = 0; + pai->ai_canonname = NULL; + pai->ai_addr = NULL; + pai->ai_next = NULL; + + if (hostname == NULL && servname == NULL) + return EAI_NONAME; + if (hints) { + /* error check for hints */ + if (hints->ai_addrlen || hints->ai_canonname || + hints->ai_addr || hints->ai_next) + SETERROR(EAI_BADHINTS); /*%< xxx */ + if (hints->ai_flags & ~AI_MASK) + SETERROR(EAI_BADFLAGS); + switch (hints->ai_family) { + case PF_UNSPEC: + case PF_INET: + case PF_INET6: + break; + default: + SETERROR(EAI_FAMILY); + } + memcpy(pai, hints, sizeof(*pai)); + +#if defined(sun) && defined(_SOCKLEN_T) && defined(__sparcv9) + /* + * We need to clear _ai_pad to preserve binary + * compatibility. See prior comment. + */ + pai->_ai_pad = 0; +#endif + /* + * 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) { + SETERROR(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 */ + SETERROR(EAI_BADFLAGS); +#else + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; +#endif + } + + /* + * 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) +#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) + SETERROR(error); + + *pai = ai0; + } + + ai0 = *pai; + + /* NULL hostname, or numeric hostname */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) + continue; + if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) + continue; + 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 the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + continue; + + if (hostname == NULL) { + /* + * filter out AFs that are not supported by the kernel + * XXX errno? + */ + if (!addrconfig(pai->ai_family)) + continue; + error = explore_null(pai, servname, &cur->ai_next); + } else + 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) + SETERROR(EAI_NONAME); + if (hostname == NULL) + SETERROR(EAI_NONAME); + + /* + * hostname as alphabetical name. + * We'll make sure that + * - if returning addrinfo list is empty, return non-zero error + * value (already known one or EAI_NONAME). + * - otherwise, + * + if we haven't had any errors, return 0 (i.e. success). + * + if we've had an error, free the list and return the error. + * without any assumption on the behavior of explore_fqdn(). + */ + + /* first, try to query DNS for all possible address families. */ + *pai = ai0; + error = explore_fqdn(pai, hostname, servname, &afai); + if (error) { + if (afai != NULL) + freeaddrinfo(afai); + goto free; + } + if (afai == NULL) { + error = EAI_NONAME; /*%< we've had no errors. */ + goto free; + } + + /* + * we would like to prefer AF_INET6 than AF_INET, so we'll make an + * outer loop by AFs. + */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + + if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) + continue; + if (!MATCH(pai->ai_socktype, ex->e_socktype, + WILD_SOCKTYPE(ex))) { + continue; + } + if (!MATCH(pai->ai_protocol, ex->e_protocol, + WILD_PROTOCOL(ex))) { + continue; + } + +#ifdef AI_ADDRCONFIG + /* + * If AI_ADDRCONFIG is specified, check if we are + * expected to return the address family or not. + */ + if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && + !addrconfig(pai->ai_family)) + continue; +#endif + + 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 the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + continue; + + if ((error = explore_copy(pai, afai, &cur->ai_next)) != 0) { + freeaddrinfo(afai); + goto free; + } + + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + freeaddrinfo(afai); /*%< afai must not be NULL at this point. */ + + if (sentinel.ai_next) { +good: + *res = sentinel.ai_next; + return(SUCCESS); + } else { + /* + * All the process succeeded, but we've had an empty list. + * This can happen if the given hints do not match our + * candidates. + */ + error = EAI_NONAME; + } + +free: +bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + *res = NULL; + return(error); +} + +/*% + * 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; + struct net_data *net_data = init(); + struct irs_ho *ho; + int error = 0; + char tmp[NS_MAXDNAME]; + const char *cp; + + INSIST(res != NULL && *res == NULL); + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + return(0); + + if (!net_data || !(ho = net_data->ho)) + return(0); +#if 0 /*%< XXX (notyet) */ + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_addrtype == af) { + if (ns_samename(name, net_data->ho_last->h_name) == 1) + return (net_data->ho_last); + for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++) + if (ns_samename(name, *hap) == 1) + return (net_data->ho_last); + } +#endif + if (!strchr(hostname, '.') && + (cp = res_hostalias(net_data->res, hostname, + tmp, sizeof(tmp)))) + hostname = cp; + result = (*ho->addrinfo)(ho, hostname, pai); + if (!net_data->ho_stayopen) { + (*ho->minimize)(ho); + } + if (result == NULL) { + int e = h_errno; + + switch(e) { + case NETDB_INTERNAL: + error = EAI_SYSTEM; + break; + case TRY_AGAIN: + error = EAI_AGAIN; + break; + case NO_RECOVERY: + error = EAI_FAIL; + break; + case HOST_NOT_FOUND: + case NO_DATA: + error = EAI_NONAME; + break; + default: + case NETDB_SUCCESS: /*%< should be impossible... */ + error = EAI_NONAME; + break; + } + goto free; + } + + for (cur = result; cur; cur = cur->ai_next) { + GET_PORT(cur, servname); /*%< XXX: redundant lookups... */ + /* canonname should already be filled. */ + } + + *res = result; + + return(0); + +free: + if (result) + freeaddrinfo(result); + return error; +} + +static int +explore_copy(pai, src0, res) + const struct addrinfo *pai; /*%< seed */ + const struct addrinfo *src0; /*%< source */ + struct addrinfo **res; +{ + int error; + struct addrinfo sentinel, *cur; + const struct addrinfo *src; + + error = 0; + sentinel.ai_next = NULL; + cur = &sentinel; + + for (src = src0; src != NULL; src = src->ai_next) { + if (src->ai_family != pai->ai_family) + continue; + + cur->ai_next = copy_ai(src); + if (!cur->ai_next) { + error = EAI_MEMORY; + goto fail; + } + + cur->ai_next->ai_socktype = pai->ai_socktype; + cur->ai_next->ai_protocol = pai->ai_protocol; + cur = cur->ai_next; + } + + *res = sentinel.ai_next; + return 0; + +fail: + freeaddrinfo(sentinel.ai_next); + 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; +{ + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; + + 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; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + switch (afd->a_af) { +#if 0 /*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->ai_next) + cur = cur->ai_next; + } else + SETERROR(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->ai_next) + cur = cur->ai_next; + } else + SETERROR(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; +{ +#ifndef SCOPE_DELIMITER + 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; + + 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 <scoped_address><delimiter><scope id> + */ + 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) { + u_int32_t scopeid = 0; + + for (cur = *res; cur; cur = cur->ai_next) { + if (cur->ai_family != AF_INET6) + continue; + sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; + if (!ip6_str2scopeid(scope, sin6, &scopeid)) { + free(hostname2); + return(EAI_NONAME); /*%< XXX: is return OK? */ + } +#ifdef HAVE_SIN6_SCOPE_ID + sin6->sin6_scope_id = scopeid; +#endif + } + } + + 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; + + 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); +#ifdef HAVE_SA_LEN + ai->ai_addr->sa_len = afd->a_socklen; +#endif + ai->ai_addrlen = afd->a_socklen; + ai->ai_addr->sa_family = ai->ai_family = afd->a_af; + p = (char *)(void *)(ai->ai_addr); + memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); + return ai; +} + +/* XXX need to malloc() the same way we do from other functions! */ +static struct addrinfo * +copy_ai(pai) + const struct addrinfo *pai; +{ + struct addrinfo *ai; + size_t l; + + l = sizeof(*ai) + pai->ai_addrlen; + if ((ai = (struct addrinfo *)malloc(l)) == NULL) + return NULL; + memset(ai, 0, l); + memcpy(ai, pai, sizeof(*ai)); + ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); + memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen); + + if (pai->ai_canonname) { + l = strlen(pai->ai_canonname) + 1; + if ((ai->ai_canonname = malloc(l)) == NULL) { + free(ai); + return NULL; + } + strcpy(ai->ai_canonname, pai->ai_canonname); /* (checked) */ + } else { + /* just to make sure */ + ai->ai_canonname = NULL; + } + + ai->ai_next = NULL; + + return ai; +} + +static int +get_portmatch(const struct addrinfo *ai, const char *servname) { + + /* get_port does not touch first argument. when matchonly == 1. */ + /* LINTED const cast */ + return get_port((const struct addrinfo *)ai, servname, 1); +} + +static int +get_port(const 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: + switch (ai->ai_family) { + case AF_INET: +#ifdef AF_INET6 + case AF_INET6: +#endif + allownumeric = 1; + break; + default: + allownumeric = 0; + break; + } + break; + default: + return EAI_SOCKTYPE; + } + + if (str_isnumber(servname)) { + if (!allownumeric) + return EAI_SERVICE; + port = atoi(servname); + if (port < 0 || port > 65535) + return EAI_SERVICE; + port = htons(port); + } 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; + case AF_INET6: + ((struct sockaddr_in6 *)(void *) + ai->ai_addr)->sin6_port = port; + break; + } + } + + 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. + */ +static int +addrconfig(af) + int af; +{ + int s; + + /* XXX errno */ + s = socket(af, SOCK_DGRAM, 0); + if (s < 0) { + if (errno != EMFILE) + return 0; + } else + close(s); + return 1; +} + +/* convert a string to a scope identifier. XXX: IPv6 specific */ +static int +ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, + u_int32_t *scopeidp) +{ + u_int32_t scopeid; + u_long lscopeid; + struct in6_addr *a6 = &sin6->sin6_addr; + char *ep; + + /* empty scopeid portion is invalid */ + if (*scope == '\0') + return (0); + +#ifdef USE_IFNAMELINKID + if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) || + IN6_IS_ADDR_MC_NODELOCAL(a6)) { + /* + * Using interface names as link indices can be allowed + * only when we can assume a one-to-one mappings between + * links and interfaces. See comments in getnameinfo.c. + */ + scopeid = if_nametoindex(scope); + if (scopeid == 0) + goto trynumeric; + *scopeidp = scopeid; + return (1); + } +#endif + + /* 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: + errno = 0; + lscopeid = strtoul(scope, &ep, 10); + scopeid = lscopeid & 0xffffffff; + if (errno == 0 && ep && *ep == '\0' && scopeid == lscopeid) { + *scopeidp = scopeid; + return (1); + } else + return (0); +} + +struct addrinfo * +hostent2addrinfo(hp, pai) + struct hostent *hp; + const struct addrinfo *pai; +{ + int i, af, error = 0; + char **aplist = NULL, *ap; + struct addrinfo sentinel, *cur; + const struct afd *afd; + + af = hp->h_addrtype; + if (pai->ai_family != AF_UNSPEC && af != pai->ai_family) + return(NULL); + + afd = find_afd(af); + if (afd == NULL) + return(NULL); + + aplist = hp->h_addr_list; + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + for (i = 0; (ap = aplist[i]) != NULL; i++) { +#if 0 /*%< the trick seems too much */ + af = hp->h_addr_list; + if (af == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) { + af = AF_INET; + ap = ap + sizeof(struct in6_addr) + - sizeof(struct in_addr); + } + afd = find_afd(af); + if (afd == NULL) + continue; +#endif /* 0 */ + + GET_AI(cur->ai_next, afd, ap); + + /* GET_PORT(cur->ai_next, servname); */ + 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); + } + while (cur->ai_next) /*%< no need to loop, actually. */ + cur = cur->ai_next; + continue; + + free: + if (cur->ai_next) + freeaddrinfo(cur->ai_next); + cur->ai_next = NULL; + /* continue, without tht pointer CUR advanced. */ + } + + return(sentinel.ai_next); +} + +struct addrinfo * +addr2addrinfo(pai, cp) + const struct addrinfo *pai; + const char *cp; +{ + const struct afd *afd; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return(NULL); + + return(get_ai(pai, afd, cp)); +} + +static struct net_data * +init() +{ + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ho) { + net_data->ho = (*net_data->irs->ho_map)(net_data->irs); + if (!net_data->ho || !net_data->res) { +error: + errno = EIO; + if (net_data && net_data->res) + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + + (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); + } + + return (net_data); +} diff --git a/usr/src/lib/libresolv2_joy/common/irs/gethostent.c b/usr/src/lib/libresolv2_joy/common/irs/gethostent.c new file mode 100644 index 0000000000..c4751c2c80 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/gethostent.c @@ -0,0 +1,1096 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: gethostent.c,v 1.8 2006/01/10 05:06:00 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <net/if.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "irs_data.h" + +/* Definitions */ + +struct pvt { + char * aliases[1]; + char * addrs[2]; + char addr[NS_IN6ADDRSZ]; + char name[NS_MAXDNAME + 1]; + struct hostent host; +}; + +/* Forward */ + +static struct net_data *init(void); +static void freepvt(struct net_data *); +static struct hostent *fakeaddr(const char *, int, struct net_data *); + +#ifdef SUNW_OVERRIDE_RETRY +extern int __res_retry(int); +extern int __res_retry_reset(void); +#endif /* SUNW_OVERRIDE_RETRY */ + + +/* Public */ + +struct hostent * +gethostbyname(const char *name) { + struct net_data *net_data = init(); + + return (gethostbyname_p(name, net_data)); +} + +struct hostent * +gethostbyname2(const char *name, int af) { + struct net_data *net_data = init(); + + return (gethostbyname2_p(name, af, net_data)); +} + +struct hostent * +gethostbyaddr(const char *addr, int len, int af) { + struct net_data *net_data = init(); + + return (gethostbyaddr_p(addr, len, af, net_data)); +} + +struct hostent * +gethostent() { + struct net_data *net_data = init(); + + return (gethostent_p(net_data)); +} + +void +sethostent(int stayopen) { + struct net_data *net_data = init(); + sethostent_p(stayopen, net_data); +} + + +void +endhostent() { + struct net_data *net_data = init(); + endhostent_p(net_data); +} + +/* Shared private. */ + +struct hostent * +gethostbyname_p(const char *name, struct net_data *net_data) { + struct hostent *hp; + + if (!net_data) + return (NULL); + + if (net_data->res->options & RES_USE_INET6) { + hp = gethostbyname2_p(name, AF_INET6, net_data); + if (hp) + return (hp); + } + return (gethostbyname2_p(name, AF_INET, net_data)); +} + +struct hostent * +gethostbyname2_p(const char *name, int af, struct net_data *net_data) { + struct irs_ho *ho; + char tmp[NS_MAXDNAME]; + struct hostent *hp; + const char *cp; + char **hap; + + if (!net_data || !(ho = net_data->ho)) + return (NULL); + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_addrtype == af) { + if (ns_samename(name, net_data->ho_last->h_name) == 1) + return (net_data->ho_last); + for (hap = net_data->ho_last->h_aliases; hap && *hap; hap++) + if (ns_samename(name, *hap) == 1) + return (net_data->ho_last); + } + if (!strchr(name, '.') && (cp = res_hostalias(net_data->res, name, + tmp, sizeof tmp))) + name = cp; + if ((hp = fakeaddr(name, af, net_data)) != NULL) + return (hp); +#ifdef SUNW_OVERRIDE_RETRY + net_data->res->retry = __res_retry(net_data->res->retry); +#endif /* SUNW_OVERRIDE_RETRY */ + net_data->ho_last = (*ho->byname2)(ho, name, af); +#ifdef SUNW_OVERRIDE_RETRY + net_data->res->retry = __res_retry_reset(); +#endif /* SUNW_OVERRIDE_RETRY */ + if (!net_data->ho_stayopen) + endhostent(); + return (net_data->ho_last); +} + +struct hostent * +gethostbyaddr_p(const char *addr, int len, int af, struct net_data *net_data) { + struct irs_ho *ho; + char **hap; + + if (!net_data || !(ho = net_data->ho)) + return (NULL); + if (net_data->ho_stayopen && net_data->ho_last && + net_data->ho_last->h_length == len) + for (hap = net_data->ho_last->h_addr_list; + hap && *hap; + hap++) + if (!memcmp(addr, *hap, len)) + return (net_data->ho_last); + net_data->ho_last = (*ho->byaddr)(ho, addr, len, af); + if (!net_data->ho_stayopen) + endhostent(); + return (net_data->ho_last); +} + + +struct hostent * +gethostent_p(struct net_data *net_data) { + struct irs_ho *ho; + struct hostent *hp; + + if (!net_data || !(ho = net_data->ho)) + return (NULL); + while ((hp = (*ho->next)(ho)) != NULL && + hp->h_addrtype == AF_INET6 && + (net_data->res->options & RES_USE_INET6) == 0U) + continue; + net_data->ho_last = hp; + return (net_data->ho_last); +} + + +void +sethostent_p(int stayopen, struct net_data *net_data) { + struct irs_ho *ho; + + if (!net_data || !(ho = net_data->ho)) + return; + freepvt(net_data); + (*ho->rewind)(ho); + net_data->ho_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endhostent_p(struct net_data *net_data) { + struct irs_ho *ho; + + if ((net_data != NULL) && ((ho = net_data->ho) != NULL)) + (*ho->minimize)(ho); +} + +#ifndef IN6_IS_ADDR_V4COMPAT +static const unsigned char in6addr_compat[12] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +#define IN6_IS_ADDR_V4COMPAT(x) (!memcmp((x)->s6_addr, in6addr_compat, 12) && \ + ((x)->s6_addr[12] != 0 || \ + (x)->s6_addr[13] != 0 || \ + (x)->s6_addr[14] != 0 || \ + ((x)->s6_addr[15] != 0 && \ + (x)->s6_addr[15] != 1))) +#endif +#ifndef IN6_IS_ADDR_V4MAPPED +#define IN6_IS_ADDR_V4MAPPED(x) (!memcmp((x)->s6_addr, in6addr_mapped, 12)) +#endif + +static const unsigned char in6addr_mapped[12] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; + +static int scan_interfaces(int *, int *); +static struct hostent *copyandmerge(struct hostent *, struct hostent *, int, int *); + +/*% + * Public functions + */ + +/*% + * AI_V4MAPPED + AF_INET6 + * If no IPv6 address then a query for IPv4 and map returned values. + * + * AI_ALL + AI_V4MAPPED + AF_INET6 + * Return IPv6 and IPv4 mapped. + * + * AI_ADDRCONFIG + * Only return IPv6 / IPv4 address if there is an interface of that + * type active. + */ + +struct hostent * +getipnodebyname(const char *name, int af, int flags, int *error_num) { + int have_v4 = 1, have_v6 = 1; + struct in_addr in4; + struct in6_addr in6; + struct hostent he, *he1 = NULL, *he2 = NULL, *he3; + int v4 = 0, v6 = 0; + struct net_data *net_data = init(); + u_long options; + int tmp_err; + + if (net_data == NULL) { + *error_num = NO_RECOVERY; + return (NULL); + } + + /* If we care about active interfaces then check. */ + if ((flags & AI_ADDRCONFIG) != 0) + if (scan_interfaces(&have_v4, &have_v6) == -1) { + *error_num = NO_RECOVERY; + return (NULL); + } + + /* Check for literal address. */ + if ((v4 = inet_pton(AF_INET, name, &in4)) != 1) + v6 = inet_pton(AF_INET6, name, &in6); + + /* Impossible combination? */ + + if ((af == AF_INET6 && (flags & AI_V4MAPPED) == 0 && v4 == 1) || + (af == AF_INET && v6 == 1) || + (have_v4 == 0 && v4 == 1) || + (have_v6 == 0 && v6 == 1) || + (have_v4 == 0 && af == AF_INET) || + (have_v6 == 0 && af == AF_INET6)) { + *error_num = HOST_NOT_FOUND; + return (NULL); + } + + /* Literal address? */ + if (v4 == 1 || v6 == 1) { + char *addr_list[2]; + char *aliases[1]; + + DE_CONST(name, he.h_name); + he.h_addr_list = addr_list; + he.h_addr_list[0] = (v4 == 1) ? (char *)&in4 : (char *)&in6; + he.h_addr_list[1] = NULL; + he.h_aliases = aliases; + he.h_aliases[0] = NULL; + he.h_length = (v4 == 1) ? INADDRSZ : IN6ADDRSZ; + he.h_addrtype = (v4 == 1) ? AF_INET : AF_INET6; + return (copyandmerge(&he, NULL, af, error_num)); + } + + options = net_data->res->options; + net_data->res->options &= ~RES_USE_INET6; + + tmp_err = NO_RECOVERY; + if (have_v6 && af == AF_INET6) { + he2 = gethostbyname2_p(name, AF_INET6, net_data); + if (he2 != NULL) { + he1 = copyandmerge(he2, NULL, af, error_num); + if (he1 == NULL) + return (NULL); + he2 = NULL; + } else { + tmp_err = net_data->res->res_h_errno; + } + } + + if (have_v4 && + ((af == AF_INET) || + (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 && + (he1 == NULL || (flags & AI_ALL) != 0)))) { + he2 = gethostbyname2_p(name, AF_INET, net_data); + if (he1 == NULL && he2 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + } else + *error_num = tmp_err; + + net_data->res->options = options; + + he3 = copyandmerge(he1, he2, af, error_num); + + if (he1 != NULL) + freehostent(he1); + return (he3); +} + +struct hostent * +getipnodebyaddr(const void *src, size_t len, int af, int *error_num) { + struct hostent *he1, *he2; + struct net_data *net_data = init(); + + /* Sanity Checks. */ +#ifdef ORIGINAL_ISC_CODE + if (src == NULL) { +#else + /* this change was added circa May 2009, but not in ISC libbind 6.0 */ + if (src == NULL|| net_data == NULL) { +#endif /* ORIGINAL_ISC_CODE */ + *error_num = NO_RECOVERY; + return (NULL); + } + + switch (af) { + case AF_INET: + if (len != (size_t)INADDRSZ) { + *error_num = NO_RECOVERY; + return (NULL); + } + break; + case AF_INET6: + if (len != (size_t)IN6ADDRSZ) { + *error_num = NO_RECOVERY; + return (NULL); + } + break; + default: + *error_num = NO_RECOVERY; + return (NULL); + } + + /* + * Lookup IPv4 and IPv4 mapped/compatible addresses + */ + if ((af == AF_INET6 && + IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src)) || + (af == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src)) || + (af == AF_INET)) { + const char *cp = src; + + if (af == AF_INET6) + cp += 12; + he1 = gethostbyaddr_p(cp, 4, AF_INET, net_data); + if (he1 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + he2 = copyandmerge(he1, NULL, af, error_num); + if (he2 == NULL) + return (NULL); + /* + * Restore original address if mapped/compatible. + */ + if (af == AF_INET6) + memcpy(he1->h_addr, src, len); + return (he2); + } + + /* + * Lookup IPv6 address. + */ + if (memcmp((const struct in6_addr *)src, &in6addr_any, 16) == 0) { + *error_num = HOST_NOT_FOUND; + return (NULL); + } + + he1 = gethostbyaddr_p(src, 16, AF_INET6, net_data); + if (he1 == NULL) { + *error_num = net_data->res->res_h_errno; + return (NULL); + } + return (copyandmerge(he1, NULL, af, error_num)); +} + +void +freehostent(struct hostent *he) { + char **cpp; + int names = 1; + int addresses = 1; + + memput(he->h_name, strlen(he->h_name) + 1); + + cpp = he->h_addr_list; + while (*cpp != NULL) { + memput(*cpp, (he->h_addrtype == AF_INET) ? + INADDRSZ : IN6ADDRSZ); + *cpp = NULL; + cpp++; + addresses++; + } + + cpp = he->h_aliases; + while (*cpp != NULL) { + memput(*cpp, strlen(*cpp) + 1); + cpp++; + names++; + } + + memput(he->h_aliases, sizeof(char *) * (names)); + memput(he->h_addr_list, sizeof(char *) * (addresses)); + memput(he, sizeof *he); +} + +/*% + * Private + */ + +/*% + * Scan the interface table and set have_v4 and have_v6 depending + * upon whether there are IPv4 and IPv6 interface addresses. + * + * Returns: + * 0 on success + * -1 on failure. + */ + +#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \ + !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF) + +#ifdef __hpux +#define lifc_len iflc_len +#define lifc_buf iflc_buf +#define lifc_req iflc_req +#define LIFCONF if_laddrconf +#else +#define SETFAMILYFLAGS +#define LIFCONF lifconf +#endif + +#ifdef __hpux +#define lifr_addr iflr_addr +#define lifr_name iflr_name +#define lifr_dstaddr iflr_dstaddr +#define lifr_flags iflr_flags +#define ss_family sa_family +#define LIFREQ if_laddrreq +#else +#define LIFREQ lifreq +#endif + +static void +scan_interfaces6(int *have_v4, int *have_v6) { + struct LIFCONF lifc; + struct LIFREQ lifreq; + struct in_addr in4; + struct in6_addr in6; + char *buf = NULL, *cp, *cplim; + static unsigned int bufsiz = 4095; + int s, cpsize, n; + + /* Get interface list from system. */ + if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) == -1) + goto cleanup; + + /* + * Grow buffer until large enough to contain all interface + * descriptions. + */ + for (;;) { + buf = memget(bufsiz); + if (buf == NULL) + goto cleanup; +#ifdef SETFAMILYFLAGS + lifc.lifc_family = AF_UNSPEC; /*%< request all families */ + lifc.lifc_flags = 0; +#endif + lifc.lifc_len = bufsiz; + lifc.lifc_buf = buf; + if ((n = ioctl(s, SIOCGLIFCONF, (char *)&lifc)) != -1) { + /* + * Some OS's just return what will fit rather + * than set EINVAL if the buffer is too small + * to fit all the interfaces in. If + * lifc.lifc_len is too near to the end of the + * buffer we will grow it just in case and + * retry. + */ + if (lifc.lifc_len + 2 * sizeof(lifreq) < bufsiz) + break; + } + if ((n == -1) && errno != EINVAL) + goto cleanup; + + if (bufsiz > 1000000) + goto cleanup; + + memput(buf, bufsiz); + bufsiz += 4096; + } + + /* Parse system's interface list. */ + cplim = buf + lifc.lifc_len; /*%< skip over if's with big ifr_addr's */ + for (cp = buf; + (*have_v4 == 0 || *have_v6 == 0) && cp < cplim; + cp += cpsize) { + memcpy(&lifreq, cp, sizeof lifreq); +#ifdef HAVE_SA_LEN +#ifdef FIX_ZERO_SA_LEN + if (lifreq.lifr_addr.sa_len == 0) + lifreq.lifr_addr.sa_len = 16; +#endif +#ifdef HAVE_MINIMUM_IFREQ + cpsize = sizeof lifreq; + if (lifreq.lifr_addr.sa_len > sizeof (struct sockaddr)) + cpsize += (int)lifreq.lifr_addr.sa_len - + (int)(sizeof (struct sockaddr)); +#else + cpsize = sizeof lifreq.lifr_name + lifreq.lifr_addr.sa_len; +#endif /* HAVE_MINIMUM_IFREQ */ +#elif defined SIOCGIFCONF_ADDR + cpsize = sizeof lifreq; +#else + cpsize = sizeof lifreq.lifr_name; + /* XXX maybe this should be a hard error? */ + if (ioctl(s, SIOCGLIFADDR, (char *)&lifreq) < 0) + continue; +#endif + switch (lifreq.lifr_addr.ss_family) { + case AF_INET: + if (*have_v4 == 0) { + memcpy(&in4, + &((struct sockaddr_in *) + &lifreq.lifr_addr)->sin_addr, + sizeof in4); + if (in4.s_addr == INADDR_ANY) + break; + n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq); + if (n < 0) + break; + if ((lifreq.lifr_flags & IFF_UP) == 0) + break; + *have_v4 = 1; + } + break; + case AF_INET6: + if (*have_v6 == 0) { + memcpy(&in6, + &((struct sockaddr_in6 *) + &lifreq.lifr_addr)->sin6_addr, sizeof in6); + if (memcmp(&in6, &in6addr_any, sizeof in6) == 0) + break; + n = ioctl(s, SIOCGLIFFLAGS, (char *)&lifreq); + if (n < 0) + break; + if ((lifreq.lifr_flags & IFF_UP) == 0) + break; + *have_v6 = 1; + } + break; + } + } + if (buf != NULL) + memput(buf, bufsiz); + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return; + cleanup: + if (buf != NULL) + memput(buf, bufsiz); + if (s != -1) + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return; +} +#endif + +#if ( defined(__linux__) || defined(__linux) || defined(LINUX) ) +#ifndef IF_NAMESIZE +# ifdef IFNAMSIZ +# define IF_NAMESIZE IFNAMSIZ +# else +# define IF_NAMESIZE 16 +# endif +#endif +static void +scan_linux6(int *have_v6) { + FILE *proc = NULL; + char address[33]; + char name[IF_NAMESIZE+1]; + int ifindex, prefix, flag3, flag4; + + proc = fopen("/proc/net/if_inet6", "r"); + if (proc == NULL) + return; + + if (fscanf(proc, "%32[a-f0-9] %x %x %x %x %16s\n", + address, &ifindex, &prefix, &flag3, &flag4, name) == 6) + *have_v6 = 1; + fclose(proc); + return; +} +#endif + +static int +scan_interfaces(int *have_v4, int *have_v6) { + struct ifconf ifc; + union { + char _pad[256]; /*%< leave space for IPv6 addresses */ + struct ifreq ifreq; + } u; + struct in_addr in4; + struct in6_addr in6; + char *buf = NULL, *cp, *cplim; + static unsigned int bufsiz = 4095; + int s, n; + size_t cpsize; + + /* Set to zero. Used as loop terminators below. */ + *have_v4 = *have_v6 = 0; + +#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \ + !defined(IRIX_EMUL_IOCTL_SIOCGIFCONF) + /* + * Try to scan the interfaces using IPv6 ioctls(). + */ + scan_interfaces6(have_v4, have_v6); + if (*have_v4 != 0 && *have_v6 != 0) + return (0); +#endif +#ifdef __linux + scan_linux6(have_v6); +#endif + + /* Get interface list from system. */ + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + goto err_ret; + + /* + * Grow buffer until large enough to contain all interface + * descriptions. + */ + for (;;) { + buf = memget(bufsiz); + if (buf == NULL) + goto err_ret; + ifc.ifc_len = bufsiz; + ifc.ifc_buf = buf; +#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF + /* + * This is a fix for IRIX OS in which the call to ioctl with + * the flag SIOCGIFCONF may not return an entry for all the + * interfaces like most flavors of Unix. + */ + if (emul_ioctl(&ifc) >= 0) + break; +#else + if ((n = ioctl(s, SIOCGIFCONF, (char *)&ifc)) != -1) { + /* + * Some OS's just return what will fit rather + * than set EINVAL if the buffer is too small + * to fit all the interfaces in. If + * ifc.ifc_len is too near to the end of the + * buffer we will grow it just in case and + * retry. + */ + if (ifc.ifc_len + 2 * sizeof(u.ifreq) < bufsiz) + break; + } +#endif + if ((n == -1) && errno != EINVAL) + goto err_ret; + + if (bufsiz > 1000000) + goto err_ret; + + memput(buf, bufsiz); + bufsiz += 4096; + } + + /* Parse system's interface list. */ + cplim = buf + ifc.ifc_len; /*%< skip over if's with big ifr_addr's */ + for (cp = buf; + (*have_v4 == 0 || *have_v6 == 0) && cp < cplim; + cp += cpsize) { + memcpy(&u.ifreq, cp, sizeof u.ifreq); +#ifdef HAVE_SA_LEN +#ifdef FIX_ZERO_SA_LEN + if (u.ifreq.ifr_addr.sa_len == 0) + u.ifreq.ifr_addr.sa_len = 16; +#endif +#ifdef HAVE_MINIMUM_IFREQ + cpsize = sizeof u.ifreq; + if (u.ifreq.ifr_addr.sa_len > sizeof (struct sockaddr)) + cpsize += (int)u.ifreq.ifr_addr.sa_len - + (int)(sizeof (struct sockaddr)); +#else + cpsize = sizeof u.ifreq.ifr_name + u.ifreq.ifr_addr.sa_len; +#endif /* HAVE_MINIMUM_IFREQ */ + if (cpsize > sizeof u.ifreq && cpsize <= sizeof u) + memcpy(&u.ifreq, cp, cpsize); +#elif defined SIOCGIFCONF_ADDR + cpsize = sizeof u.ifreq; +#else + cpsize = sizeof u.ifreq.ifr_name; + /* XXX maybe this should be a hard error? */ + if (ioctl(s, SIOCGIFADDR, (char *)&u.ifreq) < 0) + continue; +#endif + switch (u.ifreq.ifr_addr.sa_family) { + case AF_INET: + if (*have_v4 == 0) { + memcpy(&in4, + &((struct sockaddr_in *) + &u.ifreq.ifr_addr)->sin_addr, + sizeof in4); + if (in4.s_addr == INADDR_ANY) + break; + n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq); + if (n < 0) + break; + if ((u.ifreq.ifr_flags & IFF_UP) == 0) + break; + *have_v4 = 1; + } + break; + case AF_INET6: + if (*have_v6 == 0) { + memcpy(&in6, + &((struct sockaddr_in6 *) + &u.ifreq.ifr_addr)->sin6_addr, + sizeof in6); + if (memcmp(&in6, &in6addr_any, sizeof in6) == 0) + break; + n = ioctl(s, SIOCGIFFLAGS, (char *)&u.ifreq); + if (n < 0) + break; + if ((u.ifreq.ifr_flags & IFF_UP) == 0) + break; + *have_v6 = 1; + } + break; + } + } + if (buf != NULL) + memput(buf, bufsiz); + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return (0); + err_ret: + if (buf != NULL) + memput(buf, bufsiz); + if (s != -1) + close(s); + /* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */ + return (-1); +} + +static struct hostent * +copyandmerge(struct hostent *he1, struct hostent *he2, int af, int *error_num) { + struct hostent *he = NULL; + int addresses = 1; /*%< NULL terminator */ + int names = 1; /*%< NULL terminator */ + int len = 0; + char **cpp, **npp; + + /* + * Work out array sizes; + */ + if (he1 != NULL) { + cpp = he1->h_addr_list; + while (*cpp != NULL) { + addresses++; + cpp++; + } + cpp = he1->h_aliases; + while (*cpp != NULL) { + names++; + cpp++; + } + } + + if (he2 != NULL) { + cpp = he2->h_addr_list; + while (*cpp != NULL) { + addresses++; + cpp++; + } + if (he1 == NULL) { + cpp = he2->h_aliases; + while (*cpp != NULL) { + names++; + cpp++; + } + } + } + + if (addresses == 1) { + *error_num = NO_ADDRESS; + return (NULL); + } + + he = memget(sizeof *he); + if (he == NULL) + goto no_recovery; + + he->h_addr_list = memget(sizeof(char *) * (addresses)); + if (he->h_addr_list == NULL) + goto cleanup0; + memset(he->h_addr_list, 0, sizeof(char *) * (addresses)); + + /* copy addresses */ + npp = he->h_addr_list; + if (he1 != NULL) { + cpp = he1->h_addr_list; + while (*cpp != NULL) { + *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + if (*npp == NULL) + goto cleanup1; + /* convert to mapped if required */ + if (af == AF_INET6 && he1->h_addrtype == AF_INET) { + memcpy(*npp, in6addr_mapped, + sizeof in6addr_mapped); + memcpy(*npp + sizeof in6addr_mapped, *cpp, + INADDRSZ); + } else { + memcpy(*npp, *cpp, + (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + } + cpp++; + npp++; + } + } + + if (he2 != NULL) { + cpp = he2->h_addr_list; + while (*cpp != NULL) { + *npp = memget((af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + if (*npp == NULL) + goto cleanup1; + /* convert to mapped if required */ + if (af == AF_INET6 && he2->h_addrtype == AF_INET) { + memcpy(*npp, in6addr_mapped, + sizeof in6addr_mapped); + memcpy(*npp + sizeof in6addr_mapped, *cpp, + INADDRSZ); + } else { + memcpy(*npp, *cpp, + (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + } + cpp++; + npp++; + } + } + + he->h_aliases = memget(sizeof(char *) * (names)); + if (he->h_aliases == NULL) + goto cleanup1; + memset(he->h_aliases, 0, sizeof(char *) * (names)); + + /* copy aliases */ + npp = he->h_aliases; + cpp = (he1 != NULL) ? he1->h_aliases : he2->h_aliases; + while (*cpp != NULL) { + len = strlen (*cpp) + 1; + *npp = memget(len); + if (*npp == NULL) + goto cleanup2; + strcpy(*npp, *cpp); + npp++; + cpp++; + } + + /* copy hostname */ + he->h_name = memget(strlen((he1 != NULL) ? + he1->h_name : he2->h_name) + 1); + if (he->h_name == NULL) + goto cleanup2; + strcpy(he->h_name, (he1 != NULL) ? he1->h_name : he2->h_name); + + /* set address type and length */ + he->h_addrtype = af; + he->h_length = (af == AF_INET) ? INADDRSZ : IN6ADDRSZ; + return(he); + + cleanup2: + cpp = he->h_aliases; + while (*cpp != NULL) { + memput(*cpp, strlen(*cpp) + 1); + cpp++; + } + memput(he->h_aliases, sizeof(char *) * (names)); + + cleanup1: + cpp = he->h_addr_list; + while (*cpp != NULL) { + memput(*cpp, (af == AF_INET) ? INADDRSZ : IN6ADDRSZ); + *cpp = NULL; + cpp++; + } + memput(he->h_addr_list, sizeof(char *) * (addresses)); + + cleanup0: + memput(he, sizeof *he); + + no_recovery: + *error_num = NO_RECOVERY; + return (NULL); +} + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ho) { + net_data->ho = (*net_data->irs->ho_map)(net_data->irs); + if (!net_data->ho || !net_data->res) { + error: + errno = EIO; + +#ifdef SUNW_SETHERRNO + h_errno = NETDB_INTERNAL; +#endif /* SUNW_SETHERRNO */ + if (net_data && net_data->res) + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + + (*net_data->ho->res_set)(net_data->ho, net_data->res, NULL); + } + + return (net_data); +} + +static void +freepvt(struct net_data *net_data) { + if (net_data->ho_data) { + free(net_data->ho_data); + net_data->ho_data = NULL; + } +} + +static struct hostent * +fakeaddr(const char *name, int af, struct net_data *net_data) { + struct pvt *pvt; + + freepvt(net_data); + net_data->ho_data = malloc(sizeof (struct pvt)); + if (!net_data->ho_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->ho_data; +#ifndef __bsdi__ + /* + * Unlike its forebear(inet_aton), our friendly inet_pton() is strict + * in its interpretation of its input, and it will only return "1" if + * the input string is a formally valid(and thus unambiguous with + * respect to host names) internet address specification for this AF. + * + * This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now. + */ + if (inet_pton(af, name, pvt->addr) != 1) { +#else + /* BSDI XXX + * We put this back to inet_aton -- we really want the old behavior + * Long live 127.1... + */ + if ((af != AF_INET || + inet_aton(name, (struct in_addr *)pvt->addr) != 1) && + inet_pton(af, name, pvt->addr) != 1) { +#endif + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + strncpy(pvt->name, name, NS_MAXDNAME); + pvt->name[NS_MAXDNAME] = '\0'; + if (af == AF_INET && (net_data->res->options & RES_USE_INET6) != 0U) { + map_v4v6_address(pvt->addr, pvt->addr); + af = AF_INET6; + } + pvt->host.h_addrtype = af; + switch(af) { + case AF_INET: + pvt->host.h_length = NS_INADDRSZ; + break; + case AF_INET6: + pvt->host.h_length = NS_IN6ADDRSZ; + break; + default: + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt->host.h_name = pvt->name; + pvt->host.h_aliases = pvt->aliases; + pvt->aliases[0] = NULL; + pvt->addrs[0] = (char *)pvt->addr; + pvt->addrs[1] = NULL; + pvt->host.h_addr_list = pvt->addrs; + RES_SET_H_ERRNO(net_data->res, NETDB_SUCCESS); + return (&pvt->host); +} + +#ifdef grot /*%< for future use in gethostbyaddr(), for "SUNSECURITY" */ + struct hostent *rhp; + char **haddr; + u_long old_options; + char hname2[MAXDNAME+1]; + + 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 = net_data->res->options; + net_data->res->options &= ~RES_DNSRCH; + net_data->res->options |= RES_DEFNAMES; + if (!(rhp = gethostbyname(hname2))) { + net_data->res->options = old_options; + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + net_data->res->options = old_options; + for (haddr = rhp->h_addr_list; *haddr; haddr++) + if (!memcmp(*haddr, addr, INADDRSZ)) + break; + if (!*haddr) { + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + } +#endif /* grot */ +#endif /*__BIND_NOSTATIC*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/gethostent_r.c b/usr/src/lib/libresolv2_joy/common/irs/gethostent_r.c new file mode 100644 index 0000000000..1971677c5d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/gethostent_r.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: gethostent_r.c,v 1.9 2005/09/03 12:41:37 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int gethostent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/param.h> +#include <port_after.h> + +#pragma redefine extname res_gethostbyname joy_res_gethostbyname +#pragma redefine extname res_gethostbyaddr joy_res_gethostbyaddr + +#ifdef HOST_R_RETURN + +static HOST_R_RETURN +copy_hostent(struct hostent *, struct hostent *, HOST_R_COPY_ARGS); + +HOST_R_RETURN +gethostbyname_r(const char *name, struct hostent *hptr, HOST_R_ARGS) { + struct hostent *he = gethostbyname(name); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif + +#ifdef HOST_R_ERRNO + HOST_R_ERRNO; +#endif + +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif +} + +HOST_R_RETURN +gethostbyaddr_r(const char *addr, int len, int type, + struct hostent *hptr, HOST_R_ARGS) { + struct hostent *he = gethostbyaddr(addr, len, type); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif + +#ifdef HOST_R_ERRNO + HOST_R_ERRNO; +#endif + +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif +} + +/*% + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +HOST_R_RETURN +gethostent_r(struct hostent *hptr, HOST_R_ARGS) { + struct hostent *he = gethostent(); +#ifdef HOST_R_SETANSWER + int n = 0; +#endif + +#ifdef HOST_R_ERRNO + HOST_R_ERRNO; +#endif + +#ifdef HOST_R_SETANSWER + if (he == NULL || (n = copy_hostent(he, hptr, HOST_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = hptr; + + return (n); +#else + if (he == NULL) + return (HOST_R_BAD); + + return (copy_hostent(he, hptr, HOST_R_COPY)); +#endif +} + +HOST_R_SET_RETURN +#ifdef HOST_R_ENT_ARGS +sethostent_r(int stay_open, HOST_R_ENT_ARGS) +#else +sethostent_r(int stay_open) +#endif +{ +#ifdef HOST_R_ENT_ARGS + UNUSED(hdptr); +#endif + sethostent(stay_open); +#ifdef HOST_R_SET_RESULT + return (HOST_R_SET_RESULT); +#endif +} + +HOST_R_END_RETURN +#ifdef HOST_R_ENT_ARGS +endhostent_r(HOST_R_ENT_ARGS) +#else +endhostent_r(void) +#endif +{ +#ifdef HOST_R_ENT_ARGS + UNUSED(hdptr); +#endif + endhostent(); + HOST_R_END_RESULT(HOST_R_OK); +} + +/* Private */ + +#ifndef HOSTENT_DATA +static HOST_R_RETURN +copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) { + char *cp; + char **ptr; + int i, n; + int nptr, len; + + /* Find out the amount of space required to store the answer. */ + nptr = 2; /*%< NULL ptrs */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; he->h_addr_list[i]; i++, nptr++) { + len += he->h_length; + } + for (i = 0; he->h_aliases[i]; i++, nptr++) { + len += strlen(he->h_aliases[i]) + 1; + } + len += strlen(he->h_name) + 1; + len += nptr * sizeof(char*); + + if (len > buflen) { + errno = ERANGE; + return (HOST_R_BAD); + } + + /* copy address size and type */ + hptr->h_addrtype = he->h_addrtype; + n = hptr->h_length = he->h_length; + + ptr = (char **)ALIGN(buf); + cp = (char *)ALIGN(buf) + nptr * sizeof(char *); + + /* copy address list */ + hptr->h_addr_list = ptr; + for (i = 0; he->h_addr_list[i]; i++ , ptr++) { + memcpy(cp, he->h_addr_list[i], n); + hptr->h_addr_list[i] = cp; + cp += n; + } + hptr->h_addr_list[i] = NULL; + ptr++; + + /* copy official name */ + n = strlen(he->h_name) + 1; + strcpy(cp, he->h_name); + hptr->h_name = cp; + cp += n; + + /* copy aliases */ + hptr->h_aliases = ptr; + for (i = 0 ; he->h_aliases[i]; i++) { + n = strlen(he->h_aliases[i]) + 1; + strcpy(cp, he->h_aliases[i]); + hptr->h_aliases[i] = cp; + cp += n; + } + hptr->h_aliases[i] = NULL; + + return (HOST_R_OK); +} +#else /* !HOSTENT_DATA */ +static int +copy_hostent(struct hostent *he, struct hostent *hptr, HOST_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy address size and type */ + hptr->h_addrtype = he->h_addrtype; + n = hptr->h_length = he->h_length; + + /* copy up to first 35 addresses */ + i = 0; + cp = hdptr->hostbuf; + eob = hdptr->hostbuf + sizeof(hdptr->hostbuf); + hptr->h_addr_list = hdptr->h_addr_ptrs; + while (he->h_addr_list[i] && i < (_MAXADDRS)) { + if (n < (eob - cp)) { + memcpy(cp, he->h_addr_list[i], n); + hptr->h_addr_list[i] = cp; + cp += n; + } else { + break; + } + i++; + } + hptr->h_addr_list[i] = NULL; + + /* copy official name */ + if ((n = strlen(he->h_name) + 1) < (eob - cp)) { + strcpy(cp, he->h_name); + hptr->h_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + hptr->h_aliases = hdptr->host_aliases; + while (he->h_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(he->h_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, he->h_aliases[i]); + hptr->h_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + hptr->h_aliases[i] = NULL; + + return (HOST_R_OK); +} +#endif /* !HOSTENT_DATA */ +#else /* HOST_R_RETURN */ + static int gethostent_r_unknown_system = 0; +#endif /* HOST_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/getnameinfo.c b/usr/src/lib/libresolv2_joy/common/irs/getnameinfo.c new file mode 100644 index 0000000000..360bda8bfe --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/getnameinfo.c @@ -0,0 +1,334 @@ +/* + * Issues to be discussed: + * - Thread safe-ness must be checked + */ + +#if ( defined(__linux__) || defined(__linux) || defined(LINUX) ) +#ifndef IF_NAMESIZE +# ifdef IFNAMSIZ +# define IF_NAMESIZE IFNAMSIZ +# else +# define IF_NAMESIZE 16 +# endif +#endif +#endif + +/* + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by WIDE Project and + * its contributors. + * 4. 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. + */ + +#include <port_before.h> + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> +#include <net/if.h> + +#include <netdb.h> +#include <resolv_joy.h> +#include <string.h> +#include <stddef.h> + +#include <port_after.h> + +/*% + * Note that a_off will be dynamically adjusted so that to be consistent + * with the definition of sockaddr_in{,6}. + * The value presented below is just a guess. + */ +static struct afd { + int a_af; + int a_addrlen; + size_t a_socklen; + int a_off; +} afdl [] = { + /* first entry is linked last... */ + {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr)}, + {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr)}, + {0, 0, 0, 0}, +}; + +struct sockinet { +#ifdef HAVE_SA_LEN + u_char si_len; +#endif + u_char si_family; + u_short si_port; +}; + +static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *, + size_t, int)); +#ifdef HAVE_SIN6_SCOPE_ID +static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t, int)); +#endif + +int +getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) + const struct sockaddr *sa; + size_t salen; + char *host; + size_t hostlen; + char *serv; + size_t servlen; + int flags; +{ + struct afd *afd; + struct servent *sp; + struct hostent *hp; + u_short port; +#ifdef HAVE_SA_LEN + size_t len; +#endif + int family, i; + const char *addr; + char *p; + char numserv[512]; + char numaddr[512]; + const struct sockaddr_in6 *sin6; + + if (sa == NULL) + return EAI_FAIL; + +#ifdef HAVE_SA_LEN + len = sa->sa_len; + if (len != salen) return EAI_FAIL; +#endif + + family = sa->sa_family; + for (i = 0; afdl[i].a_af; i++) + if (afdl[i].a_af == family) { + afd = &afdl[i]; + goto found; + } + return EAI_FAMILY; + + found: + if (salen != afd->a_socklen) return EAI_FAIL; + + port = ((const struct sockinet *)sa)->si_port; /*%< network byte order */ + addr = (const char *)sa + afd->a_off; + + if (serv == NULL || servlen == 0U) { + /* + * rfc2553bis says that serv == NULL or servlen == 0 means that + * the caller does not want the result. + */ + } else if (flags & NI_NUMERICSERV) { + sprintf(numserv, "%d", ntohs(port)); + if (strlen(numserv) > servlen) + return EAI_MEMORY; + strcpy(serv, numserv); + } else { + sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp"); + if (sp) { + if (strlen(sp->s_name) + 1 > servlen) + return EAI_MEMORY; + strcpy(serv, sp->s_name); + } else + return EAI_NONAME; + } + + switch (sa->sa_family) { + case AF_INET: + if (ntohl(*(const u_int32_t *)addr) >> IN_CLASSA_NSHIFT == 0) + flags |= NI_NUMERICHOST; + break; + case AF_INET6: + sin6 = (const struct sockaddr_in6 *)sa; + switch (sin6->sin6_addr.s6_addr[0]) { + case 0x00: + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + ; + else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) + ; + else + flags |= NI_NUMERICHOST; + break; + default: + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) + flags |= NI_NUMERICHOST; + else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + flags |= NI_NUMERICHOST; + break; + } + break; + } + if (host == NULL || hostlen == 0U) { + /* + * rfc2553bis says that host == NULL or hostlen == 0 means that + * the caller does not want the result. + */ + } else if (flags & NI_NUMERICHOST) { + goto numeric; + } else { + hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); + + if (hp) { + if (flags & NI_NOFQDN) { + p = strchr(hp->h_name, '.'); + if (p) *p = '\0'; + } + if (strlen(hp->h_name) + 1 > hostlen) + return EAI_MEMORY; + strcpy(host, hp->h_name); + } else { + if (flags & NI_NAMEREQD) + return EAI_NONAME; + numeric: + switch(afd->a_af) { + case AF_INET6: + { + int error; + + if ((error = ip6_parsenumeric(sa, addr, host, + hostlen, + flags)) != 0) + return(error); + break; + } + + default: + if (inet_ntop(afd->a_af, addr, numaddr, + sizeof(numaddr)) == NULL) + return EAI_NONAME; + if (strlen(numaddr) + 1 > hostlen) + return EAI_MEMORY; + strcpy(host, numaddr); + } + } + } + return(0); +} + +static int +ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host, + size_t hostlen, int flags) +{ + size_t numaddrlen; + char numaddr[512]; + +#ifndef HAVE_SIN6_SCOPE_ID + UNUSED(sa); + UNUSED(flags); +#endif + + if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) + == NULL) + return EAI_SYSTEM; + + numaddrlen = strlen(numaddr); + if (numaddrlen + 1 > hostlen) /*%< don't forget terminator */ + return EAI_MEMORY; + strcpy(host, numaddr); + +#ifdef HAVE_SIN6_SCOPE_ID + if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) { + char scopebuf[MAXHOSTNAMELEN]; /*%< XXX */ + int scopelen; + + /* ip6_sa2str never fails */ + scopelen = ip6_sa2str((const struct sockaddr_in6 *)sa, + scopebuf, sizeof(scopebuf), flags); + + if (scopelen + 1 + numaddrlen + 1 > hostlen) + return EAI_MEMORY; + + /* construct <numeric-addr><delim><scopeid> */ + memcpy(host + numaddrlen + 1, scopebuf, + scopelen); + host[numaddrlen] = SCOPE_DELIMITER; + host[numaddrlen + 1 + scopelen] = '\0'; + } +#endif + + return 0; +} + +#ifdef HAVE_SIN6_SCOPE_ID +/* ARGSUSED */ +static int +ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, + size_t bufsiz, int flags) +{ +#ifdef USE_IFNAMELINKID + unsigned int ifindex = (unsigned int)sa6->sin6_scope_id; + const struct in6_addr *a6 = &sa6->sin6_addr; +#endif + char tmp[64]; + +#ifdef NI_NUMERICSCOPE + if (flags & NI_NUMERICSCOPE) { + sprintf(tmp, "%u", sa6->sin6_scope_id); + if (bufsiz != 0U) { + strncpy(buf, tmp, bufsiz - 1); + buf[bufsiz - 1] = '\0'; + } + return(strlen(tmp)); + } +#endif + +#ifdef USE_IFNAMELINKID + /* + * For a link-local address, convert the index to an interface + * name, assuming a one-to-one mapping between links and interfaces. + * Note, however, that this assumption is stronger than the + * specification of the scoped address architecture; the + * specficication says that more than one interfaces can belong to + * a single link. + */ + + /* if_indextoname() does not take buffer size. not a good api... */ + if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) && + bufsiz >= IF_NAMESIZE) { + char *p = if_indextoname(ifindex, buf); + if (p) { + return(strlen(p)); + } + } +#endif + + /* last resort */ + sprintf(tmp, "%u", sa6->sin6_scope_id); + if (bufsiz != 0U) { + strncpy(buf, tmp, bufsiz - 1); + buf[bufsiz - 1] = '\0'; + } + return(strlen(tmp)); +} +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/getnetent.c b/usr/src/lib/libresolv2_joy/common/irs/getnetent.c new file mode 100644 index 0000000000..0d00699e81 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/getnetent.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getnetent.c,v 1.7 2005/04/27 04:56:25 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "irs_data.h" + +/* Definitions */ + +struct pvt { + struct netent netent; + char * aliases[1]; + char name[MAXDNAME + 1]; +}; + +/* Forward */ + +static struct net_data *init(void); +static struct netent *nw_to_net(struct nwent *, struct net_data *); +static void freepvt(struct net_data *); +static struct netent *fakeaddr(const char *, int af, struct net_data *); + +/* Portability */ + +#ifndef INADDR_NONE +# define INADDR_NONE 0xffffffff +#endif + +/* Public */ + +struct netent * +getnetent() { + struct net_data *net_data = init(); + + return (getnetent_p(net_data)); +} + +struct netent * +getnetbyname(const char *name) { + struct net_data *net_data = init(); + + return (getnetbyname_p(name, net_data)); +} + +struct netent * +getnetbyaddr(unsigned long net, int type) { + struct net_data *net_data = init(); + + return (getnetbyaddr_p(net, type, net_data)); +} + +void +setnetent(int stayopen) { + struct net_data *net_data = init(); + + setnetent_p(stayopen, net_data); +} + + +void +endnetent() { + struct net_data *net_data = init(); + + endnetent_p(net_data); +} + +/* Shared private. */ + +struct netent * +getnetent_p(struct net_data *net_data) { + struct irs_nw *nw; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + net_data->nww_last = (*nw->next)(nw); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + return (net_data->nw_last); +} + +struct netent * +getnetbyname_p(const char *name, struct net_data *net_data) { + struct irs_nw *nw; + struct netent *np; + char **nap; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + if (net_data->nw_stayopen && net_data->nw_last) { + if (!strcmp(net_data->nw_last->n_name, name)) + return (net_data->nw_last); + for (nap = net_data->nw_last->n_aliases; nap && *nap; nap++) + if (!strcmp(name, *nap)) + return (net_data->nw_last); + } + if ((np = fakeaddr(name, AF_INET, net_data)) != NULL) + return (np); + net_data->nww_last = (*nw->byname)(nw, name, AF_INET); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + if (!net_data->nw_stayopen) + endnetent(); + return (net_data->nw_last); +} + +struct netent * +getnetbyaddr_p(unsigned long net, int type, struct net_data *net_data) { + struct irs_nw *nw; + u_char addr[4]; + int bits; + + if (!net_data || !(nw = net_data->nw)) + return (NULL); + if (net_data->nw_stayopen && net_data->nw_last) + if (type == net_data->nw_last->n_addrtype && + net == net_data->nw_last->n_net) + return (net_data->nw_last); + + /* cannonize net(host order) */ + if (net < 256UL) { + net <<= 24; + bits = 8; + } else if (net < 65536UL) { + net <<= 16; + bits = 16; + } else if (net < 16777216UL) { + net <<= 8; + bits = 24; + } else + bits = 32; + + /* convert to net order */ + addr[0] = (0xFF000000 & net) >> 24; + addr[1] = (0x00FF0000 & net) >> 16; + addr[2] = (0x0000FF00 & net) >> 8; + addr[3] = (0x000000FF & net); + + /* reduce bits to as close to natural number as possible */ + if ((bits == 32) && (addr[0] < 224) && (addr[3] == 0)) { + if ((addr[0] < 192) && (addr[2] == 0)) { + if ((addr[0] < 128) && (addr[1] == 0)) + bits = 8; + else + bits = 16; + } else { + bits = 24; + } + } + + net_data->nww_last = (*nw->byaddr)(nw, addr, bits, AF_INET); + net_data->nw_last = nw_to_net(net_data->nww_last, net_data); + if (!net_data->nw_stayopen) + endnetent(); + return (net_data->nw_last); +} + + + + +void +setnetent_p(int stayopen, struct net_data *net_data) { + struct irs_nw *nw; + + if (!net_data || !(nw = net_data->nw)) + return; + freepvt(net_data); + (*nw->rewind)(nw); + net_data->nw_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endnetent_p(struct net_data *net_data) { + struct irs_nw *nw; + + if ((net_data != NULL) && ((nw = net_data->nw) != NULL)) + (*nw->minimize)(nw); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->nw) { + net_data->nw = (*net_data->irs->nw_map)(net_data->irs); + + if (!net_data->nw || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->nw->res_set)(net_data->nw, net_data->res, NULL); + } + + return (net_data); +} + +static void +freepvt(struct net_data *net_data) { + if (net_data->nw_data) { + free(net_data->nw_data); + net_data->nw_data = NULL; + } +} + +static struct netent * +fakeaddr(const char *name, int af, struct net_data *net_data) { + struct pvt *pvt; + const char *cp; + u_long tmp; + + if (af != AF_INET) { + /* XXX should support IPv6 some day */ + errno = EAFNOSUPPORT; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + if (!isascii((unsigned char)(name[0])) || + !isdigit((unsigned char)(name[0]))) + return (NULL); + for (cp = name; *cp; ++cp) + if (!isascii(*cp) || (!isdigit((unsigned char)*cp) && *cp != '.')) + return (NULL); + if (*--cp == '.') + return (NULL); + + /* All-numeric, no dot at the end. */ + + tmp = inet_network(name); + if (tmp == INADDR_NONE) { + RES_SET_H_ERRNO(net_data->res, HOST_NOT_FOUND); + return (NULL); + } + + /* Valid network number specified. + * Fake up a netent as if we'd actually + * done a lookup. + */ + freepvt(net_data); + net_data->nw_data = malloc(sizeof (struct pvt)); + if (!net_data->nw_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->nw_data; + + strncpy(pvt->name, name, MAXDNAME); + pvt->name[MAXDNAME] = '\0'; + pvt->netent.n_name = pvt->name; + pvt->netent.n_addrtype = AF_INET; + pvt->netent.n_aliases = pvt->aliases; + pvt->aliases[0] = NULL; + pvt->netent.n_net = tmp; + + return (&pvt->netent); +} + +static struct netent * +nw_to_net(struct nwent *nwent, struct net_data *net_data) { + struct pvt *pvt; + u_long addr = 0; + int i; + int msbyte; + + if (!nwent || nwent->n_addrtype != AF_INET) + return (NULL); + freepvt(net_data); + net_data->nw_data = malloc(sizeof (struct pvt)); + if (!net_data->nw_data) { + errno = ENOMEM; + RES_SET_H_ERRNO(net_data->res, NETDB_INTERNAL); + return (NULL); + } + pvt = net_data->nw_data; + pvt->netent.n_name = nwent->n_name; + pvt->netent.n_aliases = nwent->n_aliases; + pvt->netent.n_addrtype = nwent->n_addrtype; + +/*% + * What this code does: Converts net addresses from network to host form. + * + * msbyte: the index of the most significant byte in the n_addr array. + * + * Shift bytes in significant order into addr. When all signicant + * bytes are in, zero out bits in the LSB that are not part of the network. + */ + msbyte = nwent->n_length / 8 + + ((nwent->n_length % 8) != 0 ? 1 : 0) - 1; + for (i = 0; i <= msbyte; i++) + addr = (addr << 8) | ((unsigned char *)nwent->n_addr)[i]; + i = (32 - nwent->n_length) % 8; + if (i != 0) + addr &= ~((1 << (i + 1)) - 1); + pvt->netent.n_net = addr; + return (&pvt->netent); +} + +#endif /*__BIND_NOSTATIC*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/getnetent_r.c b/usr/src/lib/libresolv2_joy/common/irs/getnetent_r.c new file mode 100644 index 0000000000..9fb52bc394 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/getnetent_r.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetent_r.c,v 1.6 2005/09/03 12:41:38 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getnetent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/param.h> +#include <port_after.h> + +#ifdef NET_R_RETURN + +static NET_R_RETURN +copy_netent(struct netent *, struct netent *, NET_R_COPY_ARGS); + +NET_R_RETURN +getnetbyname_r(const char *name, struct netent *nptr, NET_R_ARGS) { + struct netent *ne = getnetbyname(name); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +#endif +} + +#ifndef GETNETBYADDR_ADDR_T +#define GETNETBYADDR_ADDR_T long +#endif +NET_R_RETURN +getnetbyaddr_r(GETNETBYADDR_ADDR_T addr, int type, struct netent *nptr, NET_R_ARGS) { + struct netent *ne = getnetbyaddr(addr, type); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else + + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +#endif +} + +/*% + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +NET_R_RETURN +getnetent_r(struct netent *nptr, NET_R_ARGS) { + struct netent *ne = getnetent(); +#ifdef NET_R_SETANSWER + int n = 0; + + if (ne == NULL || (n = copy_netent(ne, nptr, NET_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = ne; + if (ne == NULL) + *h_errnop = h_errno; + return (n); +#else + + if (ne == NULL) + return (NET_R_BAD); + + return (copy_netent(ne, nptr, NET_R_COPY)); +#endif +} + +NET_R_SET_RETURN +#ifdef NET_R_ENT_ARGS +setnetent_r(int stay_open, NET_R_ENT_ARGS) +#else +setnetent_r(int stay_open) +#endif +{ +#ifdef NET_R_ENT_ARGS + UNUSED(ndptr); +#endif + setnetent(stay_open); +#ifdef NET_R_SET_RESULT + return (NET_R_SET_RESULT); +#endif +} + +NET_R_END_RETURN +#ifdef NET_R_ENT_ARGS +endnetent_r(NET_R_ENT_ARGS) +#else +endnetent_r() +#endif +{ +#ifdef NET_R_ENT_ARGS + UNUSED(ndptr); +#endif + endnetent(); + NET_R_END_RESULT(NET_R_OK); +} + +/* Private */ + +#ifndef NETENT_DATA +static NET_R_RETURN +copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /*%< NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; ne->n_aliases[i]; i++, numptr++) { + len += strlen(ne->n_aliases[i]) + 1; + } + len += strlen(ne->n_name) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (NET_R_BAD); + } + + /* copy net value and type */ + nptr->n_addrtype = ne->n_addrtype; + nptr->n_net = ne->n_net; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(ne->n_name) + 1; + strcpy(cp, ne->n_name); + nptr->n_name = cp; + cp += n; + + /* copy aliases */ + nptr->n_aliases = (char **)ALIGN(buf); + for (i = 0 ; ne->n_aliases[i]; i++) { + n = strlen(ne->n_aliases[i]) + 1; + strcpy(cp, ne->n_aliases[i]); + nptr->n_aliases[i] = cp; + cp += n; + } + nptr->n_aliases[i] = NULL; + + return (NET_R_OK); +} +#else /* !NETENT_DATA */ +static int +copy_netent(struct netent *ne, struct netent *nptr, NET_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy net value and type */ + nptr->n_addrtype = ne->n_addrtype; + nptr->n_net = ne->n_net; + + /* copy official name */ + cp = ndptr->line; + eob = ndptr->line + sizeof(ndptr->line); + if ((n = strlen(ne->n_name) + 1) < (eob - cp)) { + strcpy(cp, ne->n_name); + nptr->n_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + nptr->n_aliases = ndptr->net_aliases; + while (ne->n_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(ne->n_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, ne->n_aliases[i]); + nptr->n_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + nptr->n_aliases[i] = NULL; + + return (NET_R_OK); +} +#endif /* !NETENT_DATA */ +#else /* NET_R_RETURN */ + static int getnetent_r_unknown_system = 0; +#endif /* NET_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/getnetgrent.c b/usr/src/lib/libresolv2_joy/common/irs/getnetgrent.c new file mode 100644 index 0000000000..40b3e5a8ad --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/getnetgrent.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1996-1999, 2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetgrent.c,v 1.6 2008/11/14 02:36:51 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv_joy.h> +#include <stdio.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + + +/* Public */ + +#ifndef SETNETGRENT_ARGS +#define SETNETGRENT_ARGS const char *netgroup +#endif +void +setnetgrent(SETNETGRENT_ARGS) { + struct net_data *net_data = init(); + + setnetgrent_p(netgroup, net_data); +} + +void +endnetgrent(void) { + struct net_data *net_data = init(); + + endnetgrent_p(net_data); +} + +#ifndef INNETGR_ARGS +#define INNETGR_ARGS const char *netgroup, const char *host, \ + const char *user, const char *domain +#endif +int +innetgr(INNETGR_ARGS) { + struct net_data *net_data = init(); + + return (innetgr_p(netgroup, host, user, domain, net_data)); +} + +int +getnetgrent(NGR_R_CONST char **host, NGR_R_CONST char **user, + NGR_R_CONST char **domain) +{ + struct net_data *net_data = init(); + const char *ch, *cu, *cd; + int ret; + + ret = getnetgrent_p(&ch, &cu, &cd, net_data); + if (ret != 1) + return (ret); + + DE_CONST(ch, *host); + DE_CONST(cu, *user); + DE_CONST(cd, *domain); + return (ret); +} + +/* Shared private. */ + +void +setnetgrent_p(const char *netgroup, struct net_data *net_data) { + struct irs_ng *ng; + + if ((net_data != NULL) && ((ng = net_data->ng) != NULL)) + (*ng->rewind)(ng, netgroup); +} + +void +endnetgrent_p(struct net_data *net_data) { + struct irs_ng *ng; + + if (!net_data) + return; + if ((ng = net_data->ng) != NULL) + (*ng->close)(ng); + net_data->ng = NULL; +} + +int +innetgr_p(const char *netgroup, const char *host, + const char *user, const char *domain, + struct net_data *net_data) { + struct irs_ng *ng; + + if (!net_data || !(ng = net_data->ng)) + return (0); + return ((*ng->test)(ng, netgroup, host, user, domain)); +} + +int +getnetgrent_p(const char **host, const char **user, const char **domain, + struct net_data *net_data ) { + struct irs_ng *ng; + + if (!net_data || !(ng = net_data->ng)) + return (0); + return ((*ng->next)(ng, host, user, domain)); +} + +/* Private */ + +static struct net_data * +init(void) { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->ng) { + net_data->ng = (*net_data->irs->ng_map)(net_data->irs); + if (!net_data->ng) { + error: + errno = EIO; + return (NULL); + } + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/getnetgrent_r.c b/usr/src/lib/libresolv2_joy/common/irs/getnetgrent_r.c new file mode 100644 index 0000000000..aa8810320d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/getnetgrent_r.c @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1998, 1999, 2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getnetgrent_r.c,v 1.14 2008/11/14 02:36:51 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getnetgrent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <stdlib.h> +#include <port_after.h> + +#ifdef NGR_R_RETURN +#ifndef NGR_R_PRIVATE +#define NGR_R_PRIVATE 0 +#endif + +static NGR_R_RETURN +copy_protoent(NGR_R_CONST char **, NGR_R_CONST char **, NGR_R_CONST char **, + const char *, const char *, const char *, NGR_R_COPY_ARGS); + +NGR_R_RETURN +innetgr_r(const char *netgroup, const char *host, const char *user, + const char *domain) { + char *ng, *ho, *us, *dom; + + DE_CONST(netgroup, ng); + DE_CONST(host, ho); + DE_CONST(user, us); + DE_CONST(domain, dom); + + return (innetgr(ng, ho, us, dom)); +} + +/*% + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +NGR_R_RETURN +getnetgrent_r(NGR_R_CONST char **machinep, NGR_R_CONST char **userp, + NGR_R_CONST char **domainp, NGR_R_ARGS) +{ + NGR_R_CONST char *mp, *up, *dp; + int res = getnetgrent(&mp, &up, &dp); + + if (res != 1) + return (res); + + return (copy_protoent(machinep, userp, domainp, + mp, up, dp, NGR_R_COPY)); +} + +#if NGR_R_PRIVATE == 2 +struct private { + char *buf; +}; + +#endif +NGR_R_SET_RETURN +#ifdef NGR_R_SET_ARGS +setnetgrent_r(NGR_R_SET_CONST char *netgroup, NGR_R_SET_ARGS) +#else +setnetgrent_r(NGR_R_SET_CONST char *netgroup) +#endif +{ +#if NGR_R_PRIVATE == 2 + struct private *p; +#endif + char *tmp; +#if defined(NGR_R_SET_ARGS) && NGR_R_PRIVATE == 0 + UNUSED(buf); + UNUSED(buflen); +#endif + + DE_CONST(netgroup, tmp); + setnetgrent(tmp); + +#if NGR_R_PRIVATE == 1 + *buf = NULL; +#elif NGR_R_PRIVATE == 2 + *buf = p = malloc(sizeof(struct private)); + if (p == NULL) +#ifdef NGR_R_SET_RESULT + return (NGR_R_BAD); +#else + return; +#endif + p->buf = NULL; +#endif +#ifdef NGR_R_SET_RESULT + return (NGR_R_SET_RESULT); +#endif +} + +NGR_R_END_RETURN +#ifdef NGR_R_END_ARGS +endnetgrent_r(NGR_R_END_ARGS) +#else +endnetgrent_r(void) +#endif +{ +#if NGR_R_PRIVATE == 2 + struct private *p = buf; +#endif +#if defined(NGR_R_SET_ARGS) && NGR_R_PRIVATE == 0 + UNUSED(buf); + UNUSED(buflen); +#endif + + endnetgrent(); +#if NGR_R_PRIVATE == 1 + if (*buf != NULL) + free(*buf); + *buf = NULL; +#elif NGR_R_PRIVATE == 2 + if (p->buf != NULL) + free(p->buf); + free(p); +#endif + NGR_R_END_RESULT(NGR_R_OK); +} + +/* Private */ + +static int +copy_protoent(NGR_R_CONST char **machinep, NGR_R_CONST char **userp, + NGR_R_CONST char **domainp, const char *mp, const char *up, + const char *dp, NGR_R_COPY_ARGS) +{ +#if NGR_R_PRIVATE == 2 + struct private *p = buf; +#endif + char *cp; + int n; + int len; + + /* Find out the amount of space required to store the answer. */ + len = 0; + if (mp != NULL) len += strlen(mp) + 1; + if (up != NULL) len += strlen(up) + 1; + if (dp != NULL) len += strlen(dp) + 1; + +#if NGR_R_PRIVATE == 1 + if (*buf != NULL) + free(*buf); + *buf = malloc(len); + if (*buf == NULL) + return(NGR_R_BAD); + cp = *buf; +#elif NGR_R_PRIVATE == 2 + if (p->buf) + free(p->buf); + p->buf = malloc(len); + if (p->buf == NULL) + return(NGR_R_BAD); + cp = p->buf; +#else + if (len > (int)buflen) { + errno = ERANGE; + return (NGR_R_BAD); + } + cp = buf; +#endif + + if (mp != NULL) { + n = strlen(mp) + 1; + strcpy(cp, mp); + *machinep = cp; + cp += n; + } else + *machinep = NULL; + + if (up != NULL) { + n = strlen(up) + 1; + strcpy(cp, up); + *userp = cp; + cp += n; + } else + *userp = NULL; + + if (dp != NULL) { + n = strlen(dp) + 1; + strcpy(cp, dp); + *domainp = cp; + cp += n; + } else + *domainp = NULL; + + return (NGR_R_OK); +} +#else /* NGR_R_RETURN */ + static int getnetgrent_r_unknown_system = 0; +#endif /* NGR_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/getprotoent.c b/usr/src/lib/libresolv2_joy/common/irs/getprotoent.c new file mode 100644 index 0000000000..32a1040916 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/getprotoent.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getprotoent.c,v 1.4 2005/04/27 04:56:26 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + +/* Public */ + +struct protoent * +getprotoent() { + struct net_data *net_data = init(); + + return (getprotoent_p(net_data)); +} + +struct protoent * +getprotobyname(const char *name) { + struct net_data *net_data = init(); + + return (getprotobyname_p(name, net_data)); +} + +struct protoent * +getprotobynumber(int proto) { + struct net_data *net_data = init(); + + return (getprotobynumber_p(proto, net_data)); +} + +void +setprotoent(int stayopen) { + struct net_data *net_data = init(); + + setprotoent_p(stayopen, net_data); +} + +void +endprotoent() { + struct net_data *net_data = init(); + + endprotoent_p(net_data); +} + +/* Shared private. */ + +struct protoent * +getprotoent_p(struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + net_data->pr_last = (*pr->next)(pr); + return (net_data->pr_last); +} + +struct protoent * +getprotobyname_p(const char *name, struct net_data *net_data) { + struct irs_pr *pr; + char **pap; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + if (net_data->pr_stayopen && net_data->pr_last) { + if (!strcmp(net_data->pr_last->p_name, name)) + return (net_data->pr_last); + for (pap = net_data->pr_last->p_aliases; pap && *pap; pap++) + if (!strcmp(name, *pap)) + return (net_data->pr_last); + } + net_data->pr_last = (*pr->byname)(pr, name); + if (!net_data->pr_stayopen) + endprotoent(); + return (net_data->pr_last); +} + +struct protoent * +getprotobynumber_p(int proto, struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return (NULL); + if (net_data->pr_stayopen && net_data->pr_last) + if (net_data->pr_last->p_proto == proto) + return (net_data->pr_last); + net_data->pr_last = (*pr->bynumber)(pr, proto); + if (!net_data->pr_stayopen) + endprotoent(); + return (net_data->pr_last); +} + +void +setprotoent_p(int stayopen, struct net_data *net_data) { + struct irs_pr *pr; + + if (!net_data || !(pr = net_data->pr)) + return; + (*pr->rewind)(pr); + net_data->pr_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endprotoent_p(struct net_data *net_data) { + struct irs_pr *pr; + + if ((net_data != NULL) && ((pr = net_data->pr) != NULL)) + (*pr->minimize)(pr); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->pr) { + net_data->pr = (*net_data->irs->pr_map)(net_data->irs); + + if (!net_data->pr || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->pr->res_set)(net_data->pr, net_data->res, NULL); + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/getprotoent_r.c b/usr/src/lib/libresolv2_joy/common/irs/getprotoent_r.c new file mode 100644 index 0000000000..d5d9ae53b6 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/getprotoent_r.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getprotoent_r.c,v 1.6 2006/08/01 01:14:16 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getprotoent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <port_after.h> + +#ifdef PROTO_R_RETURN + +static PROTO_R_RETURN +copy_protoent(struct protoent *, struct protoent *, PROTO_R_COPY_ARGS); + +PROTO_R_RETURN +getprotobyname_r(const char *name, struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotobyname(name); +#ifdef PROTO_R_SETANSWER + int n = 0; + + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif +} + +PROTO_R_RETURN +getprotobynumber_r(int proto, struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotobynumber(proto); +#ifdef PROTO_R_SETANSWER + int n = 0; + + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif +} + +/*% + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +PROTO_R_RETURN +getprotoent_r(struct protoent *pptr, PROTO_R_ARGS) { + struct protoent *pe = getprotoent(); +#ifdef PROTO_R_SETANSWER + int n = 0; + + if (pe == NULL || (n = copy_protoent(pe, pptr, PROTO_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = pptr; + + return (n); +#else + if (pe == NULL) + return (PROTO_R_BAD); + + return (copy_protoent(pe, pptr, PROTO_R_COPY)); +#endif +} + +PROTO_R_SET_RETURN +#ifdef PROTO_R_ENT_ARGS +setprotoent_r(int stay_open, PROTO_R_ENT_ARGS) +#else +setprotoent_r(int stay_open) +#endif +{ +#ifdef PROTO_R_ENT_UNUSED + PROTO_R_ENT_UNUSED; +#endif + setprotoent(stay_open); +#ifdef PROTO_R_SET_RESULT + return (PROTO_R_SET_RESULT); +#endif +} + +PROTO_R_END_RETURN +#ifdef PROTO_R_ENT_ARGS +endprotoent_r(PROTO_R_ENT_ARGS) +#else +endprotoent_r() +#endif +{ +#ifdef PROTO_R_ENT_UNUSED + PROTO_R_ENT_UNUSED; +#endif + endprotoent(); + PROTO_R_END_RESULT(PROTO_R_OK); +} + +/* Private */ + +#ifndef PROTOENT_DATA +static PROTO_R_RETURN +copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /*%< NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; pe->p_aliases[i]; i++, numptr++) { + len += strlen(pe->p_aliases[i]) + 1; + } + len += strlen(pe->p_name) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (PROTO_R_BAD); + } + + /* copy protocol value*/ + pptr->p_proto = pe->p_proto; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(pe->p_name) + 1; + strcpy(cp, pe->p_name); + pptr->p_name = cp; + cp += n; + + /* copy aliases */ + pptr->p_aliases = (char **)ALIGN(buf); + for (i = 0 ; pe->p_aliases[i]; i++) { + n = strlen(pe->p_aliases[i]) + 1; + strcpy(cp, pe->p_aliases[i]); + pptr->p_aliases[i] = cp; + cp += n; + } + pptr->p_aliases[i] = NULL; + + return (PROTO_R_OK); +} +#else /* !PROTOENT_DATA */ +static int +copy_protoent(struct protoent *pe, struct protoent *pptr, PROTO_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy protocol value */ + pptr->p_proto = pe->p_proto; + + /* copy official name */ + cp = pdptr->line; + eob = pdptr->line + sizeof(pdptr->line); + if ((n = strlen(pe->p_name) + 1) < (eob - cp)) { + strcpy(cp, pe->p_name); + pptr->p_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + pptr->p_aliases = pdptr->proto_aliases; + while (pe->p_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(pe->p_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, pe->p_aliases[i]); + pptr->p_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + pptr->p_aliases[i] = NULL; + + return (PROTO_R_OK); +} +#endif /* PROTOENT_DATA */ +#else /* PROTO_R_RETURN */ + static int getprotoent_r_unknown_system = 0; +#endif /* PROTO_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/getservent.c b/usr/src/lib/libresolv2_joy/common/irs/getservent.c new file mode 100644 index 0000000000..31af67e659 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/getservent.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: getservent.c,v 1.4 2005/04/27 04:56:26 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#if !defined(__BIND_NOSTATIC) + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <string.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_data.h" + +/* Forward */ + +static struct net_data *init(void); + +/* Public */ + +struct servent * +getservent(void) { + struct net_data *net_data = init(); + + return (getservent_p(net_data)); +} + +struct servent * +getservbyname(const char *name, const char *proto) { + struct net_data *net_data = init(); + + return (getservbyname_p(name, proto, net_data)); +} + +struct servent * +getservbyport(int port, const char *proto) { + struct net_data *net_data = init(); + + return (getservbyport_p(port, proto, net_data)); +} + +void +setservent(int stayopen) { + struct net_data *net_data = init(); + + setservent_p(stayopen, net_data); +} + +void +endservent() { + struct net_data *net_data = init(); + + endservent_p(net_data); +} + +/* Shared private. */ + +struct servent * +getservent_p(struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + net_data->sv_last = (*sv->next)(sv); + return (net_data->sv_last); +} + +struct servent * +getservbyname_p(const char *name, const char *proto, + struct net_data *net_data) { + struct irs_sv *sv; + char **sap; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + if (net_data->sv_stayopen && net_data->sv_last) + if (!proto || !strcmp(net_data->sv_last->s_proto, proto)) { + if (!strcmp(net_data->sv_last->s_name, name)) + return (net_data->sv_last); + for (sap = net_data->sv_last->s_aliases; + sap && *sap; sap++) + if (!strcmp(name, *sap)) + return (net_data->sv_last); + } + net_data->sv_last = (*sv->byname)(sv, name, proto); + if (!net_data->sv_stayopen) + endservent(); + return (net_data->sv_last); +} + +struct servent * +getservbyport_p(int port, const char *proto, struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return (NULL); + if (net_data->sv_stayopen && net_data->sv_last) + if (port == net_data->sv_last->s_port && + ( !proto || + !strcmp(net_data->sv_last->s_proto, proto))) + return (net_data->sv_last); + net_data->sv_last = (*sv->byport)(sv, port, proto); + return (net_data->sv_last); +} + +void +setservent_p(int stayopen, struct net_data *net_data) { + struct irs_sv *sv; + + if (!net_data || !(sv = net_data->sv)) + return; + (*sv->rewind)(sv); + net_data->sv_stayopen = (stayopen != 0); + if (stayopen == 0) + net_data_minimize(net_data); +} + +void +endservent_p(struct net_data *net_data) { + struct irs_sv *sv; + + if ((net_data != NULL) && ((sv = net_data->sv) != NULL)) + (*sv->minimize)(sv); +} + +/* Private */ + +static struct net_data * +init() { + struct net_data *net_data; + + if (!(net_data = net_data_init(NULL))) + goto error; + if (!net_data->sv) { + net_data->sv = (*net_data->irs->sv_map)(net_data->irs); + + if (!net_data->sv || !net_data->res) { + error: + errno = EIO; + return (NULL); + } + (*net_data->sv->res_set)(net_data->sv, net_data->res, NULL); + } + + return (net_data); +} + +#endif /*__BIND_NOSTATIC*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/getservent_r.c b/usr/src/lib/libresolv2_joy/common/irs/getservent_r.c new file mode 100644 index 0000000000..42d1e46163 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/getservent_r.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: getservent_r.c,v 1.6 2006/08/01 01:14:16 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <port_before.h> +#if !defined(_REENTRANT) || !defined(DO_PTHREADS) + static int getservent_r_not_required = 0; +#else +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/param.h> +#include <port_after.h> + +#ifdef SERV_R_RETURN + +static SERV_R_RETURN +copy_servent(struct servent *, struct servent *, SERV_R_COPY_ARGS); + +SERV_R_RETURN +getservbyname_r(const char *name, const char *proto, + struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservbyname(name, proto); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + + return (n); +#else + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +#endif +} + +SERV_R_RETURN +getservbyport_r(int port, const char *proto, + struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservbyport(port, proto); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + + return (n); +#else + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +#endif +} + +/*% + * These assume a single context is in operation per thread. + * If this is not the case we will need to call irs directly + * rather than through the base functions. + */ + +SERV_R_RETURN +getservent_r(struct servent *sptr, SERV_R_ARGS) { + struct servent *se = getservent(); +#ifdef SERV_R_SETANSWER + int n = 0; + + if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) + *answerp = NULL; + else + *answerp = sptr; + + return (n); +#else + if (se == NULL) + return (SERV_R_BAD); + + return (copy_servent(se, sptr, SERV_R_COPY)); +#endif +} + +SERV_R_SET_RETURN +#ifdef SERV_R_ENT_ARGS +setservent_r(int stay_open, SERV_R_ENT_ARGS) +#else +setservent_r(int stay_open) +#endif +{ +#ifdef SERV_R_ENT_UNUSED + SERV_R_ENT_UNUSED; +#endif + setservent(stay_open); +#ifdef SERV_R_SET_RESULT + return (SERV_R_SET_RESULT); +#endif +} + +SERV_R_END_RETURN +#ifdef SERV_R_ENT_ARGS +endservent_r(SERV_R_ENT_ARGS) +#else +endservent_r() +#endif +{ +#ifdef SERV_R_ENT_UNUSED + SERV_R_ENT_UNUSED; +#endif + endservent(); + SERV_R_END_RESULT(SERV_R_OK); +} + +/* Private */ + +#ifndef SERVENT_DATA +static SERV_R_RETURN +copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) { + char *cp; + int i, n; + int numptr, len; + + /* Find out the amount of space required to store the answer. */ + numptr = 1; /*%< NULL ptr */ + len = (char *)ALIGN(buf) - buf; + for (i = 0; se->s_aliases[i]; i++, numptr++) { + len += strlen(se->s_aliases[i]) + 1; + } + len += strlen(se->s_name) + 1; + len += strlen(se->s_proto) + 1; + len += numptr * sizeof(char*); + + if (len > (int)buflen) { + errno = ERANGE; + return (SERV_R_BAD); + } + + /* copy port value */ + sptr->s_port = se->s_port; + + cp = (char *)ALIGN(buf) + numptr * sizeof(char *); + + /* copy official name */ + n = strlen(se->s_name) + 1; + strcpy(cp, se->s_name); + sptr->s_name = cp; + cp += n; + + /* copy aliases */ + sptr->s_aliases = (char **)ALIGN(buf); + for (i = 0 ; se->s_aliases[i]; i++) { + n = strlen(se->s_aliases[i]) + 1; + strcpy(cp, se->s_aliases[i]); + sptr->s_aliases[i] = cp; + cp += n; + } + sptr->s_aliases[i] = NULL; + + /* copy proto */ + n = strlen(se->s_proto) + 1; + strcpy(cp, se->s_proto); + sptr->s_proto = cp; + cp += n; + + return (SERV_R_OK); +} +#else /* !SERVENT_DATA */ +static int +copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) { + char *cp, *eob; + int i, n; + + /* copy port value */ + sptr->s_port = se->s_port; + + /* copy official name */ + cp = sdptr->line; + eob = sdptr->line + sizeof(sdptr->line); + if ((n = strlen(se->s_name) + 1) < (eob - cp)) { + strcpy(cp, se->s_name); + sptr->s_name = cp; + cp += n; + } else { + return (-1); + } + + /* copy aliases */ + i = 0; + sptr->s_aliases = sdptr->serv_aliases; + while (se->s_aliases[i] && i < (_MAXALIASES-1)) { + if ((n = strlen(se->s_aliases[i]) + 1) < (eob - cp)) { + strcpy(cp, se->s_aliases[i]); + sptr->s_aliases[i] = cp; + cp += n; + } else { + break; + } + i++; + } + sptr->s_aliases[i] = NULL; + + /* copy proto */ + if ((n = strlen(se->s_proto) + 1) < (eob - cp)) { + strcpy(cp, se->s_proto); + sptr->s_proto = cp; + cp += n; + } else { + return (-1); + } + + return (SERV_R_OK); +} +#endif /* !SERVENT_DATA */ +#else /*SERV_R_RETURN */ + static int getservent_r_unknown_system = 0; +#endif /*SERV_R_RETURN */ +#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/hesiod.c b/usr/src/lib/libresolv2_joy/common/irs/hesiod.c new file mode 100644 index 0000000000..7641bf80ac --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/hesiod.c @@ -0,0 +1,505 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: hesiod.c,v 1.7 2005/07/28 06:51:48 marka Exp $"; +#endif + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + + +/*! \file + * \brief + * hesiod.c --- the core portion of the hesiod resolver. + * + * This file is derived from the hesiod library from Project Athena; + * It has been extensively rewritten by Theodore Ts'o to have a more + * thread-safe interface. + * \author + * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. + */ + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "port_after.h" + +#include "pathnames.h" +#include "hesiod.h" +#include "hesiod_p.h" + +/* Forward */ + +int hesiod_init(void **context); +void hesiod_end(void *context); +char * hesiod_to_bind(void *context, const char *name, + const char *type); +char ** hesiod_resolve(void *context, const char *name, + const char *type); +void hesiod_free_list(void *context, char **list); + +static int parse_config_file(struct hesiod_p *ctx, const char *filename); +static char ** get_txt_records(struct hesiod_p *ctx, int class, + const char *name); +static int init(struct hesiod_p *ctx); + +/* Public */ + +/*% + * This function is called to initialize a hesiod_p. + */ +int +hesiod_init(void **context) { + struct hesiod_p *ctx; + char *cp; + + ctx = malloc(sizeof(struct hesiod_p)); + if (ctx == 0) { + errno = ENOMEM; + return (-1); + } + + memset(ctx, 0, sizeof (*ctx)); + + if (parse_config_file(ctx, _PATH_HESIOD_CONF) < 0) { +#ifdef DEF_RHS + /* + * Use compiled in defaults. + */ + ctx->LHS = malloc(strlen(DEF_LHS) + 1); + ctx->RHS = malloc(strlen(DEF_RHS) + 1); + if (ctx->LHS == NULL || ctx->RHS == NULL) { + errno = ENOMEM; + goto cleanup; + } + strcpy(ctx->LHS, DEF_LHS); /* (checked) */ + strcpy(ctx->RHS, DEF_RHS); /* (checked) */ +#else + goto cleanup; +#endif + } + /* + * The default RHS can be overridden by an environment + * variable. + */ + if ((cp = getenv("HES_DOMAIN")) != NULL) { + size_t RHSlen = strlen(cp) + 2; + if (ctx->RHS) + free(ctx->RHS); + ctx->RHS = malloc(RHSlen); + if (!ctx->RHS) { + errno = ENOMEM; + goto cleanup; + } + if (cp[0] == '.') { + strcpy(ctx->RHS, cp); /* (checked) */ + } else { + strcpy(ctx->RHS, "."); /* (checked) */ + strcat(ctx->RHS, cp); /* (checked) */ + } + } + + /* + * If there is no default hesiod realm set, we return an + * error. + */ + if (!ctx->RHS) { + errno = ENOEXEC; + goto cleanup; + } + +#if 0 + if (res_ninit(ctx->res) < 0) + goto cleanup; +#endif + + *context = ctx; + return (0); + + cleanup: + hesiod_end(ctx); + return (-1); +} + +/*% + * This function deallocates the hesiod_p + */ +void +hesiod_end(void *context) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + int save_errno = errno; + + if (ctx->res) + res_nclose(ctx->res); + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + if (ctx->res && ctx->free_res) + (*ctx->free_res)(ctx->res); + free(ctx); + errno = save_errno; +} + +/*% + * This function 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; + char **rhs_list = NULL; + const char *RHS, *cp; + + /* Decide what our RHS is, and set cp to the end of the actual name. */ + if ((cp = strchr(name, '@')) != NULL) { + if (strchr(cp + 1, '.')) + RHS = cp + 1; + else if ((rhs_list = hesiod_resolve(context, cp + 1, + "rhs-extension")) != NULL) + RHS = *rhs_list; + else { + errno = ENOENT; + return (NULL); + } + } else { + RHS = ctx->RHS; + cp = name + strlen(name); + } + + /* + * Allocate the space we need, including up to three periods and + * the terminating NUL. + */ + if ((bindname = malloc((cp - name) + strlen(type) + strlen(RHS) + + (ctx->LHS ? strlen(ctx->LHS) : 0) + 4)) == NULL) { + errno = ENOMEM; + if (rhs_list) + hesiod_free_list(context, rhs_list); + return NULL; + } + + /* Now put together the DNS name. */ + memcpy(bindname, name, cp - name); + bindname[cp - name] = '\0'; + strcat(bindname, "."); + strcat(bindname, type); + if (ctx->LHS) { + if (ctx->LHS[0] != '.') + strcat(bindname, "."); + strcat(bindname, ctx->LHS); + } + if (RHS[0] != '.') + strcat(bindname, "."); + strcat(bindname, RHS); + + if (rhs_list) + hesiod_free_list(context, rhs_list); + + return (bindname); +} + +/*% + * This is the core function. Given a hesiod (name, type), it + * returns an array of strings returned by the resolver. + */ +char ** +hesiod_resolve(void *context, const char *name, const char *type) { + struct hesiod_p *ctx = (struct hesiod_p *) context; + char *bindname = hesiod_to_bind(context, name, type); + char **retvec; + + if (bindname == NULL) + return (NULL); + if (init(ctx) == -1) { + free(bindname); + return (NULL); + } + + if ((retvec = get_txt_records(ctx, C_IN, bindname))) { + free(bindname); + return (retvec); + } + + if (errno != ENOENT) + return (NULL); + + retvec = get_txt_records(ctx, C_HS, bindname); + free(bindname); + return (retvec); +} + +void +hesiod_free_list(void *context, char **list) { + char **p; + + UNUSED(context); + + for (p = list; *p; p++) + free(*p); + free(list); +} + +/*% + * This function parses the /etc/hesiod.conf file + */ +static int +parse_config_file(struct hesiod_p *ctx, const char *filename) { + char *key, *data, *cp, **cpp; + char buf[MAXDNAME+7]; + FILE *fp; + + /* + * Clear the existing configuration variable, just in case + * they're set. + */ + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + ctx->RHS = ctx->LHS = 0; + + /* + * Now open and parse the file... + */ + if (!(fp = fopen(filename, "r"))) + return (-1); + + while (fgets(buf, sizeof(buf), fp) != NULL) { + cp = buf; + if (*cp == '#' || *cp == '\n' || *cp == '\r') + continue; + while(*cp == ' ' || *cp == '\t') + cp++; + key = cp; + while(*cp != ' ' && *cp != '\t' && *cp != '=') + cp++; + *cp++ = '\0'; + + while(*cp == ' ' || *cp == '\t' || *cp == '=') + cp++; + data = cp; + while(*cp != ' ' && *cp != '\n' && *cp != '\r') + cp++; + *cp++ = '\0'; + + if (strcmp(key, "lhs") == 0) + cpp = &ctx->LHS; + else if (strcmp(key, "rhs") == 0) + cpp = &ctx->RHS; + else + continue; + + *cpp = malloc(strlen(data) + 1); + if (!*cpp) { + errno = ENOMEM; + goto cleanup; + } + strcpy(*cpp, data); + } + fclose(fp); + return (0); + + cleanup: + fclose(fp); + if (ctx->RHS) + free(ctx->RHS); + if (ctx->LHS) + free(ctx->LHS); + ctx->RHS = ctx->LHS = 0; + return (-1); +} + +/*% + * 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(struct hesiod_p *ctx, int class, const char *name) { + struct { + int type; /*%< RR type */ + int class; /*%< RR class */ + int dlen; /*%< len of data section */ + u_char *data; /*%< pointer to data */ + } rr; + HEADER *hp; + u_char qbuf[MAX_HESRESP], abuf[MAX_HESRESP]; + u_char *cp, *erdata, *eom; + char *dst, *edst, **list; + int ancount, qdcount; + int i, j, n, skip; + + /* + * Construct the query and send it. + */ + n = res_nmkquery(ctx->res, QUERY, name, class, T_TXT, NULL, 0, + NULL, qbuf, MAX_HESRESP); + if (n < 0) { + errno = EMSGSIZE; + return (NULL); + } + n = res_nsend(ctx->res, qbuf, n, abuf, MAX_HESRESP); + if (n < 0) { + errno = ECONNREFUSED; + return (NULL); + } + if (n < HFIXEDSZ) { + errno = EMSGSIZE; + return (NULL); + } + + /* + * OK, parse the result. + */ + hp = (HEADER *) abuf; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + cp = abuf + sizeof(HEADER); + eom = abuf + n; + + /* Skip query, trying to get to the answer section which follows. */ + for (i = 0; i < qdcount; i++) { + skip = dn_skipname(cp, eom); + if (skip < 0 || cp + skip + QFIXEDSZ > eom) { + errno = EMSGSIZE; + return (NULL); + } + cp += skip + QFIXEDSZ; + } + + list = malloc((ancount + 1) * sizeof(char *)); + if (!list) { + errno = ENOMEM; + return (NULL); + } + j = 0; + for (i = 0; i < ancount; i++) { + skip = dn_skipname(cp, eom); + if (skip < 0) { + errno = EMSGSIZE; + goto cleanup; + } + cp += skip; + if (cp + 3 * INT16SZ + INT32SZ > eom) { + errno = EMSGSIZE; + goto cleanup; + } + rr.type = ns_get16(cp); + cp += INT16SZ; + rr.class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /*%< skip the ttl, too */ + rr.dlen = ns_get16(cp); + cp += INT16SZ; + if (cp + rr.dlen > eom) { + errno = EMSGSIZE; + goto cleanup; + } + rr.data = cp; + cp += rr.dlen; + if (rr.class != class || rr.type != T_TXT) + continue; + if (!(list[j] = malloc(rr.dlen))) + goto cleanup; + dst = list[j++]; + edst = dst + rr.dlen; + erdata = rr.data + rr.dlen; + cp = rr.data; + while (cp < erdata) { + n = (unsigned char) *cp++; + if (cp + n > eom || dst + n > edst) { + errno = EMSGSIZE; + goto cleanup; + } + memcpy(dst, cp, n); + cp += n; + dst += n; + } + if (cp != erdata) { + errno = EMSGSIZE; + goto cleanup; + } + *dst = '\0'; + } + list[j] = NULL; + if (j == 0) { + errno = ENOENT; + goto cleanup; + } + return (list); + + cleanup: + for (i = 0; i < j; i++) + free(list[i]); + free(list); + return (NULL); +} + +struct __res_state * +__hesiod_res_get(void *context) { + struct hesiod_p *ctx = context; + + if (!ctx->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + __hesiod_res_set(ctx, res, free); + } + + return (ctx->res); +} + +void +__hesiod_res_set(void *context, struct __res_state *res, + void (*free_res)(void *)) { + struct hesiod_p *ctx = context; + + if (ctx->res && ctx->free_res) { + res_nclose(ctx->res); + (*ctx->free_res)(ctx->res); + } + + ctx->res = res; + ctx->free_res = free_res; +} + +static int +init(struct hesiod_p *ctx) { + + if (!ctx->res && !__hesiod_res_get(ctx)) + return (-1); + + if (((ctx->res->options & RES_INIT) == 0U) && + (res_ninit(ctx->res) == -1)) + return (-1); + + return (0); +} diff --git a/usr/src/lib/libresolv2_joy/common/irs/hesiod_p.h b/usr/src/lib/libresolv2_joy/common/irs/hesiod_p.h new file mode 100644 index 0000000000..99da15d0cd --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/hesiod_p.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: hesiod_p.h,v 1.3 2005/04/27 04:56:27 sra Exp $ + */ + +#ifndef _HESIOD_P_H_INCLUDED +#define _HESIOD_P_H_INCLUDED + +/** \file + * \brief + * hesiod_p.h -- private definitions for the hesiod library. + * + * \author + * This file is primarily maintained by tytso@mit.edu and ghudson@mit.edu. + */ + +#define DEF_RHS ".Athena.MIT.EDU" /*%< Defaults if HESIOD_CONF */ +#define DEF_LHS ".ns" /*%< file is not */ + /*%< present. */ +struct hesiod_p { + char * LHS; /*%< normally ".ns" */ + char * RHS; /*%< AKA the default hesiod domain */ + struct __res_state * res; /*%< resolver context */ + void (*free_res)(void *); + void (*res_set)(struct hesiod_p *, struct __res_state *, + void (*)(void *)); + struct __res_state * (*res_get)(struct hesiod_p *); +}; + +#define MAX_HESRESP 1024 + +#endif /*_HESIOD_P_H_INCLUDED*/ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irp.c b/usr/src/lib/libresolv2_joy/common/irs/irp.c new file mode 100644 index 0000000000..ef10631c22 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irp.c @@ -0,0 +1,583 @@ +/* + * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1996, 1998-2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irp.c,v 1.12 2008/11/14 02:36:51 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <stdarg.h> +#include <fcntl.h> +#include <syslog.h> +#include <ctype.h> +#include <unistd.h> + +#include <isc/memcluster.h> + +#include <irs.h> +#include <irp.h> + +#include "irs_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Forward. */ + +static void irp_close(struct irs_acc *); + +#define LINEINCR 128 + +#if !defined(SUN_LEN) +#define SUN_LEN(su) \ + (sizeof (*(su)) - sizeof ((su)->sun_path) + strlen((su)->sun_path)) +#endif + + +/* Public */ + + +/* send errors to syslog if true. */ +int irp_log_errors = 1; + +/*% + * This module handles the irp module connection to irpd. + * + * The client expects a synchronous interface to functions like + * getpwnam(3), so we can't use the ctl_* i/o library on this end of + * the wire (it's used in the server). + */ + +/*% + * irs_acc *irs_irp_acc(const char *options); + * + * Initialize the irp module. + */ +struct irs_acc * +irs_irp_acc(const char *options) { + struct irs_acc *acc; + struct irp_p *irp; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(irp = memget(sizeof *irp))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + irp->inlast = 0; + irp->incurr = 0; + irp->fdCxn = -1; + acc->private = irp; + +#ifdef WANT_IRS_GR + acc->gr_map = irs_irp_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_irp_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_irp_sv; + acc->pr_map = irs_irp_pr; + acc->ho_map = irs_irp_ho; + acc->nw_map = irs_irp_nw; + acc->ng_map = irs_irp_ng; + acc->close = irp_close; + return (acc); +} + + +int +irs_irp_connection_setup(struct irp_p *cxndata, int *warned) { + if (irs_irp_is_connected(cxndata)) { + return (0); + } else if (irs_irp_connect(cxndata) != 0) { + if (warned != NULL && !*warned) { + syslog(LOG_ERR, "irpd connection failed: %m\n"); + (*warned)++; + } + + return (-1); + } + + return (0); +} + +/*% + * int irs_irp_connect(void); + * + * Sets up the connection to the remote irpd server. + * + * Returns: + * + * 0 on success, -1 on failure. + * + */ +int +irs_irp_connect(struct irp_p *pvt) { + int flags; + struct sockaddr *addr; + struct sockaddr_in iaddr; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un uaddr; +#endif + long ipaddr; + const char *irphost; + int code; + char text[256]; + int socklen = 0; + + if (pvt->fdCxn != -1) { + perror("fd != 1"); + return (-1); + } + +#ifndef NO_SOCKADDR_UN + memset(&uaddr, 0, sizeof uaddr); +#endif + memset(&iaddr, 0, sizeof iaddr); + + irphost = getenv(IRPD_HOST_ENV); + if (irphost == NULL) { + irphost = "127.0.0.1"; + } + +#ifndef NO_SOCKADDR_UN + if (irphost[0] == '/') { + addr = (struct sockaddr *)&uaddr; + strncpy(uaddr.sun_path, irphost, sizeof uaddr.sun_path); + uaddr.sun_family = AF_UNIX; + socklen = SUN_LEN(&uaddr); +#ifdef HAVE_SA_LEN + uaddr.sun_len = socklen; +#endif + } else +#endif + { + if (inet_pton(AF_INET, irphost, &ipaddr) != 1) { + errno = EADDRNOTAVAIL; + perror("inet_pton"); + return (-1); + } + + addr = (struct sockaddr *)&iaddr; + socklen = sizeof iaddr; +#ifdef HAVE_SA_LEN + iaddr.sin_len = socklen; +#endif + iaddr.sin_family = AF_INET; + iaddr.sin_port = htons(IRPD_PORT); + iaddr.sin_addr.s_addr = ipaddr; + } + + + pvt->fdCxn = socket(addr->sa_family, SOCK_STREAM, PF_UNSPEC); + if (pvt->fdCxn < 0) { + perror("socket"); + return (-1); + } + + if (connect(pvt->fdCxn, addr, socklen) != 0) { + perror("connect"); + return (-1); + } + + flags = fcntl(pvt->fdCxn, F_GETFL, 0); + if (flags < 0) { + close(pvt->fdCxn); + perror("close"); + return (-1); + } + +#if 0 + flags |= O_NONBLOCK; + if (fcntl(pvt->fdCxn, F_SETFL, flags) < 0) { + close(pvt->fdCxn); + perror("fcntl"); + return (-1); + } +#endif + + code = irs_irp_read_response(pvt, text, sizeof text); + if (code != IRPD_WELCOME_CODE) { + if (irp_log_errors) { + syslog(LOG_WARNING, "Connection failed: %s", text); + } + irs_irp_disconnect(pvt); + return (-1); + } + + return (0); +} + +/*% + * int irs_irp_is_connected(struct irp_p *pvt); + * + * Returns: + * + * Non-zero if streams are setup to remote. + * + */ + +int +irs_irp_is_connected(struct irp_p *pvt) { + return (pvt->fdCxn >= 0); +} + +/*% + * void + * irs_irp_disconnect(struct irp_p *pvt); + * + * Closes streams to remote. + */ + +void +irs_irp_disconnect(struct irp_p *pvt) { + if (pvt->fdCxn != -1) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + } +} + + + +int +irs_irp_read_line(struct irp_p *pvt, char *buffer, int len) { + char *realstart = &pvt->inbuffer[0]; + char *p, *start, *end; + int spare; + int i; + int buffpos = 0; + int left = len - 1; + + while (left > 0) { + start = p = &pvt->inbuffer[pvt->incurr]; + end = &pvt->inbuffer[pvt->inlast]; + + while (p != end && *p != '\n') + p++; + + if (p == end) { + /* Found no newline so shift data down if necessary + * and append new data to buffer + */ + if (start > realstart) { + memmove(realstart, start, end - start); + pvt->inlast = end - start; + start = realstart; + pvt->incurr = 0; + end = &pvt->inbuffer[pvt->inlast]; + } + + spare = sizeof (pvt->inbuffer) - pvt->inlast; + + p = end; + i = read(pvt->fdCxn, end, spare); + if (i < 0) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + return (buffpos > 0 ? buffpos : -1); + } else if (i == 0) { + return (buffpos); + } + + end += i; + pvt->inlast += i; + + while (p != end && *p != '\n') + p++; + } + + if (p == end) { + /* full buffer and still no newline */ + i = sizeof pvt->inbuffer; + } else { + /* include newline */ + i = p - start + 1; + } + + if (i > left) + i = left; + memcpy(buffer + buffpos, start, i); + pvt->incurr += i; + buffpos += i; + buffer[buffpos] = '\0'; + + if (p != end) { + left = 0; + } else { + left -= i; + } + } + +#if 0 + fprintf(stderr, "read line: %s\n", buffer); +#endif + return (buffpos); +} + +/*% + * int irp_read_response(struct irp_p *pvt); + * + * Returns: + * + * The number found at the beginning of the line read from + * FP. 0 on failure(0 is not a legal response code). The + * rest of the line is discarded. + * + */ + +int +irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen) { + char line[1024]; + int code; + char *p; + + if (irs_irp_read_line(pvt, line, sizeof line) <= 0) { + return (0); + } + + p = strchr(line, '\n'); + if (p == NULL) { + return (0); + } + + if (sscanf(line, "%d", &code) != 1) { + code = 0; + } else if (text != NULL && textlen > 0U) { + p = line; + while (isspace((unsigned char)*p)) p++; + while (isdigit((unsigned char)*p)) p++; + while (isspace((unsigned char)*p)) p++; + strncpy(text, p, textlen - 1); + p[textlen - 1] = '\0'; + } + + return (code); +} + +/*% + * char *irp_read_body(struct irp_p *pvt, size_t *size); + * + * Read in the body of a response. Terminated by a line with + * just a dot on it. Lines should be terminated with a CR-LF + * sequence, but we're nt piccky if the CR is missing. + * No leading dot escaping is done as the protcol doesn't + * use leading dots anywhere. + * + * Returns: + * + * Pointer to null-terminated buffer allocated by memget. + * *SIZE is set to the length of the buffer. + * + */ + +char * +irs_irp_read_body(struct irp_p *pvt, size_t *size) { + char line[1024]; + u_int linelen; + size_t len = LINEINCR; + char *buffer = memget(len); + int idx = 0; + + if (buffer == NULL) + return (NULL); + + for (;;) { + if (irs_irp_read_line(pvt, line, sizeof line) <= 0 || + strchr(line, '\n') == NULL) + goto death; + + linelen = strlen(line); + + if (line[linelen - 1] != '\n') + goto death; + + /* We're not strict about missing \r. Should we be?? */ + if (linelen > 2 && line[linelen - 2] == '\r') { + line[linelen - 2] = '\n'; + line[linelen - 1] = '\0'; + linelen--; + } + + if (linelen == 2 && line[0] == '.') { + *size = len; + buffer[idx] = '\0'; + + return (buffer); + } + + if (linelen > (len - (idx + 1))) { + char *p = memget(len + LINEINCR); + + if (p == NULL) + goto death; + memcpy(p, buffer, len); + memput(buffer, len); + buffer = p; + len += LINEINCR; + } + + memcpy(buffer + idx, line, linelen); + idx += linelen; + } + death: + memput(buffer, len); + return (NULL); +} + +/*% + * int irs_irp_get_full_response(struct irp_p *pvt, int *code, + * char **body, size_t *bodylen); + * + * Gets the response to a command. If the response indicates + * there's a body to follow(code % 10 == 1), then the + * body buffer is allcoated with memget and stored in + * *BODY. The length of the allocated body buffer is stored + * in *BODY. The caller must give the body buffer back to + * memput when done. The results code is stored in *CODE. + * + * Returns: + * + * 0 if a result was read. -1 on some sort of failure. + * + */ + +int +irs_irp_get_full_response(struct irp_p *pvt, int *code, char *text, + size_t textlen, char **body, size_t *bodylen) { + int result = irs_irp_read_response(pvt, text, textlen); + + *body = NULL; + + if (result == 0) { + return (-1); + } + + *code = result; + + /* Code that matches 2xx is a good result code. + * Code that matches xx1 means there's a response body coming. + */ + if ((result / 100) == 2 && (result % 10) == 1) { + *body = irs_irp_read_body(pvt, bodylen); + if (*body == NULL) { + return (-1); + } + } + + return (0); +} + +/*% + * int irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...); + * + * Sends command to remote connected via the PVT + * structure. FMT and args after it are fprintf-like + * arguments for formatting. + * + * Returns: + * + * 0 on success, -1 on failure. + */ + +int +irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) { + va_list ap; + char buffer[1024]; + int pos = 0; + int i, todo; + + + if (pvt->fdCxn < 0) { + return (-1); + } + + va_start(ap, fmt); + (void) vsprintf(buffer, fmt, ap); + todo = strlen(buffer); + va_end(ap); + if (todo > (int)sizeof(buffer) - 3) { + syslog(LOG_CRIT, "memory overrun in irs_irp_send_command()"); + exit(1); + } + strcat(buffer, "\r\n"); + todo = strlen(buffer); + + while (todo > 0) { + i = write(pvt->fdCxn, buffer + pos, todo); +#if 0 + /* XXX brister */ + fprintf(stderr, "Wrote: \""); + fwrite(buffer + pos, sizeof (char), todo, stderr); + fprintf(stderr, "\"\n"); +#endif + if (i < 0) { + close(pvt->fdCxn); + pvt->fdCxn = -1; + return (-1); + } + todo -= i; + } + + return (0); +} + + +/* Methods */ + +/*% + * void irp_close(struct irs_acc *this) + * + */ + +static void +irp_close(struct irs_acc *this) { + struct irp_p *irp = (struct irp_p *)this->private; + + if (irp != NULL) { + irs_irp_disconnect(irp); + memput(irp, sizeof *irp); + } + + memput(this, sizeof *this); +} + + + + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irp_ho.c b/usr/src/lib/libresolv2_joy/common/irs/irp_ho.c new file mode 100644 index 0000000000..b0de31dc89 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irp_ho.c @@ -0,0 +1,405 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996,1998 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_ho.c,v 1.3 2005/04/27 04:56:28 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include <syslog.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/irpmarshall.h> +#include <isc/memcluster.h> + +#include "irs_p.h" +#include "dns_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define Max(a,b) ((a) > (b) ? (a) : (b)) + + +struct pvt { + struct irp_p *girpdata; + int warned; + struct hostent host; +}; + +/* Forward. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); + +static void free_host(struct hostent *ho); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +/* Public. */ + +/*% + * struct irs_ho * irs_irp_ho(struct irs_acc *this) + * + * Notes: + * + * Initializes the irp_ho module. + * + */ + +struct irs_ho * +irs_irp_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + if (!(ho = memget(sizeof *ho))) { + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x0, sizeof *ho); + + if (!(pvt = memget(sizeof *pvt))) { + memput(ho, sizeof *ho); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->addrinfo = ho_addrinfo; + + return (ho); +} + +/* Methods. */ + +/*% + * Closes down the module. + * + */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + + free_host(&pvt->host); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + +/* + * struct hostent * ho_byname(struct irs_ho *this, const char *name) + * + */ + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + return (ho_byname2(this, name, AF_INET)); +} + + + + + +/* + * struct hostent * ho_byname2(struct irs_ho *this, const char *name, int af) + * + */ + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body = NULL; + size_t bodylen; + int code; + char text[256]; + + if (ho->h_name != NULL && + strcmp(name, ho->h_name) == 0 && + af == ho->h_addrtype) { + return (ho); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostbyname2 %s %s", + name, ADDR_T_STR(af)) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + + + +/* + * struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + * int len, int af) + * + */ + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body = NULL; + size_t bodylen; + int code; + char **p; + char paddr[MAXPADDRSIZE]; + char text[256]; + + if (ho->h_name != NULL && + af == ho->h_addrtype && + len == ho->h_length) { + for (p = ho->h_addr_list ; *p != NULL ; p++) { + if (memcmp(*p, addr, len) == 0) + return (ho); + } + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (inet_ntop(af, addr, paddr, sizeof paddr) == NULL) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostbyaddr %s %s", + paddr, ADDR_T_STR(af)) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + +/*% + * The implementation for gethostent(3). The first time it's + * called all the data is pulled from the remote(i.e. what + * the maximum number of gethostent(3) calls would return) + * and that data is cached. + * + */ + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *ho = &pvt->host; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "gethostent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETHOST_OK) { + free_host(ho); + if (irp_unmarshall_ho(ho, body) != 0) { + ho = NULL; + } + } else { + ho = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (ho); +} + +/*% + * void ho_rewind(struct irs_ho *this) + * + */ + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "sethostent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETHOST_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "sethostent failed: %s", text); + } + } + + return; +} + +/*% + * void ho_minimize(struct irs_ho *this) + * + */ + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + free_host(&pvt->host); + + irs_irp_disconnect(pvt->girpdata); +} + +/*% + * void free_host(struct hostent *ho) + * + */ + +static void +free_host(struct hostent *ho) { + char **p; + + if (ho == NULL) { + return; + } + + if (ho->h_name != NULL) + free(ho->h_name); + + if (ho->h_aliases != NULL) { + for (p = ho->h_aliases ; *p != NULL ; p++) + free(*p); + free(ho->h_aliases); + } + + if (ho->h_addr_list != NULL) { + for (p = ho->h_addr_list ; *p != NULL ; p++) + free(*p); + free(ho->h_addr_list); + } +} + +/* dummy */ +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + UNUSED(this); + UNUSED(name); + UNUSED(pai); + return(NULL); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irp_ng.c b/usr/src/lib/libresolv2_joy/common/irs/irp_ng.c new file mode 100644 index 0000000000..1af862cab4 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irp_ng.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996, 1998 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irp_ng.c,v 1.4 2006/12/07 04:46:27 marka Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/memcluster.h> +#include <isc/irpmarshall.h> + +#include "irs_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Definitions */ + +struct pvt { + struct irp_p *girpdata; + int warned; +}; + + +/* Forward */ + +static void ng_rewind(struct irs_ng *, const char*); +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, const char **, + const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_minimize(struct irs_ng *); + + +/* Public */ + +/*% + * Intialize the irp netgroup module. + * + */ + +struct irs_ng * +irs_irp_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + + + +/* + * void ng_close(struct irs_ng *this) + * + */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ng_minimize(this); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + + + + +/* + * void ng_rewind(struct irs_ng *this, const char *group) + * + * + */ + +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, + "setnetgrent %s", group) != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETNETGR_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setnetgrent(%s) failed: %s", + group, text); + } + } + + return; +} + +/* + * Get the next netgroup item from the cache. + * + */ + +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + int code; + char *body = NULL; + size_t bodylen; + int rval = 0; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (0); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetgrent") != 0) + return (0); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (0); + } + + if (code == IRPD_GETNETGR_OK) { + if (irp_unmarshall_ng(host, user, domain, body) == 0) { + rval = 1; + } + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (rval); +} + +/* + * Search for a match in a netgroup. + * + */ + +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + char *body = NULL; + size_t bodylen = 0; + int code; + char text[256]; + int rval = 0; + + UNUSED(name); + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (0); + } + + if (irp_marshall_ng(host, user, domain, &body, &bodylen) != 0) { + return (0); + } + + if (irs_irp_send_command(pvt->girpdata, "innetgr %s", body) == 0) { + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code == IRPD_GETNETGR_MATCHES) { + rval = 1; + } + } + + memput(body, bodylen); + + return (rval); +} + + + + +/* + * void ng_minimize(struct irs_ng *this) + * + */ + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* Private */ + + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irp_nw.c b/usr/src/lib/libresolv2_joy/common/irs/irp_nw.c new file mode 100644 index 0000000000..3f2381f95d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irp_nw.c @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996,1998 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_nw.c,v 1.4 2006/03/09 23:57:56 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#if 0 + +#endif + +/* Imports */ + +#include "port_before.h" + +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <fcntl.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/irpmarshall.h> + +#include <isc/memcluster.h> +#include <isc/misc.h> + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + struct irp_p *girpdata; + int warned; + struct nwent net; +}; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); + +static void free_nw(struct nwent *nw); + + +/* Public */ + +/*% + * struct irs_nw * irs_irp_nw(struct irs_acc *this) + * + */ + +struct irs_nw * +irs_irp_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x0, sizeof *nw); + pvt->girpdata = this->private; + + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + return (nw); +} + +/* Methods */ + +/*% + * void nw_close(struct irs_nw *this) + * + */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + + free_nw(&pvt->net); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +/*% + * struct nwent * nw_byaddr(struct irs_nw *this, void *net, + * int length, int type) + * + */ + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body = NULL; + size_t bodylen; + int code; + char paddr[24]; /*%< bigenough for ip4 w/ cidr spec. */ + char text[256]; + + if (inet_net_ntop(type, net, length, paddr, sizeof paddr) == NULL) { + return (NULL); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetbyaddr %s %s", + paddr, ADDR_T_STR(type)) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (nw); +} + +/*% + * struct nwent * nw_byname(struct irs_nw *this, const char *name, int type) + * + */ + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body = NULL; + size_t bodylen; + int code; + char text[256]; + + if (nw->n_name != NULL && + strcmp(name, nw->n_name) == 0 && + nw->n_addrtype == type) { + return (nw); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetbyname %s", name) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (nw); +} + +/*% + * void nw_rewind(struct irs_nw *this) + * + */ + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setnetent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETNET_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setnetent failed: %s", text); + } + } + + return; +} + +/*% + * Prepares the cache if necessary and returns the first, or + * next item from it. + */ + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *nw = &pvt->net; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getnetent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETNET_OK) { + free_nw(nw); + if (irp_unmarshall_nw(nw, body) != 0) { + nw = NULL; + } + } else { + nw = NULL; + } + + if (body != NULL) + memput(body, bodylen); + return (nw); +} + +/*% + * void nw_minimize(struct irs_nw *this) + * + */ + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + +/* private. */ + +/*% + * deallocate all the memory irp_unmarshall_pw allocated. + * + */ + +static void +free_nw(struct nwent *nw) { + char **p; + + if (nw == NULL) + return; + + if (nw->n_name != NULL) + free(nw->n_name); + + if (nw->n_aliases != NULL) { + for (p = nw->n_aliases ; *p != NULL ; p++) { + free(*p); + } + free(nw->n_aliases); + } + + if (nw->n_addr != NULL) + free(nw->n_addr); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irp_p.h b/usr/src/lib/libresolv2_joy/common/irs/irp_p.h new file mode 100644 index 0000000000..4f943f81bd --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irp_p.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: irp_p.h,v 1.5 2005/04/27 04:56:28 sra Exp $ + */ + +#ifndef _IRP_P_H_INCLUDED +#define _IRP_P_H_INCLUDED + +#include <stdio.h> + +struct irp_p { + char inbuffer[1024]; + int inlast; /*%< index of one past the last char in buffer */ + int incurr; /*%< index of the next char to be read from buffer */ + int fdCxn; +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_irp_acc __P((const char *)); +extern struct irs_gr * irs_irp_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_irp_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_irp_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_irp_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_irp_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_irp_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_irp_ng __P((struct irs_acc *)); + +int irs_irp_connect(struct irp_p *pvt); +int irs_irp_is_connected(struct irp_p *pvt); +void irs_irp_disconnect(struct irp_p *pvt); +int irs_irp_read_response(struct irp_p *pvt, char *text, size_t textlen); +char *irs_irp_read_body(struct irp_p *pvt, size_t *size); +int irs_irp_get_full_response(struct irp_p *pvt, int *code, + char *text, size_t textlen, + char **body, size_t *bodylen); + +extern int irp_log_errors; + +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irp_pr.c b/usr/src/lib/libresolv2_joy/common/irs/irp_pr.c new file mode 100644 index 0000000000..ea876e8281 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irp_pr.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_pr.c,v 1.3 2005/04/27 04:56:29 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include <syslog.h> +#include <sys/types.h> + +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <netdb.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/memcluster.h> +#include <isc/irpmarshall.h> + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + + +#define MAXALIASES 35 + +/* Types */ + +struct pvt { + struct irp_p *girpdata; + int warned; + struct protoent proto; +}; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +static void free_proto(struct protoent *pr); + +/* Public */ + +/*% + * struct irs_pr * irs_irp_pr(struct irs_acc *this) + * + */ + +struct irs_pr * +irs_irp_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + memset(pr, 0x0, sizeof *pr); + + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *pr); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + pr->private = pvt; + pr->close = pr_close; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + return (pr); +} + +/* Methods */ + +/*% + * void pr_close(struct irs_pr *this) + * + */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + pr_minimize(this); + + free_proto(&pvt->proto); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +/*% + * struct protoent * pr_byname(struct irs_pr *this, const char *name) + * + */ + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body = NULL; + size_t bodylen; + int code; + int i; + char text[256]; + + if (pr->p_name != NULL && strcmp(name, pr->p_name) == 0) { + return (pr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + i = irs_irp_send_command(pvt->girpdata, "getprotobyname %s", name); + if (i != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + +/*% + * struct protoent * pr_bynumber(struct irs_pr *this, int proto) + * + */ + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body = NULL; + size_t bodylen; + int code; + int i; + char text[256]; + + if (pr->p_name != NULL && proto == pr->p_proto) { + return (pr); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + i = irs_irp_send_command(pvt->girpdata, "getprotobynumber %d", proto); + if (i != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + +/*% + * void pr_rewind(struct irs_pr *this) + * + */ + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setprotoent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETPROTO_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setprotoent failed: %s", text); + } + } + + return; +} + +/*% + * Prepares the cache if necessary and returns the next item in it. + * + */ + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct protoent *pr = &pvt->proto; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getprotoent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETPROTO_OK) { + free_proto(pr); + if (irp_unmarshall_pr(pr, body) != 0) { + pr = NULL; + } + } else { + pr = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (pr); +} + +/*% + * void pr_minimize(struct irs_pr *this) + * + */ + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + +/*% + * Deallocate all the memory irp_unmarshall_pr allocated. + * + */ + +static void +free_proto(struct protoent *pr) { + char **p; + + if (pr == NULL) + return; + + if (pr->p_name != NULL) + free(pr->p_name); + + for (p = pr->p_aliases ; p != NULL && *p != NULL ; p++) + free(*p); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irp_sv.c b/usr/src/lib/libresolv2_joy/common/irs/irp_sv.c new file mode 100644 index 0000000000..577e697fe6 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irp_sv.c @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996,1998 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irp_sv.c,v 1.3 2005/04/27 04:56:29 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> + +#ifdef IRS_LCL_SV_DB +#include <db.h> +#endif +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <syslog.h> + +#include <irs.h> +#include <irp.h> +#include <isc/irpmarshall.h> +#include <isc/memcluster.h> + +#include "irs_p.h" +#include "lcl_p.h" +#include "irp_p.h" + +#include "port_after.h" + +/* Types */ + +struct pvt { + struct irp_p *girpdata; + int warned; + struct servent service; +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); + +static void free_service(struct servent *sv); + + + +/* Public */ + +/*% + * struct irs_sv * irs_irp_sv(struct irs_acc *this) + * + */ + +struct irs_sv * +irs_irp_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + if ((sv = memget(sizeof *sv)) == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x0, sizeof *sv); + + if ((pvt = memget(sizeof *pvt)) == NULL) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pvt->girpdata = this->private; + + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + + return (sv); +} + +/* Methods */ + +/*% + * void sv_close(struct irs_sv *this) + * + */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + sv_minimize(this); + + free_service(&pvt->service); + + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +/*% + * Fills the cache if necessary and returns the next item from it. + * + */ + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + size_t bodylen; + int code; + char text[256]; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservent") != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + +/*% + * struct servent * sv_byname(struct irs_sv *this, const char *name, + * const char *proto) + * + */ + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + char text[256]; + size_t bodylen; + int code; + + if (sv->s_name != NULL && + strcmp(name, sv->s_name) == 0 && + strcasecmp(proto, sv->s_proto) == 0) { + return (sv); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservbyname %s %s", + name, proto) != 0) + return (NULL); + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + +/*% + * struct servent * sv_byport(struct irs_sv *this, int port, + * const char *proto) + * + */ + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { + struct pvt *pvt = (struct pvt *)this->private; + struct servent *sv = &pvt->service; + char *body; + size_t bodylen; + char text[256]; + int code; + + if (sv->s_name != NULL && + port == sv->s_port && + strcasecmp(proto, sv->s_proto) == 0) { + return (sv); + } + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return (NULL); + } + + if (irs_irp_send_command(pvt->girpdata, "getservbyport %d %s", + ntohs((short)port), proto) != 0) { + return (NULL); + } + + if (irs_irp_get_full_response(pvt->girpdata, &code, + text, sizeof text, + &body, &bodylen) != 0) { + return (NULL); + } + + if (code == IRPD_GETSERVICE_OK) { + free_service(sv); + if (irp_unmarshall_sv(sv, body) != 0) { + sv = NULL; + } + } else { + sv = NULL; + } + + if (body != NULL) { + memput(body, bodylen); + } + + return (sv); +} + +/*% + * void sv_rewind(struct irs_sv *this) + * + */ + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + char text[256]; + int code; + + if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { + return; + } + + if (irs_irp_send_command(pvt->girpdata, "setservent") != 0) { + return; + } + + code = irs_irp_read_response(pvt->girpdata, text, sizeof text); + if (code != IRPD_GETSERVICE_SETOK) { + if (irp_log_errors) { + syslog(LOG_WARNING, "setservent failed: %s", text); + } + } + + return; +} + +/*% + * void sv_minimize(struct irs_sv *this) + * + */ + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + irs_irp_disconnect(pvt->girpdata); +} + + + + + + +static void +free_service(struct servent *sv) { + char **p; + + if (sv == NULL) { + return; + } + + if (sv->s_name != NULL) { + free(sv->s_name); + } + + for (p = sv->s_aliases ; p != NULL && *p != NULL ; p++) { + free(*p); + } + + if (sv->s_proto != NULL) { + free(sv->s_proto); + } +} + + + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irpmarshall.c b/usr/src/lib/libresolv2_joy/common/irs/irpmarshall.c new file mode 100644 index 0000000000..85ffff1866 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irpmarshall.c @@ -0,0 +1,2301 @@ +/* + * Copyright(c) 1989, 1993, 1995 + * 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. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: irpmarshall.c,v 1.7 2006/03/09 23:57:56 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#if 0 + +Check values are in approrpriate endian order. + +Double check memory allocations on unmarhsalling + +#endif + + +/* Extern */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <stdio.h> +#include <ctype.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <utmp.h> +#include <unistd.h> +#include <assert.h> +#include <errno.h> + +#include <irs.h> +#include <isc/memcluster.h> +#include <isc/irpmarshall.h> + +#include "port_after.h" + + +#ifndef HAVE_STRNDUP +static char *strndup(const char *str, size_t len); +#endif + +static char **splitarray(const char *buffer, const char *buffend, char delim); +static int joinarray(char * const * argv, char *buffer, char delim); +static char *getfield(char **res, size_t reslen, char **buffer, char delim); +static size_t joinlength(char * const *argv); +static void free_array(char **argv, size_t entries); + +#define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\ + (x == AF_INET6 ? "AF_INET6" : "UNKNOWN")) + +#define MAXPADDRSIZE (sizeof "255.255.255.255" + 1) + +static char COMMA = ','; + +static const char *COMMASTR = ","; +static const char *COLONSTR = ":"; + + + +/* See big comment at bottom of irpmarshall.h for description. */ + + +#ifdef WANT_IRS_PW +/* +++++++++++++++++++++++++ struct passwd +++++++++++++++++++++++++ */ + +/*% + * int irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) + * + * notes: \li + * + * See irpmarshall.h + * + * return: \li + * + * 0 on sucess, -1 on failure. + * + */ + +int +irp_marshall_pw(const struct passwd *pw, char **buffer, size_t *len) { + size_t need = 1 ; /*%< for null byte */ + char pwUid[24]; + char pwGid[24]; + char pwChange[24]; + char pwExpire[24]; + const char *pwClass; + const char *fieldsep = COLONSTR; + + if (pw == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(pwUid, "%ld", (long)pw->pw_uid); + sprintf(pwGid, "%ld", (long)pw->pw_gid); + +#ifdef HAVE_PW_CHANGE + sprintf(pwChange, "%ld", (long)pw->pw_change); +#else + pwChange[0] = '0'; + pwChange[1] = '\0'; +#endif + +#ifdef HAVE_PW_EXPIRE + sprintf(pwExpire, "%ld", (long)pw->pw_expire); +#else + pwExpire[0] = '0'; + pwExpire[1] = '\0'; +#endif + +#ifdef HAVE_PW_CLASS + pwClass = pw->pw_class; +#else + pwClass = ""; +#endif + + need += strlen(pw->pw_name) + 1; /*%< one for fieldsep */ + need += strlen(pw->pw_passwd) + 1; + need += strlen(pwUid) + 1; + need += strlen(pwGid) + 1; + need += strlen(pwClass) + 1; + need += strlen(pwChange) + 1; + need += strlen(pwExpire) + 1; + need += strlen(pw->pw_gecos) + 1; + need += strlen(pw->pw_dir) + 1; + need += strlen(pw->pw_shell) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /*%< for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, pw->pw_name); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_passwd); strcat(*buffer, fieldsep); + strcat(*buffer, pwUid); strcat(*buffer, fieldsep); + strcat(*buffer, pwGid); strcat(*buffer, fieldsep); + strcat(*buffer, pwClass); strcat(*buffer, fieldsep); + strcat(*buffer, pwChange); strcat(*buffer, fieldsep); + strcat(*buffer, pwExpire); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_gecos); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_dir); strcat(*buffer, fieldsep); + strcat(*buffer, pw->pw_shell); strcat(*buffer, fieldsep); + + return (0); +} + +/*% + * int irp_unmarshall_pw(struct passwd *pw, char *buffer) + * + * notes: \li + * + * See irpmarshall.h + * + * return: \li + * + * 0 on success, -1 on failure + * + */ + +int +irp_unmarshall_pw(struct passwd *pw, char *buffer) { + char *name, *pass, *class, *gecos, *dir, *shell; + uid_t pwuid; + gid_t pwgid; + time_t pwchange; + time_t pwexpire; + char *p; + long t; + char tmpbuf[24]; + char *tb = &tmpbuf[0]; + char fieldsep = ':'; + int myerrno = EINVAL; + + name = pass = class = gecos = dir = shell = NULL; + p = buffer; + + /* pw_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0) { + goto error; + } + + /* pw_passwd field */ + pass = NULL; + if (getfield(&pass, 0, &p, fieldsep) == NULL) { /*%< field can be empty */ + goto error; + } + + + /* pw_uid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /*%< junk in value */ + } + pwuid = (uid_t)t; + if ((long) pwuid != t) { /*%< value must have been too big. */ + goto error; + } + + + + /* pw_gid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /*%< junk in value */ + } + pwgid = (gid_t)t; + if ((long)pwgid != t) { /*%< value must have been too big. */ + goto error; + } + + + + /* pw_class field */ + class = NULL; + if (getfield(&class, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_change field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /*%< junk in value */ + } + pwchange = (time_t)t; + if ((long)pwchange != t) { /*%< value must have been too big. */ + goto error; + } + + + + /* pw_expire field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /*%< junk in value */ + } + pwexpire = (time_t)t; + if ((long) pwexpire != t) { /*%< value must have been too big. */ + goto error; + } + + + + /* pw_gecos field */ + gecos = NULL; + if (getfield(&gecos, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_dir field */ + dir = NULL; + if (getfield(&dir, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + /* pw_shell field */ + shell = NULL; + if (getfield(&shell, 0, &p, fieldsep) == NULL) { + goto error; + } + + + + pw->pw_name = name; + pw->pw_passwd = pass; + pw->pw_uid = pwuid; + pw->pw_gid = pwgid; + pw->pw_gecos = gecos; + pw->pw_dir = dir; + pw->pw_shell = shell; + +#ifdef HAVE_PW_CHANGE + pw->pw_change = pwchange; +#endif +#ifdef HAVE_PW_CLASS + pw->pw_class = class; +#endif +#ifdef HAVE_PW_EXPIRE + pw->pw_expire = pwexpire; +#endif + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (pass != NULL) free(pass); + if (gecos != NULL) free(gecos); + if (dir != NULL) free(dir); + if (shell != NULL) free(shell); + + return (-1); +} + +/* ------------------------- struct passwd ------------------------- */ +#endif /* WANT_IRS_PW */ +/* +++++++++++++++++++++++++ struct group +++++++++++++++++++++++++ */ + +/*% + * int irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) + * + * notes: \li + * + * See irpmarshall.h. + * + * return: \li + * + * 0 on success, -1 on failure + */ + +int +irp_marshall_gr(const struct group *gr, char **buffer, size_t *len) { + size_t need = 1; /*%< for null byte */ + char grGid[24]; + const char *fieldsep = COLONSTR; + + if (gr == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(grGid, "%ld", (long)gr->gr_gid); + + need += strlen(gr->gr_name) + 1; +#ifndef MISSING_GR_PASSWD + need += strlen(gr->gr_passwd) + 1; +#else + need++; +#endif + need += strlen(grGid) + 1; + need += joinlength(gr->gr_mem) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /*%< for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, gr->gr_name); strcat(*buffer, fieldsep); +#ifndef MISSING_GR_PASSWD + strcat(*buffer, gr->gr_passwd); +#endif + strcat(*buffer, fieldsep); + strcat(*buffer, grGid); strcat(*buffer, fieldsep); + joinarray(gr->gr_mem, *buffer, COMMA) ; strcat(*buffer, fieldsep); + + return (0); +} + +/*% + * int irp_unmarshall_gr(struct group *gr, char *buffer) + * + * notes: \li + * + * See irpmarshall.h + * + * return: \li + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_gr(struct group *gr, char *buffer) { + char *p, *q; + gid_t grgid; + long t; + char *name = NULL; + char *pass = NULL; + char **members = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (gr == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* gr_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { + goto error; + } + + + /* gr_passwd field */ + pass = NULL; + if (getfield(&pass, 0, &p, fieldsep) == NULL) { + goto error; + } + + + /* gr_gid field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0U) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /*%< junk in value */ + } + grgid = (gid_t)t; + if ((long) grgid != t) { /*%< value must have been too big. */ + goto error; + } + + + /* gr_mem field. Member names are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + members = splitarray(p, q, COMMA); + if (members == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + gr->gr_name = name; +#ifndef MISSING_GR_PASSWD + gr->gr_passwd = pass; +#endif + gr->gr_gid = grgid; + gr->gr_mem = members; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (pass != NULL) free(pass); + + return (-1); +} + + +/* ------------------------- struct group ------------------------- */ + + + + +/* +++++++++++++++++++++++++ struct servent +++++++++++++++++++++++++ */ + +/*% + * int irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) + * + * notes: \li + * + * See irpmarshall.h + * + * return: \li + * + * 0 on success, -1 on failure. + * + */ + +int +irp_marshall_sv(const struct servent *sv, char **buffer, size_t *len) { + size_t need = 1; /*%< for null byte */ + char svPort[24]; + const char *fieldsep = COLONSTR; + short realport; + + if (sv == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + /* the int s_port field is actually a short in network order. We + want host order to make the marshalled data look correct */ + realport = ntohs((short)sv->s_port); + sprintf(svPort, "%d", realport); + + need += strlen(sv->s_name) + 1; + need += joinlength(sv->s_aliases) + 1; + need += strlen(svPort) + 1; + need += strlen(sv->s_proto) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /*%< for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, sv->s_name); strcat(*buffer, fieldsep); + joinarray(sv->s_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, svPort); strcat(*buffer, fieldsep); + strcat(*buffer, sv->s_proto); strcat(*buffer, fieldsep); + + return (0); +} + +/*% + * int irp_unmarshall_sv(struct servent *sv, char *buffer) + * + * notes: \li + * + * See irpmarshall.h + * + * return: \li + * + * 0 on success, -1 on failure. + * + */ + +int +irp_unmarshall_sv(struct servent *sv, char *buffer) { + char *p, *q; + short svport; + long t; + char *name = NULL; + char *proto = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (sv == NULL || buffer == NULL) + return (-1); + + p = buffer; + + + /* s_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { + goto error; + } + + + /* s_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* s_port field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0U) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /*%< junk in value */ + } + svport = (short)t; + if ((long) svport != t) { /*%< value must have been too big. */ + goto error; + } + svport = htons(svport); + + /* s_proto field */ + proto = NULL; + if (getfield(&proto, 0, &p, fieldsep) == NULL) { + goto error; + } + + sv->s_name = name; + sv->s_aliases = aliases; + sv->s_port = svport; + sv->s_proto = proto; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + if (proto != NULL) free(proto); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct servent ------------------------- */ + +/* +++++++++++++++++++++++++ struct protoent +++++++++++++++++++++++++ */ + +/*% + * int irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) + * + * notes: \li + * + * See irpmarshall.h + * + * return: \li + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_pr(struct protoent *pr, char **buffer, size_t *len) { + size_t need = 1; /*%< for null byte */ + char prProto[24]; + const char *fieldsep = COLONSTR; + + if (pr == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + sprintf(prProto, "%d", (int)pr->p_proto); + + need += strlen(pr->p_name) + 1; + need += joinlength(pr->p_aliases) + 1; + need += strlen(prProto) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /*%< for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, pr->p_name); strcat(*buffer, fieldsep); + joinarray(pr->p_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, prProto); strcat(*buffer, fieldsep); + + return (0); + +} + +/*% + * int irp_unmarshall_pr(struct protoent *pr, char *buffer) + * + * notes: \li + * + * See irpmarshall.h + * + * return: \li + * + * 0 on success, -1 on failure + * + */ + +int irp_unmarshall_pr(struct protoent *pr, char *buffer) { + char *p, *q; + int prproto; + long t; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (pr == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* p_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { + goto error; + } + + + /* p_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* p_proto field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0U) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /*%< junk in value */ + } + prproto = (int)t; + if ((long) prproto != t) { /*%< value must have been too big. */ + goto error; + } + + pr->p_name = name; + pr->p_aliases = aliases; + pr->p_proto = prproto; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + +/* ------------------------- struct protoent ------------------------- */ + + + +/* +++++++++++++++++++++++++ struct hostent +++++++++++++++++++++++++ */ + +/*% + * int irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) + * + * notes: \li + * + * See irpmarshall.h. + * + * return: \li + * + * 0 on success, -1 on failure. + * + */ + +int +irp_marshall_ho(struct hostent *ho, char **buffer, size_t *len) { + size_t need = 1; /*%< for null byte */ + char hoaddrtype[24]; + char holength[24]; + char **av; + char *p; + int addrlen; + int malloced = 0; + size_t remlen; + const char *fieldsep = "@"; + + if (ho == NULL || len == NULL) { + errno = EINVAL; + return (-1); + } + + switch(ho->h_addrtype) { + case AF_INET: + strcpy(hoaddrtype, "AF_INET"); + break; + + case AF_INET6: + strcpy(hoaddrtype, "AF_INET6"); + break; + + default: + errno = EINVAL; + return (-1); + } + + sprintf(holength, "%d", ho->h_length); + + need += strlen(ho->h_name) + 1; + need += joinlength(ho->h_aliases) + 1; + need += strlen(hoaddrtype) + 1; + need += strlen(holength) + 1; + + /* we determine an upper bound on the string length needed, not an + exact length. */ + addrlen = (ho->h_addrtype == AF_INET ? 16 : 46) ; /*%< XX other AF's?? */ + for (av = ho->h_addr_list; av != NULL && *av != NULL ; av++) + need += addrlen; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /*%< for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + malloced = 1; + } + + strcpy(*buffer, ho->h_name); strcat(*buffer, fieldsep); + joinarray(ho->h_aliases, *buffer, COMMA); strcat(*buffer, fieldsep); + strcat(*buffer, hoaddrtype); strcat(*buffer, fieldsep); + strcat(*buffer, holength); strcat(*buffer, fieldsep); + + p = *buffer + strlen(*buffer); + remlen = need - strlen(*buffer); + for (av = ho->h_addr_list ; av != NULL && *av != NULL ; av++) { + if (inet_ntop(ho->h_addrtype, *av, p, remlen) == NULL) { + goto error; + } + if (*(av + 1) != NULL) + strcat(p, COMMASTR); + remlen -= strlen(p); + p += strlen(p); + } + strcat(*buffer, fieldsep); + + return (0); + + error: + if (malloced) { + memput(*buffer, need); + } + + return (-1); +} + +/*% + * int irp_unmarshall_ho(struct hostent *ho, char *buffer) + * + * notes: \li + * + * See irpmarshall.h. + * + * return: \li + * + * 0 on success, -1 on failure. + * + */ + +int +irp_unmarshall_ho(struct hostent *ho, char *buffer) { + char *p, *q, *r; + int hoaddrtype; + int holength; + long t; + char *name; + char **aliases = NULL; + char **hohaddrlist = NULL; + size_t hoaddrsize; + char tmpbuf[24]; + char *tb; + char **alist; + int addrcount; + char fieldsep = '@'; + int myerrno = EINVAL; + + if (ho == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + p = buffer; + + /* h_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { + goto error; + } + + + /* h_aliases field */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0U) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + hoaddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + hoaddrtype = AF_INET6; + else + goto error; + + + /* h_length field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0U) { + goto error; + } + t = strtol(tmpbuf, &tb, 10); + if (*tb) { + goto error; /*%< junk in value */ + } + holength = (int)t; + if ((long) holength != t) { /*%< value must have been too big. */ + goto error; + } + + + /* h_addr_list field */ + q = strchr(p, fieldsep); + if (q == NULL) + goto error; + + /* count how many addresss are in there */ + if (q > p + 1) { + for (addrcount = 1, r = p ; r != q ; r++) { + if (*r == COMMA) + addrcount++; + } + } else { + addrcount = 0; + } + + hoaddrsize = (addrcount + 1) * sizeof (char *); + hohaddrlist = malloc(hoaddrsize); + if (hohaddrlist == NULL) { + myerrno = ENOMEM; + goto error; + } + + memset(hohaddrlist, 0x0, hoaddrsize); + + alist = hohaddrlist; + for (t = 0, r = p ; r != q ; p = r + 1, t++) { + char saved; + while (r != q && *r != COMMA) r++; + saved = *r; + *r = 0x0; + + alist[t] = malloc(hoaddrtype == AF_INET ? 4 : 16); + if (alist[t] == NULL) { + myerrno = ENOMEM; + goto error; + } + + if (inet_pton(hoaddrtype, p, alist[t]) == -1) + goto error; + *r = saved; + } + alist[t] = NULL; + + ho->h_name = name; + ho->h_aliases = aliases; + ho->h_addrtype = hoaddrtype; + ho->h_length = holength; + ho->h_addr_list = hohaddrlist; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(hohaddrlist, 0); + free_array(aliases, 0); + + return (-1); +} + +/* ------------------------- struct hostent------------------------- */ + + + +/* +++++++++++++++++++++++++ struct netgrp +++++++++++++++++++++++++ */ + +/*% + * int irp_marshall_ng(const char *host, const char *user, + * const char *domain, char *buffer, size_t *len) + * + * notes: \li + * + * See note for irp_marshall_ng_start + * + * return: \li + * + * 0 on success, 0 on failure. + * + */ + +int +irp_marshall_ng(const char *host, const char *user, const char *domain, + char **buffer, size_t *len) { + size_t need = 1; /*%< for nul byte */ + const char *fieldsep = ","; + + if (len == NULL) { + errno = EINVAL; + return (-1); + } + + need += 4; /*%< two parens and two commas */ + need += (host == NULL ? 0 : strlen(host)); + need += (user == NULL ? 0 : strlen(user)); + need += (domain == NULL ? 0 : strlen(domain)); + + if (buffer == NULL) { + *len = need; + return (0); + } else if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /*%< for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + (*buffer)[0] = '('; + (*buffer)[1] = '\0'; + + if (host != NULL) + strcat(*buffer, host); + strcat(*buffer, fieldsep); + + if (user != NULL) + strcat(*buffer, user); + strcat(*buffer, fieldsep); + + if (domain != NULL) + strcat(*buffer, domain); + strcat(*buffer, ")"); + + return (0); +} + + + +/* ---------- */ + +/*% + * int irp_unmarshall_ng(const char **host, const char **user, + * const char **domain, char *buffer) + * + * notes: \li + * + * Unpacks the BUFFER into 3 character arrays it allocates and assigns + * to *HOST, *USER and *DOMAIN. If any field of the value is empty, + * then the corresponding paramater value will be set to NULL. + * + * return: \li + * + * 0 on success and -1 on failure. + */ + +int +irp_unmarshall_ng(const char **hostp, const char **userp, const char **domainp, + char *buffer) +{ + char *p, *q; + char fieldsep = ','; + int myerrno = EINVAL; + char *host, *user, *domain; + + if (userp == NULL || hostp == NULL || + domainp == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + host = user = domain = NULL; + + p = buffer; + while (isspace((unsigned char)*p)) { + p++; + } + if (*p != '(') { + goto error; + } + + q = p + 1; + while (*q && *q != fieldsep) + q++; + if (!*q) { + goto error; + } else if (q > p + 1) { + host = strndup(p, q - p); + } + + p = q + 1; + if (!*p) { + goto error; + } else if (*p != fieldsep) { + q = p + 1; + while (*q && *q != fieldsep) + q++; + if (!*q) { + goto error; + } + user = strndup(p, q - p); + } else { + p++; + } + + if (!*p) { + goto error; + } else if (*p != ')') { + q = p + 1; + while (*q && *q != ')') + q++; + if (!*q) { + goto error; + } + domain = strndup(p, q - p); + } + *hostp = host; + *userp = user; + *domainp = domain; + + return (0); + + error: + errno = myerrno; + + if (host != NULL) free(host); + if (user != NULL) free(user); + + return (-1); +} + +/* ------------------------- struct netgrp ------------------------- */ + + + + +/* +++++++++++++++++++++++++ struct nwent +++++++++++++++++++++++++ */ + +/*% + * int irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) + * + * notes: \li + * + * See at top. + * + * return: \li + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_nw(struct nwent *ne, char **buffer, size_t *len) { + size_t need = 1; /*%< for null byte */ + char nAddrType[24]; + char nNet[MAXPADDRSIZE]; + const char *fieldsep = COLONSTR; + + if (ne == NULL || len == NULL) { + return (-1); + } + + strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); + + if (inet_net_ntop(ne->n_addrtype, ne->n_addr, ne->n_length, + nNet, sizeof nNet) == NULL) { + return (-1); + } + + + need += strlen(ne->n_name) + 1; + need += joinlength(ne->n_aliases) + 1; + need += strlen(nAddrType) + 1; + need += strlen(nNet) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /*%< for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep); + joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep); + strcat(*buffer, nAddrType); strcat(*buffer, fieldsep); + strcat(*buffer, nNet); strcat(*buffer, fieldsep); + + return (0); +} + +/*% + * int irp_unmarshall_nw(struct nwent *ne, char *buffer) + * + * notes: \li + * + * See note up top. + * + * return: \li + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_nw(struct nwent *ne, char *buffer) { + char *p, *q; + int naddrtype; + long nnet; + int bits; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (ne == NULL || buffer == NULL) { + goto error; + } + + p = buffer; + + /* n_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { + goto error; + } + + + /* n_aliases field. Aliases are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0U) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + naddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + naddrtype = AF_INET6; + else + goto error; + + + /* n_net field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0U) { + goto error; + } + nnet = 0; + bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); + if (bits < 0) { + goto error; + } + + /* nnet = ntohl(nnet); */ /* keep in network order for nwent */ + + ne->n_name = name; + ne->n_aliases = aliases; + ne->n_addrtype = naddrtype; + ne->n_length = bits; + ne->n_addr = malloc(sizeof nnet); + if (ne->n_addr == NULL) { + goto error; + } + + memcpy(ne->n_addr, &nnet, sizeof nnet); + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct nwent ------------------------- */ + + +/* +++++++++++++++++++++++++ struct netent +++++++++++++++++++++++++ */ + +/*% + * int irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) + * + * notes: \li + * + * See at top. + * + * return: \li + * + * 0 on success and -1 on failure. + * + */ + +int +irp_marshall_ne(struct netent *ne, char **buffer, size_t *len) { + size_t need = 1; /*%< for null byte */ + char nAddrType[24]; + char nNet[MAXPADDRSIZE]; + const char *fieldsep = COLONSTR; + long nval; + + if (ne == NULL || len == NULL) { + return (-1); + } + + strcpy(nAddrType, ADDR_T_STR(ne->n_addrtype)); + + nval = htonl(ne->n_net); + if (inet_ntop(ne->n_addrtype, &nval, nNet, sizeof nNet) == NULL) { + return (-1); + } + + need += strlen(ne->n_name) + 1; + need += joinlength(ne->n_aliases) + 1; + need += strlen(nAddrType) + 1; + need += strlen(nNet) + 1; + + if (buffer == NULL) { + *len = need; + return (0); + } + + if (*buffer != NULL && need > *len) { + errno = EINVAL; + return (-1); + } + + if (*buffer == NULL) { + need += 2; /*%< for CRLF */ + *buffer = memget(need); + if (*buffer == NULL) { + errno = ENOMEM; + return (-1); + } + + *len = need; + } + + strcpy(*buffer, ne->n_name); strcat(*buffer, fieldsep); + joinarray(ne->n_aliases, *buffer, COMMA) ; strcat(*buffer, fieldsep); + strcat(*buffer, nAddrType); strcat(*buffer, fieldsep); + strcat(*buffer, nNet); strcat(*buffer, fieldsep); + + return (0); +} + +/*% + * int irp_unmarshall_ne(struct netent *ne, char *buffer) + * + * notes: \li + * + * See note up top. + * + * return: \li + * + * 0 on success and -1 on failure. + * + */ + +int +irp_unmarshall_ne(struct netent *ne, char *buffer) { + char *p, *q; + int naddrtype; + long nnet; + int bits; + char *name = NULL; + char **aliases = NULL; + char tmpbuf[24]; + char *tb; + char fieldsep = ':'; + int myerrno = EINVAL; + + if (ne == NULL || buffer == NULL) { + goto error; + } + + p = buffer; + + /* n_name field */ + name = NULL; + if (getfield(&name, 0, &p, fieldsep) == NULL || strlen(name) == 0U) { + goto error; + } + + + /* n_aliases field. Aliases are separated by commas */ + q = strchr(p, fieldsep); + if (q == NULL) { + goto error; + } + aliases = splitarray(p, q, COMMA); + if (aliases == NULL) { + myerrno = errno; + goto error; + } + p = q + 1; + + + /* h_addrtype field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0U) { + goto error; + } + if (strcmp(tmpbuf, "AF_INET") == 0) + naddrtype = AF_INET; + else if (strcmp(tmpbuf, "AF_INET6") == 0) + naddrtype = AF_INET6; + else + goto error; + + + /* n_net field */ + tb = tmpbuf; + if (getfield(&tb, sizeof tmpbuf, &p, fieldsep) == NULL || + strlen(tb) == 0U) { + goto error; + } + bits = inet_net_pton(naddrtype, tmpbuf, &nnet, sizeof nnet); + if (bits < 0) { + goto error; + } + nnet = ntohl(nnet); + + ne->n_name = name; + ne->n_aliases = aliases; + ne->n_addrtype = naddrtype; + ne->n_net = nnet; + + return (0); + + error: + errno = myerrno; + + if (name != NULL) free(name); + free_array(aliases, 0); + + return (-1); +} + + +/* ------------------------- struct netent ------------------------- */ + + +/* =========================================================================== */ + +/*% + * static char ** splitarray(const char *buffer, const char *buffend, char delim) + * + * notes: \li + * + * Split a delim separated astring. Not allowed + * to have two delims next to each other. BUFFER points to begining of + * string, BUFFEND points to one past the end of the string + * (i.e. points at where the null byte would be if null + * terminated). + * + * return: \li + * + * Returns a malloced array of pointers, each pointer pointing to a + * malloced string. If BUFEER is an empty string, then return values is + * array of 1 pointer that is NULL. Returns NULL on failure. + * + */ + +static char ** +splitarray(const char *buffer, const char *buffend, char delim) { + const char *p, *q; + int count = 0; + char **arr = NULL; + char **aptr; + + if (buffend < buffer) + return (NULL); + else if (buffend > buffer && *buffer == delim) + return (NULL); + else if (buffend > buffer && *(buffend - 1) == delim) + return (NULL); + + /* count the number of field and make sure none are empty */ + if (buffend > buffer + 1) { + for (count = 1, q = buffer ; q != buffend ; q++) { + if (*q == delim) { + if (q > buffer && (*(q - 1) == delim)) { + errno = EINVAL; + return (NULL); + } + count++; + } + } + } + + if (count > 0) { + count++ ; /*%< for NULL at end */ + aptr = arr = malloc(count * sizeof (char *)); + if (aptr == NULL) { + errno = ENOMEM; + return (NULL); + } + + memset(arr, 0x0, count * sizeof (char *)); + for (p = buffer ; p < buffend ; p++) { + for (q = p ; *q != delim && q != buffend ; q++) + /* nothing */; + *aptr = strndup(p, q - p); + + p = q; + aptr++; + } + *aptr = NULL; + } else { + arr = malloc(sizeof (char *)); + if (arr == NULL) { + errno = ENOMEM; + return (NULL); + } + + *arr = NULL; + } + + return (arr); +} + +/*% + * static size_t joinlength(char * const *argv) + * + * return: \li + * + * the number of bytes in all the arrays pointed at + * by argv, including their null bytes(which will usually be turned + * into commas). + * + * + */ + +static size_t +joinlength(char * const *argv) { + int len = 0; + + while (argv && *argv) { + len += (strlen(*argv) + 1); + argv++; + } + + return (len); +} + +/*% + * int joinarray(char * const *argv, char *buffer, char delim) + * + * notes: \li + * + * Copy all the ARGV strings into the end of BUFFER + * separating them with DELIM. BUFFER is assumed to have + * enough space to hold everything and to be already null-terminated. + * + * return: \li + * + * 0 unless argv or buffer is NULL. + * + * + */ + +static int +joinarray(char * const *argv, char *buffer, char delim) { + char * const *p; + char sep[2]; + + if (argv == NULL || buffer == NULL) { + errno = EINVAL; + return (-1); + } + + sep[0] = delim; + sep[1] = 0x0; + + for (p = argv ; *p != NULL ; p++) { + strcat(buffer, *p); + if (*(p + 1) != NULL) { + strcat(buffer, sep); + } + } + + return (0); +} + +/*% + * static char * getfield(char **res, size_t reslen, char **ptr, char delim) + * + * notes: \li + * + * Stores in *RES, which is a buffer of length RESLEN, a + * copy of the bytes from *PTR up to and including the first + * instance of DELIM. If *RES is NULL, then it will be + * assigned a malloced buffer to hold the copy. *PTR is + * modified to point at the found delimiter. + * + * return: \li + * + * If there was no delimiter, then NULL is returned, + * otherewise *RES is returned. + * + */ + +static char * +getfield(char **res, size_t reslen, char **ptr, char delim) { + char *q; + + if (res == NULL || ptr == NULL || *ptr == NULL) { + errno = EINVAL; + return (NULL); + } + + q = strchr(*ptr, delim); + + if (q == NULL) { + errno = EINVAL; + return (NULL); + } else { + if (*res == NULL) { + *res = strndup(*ptr, q - *ptr); + } else { + if ((size_t)(q - *ptr + 1) > reslen) { /*%< to big for res */ + errno = EINVAL; + return (NULL); + } else { + strncpy(*res, *ptr, q - *ptr); + (*res)[q - *ptr] = 0x0; + } + } + *ptr = q + 1; + } + + return (*res); +} + + + + + +#ifndef HAVE_STRNDUP +/* + * static char * strndup(const char *str, size_t len) + * + * notes: \li + * + * like strdup, except do len bytes instead of the whole string. Always + * null-terminates. + * + * return: \li + * + * The newly malloced string. + * + */ + +static char * +strndup(const char *str, size_t len) { + char *p = malloc(len + 1); + + if (p == NULL) + return (NULL); + strncpy(p, str, len); + p[len] = 0x0; + return (p); +} +#endif + +#if WANT_MAIN + +/*% + * static int strcmp_nws(const char *a, const char *b) + * + * notes: \li + * + * do a strcmp, except uneven lengths of whitespace compare the same + * + * return: \li + * + */ + +static int +strcmp_nws(const char *a, const char *b) { + while (*a && *b) { + if (isspace(*a) && isspace(*b)) { + do { + a++; + } while (isspace(*a)); + do { + b++; + } while (isspace(*b)); + } + if (*a < *b) + return (-1); + else if (*a > *b) + return (1); + + a++; + b++;; + } + + if (*a == *b) + return (0); + else if (*a > *b) + return (1); + else + return (-1); +} + +#endif + +/*% + * static void free_array(char **argv, size_t entries) + * + * notes: \li + * + * Free argv and each of the pointers inside it. The end of + * the array is when a NULL pointer is found inside. If + * entries is > 0, then NULL pointers inside the array do + * not indicate the end of the array. + * + */ + +static void +free_array(char **argv, size_t entries) { + char **p = argv; + int useEntries = (entries > 0U); + + if (argv == NULL) + return; + + while ((useEntries && entries > 0U) || *p) { + if (*p) + free(*p); + p++; + if (useEntries) + entries--; + } + free(argv); +} + + + + + +/* ************************************************** */ + +#if WANT_MAIN + +/*% takes an option to indicate what sort of marshalling(read the code) and + an argument. If the argument looks like a marshalled buffer(has a ':' + embedded) then it's unmarshalled and the remarshalled and the new string + is compared to the old one. +*/ + +int +main(int argc, char **argv) { + char buffer[1024]; + char *b = &buffer[0]; + size_t len = sizeof buffer; + char option; + + if (argc < 2 || argv[1][0] != '-') + exit(1); + + option = argv[1][1]; + argv++; + argc--; + + +#if 0 + { + char buff[10]; + char *p = argv[1], *q = &buff[0]; + + while (getfield(&q, sizeof buff, &p, ':') != NULL) { + printf("field: \"%s\"\n", q); + p++; + } + printf("p is now \"%s\"\n", p); + } +#endif + +#if 0 + { + char **x = splitarray(argv[1], argv[1] + strlen(argv[1]), + argv[2][0]); + char **p; + + if (x == NULL) + printf("split failed\n"); + + for (p = x ; p != NULL && *p != NULL ; p++) { + printf("\"%s\"\n", *p); + } + } +#endif + +#if 1 + switch(option) { + case 'n': { + struct nwent ne; + int i; + + if (strchr(argv[1], ':') != NULL) { + if (irp_unmarshall_nw(&ne, argv[1]) != 0) { + printf("Unmarhsalling failed\n"); + exit(1); + } + + printf("Name: \"%s\"\n", ne.n_name); + printf("Aliases:"); + for (i = 0 ; ne.n_aliases[i] != NULL ; i++) + printf("\n\t\"%s\"", ne.n_aliases[i]); + printf("\nAddrtype: %s\n", ADDR_T_STR(ne.n_addrtype)); + inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length, + buffer, sizeof buffer); + printf("Net: \"%s\"\n", buffer); + *((long*)ne.n_addr) = htonl(*((long*)ne.n_addr)); + inet_net_ntop(ne.n_addrtype, ne.n_addr, ne.n_length, + buffer, sizeof buffer); + printf("Corrected Net: \"%s\"\n", buffer); + } else { + struct netent *np1 = getnetbyname(argv[1]); + ne.n_name = np1->n_name; + ne.n_aliases = np1->n_aliases; + ne.n_addrtype = np1->n_addrtype; + ne.n_addr = &np1->n_net; + ne.n_length = (IN_CLASSA(np1->n_net) ? + 8 : + (IN_CLASSB(np1->n_net) ? + 16 : + (IN_CLASSC(np1->n_net) ? + 24 : -1))); + np1->n_net = htonl(np1->n_net); + if (irp_marshall_nw(&ne, &b, &len) != 0) { + printf("Marshalling failed\n"); + } + printf("%s\n", b); + } + break; + } + + + case 'r': { + char **hosts, **users, **domains; + size_t entries; + int i; + char *buff; + size_t size; + char *ngname; + + if (strchr(argv[1], '(') != NULL) { + if (irp_unmarshall_ng(&ngname, &entries, + &hosts, &users, &domains, + argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + +#define STRVAL(x) (x == NULL ? "*" : x) + + printf("%s {\n", ngname); + for (i = 0 ; i < entries ; i++) + printf("\t\"%s\" : \"%s\" : \"%s\"\n", + STRVAL(hosts[i]), + STRVAL(users[i]), + STRVAL(domains[i])); + printf("}\n\n\n"); + + + irp_marshall_ng_start(ngname, NULL, &size); + for (i = 0 ; i < entries ; i++) + irp_marshall_ng_next(hosts[i], users[i], + domains[i], NULL, &size); + irp_marshall_ng_end(NULL, &size); + + buff = malloc(size); + + irp_marshall_ng_start(ngname, buff, &size); + for (i = 0 ; i < entries ; i++) { + if (irp_marshall_ng_next(hosts[i], users[i], + domains[i], buff, + &size) != 0) + printf("next marshalling failed.\n"); + } + irp_marshall_ng_end(buff, &size); + + if (strcmp_nws(argv[1], buff) != 0) { + printf("compare failed:\n\t%s\n\t%s\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + char *h, *u, *d, *buff; + size_t size; + + /* run through two times. First to figure out how + much of a buffer we need. Second to do the + actual marshalling */ + + setnetgrent(argv[1]); + irp_marshall_ng_start(argv[1], NULL, &size); + while (getnetgrent(&h, &u, &d) == 1) + irp_marshall_ng_next(h, u, d, NULL, &size); + irp_marshall_ng_end(NULL, &size); + endnetgrent(argv[1]); + + buff = malloc(size); + + setnetgrent(argv[1]); + if (irp_marshall_ng_start(argv[1], buff, &size) != 0) + printf("Marshalling start failed\n"); + + while (getnetgrent(&h, &u, &d) == 1) { + if (irp_marshall_ng_next(h, u, d, buff, &size) + != 0) { + printf("Marshalling failed\n"); + } + } + + irp_marshall_ng_end(buff, &size); + endnetgrent(); + + printf("success: %s\n", buff); + } + break; + } + + + + case 'h': { + struct hostent he, *hp; + int i; + + + if (strchr(argv[1], '@') != NULL) { + if (irp_unmarshall_ho(&he, argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + + printf("Host: \"%s\"\nAliases:", he.h_name); + for (i = 0 ; he.h_aliases[i] != NULL ; i++) + printf("\n\t\t\"%s\"", he.h_aliases[i]); + printf("\nAddr Type: \"%s\"\n", + ADDR_T_STR(he.h_addrtype)); + printf("Length: %d\nAddresses:", he.h_length); + for (i = 0 ; he.h_addr_list[i] != 0 ; i++) { + inet_ntop(he.h_addrtype, he.h_addr_list[i], + buffer, sizeof buffer); + printf("\n\t\"%s\"\n", buffer); + } + printf("\n\n"); + + irp_marshall_ho(&he, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((hp = gethostbyname(argv[1])) == NULL) { + perror("gethostbyname"); + printf("\"%s\"\n", argv[1]); + exit(1); + } + + if (irp_marshall_ho(hp, &b, &len) != 0) { + printf("irp_marshall_ho failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + + case 's': { + struct servent *sv; + struct servent sv1; + + if (strchr(argv[1], ':') != NULL) { + sv = &sv1; + memset(sv, 0xef, sizeof (struct servent)); + if (irp_unmarshall_sv(sv, argv[1]) != 0) { + printf("unmarshall failed\n"); + + } + + irp_marshall_sv(sv, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((sv = getservbyname(argv[1], argv[2])) == NULL) { + perror("getservent"); + exit(1); + } + + if (irp_marshall_sv(sv, &b, &len) != 0) { + printf("irp_marshall_sv failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + case 'g': { + struct group *gr; + struct group gr1; + + if (strchr(argv[1], ':') != NULL) { + gr = &gr1; + memset(gr, 0xef, sizeof (struct group)); + if (irp_unmarshall_gr(gr, argv[1]) != 0) { + printf("unmarshall failed\n"); + + } + + irp_marshall_gr(gr, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((gr = getgrnam(argv[1])) == NULL) { + perror("getgrnam"); + exit(1); + } + + if (irp_marshall_gr(gr, &b, &len) != 0) { + printf("irp_marshall_gr failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + + case 'p': { + struct passwd *pw; + struct passwd pw1; + + if (strchr(argv[1], ':') != NULL) { + pw = &pw1; + memset(pw, 0xef, sizeof (*pw)); + if (irp_unmarshall_pw(pw, argv[1]) != 0) { + printf("unmarshall failed\n"); + exit(1); + } + + printf("User: \"%s\"\nPasswd: \"%s\"\nUid: %ld\nGid: %ld\n", + pw->pw_name, pw->pw_passwd, (long)pw->pw_uid, + (long)pw->pw_gid); + printf("Class: \"%s\"\nChange: %ld\nGecos: \"%s\"\n", + pw->pw_class, (long)pw->pw_change, pw->pw_gecos); + printf("Shell: \"%s\"\nDirectory: \"%s\"\n", + pw->pw_shell, pw->pw_dir); + + pw = getpwnam(pw->pw_name); + irp_marshall_pw(pw, &b, &len); + if (strcmp(argv[1], buffer) != 0) { + printf("compare failed:\n\t\"%s\"\n\t\"%s\"\n", + buffer, argv[1]); + } else { + printf("compare ok\n"); + } + } else { + if ((pw = getpwnam(argv[1])) == NULL) { + perror("getpwnam"); + exit(1); + } + + if (irp_marshall_pw(pw, &b, &len) != 0) { + printf("irp_marshall_pw failed\n"); + exit(1); + } + + printf("success: \"%s\"\n", buffer); + } + break; + } + + default: + printf("Wrong option: %c\n", option); + break; + } + +#endif + + return (0); +} + +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irs_data.c b/usr/src/lib/libresolv2_joy/common/irs/irs_data.c new file mode 100644 index 0000000000..f12ca20f38 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irs_data.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: irs_data.c,v 1.12 2007/08/27 03:32:26 marka Exp $"; +#endif + +#include "port_before.h" + +#ifndef __BIND_NOSTATIC + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <resolv_joy.h> +#include <stdio.h> +#include <string.h> +#include <isc/memcluster.h> + +#ifdef DO_PTHREADS +#include <pthread.h> +#endif + +#include <irs.h> +#include <stdlib.h> + +#include "port_after.h" + +#include "irs_data.h" +#undef _res +#if !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) +#undef h_errno +extern int h_errno; +#endif + +extern struct __res_state _res; + +#ifdef DO_PTHREADS +static pthread_key_t key; +static int once = 0; +#else +static struct net_data *net_data; +#endif + +void +irs_destroy(void) { +#ifndef DO_PTHREADS + if (net_data != NULL) + net_data_destroy(net_data); + net_data = NULL; +#endif +} + +void +net_data_destroy(void *p) { + struct net_data *net_data = p; + + res_ndestroy(net_data->res); + if (net_data->gr != NULL) { + (*net_data->gr->close)(net_data->gr); + net_data->gr = NULL; + } + if (net_data->pw != NULL) { + (*net_data->pw->close)(net_data->pw); + net_data->pw = NULL; + } + if (net_data->sv != NULL) { + (*net_data->sv->close)(net_data->sv); + net_data->sv = NULL; + } + if (net_data->pr != NULL) { + (*net_data->pr->close)(net_data->pr); + net_data->pr = NULL; + } + if (net_data->ho != NULL) { + (*net_data->ho->close)(net_data->ho); + net_data->ho = NULL; + } + if (net_data->nw != NULL) { + (*net_data->nw->close)(net_data->nw); + net_data->nw = NULL; + } + if (net_data->ng != NULL) { + (*net_data->ng->close)(net_data->ng); + net_data->ng = NULL; + } + if (net_data->ho_data != NULL) { + free(net_data->ho_data); + net_data->ho_data = NULL; + } + if (net_data->nw_data != NULL) { + free(net_data->nw_data); + net_data->nw_data = NULL; + } + + (*net_data->irs->close)(net_data->irs); + memput(net_data, sizeof *net_data); +} + +/*% + * applications that need a specific config file other than + * _PATH_IRS_CONF should call net_data_init directly rather than letting + * the various wrapper functions make the first call. - brister + */ + +struct net_data * +net_data_init(const char *conf_file) { +#ifdef DO_PTHREADS +#ifndef LIBBIND_MUTEX_INITIALIZER +#define LIBBIND_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#endif + static pthread_mutex_t keylock = LIBBIND_MUTEX_INITIALIZER; + struct net_data *net_data; + + if (!once) { + if (pthread_mutex_lock(&keylock) != 0) + return (NULL); + if (!once) { + if (pthread_key_create(&key, net_data_destroy) != 0) { + (void)pthread_mutex_unlock(&keylock); + return (NULL); + } + once = 1; + } + if (pthread_mutex_unlock(&keylock) != 0) + return (NULL); + } + net_data = pthread_getspecific(key); +#endif + + if (net_data == NULL) { + net_data = net_data_create(conf_file); + if (net_data == NULL) + return (NULL); +#ifdef DO_PTHREADS + if (pthread_setspecific(key, net_data) != 0) { + net_data_destroy(net_data); + return (NULL); + } +#endif + } + + return (net_data); +} + +struct net_data * +net_data_create(const char *conf_file) { + struct net_data *net_data; + + net_data = memget(sizeof (struct net_data)); + if (net_data == NULL) + return (NULL); + memset(net_data, 0, sizeof (struct net_data)); + + if ((net_data->irs = irs_gen_acc("", conf_file)) == NULL) { + memput(net_data, sizeof (struct net_data)); + return (NULL); + } +#ifndef DO_PTHREADS + (*net_data->irs->res_set)(net_data->irs, &_res, NULL); +#endif + + net_data->res = (*net_data->irs->res_get)(net_data->irs); + if (net_data->res == NULL) { + (*net_data->irs->close)(net_data->irs); + memput(net_data, sizeof (struct net_data)); + return (NULL); + } + + if ((net_data->res->options & RES_INIT) == 0U && + res_ninit(net_data->res) == -1) { + (*net_data->irs->close)(net_data->irs); + memput(net_data, sizeof (struct net_data)); + return (NULL); + } + + return (net_data); +} + +void +net_data_minimize(struct net_data *net_data) { + res_nclose(net_data->res); +} + +#ifdef _REENTRANT +struct __res_state * +__res_state(void) { + /* NULL param here means use the default config file. */ + struct net_data *net_data = net_data_init(NULL); + if (net_data && net_data->res) + return (net_data->res); + + return (&_res); +} +#else +#ifdef __linux +struct __res_state * +__res_state(void) { + return (&_res); +} +#endif +#endif + +int * +__h_errno(void) { + /* NULL param here means use the default config file. */ + struct net_data *net_data = net_data_init(NULL); + if (net_data && net_data->res) + return (&net_data->res->res_h_errno); +#ifdef ORIGINAL_ISC_CODE +#if !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) + return(&_res.res_h_errno); +#else + return (&h_errno); +#endif +#else + return (&h_errno); +#endif /* ORIGINAL_ISC_CODE */ +} + +void +__h_errno_set(struct __res_state *res, int err) { + + +#if (__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) + res->res_h_errno = err; +#else + h_errno = res->res_h_errno = err; +#endif +} + +#endif /*__BIND_NOSTATIC*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irs_data.h b/usr/src/lib/libresolv2_joy/common/irs/irs_data.h new file mode 100644 index 0000000000..cb814fd8b1 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irs_data.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: irs_data.h,v 1.3 2005/04/27 04:56:30 sra Exp $ + */ + +#ifndef __BIND_NOSTATIC + +#define net_data_init __net_data_init + +struct net_data { + struct irs_acc * irs; + + struct irs_gr * gr; + struct irs_pw * pw; + struct irs_sv * sv; + struct irs_pr * pr; + struct irs_ho * ho; + struct irs_nw * nw; + struct irs_ng * ng; + + struct group * gr_last; + struct passwd * pw_last; + struct servent * sv_last; + struct protoent * pr_last; + struct netent * nw_last; /*%< should have been ne_last */ + struct nwent * nww_last; + struct hostent * ho_last; + + unsigned int gr_stayopen :1; + unsigned int pw_stayopen :1; + unsigned int sv_stayopen :1; + unsigned int pr_stayopen :1; + unsigned int ho_stayopen :1; + unsigned int nw_stayopen :1; + + void * nw_data; + void * ho_data; + + struct __res_state * res; /*%< for gethostent.c */ +}; + +extern struct net_data * net_data_init(const char *conf_file); +extern void net_data_minimize(struct net_data *); + +#endif /*__BIND_NOSTATIC*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/irs_p.h b/usr/src/lib/libresolv2_joy/common/irs/irs_p.h new file mode 100644 index 0000000000..2a0a933fce --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/irs_p.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: irs_p.h,v 1.3 2005/04/27 04:56:30 sra Exp $ + */ + +#ifndef _IRS_P_H_INCLUDED +#define _IRS_P_H_INCLUDED + +#include <stdio.h> + +#include "pathnames.h" + +#define IRS_SV_MAXALIASES 35 + +struct lcl_sv { + FILE * fp; + char line[BUFSIZ+1]; + struct servent serv; + char * serv_aliases[IRS_SV_MAXALIASES]; +}; + +#define irs_nul_ng __irs_nul_ng +#define map_v4v6_address __map_v4v6_address +#define make_group_list __make_group_list +#define irs_lclsv_fnxt __irs_lclsv_fnxt + +extern void map_v4v6_address(const char *src, char *dst); +extern int make_group_list(struct irs_gr *, const char *, + gid_t, gid_t *, int *); +extern struct irs_ng * irs_nul_ng(struct irs_acc *); +extern struct servent * irs_lclsv_fnxt(struct lcl_sv *); + +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/lcl.c b/usr/src/lib/libresolv2_joy/common/irs/lcl.c new file mode 100644 index 0000000000..9dd6967b87 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/lcl.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: lcl.c,v 1.4 2005/04/27 04:56:30 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <isc/memcluster.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* Forward. */ + +static void lcl_close(struct irs_acc *); +static struct __res_state * lcl_res_get(struct irs_acc *); +static void lcl_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_acc * +irs_lcl_acc(const char *options) { + struct irs_acc *acc; + struct lcl_p *lcl; + + UNUSED(options); + + if (!(acc = memget(sizeof *acc))) { + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + if (!(lcl = memget(sizeof *lcl))) { + errno = ENOMEM; + free(acc); + return (NULL); + } + memset(lcl, 0x5e, sizeof *lcl); + lcl->res = NULL; + lcl->free_res = NULL; + acc->private = lcl; +#ifdef WANT_IRS_GR + acc->gr_map = irs_lcl_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_lcl_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_lcl_sv; + acc->pr_map = irs_lcl_pr; + acc->ho_map = irs_lcl_ho; + acc->nw_map = irs_lcl_nw; + acc->ng_map = irs_lcl_ng; + acc->res_get = lcl_res_get; + acc->res_set = lcl_res_set; + acc->close = lcl_close; + return (acc); +} + +/* Methods */ +static struct __res_state * +lcl_res_get(struct irs_acc *this) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + lcl_res_set(this, res, free); + } + + if ((lcl->res->options & RES_INIT) == 0U && + res_ninit(lcl->res) < 0) + return (NULL); + + return (lcl->res); +} + +static void +lcl_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl->res && lcl->free_res) { + res_nclose(lcl->res); + (*lcl->free_res)(lcl->res); + } + + lcl->res = res; + lcl->free_res = free_res; +} + +static void +lcl_close(struct irs_acc *this) { + struct lcl_p *lcl = (struct lcl_p *)this->private; + + if (lcl) { + if (lcl->free_res) + (*lcl->free_res)(lcl->res); + memput(lcl, sizeof *lcl); + } + memput(this, sizeof *this); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/lcl_ho.c b/usr/src/lib/libresolv2_joy/common/irs/lcl_ho.c new file mode 100644 index 0000000000..17c9a5e725 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/lcl_ho.c @@ -0,0 +1,578 @@ +/* + * 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. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* from gethostnamadr.c 8.1 (Berkeley) 6/4/93 */ +/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_ho.c,v 1.5 2006/03/09 23:57:56 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* Imports. */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "dns_p.h" +#include "lcl_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* Definitions. */ + +#define MAXALIASES 35 +#define MAXADDRS 35 +#define Max(a,b) ((a) > (b) ? (a) : (b)) + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +struct pvt { + FILE * fp; + struct hostent host; + char * h_addr_ptrs[MAXADDRS + 1]; + char * host_aliases[MAXALIASES]; + char hostbuf[8*1024]; + u_char host_addr[16]; /*%< IPv4 or IPv6 */ + struct __res_state *res; + void (*free_res)(void *); +}; + +typedef union { + int32_t al; + char ac; +} align; + +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 }; + +/* Forward. */ + +static void ho_close(struct irs_ho *this); +static struct hostent * ho_byname(struct irs_ho *this, const char *name); +static struct hostent * ho_byname2(struct irs_ho *this, const char *name, + int af); +static struct hostent * ho_byaddr(struct irs_ho *this, const void *addr, + int len, int af); +static struct hostent * ho_next(struct irs_ho *this); +static void ho_rewind(struct irs_ho *this); +static void ho_minimize(struct irs_ho *this); +static struct __res_state * ho_res_get(struct irs_ho *this); +static void ho_res_set(struct irs_ho *this, + struct __res_state *res, + void (*free_res)(void *)); +static struct addrinfo * ho_addrinfo(struct irs_ho *this, const char *name, + const struct addrinfo *pai); + +static size_t ns_namelen(const char *); +static int init(struct irs_ho *this); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public. */ + +struct irs_ho * +irs_lcl_ho(struct irs_acc *this) { + struct irs_ho *ho; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(ho = memget(sizeof *ho))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(ho, 0x5e, sizeof *ho); + ho->private = pvt; + ho->close = ho_close; + ho->byname = ho_byname; + ho->byname2 = ho_byname2; + ho->byaddr = ho_byaddr; + ho->next = ho_next; + ho->rewind = ho_rewind; + ho->minimize = ho_minimize; + ho->res_get = ho_res_get; + ho->res_set = ho_res_set; + ho->addrinfo = ho_addrinfo; + return (ho); +} + +/* Methods. */ + +static void +ho_close(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + ho_minimize(this); + if (pvt->fp) + (void) fclose(pvt->fp); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct hostent * +ho_byname(struct irs_ho *this, const char *name) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + + if (init(this) == -1) + return (NULL); + + if (pvt->res->options & RES_USE_INET6) { + hp = ho_byname2(this, name, AF_INET6); + if (hp) + return (hp); + } + return (ho_byname2(this, name, AF_INET)); +} + +static struct hostent * +ho_byname2(struct irs_ho *this, const char *name, int af) { + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + char **hap; + size_t n; + + if (init(this) == -1) + return (NULL); + + ho_rewind(this); + n = ns_namelen(name); + while ((hp = ho_next(this)) != NULL) { + size_t nn; + + if (hp->h_addrtype != af) + continue; + nn = ns_namelen(hp->h_name); + if (strncasecmp(hp->h_name, name, Max(n, nn)) == 0) + goto found; + for (hap = hp->h_aliases; *hap; hap++) { + nn = ns_namelen(*hap); + if (strncasecmp(*hap, name, Max(n, nn)) == 0) + goto found; + } + } + found: + if (!hp) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (hp); +} + +static struct hostent * +ho_byaddr(struct irs_ho *this, const void *addr, int len, int af) { + struct pvt *pvt = (struct pvt *)this->private; + const u_char *uaddr = addr; + struct hostent *hp; + int size; + + if (init(this) == -1) + return (NULL); + + if (af == AF_INET6 && len == IN6ADDRSZ && + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + addr = (const u_char *)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; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + if (size > len) { + errno = EINVAL; + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + + /* + * Do the search. + */ + ho_rewind(this); + while ((hp = ho_next(this)) != NULL) { + char **hap; + + for (hap = hp->h_addr_list; *hap; hap++) { + const u_char *taddr = (const u_char *)*hap; + int taf = hp->h_addrtype; + int tlen = hp->h_length; + + if (taf == AF_INET6 && tlen == IN6ADDRSZ && + (!memcmp(taddr, mapped, sizeof mapped) || + !memcmp(taddr, tunnelled, sizeof tunnelled))) { + /* Unmap. */ + taddr += sizeof mapped; + taf = AF_INET; + tlen = INADDRSZ; + } + if (taf == af && tlen == len && + !memcmp(taddr, uaddr, tlen)) + goto found; + } + } + found: + if (!hp) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + return (NULL); + } + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (hp); +} + +static struct hostent * +ho_next(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *cp, **q, *p; + char *bufp, *ndbuf, *dbuf = NULL; + int c, af, len, bufsiz, offset; + + if (init(this) == -1) + return (NULL); + + if (!pvt->fp) + ho_rewind(this); + if (!pvt->fp) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + bufp = pvt->hostbuf; + bufsiz = sizeof pvt->hostbuf; + offset = 0; + again: + if (!(p = fgets(bufp + offset, bufsiz - offset, pvt->fp))) { + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + if (dbuf) + free(dbuf); + return (NULL); + } + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + if ((cp = strpbrk(p, "#\n")) != NULL) + *cp = '\0'; + if (!(cp = strpbrk(p, " \t"))) + goto again; + *cp++ = '\0'; + if (inet_pton(AF_INET6, p, pvt->host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_aton(p, (struct in_addr *)pvt->host_addr) > 0) { + if (pvt->res->options & RES_USE_INET6) { + map_v4v6_address((char*)pvt->host_addr, + (char*)pvt->host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + goto again; + } + pvt->h_addr_ptrs[0] = (char *)pvt->host_addr; + pvt->h_addr_ptrs[1] = NULL; + pvt->host.h_addr_list = pvt->h_addr_ptrs; + pvt->host.h_length = len; + pvt->host.h_addrtype = af; + while (*cp == ' ' || *cp == '\t') + cp++; + pvt->host.h_name = cp; + q = pvt->host.h_aliases = pvt->host_aliases; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->host_aliases[MAXALIASES - 1]) + *q++ = cp; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; + } + *q = NULL; + if (dbuf) + free(dbuf); + RES_SET_H_ERRNO(pvt->res, NETDB_SUCCESS); + return (&pvt->host); +} + +static void +ho_rewind(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_HOSTS, "r"))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static void +ho_minimize(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } + if (pvt->res) + res_nclose(pvt->res); +} + +static struct __res_state * +ho_res_get(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + ho_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +ho_res_set(struct irs_ho *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +struct lcl_res_target { + struct lcl_res_target *next; + int family; +}; + +/* XXX */ +extern struct addrinfo *hostent2addrinfo __P((struct hostent *, + const struct addrinfo *pai)); + +static struct addrinfo * +ho_addrinfo(struct irs_ho *this, const char *name, const struct addrinfo *pai) +{ + struct pvt *pvt = (struct pvt *)this->private; + struct hostent *hp; + struct lcl_res_target q, q2, *p; + struct addrinfo sentinel, *cur; + + memset(&q, 0, sizeof(q2)); + memset(&q2, 0, sizeof(q2)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + switch(pai->ai_family) { + case AF_UNSPEC: /*%< INET6 then INET4 */ + q.family = AF_INET6; + q.next = &q2; + q2.family = AF_INET; + break; + case AF_INET6: + q.family = AF_INET6; + break; + case AF_INET: + q.family = AF_INET; + break; + default: + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); /*%< ??? */ + return(NULL); + } + + for (p = &q; p; p = p->next) { + struct addrinfo *ai; + + hp = (*this->byname2)(this, name, p->family); + if (hp == NULL) { + /* byname2 should've set an appropriate error */ + continue; + } + if ((hp->h_name == NULL) || (hp->h_name[0] == 0) || + (hp->h_addr_list[0] == NULL)) { + RES_SET_H_ERRNO(pvt->res, NO_RECOVERY); + continue; + } + + ai = hostent2addrinfo(hp, pai); + if (ai) { + cur->ai_next = ai; + while (cur->ai_next) + cur = cur->ai_next; + } + } + + if (sentinel.ai_next == NULL) + RES_SET_H_ERRNO(pvt->res, HOST_NOT_FOUND); + + return(sentinel.ai_next); +} + +/* Private. */ + +static size_t +ns_namelen(const char *s) { + int i; + + for (i = strlen(s); i > 0 && s[i-1] == '.'; i--) + (void)NULL; + return ((size_t) i); +} + +static int +init(struct irs_ho *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !ho_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0U) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/lcl_ng.c b/usr/src/lib/libresolv2_joy/common/irs/lcl_ng.c new file mode 100644 index 0000000000..319725ce70 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/lcl_ng.c @@ -0,0 +1,446 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: lcl_ng.c,v 1.3 2005/04/27 04:56:31 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +/* Definitions */ + +#define NG_HOST 0 /*%< Host name */ +#define NG_USER 1 /*%< User name */ +#define NG_DOM 2 /*%< and Domain name */ +#define LINSIZ 1024 /*%< Length of netgroup file line */ +/* + * XXX Warning XXX + * This code is a hack-and-slash special. It realy needs to be + * rewritten with things like strdup, and realloc in mind. + * More reasonable data structures would not be a bad thing. + */ + +/*% + * Static Variables and functions used by setnetgrent(), getnetgrent() and + * endnetgrent(). + * + * There are two linked lists: + * \li linelist is just used by setnetgrent() to parse the net group file via. + * parse_netgrp() + * \li netgrp is the list of entries for the current netgroup + */ +struct linelist { + struct linelist *l_next; /*%< Chain ptr. */ + int l_parsed; /*%< Flag for cycles */ + char * l_groupname; /*%< Name of netgroup */ + char * l_line; /*%< Netgroup entrie(s) to be parsed */ +}; + +struct ng_old_struct { + struct ng_old_struct *ng_next; /*%< Chain ptr */ + char * ng_str[3]; /*%< Field pointers, see below */ +}; + +struct pvt { + FILE *fp; + struct linelist *linehead; + struct ng_old_struct *nextgrp; + struct { + struct ng_old_struct *gr; + char *grname; + } grouphead; +}; + +/* Forward */ + +static void ng_rewind(struct irs_ng *, const char*); +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, const char *, + const char *, const char *, + const char *); +static void ng_minimize(struct irs_ng *); + +static int parse_netgrp(struct irs_ng *, const char*); +static struct linelist *read_for_group(struct irs_ng *, const char *); +static void freelists(struct irs_ng *); + +/* Public */ + +struct irs_ng * +irs_lcl_ng(struct irs_acc *this) { + struct irs_ng *ng; + struct pvt *pvt; + + UNUSED(this); + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + if (!(pvt = memget(sizeof *pvt))) { + memput(ng, sizeof *ng); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + ng->private = pvt; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods */ + +static void +ng_close(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) + fclose(pvt->fp); + freelists(this); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +/*% + * Parse the netgroup file looking for the netgroup and build the list + * of netgrp structures. Let parse_netgrp() and read_for_group() do + * most of the work. + */ +static void +ng_rewind(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL && fseek(pvt->fp, SEEK_CUR, 0L) == -1) { + fclose(pvt->fp); + pvt->fp = NULL; + } + + if (pvt->fp == NULL || pvt->grouphead.gr == NULL || + strcmp(group, pvt->grouphead.grname)) { + freelists(this); + if (pvt->fp != NULL) + fclose(pvt->fp); + pvt->fp = fopen(_PATH_NETGROUP, "r"); + if (pvt->fp != NULL) { + if (parse_netgrp(this, group)) + freelists(this); + if (!(pvt->grouphead.grname = strdup(group))) + freelists(this); + fclose(pvt->fp); + pvt->fp = NULL; + } + } + pvt->nextgrp = pvt->grouphead.gr; +} + +/*% + * Get the next netgroup off the list. + */ +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->nextgrp) { + *host = pvt->nextgrp->ng_str[NG_HOST]; + *user = pvt->nextgrp->ng_str[NG_USER]; + *domain = pvt->nextgrp->ng_str[NG_DOM]; + pvt->nextgrp = pvt->nextgrp->ng_next; + return (1); + } + return (0); +} + +/*% + * Search for a match in a netgroup. + */ +static int +ng_test(struct irs_ng *this, const char *name, + const char *host, const char *user, const char *domain) +{ + const char *ng_host, *ng_user, *ng_domain; + + ng_rewind(this, name); + while (ng_next(this, &ng_host, &ng_user, &ng_domain)) + if ((host == NULL || ng_host == NULL || + !strcmp(host, ng_host)) && + (user == NULL || ng_user == NULL || + !strcmp(user, ng_user)) && + (domain == NULL || ng_domain == NULL || + !strcmp(domain, ng_domain))) { + freelists(this); + return (1); + } + freelists(this); + return (0); +} + +static void +ng_minimize(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/* Private */ + +/*% + * endnetgrent() - cleanup + */ +static void +freelists(struct irs_ng *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct linelist *lp, *olp; + struct ng_old_struct *gp, *ogp; + + lp = pvt->linehead; + while (lp) { + olp = lp; + lp = lp->l_next; + free(olp->l_groupname); + free(olp->l_line); + free((char *)olp); + } + pvt->linehead = NULL; + if (pvt->grouphead.grname) { + free(pvt->grouphead.grname); + pvt->grouphead.grname = NULL; + } + gp = pvt->grouphead.gr; + while (gp) { + ogp = gp; + gp = gp->ng_next; + if (ogp->ng_str[NG_HOST]) + free(ogp->ng_str[NG_HOST]); + if (ogp->ng_str[NG_USER]) + free(ogp->ng_str[NG_USER]); + if (ogp->ng_str[NG_DOM]) + free(ogp->ng_str[NG_DOM]); + free((char *)ogp); + } + pvt->grouphead.gr = NULL; +} + +/*% + * Parse the netgroup file setting up the linked lists. + */ +static int +parse_netgrp(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char *spos, *epos; + int len, strpos; + char *pos, *gpos; + struct ng_old_struct *grp; + struct linelist *lp = pvt->linehead; + + /* + * First, see if the line has already been read in. + */ + while (lp) { + if (!strcmp(group, lp->l_groupname)) + break; + lp = lp->l_next; + } + if (lp == NULL && + (lp = read_for_group(this, group)) == NULL) + return (1); + if (lp->l_parsed) { + /*fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);*/ + return (1); + } else + lp->l_parsed = 1; + pos = lp->l_line; + while (*pos != '\0') { + if (*pos == '(') { + if (!(grp = malloc(sizeof (struct ng_old_struct)))) { + freelists(this); + errno = ENOMEM; + return (1); + } + memset(grp, 0, sizeof (struct ng_old_struct)); + grp->ng_next = pvt->grouphead.gr; + pvt->grouphead.gr = grp; + pos++; + gpos = strsep(&pos, ")"); + for (strpos = 0; strpos < 3; strpos++) { + if ((spos = strsep(&gpos, ","))) { + while (*spos == ' ' || *spos == '\t') + spos++; + if ((epos = strpbrk(spos, " \t"))) { + *epos = '\0'; + len = epos - spos; + } else + len = strlen(spos); + if (len > 0) { + if(!(grp->ng_str[strpos] + = (char *) + malloc(len + 1))) { + freelists(this); + return (1); + } + memcpy(grp->ng_str[strpos], + spos, + len + 1); + } + } else + goto errout; + } + } else { + spos = strsep(&pos, ", \t"); + if (spos != NULL && parse_netgrp(this, spos)) { + freelists(this); + return (1); + } + } + if (pos == NULL) + break; + while (*pos == ' ' || *pos == ',' || *pos == '\t') + pos++; + } + return (0); + errout: + /*fprintf(stderr, "Bad netgroup %s at ..%s\n", lp->l_groupname, + spos);*/ + return (1); +} + +/*% + * Read the netgroup file and save lines until the line for the netgroup + * is found. Return 1 if eof is encountered. + */ +static struct linelist * +read_for_group(struct irs_ng *this, const char *group) { + struct pvt *pvt = (struct pvt *)this->private; + char *pos, *spos, *linep = NULL, *olinep; + int len, olen, cont; + struct linelist *lp; + char line[LINSIZ + 1]; + + while (fgets(line, LINSIZ, pvt->fp) != NULL) { + pos = line; + if (*pos == '#') + continue; + while (*pos == ' ' || *pos == '\t') + pos++; + spos = pos; + while (*pos != ' ' && *pos != '\t' && *pos != '\n' && + *pos != '\0') + pos++; + len = pos - spos; + while (*pos == ' ' || *pos == '\t') + pos++; + if (*pos != '\n' && *pos != '\0') { + if (!(lp = malloc(sizeof (*lp)))) { + freelists(this); + return (NULL); + } + lp->l_parsed = 0; + if (!(lp->l_groupname = malloc(len + 1))) { + free(lp); + freelists(this); + return (NULL); + } + memcpy(lp->l_groupname, spos, len); + *(lp->l_groupname + len) = '\0'; + len = strlen(pos); + olen = 0; + olinep = NULL; + + /* + * Loop around handling line continuations. + */ + do { + if (*(pos + len - 1) == '\n') + len--; + if (*(pos + len - 1) == '\\') { + len--; + cont = 1; + } else + cont = 0; + if (len > 0) { + if (!(linep = malloc(olen + len + 1))){ + if (olen > 0) + free(olinep); + free(lp->l_groupname); + free(lp); + freelists(this); + errno = ENOMEM; + return (NULL); + } + if (olen > 0) { + memcpy(linep, olinep, olen); + free(olinep); + } + memcpy(linep + olen, pos, len); + olen += len; + *(linep + olen) = '\0'; + olinep = linep; + } + if (cont) { + if (fgets(line, LINSIZ, pvt->fp)) { + pos = line; + len = strlen(pos); + } else + cont = 0; + } + } while (cont); + lp->l_line = linep; + lp->l_next = pvt->linehead; + pvt->linehead = lp; + + /* + * If this is the one we wanted, we are done. + */ + if (!strcmp(lp->l_groupname, group)) + return (lp); + } + } + return (NULL); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/lcl_nw.c b/usr/src/lib/libresolv2_joy/common/irs/lcl_nw.c new file mode 100644 index 0000000000..2e5cd55a6c --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/lcl_nw.c @@ -0,0 +1,373 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * 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. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_nw.c,v 1.4 2005/04/27 04:56:31 sra Exp $"; +/* from getgrent.c 8.2 (Berkeley) 3/21/94"; */ +/* from BSDI Id: getgrent.c,v 2.8 1996/05/28 18:15:14 bostic Exp $ */ +#endif /* LIBC_SCCS and not lint */ + +/* Imports */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <fcntl.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include <isc/misc.h> +#include "irs_p.h" +#include "lcl_p.h" + +#define MAXALIASES 35 +#define MAXADDRSIZE 4 + +struct pvt { + FILE * fp; + char line[BUFSIZ+1]; + struct nwent net; + char * aliases[MAXALIASES]; + char addr[MAXADDRSIZE]; + struct __res_state * res; + void (*free_res)(void *); +}; + +/* Forward */ + +static void nw_close(struct irs_nw *); +static struct nwent * nw_byname(struct irs_nw *, const char *, int); +static struct nwent * nw_byaddr(struct irs_nw *, void *, int, int); +static struct nwent * nw_next(struct irs_nw *); +static void nw_rewind(struct irs_nw *); +static void nw_minimize(struct irs_nw *); +static struct __res_state * nw_res_get(struct irs_nw *this); +static void nw_res_set(struct irs_nw *this, + struct __res_state *res, + void (*free_res)(void *)); + +static int init(struct irs_nw *this); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_nw * +irs_lcl_nw(struct irs_acc *this) { + struct irs_nw *nw; + struct pvt *pvt; + + UNUSED(this); + + if (!(pvt = memget(sizeof *pvt))) { + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + if (!(nw = memget(sizeof *nw))) { + memput(pvt, sizeof *pvt); + errno = ENOMEM; + return (NULL); + } + memset(nw, 0x5e, sizeof *nw); + nw->private = pvt; + nw->close = nw_close; + nw->byname = nw_byname; + nw->byaddr = nw_byaddr; + nw->next = nw_next; + nw->rewind = nw_rewind; + nw->minimize = nw_minimize; + nw->res_get = nw_res_get; + nw->res_set = nw_res_set; + return (nw); +} + +/* Methods */ + +static void +nw_close(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + nw_minimize(this); + if (pvt->res && pvt->free_res) + (*pvt->free_res)(pvt->res); + if (pvt->fp) + (void)fclose(pvt->fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct nwent * +nw_byaddr(struct irs_nw *this, void *net, int length, int type) { + struct nwent *p; + + if (init(this) == -1) + return(NULL); + + nw_rewind(this); + while ((p = nw_next(this)) != NULL) + if (p->n_addrtype == type && p->n_length == length) + if (bitncmp(p->n_addr, net, length) == 0) + break; + return (p); +} + +static struct nwent * +nw_byname(struct irs_nw *this, const char *name, int type) { + struct nwent *p; + char **ap; + + if (init(this) == -1) + return(NULL); + + nw_rewind(this); + while ((p = nw_next(this)) != NULL) { + if (ns_samename(p->n_name, name) == 1 && + p->n_addrtype == type) + break; + for (ap = p->n_aliases; *ap; ap++) + if ((ns_samename(*ap, name) == 1) && + (p->n_addrtype == type)) + goto found; + } + found: + return (p); +} + +static void +nw_rewind(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_NETWORKS, "r"))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct nwent * +nw_next(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + struct nwent *ret = NULL; + char *p, *cp, **q; + char *bufp, *ndbuf, *dbuf = NULL; + int c, bufsiz, offset = 0; + + if (init(this) == -1) + return(NULL); + + if (pvt->fp == NULL) + nw_rewind(this); + if (pvt->fp == NULL) { + RES_SET_H_ERRNO(pvt->res, NETDB_INTERNAL); + return (NULL); + } + bufp = pvt->line; + bufsiz = sizeof(pvt->line); + + again: + p = fgets(bufp + offset, bufsiz - offset, pvt->fp); + if (p == NULL) + goto cleanup; + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + + cp = strpbrk(p, "#\n"); + if (cp != NULL) + *cp = '\0'; + pvt->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'; + pvt->net.n_length = inet_net_pton(AF_INET, cp, pvt->addr, + sizeof pvt->addr); + if (pvt->net.n_length < 0) + goto again; + pvt->net.n_addrtype = AF_INET; + pvt->net.n_addr = pvt->addr; + q = pvt->net.n_aliases = pvt->aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + ret = &pvt->net; + + cleanup: + if (dbuf) + free(dbuf); + + return (ret); +} + +static void +nw_minimize(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res) + res_nclose(pvt->res); + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct __res_state * +nw_res_get(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (!res) { + errno = ENOMEM; + return (NULL); + } + memset(res, 0, sizeof *res); + nw_res_set(this, res, free); + } + + return (pvt->res); +} + +static void +nw_res_set(struct irs_nw *this, struct __res_state *res, + void (*free_res)(void *)) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->res && pvt->free_res) { + res_nclose(pvt->res); + (*pvt->free_res)(pvt->res); + } + + pvt->res = res; + pvt->free_res = free_res; +} + +static int +init(struct irs_nw *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (!pvt->res && !nw_res_get(this)) + return (-1); + if (((pvt->res->options & RES_INIT) == 0U) && + res_ninit(pvt->res) == -1) + return (-1); + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/lcl_p.h b/usr/src/lib/libresolv2_joy/common/irs/lcl_p.h new file mode 100644 index 0000000000..e3f4f009cb --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/lcl_p.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: lcl_p.h,v 1.3 2005/04/27 04:56:31 sra Exp $ + */ + +/*! \file + * \brief + * lcl_p.h - private include file for the local accessor functions. + */ + +#ifndef _LCL_P_H_INCLUDED +#define _LCL_P_H_INCLUDED + +/*% + * Object state. + */ +struct lcl_p { + struct __res_state * res; + void (*free_res) __P((void *)); +}; + +/* + * Externs. + */ + +extern struct irs_acc * irs_lcl_acc __P((const char *)); +extern struct irs_gr * irs_lcl_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_lcl_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_lcl_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_lcl_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_lcl_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_lcl_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_lcl_ng __P((struct irs_acc *)); + +#endif /*_LCL_P_H_INCLUDED*/ diff --git a/usr/src/lib/libresolv2_joy/common/irs/lcl_pr.c b/usr/src/lib/libresolv2_joy/common/irs/lcl_pr.c new file mode 100644 index 0000000000..e1538530eb --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/lcl_pr.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * 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. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_pr.c,v 1.4 2006/03/09 23:57:56 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +#ifndef _PATH_PROTOCOLS +#define _PATH_PROTOCOLS "/etc/protocols" +#endif +#define MAXALIASES 35 + +/* Types */ + +struct pvt { + FILE * fp; + char line[BUFSIZ+1]; + char * dbuf; + struct protoent proto; + char * proto_aliases[MAXALIASES]; +}; + +/* Forward */ + +static void pr_close(struct irs_pr *); +static struct protoent * pr_next(struct irs_pr *); +static struct protoent * pr_byname(struct irs_pr *, const char *); +static struct protoent * pr_bynumber(struct irs_pr *, int); +static void pr_rewind(struct irs_pr *); +static void pr_minimize(struct irs_pr *); + +/* Portability. */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_pr * +irs_lcl_pr(struct irs_acc *this) { + struct irs_pr *pr; + struct pvt *pvt; + + if (!(pr = memget(sizeof *pr))) { + errno = ENOMEM; + return (NULL); + } + if (!(pvt = memget(sizeof *pvt))) { + memput(pr, sizeof *this); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + pr->private = pvt; + pr->close = pr_close; + pr->byname = pr_byname; + pr->bynumber = pr_bynumber; + pr->next = pr_next; + pr->rewind = pr_rewind; + pr->minimize = pr_minimize; + pr->res_get = NULL; + pr->res_set = NULL; + return (pr); +} + +/* Methods */ + +static void +pr_close(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) + (void) fclose(pvt->fp); + if (pvt->dbuf) + free(pvt->dbuf); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct protoent * +pr_byname(struct irs_pr *this, const char *name) { + + struct protoent *p; + char **cp; + + pr_rewind(this); + while ((p = pr_next(this))) { + if (!strcmp(p->p_name, name)) + goto found; + for (cp = p->p_aliases; *cp; cp++) + if (!strcmp(*cp, name)) + goto found; + } + found: + return (p); +} + +static struct protoent * +pr_bynumber(struct irs_pr *this, int proto) { + struct protoent *p; + + pr_rewind(this); + while ((p = pr_next(this))) + if (p->p_proto == proto) + break; + return (p); +} + +static void +pr_rewind(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp) { + if (fseek(pvt->fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->fp); + } + if (!(pvt->fp = fopen(_PATH_PROTOCOLS, "r" ))) + return; + if (fcntl(fileno(pvt->fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +static struct protoent * +pr_next(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + char *p, *cp, **q; + char *bufp, *ndbuf, *dbuf = NULL; + int c, bufsiz, offset; + + if (!pvt->fp) + pr_rewind(this); + if (!pvt->fp) + return (NULL); + if (pvt->dbuf) { + free(pvt->dbuf); + pvt->dbuf = NULL; + } + bufp = pvt->line; + bufsiz = BUFSIZ; + offset = 0; + again: + if ((p = fgets(bufp + offset, bufsiz - offset, pvt->fp)) == NULL) { + if (dbuf) + free(dbuf); + return (NULL); + } + if (!strchr(p, '\n') && !feof(pvt->fp)) { +#define GROWBUF 1024 + /* allocate space for longer line */ + if (dbuf == NULL) { + if ((ndbuf = malloc(bufsiz + GROWBUF)) != NULL) + strcpy(ndbuf, bufp); + } else + ndbuf = realloc(dbuf, bufsiz + GROWBUF); + if (ndbuf) { + dbuf = ndbuf; + bufp = dbuf; + bufsiz += GROWBUF; + offset = strlen(dbuf); + } else { + /* allocation failed; skip this long line */ + while ((c = getc(pvt->fp)) != EOF) + if (c == '\n') + break; + if (c != EOF) + ungetc(c, pvt->fp); + } + goto again; + } + + p -= offset; + offset = 0; + + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp != NULL) + *cp = '\0'; + pvt->proto.p_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'; + pvt->proto.p_proto = atoi(cp); + q = pvt->proto.p_aliases = pvt->proto_aliases; + if (p != NULL) { + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &pvt->proto_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + } + *q = NULL; + pvt->dbuf = dbuf; + return (&pvt->proto); +} + +static void +pr_minimize(struct irs_pr *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->fp != NULL) { + (void)fclose(pvt->fp); + pvt->fp = NULL; + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/lcl_sv.c b/usr/src/lib/libresolv2_joy/common/irs/lcl_sv.c new file mode 100644 index 0000000000..ad6526430c --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/lcl_sv.c @@ -0,0 +1,432 @@ +/* + * Copyright (c) 1989, 1993, 1995 + * 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. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: lcl_sv.c,v 1.4 2005/04/27 04:56:31 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/* extern */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#ifdef IRS_LCL_SV_DB +#include <db.h> +#endif +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "lcl_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Types */ + +struct pvt { +#ifdef IRS_LCL_SV_DB + DB * dbh; + int dbf; +#endif + struct lcl_sv sv; +}; + +/* Forward */ + +static void sv_close(struct irs_sv*); +static struct servent * sv_next(struct irs_sv *); +static struct servent * sv_byname(struct irs_sv *, const char *, + const char *); +static struct servent * sv_byport(struct irs_sv *, int, const char *); +static void sv_rewind(struct irs_sv *); +static void sv_minimize(struct irs_sv *); +/*global*/ struct servent * irs_lclsv_fnxt(struct lcl_sv *); +#ifdef IRS_LCL_SV_DB +static struct servent * sv_db_rec(struct lcl_sv *, DBT *, DBT *); +#endif + +/* Portability */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +#endif + +/* Public */ + +struct irs_sv * +irs_lcl_sv(struct irs_acc *this) { + struct irs_sv *sv; + struct pvt *pvt; + + UNUSED(this); + + if ((sv = memget(sizeof *sv)) == NULL) { + errno = ENOMEM; + return (NULL); + } + memset(sv, 0x5e, sizeof *sv); + if ((pvt = memget(sizeof *pvt)) == NULL) { + memput(sv, sizeof *sv); + errno = ENOMEM; + return (NULL); + } + memset(pvt, 0, sizeof *pvt); + sv->private = pvt; + sv->close = sv_close; + sv->next = sv_next; + sv->byname = sv_byname; + sv->byport = sv_byport; + sv->rewind = sv_rewind; + sv->minimize = sv_minimize; + sv->res_get = NULL; + sv->res_set = NULL; +#ifdef IRS_LCL_SV_DB + pvt->dbf = R_FIRST; +#endif + return (sv); +} + +/* Methods */ + +static void +sv_close(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) + (*pvt->dbh->close)(pvt->dbh); +#endif + if (pvt->sv.fp) + fclose(pvt->sv.fp); + memput(pvt, sizeof *pvt); + memput(this, sizeof *this); +} + +static struct servent * +sv_byname(struct irs_sv *this, const char *name, const char *proto) { +#ifdef IRS_LCL_SV_DB + struct pvt *pvt = (struct pvt *)this->private; +#endif + struct servent *p; + char **cp; + + sv_rewind(this); +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + + /* Note that (sizeof "/") == 2. */ + if ((strlen(name) + sizeof "/" + proto ? strlen(proto) : 0) + > sizeof pvt->sv.line) + goto try_local; + key.data = pvt->sv.line; + key.size = SPRINTF((pvt->sv.line, "%s/%s", name, + proto ? proto : "")) + 1; + if (proto != NULL) { + if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0) + return (NULL); + } else if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR) + != 0) + return (NULL); + return (sv_db_rec(&pvt->sv, &key, &data)); + } + try_local: +#endif + + while ((p = sv_next(this))) { + if (strcmp(name, p->s_name) == 0) + goto gotname; + for (cp = p->s_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + continue; + gotname: + if (proto == NULL || strcmp(p->s_proto, proto) == 0) + break; + } + return (p); +} + +static struct servent * +sv_byport(struct irs_sv *this, int port, const char *proto) { +#ifdef IRS_LCL_SV_DB + struct pvt *pvt = (struct pvt *)this->private; +#endif + struct servent *p; + + sv_rewind(this); +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + u_short *ports; + + ports = (u_short *)pvt->sv.line; + ports[0] = 0; + ports[1] = port; + key.data = ports; + key.size = sizeof(u_short) * 2; + if (proto && *proto) { + strncpy((char *)ports + key.size, proto, + BUFSIZ - key.size); + key.size += strlen((char *)ports + key.size) + 1; + if ((*pvt->dbh->get)(pvt->dbh, &key, &data, 0) != 0) + return (NULL); + } else { + if ((*pvt->dbh->seq)(pvt->dbh, &key, &data, R_CURSOR) + != 0) + return (NULL); + } + return (sv_db_rec(&pvt->sv, &key, &data)); + } +#endif + while ((p = sv_next(this))) { + if (p->s_port != port) + continue; + if (proto == NULL || strcmp(p->s_proto, proto) == 0) + break; + } + return (p); +} + +static void +sv_rewind(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + + if (pvt->sv.fp) { + if (fseek(pvt->sv.fp, 0L, SEEK_SET) == 0) + return; + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +#ifdef IRS_LCL_SV_DB + pvt->dbf = R_FIRST; + if (pvt->dbh != NULL) + return; + pvt->dbh = dbopen(_PATH_SERVICES_DB, O_RDONLY,O_RDONLY,DB_BTREE, NULL); + if (pvt->dbh != NULL) { + if (fcntl((*pvt->dbh->fd)(pvt->dbh), F_SETFD, 1) < 0) { + (*pvt->dbh->close)(pvt->dbh); + pvt->dbh = NULL; + } + return; + } +#endif + if ((pvt->sv.fp = fopen(_PATH_SERVICES, "r")) == NULL) + return; + if (fcntl(fileno(pvt->sv.fp), F_SETFD, 1) < 0) { + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +} + +static struct servent * +sv_next(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh == NULL && pvt->sv.fp == NULL) +#else + if (pvt->sv.fp == NULL) +#endif + sv_rewind(this); + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + DBT key, data; + + while ((*pvt->dbh->seq)(pvt->dbh, &key, &data, pvt->dbf) == 0){ + pvt->dbf = R_NEXT; + if (((char *)key.data)[0]) + continue; + return (sv_db_rec(&pvt->sv, &key, &data)); + } + } +#endif + + if (pvt->sv.fp == NULL) + return (NULL); + return (irs_lclsv_fnxt(&pvt->sv)); +} + +static void +sv_minimize(struct irs_sv *this) { + struct pvt *pvt = (struct pvt *)this->private; + +#ifdef IRS_LCL_SV_DB + if (pvt->dbh != NULL) { + (*pvt->dbh->close)(pvt->dbh); + pvt->dbh = NULL; + } +#endif + if (pvt->sv.fp != NULL) { + (void)fclose(pvt->sv.fp); + pvt->sv.fp = NULL; + } +} + +/* Quasipublic. */ + +struct servent * +irs_lclsv_fnxt(struct lcl_sv *sv) { + char *p, *cp, **q; + + again: + if ((p = fgets(sv->line, BUFSIZ, sv->fp)) == NULL) + return (NULL); + if (*p == '#') + goto again; + sv->serv.s_name = p; + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + if (*p == '\0' || *p == '#' || *p == '\n') + goto again; + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + if (*p == '\0' || *p == '#' || *p == '\n') + goto again; + sv->serv.s_port = htons((u_short)strtol(p, &cp, 10)); + if (cp == p || (*cp != '/' && *cp != ',')) + goto again; + p = cp + 1; + sv->serv.s_proto = p; + + q = sv->serv.s_aliases = sv->serv_aliases; + + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + + while (*p == ' ' || *p == '\t') { + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + ++p; + if (*p == '\0' || *p == '#' || *p == '\n') + break; + if (q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) + *q++ = p; + while (*p && *p != '\n' && *p != ' ' && *p != '\t' && *p != '#') + ++p; + } + + *p = '\0'; + *q = NULL; + return (&sv->serv); +} + +/* Private. */ + +#ifdef IRS_LCL_SV_DB +static struct servent * +sv_db_rec(struct lcl_sv *sv, DBT *key, DBT *data) { + char *p, **q; + int n; + + p = data->data; + p[data->size - 1] = '\0'; /*%< should be, but we depend on it */ + if (((char *)key->data)[0] == '\0') { + if (key->size < sizeof(u_short)*2 || data->size < 2) + return (NULL); + sv->serv.s_port = ((u_short *)key->data)[1]; + n = strlen(p) + 1; + if ((size_t)n > sizeof(sv->line)) { + n = sizeof(sv->line); + } + memcpy(sv->line, p, n); + sv->serv.s_name = sv->line; + if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL) + *(sv->serv.s_proto)++ = '\0'; + p += n; + data->size -= n; + } else { + if (data->size < sizeof(u_short) + 1) + return (NULL); + if (key->size > sizeof(sv->line)) + key->size = sizeof(sv->line); + ((char *)key->data)[key->size - 1] = '\0'; + memcpy(sv->line, key->data, key->size); + sv->serv.s_name = sv->line; + if ((sv->serv.s_proto = strchr(sv->line, '/')) != NULL) + *(sv->serv.s_proto)++ = '\0'; + sv->serv.s_port = *(u_short *)data->data; + p += sizeof(u_short); + data->size -= sizeof(u_short); + } + q = sv->serv.s_aliases = sv->serv_aliases; + while (data->size > 0 && q < &sv->serv_aliases[IRS_SV_MAXALIASES - 1]) { + + *q++ = p; + n = strlen(p) + 1; + data->size -= n; + p += n; + } + *q = NULL; + return (&sv->serv); +} +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/nis.c b/usr/src/lib/libresolv2_joy/common/irs/nis.c new file mode 100644 index 0000000000..ac1796543c --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/nis.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nis.c,v 1.3 2005/04/27 04:56:32 sra Exp $"; +#endif + +/* Imports */ + +#include "port_before.h" + +#ifdef WANT_IRS_NIS + +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include <sys/types.h> +#include <netinet/in.h> +#ifdef T_NULL +#undef T_NULL /* Silence re-definition warning of T_NULL. */ +#endif +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <isc/memcluster.h> +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "nis_p.h" + +/* Forward */ + +static void nis_close(struct irs_acc *); +static struct __res_state * nis_res_get(struct irs_acc *); +static void nis_res_set(struct irs_acc *, struct __res_state *, + void (*)(void *)); + +/* Public */ + +struct irs_acc * +irs_nis_acc(const char *options) { + struct nis_p *nis; + struct irs_acc *acc; + char *domain; + + UNUSED(options); + + if (yp_get_default_domain(&domain) != 0) + return (NULL); + if (!(nis = memget(sizeof *nis))) { + errno = ENOMEM; + return (NULL); + } + memset(nis, 0, sizeof *nis); + if (!(acc = memget(sizeof *acc))) { + memput(nis, sizeof *nis); + errno = ENOMEM; + return (NULL); + } + memset(acc, 0x5e, sizeof *acc); + acc->private = nis; + nis->domain = strdup(domain); +#ifdef WANT_IRS_GR + acc->gr_map = irs_nis_gr; +#else + acc->gr_map = NULL; +#endif +#ifdef WANT_IRS_PW + acc->pw_map = irs_nis_pw; +#else + acc->pw_map = NULL; +#endif + acc->sv_map = irs_nis_sv; + acc->pr_map = irs_nis_pr; + acc->ho_map = irs_nis_ho; + acc->nw_map = irs_nis_nw; + acc->ng_map = irs_nis_ng; + acc->res_get = nis_res_get; + acc->res_set = nis_res_set; + acc->close = nis_close; + return (acc); +} + +/* Methods */ + +static struct __res_state * +nis_res_get(struct irs_acc *this) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res == NULL) { + struct __res_state *res; + res = (struct __res_state *)malloc(sizeof *res); + if (res == NULL) + return (NULL); + memset(res, 0, sizeof *res); + nis_res_set(this, res, free); + } + + if ((nis->res->options & RES_INIT) == 0 && + res_ninit(nis->res) < 0) + return (NULL); + + return (nis->res); +} + +static void +nis_res_set(struct irs_acc *this, struct __res_state *res, + void (*free_res)(void *)) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res && nis->free_res) { + res_nclose(nis->res); + (*nis->free_res)(nis->res); + } + + nis->res = res; + nis->free_res = free_res; +} + +static void +nis_close(struct irs_acc *this) { + struct nis_p *nis = (struct nis_p *)this->private; + + if (nis->res && nis->free_res) + (*nis->free_res)(nis->res); + free(nis->domain); + memput(nis, sizeof *nis); + memput(this, sizeof *this); +} + +#endif /*WANT_IRS_NIS*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/nis_p.h b/usr/src/lib/libresolv2_joy/common/irs/nis_p.h new file mode 100644 index 0000000000..70e2948d67 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/nis_p.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: nis_p.h,v 1.3 2005/04/27 04:56:33 sra Exp $ + */ + +/*! \file + * \brief + * nis_p.h - private include file for the NIS functions. + */ + +/*% + * Object state. + */ +struct nis_p { + char * domain; + struct __res_state * res; + void (*free_res) __P((void *)); +}; + + +/* + * Methods. + */ + +extern struct irs_gr * irs_nis_gr __P((struct irs_acc *)); +extern struct irs_pw * irs_nis_pw __P((struct irs_acc *)); +extern struct irs_sv * irs_nis_sv __P((struct irs_acc *)); +extern struct irs_pr * irs_nis_pr __P((struct irs_acc *)); +extern struct irs_ho * irs_nis_ho __P((struct irs_acc *)); +extern struct irs_nw * irs_nis_nw __P((struct irs_acc *)); +extern struct irs_ng * irs_nis_ng __P((struct irs_acc *)); diff --git a/usr/src/lib/libresolv2_joy/common/irs/nul_ng.c b/usr/src/lib/libresolv2_joy/common/irs/nul_ng.c new file mode 100644 index 0000000000..504813bde1 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/nul_ng.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: nul_ng.c,v 1.3 2005/04/27 04:56:34 sra Exp $"; +#endif + +/*! \file + * \brief + * nul_ng.c - the netgroup accessor null map + */ + +#include "port_before.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <stdio.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <stdlib.h> +#include <errno.h> + +#include <irs.h> +#include <isc/memcluster.h> + +#include "port_after.h" + +#include "irs_p.h" +#include "hesiod.h" +#include "dns_p.h" + +/* Forward. */ + +static void ng_close(struct irs_ng *); +static int ng_next(struct irs_ng *, const char **, + const char **, const char **); +static int ng_test(struct irs_ng *, + const char *, const char *, + const char *, const char *); +static void ng_rewind(struct irs_ng *, const char *); +static void ng_minimize(struct irs_ng *); + +/* Public. */ + +struct irs_ng * +irs_nul_ng(struct irs_acc *this) { + struct irs_ng *ng; + + UNUSED(this); + + if (!(ng = memget(sizeof *ng))) { + errno = ENOMEM; + return (NULL); + } + memset(ng, 0x5e, sizeof *ng); + ng->private = NULL; + ng->close = ng_close; + ng->next = ng_next; + ng->test = ng_test; + ng->rewind = ng_rewind; + ng->minimize = ng_minimize; + return (ng); +} + +/* Methods. */ + +static void +ng_close(struct irs_ng *this) { + memput(this, sizeof *this); +} + +/* ARGSUSED */ +static int +ng_next(struct irs_ng *this, const char **host, const char **user, + const char **domain) +{ + UNUSED(this); + UNUSED(host); + UNUSED(user); + UNUSED(domain); + errno = ENOENT; + return (-1); +} + +static int +ng_test(struct irs_ng *this, const char *name, + const char *user, const char *host, const char *domain) +{ + UNUSED(this); + UNUSED(name); + UNUSED(user); + UNUSED(host); + UNUSED(domain); + errno = ENODEV; + return (-1); +} + +static void +ng_rewind(struct irs_ng *this, const char *netgroup) { + UNUSED(this); + UNUSED(netgroup); + /* NOOP */ +} + +static void +ng_minimize(struct irs_ng *this) { + UNUSED(this); + /* NOOP */ +} diff --git a/usr/src/lib/libresolv2_joy/common/irs/pathnames.h b/usr/src/lib/libresolv2_joy/common/irs/pathnames.h new file mode 100644 index 0000000000..1646842155 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/pathnames.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: pathnames.h,v 1.3 2005/04/27 04:56:34 sra Exp $ + */ + +#ifndef _PATH_IRS_CONF +#define _PATH_IRS_CONF "/etc/irs.conf" +#endif + +#ifndef _PATH_NETWORKS +#define _PATH_NETWORKS "/etc/networks" +#endif + +#ifndef _PATH_GROUP +#define _PATH_GROUP "/etc/group" +#endif + +#ifndef _PATH_NETGROUP +#define _PATH_NETGROUP "/etc/netgroup" +#endif + +#ifndef _PATH_SERVICES +#define _PATH_SERVICES "/etc/services" +#endif + +#ifdef IRS_LCL_SV_DB +#ifndef _PATH_SERVICES_DB +#define _PATH_SERVICES_DB _PATH_SERVICES ".db" +#endif +#endif + +#ifndef _PATH_HESIOD_CONF +#define _PATH_HESIOD_CONF "/etc/hesiod.conf" +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/irs/util.c b/usr/src/lib/libresolv2_joy/common/irs/util.c new file mode 100644 index 0000000000..9c70eabddc --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/irs/util.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: util.c,v 1.3 2005/04/27 04:56:34 sra Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <irs.h> + +#include "port_after.h" + +#include "irs_p.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +void +map_v4v6_address(const char *src, char *dst) { + u_char *p = (u_char *)dst; + char tmp[NS_INADDRSZ]; + int i; + + /* Stash a temporary copy so our caller can update in place. */ + memcpy(tmp, src, NS_INADDRSZ); + /* Mark this ipv6 addr as a mapped ipv4. */ + for (i = 0; i < 10; i++) + *p++ = 0x00; + *p++ = 0xff; + *p++ = 0xff; + /* Retrieve the saved copy and we're done. */ + memcpy((void*)p, tmp, NS_INADDRSZ); +} + +int +make_group_list(struct irs_gr *this, const char *name, + gid_t basegid, gid_t *groups, int *ngroups) +{ + struct group *grp; + int i, ng; + int ret, maxgroups; + + ret = -1; + ng = 0; + maxgroups = *ngroups; + /* + * When installing primary group, duplicate it; + * the first element of groups is the effective gid + * and will be overwritten when a setgid file is executed. + */ + if (ng >= maxgroups) + goto done; + groups[ng++] = basegid; + if (ng >= maxgroups) + goto done; + groups[ng++] = basegid; + /* + * Scan the group file to find additional groups. + */ + (*this->rewind)(this); + while ((grp = (*this->next)(this)) != NULL) { + if ((gid_t)grp->gr_gid == basegid) + continue; + for (i = 0; grp->gr_mem[i]; i++) { + if (!strcmp(grp->gr_mem[i], name)) { + if (ng >= maxgroups) + goto done; + groups[ng++] = grp->gr_gid; + break; + } + } + } + ret = 0; + done: + *ngroups = ng; + return (ret); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/assertions.c b/usr/src/lib/libresolv2_joy/common/isc/assertions.c new file mode 100644 index 0000000000..b71e5a32d3 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/assertions.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1997, 1999, 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: assertions.c,v 1.5 2008/11/14 02:36:51 marka Exp $"; +#endif + +#include "port_before.h" + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/assertions.h> + +#include "port_after.h" + +/* + * Forward. + */ + +static void default_assertion_failed(const char *, int, assertion_type, + const char *, int); + +/* + * Public. + */ + +assertion_failure_callback __assertion_failed = default_assertion_failed; + +void +set_assertion_failure_callback(assertion_failure_callback f) { + if (f == NULL) + __assertion_failed = default_assertion_failed; + else + __assertion_failed = f; +} + +const char * +assertion_type_to_text(assertion_type type) { + const char *result; + + switch (type) { + case assert_require: + result = "REQUIRE"; + break; + case assert_ensure: + result = "ENSURE"; + break; + case assert_insist: + result = "INSIST"; + break; + case assert_invariant: + result = "INVARIANT"; + break; + default: + result = NULL; + } + return (result); +} + +/* + * Private. + */ + +/* coverity[+kill] */ +static void +default_assertion_failed(const char *file, int line, assertion_type type, + const char *cond, int print_errno) +{ + fprintf(stderr, "%s:%d: %s(%s)%s%s failed.\n", + file, line, assertion_type_to_text(type), cond, + (print_errno) ? ": " : "", + (print_errno) ? strerror(errno) : ""); + abort(); + /* NOTREACHED */ +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/base64.c b/usr/src/lib/libresolv2_joy/common/isc/base64.c new file mode 100644 index 0000000000..79c35722b1 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/base64.c @@ -0,0 +1,333 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: base64.c,v 1.4 2005/04/27 04:56:34 sra Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "port_after.h" + +#ifndef ORIGINAL_ISC_CODE +#pragma weak __b64_ntop = b64_ntop +#pragma weak __b64_pton = b64_pton +#endif /* ORIGINAL_ISC_CODE */ + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2U < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0U != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1U) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /*%< Returned value doesn't count \\0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(src, target, targsize) + char const *src; + u_char *target; + size_t targsize; +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /*%< Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /*%< A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /*%< We got a pad char. */ + ch = *src++; /*%< Skip it, get next. */ + switch (state) { + case 0: /*%< Invalid = in first position */ + case 1: /*%< Invalid = in second position */ + return (-1); + + case 2: /*%< Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /*%< Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /*%< Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/bitncmp.c b/usr/src/lib/libresolv2_joy/common/isc/bitncmp.c new file mode 100644 index 0000000000..efe5009292 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/bitncmp.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1996, 1999, 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: bitncmp.c,v 1.5 2008/11/14 02:36:51 marka Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> + +#include <string.h> + +#include "port_after.h" + +#include <isc/misc.h> + +/*% + * int + * bitncmp(l, r, n) + * compare bit masks l and r, for n bits. + * return: + * -1, 1, or 0 in the libc tradition. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0x11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +bitncmp(const void *l, const void *r, int n) { + u_int lb, rb; + int x, b; + + b = n / 8; + x = memcmp(l, r, b); + if (x || (n % 8) == 0) + return (x); + + lb = ((const u_char *)l)[b]; + rb = ((const u_char *)r)[b]; + for (b = n % 8; b > 0; b--) { + if ((lb & 0x80) != (rb & 0x80)) { + if (lb & 0x80) + return (1); + return (-1); + } + lb <<= 1; + rb <<= 1; + } + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/ctl_clnt.c b/usr/src/lib/libresolv2_joy/common/isc/ctl_clnt.c new file mode 100644 index 0000000000..f71001a6d4 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/ctl_clnt.c @@ -0,0 +1,620 @@ +/* + * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1998-2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_clnt.c,v 1.11 2008/11/14 02:36:51 marka Exp $"; +#endif /* not lint */ + +/* Extern. */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#ifdef HAVE_MEMORY_H +#include <memory.h> +#endif + +#include <isc/assertions.h> +#include <isc/ctl.h> +#include <isc/eventlib.h> +#include <isc/list.h> +#include <isc/memcluster.h> + +#include "ctl_p.h" + +#include "port_after.h" + +/* Constants. */ + + +/* Macros. */ + +#define donefunc_p(ctx) ((ctx).donefunc != NULL) +#define arpacode_p(line) (isdigit((unsigned char)(line[0])) && \ + isdigit((unsigned char)(line[1])) && \ + isdigit((unsigned char)(line[2]))) +#define arpacont_p(line) (line[3] == '-') +#define arpadone_p(line) (line[3] == ' ' || line[3] == '\t' || \ + line[3] == '\r' || line[3] == '\0') + +/* Types. */ + +enum state { + initializing = 0, connecting, connected, destroyed +}; + +struct ctl_tran { + LINK(struct ctl_tran) link; + LINK(struct ctl_tran) wlink; + struct ctl_cctx * ctx; + struct ctl_buf outbuf; + ctl_clntdone donefunc; + void * uap; +}; + +struct ctl_cctx { + enum state state; + evContext ev; + int sock; + ctl_logfunc logger; + ctl_clntdone donefunc; + void * uap; + evConnID coID; + evTimerID tiID; + evFileID rdID; + evStreamID wrID; + struct ctl_buf inbuf; + struct timespec timeout; + LIST(struct ctl_tran) tran; + LIST(struct ctl_tran) wtran; +}; + +/* Forward. */ + +static struct ctl_tran *new_tran(struct ctl_cctx *, ctl_clntdone, void *, int); +static void start_write(struct ctl_cctx *); +static void destroy(struct ctl_cctx *, int); +static void error(struct ctl_cctx *); +static void new_state(struct ctl_cctx *, enum state); +static void conn_done(evContext, void *, int, + const void *, int, + const void *, int); +static void write_done(evContext, void *, int, int); +static void start_read(struct ctl_cctx *); +static void stop_read(struct ctl_cctx *); +static void readable(evContext, void *, int, int); +static void start_timer(struct ctl_cctx *); +static void stop_timer(struct ctl_cctx *); +static void touch_timer(struct ctl_cctx *); +static void timer(evContext, void *, + struct timespec, struct timespec); + +#ifndef HAVE_MEMCHR +static void * +memchr(const void *b, int c, size_t len) { + const unsigned char *p = b; + size_t i; + + for (i = 0; i < len; i++, p++) + if (*p == (unsigned char)c) + return ((void *)p); + return (NULL); +} +#endif + +/* Private data. */ + +static const char * const state_names[] = { + "initializing", "connecting", "connected", "destroyed" +}; + +/* Public. */ + +/*% + * void + * ctl_client() + * create, condition, and connect to a listener on the control port. + */ +struct ctl_cctx * +ctl_client(evContext lev, const struct sockaddr *cap, size_t cap_len, + const struct sockaddr *sap, size_t sap_len, + ctl_clntdone donefunc, void *uap, + u_int timeout, ctl_logfunc logger) +{ + static const char me[] = "ctl_client"; + static const int on = 1; + struct ctl_cctx *ctx; + struct sockaddr *captmp; + + if (logger == NULL) + logger = ctl_logger; + ctx = memget(sizeof *ctx); + if (ctx == NULL) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + goto fatal; + } + ctx->state = initializing; + ctx->ev = lev; + ctx->logger = logger; + ctx->timeout = evConsTime(timeout, 0); + ctx->donefunc = donefunc; + ctx->uap = uap; + ctx->coID.opaque = NULL; + ctx->tiID.opaque = NULL; + ctx->rdID.opaque = NULL; + ctx->wrID.opaque = NULL; + buffer_init(ctx->inbuf); + INIT_LIST(ctx->tran); + INIT_LIST(ctx->wtran); + ctx->sock = socket(sap->sa_family, SOCK_STREAM, PF_UNSPEC); + if (ctx->sock > evHighestFD(ctx->ev)) { + ctx->sock = -1; + errno = ENOTSOCK; + } + if (ctx->sock < 0) { + (*ctx->logger)(ctl_error, "%s: socket: %s", + me, strerror(errno)); + goto fatal; + } + if (cap != NULL) { + if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR, + (const char *)&on, sizeof on) != 0) { + (*ctx->logger)(ctl_warning, + "%s: setsockopt(REUSEADDR): %s", + me, strerror(errno)); + } + DE_CONST(cap, captmp); + if (bind(ctx->sock, captmp, cap_len) < 0) { + (*ctx->logger)(ctl_error, "%s: bind: %s", me, + strerror(errno)); + goto fatal; + } + } + if (evConnect(lev, ctx->sock, (const struct sockaddr *)sap, sap_len, + conn_done, ctx, &ctx->coID) < 0) { + (*ctx->logger)(ctl_error, "%s: evConnect(fd %d): %s", + me, ctx->sock, strerror(errno)); + fatal: + if (ctx != NULL) { + if (ctx->sock >= 0) + close(ctx->sock); + memput(ctx, sizeof *ctx); + } + return (NULL); + } + new_state(ctx, connecting); + return (ctx); +} + +/*% + * void + * ctl_endclient(ctx) + * close a client and release all of its resources. + */ +void +ctl_endclient(struct ctl_cctx *ctx) { + if (ctx->state != destroyed) + destroy(ctx, 0); + memput(ctx, sizeof *ctx); +} + +/*% + * int + * ctl_command(ctx, cmd, len, donefunc, uap) + * Queue a transaction, which will begin with sending cmd + * and complete by calling donefunc with the answer. + */ +int +ctl_command(struct ctl_cctx *ctx, const char *cmd, size_t len, + ctl_clntdone donefunc, void *uap) +{ + struct ctl_tran *tran; + char *pc; + unsigned int n; + + switch (ctx->state) { + case destroyed: + errno = ENOTCONN; + return (-1); + case connecting: + case connected: + break; + default: + abort(); + } + if (len >= (size_t)MAX_LINELEN) { + errno = EMSGSIZE; + return (-1); + } + tran = new_tran(ctx, donefunc, uap, 1); + if (tran == NULL) + return (-1); + if (ctl_bufget(&tran->outbuf, ctx->logger) < 0) + return (-1); + memcpy(tran->outbuf.text, cmd, len); + tran->outbuf.used = len; + for (pc = tran->outbuf.text, n = 0; n < tran->outbuf.used; pc++, n++) + if (!isascii((unsigned char)*pc) || + !isprint((unsigned char)*pc)) + *pc = '\040'; + start_write(ctx); + return (0); +} + +/* Private. */ + +static struct ctl_tran * +new_tran(struct ctl_cctx *ctx, ctl_clntdone donefunc, void *uap, int w) { + struct ctl_tran *new = memget(sizeof *new); + + if (new == NULL) + return (NULL); + new->ctx = ctx; + buffer_init(new->outbuf); + new->donefunc = donefunc; + new->uap = uap; + INIT_LINK(new, link); + INIT_LINK(new, wlink); + APPEND(ctx->tran, new, link); + if (w) + APPEND(ctx->wtran, new, wlink); + return (new); +} + +static void +start_write(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::start_write"; + struct ctl_tran *tran; + struct iovec iov[2], *iovp = iov; + char * tmp; + + REQUIRE(ctx->state == connecting || ctx->state == connected); + /* If there is a write in progress, don't try to write more yet. */ + if (ctx->wrID.opaque != NULL) + return; + /* If there are no trans, make sure timer is off, and we're done. */ + if (EMPTY(ctx->wtran)) { + if (ctx->tiID.opaque != NULL) + stop_timer(ctx); + return; + } + /* Pull it off the head of the write queue. */ + tran = HEAD(ctx->wtran); + UNLINK(ctx->wtran, tran, wlink); + /* Since there are some trans, make sure timer is successfully "on". */ + if (ctx->tiID.opaque != NULL) + touch_timer(ctx); + else + start_timer(ctx); + if (ctx->state == destroyed) + return; + /* Marshall a newline-terminated message and clock it out. */ + *iovp++ = evConsIovec(tran->outbuf.text, tran->outbuf.used); + DE_CONST("\r\n", tmp); + *iovp++ = evConsIovec(tmp, 2); + if (evWrite(ctx->ev, ctx->sock, iov, iovp - iov, + write_done, tran, &ctx->wrID) < 0) { + (*ctx->logger)(ctl_error, "%s: evWrite: %s", me, + strerror(errno)); + error(ctx); + return; + } + if (evTimeRW(ctx->ev, ctx->wrID, ctx->tiID) < 0) { + (*ctx->logger)(ctl_error, "%s: evTimeRW: %s", me, + strerror(errno)); + error(ctx); + return; + } +} + +static void +destroy(struct ctl_cctx *ctx, int notify) { + struct ctl_tran *this, *next; + + if (ctx->sock != -1) { + (void) close(ctx->sock); + ctx->sock = -1; + } + switch (ctx->state) { + case connecting: + REQUIRE(ctx->wrID.opaque == NULL); + REQUIRE(EMPTY(ctx->tran)); + /* + * This test is nec'y since destroy() can be called from + * start_read() while the state is still "connecting". + */ + if (ctx->coID.opaque != NULL) { + (void)evCancelConn(ctx->ev, ctx->coID); + ctx->coID.opaque = NULL; + } + break; + case connected: + REQUIRE(ctx->coID.opaque == NULL); + if (ctx->wrID.opaque != NULL) { + (void)evCancelRW(ctx->ev, ctx->wrID); + ctx->wrID.opaque = NULL; + } + if (ctx->rdID.opaque != NULL) + stop_read(ctx); + break; + case destroyed: + break; + default: + abort(); + } + if (allocated_p(ctx->inbuf)) + ctl_bufput(&ctx->inbuf); + for (this = HEAD(ctx->tran); this != NULL; this = next) { + next = NEXT(this, link); + if (allocated_p(this->outbuf)) + ctl_bufput(&this->outbuf); + if (notify && this->donefunc != NULL) + (*this->donefunc)(ctx, this->uap, NULL, 0); + memput(this, sizeof *this); + } + if (ctx->tiID.opaque != NULL) + stop_timer(ctx); + new_state(ctx, destroyed); +} + +static void +error(struct ctl_cctx *ctx) { + REQUIRE(ctx->state != destroyed); + destroy(ctx, 1); +} + +static void +new_state(struct ctl_cctx *ctx, enum state new_state) { + static const char me[] = "isc/ctl_clnt::new_state"; + + (*ctx->logger)(ctl_debug, "%s: %s -> %s", me, + state_names[ctx->state], state_names[new_state]); + ctx->state = new_state; +} + +static void +conn_done(evContext ev, void *uap, int fd, + const void *la, int lalen, + const void *ra, int ralen) +{ + static const char me[] = "isc/ctl_clnt::conn_done"; + struct ctl_cctx *ctx = uap; + struct ctl_tran *tran; + + UNUSED(ev); + UNUSED(la); + UNUSED(lalen); + UNUSED(ra); + UNUSED(ralen); + + ctx->coID.opaque = NULL; + if (fd < 0) { + (*ctx->logger)(ctl_error, "%s: evConnect: %s", me, + strerror(errno)); + error(ctx); + return; + } + new_state(ctx, connected); + tran = new_tran(ctx, ctx->donefunc, ctx->uap, 0); + if (tran == NULL) { + (*ctx->logger)(ctl_error, "%s: new_tran failed: %s", me, + strerror(errno)); + error(ctx); + return; + } + start_read(ctx); + if (ctx->state == destroyed) { + (*ctx->logger)(ctl_error, "%s: start_read failed: %s", + me, strerror(errno)); + error(ctx); + return; + } +} + +static void +write_done(evContext lev, void *uap, int fd, int bytes) { + struct ctl_tran *tran = (struct ctl_tran *)uap; + struct ctl_cctx *ctx = tran->ctx; + + UNUSED(lev); + UNUSED(fd); + + ctx->wrID.opaque = NULL; + if (ctx->tiID.opaque != NULL) + touch_timer(ctx); + ctl_bufput(&tran->outbuf); + start_write(ctx); + if (bytes < 0) + destroy(ctx, 1); + else + start_read(ctx); +} + +static void +start_read(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::start_read"; + + REQUIRE(ctx->state == connecting || ctx->state == connected); + REQUIRE(ctx->rdID.opaque == NULL); + if (evSelectFD(ctx->ev, ctx->sock, EV_READ, readable, ctx, + &ctx->rdID) < 0) + { + (*ctx->logger)(ctl_error, "%s: evSelect(fd %d): %s", me, + ctx->sock, strerror(errno)); + error(ctx); + return; + } +} + +static void +stop_read(struct ctl_cctx *ctx) { + REQUIRE(ctx->coID.opaque == NULL); + REQUIRE(ctx->rdID.opaque != NULL); + (void)evDeselectFD(ctx->ev, ctx->rdID); + ctx->rdID.opaque = NULL; +} + +static void +readable(evContext ev, void *uap, int fd, int evmask) { + static const char me[] = "isc/ctl_clnt::readable"; + struct ctl_cctx *ctx = uap; + struct ctl_tran *tran; + ssize_t n; + char *eos; + + UNUSED(ev); + + REQUIRE(ctx != NULL); + REQUIRE(fd >= 0); + REQUIRE(evmask == EV_READ); + REQUIRE(ctx->state == connected); + REQUIRE(!EMPTY(ctx->tran)); + tran = HEAD(ctx->tran); + if (!allocated_p(ctx->inbuf) && + ctl_bufget(&ctx->inbuf, ctx->logger) < 0) { + (*ctx->logger)(ctl_error, "%s: can't get an input buffer", me); + error(ctx); + return; + } + n = read(ctx->sock, ctx->inbuf.text + ctx->inbuf.used, + MAX_LINELEN - ctx->inbuf.used); + if (n <= 0) { + (*ctx->logger)(ctl_warning, "%s: read: %s", me, + (n == 0) ? "Unexpected EOF" : strerror(errno)); + error(ctx); + return; + } + if (ctx->tiID.opaque != NULL) + touch_timer(ctx); + ctx->inbuf.used += n; + (*ctx->logger)(ctl_debug, "%s: read %d, used %d", me, + n, ctx->inbuf.used); + again: + eos = memchr(ctx->inbuf.text, '\n', ctx->inbuf.used); + if (eos != NULL && eos != ctx->inbuf.text && eos[-1] == '\r') { + int done = 0; + + eos[-1] = '\0'; + if (!arpacode_p(ctx->inbuf.text)) { + /* XXX Doesn't FTP do this sometimes? Is it legal? */ + (*ctx->logger)(ctl_error, "%s: no arpa code (%s)", me, + ctx->inbuf.text); + error(ctx); + return; + } + if (arpadone_p(ctx->inbuf.text)) + done = 1; + else if (arpacont_p(ctx->inbuf.text)) + done = 0; + else { + /* XXX Doesn't FTP do this sometimes? Is it legal? */ + (*ctx->logger)(ctl_error, "%s: no arpa flag (%s)", me, + ctx->inbuf.text); + error(ctx); + return; + } + (*tran->donefunc)(ctx, tran->uap, ctx->inbuf.text, + (done ? 0 : CTL_MORE)); + ctx->inbuf.used -= ((eos - ctx->inbuf.text) + 1); + if (ctx->inbuf.used == 0U) + ctl_bufput(&ctx->inbuf); + else + memmove(ctx->inbuf.text, eos + 1, ctx->inbuf.used); + if (done) { + UNLINK(ctx->tran, tran, link); + memput(tran, sizeof *tran); + stop_read(ctx); + start_write(ctx); + return; + } + if (allocated_p(ctx->inbuf)) + goto again; + return; + } + if (ctx->inbuf.used == (size_t)MAX_LINELEN) { + (*ctx->logger)(ctl_error, "%s: line too long (%-10s...)", me, + ctx->inbuf.text); + error(ctx); + } +} + +/* Timer related stuff. */ + +static void +start_timer(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::start_timer"; + + REQUIRE(ctx->tiID.opaque == NULL); + if (evSetIdleTimer(ctx->ev, timer, ctx, ctx->timeout, &ctx->tiID) < 0){ + (*ctx->logger)(ctl_error, "%s: evSetIdleTimer: %s", me, + strerror(errno)); + error(ctx); + return; + } +} + +static void +stop_timer(struct ctl_cctx *ctx) { + static const char me[] = "isc/ctl_clnt::stop_timer"; + + REQUIRE(ctx->tiID.opaque != NULL); + if (evClearIdleTimer(ctx->ev, ctx->tiID) < 0) { + (*ctx->logger)(ctl_error, "%s: evClearIdleTimer: %s", me, + strerror(errno)); + error(ctx); + return; + } + ctx->tiID.opaque = NULL; +} + +static void +touch_timer(struct ctl_cctx *ctx) { + REQUIRE(ctx->tiID.opaque != NULL); + + evTouchIdleTimer(ctx->ev, ctx->tiID); +} + +static void +timer(evContext ev, void *uap, struct timespec due, struct timespec itv) { + static const char me[] = "isc/ctl_clnt::timer"; + struct ctl_cctx *ctx = uap; + + UNUSED(ev); + UNUSED(due); + UNUSED(itv); + + ctx->tiID.opaque = NULL; + (*ctx->logger)(ctl_error, "%s: timeout after %u seconds while %s", me, + ctx->timeout.tv_sec, state_names[ctx->state]); + error(ctx); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/ctl_p.c b/usr/src/lib/libresolv2_joy/common/isc/ctl_p.c new file mode 100644 index 0000000000..7ab719a5e6 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/ctl_p.c @@ -0,0 +1,188 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_p.c,v 1.4 2005/04/27 04:56:35 sra Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* Extern. */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <isc/assertions.h> +#include <isc/eventlib.h> +#include <isc/logging.h> +#include <isc/memcluster.h> +#include <isc/ctl.h> + +#include "ctl_p.h" + +#include "port_after.h" + +/* Constants. */ + +const char * const ctl_sevnames[] = { + "debug", "warning", "error" +}; + +/* Public. */ + +/*% + * ctl_logger() + * if ctl_startup()'s caller didn't specify a logger, this one + * is used. this pollutes stderr with all kinds of trash so it will + * probably never be used in real applications. + */ +void +ctl_logger(enum ctl_severity severity, const char *format, ...) { + va_list ap; + static const char me[] = "ctl_logger"; + + fprintf(stderr, "%s(%s): ", me, ctl_sevnames[severity]); + va_start(ap, format); + vfprintf(stderr, format, ap); + va_end(ap); + fputc('\n', stderr); +} + +int +ctl_bufget(struct ctl_buf *buf, ctl_logfunc logger) { + static const char me[] = "ctl_bufget"; + + REQUIRE(!allocated_p(*buf) && buf->used == 0U); + buf->text = memget(MAX_LINELEN); + if (!allocated_p(*buf)) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + return (-1); + } + buf->used = 0; + return (0); +} + +void +ctl_bufput(struct ctl_buf *buf) { + + REQUIRE(allocated_p(*buf)); + memput(buf->text, MAX_LINELEN); + buf->text = NULL; + buf->used = 0; +} + +const char * +ctl_sa_ntop(const struct sockaddr *sa, + char *buf, size_t size, + ctl_logfunc logger) +{ + static const char me[] = "ctl_sa_ntop"; + static const char punt[] = "[0].-1"; + char tmp[INET6_ADDRSTRLEN]; + + switch (sa->sa_family) { + case AF_INET6: { + const struct sockaddr_in6 *in6 = + (const struct sockaddr_in6 *) sa; + + if (inet_ntop(in6->sin6_family, &in6->sin6_addr, tmp, sizeof tmp) + == NULL) { + (*logger)(ctl_error, "%s: inet_ntop(%u %04x): %s", + me, in6->sin6_family, + in6->sin6_port, strerror(errno)); + return (punt); + } + if (strlen(tmp) + sizeof "[].65535" > size) { + (*logger)(ctl_error, "%s: buffer overflow", me); + return (punt); + } + (void) sprintf(buf, "[%s].%u", tmp, ntohs(in6->sin6_port)); + return (buf); + } + case AF_INET: { + const struct sockaddr_in *in = + (const struct sockaddr_in *) sa; + + if (inet_ntop(in->sin_family, &in->sin_addr, tmp, sizeof tmp) + == NULL) { + (*logger)(ctl_error, "%s: inet_ntop(%u %04x %08x): %s", + me, in->sin_family, + in->sin_port, in->sin_addr.s_addr, + strerror(errno)); + return (punt); + } + if (strlen(tmp) + sizeof "[].65535" > size) { + (*logger)(ctl_error, "%s: buffer overflow", me); + return (punt); + } + (void) sprintf(buf, "[%s].%u", tmp, ntohs(in->sin_port)); + return (buf); + } +#ifndef NO_SOCKADDR_UN + case AF_UNIX: { + const struct sockaddr_un *un = + (const struct sockaddr_un *) sa; + unsigned int x = sizeof un->sun_path; + + if (x > size) + x = size; + strncpy(buf, un->sun_path, x - 1); + buf[x - 1] = '\0'; + return (buf); + } +#endif + default: + return (punt); + } +} + +void +ctl_sa_copy(const struct sockaddr *src, struct sockaddr *dst) { + switch (src->sa_family) { + case AF_INET6: + *((struct sockaddr_in6 *)dst) = + *((const struct sockaddr_in6 *)src); + break; + case AF_INET: + *((struct sockaddr_in *)dst) = + *((const struct sockaddr_in *)src); + break; +#ifndef NO_SOCKADDR_UN + case AF_UNIX: + *((struct sockaddr_un *)dst) = + *((const struct sockaddr_un *)src); + break; +#endif + default: + *dst = *src; + break; + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/ctl_p.h b/usr/src/lib/libresolv2_joy/common/isc/ctl_p.h new file mode 100644 index 0000000000..18a52ae39c --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/ctl_p.h @@ -0,0 +1,28 @@ +struct ctl_buf { + char * text; + size_t used; +}; + +#define MAX_LINELEN 990 /*%< Like SMTP. */ +#ifndef NO_SOCKADDR_UN +#define MAX_NTOP PATH_MAX +#else +#define MAX_NTOP (sizeof "[255.255.255.255].65535") +#endif + +#define allocated_p(Buf) ((Buf).text != NULL) +#define buffer_init(Buf) ((Buf).text = 0, (Buf.used) = 0) + +#define ctl_bufget __ctl_bufget +#define ctl_bufput __ctl_bufput +#define ctl_sa_ntop __ctl_sa_ntop +#define ctl_sa_copy __ctl_sa_copy + +int ctl_bufget(struct ctl_buf *, ctl_logfunc); +void ctl_bufput(struct ctl_buf *); +const char * ctl_sa_ntop(const struct sockaddr *, char *, size_t, + ctl_logfunc); +void ctl_sa_copy(const struct sockaddr *, + struct sockaddr *); + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/ctl_srvr.c b/usr/src/lib/libresolv2_joy/common/isc/ctl_srvr.c new file mode 100644 index 0000000000..8fd7a21ffa --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/ctl_srvr.c @@ -0,0 +1,787 @@ +/* + * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1998-2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: ctl_srvr.c,v 1.10 2008/11/14 02:36:51 marka Exp $"; +#endif /* not lint */ + +/* Extern. */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/un.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <fcntl.h> +#ifdef HAVE_MEMORY_H +#include <memory.h> +#endif + +#include <isc/assertions.h> +#include <isc/ctl.h> +#include <isc/eventlib.h> +#include <isc/list.h> +#include <isc/logging.h> +#include <isc/memcluster.h> + +#include "ctl_p.h" + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Macros. */ + +#define lastverb_p(verb) (verb->name == NULL || verb->func == NULL) +#define address_expr ctl_sa_ntop((struct sockaddr *)&sess->sa, \ + tmp, sizeof tmp, ctx->logger) + +/* Types. */ + +enum state { + available = 0, initializing, writing, reading, reading_data, + processing, idling, quitting, closing +}; + +union sa_un { + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif +}; + +struct ctl_sess { + LINK(struct ctl_sess) link; + struct ctl_sctx * ctx; + enum state state; + int sock; + union sa_un sa; + evFileID rdID; + evStreamID wrID; + evTimerID rdtiID; + evTimerID wrtiID; + struct ctl_buf inbuf; + struct ctl_buf outbuf; + const struct ctl_verb * verb; + u_int helpcode; + const void * respctx; + u_int respflags; + ctl_srvrdone donefunc; + void * uap; + void * csctx; +}; + +struct ctl_sctx { + evContext ev; + void * uctx; + u_int unkncode; + u_int timeoutcode; + const struct ctl_verb * verbs; + const struct ctl_verb * connverb; + int sock; + int max_sess; + int cur_sess; + struct timespec timeout; + ctl_logfunc logger; + evConnID acID; + LIST(struct ctl_sess) sess; +}; + +/* Forward. */ + +static void ctl_accept(evContext, void *, int, + const void *, int, + const void *, int); +static void ctl_close(struct ctl_sess *); +static void ctl_new_state(struct ctl_sess *, + enum state, + const char *); +static void ctl_start_read(struct ctl_sess *); +static void ctl_stop_read(struct ctl_sess *); +static void ctl_readable(evContext, void *, int, int); +static void ctl_rdtimeout(evContext, void *, + struct timespec, + struct timespec); +static void ctl_wrtimeout(evContext, void *, + struct timespec, + struct timespec); +static void ctl_docommand(struct ctl_sess *); +static void ctl_writedone(evContext, void *, int, int); +static void ctl_morehelp(struct ctl_sctx *, + struct ctl_sess *, + const struct ctl_verb *, + const char *, + u_int, const void *, void *); +static void ctl_signal_done(struct ctl_sctx *, + struct ctl_sess *); + +/* Private data. */ + +static const char * state_names[] = { + "available", "initializing", "writing", "reading", + "reading_data", "processing", "idling", "quitting", "closing" +}; + +static const char space[] = " "; + +static const struct ctl_verb fakehelpverb = { + "fakehelp", ctl_morehelp , NULL +}; + +/* Public. */ + +/*% + * void + * ctl_server() + * create, condition, and start a listener on the control port. + */ +struct ctl_sctx * +ctl_server(evContext lev, const struct sockaddr *sap, size_t sap_len, + const struct ctl_verb *verbs, + u_int unkncode, u_int timeoutcode, + u_int timeout, int backlog, int max_sess, + ctl_logfunc logger, void *uctx) +{ + static const char me[] = "ctl_server"; + static const int on = 1; + const struct ctl_verb *connverb; + struct ctl_sctx *ctx; + int save_errno; + + if (logger == NULL) + logger = ctl_logger; + for (connverb = verbs; + connverb->name != NULL && connverb->func != NULL; + connverb++) + if (connverb->name[0] == '\0') + break; + if (connverb->func == NULL) { + (*logger)(ctl_error, "%s: no connection verb found", me); + return (NULL); + } + ctx = memget(sizeof *ctx); + if (ctx == NULL) { + (*logger)(ctl_error, "%s: getmem: %s", me, strerror(errno)); + return (NULL); + } + ctx->ev = lev; + ctx->uctx = uctx; + ctx->unkncode = unkncode; + ctx->timeoutcode = timeoutcode; + ctx->verbs = verbs; + ctx->timeout = evConsTime(timeout, 0); + ctx->logger = logger; + ctx->connverb = connverb; + ctx->max_sess = max_sess; + ctx->cur_sess = 0; + INIT_LIST(ctx->sess); + ctx->sock = socket(sap->sa_family, SOCK_STREAM, PF_UNSPEC); + if (ctx->sock > evHighestFD(ctx->ev)) { + ctx->sock = -1; + errno = ENOTSOCK; + } + if (ctx->sock < 0) { + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: socket: %s", + me, strerror(errno)); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + if (ctx->sock > evHighestFD(lev)) { + close(ctx->sock); + (*ctx->logger)(ctl_error, "%s: file descriptor > evHighestFD"); + errno = ENFILE; + memput(ctx, sizeof *ctx); + return (NULL); + } +#ifdef NO_UNIX_REUSEADDR + if (sap->sa_family != AF_UNIX) +#endif + if (setsockopt(ctx->sock, SOL_SOCKET, SO_REUSEADDR, + (const char *)&on, sizeof on) != 0) { + (*ctx->logger)(ctl_warning, + "%s: setsockopt(REUSEADDR): %s", + me, strerror(errno)); + } + if (bind(ctx->sock, sap, sap_len) < 0) { + char tmp[MAX_NTOP]; + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: bind: %s: %s", + me, ctl_sa_ntop((const struct sockaddr *)sap, + tmp, sizeof tmp, ctx->logger), + strerror(save_errno)); + close(ctx->sock); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + if (fcntl(ctx->sock, F_SETFD, 1) < 0) { + (*ctx->logger)(ctl_warning, "%s: fcntl: %s", me, + strerror(errno)); + } + if (evListen(lev, ctx->sock, backlog, ctl_accept, ctx, + &ctx->acID) < 0) { + save_errno = errno; + (*ctx->logger)(ctl_error, "%s: evListen(fd %d): %s", + me, ctx->sock, strerror(errno)); + close(ctx->sock); + memput(ctx, sizeof *ctx); + errno = save_errno; + return (NULL); + } + (*ctx->logger)(ctl_debug, "%s: new ctx %p, sock %d", + me, ctx, ctx->sock); + return (ctx); +} + +/*% + * void + * ctl_endserver(ctx) + * if the control listener is open, close it. clean out all eventlib + * stuff. close all active sessions. + */ +void +ctl_endserver(struct ctl_sctx *ctx) { + static const char me[] = "ctl_endserver"; + struct ctl_sess *this, *next; + + (*ctx->logger)(ctl_debug, "%s: ctx %p, sock %d, acID %p, sess %p", + me, ctx, ctx->sock, ctx->acID.opaque, ctx->sess); + if (ctx->acID.opaque != NULL) { + (void)evCancelConn(ctx->ev, ctx->acID); + ctx->acID.opaque = NULL; + } + if (ctx->sock != -1) { + (void) close(ctx->sock); + ctx->sock = -1; + } + for (this = HEAD(ctx->sess); this != NULL; this = next) { + next = NEXT(this, link); + ctl_close(this); + } + memput(ctx, sizeof *ctx); +} + +/*% + * If body is non-NULL then it we add a "." line after it. + * Caller must have escaped lines with leading ".". + */ +void +ctl_response(struct ctl_sess *sess, u_int code, const char *text, + u_int flags, const void *respctx, ctl_srvrdone donefunc, + void *uap, const char *body, size_t bodylen) +{ + static const char me[] = "ctl_response"; + struct iovec iov[3], *iovp = iov; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP], *pc; + int n; + + REQUIRE(sess->state == initializing || + sess->state == processing || + sess->state == reading_data || + sess->state == writing); + REQUIRE(sess->wrtiID.opaque == NULL); + REQUIRE(sess->wrID.opaque == NULL); + ctl_new_state(sess, writing, me); + sess->donefunc = donefunc; + sess->uap = uap; + if (!allocated_p(sess->outbuf) && + ctl_bufget(&sess->outbuf, ctx->logger) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: cant get an output buffer", + me, address_expr); + goto untimely; + } + if (sizeof "000-\r\n" + strlen(text) > (size_t)MAX_LINELEN) { + (*ctx->logger)(ctl_error, "%s: %s: output buffer ovf, closing", + me, address_expr); + goto untimely; + } + sess->outbuf.used = SPRINTF((sess->outbuf.text, "%03d%c%s\r\n", + code, (flags & CTL_MORE) != 0 ? '-' : ' ', + text)); + for (pc = sess->outbuf.text, n = 0; + n < (int)sess->outbuf.used-2; pc++, n++) + if (!isascii((unsigned char)*pc) || + !isprint((unsigned char)*pc)) + *pc = '\040'; + *iovp++ = evConsIovec(sess->outbuf.text, sess->outbuf.used); + if (body != NULL) { + char *tmp; + DE_CONST(body, tmp); + *iovp++ = evConsIovec(tmp, bodylen); + DE_CONST(".\r\n", tmp); + *iovp++ = evConsIovec(tmp, 3); + } + (*ctx->logger)(ctl_debug, "%s: [%d] %s", me, + sess->outbuf.used, sess->outbuf.text); + if (evWrite(ctx->ev, sess->sock, iov, iovp - iov, + ctl_writedone, sess, &sess->wrID) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: evWrite: %s", me, + address_expr, strerror(errno)); + goto untimely; + } + if (evSetIdleTimer(ctx->ev, ctl_wrtimeout, sess, ctx->timeout, + &sess->wrtiID) < 0) + { + (*ctx->logger)(ctl_error, "%s: %s: evSetIdleTimer: %s", me, + address_expr, strerror(errno)); + goto untimely; + } + if (evTimeRW(ctx->ev, sess->wrID, sess->wrtiID) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: evTimeRW: %s", me, + address_expr, strerror(errno)); + untimely: + ctl_signal_done(ctx, sess); + ctl_close(sess); + return; + } + sess->respctx = respctx; + sess->respflags = flags; +} + +void +ctl_sendhelp(struct ctl_sess *sess, u_int code) { + static const char me[] = "ctl_sendhelp"; + struct ctl_sctx *ctx = sess->ctx; + + sess->helpcode = code; + sess->verb = &fakehelpverb; + ctl_morehelp(ctx, sess, NULL, me, CTL_MORE, + (const void *)ctx->verbs, NULL); +} + +void * +ctl_getcsctx(struct ctl_sess *sess) { + return (sess->csctx); +} + +void * +ctl_setcsctx(struct ctl_sess *sess, void *csctx) { + void *old = sess->csctx; + + sess->csctx = csctx; + return (old); +} + +/* Private functions. */ + +static void +ctl_accept(evContext lev, void *uap, int fd, + const void *lav, int lalen, + const void *rav, int ralen) +{ + static const char me[] = "ctl_accept"; + struct ctl_sctx *ctx = uap; + struct ctl_sess *sess = NULL; + char tmp[MAX_NTOP]; + + UNUSED(lev); + UNUSED(lalen); + UNUSED(ralen); + + if (fd < 0) { + (*ctx->logger)(ctl_error, "%s: accept: %s", + me, strerror(errno)); + return; + } + if (ctx->cur_sess == ctx->max_sess) { + (*ctx->logger)(ctl_error, "%s: %s: too many control sessions", + me, ctl_sa_ntop((const struct sockaddr *)rav, + tmp, sizeof tmp, + ctx->logger)); + (void) close(fd); + return; + } + sess = memget(sizeof *sess); + if (sess == NULL) { + (*ctx->logger)(ctl_error, "%s: memget: %s", me, + strerror(errno)); + (void) close(fd); + return; + } + if (fcntl(fd, F_SETFD, 1) < 0) { + (*ctx->logger)(ctl_warning, "%s: fcntl: %s", me, + strerror(errno)); + } + ctx->cur_sess++; + INIT_LINK(sess, link); + APPEND(ctx->sess, sess, link); + sess->ctx = ctx; + sess->sock = fd; + sess->wrID.opaque = NULL; + sess->rdID.opaque = NULL; + sess->wrtiID.opaque = NULL; + sess->rdtiID.opaque = NULL; + sess->respctx = NULL; + sess->csctx = NULL; + if (((const struct sockaddr *)rav)->sa_family == AF_UNIX) + ctl_sa_copy((const struct sockaddr *)lav, + (struct sockaddr *)&sess->sa); + else + ctl_sa_copy((const struct sockaddr *)rav, + (struct sockaddr *)&sess->sa); + sess->donefunc = NULL; + buffer_init(sess->inbuf); + buffer_init(sess->outbuf); + sess->state = available; + ctl_new_state(sess, initializing, me); + sess->verb = ctx->connverb; + (*ctx->logger)(ctl_debug, "%s: %s: accepting (fd %d)", + me, address_expr, sess->sock); + (*ctx->connverb->func)(ctx, sess, ctx->connverb, "", 0, + (const struct sockaddr *)rav, ctx->uctx); +} + +static void +ctl_new_state(struct ctl_sess *sess, enum state new_state, const char *reason) +{ + static const char me[] = "ctl_new_state"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + (*ctx->logger)(ctl_debug, "%s: %s: %s -> %s (%s)", + me, address_expr, + state_names[sess->state], + state_names[new_state], reason); + sess->state = new_state; +} + +static void +ctl_close(struct ctl_sess *sess) { + static const char me[] = "ctl_close"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + REQUIRE(sess->state == initializing || + sess->state == writing || + sess->state == reading || + sess->state == processing || + sess->state == reading_data || + sess->state == idling); + REQUIRE(sess->sock != -1); + if (sess->state == reading || sess->state == reading_data) + ctl_stop_read(sess); + else if (sess->state == writing) { + if (sess->wrID.opaque != NULL) { + (void) evCancelRW(ctx->ev, sess->wrID); + sess->wrID.opaque = NULL; + } + if (sess->wrtiID.opaque != NULL) { + (void) evClearIdleTimer(ctx->ev, sess->wrtiID); + sess->wrtiID.opaque = NULL; + } + } + ctl_new_state(sess, closing, me); + (void) close(sess->sock); + if (allocated_p(sess->inbuf)) + ctl_bufput(&sess->inbuf); + if (allocated_p(sess->outbuf)) + ctl_bufput(&sess->outbuf); + (*ctx->logger)(ctl_debug, "%s: %s: closed (fd %d)", + me, address_expr, sess->sock); + UNLINK(ctx->sess, sess, link); + memput(sess, sizeof *sess); + ctx->cur_sess--; +} + +static void +ctl_start_read(struct ctl_sess *sess) { + static const char me[] = "ctl_start_read"; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + REQUIRE(sess->state == initializing || + sess->state == writing || + sess->state == processing || + sess->state == idling); + REQUIRE(sess->rdtiID.opaque == NULL); + REQUIRE(sess->rdID.opaque == NULL); + sess->inbuf.used = 0; + if (evSetIdleTimer(ctx->ev, ctl_rdtimeout, sess, ctx->timeout, + &sess->rdtiID) < 0) + { + (*ctx->logger)(ctl_error, "%s: %s: evSetIdleTimer: %s", me, + address_expr, strerror(errno)); + ctl_close(sess); + return; + } + if (evSelectFD(ctx->ev, sess->sock, EV_READ, + ctl_readable, sess, &sess->rdID) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: evSelectFD: %s", me, + address_expr, strerror(errno)); + return; + } + ctl_new_state(sess, reading, me); +} + +static void +ctl_stop_read(struct ctl_sess *sess) { + static const char me[] = "ctl_stop_read"; + struct ctl_sctx *ctx = sess->ctx; + + REQUIRE(sess->state == reading || sess->state == reading_data); + REQUIRE(sess->rdID.opaque != NULL); + (void) evDeselectFD(ctx->ev, sess->rdID); + sess->rdID.opaque = NULL; + if (sess->rdtiID.opaque != NULL) { + (void) evClearIdleTimer(ctx->ev, sess->rdtiID); + sess->rdtiID.opaque = NULL; + } + ctl_new_state(sess, idling, me); +} + +static void +ctl_readable(evContext lev, void *uap, int fd, int evmask) { + static const char me[] = "ctl_readable"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx; + char *eos, tmp[MAX_NTOP]; + ssize_t n; + + REQUIRE(sess != NULL); + REQUIRE(fd >= 0); + REQUIRE(evmask == EV_READ); + REQUIRE(sess->state == reading || sess->state == reading_data); + + ctx = sess->ctx; + evTouchIdleTimer(lev, sess->rdtiID); + if (!allocated_p(sess->inbuf) && + ctl_bufget(&sess->inbuf, ctx->logger) < 0) { + (*ctx->logger)(ctl_error, "%s: %s: cant get an input buffer", + me, address_expr); + ctl_close(sess); + return; + } + n = read(sess->sock, sess->inbuf.text + sess->inbuf.used, + MAX_LINELEN - sess->inbuf.used); + if (n <= 0) { + (*ctx->logger)(ctl_debug, "%s: %s: read: %s", + me, address_expr, + (n == 0) ? "Unexpected EOF" : strerror(errno)); + ctl_close(sess); + return; + } + sess->inbuf.used += n; + eos = memchr(sess->inbuf.text, '\n', sess->inbuf.used); + if (eos != NULL && eos != sess->inbuf.text && eos[-1] == '\r') { + eos[-1] = '\0'; + if ((sess->respflags & CTL_DATA) != 0) { + INSIST(sess->verb != NULL); + (*sess->verb->func)(sess->ctx, sess, sess->verb, + sess->inbuf.text, + CTL_DATA, sess->respctx, + sess->ctx->uctx); + } else { + ctl_stop_read(sess); + ctl_docommand(sess); + } + sess->inbuf.used -= ((eos - sess->inbuf.text) + 1); + if (sess->inbuf.used == 0U) + ctl_bufput(&sess->inbuf); + else + memmove(sess->inbuf.text, eos + 1, sess->inbuf.used); + return; + } + if (sess->inbuf.used == (size_t)MAX_LINELEN) { + (*ctx->logger)(ctl_error, "%s: %s: line too long, closing", + me, address_expr); + ctl_close(sess); + } +} + +static void +ctl_wrtimeout(evContext lev, void *uap, + struct timespec due, + struct timespec itv) +{ + static const char me[] = "ctl_wrtimeout"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + UNUSED(lev); + UNUSED(due); + UNUSED(itv); + + REQUIRE(sess->state == writing); + sess->wrtiID.opaque = NULL; + (*ctx->logger)(ctl_warning, "%s: %s: write timeout, closing", + me, address_expr); + if (sess->wrID.opaque != NULL) { + (void) evCancelRW(ctx->ev, sess->wrID); + sess->wrID.opaque = NULL; + } + ctl_signal_done(ctx, sess); + ctl_new_state(sess, processing, me); + ctl_close(sess); +} + +static void +ctl_rdtimeout(evContext lev, void *uap, + struct timespec due, + struct timespec itv) +{ + static const char me[] = "ctl_rdtimeout"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + + UNUSED(lev); + UNUSED(due); + UNUSED(itv); + + REQUIRE(sess->state == reading); + sess->rdtiID.opaque = NULL; + (*ctx->logger)(ctl_warning, "%s: %s: timeout, closing", + me, address_expr); + if (sess->state == reading || sess->state == reading_data) + ctl_stop_read(sess); + ctl_signal_done(ctx, sess); + ctl_new_state(sess, processing, me); + ctl_response(sess, ctx->timeoutcode, "Timeout.", CTL_EXIT, NULL, + NULL, NULL, NULL, 0); +} + +static void +ctl_docommand(struct ctl_sess *sess) { + static const char me[] = "ctl_docommand"; + char *name, *rest, tmp[MAX_NTOP]; + struct ctl_sctx *ctx = sess->ctx; + const struct ctl_verb *verb; + + REQUIRE(allocated_p(sess->inbuf)); + (*ctx->logger)(ctl_debug, "%s: %s: \"%s\" [%u]", + me, address_expr, + sess->inbuf.text, (u_int)sess->inbuf.used); + ctl_new_state(sess, processing, me); + name = sess->inbuf.text + strspn(sess->inbuf.text, space); + rest = name + strcspn(name, space); + if (*rest != '\0') { + *rest++ = '\0'; + rest += strspn(rest, space); + } + for (verb = ctx->verbs; + verb != NULL && verb->name != NULL && verb->func != NULL; + verb++) + if (verb->name[0] != '\0' && strcasecmp(name, verb->name) == 0) + break; + if (verb != NULL && verb->name != NULL && verb->func != NULL) { + sess->verb = verb; + (*verb->func)(ctx, sess, verb, rest, 0, NULL, ctx->uctx); + } else { + char buf[1100]; + + if (sizeof "Unrecognized command \"\" (args \"\")" + + strlen(name) + strlen(rest) > sizeof buf) + strcpy(buf, "Unrecognized command (buf ovf)"); + else + sprintf(buf, + "Unrecognized command \"%s\" (args \"%s\")", + name, rest); + ctl_response(sess, ctx->unkncode, buf, 0, NULL, NULL, NULL, + NULL, 0); + } +} + +static void +ctl_writedone(evContext lev, void *uap, int fd, int bytes) { + static const char me[] = "ctl_writedone"; + struct ctl_sess *sess = uap; + struct ctl_sctx *ctx = sess->ctx; + char tmp[MAX_NTOP]; + int save_errno = errno; + + UNUSED(lev); + UNUSED(uap); + + REQUIRE(sess->state == writing); + REQUIRE(fd == sess->sock); + REQUIRE(sess->wrtiID.opaque != NULL); + sess->wrID.opaque = NULL; + (void) evClearIdleTimer(ctx->ev, sess->wrtiID); + sess->wrtiID.opaque = NULL; + if (bytes < 0) { + (*ctx->logger)(ctl_error, "%s: %s: %s", + me, address_expr, strerror(save_errno)); + ctl_close(sess); + return; + } + + INSIST(allocated_p(sess->outbuf)); + ctl_bufput(&sess->outbuf); + if ((sess->respflags & CTL_EXIT) != 0) { + ctl_signal_done(ctx, sess); + ctl_close(sess); + return; + } else if ((sess->respflags & CTL_MORE) != 0) { + INSIST(sess->verb != NULL); + (*sess->verb->func)(sess->ctx, sess, sess->verb, "", + CTL_MORE, sess->respctx, sess->ctx->uctx); + } else { + ctl_signal_done(ctx, sess); + ctl_start_read(sess); + } +} + +static void +ctl_morehelp(struct ctl_sctx *ctx, struct ctl_sess *sess, + const struct ctl_verb *verb, const char *text, + u_int respflags, const void *respctx, void *uctx) +{ + const struct ctl_verb *this = respctx, *next = this + 1; + + UNUSED(ctx); + UNUSED(verb); + UNUSED(text); + UNUSED(uctx); + + REQUIRE(!lastverb_p(this)); + REQUIRE((respflags & CTL_MORE) != 0); + if (lastverb_p(next)) + respflags &= ~CTL_MORE; + ctl_response(sess, sess->helpcode, this->help, respflags, next, + NULL, NULL, NULL, 0); +} + +static void +ctl_signal_done(struct ctl_sctx *ctx, struct ctl_sess *sess) { + if (sess->donefunc != NULL) { + (*sess->donefunc)(ctx, sess, sess->uap); + sess->donefunc = NULL; + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/ev_connects.c b/usr/src/lib/libresolv2_joy/common/isc/ev_connects.c new file mode 100644 index 0000000000..38dfdbe512 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/ev_connects.c @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* ev_connects.c - implement asynch connect/accept for the eventlib + * vix 16sep96 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_connects.c,v 1.8 2006/03/09 23:57:56 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> + +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +/* Macros. */ + +#define GETXXXNAME(f, s, sa, len) ( \ + (f((s), (&sa), (&len)) >= 0) ? 0 : \ + (errno != EAFNOSUPPORT && errno != EOPNOTSUPP) ? -1 : ( \ + memset(&(sa), 0, sizeof (sa)), \ + (len) = sizeof (sa), \ + (sa).sa_family = AF_UNIX, \ + 0 \ + ) \ + ) + +/* Forward. */ + +static void listener(evContext ctx, void *uap, int fd, int evmask); +static void connector(evContext ctx, void *uap, int fd, int evmask); + +/* Public. */ + +int +evListen(evContext opaqueCtx, int fd, int maxconn, + evConnFunc func, void *uap, evConnID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evConn *new; + int mode; + + OKNEW(new); + new->flags = EV_CONN_LISTEN; + OKFREE(mode = fcntl(fd, F_GETFL, NULL), new); /*%< side effect: validate fd. */ + /* + * Remember the nonblocking status. We assume that either evSelectFD + * has not been done to this fd, or that if it has then the caller + * will evCancelConn before they evDeselectFD. If our assumptions + * are not met, then we might restore the old nonblocking status + * incorrectly. + */ + if ((mode & PORT_NONBLOCK) == 0) { +#ifdef USE_FIONBIO_IOCTL + int on = 1; + OKFREE(ioctl(fd, FIONBIO, (char *)&on), new); +#else + OKFREE(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK), new); +#endif + new->flags |= EV_CONN_BLOCK; + } + OKFREE(listen(fd, maxconn), new); + if (evSelectFD(opaqueCtx, fd, EV_READ, listener, new, &new->file) < 0){ + int save = errno; + + FREE(new); + errno = save; + return (-1); + } + new->flags |= EV_CONN_SELECTED; + new->func = func; + new->uap = uap; + new->fd = fd; + if (ctx->conns != NULL) + ctx->conns->prev = new; + new->prev = NULL; + new->next = ctx->conns; + ctx->conns = new; + if (id) + id->opaque = new; + return (0); +} + +int +evConnect(evContext opaqueCtx, int fd, const void *ra, int ralen, + evConnFunc func, void *uap, evConnID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evConn *new; + + OKNEW(new); + new->flags = 0; + /* Do the select() first to get the socket into nonblocking mode. */ + if (evSelectFD(opaqueCtx, fd, EV_MASK_ALL, + connector, new, &new->file) < 0) { + int save = errno; + + FREE(new); + errno = save; + return (-1); + } + new->flags |= EV_CONN_SELECTED; + if (connect(fd, ra, ralen) < 0 && + errno != EWOULDBLOCK && + errno != EAGAIN && + errno != EINPROGRESS) { + int save = errno; + + (void) evDeselectFD(opaqueCtx, new->file); + FREE(new); + errno = save; + return (-1); + } + /* No error, or EWOULDBLOCK. select() tells when it's ready. */ + new->func = func; + new->uap = uap; + new->fd = fd; + if (ctx->conns != NULL) + ctx->conns->prev = new; + new->prev = NULL; + new->next = ctx->conns; + ctx->conns = new; + if (id) + id->opaque = new; + return (0); +} + +int +evCancelConn(evContext opaqueCtx, evConnID id) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *this = id.opaque; + evAccept *acc, *nxtacc; + int mode; + + if ((this->flags & EV_CONN_SELECTED) != 0) + (void) evDeselectFD(opaqueCtx, this->file); + if ((this->flags & EV_CONN_BLOCK) != 0) { + mode = fcntl(this->fd, F_GETFL, NULL); + if (mode == -1) { + if (errno != EBADF) + return (-1); + } else { +#ifdef USE_FIONBIO_IOCTL + int off = 0; + OK(ioctl(this->fd, FIONBIO, (char *)&off)); +#else + OK(fcntl(this->fd, F_SETFL, mode & ~PORT_NONBLOCK)); +#endif + } + } + + /* Unlink from ctx->conns. */ + if (this->prev != NULL) + this->prev->next = this->next; + else + ctx->conns = this->next; + if (this->next != NULL) + this->next->prev = this->prev; + + /* + * Remove `this' from the ctx->accepts list (zero or more times). + */ + for (acc = HEAD(ctx->accepts), nxtacc = NULL; + acc != NULL; + acc = nxtacc) + { + nxtacc = NEXT(acc, link); + if (acc->conn == this) { + UNLINK(ctx->accepts, acc, link); + close(acc->fd); + FREE(acc); + } + } + + /* Wrap up and get out. */ + FREE(this); + return (0); +} + +int evHold(evContext opaqueCtx, evConnID id) { + evConn *this = id.opaque; + + if ((this->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + if ((this->flags & EV_CONN_SELECTED) == 0) + return (0); + this->flags &= ~EV_CONN_SELECTED; + return (evDeselectFD(opaqueCtx, this->file)); +} + +int evUnhold(evContext opaqueCtx, evConnID id) { + evConn *this = id.opaque; + int ret; + + if ((this->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + if ((this->flags & EV_CONN_SELECTED) != 0) + return (0); + ret = evSelectFD(opaqueCtx, this->fd, EV_READ, listener, this, + &this->file); + if (ret == 0) + this->flags |= EV_CONN_SELECTED; + return (ret); +} + +int +evTryAccept(evContext opaqueCtx, evConnID id, int *sys_errno) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = id.opaque; + evAccept *new; + + if ((conn->flags & EV_CONN_LISTEN) == 0) { + errno = EINVAL; + return (-1); + } + OKNEW(new); + new->conn = conn; + new->ralen = sizeof new->ra; + new->fd = accept(conn->fd, &new->ra.sa, &new->ralen); + if (new->fd > ctx->highestFD) { + close(new->fd); + new->fd = -1; + new->ioErrno = ENOTSOCK; + } + if (new->fd >= 0) { + new->lalen = sizeof new->la; + if (GETXXXNAME(getsockname, new->fd, new->la.sa, new->lalen) < 0) { + new->ioErrno = errno; + (void) close(new->fd); + new->fd = -1; + } else + new->ioErrno = 0; + } else { + new->ioErrno = errno; + if (errno == EAGAIN || errno == EWOULDBLOCK) { + FREE(new); + return (-1); + } + } + INIT_LINK(new, link); + APPEND(ctx->accepts, new, link); + *sys_errno = new->ioErrno; + return (0); +} + +/* Private. */ + +static void +listener(evContext opaqueCtx, void *uap, int fd, int evmask) { + evContext_p *ctx = opaqueCtx.opaque; + evConn *conn = uap; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la, ra; + int new; + ISC_SOCKLEN_T lalen = 0, ralen; + + REQUIRE((evmask & EV_READ) != 0); + ralen = sizeof ra; + new = accept(fd, &ra.sa, &ralen); + if (new > ctx->highestFD) { + close(new); + new = -1; + errno = ENOTSOCK; + } + if (new >= 0) { + lalen = sizeof la; + if (GETXXXNAME(getsockname, new, la.sa, lalen) < 0) { + int save = errno; + + (void) close(new); + errno = save; + new = -1; + } + } else if (errno == EAGAIN || errno == EWOULDBLOCK) + return; + (*conn->func)(opaqueCtx, conn->uap, new, &la.sa, lalen, &ra.sa, ralen); +} + +static void +connector(evContext opaqueCtx, void *uap, int fd, int evmask) { + evConn *conn = uap; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la, ra; + ISC_SOCKLEN_T lalen, ralen; +#ifndef NETREAD_BROKEN + char buf[1]; +#endif + void *conn_uap; + evConnFunc conn_func; + evConnID id; + int socket_errno = 0; + ISC_SOCKLEN_T optlen; + + UNUSED(evmask); + + lalen = sizeof la; + ralen = sizeof ra; + conn_uap = conn->uap; + conn_func = conn->func; + id.opaque = conn; +#ifdef SO_ERROR + optlen = sizeof socket_errno; + if (fd < 0 && + getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, (char *)&socket_errno, + &optlen) < 0) + socket_errno = errno; + else + errno = socket_errno; +#endif + if (evCancelConn(opaqueCtx, id) < 0 || + socket_errno || +#ifdef NETREAD_BROKEN + 0 || +#else + read(fd, buf, 0) < 0 || +#endif + GETXXXNAME(getsockname, fd, la.sa, lalen) < 0 || + GETXXXNAME(getpeername, fd, ra.sa, ralen) < 0) { + int save = errno; + + (void) close(fd); /*%< XXX closing caller's fd */ + errno = save; + fd = -1; + } + (*conn_func)(opaqueCtx, conn_uap, fd, &la.sa, lalen, &ra.sa, ralen); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/ev_files.c b/usr/src/lib/libresolv2_joy/common/isc/ev_files.c new file mode 100644 index 0000000000..b12baf1aaa --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/ev_files.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* ev_files.c - implement asynch file IO for the eventlib + * vix 11sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_files.c,v 1.8 2005/07/28 06:51:48 marka Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ioctl.h> + +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include "eventlib_p.h" + +#include "port_after.h" + +static evFile *FindFD(const evContext_p *ctx, int fd, int eventmask); + +int +evSelectFD(evContext opaqueCtx, + int fd, + int eventmask, + evFileFunc func, + void *uap, + evFileID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + evFile *id; + int mode; + + evPrintf(ctx, 1, + "evSelectFD(ctx %p, fd %d, mask 0x%x, func %p, uap %p)\n", + ctx, fd, eventmask, func, uap); + if (eventmask == 0 || (eventmask & ~EV_MASK_ALL) != 0) + EV_ERR(EINVAL); +#ifndef USE_POLL + if (fd > ctx->highestFD) + EV_ERR(EINVAL); +#endif + OK(mode = fcntl(fd, F_GETFL, NULL)); /*%< side effect: validate fd. */ + /* + * The first time we touch a file descriptor, we need to check to see + * if the application already had it in O_NONBLOCK mode and if so, all + * of our deselect()'s have to leave it in O_NONBLOCK. If not, then + * all but our last deselect() has to leave it in O_NONBLOCK. + */ +#ifdef USE_POLL + /* Make sure both ctx->pollfds[] and ctx->fdTable[] are large enough */ + if (fd >= ctx->maxnfds && evPollfdRealloc(ctx, 1, fd) != 0) + EV_ERR(ENOMEM); +#endif /* USE_POLL */ + id = FindFD(ctx, fd, EV_MASK_ALL); + if (id == NULL) { + if (mode & PORT_NONBLOCK) + FD_SET(fd, &ctx->nonblockBefore); + else { +#ifdef USE_FIONBIO_IOCTL + int on = 1; + OK(ioctl(fd, FIONBIO, (char *)&on)); +#else + OK(fcntl(fd, F_SETFL, mode | PORT_NONBLOCK)); +#endif + FD_CLR(fd, &ctx->nonblockBefore); + } + } + + /* + * If this descriptor is already in use, search for it again to see + * if any of the eventmask bits we want to set are already captured. + * We cannot usefully capture the same fd event more than once in the + * same context. + */ + if (id != NULL && FindFD(ctx, fd, eventmask) != NULL) + EV_ERR(ETOOMANYREFS); + + /* Allocate and fill. */ + OKNEW(id); + id->func = func; + id->uap = uap; + id->fd = fd; + id->eventmask = eventmask; + + /* + * Insert at head. Order could be important for performance if we + * believe that evGetNext()'s accesses to the fd_sets will be more + * serial and therefore more cache-lucky if the list is ordered by + * ``fd.'' We do not believe these things, so we don't do it. + * + * The interesting sequence is where GetNext() has cached a select() + * result and the caller decides to evSelectFD() on some descriptor. + * Since GetNext() starts at the head, it can miss new entries we add + * at the head. This is not a serious problem since the event being + * evSelectFD()'d for has to occur before evSelectFD() is called for + * the file event to be considered "missed" -- a real corner case. + * Maintaining a "tail" pointer for ctx->files would fix this, but I'm + * not sure it would be ``more correct.'' + */ + if (ctx->files != NULL) + ctx->files->prev = id; + id->prev = NULL; + id->next = ctx->files; + ctx->files = id; + + /* Insert into fd table. */ + if (ctx->fdTable[fd] != NULL) + ctx->fdTable[fd]->fdprev = id; + id->fdprev = NULL; + id->fdnext = ctx->fdTable[fd]; + ctx->fdTable[fd] = id; + + /* Turn on the appropriate bits in the {rd,wr,ex}Next fd_set's. */ + if (eventmask & EV_READ) + FD_SET(fd, &ctx->rdNext); + if (eventmask & EV_WRITE) + FD_SET(fd, &ctx->wrNext); + if (eventmask & EV_EXCEPT) + FD_SET(fd, &ctx->exNext); + + /* Update fdMax. */ + if (fd > ctx->fdMax) + ctx->fdMax = fd; + + /* Remember the ID if the caller provided us a place for it. */ + if (opaqueID) + opaqueID->opaque = id; + + return (0); +} + +int +evDeselectFD(evContext opaqueCtx, evFileID opaqueID) { + evContext_p *ctx = opaqueCtx.opaque; + evFile *del = opaqueID.opaque; + evFile *cur; + int mode, eventmask; + + if (!del) { + evPrintf(ctx, 11, "evDeselectFD(NULL) ignored\n"); + errno = EINVAL; + return (-1); + } + + evPrintf(ctx, 1, "evDeselectFD(fd %d, mask 0x%x)\n", + del->fd, del->eventmask); + + /* Get the mode. Unless the file has been closed, errors are bad. */ + mode = fcntl(del->fd, F_GETFL, NULL); + if (mode == -1 && errno != EBADF) + EV_ERR(errno); + + /* Remove from the list of files. */ + if (del->prev != NULL) + del->prev->next = del->next; + else + ctx->files = del->next; + if (del->next != NULL) + del->next->prev = del->prev; + + /* Remove from the fd table. */ + if (del->fdprev != NULL) + del->fdprev->fdnext = del->fdnext; + else + ctx->fdTable[del->fd] = del->fdnext; + if (del->fdnext != NULL) + del->fdnext->fdprev = del->fdprev; + + /* + * If the file descriptor does not appear in any other select() entry, + * and if !EV_WASNONBLOCK, and if we got no EBADF when we got the mode + * earlier, then: restore the fd to blocking status. + */ + if (!(cur = FindFD(ctx, del->fd, EV_MASK_ALL)) && + !FD_ISSET(del->fd, &ctx->nonblockBefore) && + mode != -1) { + /* + * Note that we won't return an error status to the caller if + * this fcntl() fails since (a) we've already done the work + * and (b) the caller didn't ask us anything about O_NONBLOCK. + */ +#ifdef USE_FIONBIO_IOCTL + int off = 0; + (void) ioctl(del->fd, FIONBIO, (char *)&off); +#else + (void) fcntl(del->fd, F_SETFL, mode & ~PORT_NONBLOCK); +#endif + } + + /* + * Now find all other uses of this descriptor and OR together an event + * mask so that we don't turn off {rd,wr,ex}Next bits that some other + * file event is using. As an optimization, stop if the event mask + * fills. + */ + eventmask = 0; + for ((void)NULL; + cur != NULL && eventmask != EV_MASK_ALL; + cur = cur->next) + if (cur->fd == del->fd) + eventmask |= cur->eventmask; + + /* OK, now we know which bits we can clear out. */ + if (!(eventmask & EV_READ)) { + FD_CLR(del->fd, &ctx->rdNext); + if (FD_ISSET(del->fd, &ctx->rdLast)) { + FD_CLR(del->fd, &ctx->rdLast); + ctx->fdCount--; + } + } + if (!(eventmask & EV_WRITE)) { + FD_CLR(del->fd, &ctx->wrNext); + if (FD_ISSET(del->fd, &ctx->wrLast)) { + FD_CLR(del->fd, &ctx->wrLast); + ctx->fdCount--; + } + } + if (!(eventmask & EV_EXCEPT)) { + FD_CLR(del->fd, &ctx->exNext); + if (FD_ISSET(del->fd, &ctx->exLast)) { + FD_CLR(del->fd, &ctx->exLast); + ctx->fdCount--; + } + } + + /* If this was the maxFD, find the new one. */ + if (del->fd == ctx->fdMax) { + ctx->fdMax = -1; + for (cur = ctx->files; cur; cur = cur->next) + if (cur->fd > ctx->fdMax) + ctx->fdMax = cur->fd; + } + + /* If this was the fdNext, cycle that to the next entry. */ + if (del == ctx->fdNext) + ctx->fdNext = del->next; + + /* Couldn't free it before now since we were using fields out of it. */ + FREE(del); + + return (0); +} + +static evFile * +FindFD(const evContext_p *ctx, int fd, int eventmask) { + evFile *id; + + for (id = ctx->fdTable[fd]; id != NULL; id = id->fdnext) + if (id->fd == fd && (id->eventmask & eventmask) != 0) + break; + return (id); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/ev_streams.c b/usr/src/lib/libresolv2_joy/common/isc/ev_streams.c new file mode 100644 index 0000000000..5dad36d04a --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/ev_streams.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* ev_streams.c - implement asynch stream file IO for the eventlib + * vix 04mar96 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_streams.c,v 1.5 2005/04/27 04:56:36 sra Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/uio.h> + +#include <errno.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +static int copyvec(evStream *str, const struct iovec *iov, int iocnt); +static void consume(evStream *str, size_t bytes); +static void done(evContext opaqueCtx, evStream *str); +static void writable(evContext opaqueCtx, void *uap, int fd, int evmask); +static void readable(evContext opaqueCtx, void *uap, int fd, int evmask); + +struct iovec +evConsIovec(void *buf, size_t cnt) { + struct iovec ret; + + memset(&ret, 0xf5, sizeof ret); + ret.iov_base = buf; + ret.iov_len = cnt; + return (ret); +} + +int +evWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, + evStreamFunc func, void *uap, evStreamID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evStream *new; + int save; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->fd = fd; + new->flags = 0; + if (evSelectFD(opaqueCtx, fd, EV_WRITE, writable, new, &new->file) < 0) + goto free; + if (copyvec(new, iov, iocnt) < 0) + goto free; + new->prevDone = NULL; + new->nextDone = NULL; + if (ctx->streams != NULL) + ctx->streams->prev = new; + new->prev = NULL; + new->next = ctx->streams; + ctx->streams = new; + if (id != NULL) + id->opaque = new; + return (0); + free: + save = errno; + FREE(new); + errno = save; + return (-1); +} + +int +evRead(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt, + evStreamFunc func, void *uap, evStreamID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evStream *new; + int save; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->fd = fd; + new->flags = 0; + if (evSelectFD(opaqueCtx, fd, EV_READ, readable, new, &new->file) < 0) + goto free; + if (copyvec(new, iov, iocnt) < 0) + goto free; + new->prevDone = NULL; + new->nextDone = NULL; + if (ctx->streams != NULL) + ctx->streams->prev = new; + new->prev = NULL; + new->next = ctx->streams; + ctx->streams = new; + if (id) + id->opaque = new; + return (0); + free: + save = errno; + FREE(new); + errno = save; + return (-1); +} + +int +evTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ { + evStream *str = id.opaque; + + UNUSED(opaqueCtx); + + str->timer = timer; + str->flags |= EV_STR_TIMEROK; + return (0); +} + +int +evUntimeRW(evContext opaqueCtx, evStreamID id) /*ARGSUSED*/ { + evStream *str = id.opaque; + + UNUSED(opaqueCtx); + + str->flags &= ~EV_STR_TIMEROK; + return (0); +} + +int +evCancelRW(evContext opaqueCtx, evStreamID id) { + evContext_p *ctx = opaqueCtx.opaque; + evStream *old = id.opaque; + + /* + * The streams list is doubly threaded. First, there's ctx->streams + * that's used by evDestroy() to find and cancel all streams. Second, + * there's ctx->strDone (head) and ctx->strLast (tail) which thread + * through the potentially smaller number of "IO completed" streams, + * used in evGetNext() to avoid scanning the entire list. + */ + + /* Unlink from ctx->streams. */ + if (old->prev != NULL) + old->prev->next = old->next; + else + ctx->streams = old->next; + if (old->next != NULL) + old->next->prev = old->prev; + + /* + * If 'old' is on the ctx->strDone list, remove it. Update + * ctx->strLast if necessary. + */ + if (old->prevDone == NULL && old->nextDone == NULL) { + /* + * Either 'old' is the only item on the done list, or it's + * not on the done list. If the former, then we unlink it + * from the list. If the latter, we leave the list alone. + */ + if (ctx->strDone == old) { + ctx->strDone = NULL; + ctx->strLast = NULL; + } + } else { + if (old->prevDone != NULL) + old->prevDone->nextDone = old->nextDone; + else + ctx->strDone = old->nextDone; + if (old->nextDone != NULL) + old->nextDone->prevDone = old->prevDone; + else + ctx->strLast = old->prevDone; + } + + /* Deallocate the stream. */ + if (old->file.opaque) + evDeselectFD(opaqueCtx, old->file); + memput(old->iovOrig, sizeof (struct iovec) * old->iovOrigCount); + FREE(old); + return (0); +} + +/* Copy a scatter/gather vector and initialize a stream handler's IO. */ +static int +copyvec(evStream *str, const struct iovec *iov, int iocnt) { + int i; + + str->iovOrig = (struct iovec *)memget(sizeof(struct iovec) * iocnt); + if (str->iovOrig == NULL) { + errno = ENOMEM; + return (-1); + } + str->ioTotal = 0; + for (i = 0; i < iocnt; i++) { + str->iovOrig[i] = iov[i]; + str->ioTotal += iov[i].iov_len; + } + str->iovOrigCount = iocnt; + str->iovCur = str->iovOrig; + str->iovCurCount = str->iovOrigCount; + str->ioDone = 0; + return (0); +} + +/* Pull off or truncate lead iovec(s). */ +static void +consume(evStream *str, size_t bytes) { + while (bytes > 0U) { + if (bytes < (size_t)str->iovCur->iov_len) { + str->iovCur->iov_len -= bytes; + str->iovCur->iov_base = (void *) + ((u_char *)str->iovCur->iov_base + bytes); + str->ioDone += bytes; + bytes = 0; + } else { + bytes -= str->iovCur->iov_len; + str->ioDone += str->iovCur->iov_len; + str->iovCur++; + str->iovCurCount--; + } + } +} + +/* Add a stream to Done list and deselect the FD. */ +static void +done(evContext opaqueCtx, evStream *str) { + evContext_p *ctx = opaqueCtx.opaque; + + if (ctx->strLast != NULL) { + str->prevDone = ctx->strLast; + ctx->strLast->nextDone = str; + ctx->strLast = str; + } else { + INSIST(ctx->strDone == NULL); + ctx->strDone = ctx->strLast = str; + } + evDeselectFD(opaqueCtx, str->file); + str->file.opaque = NULL; + /* evDrop() will call evCancelRW() on us. */ +} + +/* Dribble out some bytes on the stream. (Called by evDispatch().) */ +static void +writable(evContext opaqueCtx, void *uap, int fd, int evmask) { + evStream *str = uap; + int bytes; + + UNUSED(evmask); + + bytes = writev(fd, str->iovCur, str->iovCurCount); + if (bytes > 0) { + if ((str->flags & EV_STR_TIMEROK) != 0) + evTouchIdleTimer(opaqueCtx, str->timer); + consume(str, bytes); + } else { + if (bytes < 0 && errno != EINTR) { + str->ioDone = -1; + str->ioErrno = errno; + } + } + if (str->ioDone == -1 || str->ioDone == str->ioTotal) + done(opaqueCtx, str); +} + +/* Scoop up some bytes from the stream. (Called by evDispatch().) */ +static void +readable(evContext opaqueCtx, void *uap, int fd, int evmask) { + evStream *str = uap; + int bytes; + + UNUSED(evmask); + + bytes = readv(fd, str->iovCur, str->iovCurCount); + if (bytes > 0) { + if ((str->flags & EV_STR_TIMEROK) != 0) + evTouchIdleTimer(opaqueCtx, str->timer); + consume(str, bytes); + } else { + if (bytes == 0) + str->ioDone = 0; + else { + if (errno != EINTR) { + str->ioDone = -1; + str->ioErrno = errno; + } + } + } + if (str->ioDone <= 0 || str->ioDone == str->ioTotal) + done(opaqueCtx, str); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/ev_timers.c b/usr/src/lib/libresolv2_joy/common/isc/ev_timers.c new file mode 100644 index 0000000000..12ac2cebca --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/ev_timers.c @@ -0,0 +1,499 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* ev_timers.c - implement timers for the eventlib + * vix 09sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_timers.c,v 1.6 2005/04/27 04:56:36 sra Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <errno.h> + +#include <isc/assertions.h> +#include <isc/eventlib.h> +#include "eventlib_p.h" + +#include "port_after.h" + +/* Constants. */ + +#define MILLION 1000000 +#define BILLION 1000000000 + +/* Forward. */ + +static int due_sooner(void *, void *); +static void set_index(void *, int); +static void free_timer(void *, void *); +static void print_timer(void *, void *); +static void idle_timeout(evContext, void *, struct timespec, struct timespec); + +/* Private type. */ + +typedef struct { + evTimerFunc func; + void * uap; + struct timespec lastTouched; + struct timespec max_idle; + evTimer * timer; +} idle_timer; + +/* Public. */ + +struct timespec +evConsTime(time_t sec, long nsec) { + struct timespec x; + + x.tv_sec = sec; + x.tv_nsec = nsec; + return (x); +} + +struct timespec +evAddTime(struct timespec addend1, struct timespec addend2) { + struct timespec x; + + x.tv_sec = addend1.tv_sec + addend2.tv_sec; + x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec; + if (x.tv_nsec >= BILLION) { + x.tv_sec++; + x.tv_nsec -= BILLION; + } + return (x); +} + +struct timespec +evSubTime(struct timespec minuend, struct timespec subtrahend) { + struct timespec x; + + x.tv_sec = minuend.tv_sec - subtrahend.tv_sec; + if (minuend.tv_nsec >= subtrahend.tv_nsec) + x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec; + else { + x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec; + x.tv_sec--; + } + return (x); +} + +int +evCmpTime(struct timespec a, struct timespec b) { + long x = a.tv_sec - b.tv_sec; + + if (x == 0L) + x = a.tv_nsec - b.tv_nsec; + return (x < 0L ? (-1) : x > 0L ? (1) : (0)); +} + +struct timespec +evNowTime() { + struct timeval now; +#ifdef CLOCK_REALTIME + struct timespec tsnow; + int m = CLOCK_REALTIME; + +#ifdef CLOCK_MONOTONIC + if (__evOptMonoTime) + m = CLOCK_MONOTONIC; +#endif + if (clock_gettime(m, &tsnow) == 0) + return (tsnow); +#endif + if (gettimeofday(&now, NULL) < 0) + return (evConsTime(0, 0)); + return (evTimeSpec(now)); +} + +struct timespec +evUTCTime() { + struct timeval now; +#ifdef CLOCK_REALTIME + struct timespec tsnow; + if (clock_gettime(CLOCK_REALTIME, &tsnow) == 0) + return (tsnow); +#endif + if (gettimeofday(&now, NULL) < 0) + return (evConsTime(0, 0)); + return (evTimeSpec(now)); +} + +struct timespec +evLastEventTime(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + + return (ctx->lastEventTime); +} + +struct timespec +evTimeSpec(struct timeval tv) { + struct timespec ts; + + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; + return (ts); +} + +struct timeval +evTimeVal(struct timespec ts) { + struct timeval tv; + + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return (tv); +} + +int +evSetTimer(evContext opaqueCtx, + evTimerFunc func, + void *uap, + struct timespec due, + struct timespec inter, + evTimerID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *id; + + evPrintf(ctx, 1, +"evSetTimer(ctx %p, func %p, uap %p, due %ld.%09ld, inter %ld.%09ld)\n", + ctx, func, uap, + (long)due.tv_sec, due.tv_nsec, + (long)inter.tv_sec, inter.tv_nsec); + +#ifdef __hpux + /* + * tv_sec and tv_nsec are unsigned. + */ + if (due.tv_nsec >= BILLION) + EV_ERR(EINVAL); + + if (inter.tv_nsec >= BILLION) + EV_ERR(EINVAL); +#else + if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION) + EV_ERR(EINVAL); + + if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION) + EV_ERR(EINVAL); +#endif + + /* due={0,0} is a magic cookie meaning "now." */ + if (due.tv_sec == (time_t)0 && due.tv_nsec == 0L) + due = evNowTime(); + + /* Allocate and fill. */ + OKNEW(id); + id->func = func; + id->uap = uap; + id->due = due; + id->inter = inter; + + if (heap_insert(ctx->timers, id) < 0) + return (-1); + + /* Remember the ID if the caller provided us a place for it. */ + if (opaqueID) + opaqueID->opaque = id; + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evSetTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (0); +} + +int +evClearTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *del = id.opaque; + + if (ctx->cur != NULL && + ctx->cur->type == Timer && + ctx->cur->u.timer.this == del) { + evPrintf(ctx, 8, "deferring delete of timer (executing)\n"); + /* + * Setting the interval to zero ensures that evDrop() will + * clean up the timer. + */ + del->inter = evConsTime(0, 0); + return (0); + } + + if (heap_element(ctx->timers, del->index) != del) + EV_ERR(ENOENT); + + if (heap_delete(ctx->timers, del->index) < 0) + return (-1); + FREE(del); + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evClearTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (0); +} + +int +evConfigTimer(evContext opaqueCtx, + evTimerID id, + const char *param, + int value +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = id.opaque; + int result=0; + + UNUSED(value); + + if (heap_element(ctx->timers, timer->index) != timer) + EV_ERR(ENOENT); + + if (strcmp(param, "rate") == 0) + timer->mode |= EV_TMR_RATE; + else if (strcmp(param, "interval") == 0) + timer->mode &= ~EV_TMR_RATE; + else + EV_ERR(EINVAL); + + return (result); +} + +int +evResetTimer(evContext opaqueCtx, + evTimerID id, + evTimerFunc func, + void *uap, + struct timespec due, + struct timespec inter +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = id.opaque; + struct timespec old_due; + int result=0; + + if (heap_element(ctx->timers, timer->index) != timer) + EV_ERR(ENOENT); + +#ifdef __hpux + /* + * tv_sec and tv_nsec are unsigned. + */ + if (due.tv_nsec >= BILLION) + EV_ERR(EINVAL); + + if (inter.tv_nsec >= BILLION) + EV_ERR(EINVAL); +#else + if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION) + EV_ERR(EINVAL); + + if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION) + EV_ERR(EINVAL); +#endif + + old_due = timer->due; + + timer->func = func; + timer->uap = uap; + timer->due = due; + timer->inter = inter; + + switch (evCmpTime(due, old_due)) { + case -1: + result = heap_increased(ctx->timers, timer->index); + break; + case 0: + result = 0; + break; + case 1: + result = heap_decreased(ctx->timers, timer->index); + break; + } + + if (ctx->debug > 7) { + evPrintf(ctx, 7, "timers after evResetTimer:\n"); + (void) heap_for_each(ctx->timers, print_timer, (void *)ctx); + } + + return (result); +} + +int +evSetIdleTimer(evContext opaqueCtx, + evTimerFunc func, + void *uap, + struct timespec max_idle, + evTimerID *opaqueID +) { + evContext_p *ctx = opaqueCtx.opaque; + idle_timer *tt; + + /* Allocate and fill. */ + OKNEW(tt); + tt->func = func; + tt->uap = uap; + tt->lastTouched = ctx->lastEventTime; + tt->max_idle = max_idle; + + if (evSetTimer(opaqueCtx, idle_timeout, tt, + evAddTime(ctx->lastEventTime, max_idle), + max_idle, opaqueID) < 0) { + FREE(tt); + return (-1); + } + + tt->timer = opaqueID->opaque; + + return (0); +} + +int +evClearIdleTimer(evContext opaqueCtx, evTimerID id) { + evTimer *del = id.opaque; + idle_timer *tt = del->uap; + + FREE(tt); + return (evClearTimer(opaqueCtx, id)); +} + +int +evResetIdleTimer(evContext opaqueCtx, + evTimerID opaqueID, + evTimerFunc func, + void *uap, + struct timespec max_idle +) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *timer = opaqueID.opaque; + idle_timer *tt = timer->uap; + + tt->func = func; + tt->uap = uap; + tt->lastTouched = ctx->lastEventTime; + tt->max_idle = max_idle; + + return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt, + evAddTime(ctx->lastEventTime, max_idle), + max_idle)); +} + +int +evTouchIdleTimer(evContext opaqueCtx, evTimerID id) { + evContext_p *ctx = opaqueCtx.opaque; + evTimer *t = id.opaque; + idle_timer *tt = t->uap; + + tt->lastTouched = ctx->lastEventTime; + + return (0); +} + +/* Public to the rest of eventlib. */ + +heap_context +evCreateTimers(const evContext_p *ctx) { + + UNUSED(ctx); + + return (heap_new(due_sooner, set_index, 2048)); +} + +void +evDestroyTimers(const evContext_p *ctx) { + (void) heap_for_each(ctx->timers, free_timer, NULL); + (void) heap_free(ctx->timers); +} + +/* Private. */ + +static int +due_sooner(void *a, void *b) { + evTimer *a_timer, *b_timer; + + a_timer = a; + b_timer = b; + return (evCmpTime(a_timer->due, b_timer->due) < 0); +} + +static void +set_index(void *what, int index) { + evTimer *timer; + + timer = what; + timer->index = index; +} + +static void +free_timer(void *what, void *uap) { + evTimer *t = what; + + UNUSED(uap); + + FREE(t); +} + +static void +print_timer(void *what, void *uap) { + evTimer *cur = what; + evContext_p *ctx = uap; + + cur = what; + evPrintf(ctx, 7, + " func %p, uap %p, due %ld.%09ld, inter %ld.%09ld\n", + cur->func, cur->uap, + (long)cur->due.tv_sec, cur->due.tv_nsec, + (long)cur->inter.tv_sec, cur->inter.tv_nsec); +} + +static void +idle_timeout(evContext opaqueCtx, + void *uap, + struct timespec due, + struct timespec inter +) { + evContext_p *ctx = opaqueCtx.opaque; + idle_timer *this = uap; + struct timespec idle; + + UNUSED(due); + UNUSED(inter); + + idle = evSubTime(ctx->lastEventTime, this->lastTouched); + if (evCmpTime(idle, this->max_idle) >= 0) { + (this->func)(opaqueCtx, this->uap, this->timer->due, + this->max_idle); + /* + * Setting the interval to zero will cause the timer to + * be cleaned up in evDrop(). + */ + this->timer->inter = evConsTime(0, 0); + FREE(this); + } else { + /* evDrop() will reschedule the timer. */ + this->timer->inter = evSubTime(this->max_idle, idle); + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/ev_waits.c b/usr/src/lib/libresolv2_joy/common/isc/ev_waits.c new file mode 100644 index 0000000000..99da1526c7 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/ev_waits.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* ev_waits.c - implement deferred function calls for the eventlib + * vix 05dec95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: ev_waits.c,v 1.4 2005/04/27 04:56:36 sra Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <errno.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +/* Forward. */ + +static void print_waits(evContext_p *ctx); +static evWaitList * evNewWaitList(evContext_p *); +static void evFreeWaitList(evContext_p *, evWaitList *); +static evWaitList * evGetWaitList(evContext_p *, const void *, int); + + +/* Public. */ + +/*% + * Enter a new wait function on the queue. + */ +int +evWaitFor(evContext opaqueCtx, const void *tag, + evWaitFunc func, void *uap, evWaitID *id) +{ + evContext_p *ctx = opaqueCtx.opaque; + evWait *new; + evWaitList *wl = evGetWaitList(ctx, tag, 1); + + OKNEW(new); + new->func = func; + new->uap = uap; + new->tag = tag; + new->next = NULL; + if (wl->last != NULL) + wl->last->next = new; + else + wl->first = new; + wl->last = new; + if (id != NULL) + id->opaque = new; + if (ctx->debug >= 9) + print_waits(ctx); + return (0); +} + +/*% + * Mark runnable all waiting functions having a certain tag. + */ +int +evDo(evContext opaqueCtx, const void *tag) { + evContext_p *ctx = opaqueCtx.opaque; + evWaitList *wl = evGetWaitList(ctx, tag, 0); + evWait *first; + + if (!wl) { + errno = ENOENT; + return (-1); + } + + first = wl->first; + INSIST(first != NULL); + + if (ctx->waitDone.last != NULL) + ctx->waitDone.last->next = first; + else + ctx->waitDone.first = first; + ctx->waitDone.last = wl->last; + evFreeWaitList(ctx, wl); + + return (0); +} + +/*% + * Remove a waiting (or ready to run) function from the queue. + */ +int +evUnwait(evContext opaqueCtx, evWaitID id) { + evContext_p *ctx = opaqueCtx.opaque; + evWait *this, *prev; + evWaitList *wl; + int found = 0; + + this = id.opaque; + INSIST(this != NULL); + wl = evGetWaitList(ctx, this->tag, 0); + if (wl != NULL) { + for (prev = NULL, this = wl->first; + this != NULL; + prev = this, this = this->next) + if (this == (evWait *)id.opaque) { + found = 1; + if (prev != NULL) + prev->next = this->next; + else + wl->first = this->next; + if (wl->last == this) + wl->last = prev; + if (wl->first == NULL) + evFreeWaitList(ctx, wl); + break; + } + } + + if (!found) { + /* Maybe it's done */ + for (prev = NULL, this = ctx->waitDone.first; + this != NULL; + prev = this, this = this->next) + if (this == (evWait *)id.opaque) { + found = 1; + if (prev != NULL) + prev->next = this->next; + else + ctx->waitDone.first = this->next; + if (ctx->waitDone.last == this) + ctx->waitDone.last = prev; + break; + } + } + + if (!found) { + errno = ENOENT; + return (-1); + } + + FREE(this); + + if (ctx->debug >= 9) + print_waits(ctx); + + return (0); +} + +int +evDefer(evContext opaqueCtx, evWaitFunc func, void *uap) { + evContext_p *ctx = opaqueCtx.opaque; + evWait *new; + + OKNEW(new); + new->func = func; + new->uap = uap; + new->tag = NULL; + new->next = NULL; + if (ctx->waitDone.last != NULL) + ctx->waitDone.last->next = new; + else + ctx->waitDone.first = new; + ctx->waitDone.last = new; + if (ctx->debug >= 9) + print_waits(ctx); + return (0); +} + +/* Private. */ + +static void +print_waits(evContext_p *ctx) { + evWaitList *wl; + evWait *this; + + evPrintf(ctx, 9, "wait waiting:\n"); + for (wl = ctx->waitLists; wl != NULL; wl = wl->next) { + INSIST(wl->first != NULL); + evPrintf(ctx, 9, " tag %p:", wl->first->tag); + for (this = wl->first; this != NULL; this = this->next) + evPrintf(ctx, 9, " %p", this); + evPrintf(ctx, 9, "\n"); + } + evPrintf(ctx, 9, "wait done:"); + for (this = ctx->waitDone.first; this != NULL; this = this->next) + evPrintf(ctx, 9, " %p", this); + evPrintf(ctx, 9, "\n"); +} + +static evWaitList * +evNewWaitList(evContext_p *ctx) { + evWaitList *new; + + NEW(new); + if (new == NULL) + return (NULL); + new->first = new->last = NULL; + new->prev = NULL; + new->next = ctx->waitLists; + if (new->next != NULL) + new->next->prev = new; + ctx->waitLists = new; + return (new); +} + +static void +evFreeWaitList(evContext_p *ctx, evWaitList *this) { + + INSIST(this != NULL); + + if (this->prev != NULL) + this->prev->next = this->next; + else + ctx->waitLists = this->next; + if (this->next != NULL) + this->next->prev = this->prev; + FREE(this); +} + +static evWaitList * +evGetWaitList(evContext_p *ctx, const void *tag, int should_create) { + evWaitList *this; + + for (this = ctx->waitLists; this != NULL; this = this->next) { + if (this->first != NULL && this->first->tag == tag) + break; + } + if (this == NULL && should_create) + this = evNewWaitList(ctx); + return (this); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/eventlib.c b/usr/src/lib/libresolv2_joy/common/isc/eventlib.c new file mode 100644 index 0000000000..be4a7848b9 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/eventlib.c @@ -0,0 +1,933 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* eventlib.c - implement glue for the eventlib + * vix 09sep95 [initial] + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: eventlib.c,v 1.10 2006/03/09 23:57:56 marka Exp $"; +#endif + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/stat.h> +#ifdef SOLARIS2 +#include <limits.h> +#endif /* SOLARIS2 */ + +#include <errno.h> +#include <signal.h> +#include <stdarg.h> +#include <stdlib.h> +#include <unistd.h> + +#include <isc/eventlib.h> +#include <isc/assertions.h> +#include "eventlib_p.h" + +#include "port_after.h" + +int __evOptMonoTime; + +#ifdef USE_POLL +#define pselect Pselect +#endif /* USE_POLL */ + +/* Forward. */ + +#if defined(NEED_PSELECT) || defined(USE_POLL) +static int pselect(int, void *, void *, void *, + struct timespec *, + const sigset_t *); +#endif + +int __evOptMonoTime; + +/* Public. */ + +int +evCreate(evContext *opaqueCtx) { + evContext_p *ctx; + + /* Make sure the memory heap is initialized. */ + if (meminit(0, 0) < 0 && errno != EEXIST) + return (-1); + + OKNEW(ctx); + + /* Global. */ + ctx->cur = NULL; + + /* Debugging. */ + ctx->debug = 0; + ctx->output = NULL; + + /* Connections. */ + ctx->conns = NULL; + INIT_LIST(ctx->accepts); + + /* Files. */ + ctx->files = NULL; +#ifdef USE_POLL + ctx->pollfds = NULL; + ctx->maxnfds = 0; + ctx->firstfd = 0; + emulMaskInit(ctx, rdLast, EV_READ, 1); + emulMaskInit(ctx, rdNext, EV_READ, 0); + emulMaskInit(ctx, wrLast, EV_WRITE, 1); + emulMaskInit(ctx, wrNext, EV_WRITE, 0); + emulMaskInit(ctx, exLast, EV_EXCEPT, 1); + emulMaskInit(ctx, exNext, EV_EXCEPT, 0); + emulMaskInit(ctx, nonblockBefore, EV_WASNONBLOCKING, 0); +#endif /* USE_POLL */ + FD_ZERO(&ctx->rdNext); + FD_ZERO(&ctx->wrNext); + FD_ZERO(&ctx->exNext); + FD_ZERO(&ctx->nonblockBefore); + ctx->fdMax = -1; + ctx->fdNext = NULL; + ctx->fdCount = 0; /*%< Invalidate {rd,wr,ex}Last. */ +#ifndef USE_POLL + ctx->highestFD = FD_SETSIZE - 1; + memset(ctx->fdTable, 0, sizeof ctx->fdTable); +#else + ctx->highestFD = INT_MAX / sizeof(struct pollfd); + ctx->fdTable = NULL; +#endif /* USE_POLL */ +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastFdCount = 0; +#endif + + /* Streams. */ + ctx->streams = NULL; + ctx->strDone = NULL; + ctx->strLast = NULL; + + /* Timers. */ + ctx->lastEventTime = evNowTime(); +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastSelectTime = ctx->lastEventTime; +#endif + ctx->timers = evCreateTimers(ctx); + if (ctx->timers == NULL) + return (-1); + + /* Waits. */ + ctx->waitLists = NULL; + ctx->waitDone.first = ctx->waitDone.last = NULL; + ctx->waitDone.prev = ctx->waitDone.next = NULL; + + opaqueCtx->opaque = ctx; + return (0); +} + +void +evSetDebug(evContext opaqueCtx, int level, FILE *output) { + evContext_p *ctx = opaqueCtx.opaque; + + ctx->debug = level; + ctx->output = output; +} + +int +evDestroy(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + int revs = 424242; /*%< Doug Adams. */ + evWaitList *this_wl, *next_wl; + evWait *this_wait, *next_wait; + + /* Connections. */ + while (revs-- > 0 && ctx->conns != NULL) { + evConnID id; + + id.opaque = ctx->conns; + (void) evCancelConn(opaqueCtx, id); + } + INSIST(revs >= 0); + + /* Streams. */ + while (revs-- > 0 && ctx->streams != NULL) { + evStreamID id; + + id.opaque = ctx->streams; + (void) evCancelRW(opaqueCtx, id); + } + + /* Files. */ + while (revs-- > 0 && ctx->files != NULL) { + evFileID id; + + id.opaque = ctx->files; + (void) evDeselectFD(opaqueCtx, id); + } + INSIST(revs >= 0); + + /* Timers. */ + evDestroyTimers(ctx); + + /* Waits. */ + for (this_wl = ctx->waitLists; + revs-- > 0 && this_wl != NULL; + this_wl = next_wl) { + next_wl = this_wl->next; + for (this_wait = this_wl->first; + revs-- > 0 && this_wait != NULL; + this_wait = next_wait) { + next_wait = this_wait->next; + FREE(this_wait); + } + FREE(this_wl); + } + for (this_wait = ctx->waitDone.first; + revs-- > 0 && this_wait != NULL; + this_wait = next_wait) { + next_wait = this_wait->next; + FREE(this_wait); + } + + FREE(ctx); + return (0); +} + +int +evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) { + evContext_p *ctx = opaqueCtx.opaque; + struct timespec nextTime; + evTimer *nextTimer; + evEvent_p *new; + int x, pselect_errno, timerPast; +#ifdef EVENTLIB_TIME_CHECKS + struct timespec interval; +#endif + + /* Ensure that exactly one of EV_POLL or EV_WAIT was specified. */ + x = ((options & EV_POLL) != 0) + ((options & EV_WAIT) != 0); + if (x != 1) + EV_ERR(EINVAL); + + /* Get the time of day. We'll do this again after select() blocks. */ + ctx->lastEventTime = evNowTime(); + + again: + /* Finished accept()'s do not require a select(). */ + if (!EMPTY(ctx->accepts)) { + OKNEW(new); + new->type = Accept; + new->u.accept.this = HEAD(ctx->accepts); + UNLINK(ctx->accepts, HEAD(ctx->accepts), link); + opaqueEv->opaque = new; + return (0); + } + + /* Stream IO does not require a select(). */ + if (ctx->strDone != NULL) { + OKNEW(new); + new->type = Stream; + new->u.stream.this = ctx->strDone; + ctx->strDone = ctx->strDone->nextDone; + if (ctx->strDone == NULL) + ctx->strLast = NULL; + opaqueEv->opaque = new; + return (0); + } + + /* Waits do not require a select(). */ + if (ctx->waitDone.first != NULL) { + OKNEW(new); + new->type = Wait; + new->u.wait.this = ctx->waitDone.first; + ctx->waitDone.first = ctx->waitDone.first->next; + if (ctx->waitDone.first == NULL) + ctx->waitDone.last = NULL; + opaqueEv->opaque = new; + return (0); + } + + /* Get the status and content of the next timer. */ + if ((nextTimer = heap_element(ctx->timers, 1)) != NULL) { + nextTime = nextTimer->due; + timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); + } else + timerPast = 0; /*%< Make gcc happy. */ + evPrintf(ctx, 9, "evGetNext: fdCount %d\n", ctx->fdCount); + if (ctx->fdCount == 0) { + static const struct timespec NoTime = {0, 0L}; + enum { JustPoll, Block, Timer } m; + struct timespec t, *tp; + + /* Are there any events at all? */ + if ((options & EV_WAIT) != 0 && !nextTimer && ctx->fdMax == -1) + EV_ERR(ENOENT); + + /* Figure out what select()'s timeout parameter should be. */ + if ((options & EV_POLL) != 0) { + m = JustPoll; + t = NoTime; + tp = &t; + } else if (nextTimer == NULL) { + m = Block; + /* ``t'' unused. */ + tp = NULL; + } else if (timerPast) { + m = JustPoll; + t = NoTime; + tp = &t; + } else { + m = Timer; + /* ``t'' filled in later. */ + tp = &t; + } +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) { + interval = evSubTime(ctx->lastEventTime, + ctx->lastSelectTime); + if (interval.tv_sec > 0 || interval.tv_nsec > 0) + evPrintf(ctx, 1, + "time between pselect() %u.%09u count %d\n", + interval.tv_sec, interval.tv_nsec, + ctx->lastFdCount); + } +#endif + do { +#ifndef USE_POLL + /* XXX need to copy only the bits we are using. */ + ctx->rdLast = ctx->rdNext; + ctx->wrLast = ctx->wrNext; + ctx->exLast = ctx->exNext; +#else + /* + * The pollfd structure uses separate fields for + * the input and output events (corresponding to + * the ??Next and ??Last fd sets), so there's no + * need to copy one to the other. + */ +#endif /* USE_POLL */ + if (m == Timer) { + INSIST(tp == &t); + t = evSubTime(nextTime, ctx->lastEventTime); + } + + /* XXX should predict system's earliness and adjust. */ + x = pselect(ctx->fdMax+1, + &ctx->rdLast, &ctx->wrLast, &ctx->exLast, + tp, NULL); + pselect_errno = errno; + +#ifndef USE_POLL + evPrintf(ctx, 4, "select() returns %d (err: %s)\n", + x, (x == -1) ? strerror(errno) : "none"); +#else + evPrintf(ctx, 4, "poll() returns %d (err: %s)\n", + x, (x == -1) ? strerror(errno) : "none"); +#endif /* USE_POLL */ + /* Anything but a poll can change the time. */ + if (m != JustPoll) + ctx->lastEventTime = evNowTime(); + + /* Select() likes to finish about 10ms early. */ + } while (x == 0 && m == Timer && + evCmpTime(ctx->lastEventTime, nextTime) < 0); +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastSelectTime = ctx->lastEventTime; +#endif + if (x < 0) { + if (pselect_errno == EINTR) { + if ((options & EV_NULL) != 0) + goto again; + OKNEW(new); + new->type = Null; + /* No data. */ + opaqueEv->opaque = new; + return (0); + } + if (pselect_errno == EBADF) { + for (x = 0; x <= ctx->fdMax; x++) { + struct stat sb; + + if (FD_ISSET(x, &ctx->rdNext) == 0 && + FD_ISSET(x, &ctx->wrNext) == 0 && + FD_ISSET(x, &ctx->exNext) == 0) + continue; + if (fstat(x, &sb) == -1 && + errno == EBADF) + evPrintf(ctx, 1, "EBADF: %d\n", + x); + } + abort(); + } + EV_ERR(pselect_errno); + } + if (x == 0 && (nextTimer == NULL || !timerPast) && + (options & EV_POLL)) + EV_ERR(EWOULDBLOCK); + ctx->fdCount = x; +#ifdef EVENTLIB_TIME_CHECKS + ctx->lastFdCount = x; +#endif + } + INSIST(nextTimer || ctx->fdCount); + + /* Timers go first since we'd like them to be accurate. */ + if (nextTimer && !timerPast) { + /* Has anything happened since we blocked? */ + timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); + } + if (nextTimer && timerPast) { + OKNEW(new); + new->type = Timer; + new->u.timer.this = nextTimer; + opaqueEv->opaque = new; + return (0); + } + + /* No timers, so there should be a ready file descriptor. */ + x = 0; + while (ctx->fdCount > 0) { + evFile *fid; + int fd, eventmask; + + if (ctx->fdNext == NULL) { + if (++x == 2) { + /* + * Hitting the end twice means that the last + * select() found some FD's which have since + * been deselected. + * + * On some systems, the count returned by + * selects is the total number of bits in + * all masks that are set, and on others it's + * the number of fd's that have some bit set, + * and on others, it's just broken. We + * always assume that it's the number of + * bits set in all masks, because that's what + * the man page says it should do, and + * the worst that can happen is we do an + * extra select(). + */ + ctx->fdCount = 0; + break; + } + ctx->fdNext = ctx->files; + } + fid = ctx->fdNext; + ctx->fdNext = fid->next; + + fd = fid->fd; + eventmask = 0; + if (FD_ISSET(fd, &ctx->rdLast)) + eventmask |= EV_READ; + if (FD_ISSET(fd, &ctx->wrLast)) + eventmask |= EV_WRITE; + if (FD_ISSET(fd, &ctx->exLast)) + eventmask |= EV_EXCEPT; + eventmask &= fid->eventmask; + if (eventmask != 0) { + if ((eventmask & EV_READ) != 0) { + FD_CLR(fd, &ctx->rdLast); + ctx->fdCount--; + } + if ((eventmask & EV_WRITE) != 0) { + FD_CLR(fd, &ctx->wrLast); + ctx->fdCount--; + } + if ((eventmask & EV_EXCEPT) != 0) { + FD_CLR(fd, &ctx->exLast); + ctx->fdCount--; + } + OKNEW(new); + new->type = File; + new->u.file.this = fid; + new->u.file.eventmask = eventmask; + opaqueEv->opaque = new; + return (0); + } + } + if (ctx->fdCount < 0) { + /* + * select()'s count is off on a number of systems, and + * can result in fdCount < 0. + */ + evPrintf(ctx, 4, "fdCount < 0 (%d)\n", ctx->fdCount); + ctx->fdCount = 0; + } + + /* We get here if the caller deselect()'s an FD. Gag me with a goto. */ + goto again; +} + +int +evDispatch(evContext opaqueCtx, evEvent opaqueEv) { + evContext_p *ctx = opaqueCtx.opaque; + evEvent_p *ev = opaqueEv.opaque; +#ifdef EVENTLIB_TIME_CHECKS + void *func; + struct timespec start_time; + struct timespec interval; +#endif + +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) + start_time = evNowTime(); +#endif + ctx->cur = ev; + switch (ev->type) { + case Accept: { + evAccept *this = ev->u.accept.this; + + evPrintf(ctx, 5, + "Dispatch.Accept: fd %d -> %d, func %p, uap %p\n", + this->conn->fd, this->fd, + this->conn->func, this->conn->uap); + errno = this->ioErrno; + (this->conn->func)(opaqueCtx, this->conn->uap, this->fd, + &this->la, this->lalen, + &this->ra, this->ralen); +#ifdef EVENTLIB_TIME_CHECKS + func = this->conn->func; +#endif + break; + } + case File: { + evFile *this = ev->u.file.this; + int eventmask = ev->u.file.eventmask; + + evPrintf(ctx, 5, + "Dispatch.File: fd %d, mask 0x%x, func %p, uap %p\n", + this->fd, this->eventmask, this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->fd, eventmask); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Stream: { + evStream *this = ev->u.stream.this; + + evPrintf(ctx, 5, + "Dispatch.Stream: fd %d, func %p, uap %p\n", + this->fd, this->func, this->uap); + errno = this->ioErrno; + (this->func)(opaqueCtx, this->uap, this->fd, this->ioDone); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Timer: { + evTimer *this = ev->u.timer.this; + + evPrintf(ctx, 5, "Dispatch.Timer: func %p, uap %p\n", + this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->due, this->inter); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Wait: { + evWait *this = ev->u.wait.this; + + evPrintf(ctx, 5, + "Dispatch.Wait: tag %p, func %p, uap %p\n", + this->tag, this->func, this->uap); + (this->func)(opaqueCtx, this->uap, this->tag); +#ifdef EVENTLIB_TIME_CHECKS + func = this->func; +#endif + break; + } + case Null: { + /* No work. */ +#ifdef EVENTLIB_TIME_CHECKS + func = NULL; +#endif + break; + } + default: { + abort(); + } + } +#ifdef EVENTLIB_TIME_CHECKS + if (ctx->debug > 0) { + interval = evSubTime(evNowTime(), start_time); + /* + * Complain if it took longer than 50 milliseconds. + * + * We call getuid() to make an easy to find mark in a kernel + * trace. + */ + if (interval.tv_sec > 0 || interval.tv_nsec > 50000000) + evPrintf(ctx, 1, + "dispatch interval %u.%09u uid %d type %d func %p\n", + interval.tv_sec, interval.tv_nsec, + getuid(), ev->type, func); + } +#endif + ctx->cur = NULL; + evDrop(opaqueCtx, opaqueEv); + return (0); +} + +void +evDrop(evContext opaqueCtx, evEvent opaqueEv) { + evContext_p *ctx = opaqueCtx.opaque; + evEvent_p *ev = opaqueEv.opaque; + + switch (ev->type) { + case Accept: { + FREE(ev->u.accept.this); + break; + } + case File: { + /* No work. */ + break; + } + case Stream: { + evStreamID id; + + id.opaque = ev->u.stream.this; + (void) evCancelRW(opaqueCtx, id); + break; + } + case Timer: { + evTimer *this = ev->u.timer.this; + evTimerID opaque; + + /* Check to see whether the user func cleared the timer. */ + if (heap_element(ctx->timers, this->index) != this) { + evPrintf(ctx, 5, "Dispatch.Timer: timer rm'd?\n"); + break; + } + /* + * Timer is still there. Delete it if it has expired, + * otherwise set it according to its next interval. + */ + if (this->inter.tv_sec == (time_t)0 && + this->inter.tv_nsec == 0L) { + opaque.opaque = this; + (void) evClearTimer(opaqueCtx, opaque); + } else { + opaque.opaque = this; + (void) evResetTimer(opaqueCtx, opaque, this->func, + this->uap, + evAddTime((this->mode & EV_TMR_RATE) ? + this->due : + ctx->lastEventTime, + this->inter), + this->inter); + } + break; + } + case Wait: { + FREE(ev->u.wait.this); + break; + } + case Null: { + /* No work. */ + break; + } + default: { + abort(); + } + } + FREE(ev); +} + +int +evMainLoop(evContext opaqueCtx) { + evEvent event; + int x; + + while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) + if ((x = evDispatch(opaqueCtx, event)) < 0) + break; + return (x); +} + +int +evHighestFD(evContext opaqueCtx) { + evContext_p *ctx = opaqueCtx.opaque; + + return (ctx->highestFD); +} + +void +evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + if (ctx->output != NULL && ctx->debug >= level) { + vfprintf(ctx->output, fmt, ap); + fflush(ctx->output); + } + va_end(ap); +} + +int +evSetOption(evContext *opaqueCtx, const char *option, int value) { + /* evContext_p *ctx = opaqueCtx->opaque; */ + + UNUSED(opaqueCtx); + UNUSED(value); +#ifndef CLOCK_MONOTONIC + UNUSED(option); +#endif + +#ifdef CLOCK_MONOTONIC + if (strcmp(option, "monotime") == 0) { + if (opaqueCtx != NULL) + errno = EINVAL; + if (value == 0 || value == 1) { + __evOptMonoTime = value; + return (0); + } else { + errno = EINVAL; + return (-1); + } + } +#endif + errno = ENOENT; + return (-1); +} + +int +evGetOption(evContext *opaqueCtx, const char *option, int *value) { + /* evContext_p *ctx = opaqueCtx->opaque; */ + + UNUSED(opaqueCtx); +#ifndef CLOCK_MONOTONIC + UNUSED(value); + UNUSED(option); +#endif + +#ifdef CLOCK_MONOTONIC + if (strcmp(option, "monotime") == 0) { + if (opaqueCtx != NULL) + errno = EINVAL; + *value = __evOptMonoTime; + return (0); + } +#endif + errno = ENOENT; + return (-1); +} + +#if defined(NEED_PSELECT) || defined(USE_POLL) +/* XXX needs to move to the porting library. */ +static int +pselect(int nfds, void *rfds, void *wfds, void *efds, + struct timespec *tsp, + const sigset_t *sigmask) +{ + struct timeval tv, *tvp; + sigset_t sigs; + int n; +#ifdef USE_POLL + int polltimeout = INFTIM; + evContext_p *ctx; + struct pollfd *fds; + nfds_t pnfds; + + UNUSED(nfds); +#endif /* USE_POLL */ + + if (tsp) { + tvp = &tv; + tv = evTimeVal(*tsp); +#ifdef USE_POLL + polltimeout = 1000 * tv.tv_sec + tv.tv_usec / 1000; +#endif /* USE_POLL */ + } else + tvp = NULL; + if (sigmask) + sigprocmask(SIG_SETMASK, sigmask, &sigs); +#ifndef USE_POLL + n = select(nfds, rfds, wfds, efds, tvp); +#else + /* + * rfds, wfds, and efds should all be from the same evContext_p, + * so any of them will do. If they're all NULL, the caller is + * presumably calling us to block. + */ + if (rfds != NULL) + ctx = ((__evEmulMask *)rfds)->ctx; + else if (wfds != NULL) + ctx = ((__evEmulMask *)wfds)->ctx; + else if (efds != NULL) + ctx = ((__evEmulMask *)efds)->ctx; + else + ctx = NULL; + if (ctx != NULL && ctx->fdMax != -1) { + fds = &(ctx->pollfds[ctx->firstfd]); + pnfds = ctx->fdMax - ctx->firstfd + 1; + } else { + fds = NULL; + pnfds = 0; + } + n = poll(fds, pnfds, polltimeout); + if (n > 0) { + int i, e; + + INSIST(ctx != NULL); + for (e = 0, i = ctx->firstfd; i <= ctx->fdMax; i++) { + if (ctx->pollfds[i].fd < 0) + continue; + if (FD_ISSET(i, &ctx->rdLast)) + e++; + if (FD_ISSET(i, &ctx->wrLast)) + e++; + if (FD_ISSET(i, &ctx->exLast)) + e++; + } + n = e; + } +#endif /* USE_POLL */ + if (sigmask) + sigprocmask(SIG_SETMASK, &sigs, NULL); + if (tsp) + *tsp = evTimeSpec(tv); + return (n); +} +#endif + +#ifdef USE_POLL +int +evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd) { + + int i, maxnfds; + void *pollfds, *fdTable; + + if (fd < ctx->maxnfds) + return (0); + + /* Don't allow ridiculously small values for pollfd_chunk_size */ + if (pollfd_chunk_size < 20) + pollfd_chunk_size = 20; + + maxnfds = (1 + (fd/pollfd_chunk_size)) * pollfd_chunk_size; + + pollfds = realloc(ctx->pollfds, maxnfds * sizeof(*ctx->pollfds)); + if (pollfds != NULL) + ctx->pollfds = pollfds; + fdTable = realloc(ctx->fdTable, maxnfds * sizeof(*ctx->fdTable)); + if (fdTable != NULL) + ctx->fdTable = fdTable; + + if (pollfds == NULL || fdTable == NULL) { + evPrintf(ctx, 2, "pollfd() realloc (%ld) failed\n", + (long)maxnfds*sizeof(struct pollfd)); + return (-1); + } + + for (i = ctx->maxnfds; i < maxnfds; i++) { + ctx->pollfds[i].fd = -1; + ctx->pollfds[i].events = 0; + ctx->fdTable[i] = 0; + } + + ctx->maxnfds = maxnfds; + + return (0); +} + +/* Find the appropriate 'events' or 'revents' field in the pollfds array */ +short * +__fd_eventfield(int fd, __evEmulMask *maskp) { + + evContext_p *ctx = (evContext_p *)maskp->ctx; + + if (!maskp->result || maskp->type == EV_WASNONBLOCKING) + return (&(ctx->pollfds[fd].events)); + else + return (&(ctx->pollfds[fd].revents)); +} + +/* Translate to poll(2) event */ +short +__poll_event(__evEmulMask *maskp) { + + switch ((maskp)->type) { + case EV_READ: + return (POLLRDNORM); + case EV_WRITE: + return (POLLWRNORM); + case EV_EXCEPT: + return (POLLRDBAND | POLLPRI | POLLWRBAND); + case EV_WASNONBLOCKING: + return (POLLHUP); + default: + return (0); + } +} + +/* + * Clear the events corresponding to the specified mask. If this leaves + * the events mask empty (apart from the POLLHUP bit), set the fd field + * to -1 so that poll(2) will ignore this fd. + */ +void +__fd_clr(int fd, __evEmulMask *maskp) { + + evContext_p *ctx = maskp->ctx; + + *__fd_eventfield(fd, maskp) &= ~__poll_event(maskp); + if ((ctx->pollfds[fd].events & ~POLLHUP) == 0) { + ctx->pollfds[fd].fd = -1; + if (fd == ctx->fdMax) + while (ctx->fdMax > ctx->firstfd && + ctx->pollfds[ctx->fdMax].fd < 0) + ctx->fdMax--; + if (fd == ctx->firstfd) + while (ctx->firstfd <= ctx->fdMax && + ctx->pollfds[ctx->firstfd].fd < 0) + ctx->firstfd++; + /* + * Do we have a empty set of descriptors? + */ + if (ctx->firstfd > ctx->fdMax) { + ctx->fdMax = -1; + ctx->firstfd = 0; + } + } +} + +/* + * Set the events bit(s) corresponding to the specified mask. If the events + * field has any other bits than POLLHUP set, also set the fd field so that + * poll(2) will watch this fd. + */ +void +__fd_set(int fd, __evEmulMask *maskp) { + + evContext_p *ctx = maskp->ctx; + + *__fd_eventfield(fd, maskp) |= __poll_event(maskp); + if ((ctx->pollfds[fd].events & ~POLLHUP) != 0) { + ctx->pollfds[fd].fd = fd; + if (fd < ctx->firstfd || ctx->fdMax == -1) + ctx->firstfd = fd; + if (fd > ctx->fdMax) + ctx->fdMax = fd; + } +} +#endif /* USE_POLL */ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/eventlib_p.h b/usr/src/lib/libresolv2_joy/common/isc/eventlib_p.h new file mode 100644 index 0000000000..0a3614ab23 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/eventlib_p.h @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*! \file + * \brief private interfaces for eventlib + * \author vix 09sep95 [initial] + * + * $Id: eventlib_p.h,v 1.9 2006/03/09 23:57:56 marka Exp $ + */ + +#ifndef _EVENTLIB_P_H +#define _EVENTLIB_P_H + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/un.h> + +#define EVENTLIB_DEBUG 1 + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/heap.h> +#include <isc/list.h> +#include <isc/memcluster.h> + +#define EV_MASK_ALL (EV_READ | EV_WRITE | EV_EXCEPT) +#define EV_ERR(e) return (errno = (e), -1) +#define OK(x) if ((x) < 0) EV_ERR(errno); else (void)NULL +#define OKFREE(x, y) if ((x) < 0) { FREE((y)); EV_ERR(errno); } \ + else (void)NULL + +#define NEW(p) if (((p) = memget(sizeof *(p))) != NULL) \ + FILL(p); \ + else \ + (void)NULL; +#define OKNEW(p) if (!((p) = memget(sizeof *(p)))) { \ + errno = ENOMEM; \ + return (-1); \ + } else \ + FILL(p) +#define FREE(p) memput((p), sizeof *(p)) + +#if EVENTLIB_DEBUG +#define FILL(p) memset((p), 0xF5, sizeof *(p)) +#else +#define FILL(p) +#endif + +#ifdef USE_POLL +#ifdef HAVE_STROPTS_H +#include <stropts.h> +#endif +#include <poll.h> +#endif /* USE_POLL */ + +typedef struct evConn { + evConnFunc func; + void * uap; + int fd; + int flags; +#define EV_CONN_LISTEN 0x0001 /*%< Connection is a listener. */ +#define EV_CONN_SELECTED 0x0002 /*%< evSelectFD(conn->file). */ +#define EV_CONN_BLOCK 0x0004 /*%< Listener fd was blocking. */ + evFileID file; + struct evConn * prev; + struct evConn * next; +} evConn; + +typedef struct evAccept { + int fd; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } la; + ISC_SOCKLEN_T lalen; + union { + struct sockaddr sa; + struct sockaddr_in in; +#ifndef NO_SOCKADDR_UN + struct sockaddr_un un; +#endif + } ra; + ISC_SOCKLEN_T ralen; + int ioErrno; + evConn * conn; + LINK(struct evAccept) link; +} evAccept; + +typedef struct evFile { + evFileFunc func; + void * uap; + int fd; + int eventmask; + int preemptive; + struct evFile * prev; + struct evFile * next; + struct evFile * fdprev; + struct evFile * fdnext; +} evFile; + +typedef struct evStream { + evStreamFunc func; + void * uap; + evFileID file; + evTimerID timer; + int flags; +#define EV_STR_TIMEROK 0x0001 /*%< IFF timer valid. */ + int fd; + struct iovec * iovOrig; + int iovOrigCount; + struct iovec * iovCur; + int iovCurCount; + int ioTotal; + int ioDone; + int ioErrno; + struct evStream *prevDone, *nextDone; + struct evStream *prev, *next; +} evStream; + +typedef struct evTimer { + evTimerFunc func; + void * uap; + struct timespec due, inter; + int index; + int mode; +#define EV_TMR_RATE 1 +} evTimer; + +typedef struct evWait { + evWaitFunc func; + void * uap; + const void * tag; + struct evWait * next; +} evWait; + +typedef struct evWaitList { + evWait * first; + evWait * last; + struct evWaitList * prev; + struct evWaitList * next; +} evWaitList; + +typedef struct evEvent_p { + enum { Accept, File, Stream, Timer, Wait, Free, Null } type; + union { + struct { evAccept *this; } accept; + struct { evFile *this; int eventmask; } file; + struct { evStream *this; } stream; + struct { evTimer *this; } timer; + struct { evWait *this; } wait; + struct { struct evEvent_p *next; } free; + struct { const void *placeholder; } null; + } u; +} evEvent_p; + +#ifdef USE_POLL +typedef struct { + void *ctx; /* pointer to the evContext_p */ + uint32_t type; /* READ, WRITE, EXCEPT, nonblk */ + uint32_t result; /* 1 => revents, 0 => events */ +} __evEmulMask; + +#define emulMaskInit(ctx, field, ev, lastnext) \ + ctx->field.ctx = ctx; \ + ctx->field.type = ev; \ + ctx->field.result = lastnext; + +extern short *__fd_eventfield(int fd, __evEmulMask *maskp); +extern short __poll_event(__evEmulMask *maskp); +extern void __fd_clr(int fd, __evEmulMask *maskp); +extern void __fd_set(int fd, __evEmulMask *maskp); + +#undef FD_ZERO +#define FD_ZERO(maskp) + +#undef FD_SET +#define FD_SET(fd, maskp) \ + __fd_set(fd, maskp) + +#undef FD_CLR +#define FD_CLR(fd, maskp) \ + __fd_clr(fd, maskp) + +#undef FD_ISSET +#define FD_ISSET(fd, maskp) \ + ((*__fd_eventfield(fd, maskp) & __poll_event(maskp)) != 0) + +#endif /* USE_POLL */ + +typedef struct { + /* Global. */ + const evEvent_p *cur; + /* Debugging. */ + int debug; + FILE *output; + /* Connections. */ + evConn *conns; + LIST(evAccept) accepts; + /* Files. */ + evFile *files, *fdNext; +#ifndef USE_POLL + fd_set rdLast, rdNext; + fd_set wrLast, wrNext; + fd_set exLast, exNext; + fd_set nonblockBefore; + int fdMax, fdCount, highestFD; + evFile *fdTable[FD_SETSIZE]; +#else + struct pollfd *pollfds; /* Allocated as needed */ + evFile **fdTable; /* Ditto */ + int maxnfds; /* # elements in above */ + int firstfd; /* First active fd */ + int fdMax; /* Last active fd */ + int fdCount; /* # fd:s with I/O */ + int highestFD; /* max fd allowed by OS */ + __evEmulMask rdLast, rdNext; + __evEmulMask wrLast, wrNext; + __evEmulMask exLast, exNext; + __evEmulMask nonblockBefore; +#endif /* USE_POLL */ +#ifdef EVENTLIB_TIME_CHECKS + struct timespec lastSelectTime; + int lastFdCount; +#endif + /* Streams. */ + evStream *streams; + evStream *strDone, *strLast; + /* Timers. */ + struct timespec lastEventTime; + heap_context timers; + /* Waits. */ + evWaitList *waitLists; + evWaitList waitDone; +} evContext_p; + +/* eventlib.c */ +#define evPrintf __evPrintf +void evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) + ISC_FORMAT_PRINTF(3, 4); + +#ifdef USE_POLL +extern int evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd); +#endif /* USE_POLL */ + +/* ev_timers.c */ +#define evCreateTimers __evCreateTimers +heap_context evCreateTimers(const evContext_p *); +#define evDestroyTimers __evDestroyTimers +void evDestroyTimers(const evContext_p *); + +/* ev_waits.c */ +#define evFreeWait __evFreeWait +evWait *evFreeWait(evContext_p *ctx, evWait *old); + +/* Global options */ +extern int __evOptMonoTime; + +#endif /*_EVENTLIB_P_H*/ diff --git a/usr/src/lib/libresolv2_joy/common/isc/heap.c b/usr/src/lib/libresolv2_joy/common/isc/heap.c new file mode 100644 index 0000000000..3d22b6fc71 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/heap.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1997,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*% + * Heap implementation of priority queues adapted from the following: + * + * _Introduction to Algorithms_, Cormen, Leiserson, and Rivest, + * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7. + * + * _Algorithms_, Second Edition, Sedgewick, Addison-Wesley, 1988, + * ISBN 0-201-06673-4, chapter 11. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: heap.c,v 1.4 2006/03/09 23:57:56 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <stddef.h> +#include <stdlib.h> +#include <errno.h> + +#include "port_after.h" + +#include <isc/heap.h> + +/*% + * Note: to make heap_parent and heap_left easy to compute, the first + * element of the heap array is not used; i.e. heap subscripts are 1-based, + * not 0-based. + */ +#define heap_parent(i) ((i) >> 1) +#define heap_left(i) ((i) << 1) + +#define ARRAY_SIZE_INCREMENT 512 + +heap_context +heap_new(heap_higher_priority_func higher_priority, heap_index_func index, + int array_size_increment) { + heap_context ctx; + + if (higher_priority == NULL) + return (NULL); + + ctx = (heap_context)malloc(sizeof (struct heap_context)); + if (ctx == NULL) + return (NULL); + + ctx->array_size = 0; + if (array_size_increment == 0) + ctx->array_size_increment = ARRAY_SIZE_INCREMENT; + else + ctx->array_size_increment = array_size_increment; + ctx->heap_size = 0; + ctx->heap = NULL; + ctx->higher_priority = higher_priority; + ctx->index = index; + return (ctx); +} + +int +heap_free(heap_context ctx) { + if (ctx == NULL) { + errno = EINVAL; + return (-1); + } + + if (ctx->heap != NULL) + free(ctx->heap); + free(ctx); + + return (0); +} + +static int +heap_resize(heap_context ctx) { + void **new_heap; + + ctx->array_size += ctx->array_size_increment; + new_heap = (void **)realloc(ctx->heap, + (ctx->array_size) * (sizeof (void *))); + if (new_heap == NULL) { + errno = ENOMEM; + return (-1); + } + ctx->heap = new_heap; + return (0); +} + +static void +float_up(heap_context ctx, int i, void *elt) { + int p; + + for ( p = heap_parent(i); + i > 1 && ctx->higher_priority(elt, ctx->heap[p]); + i = p, p = heap_parent(i) ) { + ctx->heap[i] = ctx->heap[p]; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); + } + ctx->heap[i] = elt; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); +} + +static void +sink_down(heap_context ctx, int i, void *elt) { + int j, size, half_size; + + size = ctx->heap_size; + half_size = size / 2; + while (i <= half_size) { + /* find smallest of the (at most) two children */ + j = heap_left(i); + if (j < size && ctx->higher_priority(ctx->heap[j+1], + ctx->heap[j])) + j++; + if (ctx->higher_priority(elt, ctx->heap[j])) + break; + ctx->heap[i] = ctx->heap[j]; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); + i = j; + } + ctx->heap[i] = elt; + if (ctx->index != NULL) + (ctx->index)(ctx->heap[i], i); +} + +int +heap_insert(heap_context ctx, void *elt) { + int i; + + if (ctx == NULL || elt == NULL) { + errno = EINVAL; + return (-1); + } + + i = ++ctx->heap_size; + if (ctx->heap_size >= ctx->array_size && heap_resize(ctx) < 0) + return (-1); + + float_up(ctx, i, elt); + + return (0); +} + +int +heap_delete(heap_context ctx, int i) { + void *elt; + int less; + + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + if (i == ctx->heap_size) { + ctx->heap_size--; + } else { + elt = ctx->heap[ctx->heap_size--]; + less = ctx->higher_priority(elt, ctx->heap[i]); + ctx->heap[i] = elt; + if (less) + float_up(ctx, i, ctx->heap[i]); + else + sink_down(ctx, i, ctx->heap[i]); + } + + return (0); +} + +int +heap_increased(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + float_up(ctx, i, ctx->heap[i]); + + return (0); +} + +int +heap_decreased(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (-1); + } + + sink_down(ctx, i, ctx->heap[i]); + + return (0); +} + +void * +heap_element(heap_context ctx, int i) { + if (ctx == NULL || i < 1 || i > ctx->heap_size) { + errno = EINVAL; + return (NULL); + } + + return (ctx->heap[i]); +} + +int +heap_for_each(heap_context ctx, heap_for_each_func action, void *uap) { + int i; + + if (ctx == NULL || action == NULL) { + errno = EINVAL; + return (-1); + } + + for (i = 1; i <= ctx->heap_size; i++) + (action)(ctx->heap[i], uap); + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/hex.c b/usr/src/lib/libresolv2_joy/common/isc/hex.c new file mode 100644 index 0000000000..e43be4f3b5 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/hex.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2001 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#include <port_before.h> +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <isc/misc.h> +#include <port_after.h> + +static const char hex[17] = "0123456789abcdef"; + +int +isc_gethexstring(unsigned char *buf, size_t len, int count, FILE *fp, + int *multiline) +{ + int c, n; + unsigned char x; + char *s; + int result = count; + + x = 0; /*%< silence compiler */ + n = 0; + while (count > 0) { + c = fgetc(fp); + + if ((c == EOF) || + (c == '\n' && !*multiline) || + (c == '(' && *multiline) || + (c == ')' && !*multiline)) + goto formerr; + /* comment */ + if (c == ';') { + do { + c = fgetc(fp); + } while (c != EOF && c != '\n'); + if (c == '\n' && *multiline) + continue; + goto formerr; + } + /* white space */ + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') + continue; + /* multiline */ + if ('(' == c || c == ')') { + *multiline = (c == '(' /*)*/); + continue; + } + if ((s = strchr(hex, tolower(c))) == NULL) + goto formerr; + x = (x<<4) | (s - hex); + if (++n == 2) { + if (len > 0U) { + *buf++ = x; + len--; + } else + result = -1; + count--; + n = 0; + } + } + return (result); + + formerr: + if (c == '\n') + ungetc(c, fp); + return (-1); +} + +void +isc_puthexstring(FILE *fp, const unsigned char *buf, size_t buflen, + size_t len1, size_t len2, const char *sep) +{ + size_t i = 0; + + if (len1 < 4U) + len1 = 4; + if (len2 < 4U) + len2 = 4; + while (buflen > 0U) { + fputc(hex[(buf[0]>>4)&0xf], fp); + fputc(hex[buf[0]&0xf], fp); + i += 2; + buflen--; + buf++; + if (i >= len1 && sep != NULL) { + fputs(sep, fp); + i = 0; + len1 = len2; + } + } +} + +void +isc_tohex(const unsigned char *buf, size_t buflen, char *t) { + while (buflen > 0U) { + *t++ = hex[(buf[0]>>4)&0xf]; + *t++ = hex[buf[0]&0xf]; + buf++; + buflen--; + } + *t = '\0'; +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/logging.c b/usr/src/lib/libresolv2_joy/common/isc/logging.c new file mode 100644 index 0000000000..8c2af2b9e3 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/logging.c @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1996-1999, 2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: logging.c,v 1.9 2008/11/14 02:36:51 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/stat.h> + +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <syslog.h> +#include <errno.h> +#include <time.h> +#include <unistd.h> + +#include <isc/assertions.h> +#include <isc/logging.h> +#include <isc/memcluster.h> +#include <isc/misc.h> + +#include "port_after.h" + +#include "logging_p.h" + +static const int syslog_priority[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, + LOG_WARNING, LOG_ERR, LOG_CRIT }; + +static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +static const char *level_text[] = { + "info: ", "notice: ", "warning: ", "error: ", "critical: " +}; + +static void +version_rename(log_channel chan) { + unsigned int ver; + char old_name[PATH_MAX+1]; + char new_name[PATH_MAX+1]; + + ver = chan->out.file.versions; + if (ver < 1) + return; + if (ver > LOG_MAX_VERSIONS) + ver = LOG_MAX_VERSIONS; + /* + * Need to have room for '.nn' (XXX assumes LOG_MAX_VERSIONS < 100) + */ + if (strlen(chan->out.file.name) > (size_t)(PATH_MAX-3)) + return; + for (ver--; ver > 0; ver--) { + sprintf(old_name, "%s.%d", chan->out.file.name, ver-1); + sprintf(new_name, "%s.%d", chan->out.file.name, ver); + (void)isc_movefile(old_name, new_name); + } + sprintf(new_name, "%s.0", chan->out.file.name); + (void)isc_movefile(chan->out.file.name, new_name); +} + +FILE * +log_open_stream(log_channel chan) { + FILE *stream; + int fd, flags; + struct stat sb; + int regular; + + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + + /* + * Don't open already open streams + */ + if (chan->out.file.stream != NULL) + return (chan->out.file.stream); + + if (stat(chan->out.file.name, &sb) < 0) { + if (errno != ENOENT) { + syslog(LOG_ERR, + "log_open_stream: stat of %s failed: %s", + chan->out.file.name, strerror(errno)); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + regular = 1; + } else + regular = (sb.st_mode & S_IFREG); + + if (chan->out.file.versions) { + if (!regular) { + syslog(LOG_ERR, + "log_open_stream: want versions but %s isn't a regular file", + chan->out.file.name); + chan->flags |= LOG_CHANNEL_BROKEN; + errno = EINVAL; + return (NULL); + } + } + + flags = O_WRONLY|O_CREAT|O_APPEND; + + if ((chan->flags & LOG_TRUNCATE) != 0) { + if (regular) { + (void)unlink(chan->out.file.name); + flags |= O_EXCL; + } else { + syslog(LOG_ERR, + "log_open_stream: want truncation but %s isn't a regular file", + chan->out.file.name); + chan->flags |= LOG_CHANNEL_BROKEN; + errno = EINVAL; + return (NULL); + } + } + + fd = open(chan->out.file.name, flags, + S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + if (fd < 0) { + syslog(LOG_ERR, "log_open_stream: open(%s) failed: %s", + chan->out.file.name, strerror(errno)); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + stream = fdopen(fd, "a"); + if (stream == NULL) { + syslog(LOG_ERR, "log_open_stream: fdopen() failed"); + chan->flags |= LOG_CHANNEL_BROKEN; + return (NULL); + } + (void) fchown(fd, chan->out.file.owner, chan->out.file.group); + + chan->out.file.stream = stream; + return (stream); +} + +int +log_close_stream(log_channel chan) { + FILE *stream; + + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (0); + } + stream = chan->out.file.stream; + chan->out.file.stream = NULL; + if (stream != NULL && fclose(stream) == EOF) + return (-1); + return (0); +} + +void +log_close_debug_channels(log_context lc) { + log_channel_list lcl; + int i; + + for (i = 0; i < lc->num_categories; i++) + for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl->next) + if (lcl->channel->type == log_file && + lcl->channel->out.file.stream != NULL && + lcl->channel->flags & LOG_REQUIRE_DEBUG) + (void)log_close_stream(lcl->channel); +} + +FILE * +log_get_stream(log_channel chan) { + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + return (chan->out.file.stream); +} + +char * +log_get_filename(log_channel chan) { + if (chan == NULL || chan->type != log_file) { + errno = EINVAL; + return (NULL); + } + return (chan->out.file.name); +} + +int +log_check_channel(log_context lc, int level, log_channel chan) { + int debugging, chan_level; + + REQUIRE(lc != NULL); + + debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return (0); + + if ((chan->flags & (LOG_CHANNEL_BROKEN|LOG_CHANNEL_OFF)) != 0) + return (0); + + /* Some channels only log when debugging is on. */ + if ((chan->flags & LOG_REQUIRE_DEBUG) && !debugging) + return (0); + + /* Some channels use the global level. */ + if ((chan->flags & LOG_USE_CONTEXT_LEVEL) != 0) { + chan_level = lc->level; + } else + chan_level = chan->level; + + if (level > chan_level) + return (0); + + return (1); +} + +int +log_check(log_context lc, int category, int level) { + log_channel_list lcl; + int debugging; + + REQUIRE(lc != NULL); + + debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return (0); + + if (category < 0 || category > lc->num_categories) + category = 0; /*%< use default */ + lcl = lc->categories[category]; + if (lcl == NULL) { + category = 0; + lcl = lc->categories[0]; + } + + for ( /* nothing */; lcl != NULL; lcl = lcl->next) { + if (log_check_channel(lc, level, lcl->channel)) + return (1); + } + return (0); +} + +void +log_vwrite(log_context lc, int category, int level, const char *format, + va_list args) { + log_channel_list lcl; + int pri, debugging, did_vsprintf = 0; + int original_category; + FILE *stream; + log_channel chan; + struct timeval tv; + struct tm *local_tm; +#ifdef HAVE_TIME_R + struct tm tm_tmp; +#endif + time_t tt; + const char *category_name; + const char *level_str; + char time_buf[256]; + char level_buf[256]; + + REQUIRE(lc != NULL); + + debugging = (lc->flags & LOG_OPTION_DEBUG); + + /* + * If not debugging, short circuit debugging messages very early. + */ + if (level > 0 && !debugging) + return; + + if (category < 0 || category > lc->num_categories) + category = 0; /*%< use default */ + original_category = category; + lcl = lc->categories[category]; + if (lcl == NULL) { + category = 0; + lcl = lc->categories[0]; + } + + /* + * Get the current time and format it. + */ + time_buf[0]='\0'; + if (gettimeofday(&tv, NULL) < 0) { + syslog(LOG_INFO, "gettimeofday failed in log_vwrite()"); + } else { + tt = tv.tv_sec; +#ifdef HAVE_TIME_R + local_tm = localtime_r(&tt, &tm_tmp); +#else + local_tm = localtime(&tt); +#endif + if (local_tm != NULL) { + sprintf(time_buf, "%02d-%s-%4d %02d:%02d:%02d.%03ld ", + local_tm->tm_mday, months[local_tm->tm_mon], + local_tm->tm_year+1900, local_tm->tm_hour, + local_tm->tm_min, local_tm->tm_sec, + (long)tv.tv_usec/1000); + } + } + + /* + * Make a string representation of the current category and level + */ + + if (lc->category_names != NULL && + lc->category_names[original_category] != NULL) + category_name = lc->category_names[original_category]; + else + category_name = ""; + + if (level >= log_critical) { + if (level >= 0) { + sprintf(level_buf, "debug %d: ", level); + level_str = level_buf; + } else + level_str = level_text[-level-1]; + } else { + sprintf(level_buf, "level %d: ", level); + level_str = level_buf; + } + + /* + * Write the message to channels. + */ + for ( /* nothing */; lcl != NULL; lcl = lcl->next) { + chan = lcl->channel; + + if (!log_check_channel(lc, level, chan)) + continue; + + if (!did_vsprintf) { + (void)vsprintf(lc->buffer, format, args); + if (strlen(lc->buffer) > (size_t)LOG_BUFFER_SIZE) { + syslog(LOG_CRIT, + "memory overrun in log_vwrite()"); + exit(1); + } + did_vsprintf = 1; + } + + switch (chan->type) { + case log_syslog: + if (level >= log_critical) + pri = (level >= 0) ? 0 : -level; + else + pri = -log_critical; + syslog(chan->out.facility|syslog_priority[pri], + "%s%s%s%s", + (chan->flags & LOG_TIMESTAMP) ? time_buf : "", + (chan->flags & LOG_PRINT_CATEGORY) ? + category_name : "", + (chan->flags & LOG_PRINT_LEVEL) ? + level_str : "", + lc->buffer); + break; + case log_file: + stream = chan->out.file.stream; + if (stream == NULL) { + stream = log_open_stream(chan); + if (stream == NULL) + break; + } + if (chan->out.file.max_size != ULONG_MAX) { + long pos; + + pos = ftell(stream); + if (pos >= 0 && + (unsigned long)pos > + chan->out.file.max_size) { + /* + * try to roll over the log files, + * ignoring all all return codes + * except the open (we don't want + * to write any more anyway) + */ + log_close_stream(chan); + version_rename(chan); + stream = log_open_stream(chan); + if (stream == NULL) + break; + } + } + fprintf(stream, "%s%s%s%s\n", + (chan->flags & LOG_TIMESTAMP) ? time_buf : "", + (chan->flags & LOG_PRINT_CATEGORY) ? + category_name : "", + (chan->flags & LOG_PRINT_LEVEL) ? + level_str : "", + lc->buffer); + fflush(stream); + break; + case log_null: + break; + default: + syslog(LOG_ERR, + "unknown channel type in log_vwrite()"); + } + } +} + +void +log_write(log_context lc, int category, int level, const char *format, ...) { + va_list args; + + va_start(args, format); + log_vwrite(lc, category, level, format, args); + va_end(args); +} + +/*% + * Functions to create, set, or destroy contexts + */ + +int +log_new_context(int num_categories, char **category_names, log_context *lc) { + log_context nlc; + + nlc = memget(sizeof (struct log_context)); + if (nlc == NULL) { + errno = ENOMEM; + return (-1); + } + nlc->num_categories = num_categories; + nlc->category_names = category_names; + nlc->categories = memget(num_categories * sizeof (log_channel_list)); + if (nlc->categories == NULL) { + memput(nlc, sizeof (struct log_context)); + errno = ENOMEM; + return (-1); + } + memset(nlc->categories, '\0', + num_categories * sizeof (log_channel_list)); + nlc->flags = 0U; + nlc->level = 0; + *lc = nlc; + return (0); +} + +void +log_free_context(log_context lc) { + log_channel_list lcl, lcl_next; + log_channel chan; + int i; + + REQUIRE(lc != NULL); + + for (i = 0; i < lc->num_categories; i++) + for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl_next) { + lcl_next = lcl->next; + chan = lcl->channel; + (void)log_free_channel(chan); + memput(lcl, sizeof (struct log_channel_list)); + } + memput(lc->categories, + lc->num_categories * sizeof (log_channel_list)); + memput(lc, sizeof (struct log_context)); +} + +int +log_add_channel(log_context lc, int category, log_channel chan) { + log_channel_list lcl; + + if (lc == NULL || category < 0 || category >= lc->num_categories) { + errno = EINVAL; + return (-1); + } + + lcl = memget(sizeof (struct log_channel_list)); + if (lcl == NULL) { + errno = ENOMEM; + return(-1); + } + lcl->channel = chan; + lcl->next = lc->categories[category]; + lc->categories[category] = lcl; + chan->references++; + return (0); +} + +int +log_remove_channel(log_context lc, int category, log_channel chan) { + log_channel_list lcl, prev_lcl, next_lcl; + int found = 0; + + if (lc == NULL || category < 0 || category >= lc->num_categories) { + errno = EINVAL; + return (-1); + } + + for (prev_lcl = NULL, lcl = lc->categories[category]; + lcl != NULL; + lcl = next_lcl) { + next_lcl = lcl->next; + if (lcl->channel == chan) { + log_free_channel(chan); + if (prev_lcl != NULL) + prev_lcl->next = next_lcl; + else + lc->categories[category] = next_lcl; + memput(lcl, sizeof (struct log_channel_list)); + /* + * We just set found instead of returning because + * the channel might be on the list more than once. + */ + found = 1; + } else + prev_lcl = lcl; + } + if (!found) { + errno = ENOENT; + return (-1); + } + return (0); +} + +int +log_option(log_context lc, int option, int value) { + if (lc == NULL) { + errno = EINVAL; + return (-1); + } + switch (option) { + case LOG_OPTION_DEBUG: + if (value) + lc->flags |= option; + else + lc->flags &= ~option; + break; + case LOG_OPTION_LEVEL: + lc->level = value; + break; + default: + errno = EINVAL; + return (-1); + } + return (0); +} + +int +log_category_is_active(log_context lc, int category) { + if (lc == NULL) { + errno = EINVAL; + return (-1); + } + if (category >= 0 && category < lc->num_categories && + lc->categories[category] != NULL) + return (1); + return (0); +} + +log_channel +log_new_syslog_channel(unsigned int flags, int level, int facility) { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_syslog; + chan->flags = flags; + chan->level = level; + chan->out.facility = facility; + chan->references = 0; + return (chan); +} + +log_channel +log_new_file_channel(unsigned int flags, int level, + const char *name, FILE *stream, unsigned int versions, + unsigned long max_size) { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_file; + chan->flags = flags; + chan->level = level; + if (name != NULL) { + size_t len; + + len = strlen(name); + /* + * Quantize length to a multiple of 256. There's space for the + * NUL, since if len is a multiple of 256, the size chosen will + * be the next multiple. + */ + chan->out.file.name_size = ((len / 256) + 1) * 256; + chan->out.file.name = memget(chan->out.file.name_size); + if (chan->out.file.name == NULL) { + memput(chan, sizeof (struct log_channel)); + errno = ENOMEM; + return (NULL); + } + /* This is safe. */ + strcpy(chan->out.file.name, name); + } else { + chan->out.file.name_size = 0; + chan->out.file.name = NULL; + } + chan->out.file.stream = stream; + chan->out.file.versions = versions; + chan->out.file.max_size = max_size; + chan->out.file.owner = getuid(); + chan->out.file.group = getgid(); + chan->references = 0; + return (chan); +} + +int +log_set_file_owner(log_channel chan, uid_t owner, gid_t group) { + if (chan->type != log_file) { + errno = EBADF; + return (-1); + } + chan->out.file.owner = owner; + chan->out.file.group = group; + return (0); +} + +log_channel +log_new_null_channel() { + log_channel chan; + + chan = memget(sizeof (struct log_channel)); + if (chan == NULL) { + errno = ENOMEM; + return (NULL); + } + chan->type = log_null; + chan->flags = LOG_CHANNEL_OFF; + chan->level = log_info; + chan->references = 0; + return (chan); +} + +int +log_inc_references(log_channel chan) { + if (chan == NULL) { + errno = EINVAL; + return (-1); + } + chan->references++; + return (0); +} + +int +log_dec_references(log_channel chan) { + if (chan == NULL || chan->references <= 0) { + errno = EINVAL; + return (-1); + } + chan->references--; + return (0); +} + +log_channel_type +log_get_channel_type(log_channel chan) { + REQUIRE(chan != NULL); + + return (chan->type); +} + +int +log_free_channel(log_channel chan) { + if (chan == NULL || chan->references <= 0) { + errno = EINVAL; + return (-1); + } + chan->references--; + if (chan->references == 0) { + if (chan->type == log_file) { + if ((chan->flags & LOG_CLOSE_STREAM) && + chan->out.file.stream != NULL) + (void)fclose(chan->out.file.stream); + if (chan->out.file.name != NULL) + memput(chan->out.file.name, + chan->out.file.name_size); + } + memput(chan, sizeof (struct log_channel)); + } + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/logging_p.h b/usr/src/lib/libresolv2_joy/common/isc/logging_p.h new file mode 100644 index 0000000000..5e6314f190 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/logging_p.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 LOGGING_P_H +#define LOGGING_P_H + +typedef struct log_file_desc { + char *name; + size_t name_size; + FILE *stream; + unsigned int versions; + unsigned long max_size; + uid_t owner; + gid_t group; +} log_file_desc; + +typedef union log_output { + int facility; + log_file_desc file; +} log_output; + +struct log_channel { + int level; /*%< don't log messages > level */ + log_channel_type type; + log_output out; + unsigned int flags; + int references; +}; + +typedef struct log_channel_list { + log_channel channel; + struct log_channel_list *next; +} *log_channel_list; + +#define LOG_BUFFER_SIZE 20480 + +struct log_context { + int num_categories; + char **category_names; + log_channel_list *categories; + int flags; + int level; + char buffer[LOG_BUFFER_SIZE]; +}; + +#endif /* !LOGGING_P_H */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/memcluster.c b/usr/src/lib/libresolv2_joy/common/isc/memcluster.c new file mode 100644 index 0000000000..515793fd6a --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/memcluster.c @@ -0,0 +1,588 @@ +/* + * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1997,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + + +/* When this symbol is defined allocations via memget are made slightly + bigger and some debugging info stuck before and after the region given + back to the caller. */ +/* #define DEBUGGING_MEMCLUSTER */ +#define MEMCLUSTER_ATEND + + +#if !defined(LINT) && !defined(CODECENTER) +static const char rcsid[] = "$Id: memcluster.c,v 1.11 2006/08/30 23:34:38 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/param.h> +#include <sys/stat.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include <isc/memcluster.h> +#include <isc/assertions.h> + +#include "port_after.h" + +#ifdef MEMCLUSTER_RECORD +#ifndef DEBUGGING_MEMCLUSTER +#define DEBUGGING_MEMCLUSTER +#endif +#endif + +#define DEF_MAX_SIZE 1100 +#define DEF_MEM_TARGET 4096 + +typedef u_int32_t fence_t; + +typedef struct { + void * next; +#if defined(DEBUGGING_MEMCLUSTER) +#if defined(MEMCLUSTER_RECORD) + const char * file; + int line; +#endif + size_t size; + fence_t fencepost; +#endif +} memcluster_element; + +#define SMALL_SIZE_LIMIT sizeof(memcluster_element) +#define P_SIZE sizeof(void *) +#define FRONT_FENCEPOST 0xfebafeba +#define BACK_FENCEPOST 0xabefabef +#define FENCEPOST_SIZE 4 + +#ifndef MEMCLUSTER_LITTLE_MALLOC +#define MEMCLUSTER_BIG_MALLOC 1 +#define NUM_BASIC_BLOCKS 64 +#endif + +struct stats { + u_long gets; + u_long totalgets; + u_long blocks; + u_long freefrags; +}; + +#ifdef DO_PTHREADS +#include <pthread.h> +static pthread_mutex_t memlock = PTHREAD_MUTEX_INITIALIZER; +#define MEMLOCK (void)pthread_mutex_lock(&memlock) +#define MEMUNLOCK (void)pthread_mutex_unlock(&memlock) +#else +/* + * Catch bad lock usage in non threaded build. + */ +static unsigned int memlock = 0; +#define MEMLOCK do { INSIST(memlock == 0); memlock = 1; } while (0) +#define MEMUNLOCK do { INSIST(memlock == 1); memlock = 0; } while (0) +#endif /* DO_PTHEADS */ + +/* Private data. */ + +static size_t max_size; +static size_t mem_target; +#ifndef MEMCLUSTER_BIG_MALLOC +static size_t mem_target_half; +static size_t mem_target_fudge; +#endif +static memcluster_element ** freelists; +#ifdef MEMCLUSTER_RECORD +static memcluster_element ** activelists; +#endif +#ifdef MEMCLUSTER_BIG_MALLOC +static memcluster_element * basic_blocks; +#endif +static struct stats * stats; + +/* Forward. */ + +static size_t quantize(size_t); +#if defined(DEBUGGING_MEMCLUSTER) +static void check(unsigned char *, int, size_t); +#endif + +/* Public. */ + +int +meminit(size_t init_max_size, size_t target_size) { + +#if defined(DEBUGGING_MEMCLUSTER) + INSIST(sizeof(fence_t) == FENCEPOST_SIZE); +#endif + if (freelists != NULL) { + errno = EEXIST; + return (-1); + } + if (init_max_size == 0U) + max_size = DEF_MAX_SIZE; + else + max_size = init_max_size; + if (target_size == 0U) + mem_target = DEF_MEM_TARGET; + else + mem_target = target_size; +#ifndef MEMCLUSTER_BIG_MALLOC + mem_target_half = mem_target / 2; + mem_target_fudge = mem_target + mem_target / 4; +#endif + freelists = malloc(max_size * sizeof (memcluster_element *)); + stats = malloc((max_size+1) * sizeof (struct stats)); + if (freelists == NULL || stats == NULL) { + errno = ENOMEM; + return (-1); + } + memset(freelists, 0, + max_size * sizeof (memcluster_element *)); + memset(stats, 0, (max_size + 1) * sizeof (struct stats)); +#ifdef MEMCLUSTER_RECORD + activelists = malloc((max_size + 1) * sizeof (memcluster_element *)); + if (activelists == NULL) { + errno = ENOMEM; + return (-1); + } + memset(activelists, 0, + (max_size + 1) * sizeof (memcluster_element *)); +#endif +#ifdef MEMCLUSTER_BIG_MALLOC + basic_blocks = NULL; +#endif + return (0); +} + +void * +__memget(size_t size) { + return (__memget_record(size, NULL, 0)); +} + +void * +__memget_record(size_t size, const char *file, int line) { + size_t new_size = quantize(size); +#if defined(DEBUGGING_MEMCLUSTER) + memcluster_element *e; + char *p; + fence_t fp = BACK_FENCEPOST; +#endif + void *ret; + + MEMLOCK; + +#if !defined(MEMCLUSTER_RECORD) + UNUSED(file); + UNUSED(line); +#endif + if (freelists == NULL) { + if (meminit(0, 0) == -1) { + MEMUNLOCK; + return (NULL); + } + } + if (size == 0U) { + MEMUNLOCK; + errno = EINVAL; + return (NULL); + } + if (size >= max_size || new_size >= max_size) { + /* memget() was called on something beyond our upper limit. */ + stats[max_size].gets++; + stats[max_size].totalgets++; +#if defined(DEBUGGING_MEMCLUSTER) + e = malloc(new_size); + if (e == NULL) { + MEMUNLOCK; + errno = ENOMEM; + return (NULL); + } + e->next = NULL; + e->size = size; +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; + e->next = activelists[max_size]; + activelists[max_size] = e; +#endif + MEMUNLOCK; + e->fencepost = FRONT_FENCEPOST; + p = (char *)e + sizeof *e + size; + memcpy(p, &fp, sizeof fp); + return ((char *)e + sizeof *e); +#else + MEMUNLOCK; + return (malloc(size)); +#endif + } + + /* + * If there are no blocks in the free list for this size, get a chunk + * of memory and then break it up into "new_size"-sized blocks, adding + * them to the free list. + */ + if (freelists[new_size] == NULL) { + int i, frags; + size_t total_size; + void *new; + char *curr, *next; + +#ifdef MEMCLUSTER_BIG_MALLOC + if (basic_blocks == NULL) { + new = malloc(NUM_BASIC_BLOCKS * mem_target); + if (new == NULL) { + MEMUNLOCK; + errno = ENOMEM; + return (NULL); + } + curr = new; + next = curr + mem_target; + for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) { + ((memcluster_element *)curr)->next = next; + curr = next; + next += mem_target; + } + /* + * curr is now pointing at the last block in the + * array. + */ + ((memcluster_element *)curr)->next = NULL; + basic_blocks = new; + } + total_size = mem_target; + new = basic_blocks; + basic_blocks = basic_blocks->next; +#else + if (new_size > mem_target_half) + total_size = mem_target_fudge; + else + total_size = mem_target; + new = malloc(total_size); + if (new == NULL) { + MEMUNLOCK; + errno = ENOMEM; + return (NULL); + } +#endif + frags = total_size / new_size; + stats[new_size].blocks++; + stats[new_size].freefrags += frags; + /* Set up a linked-list of blocks of size "new_size". */ + curr = new; + next = curr + new_size; + for (i = 0; i < (frags - 1); i++) { +#if defined (DEBUGGING_MEMCLUSTER) + memset(curr, 0xa5, new_size); +#endif + ((memcluster_element *)curr)->next = next; + curr = next; + next += new_size; + } + /* curr is now pointing at the last block in the array. */ +#if defined (DEBUGGING_MEMCLUSTER) + memset(curr, 0xa5, new_size); +#endif + ((memcluster_element *)curr)->next = freelists[new_size]; + freelists[new_size] = new; + } + + /* The free list uses the "rounded-up" size "new_size". */ +#if defined (DEBUGGING_MEMCLUSTER) + e = freelists[new_size]; + ret = (char *)e + sizeof *e; + /* + * Check to see if this buffer has been written to while on free list. + */ + check(ret, 0xa5, new_size - sizeof *e); + /* + * Mark memory we are returning. + */ + memset(ret, 0xe5, size); +#else + ret = freelists[new_size]; +#endif + freelists[new_size] = freelists[new_size]->next; +#if defined(DEBUGGING_MEMCLUSTER) + e->next = NULL; + e->size = size; + e->fencepost = FRONT_FENCEPOST; +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; + e->next = activelists[size]; + activelists[size] = e; +#endif + p = (char *)e + sizeof *e + size; + memcpy(p, &fp, sizeof fp); +#endif + + /* + * The stats[] uses the _actual_ "size" requested by the + * caller, with the caveat (in the code above) that "size" >= the + * max. size (max_size) ends up getting recorded as a call to + * max_size. + */ + stats[size].gets++; + stats[size].totalgets++; + stats[new_size].freefrags--; + MEMUNLOCK; +#if defined(DEBUGGING_MEMCLUSTER) + return ((char *)e + sizeof *e); +#else + return (ret); +#endif +} + +/*% + * This is a call from an external caller, + * so we want to count this as a user "put". + */ +void +__memput(void *mem, size_t size) { + __memput_record(mem, size, NULL, 0); +} + +void +__memput_record(void *mem, size_t size, const char *file, int line) { + size_t new_size = quantize(size); +#if defined (DEBUGGING_MEMCLUSTER) + memcluster_element *e; + memcluster_element *el; +#ifdef MEMCLUSTER_RECORD + memcluster_element *prev; +#endif + fence_t fp; + char *p; +#endif + + MEMLOCK; + +#if !defined (MEMCLUSTER_RECORD) + UNUSED(file); + UNUSED(line); +#endif + + REQUIRE(freelists != NULL); + + if (size == 0U) { + MEMUNLOCK; + errno = EINVAL; + return; + } + +#if defined (DEBUGGING_MEMCLUSTER) + e = (memcluster_element *) ((char *)mem - sizeof *e); + INSIST(e->fencepost == FRONT_FENCEPOST); + INSIST(e->size == size); + p = (char *)e + sizeof *e + size; + memcpy(&fp, p, sizeof fp); + INSIST(fp == BACK_FENCEPOST); + INSIST(((u_long)mem % 4) == 0); +#ifdef MEMCLUSTER_RECORD + prev = NULL; + if (size == max_size || new_size >= max_size) + el = activelists[max_size]; + else + el = activelists[size]; + while (el != NULL && el != e) { + prev = el; + el = el->next; + } + INSIST(el != NULL); /*%< double free */ + if (prev == NULL) { + if (size == max_size || new_size >= max_size) + activelists[max_size] = el->next; + else + activelists[size] = el->next; + } else + prev->next = el->next; +#endif +#endif + + if (size == max_size || new_size >= max_size) { + /* memput() called on something beyond our upper limit */ +#if defined(DEBUGGING_MEMCLUSTER) + free(e); +#else + free(mem); +#endif + + INSIST(stats[max_size].gets != 0U); + stats[max_size].gets--; + MEMUNLOCK; + return; + } + + /* The free list uses the "rounded-up" size "new_size": */ +#if defined(DEBUGGING_MEMCLUSTER) + memset(mem, 0xa5, new_size - sizeof *e); /*%< catch write after free */ + e->size = 0; /*%< catch double memput() */ +#ifdef MEMCLUSTER_RECORD + e->file = file; + e->line = line; +#endif +#ifdef MEMCLUSTER_ATEND + e->next = NULL; + el = freelists[new_size]; + while (el != NULL && el->next != NULL) + el = el->next; + if (el) + el->next = e; + else + freelists[new_size] = e; +#else + e->next = freelists[new_size]; + freelists[new_size] = (void *)e; +#endif +#else + ((memcluster_element *)mem)->next = freelists[new_size]; + freelists[new_size] = (memcluster_element *)mem; +#endif + + /* + * The stats[] uses the _actual_ "size" requested by the + * caller, with the caveat (in the code above) that "size" >= the + * max. size (max_size) ends up getting recorded as a call to + * max_size. + */ + INSIST(stats[size].gets != 0U); + stats[size].gets--; + stats[new_size].freefrags++; + MEMUNLOCK; +} + +void * +__memget_debug(size_t size, const char *file, int line) { + void *ptr; + ptr = __memget_record(size, file, line); + fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line, + (u_long)size, ptr); + return (ptr); +} + +void +__memput_debug(void *ptr, size_t size, const char *file, int line) { + fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line, ptr, + (u_long)size); + __memput_record(ptr, size, file, line); +} + +/*% + * Print the stats[] on the stream "out" with suitable formatting. + */ +void +memstats(FILE *out) { + size_t i; +#ifdef MEMCLUSTER_RECORD + memcluster_element *e; +#endif + + MEMLOCK; + + if (freelists == NULL) { + MEMUNLOCK; + return; + } + for (i = 1; i <= max_size; i++) { + const struct stats *s = &stats[i]; + + if (s->totalgets == 0U && s->gets == 0U) + continue; + fprintf(out, "%s%5lu: %11lu gets, %11lu rem", + (i == max_size) ? ">=" : " ", + (unsigned long)i, s->totalgets, s->gets); + if (s->blocks != 0U) + fprintf(out, " (%lu bl, %lu ff)", + s->blocks, s->freefrags); + fputc('\n', out); + } +#ifdef MEMCLUSTER_RECORD + fprintf(out, "Active Memory:\n"); + for (i = 1; i <= max_size; i++) { + if ((e = activelists[i]) != NULL) + while (e != NULL) { + fprintf(out, "%s:%d %p:%lu\n", + e->file != NULL ? e->file : + "<UNKNOWN>", e->line, + (char *)e + sizeof *e, + (u_long)e->size); + e = e->next; + } + } +#endif + MEMUNLOCK; +} + +int +memactive(void) { + size_t i; + + if (stats == NULL) + return (0); + for (i = 1; i <= max_size; i++) + if (stats[i].gets != 0U) + return (1); + return (0); +} + +/* Private. */ + +/*% + * Round up size to a multiple of sizeof(void *). This guarantees that a + * block is at least sizeof void *, and that we won't violate alignment + * restrictions, both of which are needed to make lists of blocks. + */ +static size_t +quantize(size_t size) { + int remainder; + /* + * If there is no remainder for the integer division of + * + * (rightsize/P_SIZE) + * + * then we already have a good size; if not, then we need + * to round up the result in order to get a size big + * enough to satisfy the request _and_ aligned on P_SIZE boundaries. + */ + remainder = size % P_SIZE; + if (remainder != 0) + size += P_SIZE - remainder; +#if defined(DEBUGGING_MEMCLUSTER) + return (size + SMALL_SIZE_LIMIT + sizeof (int)); +#else + return (size); +#endif +} + +#if defined(DEBUGGING_MEMCLUSTER) +static void +check(unsigned char *a, int value, size_t len) { + size_t i; + for (i = 0; i < len; i++) + INSIST(a[i] == value); +} +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/movefile.c b/usr/src/lib/libresolv2_joy/common/isc/movefile.c new file mode 100644 index 0000000000..0ffc7047e2 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/movefile.c @@ -0,0 +1,43 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 2000 by Internet Software Consortium, Inc. + * + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + + +#include <port_before.h> +#include <stdio.h> +#include <isc/misc.h> +#include <port_after.h> +#ifndef HAVE_MOVEFILE +/* + * rename() is lame (can't overwrite an existing file) on some systems. + * use movefile() instead, and let lame OS ports do what they need to. + */ + +int +isc_movefile(const char *oldname, const char *newname) { + return (rename(oldname, newname)); +} +#else + static int os_port_has_isc_movefile = 1; +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/isc/tree.c b/usr/src/lib/libresolv2_joy/common/isc/tree.c new file mode 100644 index 0000000000..8ba675fbe8 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/isc/tree.c @@ -0,0 +1,534 @@ +#ifndef LINT +static const char rcsid[] = "$Id: tree.c,v 1.4 2005/04/27 04:56:39 sra Exp $"; +#endif + +/*% + * tree - balanced binary tree library + * + * vix 05apr94 [removed vixie.h dependencies; cleaned up formatting, names] + * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] + * vix 23jun86 [added delete uar to add for replaced nodes] + * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224] + * vix 06feb86 [added tree_mung()] + * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221] + * vix 14dec85 [written] + */ + +/*% + * This program text was created by Paul Vixie using examples from the book: + * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN + * 0-13-022005-1. Any errors in the conversion from Modula-2 to C are Paul + * Vixie's. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*#define DEBUG "tree"*/ + +#include "port_before.h" + +#include <stdio.h> +#include <stdlib.h> + +#include "port_after.h" + +#include <isc/memcluster.h> +#include <isc/tree.h> + +#ifdef DEBUG +static int debugDepth = 0; +static char *debugFuncs[256]; +# define ENTER(proc) { \ + debugFuncs[debugDepth] = proc; \ + fprintf(stderr, "ENTER(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + debugDepth++; \ + } +# define RET(value) { \ + debugDepth--; \ + fprintf(stderr, "RET(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + return (value); \ + } +# define RETV { \ + debugDepth--; \ + fprintf(stderr, "RETV(%d:%s.%s)\n", \ + debugDepth, DEBUG, \ + debugFuncs[debugDepth]); \ + return; \ + } +# define MSG(msg) fprintf(stderr, "MSG(%s)\n", msg); +#else +# define ENTER(proc) ; +# define RET(value) return (value); +# define RETV return; +# define MSG(msg) ; +#endif + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif + +static tree * sprout(tree **, tree_t, int *, int (*)(), void (*)()); +static int delete(tree **, int (*)(), tree_t, void (*)(), int *, int *); +static void del(tree **, int *, tree **, void (*)(), int *); +static void bal_L(tree **, int *); +static void bal_R(tree **, int *); + +void +tree_init(tree **ppr_tree) { + ENTER("tree_init") + *ppr_tree = NULL; + RETV +} + +tree_t +tree_srch(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t), tree_t p_user) { + ENTER("tree_srch") + + if (*ppr_tree) { + int i_comp = (*pfi_compare)(p_user, (**ppr_tree).data); + + if (i_comp > 0) + RET(tree_srch(&(**ppr_tree).right, + pfi_compare, + p_user)) + + if (i_comp < 0) + RET(tree_srch(&(**ppr_tree).left, + pfi_compare, + p_user)) + + /* not higher, not lower... this must be the one. + */ + RET((**ppr_tree).data) + } + + /* grounded. NOT found. + */ + RET(NULL) +} + +tree_t +tree_add(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t), + tree_t p_user, void (*pfv_uar)()) +{ + int i_balance = FALSE; + + ENTER("tree_add") + if (!sprout(ppr_tree, p_user, &i_balance, pfi_compare, pfv_uar)) + RET(NULL) + RET(p_user) +} + +int +tree_delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t), + tree_t p_user, void (*pfv_uar)()) +{ + int i_balance = FALSE, i_uar_called = FALSE; + + ENTER("tree_delete"); + RET(delete(ppr_p, pfi_compare, p_user, pfv_uar, + &i_balance, &i_uar_called)) +} + +int +tree_trav(tree **ppr_tree, int (*pfi_uar)(tree_t)) { + ENTER("tree_trav") + + if (!*ppr_tree) + RET(TRUE) + + if (!tree_trav(&(**ppr_tree).left, pfi_uar)) + RET(FALSE) + if (!(*pfi_uar)((**ppr_tree).data)) + RET(FALSE) + if (!tree_trav(&(**ppr_tree).right, pfi_uar)) + RET(FALSE) + RET(TRUE) +} + +void +tree_mung(tree **ppr_tree, void (*pfv_uar)(tree_t)) { + ENTER("tree_mung") + if (*ppr_tree) { + tree_mung(&(**ppr_tree).left, pfv_uar); + tree_mung(&(**ppr_tree).right, pfv_uar); + if (pfv_uar) + (*pfv_uar)((**ppr_tree).data); + memput(*ppr_tree, sizeof(tree)); + *ppr_tree = NULL; + } + RETV +} + +static tree * +sprout(tree **ppr, tree_t p_data, int *pi_balance, + int (*pfi_compare)(tree_t, tree_t), void (*pfv_delete)(tree_t)) +{ + tree *p1, *p2, *sub; + int cmp; + + ENTER("sprout") + + /* are we grounded? if so, add the node "here" and set the rebalance + * flag, then exit. + */ + if (!*ppr) { + MSG("grounded. adding new node, setting h=true") + *ppr = (tree *) memget(sizeof(tree)); + if (*ppr) { + (*ppr)->left = NULL; + (*ppr)->right = NULL; + (*ppr)->bal = 0; + (*ppr)->data = p_data; + *pi_balance = TRUE; + } + RET(*ppr); + } + + /* compare the data using routine passed by caller. + */ + cmp = (*pfi_compare)(p_data, (*ppr)->data); + + /* if LESS, prepare to move to the left. + */ + if (cmp < 0) { + MSG("LESS. sprouting left.") + sub = sprout(&(*ppr)->left, p_data, pi_balance, + pfi_compare, pfv_delete); + if (sub && *pi_balance) { /*%< left branch has grown */ + MSG("LESS: left branch has grown") + switch ((*ppr)->bal) { + case 1: + /* right branch WAS longer; bal is ok now */ + MSG("LESS: case 1.. bal restored implicitly") + (*ppr)->bal = 0; + *pi_balance = FALSE; + break; + case 0: + /* balance WAS okay; now left branch longer */ + MSG("LESS: case 0.. balnce bad but still ok") + (*ppr)->bal = -1; + break; + case -1: + /* left branch was already too long. rebal */ + MSG("LESS: case -1: rebalancing") + p1 = (*ppr)->left; + if (p1->bal == -1) { /*%< LL */ + MSG("LESS: single LL") + (*ppr)->left = p1->right; + p1->right = *ppr; + (*ppr)->bal = 0; + *ppr = p1; + } else { /*%< double LR */ + MSG("LESS: double LR") + + p2 = p1->right; + p1->right = p2->left; + p2->left = p1; + + (*ppr)->left = p2->right; + p2->right = *ppr; + + if (p2->bal == -1) + (*ppr)->bal = 1; + else + (*ppr)->bal = 0; + + if (p2->bal == 1) + p1->bal = -1; + else + p1->bal = 0; + *ppr = p2; + } /*else*/ + (*ppr)->bal = 0; + *pi_balance = FALSE; + } /*switch*/ + } /*if*/ + RET(sub) + } /*if*/ + + /* if MORE, prepare to move to the right. + */ + if (cmp > 0) { + MSG("MORE: sprouting to the right") + sub = sprout(&(*ppr)->right, p_data, pi_balance, + pfi_compare, pfv_delete); + if (sub && *pi_balance) { + MSG("MORE: right branch has grown") + + switch ((*ppr)->bal) { + case -1: + MSG("MORE: balance was off, fixed implicitly") + (*ppr)->bal = 0; + *pi_balance = FALSE; + break; + case 0: + MSG("MORE: balance was okay, now off but ok") + (*ppr)->bal = 1; + break; + case 1: + MSG("MORE: balance was off, need to rebalance") + p1 = (*ppr)->right; + if (p1->bal == 1) { /*%< RR */ + MSG("MORE: single RR") + (*ppr)->right = p1->left; + p1->left = *ppr; + (*ppr)->bal = 0; + *ppr = p1; + } else { /*%< double RL */ + MSG("MORE: double RL") + + p2 = p1->left; + p1->left = p2->right; + p2->right = p1; + + (*ppr)->right = p2->left; + p2->left = *ppr; + + if (p2->bal == 1) + (*ppr)->bal = -1; + else + (*ppr)->bal = 0; + + if (p2->bal == -1) + p1->bal = 1; + else + p1->bal = 0; + + *ppr = p2; + } /*else*/ + (*ppr)->bal = 0; + *pi_balance = FALSE; + } /*switch*/ + } /*if*/ + RET(sub) + } /*if*/ + + /* not less, not more: this is the same key! replace... + */ + MSG("FOUND: Replacing data value") + *pi_balance = FALSE; + if (pfv_delete) + (*pfv_delete)((*ppr)->data); + (*ppr)->data = p_data; + RET(*ppr) +} + +static int +delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t), tree_t p_user, + void (*pfv_uar)(tree_t), int *pi_balance, int *pi_uar_called) +{ + tree *pr_q; + int i_comp, i_ret; + + ENTER("delete") + + if (*ppr_p == NULL) { + MSG("key not in tree") + RET(FALSE) + } + + i_comp = (*pfi_compare)((*ppr_p)->data, p_user); + if (i_comp > 0) { + MSG("too high - scan left") + i_ret = delete(&(*ppr_p)->left, pfi_compare, p_user, pfv_uar, + pi_balance, pi_uar_called); + if (*pi_balance) + bal_L(ppr_p, pi_balance); + } else if (i_comp < 0) { + MSG("too low - scan right") + i_ret = delete(&(*ppr_p)->right, pfi_compare, p_user, pfv_uar, + pi_balance, pi_uar_called); + if (*pi_balance) + bal_R(ppr_p, pi_balance); + } else { + MSG("equal") + pr_q = *ppr_p; + if (pr_q->right == NULL) { + MSG("right subtree null") + *ppr_p = pr_q->left; + *pi_balance = TRUE; + } else if (pr_q->left == NULL) { + MSG("right subtree non-null, left subtree null") + *ppr_p = pr_q->right; + *pi_balance = TRUE; + } else { + MSG("neither subtree null") + del(&pr_q->left, pi_balance, &pr_q, + pfv_uar, pi_uar_called); + if (*pi_balance) + bal_L(ppr_p, pi_balance); + } + if (!*pi_uar_called && pfv_uar) + (*pfv_uar)(pr_q->data); + /* Thanks to wuth@castrov.cuc.ab.ca for the following stmt. */ + memput(pr_q, sizeof(tree)); + i_ret = TRUE; + } + RET(i_ret) +} + +static void +del(tree **ppr_r, int *pi_balance, tree **ppr_q, + void (*pfv_uar)(tree_t), int *pi_uar_called) +{ + ENTER("del") + + if ((*ppr_r)->right != NULL) { + del(&(*ppr_r)->right, pi_balance, ppr_q, + pfv_uar, pi_uar_called); + if (*pi_balance) + bal_R(ppr_r, pi_balance); + } else { + if (pfv_uar) + (*pfv_uar)((*ppr_q)->data); + *pi_uar_called = TRUE; + (*ppr_q)->data = (*ppr_r)->data; + *ppr_q = *ppr_r; + *ppr_r = (*ppr_r)->left; + *pi_balance = TRUE; + } + + RETV +} + +static void +bal_L(tree **ppr_p, int *pi_balance) { + tree *p1, *p2; + int b1, b2; + + ENTER("bal_L") + MSG("left branch has shrunk") + + switch ((*ppr_p)->bal) { + case -1: + MSG("was imbalanced, fixed implicitly") + (*ppr_p)->bal = 0; + break; + case 0: + MSG("was okay, is now one off") + (*ppr_p)->bal = 1; + *pi_balance = FALSE; + break; + case 1: + MSG("was already off, this is too much") + p1 = (*ppr_p)->right; + b1 = p1->bal; + if (b1 >= 0) { + MSG("single RR") + (*ppr_p)->right = p1->left; + p1->left = *ppr_p; + if (b1 == 0) { + MSG("b1 == 0") + (*ppr_p)->bal = 1; + p1->bal = -1; + *pi_balance = FALSE; + } else { + MSG("b1 != 0") + (*ppr_p)->bal = 0; + p1->bal = 0; + } + *ppr_p = p1; + } else { + MSG("double RL") + p2 = p1->left; + b2 = p2->bal; + p1->left = p2->right; + p2->right = p1; + (*ppr_p)->right = p2->left; + p2->left = *ppr_p; + if (b2 == 1) + (*ppr_p)->bal = -1; + else + (*ppr_p)->bal = 0; + if (b2 == -1) + p1->bal = 1; + else + p1->bal = 0; + *ppr_p = p2; + p2->bal = 0; + } + } + RETV +} + +static void +bal_R(tree **ppr_p, int *pi_balance) { + tree *p1, *p2; + int b1, b2; + + ENTER("bal_R") + MSG("right branch has shrunk") + switch ((*ppr_p)->bal) { + case 1: + MSG("was imbalanced, fixed implicitly") + (*ppr_p)->bal = 0; + break; + case 0: + MSG("was okay, is now one off") + (*ppr_p)->bal = -1; + *pi_balance = FALSE; + break; + case -1: + MSG("was already off, this is too much") + p1 = (*ppr_p)->left; + b1 = p1->bal; + if (b1 <= 0) { + MSG("single LL") + (*ppr_p)->left = p1->right; + p1->right = *ppr_p; + if (b1 == 0) { + MSG("b1 == 0") + (*ppr_p)->bal = -1; + p1->bal = 1; + *pi_balance = FALSE; + } else { + MSG("b1 != 0") + (*ppr_p)->bal = 0; + p1->bal = 0; + } + *ppr_p = p1; + } else { + MSG("double LR") + p2 = p1->right; + b2 = p2->bal; + p1->right = p2->left; + p2->left = p1; + (*ppr_p)->left = p2->right; + p2->right = *ppr_p; + if (b2 == -1) + (*ppr_p)->bal = 1; + else + (*ppr_p)->bal = 0; + if (b2 == 1) + p1->bal = -1; + else + p1->bal = 0; + *ppr_p = p2; + p2->bal = 0; + } + } + RETV +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/llib-lresolv_joy b/usr/src/lib/libresolv2_joy/common/llib-lresolv_joy new file mode 100644 index 0000000000..aedd06a0fa --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/llib-lresolv_joy @@ -0,0 +1,59 @@ +/* LINTLIBRARY */ +/* PROTOLIB1 */ + +/* + * Copyright (c) 1997-1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/nameser.h> +#include <resolv.h> + +/* + * usr/src/lib/libresolv2 routines + */ + +int dn_skipname(const uchar_t *, const uchar_t *); +void fp_query(const u_char *, FILE *); +const uchar_t * p_cdname(const uchar_t *, const uchar_t *, FILE *); +const char * p_class(int); +void p_query(const u_char *); +const char * p_time(unsigned int); +const char * p_type(int); +void putlong(unsigned int, uchar_t *); +uint32_t _getlong(const u_char *); +uint16_t _getshort(const u_char *); +const char * hstrerror(int); +int res_init(void); +int res_mkquery(int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int); +int res_query(const char *, int, int, u_char *, int); +int res_querydomain(const char *, const char *, int, int, + u_char *, int); +int res_search(const char *, int, int, u_char *, int); +int res_send(const u_char *, int, u_char *, int); +int res_update(ns_updrec *); +int res_ninit(res_state); +void fp_resstat(const res_state, FILE *); +const char * res_hostalias(const res_state, const char *, char *, size_t); +int res_nquery(res_state, const char *, int, int, u_char *, int); +int res_nsearch(res_state, const char *, int, int, u_char *, int); +int res_nquerydomain(res_state, const char *, const char *, + int, int, u_char *, int); +int res_nmkquery(res_state, int, const char *, int, int, + const u_char *, int, const u_char *, + u_char *, int); +int res_nsend(res_state, const u_char *, int, u_char *, int); +int res_nmkupdate(res_state, ns_updrec *, u_char *, int); +void res_nclose(res_state); +int res_nsendsigned(res_state, const u_char *, int, ns_tsig_key *, + u_char *, int); +int dn_comp(const char *, u_char *, int, u_char **, u_char **); +int dn_expand(const u_char *, const u_char *, const u_char *, + char *, int); diff --git a/usr/src/lib/print/libhttp-core/common/mapfile b/usr/src/lib/libresolv2_joy/common/mapfile-vers index 1d641d73e1..e0c66a1c96 100644 --- a/usr/src/lib/print/libhttp-core/common/mapfile +++ b/usr/src/lib/libresolv2_joy/common/mapfile-vers @@ -18,13 +18,8 @@ # # CDDL HEADER END # - -# -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -# - # -# $Id: mapfile.in,v 1.2 2006/03/02 06:31:36 njacobs Exp $ +# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. # # @@ -41,31 +36,25 @@ # MAPFILE HEADER END # -# -# Common interfaces that are most likely to be shared amongst the various -# PAPI implementations. -# - $mapfile_version 2 -SYMBOL_VERSION SUNWprivate_1.0 { +SYMBOL_VERSION SUNWprivate { global: - httpCheck ; - httpClose ; - httpConnectEncrypt ; - httpDumpData ; - httpEncode64 ; - httpEncryption ; - httpFlush ; - httpGetSubField ; - httpPost ; - httpRead ; - httpReconnect ; - httpSetField ; - httpUpdate ; - httpWait ; - httpWrite ; - + joy_dn_expand; + joy_res_nsearch; + joy_res_ninit; + joy_res_ndestroy; + joy_res_gethostbyaddr; + joy_res_gethostbyname; + joy_res_gethostbyname2; + joy_res_sethostent; + joy_res_endhostent; + __joy_res_override_retry; + __joy_res_unset_no_hosts_fallback; + __joy_res_set_no_hosts_fallback; + __joy_h_errno; + __joy_ns_get16; + __joy_ns_get32; local: - * ; -} ; + *; +}; diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_date.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_date.c new file mode 100644 index 0000000000..292375af63 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_date.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_date.c,v 1.6 2005/04/27 04:56:39 sra Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static int datepart(const char *, int, int, int, int *); + +/* Public. */ + +/*% + * Convert a date in ASCII into the number of seconds since + * 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all + * digits required, no spaces allowed. + */ + +u_int32_t +ns_datetosecs(const char *cp, int *errp) { + struct tm time; + u_int32_t result; + int mdays, i; + static const int days_per_month[12] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if (strlen(cp) != 14U) { + *errp = 1; + return (0); + } + *errp = 0; + + memset(&time, 0, sizeof time); + time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900; + time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1; + time.tm_mday = datepart(cp + 6, 2, 01, 31, errp); + time.tm_hour = datepart(cp + 8, 2, 00, 23, errp); + time.tm_min = datepart(cp + 10, 2, 00, 59, errp); + time.tm_sec = datepart(cp + 12, 2, 00, 59, errp); + if (*errp) /*%< Any parse errors? */ + return (0); + + /* + * OK, now because timegm() is not available in all environments, + * we will do it by hand. Roll up sleeves, curse the gods, begin! + */ + +#define SECS_PER_DAY ((u_int32_t)24*60*60) +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + + result = time.tm_sec; /*%< Seconds */ + result += time.tm_min * 60; /*%< Minutes */ + result += time.tm_hour * (60*60); /*%< Hours */ + result += (time.tm_mday - 1) * SECS_PER_DAY; /*%< Days */ + /* Months are trickier. Look without leaping, then leap */ + mdays = 0; + for (i = 0; i < time.tm_mon; i++) + mdays += days_per_month[i]; + result += mdays * SECS_PER_DAY; /*%< Months */ + if (time.tm_mon > 1 && isleap(1900+time.tm_year)) + result += SECS_PER_DAY; /*%< Add leapday for this year */ + /* First figure years without leapdays, then add them in. */ + /* The loop is slow, FIXME, but simple and accurate. */ + result += (time.tm_year - 70) * (SECS_PER_DAY*365); /*%< Years */ + for (i = 70; i < time.tm_year; i++) + if (isleap(1900+i)) + result += SECS_PER_DAY; /*%< Add leapday for prev year */ + return (result); +} + +/* Private. */ + +/*% + * Parse part of a date. Set error flag if any error. + * Don't reset the flag if there is no error. + */ +static int +datepart(const char *buf, int size, int min, int max, int *errp) { + int result = 0; + int i; + + for (i = 0; i < size; i++) { + if (!isdigit((unsigned char)(buf[i]))) + *errp = 1; + result = (result * 10) + buf[i] - '0'; + } + if (result < min) + *errp = 1; + if (result > max) + *errp = 1; + return (result); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_name.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_name.c new file mode 100644 index 0000000000..f6b0accef1 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_name.c @@ -0,0 +1,1153 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_name.c,v 1.11 2009/01/23 19:59:16 each Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv_joy.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include <limits.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +#define NS_TYPE_ELT 0x40 /*%< EDNS0 extended label type */ +#define DNS_LABELTYPE_BITSTRING 0x41 + +/* Data. */ + +static const char digits[] = "0123456789"; + +static const char digitvalue[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ + -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ +}; + +/* Forward. */ + +static int special(int); +static int printable(int); +static int dn_find(const u_char *, const u_char *, + const u_char * const *, + const u_char * const *); +static int encode_bitsring(const char **, const char *, + unsigned char **, unsigned char **, + unsigned const char *); +static int labellen(const u_char *); +static int decode_bitstring(const unsigned char **, + char *, const char *); + +/* Public. */ + +/*% + * Convert an encoded domain name to printable ascii as per RFC1035. + + * return: + *\li Number of bytes written to buffer, or -1 (with errno set) + * + * notes: + *\li The root is returned as "." + *\li All other domains are returned in non absolute form + */ +int +ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) +{ + const u_char *cp; + char *dn, *eom; + u_char c; + u_int n; + int l; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + if (dn != dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; /*%< XXX */ + return (-1); + } + if (dn + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) { + int m; + + if (n != DNS_LABELTYPE_BITSTRING) { + /* XXX: labellen should reject this case */ + errno = EINVAL; + return (-1); + } + if ((m = decode_bitstring(&cp, dn, eom)) < 0) + { + errno = EMSGSIZE; + return (-1); + } + dn += m; + continue; + } + for ((void)NULL; l > 0; l--) { + c = *cp++; + if (special(c)) { + if (dn + 1 >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\\'; + *dn++ = (char)c; + } else if (!printable(c)) { + if (dn + 3 >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\\'; + *dn++ = digits[c / 100]; + *dn++ = digits[(c % 100) / 10]; + *dn++ = digits[c % 10]; + } else { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = (char)c; + } + } + } + if (dn == dst) { + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '.'; + } + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + *dn++ = '\0'; + return (dn - dst); +} + +/*% + * Convert a ascii string into an encoded domain name as per RFC1035. + * + * return: + * + *\li -1 if it fails + *\li 1 if string was fully qualified + *\li 0 is string was not fully qualified + * + * notes: + *\li Enforces label and domain length limits. + */ +int +ns_name_pton(const char *src, u_char *dst, size_t dstsiz) { + return (ns_name_pton2(src, dst, dstsiz, NULL)); +} + +/* + * ns_name_pton2(src, dst, dstsiz, *dstlen) + * Convert a ascii string into an encoded domain name as per RFC1035. + * return: + * -1 if it fails + * 1 if string was fully qualified + * 0 is string was not fully qualified + * side effects: + * fills in *dstlen (if non-NULL) + * notes: + * Enforces label and domain length limits. + */ +int +ns_name_pton2(const char *src, u_char *dst, size_t dstsiz, size_t *dstlen) { + u_char *label, *bp, *eom; + int c, n, escaped, e = 0; + char *cp; + + escaped = 0; + bp = dst; + eom = dst + dstsiz; + label = bp++; + + while ((c = *src++) != 0) { + if (escaped) { + if (c == '[') { /*%< start a bit string label */ + if ((cp = strchr(src, ']')) == NULL) { + errno = EINVAL; /*%< ??? */ + return (-1); + } + if ((e = encode_bitsring(&src, cp + 2, + &label, &bp, eom)) + != 0) { + errno = e; + return (-1); + } + escaped = 0; + label = bp++; + if ((c = *src++) == 0) + goto done; + else if (c != '.') { + errno = EINVAL; + return (-1); + } + continue; + } + else if ((cp = strchr(digits, c)) != NULL) { + n = (cp - digits) * 100; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + errno = EMSGSIZE; + return (-1); + } + n += (cp - digits) * 10; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + errno = EMSGSIZE; + return (-1); + } + n += (cp - digits); + if (n > 255) { + errno = EMSGSIZE; + return (-1); + } + c = n; + } + escaped = 0; + } else if (c == '\\') { + escaped = 1; + continue; + } else if (c == '.') { + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ + errno = EMSGSIZE; + return (-1); + } + if (label >= eom) { + errno = EMSGSIZE; + return (-1); + } + *label = c; + /* Fully qualified ? */ + if (*src == '\0') { + if (c != 0) { + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = '\0'; + } + if ((bp - dst) > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + if (dstlen != NULL) + *dstlen = (bp - dst); + return (1); + } + if (c == 0 || *src == '.') { + errno = EMSGSIZE; + return (-1); + } + label = bp++; + continue; + } + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = (u_char)c; + } + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ + errno = EMSGSIZE; + return (-1); + } + done: + if (label >= eom) { + errno = EMSGSIZE; + return (-1); + } + *label = c; + if (c != 0) { + if (bp >= eom) { + errno = EMSGSIZE; + return (-1); + } + *bp++ = 0; + } + if ((bp - dst) > MAXCDNAME) { /*%< src too big */ + errno = EMSGSIZE; + return (-1); + } + if (dstlen != NULL) + *dstlen = (bp - dst); + return (0); +} + +/*% + * Convert a network strings labels into all lowercase. + * + * return: + *\li Number of bytes written to buffer, or -1 (with errno set) + * + * notes: + *\li Enforces label and domain length limits. + */ + +int +ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) +{ + const u_char *cp; + u_char *dn, *eom; + u_char c; + u_int n; + int l; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + if (dn >= eom) { + errno = EMSGSIZE; + return (-1); + } + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Some kind of compression pointer. */ + errno = EMSGSIZE; + return (-1); + } + *dn++ = n; + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; + return (-1); + } + if (dn + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + for ((void)NULL; l > 0; l--) { + c = *cp++; + if (isascii(c) && isupper(c)) + *dn++ = tolower(c); + else + *dn++ = c; + } + } + *dn++ = '\0'; + return (dn - dst); +} + +/*% + * Unpack a domain name from a message, source may be compressed. + * + * return: + *\li -1 if it fails, or consumed octets if it succeeds. + */ +int +ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, + u_char *dst, size_t dstsiz) +{ + return (ns_name_unpack2(msg, eom, src, dst, dstsiz, NULL)); +} + +/* + * ns_name_unpack2(msg, eom, src, dst, dstsiz, *dstlen) + * Unpack a domain name from a message, source may be compressed. + * return: + * -1 if it fails, or consumed octets if it succeeds. + * side effect: + * fills in *dstlen (if non-NULL). + */ +int +ns_name_unpack2(const u_char *msg, const u_char *eom, const u_char *src, + u_char *dst, size_t dstsiz, size_t *dstlen) +{ + const u_char *srcp, *dstlim; + u_char *dstp; + int n, len, checked, l; + + len = -1; + checked = 0; + dstp = dst; + srcp = src; + dstlim = dst + dstsiz; + if (srcp < msg || srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + /* Fetch next label in domain name. */ + while ((n = *srcp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: + case NS_TYPE_ELT: + /* Limit checks. */ + if ((l = labellen(srcp - 1)) < 0) { + errno = EMSGSIZE; + return (-1); + } + if (dstp + l + 1 >= dstlim || srcp + l >= eom) { + errno = EMSGSIZE; + return (-1); + } + checked += l + 1; + *dstp++ = n; + memcpy(dstp, srcp, l); + dstp += l; + srcp += l; + break; + + case NS_CMPRSFLGS: + if (srcp >= eom) { + errno = EMSGSIZE; + return (-1); + } + if (len < 0) + len = srcp - src + 1; + srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); + if (srcp < msg || srcp >= eom) { /*%< Out of range. */ + errno = EMSGSIZE; + return (-1); + } + checked += 2; + /* + * Check for loops in the compressed name; + * if we've looked at the whole message, + * there must be a loop. + */ + if (checked >= eom - msg) { + errno = EMSGSIZE; + return (-1); + } + break; + + default: + errno = EMSGSIZE; + return (-1); /*%< flag error */ + } + } + *dstp++ = 0; + if (dstlen != NULL) + *dstlen = dstp - dst; + if (len < 0) + len = srcp - src; + return (len); +} + +/*% + * Pack domain name 'domain' into 'comp_dn'. + * + * return: + *\li Size of the compressed name, or -1. + * + * notes: + *\li 'dnptrs' is an array of pointers to previous compressed names. + *\li dnptrs[0] is a pointer to the beginning of the message. The array + * ends with NULL. + *\li 'lastdnptr' is a pointer to the end of the array pointed to + * by 'dnptrs'. + * + * Side effects: + *\li The list of pointers in dnptrs is updated for labels inserted into + * the message as we compress the name. If 'dnptr' is NULL, we don't + * try to compress names. If 'lastdnptr' is NULL, we don't update the + * list. + */ +int +ns_name_pack(const u_char *src, u_char *dst, int dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char *dstp; + const u_char **cpp, **lpp, *eob, *msg; + const u_char *srcp; + int n, l, first = 1; + + srcp = src; + dstp = dst; + eob = dstp + dstsiz; + lpp = cpp = NULL; + if (dnptrs != NULL) { + if ((msg = *dnptrs++) != NULL) { + for (cpp = dnptrs; *cpp != NULL; cpp++) + (void)NULL; + lpp = cpp; /*%< end of list to search */ + } + } else + msg = NULL; + + /* make sure the domain we are about to add is legal */ + l = 0; + do { + int l0; + + n = *srcp; + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + errno = EMSGSIZE; + return (-1); + } + if ((l0 = labellen(srcp)) < 0) { + errno = EINVAL; + return (-1); + } + l += l0 + 1; + if (l > MAXCDNAME) { + errno = EMSGSIZE; + return (-1); + } + srcp += l0 + 1; + } while (n != 0); + + /* from here on we need to reset compression pointer array on error */ + srcp = src; + do { + /* Look to see if we can use pointers. */ + n = *srcp; + if (n != 0 && msg != NULL) { + l = dn_find(srcp, msg, (const u_char * const *)dnptrs, + (const u_char * const *)lpp); + if (l >= 0) { + if (dstp + 1 >= eob) { + goto cleanup; + } + *dstp++ = (l >> 8) | NS_CMPRSFLGS; + *dstp++ = l % 256; + return (dstp - dst); + } + /* Not found, save it. */ + if (lastdnptr != NULL && cpp < lastdnptr - 1 && + (dstp - msg) < 0x4000 && first) { + *cpp++ = dstp; + *cpp = NULL; + first = 0; + } + } + /* copy label to buffer */ + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Should not happen. */ + goto cleanup; + } + n = labellen(srcp); + if (dstp + 1 + n >= eob) { + goto cleanup; + } + memcpy(dstp, srcp, n + 1); + srcp += n + 1; + dstp += n + 1; + } while (n != 0); + + if (dstp > eob) { +cleanup: + if (msg != NULL) + *lpp = NULL; + errno = EMSGSIZE; + return (-1); + } + return (dstp - dst); +} + +/*% + * Expand compressed domain name to presentation format. + * + * return: + *\li Number of bytes read out of `src', or -1 (with errno set). + * + * note: + *\li Root domain returns as "." not "". + */ +int +ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, size_t dstsiz) +{ + u_char tmp[NS_MAXCDNAME]; + int n; + + if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) + return (-1); + if (ns_name_ntop(tmp, dst, dstsiz) == -1) + return (-1); + return (n); +} + +/*% + * Compress a domain name into wire format, using compression pointers. + * + * return: + *\li Number of bytes consumed in `dst' or -1 (with errno set). + * + * notes: + *\li 'dnptrs' is an array of pointers to previous compressed names. + *\li dnptrs[0] is a pointer to the beginning of the message. + *\li The list ends with NULL. 'lastdnptr' is a pointer to the end of the + * array pointed to by 'dnptrs'. Side effect is to update the list of + * pointers for labels inserted into the message as we compress the name. + *\li If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' + * is NULL, we don't update the list. + */ +int +ns_name_compress(const char *src, u_char *dst, size_t dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char tmp[NS_MAXCDNAME]; + + if (ns_name_pton(src, tmp, sizeof tmp) == -1) + return (-1); + return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); +} + +/*% + * Reset dnptrs so that there are no active references to pointers at or + * after src. + */ +void +ns_name_rollback(const u_char *src, const u_char **dnptrs, + const u_char **lastdnptr) +{ + while (dnptrs < lastdnptr && *dnptrs != NULL) { + if (*dnptrs >= src) { + *dnptrs = NULL; + break; + } + dnptrs++; + } +} + +/*% + * Advance *ptrptr to skip over the compressed name it points at. + * + * return: + *\li 0 on success, -1 (with errno set) on failure. + */ +int +ns_name_skip(const u_char **ptrptr, const u_char *eom) +{ + const u_char *cp; + u_int n; + int l; + + cp = *ptrptr; + while (cp < eom && (n = *cp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: /*%< normal case, n == len */ + cp += n; + continue; + case NS_TYPE_ELT: /*%< EDNS0 extended label */ + if ((l = labellen(cp - 1)) < 0) { + errno = EMSGSIZE; /*%< XXX */ + return (-1); + } + cp += l; + continue; + case NS_CMPRSFLGS: /*%< indirection */ + cp++; + break; + default: /*%< illegal type */ + errno = EMSGSIZE; + return (-1); + } + break; + } + if (cp > eom) { + errno = EMSGSIZE; + return (-1); + } + *ptrptr = cp; + return (0); +} + +/* Find the number of octets an nname takes up, including the root label. + * (This is basically ns_name_skip() without compression-pointer support.) + * ((NOTE: can only return zero if passed-in namesiz argument is zero.)) + */ +ssize_t +ns_name_length(ns_nname_ct nname, size_t namesiz) { + ns_nname_ct orig = nname; + u_int n; + + while (namesiz-- > 0 && (n = *nname++) != 0) { + if ((n & NS_CMPRSFLGS) != 0) { + errno = EISDIR; + return (-1); + } + if (n > namesiz) { + errno = EMSGSIZE; + return (-1); + } + nname += n; + namesiz -= n; + } + return (nname - orig); +} + +/* Compare two nname's for equality. Return -1 on error (setting errno). + */ +int +ns_name_eq(ns_nname_ct a, size_t as, ns_nname_ct b, size_t bs) { + ns_nname_ct ae = a + as, be = b + bs; + int ac, bc; + + while (ac = *a, bc = *b, ac != 0 && bc != 0) { + if ((ac & NS_CMPRSFLGS) != 0 || (bc & NS_CMPRSFLGS) != 0) { + errno = EISDIR; + return (-1); + } + if (a + ac >= ae || b + bc >= be) { + errno = EMSGSIZE; + return (-1); + } + if (ac != bc || strncasecmp((const char *) ++a, + (const char *) ++b, ac) != 0) + return (0); + a += ac, b += bc; + } + return (ac == 0 && bc == 0); +} + +/* Is domain "A" owned by (at or below) domain "B"? + */ +int +ns_name_owned(ns_namemap_ct a, int an, ns_namemap_ct b, int bn) { + /* If A is shorter, it cannot be owned by B. */ + if (an < bn) + return (0); + + /* If they are unequal before the length of the shorter, A cannot... */ + while (bn > 0) { + if (a->len != b->len || + strncasecmp((const char *) a->base, + (const char *) b->base, a->len) != 0) + return (0); + a++, an--; + b++, bn--; + } + + /* A might be longer or not, but either way, B owns it. */ + return (1); +} + +/* Build an array of <base,len> tuples from an nname, top-down order. + * Return the number of tuples (labels) thus discovered. + */ +int +ns_name_map(ns_nname_ct nname, size_t namelen, ns_namemap_t map, int mapsize) { + u_int n; + int l; + + n = *nname++; + namelen--; + + /* Root zone? */ + if (n == 0) { + /* Extra data follows name? */ + if (namelen > 0) { + errno = EMSGSIZE; + return (-1); + } + return (0); + } + + /* Compression pointer? */ + if ((n & NS_CMPRSFLGS) != 0) { + errno = EISDIR; + return (-1); + } + + /* Label too long? */ + if (n > namelen) { + errno = EMSGSIZE; + return (-1); + } + + /* Recurse to get rest of name done first. */ + l = ns_name_map(nname + n, namelen - n, map, mapsize); + if (l < 0) + return (-1); + + /* Too many labels? */ + if (l >= mapsize) { + errno = ENAMETOOLONG; + return (-1); + } + + /* We're on our way back up-stack, store current map data. */ + map[l].base = nname; + map[l].len = n; + return (l + 1); +} + +/* Count the labels in a domain name. Root counts, so COM. has two. This + * is to make the result comparable to the result of ns_name_map(). + */ +int +ns_name_labels(ns_nname_ct nname, size_t namesiz) { + int ret = 0; + u_int n; + + while (namesiz-- > 0 && (n = *nname++) != 0) { + if ((n & NS_CMPRSFLGS) != 0) { + errno = EISDIR; + return (-1); + } + if (n > namesiz) { + errno = EMSGSIZE; + return (-1); + } + nname += n; + namesiz -= n; + ret++; + } + return (ret + 1); +} + +/* Private. */ + +/*% + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this characted special ("in need of quoting") ? + * + * return: + *\li boolean. + */ +static int +special(int ch) { + switch (ch) { + case 0x22: /*%< '"' */ + case 0x2E: /*%< '.' */ + case 0x3B: /*%< ';' */ + case 0x5C: /*%< '\\' */ + case 0x28: /*%< '(' */ + case 0x29: /*%< ')' */ + /* Special modifiers in zone files. */ + case 0x40: /*%< '@' */ + case 0x24: /*%< '$' */ + return (1); + default: + return (0); + } +} + +/*% + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this character visible and not a space when printed ? + * + * return: + *\li boolean. + */ +static int +printable(int ch) { + return (ch > 0x20 && ch < 0x7f); +} + +/*% + * Thinking in noninternationalized USASCII (per the DNS spec), + * convert this character to lower case if it's upper case. + */ +static int +mklower(int ch) { + if (ch >= 0x41 && ch <= 0x5A) + return (ch + 0x20); + return (ch); +} + +/*% + * Search for the counted-label name in an array of compressed names. + * + * return: + *\li offset from msg if found, or -1. + * + * notes: + *\li dnptrs is the pointer to the first name on the list, + *\li not the pointer to the start of the message. + */ +static int +dn_find(const u_char *domain, const u_char *msg, + const u_char * const *dnptrs, + const u_char * const *lastdnptr) +{ + const u_char *dn, *cp, *sp; + const u_char * const *cpp; + u_int n; + + for (cpp = dnptrs; cpp < lastdnptr; cpp++) { + sp = *cpp; + /* + * terminate search on: + * root label + * compression pointer + * unusable offset + */ + while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && + (sp - msg) < 0x4000) { + dn = domain; + cp = sp; + while ((n = *cp++) != 0) { + /* + * check for indirection + */ + switch (n & NS_CMPRSFLGS) { + case 0: /*%< normal case, n == len */ + n = labellen(cp - 1); /*%< XXX */ + if (n != *dn++) + goto next; + + for ((void)NULL; n > 0; n--) + if (mklower(*dn++) != + mklower(*cp++)) + goto next; + /* Is next root for both ? */ + if (*dn == '\0' && *cp == '\0') + return (sp - msg); + if (*dn) + continue; + goto next; + case NS_CMPRSFLGS: /*%< indirection */ + cp = msg + (((n & 0x3f) << 8) | *cp); + break; + + default: /*%< illegal type */ + errno = EMSGSIZE; + return (-1); + } + } + next: ; + sp += *sp + 1; + } + } + errno = ENOENT; + return (-1); +} + +static int +decode_bitstring(const unsigned char **cpp, char *dn, const char *eom) +{ + const unsigned char *cp = *cpp; + char *beg = dn, tc; + int b, blen, plen, i; + + if ((blen = (*cp & 0xff)) == 0) + blen = 256; + plen = (blen + 3) / 4; + plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1); + if (dn + plen >= eom) + return (-1); + + cp++; + i = SPRINTF((dn, "\\[x")); + if (i < 0) + return (-1); + dn += i; + for (b = blen; b > 7; b -= 8, cp++) { + i = SPRINTF((dn, "%02x", *cp & 0xff)); + if (i < 0) + return (-1); + dn += i; + } + if (b > 4) { + tc = *cp++; + i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b)))); + if (i < 0) + return (-1); + dn += i; + } else if (b > 0) { + tc = *cp++; + i = SPRINTF((dn, "%1x", + ((tc >> 4) & 0x0f) & (0x0f << (4 - b)))); + if (i < 0) + return (-1); + dn += i; + } + i = SPRINTF((dn, "/%d]", blen)); + if (i < 0) + return (-1); + dn += i; + + *cpp = cp; + return (dn - beg); +} + +static int +encode_bitsring(const char **bp, const char *end, unsigned char **labelp, + unsigned char ** dst, unsigned const char *eom) +{ + int afterslash = 0; + const char *cp = *bp; + unsigned char *tp; + char c; + const char *beg_blen; + char *end_blen = NULL; + int value = 0, count = 0, tbcount = 0, blen = 0; + + beg_blen = end_blen = NULL; + + /* a bitstring must contain at least 2 characters */ + if (end - cp < 2) + return (EINVAL); + + /* XXX: currently, only hex strings are supported */ + if (*cp++ != 'x') + return (EINVAL); + if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */ + return (EINVAL); + + for (tp = *dst + 1; cp < end && tp < eom; cp++) { + switch((c = *cp)) { + case ']': /*%< end of the bitstring */ + if (afterslash) { + if (beg_blen == NULL) + return (EINVAL); + blen = (int)strtol(beg_blen, &end_blen, 10); + if (*end_blen != ']') + return (EINVAL); + } + if (count) + *tp++ = ((value << 4) & 0xff); + cp++; /*%< skip ']' */ + goto done; + case '/': + afterslash = 1; + break; + default: + if (afterslash) { + if (!isdigit(c&0xff)) + return (EINVAL); + if (beg_blen == NULL) { + + if (c == '0') { + /* blen never begings with 0 */ + return (EINVAL); + } + beg_blen = cp; + } + } else { + if (!isxdigit(c&0xff)) + return (EINVAL); + value <<= 4; + value += digitvalue[(int)c]; + count += 4; + tbcount += 4; + if (tbcount > 256) + return (EINVAL); + if (count == 8) { + *tp++ = value; + count = 0; + } + } + break; + } + } + done: + if (cp >= end || tp >= eom) + return (EMSGSIZE); + + /* + * bit length validation: + * If a <length> is present, the number of digits in the <bit-data> + * MUST be just sufficient to contain the number of bits specified + * by the <length>. If there are insignificant bits in a final + * hexadecimal or octal digit, they MUST be zero. + * RFC2673, Section 3.2. + */ + if (blen > 0) { + int traillen; + + if (((blen + 3) & ~3) != tbcount) + return (EINVAL); + traillen = tbcount - blen; /*%< between 0 and 3 */ + if (((value << (8 - traillen)) & 0xff) != 0) + return (EINVAL); + } + else + blen = tbcount; + if (blen == 256) + blen = 0; + + /* encode the type and the significant bit fields */ + **labelp = DNS_LABELTYPE_BITSTRING; + **dst = blen; + + *bp = cp; + *dst = tp; + + return (0); +} + +static int +labellen(const u_char *lp) +{ + int bitlen; + u_char l = *lp; + + if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* should be avoided by the caller */ + return (-1); + } + + if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) { + if (l == DNS_LABELTYPE_BITSTRING) { + if ((bitlen = *(lp + 1)) == 0) + bitlen = 256; + return ((bitlen + 7 ) / 8 + 1); + } + return (-1); /*%< unknwon ELT */ + } + return (l); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_netint.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_netint.c new file mode 100644 index 0000000000..e196217f9b --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_netint.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_netint.c,v 1.3 2005/04/27 04:56:40 sra Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <arpa/nameser.h> + +#include "port_after.h" + +#pragma redefine_extname __ns_get16 __joy_ns_get16 +#pragma redefine_extname __ns_get32 __joy_ns_get32 + +/* Public. */ + +u_int +ns_get16(const u_char *src) { + u_int dst; + + NS_GET16(dst, src); + return (dst); +} + +u_long +ns_get32(const u_char *src) { + u_long dst; + + NS_GET32(dst, src); + return (dst); +} + +void +ns_put16(u_int src, u_char *dst) { + NS_PUT16(src, dst); +} + +void +ns_put32(u_long src, u_char *dst) { + NS_PUT32(src, dst); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_newmsg.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_newmsg.c new file mode 100644 index 0000000000..c18dd060e1 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_newmsg.c @@ -0,0 +1,273 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_newmsg.c,v 1.3 2009/02/26 10:48:57 marka Exp $"; +#endif + +#include <port_before.h> + +#include <arpa/nameser.h> + +#include <assert.h> +#include <errno.h> +#include <string.h> + +#include <port_after.h> + +static int rdcpy(ns_newmsg *, ns_type, const u_char *, size_t); + +/* Initialize a "newmsg" object to empty. + */ +int +ns_newmsg_init(u_char *buffer, size_t bufsiz, ns_newmsg *handle) { + ns_msg *msg = &handle->msg; + + memset(handle, 0, sizeof *handle); + msg->_msg = buffer; + msg->_eom = buffer + bufsiz; + msg->_sect = ns_s_qd; + msg->_rrnum = 0; + msg->_msg_ptr = buffer + NS_HFIXEDSZ; + handle->dnptrs[0] = msg->_msg; + handle->dnptrs[1] = NULL; + handle->lastdnptr = &handle->dnptrs[sizeof handle->dnptrs / + sizeof handle->dnptrs[0] - 1]; + return (0); +} + +/* Initialize a "newmsg" object by copying an existing parsed message. + */ +int +ns_newmsg_copy(ns_newmsg *handle, ns_msg *msg) { + ns_flag flag; + ns_sect sect; + + ns_newmsg_id(handle, ns_msg_id(*msg)); + for (flag = ns_f_qr; flag < ns_f_max; flag++) + ns_newmsg_flag(handle, flag, ns_msg_getflag(*msg, flag)); + for (sect = ns_s_qd; sect < ns_s_max; sect++) { + int i, count; + + count = ns_msg_count(*msg, sect); + for (i = 0; i < count; i++) { + ns_rr2 rr; + int x; + + if (ns_parserr2(msg, sect, i, &rr) < 0) + return (-1); + if (sect == ns_s_qd) + x = ns_newmsg_q(handle, + ns_rr_nname(rr), + ns_rr_type(rr), + ns_rr_class(rr)); + else + x = ns_newmsg_rr(handle, sect, + ns_rr_nname(rr), + ns_rr_type(rr), + ns_rr_class(rr), + ns_rr_ttl(rr), + ns_rr_rdlen(rr), + ns_rr_rdata(rr)); + if (x < 0) + return (-1); + } + } + return (0); +} + +/* Set the message-ID in a "newmsg" object. + */ +void +ns_newmsg_id(ns_newmsg *handle, u_int16_t id) { + ns_msg *msg = &handle->msg; + + msg->_id = id; +} + +/* Set a flag (including rcode or opcode) in a "newmsg" object. + */ +void +ns_newmsg_flag(ns_newmsg *handle, ns_flag flag, u_int value) { + extern struct _ns_flagdata _ns_flagdata[16]; + struct _ns_flagdata *fd = &_ns_flagdata[flag]; + ns_msg *msg = &handle->msg; + + assert(flag < ns_f_max); + msg->_flags &= (~fd->mask); + msg->_flags |= (value << fd->shift); +} + +/* Add a question (or zone, if it's an update) to a "newmsg" object. + */ +int +ns_newmsg_q(ns_newmsg *handle, ns_nname_ct qname, + ns_type qtype, ns_class qclass) +{ + ns_msg *msg = &handle->msg; + u_char *t; + int n; + + if (msg->_sect != ns_s_qd) { + errno = ENODEV; + return (-1); + } + t = (u_char *) (unsigned long) msg->_msg_ptr; + if (msg->_rrnum == 0) + msg->_sections[ns_s_qd] = t; + n = ns_name_pack(qname, t, msg->_eom - t, + handle->dnptrs, handle->lastdnptr); + if (n < 0) + return (-1); + t += n; + if (t + QFIXEDSZ >= msg->_eom) { + errno = EMSGSIZE; + return (-1); + } + NS_PUT16(qtype, t); + NS_PUT16(qclass, t); + msg->_msg_ptr = t; + msg->_counts[ns_s_qd] = ++msg->_rrnum; + return (0); +} + +/* Add an RR to a "newmsg" object. + */ +int +ns_newmsg_rr(ns_newmsg *handle, ns_sect sect, + ns_nname_ct name, ns_type type, + ns_class rr_class, u_int32_t ttl, + u_int16_t rdlen, const u_char *rdata) +{ + ns_msg *msg = &handle->msg; + u_char *t; + int n; + + if (sect < msg->_sect) { + errno = ENODEV; + return (-1); + } + t = (u_char *) (unsigned long) msg->_msg_ptr; + if (sect > msg->_sect) { + msg->_sect = sect; + msg->_sections[sect] = t; + msg->_rrnum = 0; + } + n = ns_name_pack(name, t, msg->_eom - t, + handle->dnptrs, handle->lastdnptr); + if (n < 0) + return (-1); + t += n; + if (t + RRFIXEDSZ + rdlen >= msg->_eom) { + errno = EMSGSIZE; + return (-1); + } + NS_PUT16(type, t); + NS_PUT16(rr_class, t); + NS_PUT32(ttl, t); + msg->_msg_ptr = t; + if (rdcpy(handle, type, rdata, rdlen) < 0) + return (-1); + msg->_counts[sect] = ++msg->_rrnum; + return (0); +} + +/* Complete a "newmsg" object and return its size for use in write(). + * (Note: the "newmsg" object is also made ready for ns_parserr() etc.) + */ +size_t +ns_newmsg_done(ns_newmsg *handle) { + ns_msg *msg = &handle->msg; + ns_sect sect; + u_char *t; + + t = (u_char *) (unsigned long) msg->_msg; + NS_PUT16(msg->_id, t); + NS_PUT16(msg->_flags, t); + for (sect = 0; sect < ns_s_max; sect++) + NS_PUT16(msg->_counts[sect], t); + msg->_eom = msg->_msg_ptr; + msg->_sect = ns_s_max; + msg->_rrnum = -1; + msg->_msg_ptr = NULL; + return (msg->_eom - msg->_msg); +} + +/* Private. */ + +/* Copy an RDATA, using compression pointers where RFC1035 permits. + */ +static int +rdcpy(ns_newmsg *handle, ns_type type, const u_char *rdata, size_t rdlen) { + ns_msg *msg = &handle->msg; + u_char *p = (u_char *) (unsigned long) msg->_msg_ptr; + u_char *t = p + NS_INT16SZ; + u_char *s = t; + int n; + + switch (type) { + case ns_t_soa: + /* MNAME. */ + n = ns_name_pack(rdata, t, msg->_eom - t, + handle->dnptrs, handle->lastdnptr); + if (n < 0) + return (-1); + t += n; + if (ns_name_skip(&rdata, msg->_eom) < 0) + return (-1); + + /* ANAME. */ + n = ns_name_pack(rdata, t, msg->_eom - t, + handle->dnptrs, handle->lastdnptr); + if (n < 0) + return (-1); + t += n; + if (ns_name_skip(&rdata, msg->_eom) < 0) + return (-1); + + /* Serial, Refresh, Retry, Expiry, and Minimum. */ + if ((msg->_eom - t) < (NS_INT32SZ * 5)) { + errno = EMSGSIZE; + return (-1); + } + memcpy(t, rdata, NS_INT32SZ * 5); + t += (NS_INT32SZ * 5); + break; + case ns_t_ptr: + case ns_t_cname: + case ns_t_ns: + /* PTRDNAME, CNAME, or NSDNAME. */ + n = ns_name_pack(rdata, t, msg->_eom - t, + handle->dnptrs, handle->lastdnptr); + if (n < 0) + return (-1); + t += n; + break; + default: + memcpy(t, rdata, rdlen); + t += rdlen; + } + NS_PUT16(t - s, p); + msg->_msg_ptr = t; + return (0); +} + diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_parse.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_parse.c new file mode 100644 index 0000000000..ba11eea707 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_parse.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_parse.c,v 1.10 2009/01/23 19:59:16 each Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv_joy.h> +#include <string.h> + +#include "port_after.h" + +/* Forward. */ + +static void setsection(ns_msg *msg, ns_sect sect); + +/* Macros. */ + +#if !defined(SOLARIS2) || defined(__COVERITY__) +#define RETERR(err) do { errno = (err); return (-1); } while (0) +#else +#define RETERR(err) \ + do { errno = (err); if (errno == errno) return (-1); } while (0) +#endif + +#define PARSE_FMT_PRESO 0 /* Parse using presentation-format names */ +#define PARSE_FMT_WIRE 1 /* Parse using network-format names */ + +/* Public. */ + +/* These need to be in the same order as the nres.h:ns_flag enum. */ +struct _ns_flagdata _ns_flagdata[16] = { + { 0x8000, 15 }, /*%< qr. */ + { 0x7800, 11 }, /*%< opcode. */ + { 0x0400, 10 }, /*%< aa. */ + { 0x0200, 9 }, /*%< tc. */ + { 0x0100, 8 }, /*%< rd. */ + { 0x0080, 7 }, /*%< ra. */ + { 0x0040, 6 }, /*%< z. */ + { 0x0020, 5 }, /*%< ad. */ + { 0x0010, 4 }, /*%< cd. */ + { 0x000f, 0 }, /*%< rcode. */ + { 0x0000, 0 }, /*%< expansion (1/6). */ + { 0x0000, 0 }, /*%< expansion (2/6). */ + { 0x0000, 0 }, /*%< expansion (3/6). */ + { 0x0000, 0 }, /*%< expansion (4/6). */ + { 0x0000, 0 }, /*%< expansion (5/6). */ + { 0x0000, 0 }, /*%< expansion (6/6). */ +}; + +int ns_msg_getflag(ns_msg handle, int flag) { + return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift); +} + +int +ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { + const u_char *optr = ptr; + + for ((void)NULL; count > 0; count--) { + int b, rdlength; + + b = dn_skipname(ptr, eom); + if (b < 0) + RETERR(EMSGSIZE); + ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; + if (section != ns_s_qd) { + if (ptr + NS_INT32SZ + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + ptr += NS_INT32SZ/*TTL*/; + NS_GET16(rdlength, ptr); + ptr += rdlength/*RData*/; + } + } + if (ptr > eom) + RETERR(EMSGSIZE); + return (ptr - optr); +} + +int +ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { + const u_char *eom = msg + msglen; + int i; + + handle->_msg = msg; + handle->_eom = eom; + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_id, msg); + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_flags, msg); + for (i = 0; i < ns_s_max; i++) { + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_counts[i], msg); + } + for (i = 0; i < ns_s_max; i++) + if (handle->_counts[i] == 0) + handle->_sections[i] = NULL; + else { + int b = ns_skiprr(msg, eom, (ns_sect)i, + handle->_counts[i]); + + if (b < 0) + return (-1); + handle->_sections[i] = msg; + msg += b; + } + if (msg != eom) + RETERR(EMSGSIZE); + setsection(handle, ns_s_max); + return (0); +} + +int +ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { + int b; + int tmp; + + /* Make section right. */ + tmp = section; + if (tmp < 0 || section >= ns_s_max) + RETERR(ENODEV); + if (section != handle->_sect) + setsection(handle, section); + + /* Make rrnum right. */ + if (rrnum == -1) + rrnum = handle->_rrnum; + if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) + RETERR(ENODEV); + if (rrnum < handle->_rrnum) + setsection(handle, section); + if (rrnum > handle->_rrnum) { + b = ns_skiprr(handle->_msg_ptr, handle->_eom, section, + rrnum - handle->_rrnum); + + if (b < 0) + return (-1); + handle->_msg_ptr += b; + handle->_rrnum = rrnum; + } + + /* Do the parse. */ + b = dn_expand(handle->_msg, handle->_eom, + handle->_msg_ptr, rr->name, NS_MAXDNAME); + if (b < 0) + return (-1); + handle->_msg_ptr += b; + if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET16(rr->type, handle->_msg_ptr); + NS_GET16(rr->rr_class, handle->_msg_ptr); + if (section == ns_s_qd) { + rr->ttl = 0; + rr->rdlength = 0; + rr->rdata = NULL; + } else { + if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET32(rr->ttl, handle->_msg_ptr); + NS_GET16(rr->rdlength, handle->_msg_ptr); + if (handle->_msg_ptr + rr->rdlength > handle->_eom) + RETERR(EMSGSIZE); + rr->rdata = handle->_msg_ptr; + handle->_msg_ptr += rr->rdlength; + } + if (++handle->_rrnum > handle->_counts[(int)section]) + setsection(handle, (ns_sect)((int)section + 1)); + + /* All done. */ + return (0); +} + +/* + * This is identical to the above but uses network-format (uncompressed) names. + */ +int +ns_parserr2(ns_msg *handle, ns_sect section, int rrnum, ns_rr2 *rr) { + int b; + int tmp; + + /* Make section right. */ + if ((tmp = section) < 0 || section >= ns_s_max) + RETERR(ENODEV); + if (section != handle->_sect) + setsection(handle, section); + + /* Make rrnum right. */ + if (rrnum == -1) + rrnum = handle->_rrnum; + if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) + RETERR(ENODEV); + if (rrnum < handle->_rrnum) + setsection(handle, section); + if (rrnum > handle->_rrnum) { + b = ns_skiprr(handle->_msg_ptr, handle->_eom, section, + rrnum - handle->_rrnum); + + if (b < 0) + return (-1); + handle->_msg_ptr += b; + handle->_rrnum = rrnum; + } + + /* Do the parse. */ + b = ns_name_unpack2(handle->_msg, handle->_eom, handle->_msg_ptr, + rr->nname, NS_MAXNNAME, &rr->nnamel); + if (b < 0) + return (-1); + handle->_msg_ptr += b; + if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET16(rr->type, handle->_msg_ptr); + NS_GET16(rr->rr_class, handle->_msg_ptr); + if (section == ns_s_qd) { + rr->ttl = 0; + rr->rdlength = 0; + rr->rdata = NULL; + } else { + if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET32(rr->ttl, handle->_msg_ptr); + NS_GET16(rr->rdlength, handle->_msg_ptr); + if (handle->_msg_ptr + rr->rdlength > handle->_eom) + RETERR(EMSGSIZE); + rr->rdata = handle->_msg_ptr; + handle->_msg_ptr += rr->rdlength; + } + if (++handle->_rrnum > handle->_counts[(int)section]) + setsection(handle, (ns_sect)((int)section + 1)); + + /* All done. */ + return (0); +} + +/* Private. */ + +static void +setsection(ns_msg *msg, ns_sect sect) { + msg->_sect = sect; + if (sect == ns_s_max) { + msg->_rrnum = -1; + msg->_msg_ptr = NULL; + } else { + msg->_rrnum = 0; + msg->_msg_ptr = msg->_sections[(int)sect]; + } +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_print.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_print.c new file mode 100644 index 0000000000..e70df376c1 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_print.c @@ -0,0 +1,1242 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_print.c,v 1.12 2009/03/03 05:29:58 each Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <isc/assertions.h> +#include <isc/dst.h> +#include <errno.h> +#include <resolv_joy.h> +#include <string.h> +#include <ctype.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static size_t prune_origin(const char *name, const char *origin); +static int charstr(const u_char *rdata, const u_char *edata, + char **buf, size_t *buflen); +static int addname(const u_char *msg, size_t msglen, + const u_char **p, const char *origin, + char **buf, size_t *buflen); +static void addlen(size_t len, char **buf, size_t *buflen); +static int addstr(const char *src, size_t len, + char **buf, size_t *buflen); +static int addtab(size_t len, size_t target, int spaced, + char **buf, size_t *buflen); + +/* Macros. */ + +#define T(x) \ + do { \ + if ((x) < 0) \ + return (-1); \ + } while (0) + +static const char base32hex[] = + "0123456789ABCDEFGHIJKLMNOPQRSTUV=0123456789abcdefghijklmnopqrstuv"; + +/* Public. */ + +/*% + * Convert an RR to presentation format. + * + * return: + *\li Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrr(const ns_msg *handle, const ns_rr *rr, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + int n; + + n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), + ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), + ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), + name_ctx, origin, buf, buflen); + return (n); +} + +/*% + * Convert the fields of an RR into presentation format. + * + * return: + *\li Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrrf(const u_char *msg, size_t msglen, + const char *name, ns_class class, ns_type type, + u_long ttl, const u_char *rdata, size_t rdlen, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + const char *obuf = buf; + const u_char *edata = rdata + rdlen; + int spaced = 0; + + const char *comment; + char tmp[100]; + int len, x; + + /* + * Owner. + */ + if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { + T(addstr("\t\t\t", 3, &buf, &buflen)); + } else { + len = prune_origin(name, origin); + if (*name == '\0') { + goto root; + } else if (len == 0) { + T(addstr("@\t\t\t", 4, &buf, &buflen)); + } else { + T(addstr(name, len, &buf, &buflen)); + /* Origin not used or not root, and no trailing dot? */ + if (((origin == NULL || origin[0] == '\0') || + (origin[0] != '.' && origin[1] != '\0' && + name[len] == '\0')) && name[len - 1] != '.') { + root: + T(addstr(".", 1, &buf, &buflen)); + len++; + } + T(spaced = addtab(len, 24, spaced, &buf, &buflen)); + } + } + + /* + * TTL, Class, Type. + */ + T(x = ns_format_ttl(ttl, buf, buflen)); + addlen(x, &buf, &buflen); + len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); + T(addstr(tmp, len, &buf, &buflen)); + T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); + + /* + * RData. + */ + switch (type) { + case ns_t_a: + if (rdlen != (size_t)NS_INADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + case ns_t_dname: + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + + case ns_t_hinfo: + case ns_t_isdn: + /* First word. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + + /* Second word, optional in ISDN records. */ + if (type == ns_t_isdn && rdata == edata) + break; + + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_soa: { + u_long t; + + /* Server name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Administrator name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" (\n", 3, &buf, &buflen)); + spaced = 0; + + if ((edata - rdata) != 5*NS_INT32SZ) + goto formerr; + + /* Serial number. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + len = SPRINTF((tmp, "%lu", t)); + T(addstr(tmp, len, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; serial\n", 9, &buf, &buflen)); + spaced = 0; + + /* Refresh interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; refresh\n", 10, &buf, &buflen)); + spaced = 0; + + /* Retry interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; retry\n", 8, &buf, &buflen)); + spaced = 0; + + /* Expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; expiry\n", 9, &buf, &buflen)); + spaced = 0; + + /* Minimum TTL. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(addstr(" )", 2, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; minimum\n", 10, &buf, &buflen)); + + break; + } + + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: + case ns_t_kx: { + u_int t; + + if (rdlen < (size_t)NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Target. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_px: { + u_int t; + + if (rdlen < (size_t)NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_x25: + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_txt: + case ns_t_spf: + while (rdata < edata) { + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + if (rdata < edata) + T(addstr(" ", 1, &buf, &buflen)); + } + break; + + case ns_t_nsap: { + char t[2+255*3]; + + (void) inet_nsap_ntoa(rdlen, rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_aaaa: + if (rdlen != (size_t)NS_IN6ADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET6, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_loc: { + char t[255]; + + /* XXX protocol format checking? */ + (void) loc_ntoa(rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_naptr: { + u_int order, preference; + char t[50]; + + if (rdlen < 2U*NS_INT16SZ) + goto formerr; + + /* Order, Precedence. */ + order = ns_get16(rdata); rdata += NS_INT16SZ; + preference = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u ", order, preference)); + T(addstr(t, len, &buf, &buflen)); + + /* Flags. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Service. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Regexp. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len < 0) + return (-1); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_srv: { + u_int priority, weight, port; + char t[50]; + + if (rdlen < 3U*NS_INT16SZ) + goto formerr; + + /* Priority, Weight, Port. */ + priority = ns_get16(rdata); rdata += NS_INT16SZ; + weight = ns_get16(rdata); rdata += NS_INT16SZ; + port = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u %u ", priority, weight, port)); + T(addstr(t, len, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_minfo: + case ns_t_rp: + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + + case ns_t_wks: { + int n, lcnt; + + if (rdlen < 1U + NS_INT32SZ) + goto formerr; + + /* Address. */ + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += NS_INADDRSZ; + + /* Protocol. */ + len = SPRINTF((tmp, " %u ( ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata += NS_INT8SZ; + + /* Bit map. */ + n = 0; + lcnt = 0; + while (rdata < edata) { + u_int c = *rdata++; + do { + if (c & 0200) { + if (lcnt == 0) { + T(addstr("\n\t\t\t\t", 5, + &buf, &buflen)); + lcnt = 10; + spaced = 0; + } + len = SPRINTF((tmp, "%d ", n)); + T(addstr(tmp, len, &buf, &buflen)); + lcnt--; + } + c <<= 1; + } while (++n & 07); + } + T(addstr(")", 1, &buf, &buflen)); + + break; + } + + case ns_t_key: + case ns_t_dnskey: { + char base64_key[NS_MD5RSA_MAX_BASE64]; + u_int keyflags, protocol, algorithm, key_id; + const char *leader; + int n; + + if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) + goto formerr; + + /* Key flags, Protocol, Algorithm. */ + key_id = dst_s_dns_key_id(rdata, edata-rdata); + keyflags = ns_get16(rdata); rdata += NS_INT16SZ; + protocol = *rdata++; + algorithm = *rdata++; + len = SPRINTF((tmp, "0x%04x %u %u", + keyflags, protocol, algorithm)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Public key data. */ + len = b64_ntop(rdata, edata - rdata, + base64_key, sizeof base64_key); + if (len < 0) + goto formerr; + if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } else + leader = " "; + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + n = SPRINTF((tmp, " ; key_tag= %u", key_id)); + T(addstr(tmp, n, &buf, &buflen)); + + break; + } + + case ns_t_sig: + case ns_t_rrsig: { + char base64_key[NS_MD5RSA_MAX_BASE64]; + u_int type, algorithm, labels, footprint; + const char *leader; + u_long t; + int n; + + if (rdlen < 22U) + goto formerr; + + /* Type covered, Algorithm, Label count, Original TTL. */ + type = ns_get16(rdata); rdata += NS_INT16SZ; + algorithm = *rdata++; + labels = *rdata++; + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s %d %d %lu ", + p_type(type), algorithm, labels, t)); + T(addstr(tmp, len, &buf, &buflen)); + if (labels > (u_int)dn_count_labels(name)) + goto formerr; + + /* Signature expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Time signed. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Signature Footprint. */ + footprint = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", footprint)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Signer's name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + /* Signature. */ + len = b64_ntop(rdata, edata - rdata, + base64_key, sizeof base64_key); + if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } else + leader = " "; + if (len < 0) + goto formerr; + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + break; + } + + case ns_t_nxt: { + int n, c; + + /* Next domain name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + /* Type bit map. */ + n = edata - rdata; + for (c = 0; c < n*8; c++) + if (NS_NXT_BIT_ISSET(c, rdata)) { + len = SPRINTF((tmp, " %s", p_type(c))); + T(addstr(tmp, len, &buf, &buflen)); + } + break; + } + + case ns_t_cert: { + u_int c_type, key_tag, alg; + int n; + unsigned int siz; + char base64_cert[8192], tmp[40]; + const char *leader; + + c_type = ns_get16(rdata); rdata += NS_INT16SZ; + key_tag = ns_get16(rdata); rdata += NS_INT16SZ; + alg = (u_int) *rdata++; + + len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg)); + T(addstr(tmp, len, &buf, &buflen)); + siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ + if (siz > sizeof(base64_cert) * 3/4) { + const char *str = "record too long to print"; + T(addstr(str, strlen(str), &buf, &buflen)); + } + else { + len = b64_ntop(rdata, edata-rdata, base64_cert, siz); + + if (len < 0) + goto formerr; + else if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } + else + leader = " "; + + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), + &buf, &buflen)); + T(addstr(base64_cert + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + } + break; + } + + case ns_t_tkey: { + /* KJD - need to complete this */ + u_long t; + int mode, err, keysize; + + /* Algorithm name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Inception. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Experation. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Mode , Error, Key Size. */ + /* Priority, Weight, Port. */ + mode = ns_get16(rdata); rdata += NS_INT16SZ; + err = ns_get16(rdata); rdata += NS_INT16SZ; + keysize = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); + T(addstr(tmp, len, &buf, &buflen)); + + /* XXX need to dump key, print otherdata length & other data */ + break; + } + + case ns_t_tsig: { + /* BEW - need to complete this */ + int n; + + T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + rdata += 8; /*%< time */ + n = ns_get16(rdata); rdata += INT16SZ; + rdata += n; /*%< sig */ + n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */ + sprintf(buf, "%d", ns_get16(rdata)); + rdata += INT16SZ; + addlen(strlen(buf), &buf, &buflen); + break; + } + + case ns_t_a6: { + struct in6_addr a; + int pbyte, pbit; + + /* prefix length */ + if (rdlen == 0U) goto formerr; + len = SPRINTF((tmp, "%d ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + pbit = *rdata; + if (pbit > 128) goto formerr; + pbyte = (pbit & ~7) / 8; + rdata++; + + /* address suffix: provided only when prefix len != 128 */ + if (pbit < 128) { + if (rdata + pbyte >= edata) goto formerr; + memset(&a, 0, sizeof(a)); + memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); + (void) inet_ntop(AF_INET6, &a, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += sizeof(a) - pbyte; + } + + /* prefix name: provided only when prefix len > 0 */ + if (pbit == 0) + break; + if (rdata >= edata) goto formerr; + T(addstr(" ", 1, &buf, &buflen)); + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_opt: { + len = SPRINTF((tmp, "%u bytes", class)); + T(addstr(tmp, len, &buf, &buflen)); + break; + } + + case ns_t_ds: + case ns_t_dlv: + case ns_t_sshfp: { + u_int t; + + if (type == ns_t_ds || type == ns_t_dlv) { + if (rdlen < 4U) goto formerr; + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + } else + if (rdlen < 2U) goto formerr; + + len = SPRINTF((tmp, "%u ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata++; + + len = SPRINTF((tmp, "%u ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata++; + + while (rdata < edata) { + len = SPRINTF((tmp, "%02X", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata++; + } + break; + } + + case ns_t_nsec3: + case ns_t_nsec3param: { + u_int t, w, l, j, k, c; + + len = SPRINTF((tmp, "%u ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata++; + + len = SPRINTF((tmp, "%u ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata++; + + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + t = *rdata++; + if (t == 0) { + T(addstr("-", 1, &buf, &buflen)); + } else { + while (t-- > 0) { + len = SPRINTF((tmp, "%02X", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata++; + } + } + if (type == ns_t_nsec3param) + break; + T(addstr(" ", 1, &buf, &buflen)); + + t = *rdata++; + while (t > 0) { + switch (t) { + case 1: + tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; + tmp[1] = base32hex[((rdata[0]<<2)&0x1c)]; + tmp[2] = tmp[3] = tmp[4] = '='; + tmp[5] = tmp[6] = tmp[7] = '='; + break; + case 2: + tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; + tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| + ((rdata[1]>>6)&0x03)]; + tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; + tmp[3] = base32hex[((rdata[1]<<4)&0x10)]; + tmp[4] = tmp[5] = tmp[6] = tmp[7] = '='; + break; + case 3: + tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; + tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| + ((rdata[1]>>6)&0x03)]; + tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; + tmp[3] = base32hex[((rdata[1]<<4)&0x10)| + ((rdata[2]>>4)&0x0f)]; + tmp[4] = base32hex[((rdata[2]<<1)&0x1e)]; + tmp[5] = tmp[6] = tmp[7] = '='; + break; + case 4: + tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; + tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| + ((rdata[1]>>6)&0x03)]; + tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; + tmp[3] = base32hex[((rdata[1]<<4)&0x10)| + ((rdata[2]>>4)&0x0f)]; + tmp[4] = base32hex[((rdata[2]<<1)&0x1e)| + ((rdata[3]>>7)&0x01)]; + tmp[5] = base32hex[((rdata[3]>>2)&0x1f)]; + tmp[6] = base32hex[(rdata[3]<<3)&0x18]; + tmp[7] = '='; + break; + default: + tmp[0] = base32hex[((rdata[0]>>3)&0x1f)]; + tmp[1] = base32hex[((rdata[0]<<2)&0x1c)| + ((rdata[1]>>6)&0x03)]; + tmp[2] = base32hex[((rdata[1]>>1)&0x1f)]; + tmp[3] = base32hex[((rdata[1]<<4)&0x10)| + ((rdata[2]>>4)&0x0f)]; + tmp[4] = base32hex[((rdata[2]<<1)&0x1e)| + ((rdata[3]>>7)&0x01)]; + tmp[5] = base32hex[((rdata[3]>>2)&0x1f)]; + tmp[6] = base32hex[((rdata[3]<<3)&0x18)| + ((rdata[4]>>5)&0x07)]; + tmp[7] = base32hex[(rdata[4]&0x1f)]; + break; + } + T(addstr(tmp, 8, &buf, &buflen)); + if (t >= 5) { + rdata += 5; + t -= 5; + } else { + rdata += t; + t -= t; + } + } + + while (rdata < edata) { + w = *rdata++; + l = *rdata++; + for (j = 0; j < l; j++) { + if (rdata[j] == 0) + continue; + for (k = 0; k < 8; k++) { + if ((rdata[j] & (0x80 >> k)) == 0) + continue; + c = w * 256 + j * 8 + k; + len = SPRINTF((tmp, " %s", p_type(c))); + T(addstr(tmp, len, &buf, &buflen)); + } + } + rdata += l; + } + break; + } + + case ns_t_nsec: { + u_int w, l, j, k, c; + + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + while (rdata < edata) { + w = *rdata++; + l = *rdata++; + for (j = 0; j < l; j++) { + if (rdata[j] == 0) + continue; + for (k = 0; k < 8; k++) { + if ((rdata[j] & (0x80 >> k)) == 0) + continue; + c = w * 256 + j * 8 + k; + len = SPRINTF((tmp, " %s", p_type(c))); + T(addstr(tmp, len, &buf, &buflen)); + } + } + rdata += l; + } + break; + } + + case ns_t_dhcid: { + int n; + unsigned int siz; + char base64_dhcid[8192]; + const char *leader; + + siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ + if (siz > sizeof(base64_dhcid) * 3/4) { + const char *str = "record too long to print"; + T(addstr(str, strlen(str), &buf, &buflen)); + } else { + len = b64_ntop(rdata, edata-rdata, base64_dhcid, siz); + + if (len < 0) + goto formerr; + + else if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } + else + leader = " "; + + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), + &buf, &buflen)); + T(addstr(base64_dhcid + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + } + } + + case ns_t_ipseckey: { + int n; + unsigned int siz; + char base64_key[8192]; + const char *leader; + + if (rdlen < 2) + goto formerr; + + switch (rdata[1]) { + case 0: + case 3: + if (rdlen < 3) + goto formerr; + break; + case 1: + if (rdlen < 7) + goto formerr; + break; + case 2: + if (rdlen < 19) + goto formerr; + break; + default: + comment = "unknown IPSECKEY gateway type"; + goto hexify; + } + + len = SPRINTF((tmp, "%u ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata++; + + len = SPRINTF((tmp, "%u ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata++; + + len = SPRINTF((tmp, "%u ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata++; + + switch (rdata[-2]) { + case 0: + T(addstr(".", 1, &buf, &buflen)); + break; + case 1: + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += 4; + break; + case 2: + (void) inet_ntop(AF_INET6, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += 16; + break; + case 3: + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + if (rdata >= edata) + break; + + siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ + if (siz > sizeof(base64_key) * 3/4) { + const char *str = "record too long to print"; + T(addstr(str, strlen(str), &buf, &buflen)); + } else { + len = b64_ntop(rdata, edata-rdata, base64_key, siz); + + if (len < 0) + goto formerr; + + else if (len > 15) { + T(addstr(" (", 2, &buf, &buflen)); + leader = "\n\t\t"; + spaced = 0; + } + else + leader = " "; + + for (n = 0; n < len; n += 48) { + T(addstr(leader, strlen(leader), + &buf, &buflen)); + T(addstr(base64_key + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + } + } + + case ns_t_hip: { + unsigned int i, hip_len, algorithm, key_len; + char base64_key[NS_MD5RSA_MAX_BASE64]; + unsigned int siz; + const char *leader = "\n\t\t\t\t\t"; + + hip_len = *rdata++; + algorithm = *rdata++; + key_len = ns_get16(rdata); + rdata += NS_INT16SZ; + + siz = key_len*4/3 + 4; /* "+4" accounts for trailing \0 */ + if (siz > sizeof(base64_key) * 3/4) { + const char *str = "record too long to print"; + T(addstr(str, strlen(str), &buf, &buflen)); + } else { + len = sprintf(tmp, "( %u ", algorithm); + T(addstr(tmp, len, &buf, &buflen)); + + for (i = 0; i < hip_len; i++) { + len = sprintf(tmp, "%02X", *rdata); + T(addstr(tmp, len, &buf, &buflen)); + rdata++; + } + T(addstr(leader, strlen(leader), &buf, &buflen)); + + len = b64_ntop(rdata, key_len, base64_key, siz); + if (len < 0) + goto formerr; + + T(addstr(base64_key, len, &buf, &buflen)); + + rdata += key_len; + while (rdata < edata) { + T(addstr(leader, strlen(leader), &buf, &buflen)); + T(addname(msg, msglen, &rdata, origin, + &buf, &buflen)); + } + T(addstr(" )", 2, &buf, &buflen)); + } + break; + } + + default: + comment = "unknown RR type"; + goto hexify; + } + return (buf - obuf); + formerr: + comment = "RR format error"; + hexify: { + int n, m; + char *p; + + len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata), + rdlen != 0U ? " (" : "", comment)); + T(addstr(tmp, len, &buf, &buflen)); + while (rdata < edata) { + p = tmp; + p += SPRINTF((p, "\n\t")); + spaced = 0; + n = MIN(16, edata - rdata); + for (m = 0; m < n; m++) + p += SPRINTF((p, "%02x ", rdata[m])); + T(addstr(tmp, p - tmp, &buf, &buflen)); + if (n < 16) { + T(addstr(")", 1, &buf, &buflen)); + T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); + } + p = tmp; + p += SPRINTF((p, "; ")); + for (m = 0; m < n; m++) + *p++ = (isascii(rdata[m]) && isprint(rdata[m])) + ? rdata[m] + : '.'; + T(addstr(tmp, p - tmp, &buf, &buflen)); + rdata += n; + } + return (buf - obuf); + } +} + +/* Private. */ + +/*% + * size_t + * prune_origin(name, origin) + * Find out if the name is at or under the current origin. + * return: + * Number of characters in name before start of origin, + * or length of name if origin does not match. + * notes: + * This function should share code with samedomain(). + */ +static size_t +prune_origin(const char *name, const char *origin) { + const char *oname = name; + + while (*name != '\0') { + if (origin != NULL && ns_samename(name, origin) == 1) + return (name - oname - (name > oname)); + while (*name != '\0') { + if (*name == '\\') { + name++; + /* XXX need to handle \nnn form. */ + if (*name == '\0') + break; + } else if (*name == '.') { + name++; + break; + } + name++; + } + } + return (name - oname); +} + +/*% + * int + * charstr(rdata, edata, buf, buflen) + * Format a <character-string> into the presentation buffer. + * return: + * Number of rdata octets consumed + * 0 for protocol format error + * -1 for output buffer error + * side effects: + * buffer is advanced on success. + */ +static int +charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { + const u_char *odata = rdata; + size_t save_buflen = *buflen; + char *save_buf = *buf; + + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + if (rdata < edata) { + int n = *rdata; + + if (rdata + 1 + n <= edata) { + rdata++; + while (n-- > 0) { + if (strchr("\n\"\\", *rdata) != NULL) + if (addstr("\\", 1, buf, buflen) < 0) + goto enospc; + if (addstr((const char *)rdata, 1, + buf, buflen) < 0) + goto enospc; + rdata++; + } + } + } + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + return (rdata - odata); + enospc: + errno = ENOSPC; + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static int +addname(const u_char *msg, size_t msglen, + const u_char **pp, const char *origin, + char **buf, size_t *buflen) +{ + size_t newlen, save_buflen = *buflen; + char *save_buf = *buf; + int n; + + n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); + if (n < 0) + goto enospc; /*%< Guess. */ + newlen = prune_origin(*buf, origin); + if (**buf == '\0') { + goto root; + } else if (newlen == 0U) { + /* Use "@" instead of name. */ + if (newlen + 2 > *buflen) + goto enospc; /* No room for "@\0". */ + (*buf)[newlen++] = '@'; + (*buf)[newlen] = '\0'; + } else { + if (((origin == NULL || origin[0] == '\0') || + (origin[0] != '.' && origin[1] != '\0' && + (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { + /* No trailing dot. */ + root: + if (newlen + 2 > *buflen) + goto enospc; /* No room for ".\0". */ + (*buf)[newlen++] = '.'; + (*buf)[newlen] = '\0'; + } + } + *pp += n; + addlen(newlen, buf, buflen); + **buf = '\0'; + return (newlen); + enospc: + errno = ENOSPC; + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static void +addlen(size_t len, char **buf, size_t *buflen) { + INSIST(len <= *buflen); + *buf += len; + *buflen -= len; +} + +static int +addstr(const char *src, size_t len, char **buf, size_t *buflen) { + if (len >= *buflen) { + errno = ENOSPC; + return (-1); + } + memcpy(*buf, src, len); + addlen(len, buf, buflen); + **buf = '\0'; + return (0); +} + +static int +addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { + size_t save_buflen = *buflen; + char *save_buf = *buf; + int t; + + if (spaced || len >= target - 1) { + T(addstr(" ", 2, buf, buflen)); + spaced = 1; + } else { + for (t = (target - len - 1) / 8; t >= 0; t--) + if (addstr("\t", 1, buf, buflen) < 0) { + *buflen = save_buflen; + *buf = save_buf; + return (-1); + } + spaced = 0; + } + return (spaced); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_rdata.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_rdata.c new file mode 100644 index 0000000000..eac4052278 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_rdata.c @@ -0,0 +1,300 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_rdata.c,v 1.2 2009/01/23 23:49:15 tbox Exp $"; +#endif + +#include "port_before.h" + +#if __OpenBSD__ +#include <sys/types.h> +#endif +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv_joy.h> +#include <string.h> + +#include "port_after.h" + +#define CONSUME_SRC \ + do { \ + rdata += n, rdlen -= n; \ + } while (0) + +#define CONSUME_DST \ + do { \ + nrdata += n, nrdsiz -= n, nrdlen += n; \ + } while (0) + +#define UNPACK_DNAME \ + do { \ + size_t t; \ + \ + if ((n = ns_name_unpack2(msg,eom,rdata,nrdata,nrdsiz,&t))<0) {\ + errno = EMSGSIZE; \ + return (-1); \ + } \ + CONSUME_SRC; \ + n = t; \ + CONSUME_DST; \ + } while (0) + +#define UNPACK_SOME(x) \ + do { \ + n = (x); \ + if ((size_t)n > rdlen || (size_t)n > nrdsiz) { \ + errno = EMSGSIZE; \ + return (-1); \ + } \ + memcpy(nrdata, rdata, n); \ + CONSUME_SRC; CONSUME_DST; \ + } while (0) + +#define UNPACK_REST(x) \ + do { \ + n = (x); \ + if ((size_t)n != rdlen) { \ + errno = EMSGSIZE; \ + return (-1); \ + } \ + memcpy(nrdata, rdata, n); \ + CONSUME_SRC; CONSUME_DST; \ + } while (0) + +ssize_t +ns_rdata_unpack(const u_char *msg, const u_char *eom, + ns_type type, const u_char *rdata, size_t rdlen, + u_char *nrdata, size_t nrdsiz) +{ + size_t nrdlen = 0; + int n; + + switch (type) { + case ns_t_a: + UNPACK_REST(NS_INADDRSZ); + break; + case ns_t_aaaa: + UNPACK_REST(NS_IN6ADDRSZ); + break; + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + case ns_t_dname: + UNPACK_DNAME; + break; + case ns_t_soa: + UNPACK_DNAME; + UNPACK_DNAME; + UNPACK_SOME(NS_INT32SZ * 5); + break; + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: + UNPACK_SOME(NS_INT16SZ); + UNPACK_DNAME; + break; + case ns_t_px: + UNPACK_SOME(NS_INT16SZ); + UNPACK_DNAME; + UNPACK_DNAME; + break; + case ns_t_srv: + UNPACK_SOME(NS_INT16SZ * 3); + UNPACK_DNAME; + break; + case ns_t_minfo: + case ns_t_rp: + UNPACK_DNAME; + UNPACK_DNAME; + break; + default: + UNPACK_SOME(rdlen); + break; + } + if (rdlen > 0) { + errno = EMSGSIZE; + return (-1); + } + return (nrdlen); +} + +#define EQUAL_CONSUME \ + do { \ + rdata1 += n, rdlen1 -= n; \ + rdata2 += n, rdlen2 -= n; \ + } while (0) + +#define EQUAL_DNAME \ + do { \ + ssize_t n; \ + \ + if (rdlen1 != rdlen2) \ + return (0); \ + n = ns_name_eq(rdata1, rdlen1, rdata2, rdlen2); \ + if (n <= 0) \ + return (n); \ + n = rdlen1; \ + EQUAL_CONSUME; \ + } while (0) + +#define EQUAL_SOME(x) \ + do { \ + size_t n = (x); \ + \ + if (n > rdlen1 || n > rdlen2) { \ + errno = EMSGSIZE; \ + return (-1); \ + } \ + if (memcmp(rdata1, rdata2, n) != 0) \ + return (0); \ + EQUAL_CONSUME; \ + } while (0) + +int +ns_rdata_equal(ns_type type, + const u_char *rdata1, size_t rdlen1, + const u_char *rdata2, size_t rdlen2) +{ + switch (type) { + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + case ns_t_dname: + EQUAL_DNAME; + break; + case ns_t_soa: + /* "There can be only one." --Highlander */ + break; + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: + EQUAL_SOME(NS_INT16SZ); + EQUAL_DNAME; + break; + case ns_t_px: + EQUAL_SOME(NS_INT16SZ); + EQUAL_DNAME; + EQUAL_DNAME; + break; + case ns_t_srv: + EQUAL_SOME(NS_INT16SZ * 3); + EQUAL_DNAME; + break; + case ns_t_minfo: + case ns_t_rp: + EQUAL_DNAME; + EQUAL_DNAME; + break; + default: + EQUAL_SOME(rdlen1); + break; + } + if (rdlen1 != 0 || rdlen2 != 0) + return (0); + return (1); +} + +#define REFERS_DNAME \ + do { \ + int n; \ + \ + n = ns_name_eq(rdata, rdlen, nname, NS_MAXNNAME); \ + if (n < 0) \ + return (-1); \ + if (n > 0) \ + return (1); \ + n = dn_skipname(rdata, rdata + rdlen); \ + if (n < 0) \ + return (-1); \ + CONSUME_SRC; \ + } while (0) + +#define REFERS_SOME(x) \ + do { \ + size_t n = (x); \ + \ + if (n > rdlen) { \ + errno = EMSGSIZE; \ + return (-1); \ + } \ + CONSUME_SRC; \ + } while (0) + +int +ns_rdata_refers(ns_type type, + const u_char *rdata, size_t rdlen, + const u_char *nname) +{ + switch (type) { + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + case ns_t_dname: + REFERS_DNAME; + break; + case ns_t_soa: + REFERS_DNAME; + REFERS_DNAME; + REFERS_SOME(NS_INT32SZ * 5); + break; + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: + REFERS_SOME(NS_INT16SZ); + REFERS_DNAME; + break; + case ns_t_px: + REFERS_SOME(NS_INT16SZ); + REFERS_DNAME; + REFERS_DNAME; + break; + case ns_t_srv: + REFERS_SOME(NS_INT16SZ * 3); + REFERS_DNAME; + break; + case ns_t_minfo: + case ns_t_rp: + REFERS_DNAME; + REFERS_DNAME; + break; + default: + REFERS_SOME(rdlen); + break; + } + if (rdlen != 0) { + errno = EMSGSIZE; + return (-1); + } + return (0); +} diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_samedomain.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_samedomain.c new file mode 100644 index 0000000000..5e9f5cab54 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_samedomain.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_samedomain.c,v 1.6 2005/04/27 04:56:40 sra Exp $"; +#endif + +#include "port_before.h" + +#include <sys/types.h> +#include <arpa/nameser.h> +#include <errno.h> +#include <string.h> + +#include "port_after.h" + +/*% + * Check whether a name belongs to a domain. + * + * Inputs: + *\li a - the domain whose ancestory is being verified + *\li b - the potential ancestor we're checking against + * + * Return: + *\li boolean - is a at or below b? + * + * Notes: + *\li Trailing dots are first removed from name and domain. + * Always compare complete subdomains, not only whether the + * domain name is the trailing string of the given name. + * + *\li "host.foobar.top" lies in "foobar.top" and in "top" and in "" + * but NOT in "bar.top" + */ + +int +ns_samedomain(const char *a, const char *b) { + size_t la, lb; + int diff, i, escaped; + const char *cp; + + la = strlen(a); + lb = strlen(b); + + /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */ + if (la != 0U && a[la - 1] == '.') { + escaped = 0; + /* Note this loop doesn't get executed if la==1. */ + for (i = la - 2; i >= 0; i--) + if (a[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + la--; + } + + /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */ + if (lb != 0U && b[lb - 1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if lb==1 */ + for (i = lb - 2; i >= 0; i--) + if (b[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + lb--; + } + + /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */ + if (lb == 0U) + return (1); + + /* 'b' longer than 'a' means 'a' can't be in 'b'. */ + if (lb > la) + return (0); + + /* 'a' and 'b' being equal at this point indicates sameness. */ + if (lb == la) + return (strncasecmp(a, b, lb) == 0); + + /* Ok, we know la > lb. */ + + diff = la - lb; + + /* + * If 'a' is only 1 character longer than 'b', then it can't be + * a subdomain of 'b' (because of the need for the '.' label + * separator). + */ + if (diff < 2) + return (0); + + /* + * If the character before the last 'lb' characters of 'b' + * isn't '.', then it can't be a match (this lets us avoid + * having "foobar.com" match "bar.com"). + */ + if (a[diff - 1] != '.') + return (0); + + /* + * We're not sure about that '.', however. It could be escaped + * and thus not a really a label separator. + */ + escaped = 0; + for (i = diff - 2; i >= 0; i--) + if (a[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (escaped) + return (0); + + /* Now compare aligned trailing substring. */ + cp = a + diff; + return (strncasecmp(cp, b, lb) == 0); +} + +/*% + * is "a" a subdomain of "b"? + */ +int +ns_subdomain(const char *a, const char *b) { + return (ns_samename(a, b) != 1 && ns_samedomain(a, b)); +} + +/*% + * make a canonical copy of domain name "src" + * + * notes: + * \code + * foo -> foo. + * foo. -> foo. + * foo.. -> foo. + * foo\. -> foo\.. + * foo\\. -> foo\\. + * \endcode + */ + +int +ns_makecanon(const char *src, char *dst, size_t dstsize) { + size_t n = strlen(src); + + if (n + sizeof "." > dstsize) { /*%< Note: sizeof == 2 */ + errno = EMSGSIZE; + return (-1); + } + strcpy(dst, src); + while (n >= 1U && dst[n - 1] == '.') /*%< Ends in "." */ + if (n >= 2U && dst[n - 2] == '\\' && /*%< Ends in "\." */ + (n < 3U || dst[n - 3] != '\\')) /*%< But not "\\." */ + break; + else + dst[--n] = '\0'; + dst[n++] = '.'; + dst[n] = '\0'; + return (0); +} + +/*% + * determine whether domain name "a" is the same as domain name "b" + * + * return: + *\li -1 on error + *\li 0 if names differ + *\li 1 if names are the same + */ + +int +ns_samename(const char *a, const char *b) { + char ta[NS_MAXDNAME], tb[NS_MAXDNAME]; + + if (ns_makecanon(a, ta, sizeof ta) < 0 || + ns_makecanon(b, tb, sizeof tb) < 0) + return (-1); + if (strcasecmp(ta, tb) == 0) + return (1); + else + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_sign.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_sign.c new file mode 100644 index 0000000000..fc7dd19f7b --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_sign.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999 by Internet Software Consortium, Inc. + * + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_sign.c,v 1.6 2006/03/09 23:57:56 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <isc/dst.h> +#include <isc/assertions.h> + +#include "port_after.h" + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eob) { \ + errno = EMSGSIZE; \ + return(NS_TSIG_ERROR_NO_SPACE); \ + } \ + } while (0) + +/*% + * ns_sign + * + * Parameters: + *\li msg message to be sent + *\li msglen input - length of message + * output - length of signed message + *\li msgsize length of buffer containing message + *\li error value to put in the error field + *\li key tsig key used for signing + *\li querysig (response), the signature in the query + *\li querysiglen (response), the length of the signature in the query + *\li sig a buffer to hold the generated signature + *\li siglen input - length of signature buffer + * output - length of signature + * + * Errors: + *\li - bad input data (-1) + *\li - bad key / sign failed (-BADKEY) + *\li - not enough space (NS_TSIG_ERROR_NO_SPACE) + */ +int +ns_sign(u_char *msg, int *msglen, int msgsize, int error, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t in_timesigned) +{ + return(ns_sign2(msg, msglen, msgsize, error, k, + querysig, querysiglen, sig, siglen, + in_timesigned, NULL, NULL)); +} + +int +ns_sign2(u_char *msg, int *msglen, int msgsize, int error, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t in_timesigned, u_char **dnptrs, u_char **lastdnptr) +{ + HEADER *hp = (HEADER *)msg; + DST_KEY *key = (DST_KEY *)k; + u_char *cp, *eob; + u_char *lenp; + u_char *alg; + int n; + time_t timesigned; + u_char name[NS_MAXCDNAME]; + + dst_init(); + if (msg == NULL || msglen == NULL || sig == NULL || siglen == NULL) + return (-1); + + cp = msg + *msglen; + eob = msg + msgsize; + + /* Name. */ + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + n = ns_name_pton(key->dk_key_name, name, sizeof name); + if (n != -1) + n = ns_name_pack(name, cp, eob - cp, + (const u_char **)dnptrs, + (const u_char **)lastdnptr); + + } else { + n = ns_name_pton("", name, sizeof name); + if (n != -1) + n = ns_name_pack(name, cp, eob - cp, NULL, NULL); + } + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + cp += n; + + /* Type, class, ttl, length (not filled in yet). */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(ns_t_tsig, cp); + PUTSHORT(ns_c_any, cp); + PUTLONG(0, cp); /*%< TTL */ + lenp = cp; + cp += 2; + + /* Alg. */ + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + if (key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL); + } + else + n = dn_comp("", cp, eob - cp, NULL, NULL); + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + alg = cp; + cp += n; + + /* Time. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(0, cp); + timesigned = time(NULL); + if (error != ns_r_badtime) + PUTLONG(timesigned, cp); + else + PUTLONG(in_timesigned, cp); + PUTSHORT(NS_TSIG_FUDGE, cp); + + /* Compute the signature. */ + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + void *ctx; + u_char buf[NS_MAXCDNAME], *cp2; + int n; + + dst_sign_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0); + + /* Digest the query signature, if this is a response. */ + if (querysiglen > 0 && querysig != NULL) { + u_int16_t len_n = htons(querysiglen); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, + (u_char *)&len_n, INT16SZ, NULL, 0); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, + querysig, querysiglen, NULL, 0); + } + + /* Digest the message. */ + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, msg, *msglen, + NULL, 0); + + /* Digest the key name. */ + n = ns_name_ntol(name, buf, sizeof(buf)); + INSIST(n > 0); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the class and TTL. */ + cp2 = buf; + PUTSHORT(ns_c_any, cp2); + PUTLONG(0, cp2); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf, + NULL, 0); + + /* Digest the algorithm. */ + n = ns_name_ntol(alg, buf, sizeof(buf)); + INSIST(n > 0); + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the time signed, fudge, error, and other data */ + cp2 = buf; + PUTSHORT(0, cp2); /*%< Top 16 bits of time */ + if (error != ns_r_badtime) + PUTLONG(timesigned, cp2); + else + PUTLONG(in_timesigned, cp2); + PUTSHORT(NS_TSIG_FUDGE, cp2); + PUTSHORT(error, cp2); /*%< Error */ + if (error != ns_r_badtime) + PUTSHORT(0, cp2); /*%< Other data length */ + else { + PUTSHORT(INT16SZ+INT32SZ, cp2); /*%< Other data length */ + PUTSHORT(0, cp2); /*%< Top 16 bits of time */ + PUTLONG(timesigned, cp2); + } + dst_sign_data(SIG_MODE_UPDATE, key, &ctx, buf, cp2-buf, + NULL, 0); + + n = dst_sign_data(SIG_MODE_FINAL, key, &ctx, NULL, 0, + sig, *siglen); + if (n < 0) + return (-ns_r_badkey); + *siglen = n; + } else + *siglen = 0; + + /* Add the signature. */ + BOUNDS_CHECK(cp, INT16SZ + (*siglen)); + PUTSHORT(*siglen, cp); + memcpy(cp, sig, *siglen); + cp += (*siglen); + + /* The original message ID & error. */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ); + PUTSHORT(ntohs(hp->id), cp); /*%< already in network order */ + PUTSHORT(error, cp); + + /* Other data. */ + BOUNDS_CHECK(cp, INT16SZ); + if (error != ns_r_badtime) + PUTSHORT(0, cp); /*%< Other data length */ + else { + PUTSHORT(INT16SZ+INT32SZ, cp); /*%< Other data length */ + BOUNDS_CHECK(cp, INT32SZ+INT16SZ); + PUTSHORT(0, cp); /*%< Top 16 bits of time */ + PUTLONG(timesigned, cp); + } + + /* Go back and fill in the length. */ + PUTSHORT(cp - lenp - INT16SZ, lenp); + + hp->arcount = htons(ntohs(hp->arcount) + 1); + *msglen = (cp - msg); + return (0); +} + +int +ns_sign_tcp_init(void *k, const u_char *querysig, int querysiglen, + ns_tcp_tsig_state *state) +{ + dst_init(); + if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0) + return (-1); + state->counter = -1; + state->key = k; + if (state->key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (querysiglen > (int)sizeof(state->sig)) + return (-1); + memcpy(state->sig, querysig, querysiglen); + state->siglen = querysiglen; + return (0); +} + +int +ns_sign_tcp(u_char *msg, int *msglen, int msgsize, int error, + ns_tcp_tsig_state *state, int done) +{ + return (ns_sign_tcp2(msg, msglen, msgsize, error, state, + done, NULL, NULL)); +} + +int +ns_sign_tcp2(u_char *msg, int *msglen, int msgsize, int error, + ns_tcp_tsig_state *state, int done, + u_char **dnptrs, u_char **lastdnptr) +{ + u_char *cp, *eob, *lenp; + u_char buf[MAXDNAME], *cp2; + HEADER *hp = (HEADER *)msg; + time_t timesigned; + int n; + + if (msg == NULL || msglen == NULL || state == NULL) + return (-1); + + state->counter++; + if (state->counter == 0) + return (ns_sign2(msg, msglen, msgsize, error, state->key, + state->sig, state->siglen, + state->sig, &state->siglen, 0, + dnptrs, lastdnptr)); + + if (state->siglen > 0) { + u_int16_t siglen_n = htons(state->siglen); + dst_sign_data(SIG_MODE_INIT, state->key, &state->ctx, + NULL, 0, NULL, 0); + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, + (u_char *)&siglen_n, INT16SZ, NULL, 0); + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, + state->sig, state->siglen, NULL, 0); + state->siglen = 0; + } + + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, msg, *msglen, + NULL, 0); + + if (done == 0 && (state->counter % 100 != 0)) + return (0); + + cp = msg + *msglen; + eob = msg + msgsize; + + /* Name. */ + n = dn_comp(state->key->dk_key_name, cp, eob - cp, dnptrs, lastdnptr); + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + cp += n; + + /* Type, class, ttl, length (not filled in yet). */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(ns_t_tsig, cp); + PUTSHORT(ns_c_any, cp); + PUTLONG(0, cp); /*%< TTL */ + lenp = cp; + cp += 2; + + /* Alg. */ + n = dn_comp(NS_TSIG_ALG_HMAC_MD5, cp, eob - cp, NULL, NULL); + if (n < 0) + return (NS_TSIG_ERROR_NO_SPACE); + cp += n; + + /* Time. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + PUTSHORT(0, cp); + timesigned = time(NULL); + PUTLONG(timesigned, cp); + PUTSHORT(NS_TSIG_FUDGE, cp); + + /* + * Compute the signature. + */ + + /* Digest the time signed and fudge. */ + cp2 = buf; + PUTSHORT(0, cp2); /*%< Top 16 bits of time */ + PUTLONG(timesigned, cp2); + PUTSHORT(NS_TSIG_FUDGE, cp2); + + dst_sign_data(SIG_MODE_UPDATE, state->key, &state->ctx, + buf, cp2 - buf, NULL, 0); + + n = dst_sign_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0, + state->sig, sizeof(state->sig)); + if (n < 0) + return (-ns_r_badkey); + state->siglen = n; + + /* Add the signature. */ + BOUNDS_CHECK(cp, INT16SZ + state->siglen); + PUTSHORT(state->siglen, cp); + memcpy(cp, state->sig, state->siglen); + cp += state->siglen; + + /* The original message ID & error. */ + BOUNDS_CHECK(cp, INT16SZ + INT16SZ); + PUTSHORT(ntohs(hp->id), cp); /*%< already in network order */ + PUTSHORT(error, cp); + + /* Other data. */ + BOUNDS_CHECK(cp, INT16SZ); + PUTSHORT(0, cp); + + /* Go back and fill in the length. */ + PUTSHORT(cp - lenp - INT16SZ, lenp); + + hp->arcount = htons(ntohs(hp->arcount) + 1); + *msglen = (cp - msg); + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_ttl.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_ttl.c new file mode 100644 index 0000000000..69c2f83f57 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_ttl.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_ttl.c,v 1.4 2005/07/28 06:51:49 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" + +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static int fmt1(int t, char s, char **buf, size_t *buflen); + +/* Macros. */ + +#define T(x) if ((x) < 0) return (-1); else (void)NULL + +/* Public. */ + +int +ns_format_ttl(u_long src, char *dst, size_t dstlen) { + char *odst = dst; + int secs, mins, hours, days, weeks, x; + char *p; + + secs = src % 60; src /= 60; + mins = src % 60; src /= 60; + hours = src % 24; src /= 24; + days = src % 7; src /= 7; + weeks = src; src = 0; + + x = 0; + if (weeks) { + T(fmt1(weeks, 'W', &dst, &dstlen)); + x++; + } + if (days) { + T(fmt1(days, 'D', &dst, &dstlen)); + x++; + } + if (hours) { + T(fmt1(hours, 'H', &dst, &dstlen)); + x++; + } + if (mins) { + T(fmt1(mins, 'M', &dst, &dstlen)); + x++; + } + if (secs || !(weeks || days || hours || mins)) { + T(fmt1(secs, 'S', &dst, &dstlen)); + x++; + } + + if (x > 1) { + int ch; + + for (p = odst; (ch = *p) != '\0'; p++) + if (isascii(ch) && isupper(ch)) + *p = tolower(ch); + } + + return (dst - odst); +} + +int +ns_parse_ttl(const char *src, u_long *dst) { + u_long ttl, tmp; + int ch, digits, dirty; + + ttl = 0; + tmp = 0; + digits = 0; + dirty = 0; + while ((ch = *src++) != '\0') { + if (!isascii(ch) || !isprint(ch)) + goto einval; + if (isdigit(ch)) { + tmp *= 10; + tmp += (ch - '0'); + digits++; + continue; + } + if (digits == 0) + goto einval; + if (islower(ch)) + ch = toupper(ch); + switch (ch) { + case 'W': tmp *= 7; + case 'D': tmp *= 24; + case 'H': tmp *= 60; + case 'M': tmp *= 60; + case 'S': break; + default: goto einval; + } + ttl += tmp; + tmp = 0; + digits = 0; + dirty = 1; + } + if (digits > 0) { + if (dirty) + goto einval; + else + ttl += tmp; + } else if (!dirty) + goto einval; + *dst = ttl; + return (0); + + einval: + errno = EINVAL; + return (-1); +} + +/* Private. */ + +static int +fmt1(int t, char s, char **buf, size_t *buflen) { + char tmp[50]; + size_t len; + + len = SPRINTF((tmp, "%d%c", t, s)); + if (len + 1 > *buflen) + return (-1); + strcpy(*buf, tmp); + *buf += len; + *buflen -= len; + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/nameser/ns_verify.c b/usr/src/lib/libresolv2_joy/common/nameser/ns_verify.c new file mode 100644 index 0000000000..b4b63d4641 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/nameser/ns_verify.c @@ -0,0 +1,484 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999 by Internet Software Consortium, Inc. + * + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 lint +static const char rcsid[] = "$Id: ns_verify.c,v 1.5 2006/03/09 23:57:56 marka Exp $"; +#endif + +/* Import. */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <isc/dst.h> + +#include "port_after.h" + +/* Private. */ + +#define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + return (NS_TSIG_ERROR_FORMERR); \ + } \ + } while (0) + +/* Public. */ + +u_char * +ns_find_tsig(u_char *msg, u_char *eom) { + HEADER *hp = (HEADER *)msg; + int n, type; + u_char *cp = msg, *start; + + if (msg == NULL || eom == NULL || msg > eom) + return (NULL); + + if (cp + HFIXEDSZ >= eom) + return (NULL); + + if (hp->arcount == 0) + return (NULL); + + cp += HFIXEDSZ; + + n = ns_skiprr(cp, eom, ns_s_qd, ntohs(hp->qdcount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_an, ntohs(hp->ancount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_ns, ntohs(hp->nscount)); + if (n < 0) + return (NULL); + cp += n; + + n = ns_skiprr(cp, eom, ns_s_ar, ntohs(hp->arcount) - 1); + if (n < 0) + return (NULL); + cp += n; + + start = cp; + n = dn_skipname(cp, eom); + if (n < 0) + return (NULL); + cp += n; + if (cp + INT16SZ >= eom) + return (NULL); + + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NULL); + return (start); +} + +/* ns_verify + * + * Parameters: + *\li statp res stuff + *\li msg received message + *\li msglen length of message + *\li key tsig key used for verifying. + *\li querysig (response), the signature in the query + *\li querysiglen (response), the length of the signature in the query + *\li sig (query), a buffer to hold the signature + *\li siglen (query), input - length of signature buffer + * output - length of signature + * + * Errors: + *\li - bad input (-1) + *\li - invalid dns message (NS_TSIG_ERROR_FORMERR) + *\li - TSIG is not present (NS_TSIG_ERROR_NO_TSIG) + *\li - key doesn't match (-ns_r_badkey) + *\li - TSIG verification fails with BADKEY (-ns_r_badkey) + *\li - TSIG verification fails with BADSIG (-ns_r_badsig) + *\li - TSIG verification fails with BADTIME (-ns_r_badtime) + *\li - TSIG verification succeeds, error set to BAKEY (ns_r_badkey) + *\li - TSIG verification succeeds, error set to BADSIG (ns_r_badsig) + *\li - TSIG verification succeeds, error set to BADTIME (ns_r_badtime) + */ +int +ns_verify(u_char *msg, int *msglen, void *k, + const u_char *querysig, int querysiglen, u_char *sig, int *siglen, + time_t *timesigned, int nostrip) +{ + HEADER *hp = (HEADER *)msg; + DST_KEY *key = (DST_KEY *)k; + u_char *cp = msg, *eom; + char name[MAXDNAME], alg[MAXDNAME]; + u_char *recstart, *rdatastart; + u_char *sigstart, *otherstart; + int n; + int error; + u_int16_t type, length; + u_int16_t fudge, sigfieldlen, otherfieldlen; + + dst_init(); + if (msg == NULL || msglen == NULL || *msglen < 0) + return (-1); + + eom = msg + *msglen; + + recstart = ns_find_tsig(msg, eom); + if (recstart == NULL) + return (NS_TSIG_ERROR_NO_TSIG); + + cp = recstart; + + /* Read the key name. */ + n = dn_expand(msg, eom, cp, name, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + cp += n; + + /* Read the type. */ + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NS_TSIG_ERROR_NO_TSIG); + + /* Skip the class and TTL, save the length. */ + cp += INT16SZ + INT32SZ; + GETSHORT(length, cp); + if (eom - cp != length) + return (NS_TSIG_ERROR_FORMERR); + + /* Read the algorithm name. */ + rdatastart = cp; + n = dn_expand(msg, eom, cp, alg, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1) + return (-ns_r_badkey); + cp += n; + + /* Read the time signed and fudge. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + cp += INT16SZ; + GETLONG((*timesigned), cp); + GETSHORT(fudge, cp); + + /* Read the signature. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(sigfieldlen, cp); + BOUNDS_CHECK(cp, sigfieldlen); + sigstart = cp; + cp += sigfieldlen; + + /* Skip id and read error. */ + BOUNDS_CHECK(cp, 2*INT16SZ); + cp += INT16SZ; + GETSHORT(error, cp); + + /* Parse the other data. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(otherfieldlen, cp); + BOUNDS_CHECK(cp, otherfieldlen); + otherstart = cp; + cp += otherfieldlen; + + if (cp != eom) + return (NS_TSIG_ERROR_FORMERR); + + /* Verify that the key used is OK. */ + if (key != NULL) { + if (key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (error != ns_r_badsig && error != ns_r_badkey) { + if (ns_samename(key->dk_key_name, name) != 1) + return (-ns_r_badkey); + } + } + + hp->arcount = htons(ntohs(hp->arcount) - 1); + + /* + * Do the verification. + */ + + if (key != NULL && error != ns_r_badsig && error != ns_r_badkey) { + void *ctx; + u_char buf[MAXDNAME]; + u_char buf2[MAXDNAME]; + + /* Digest the query signature, if this is a response. */ + dst_verify_data(SIG_MODE_INIT, key, &ctx, NULL, 0, NULL, 0); + if (querysiglen > 0 && querysig != NULL) { + u_int16_t len_n = htons(querysiglen); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + (u_char *)&len_n, INT16SZ, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + querysig, querysiglen, NULL, 0); + } + + /* Digest the message. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, msg, recstart - msg, + NULL, 0); + + /* Digest the key name. */ + n = ns_name_pton(name, buf2, sizeof(buf2)); + if (n < 0) + return (-1); + n = ns_name_ntol(buf2, buf, sizeof(buf)); + if (n < 0) + return (-1); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the class and TTL. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + recstart + dn_skipname(recstart, eom) + INT16SZ, + INT16SZ + INT32SZ, NULL, 0); + + /* Digest the algorithm. */ + n = ns_name_pton(alg, buf2, sizeof(buf2)); + if (n < 0) + return (-1); + n = ns_name_ntol(buf2, buf, sizeof(buf)); + if (n < 0) + return (-1); + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, buf, n, NULL, 0); + + /* Digest the time signed and fudge. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + rdatastart + dn_skipname(rdatastart, eom), + INT16SZ + INT32SZ + INT16SZ, NULL, 0); + + /* Digest the error and other data. */ + dst_verify_data(SIG_MODE_UPDATE, key, &ctx, + otherstart - INT16SZ - INT16SZ, + otherfieldlen + INT16SZ + INT16SZ, NULL, 0); + + n = dst_verify_data(SIG_MODE_FINAL, key, &ctx, NULL, 0, + sigstart, sigfieldlen); + + if (n < 0) + return (-ns_r_badsig); + + if (sig != NULL && siglen != NULL) { + if (*siglen < sigfieldlen) + return (NS_TSIG_ERROR_NO_SPACE); + memcpy(sig, sigstart, sigfieldlen); + *siglen = sigfieldlen; + } + } else { + if (sigfieldlen > 0) + return (NS_TSIG_ERROR_FORMERR); + if (sig != NULL && siglen != NULL) + *siglen = 0; + } + + /* Reset the counter, since we still need to check for badtime. */ + hp->arcount = htons(ntohs(hp->arcount) + 1); + + /* Verify the time. */ + if (abs((*timesigned) - time(NULL)) > fudge) + return (-ns_r_badtime); + + if (nostrip == 0) { + *msglen = recstart - msg; + hp->arcount = htons(ntohs(hp->arcount) - 1); + } + + if (error != NOERROR) + return (error); + + return (0); +} + +int +ns_verify_tcp_init(void *k, const u_char *querysig, int querysiglen, + ns_tcp_tsig_state *state) +{ + dst_init(); + if (state == NULL || k == NULL || querysig == NULL || querysiglen < 0) + return (-1); + state->counter = -1; + state->key = k; + if (state->key->dk_alg != KEY_HMAC_MD5) + return (-ns_r_badkey); + if (querysiglen > (int)sizeof(state->sig)) + return (-1); + memcpy(state->sig, querysig, querysiglen); + state->siglen = querysiglen; + return (0); +} + +int +ns_verify_tcp(u_char *msg, int *msglen, ns_tcp_tsig_state *state, + int required) +{ + HEADER *hp = (HEADER *)msg; + u_char *recstart, *sigstart; + unsigned int sigfieldlen, otherfieldlen; + u_char *cp, *eom, *cp2; + char name[MAXDNAME], alg[MAXDNAME]; + u_char buf[MAXDNAME]; + int n, type, length, fudge, error; + time_t timesigned; + + if (msg == NULL || msglen == NULL || state == NULL) + return (-1); + + eom = msg + *msglen; + + state->counter++; + if (state->counter == 0) + return (ns_verify(msg, msglen, state->key, + state->sig, state->siglen, + state->sig, &state->siglen, ×igned, 0)); + + if (state->siglen > 0) { + u_int16_t siglen_n = htons(state->siglen); + + dst_verify_data(SIG_MODE_INIT, state->key, &state->ctx, + NULL, 0, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + (u_char *)&siglen_n, INT16SZ, NULL, 0); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + state->sig, state->siglen, NULL, 0); + state->siglen = 0; + } + + cp = recstart = ns_find_tsig(msg, eom); + + if (recstart == NULL) { + if (required) + return (NS_TSIG_ERROR_NO_TSIG); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + msg, *msglen, NULL, 0); + return (0); + } + + hp->arcount = htons(ntohs(hp->arcount) - 1); + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + msg, recstart - msg, NULL, 0); + + /* Read the key name. */ + n = dn_expand(msg, eom, cp, name, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + cp += n; + + /* Read the type. */ + BOUNDS_CHECK(cp, 2*INT16SZ + INT32SZ + INT16SZ); + GETSHORT(type, cp); + if (type != ns_t_tsig) + return (NS_TSIG_ERROR_NO_TSIG); + + /* Skip the class and TTL, save the length. */ + cp += INT16SZ + INT32SZ; + GETSHORT(length, cp); + if (eom - cp != length) + return (NS_TSIG_ERROR_FORMERR); + + /* Read the algorithm name. */ + n = dn_expand(msg, eom, cp, alg, MAXDNAME); + if (n < 0) + return (NS_TSIG_ERROR_FORMERR); + if (ns_samename(alg, NS_TSIG_ALG_HMAC_MD5) != 1) + return (-ns_r_badkey); + cp += n; + + /* Verify that the key used is OK. */ + if ((ns_samename(state->key->dk_key_name, name) != 1 || + state->key->dk_alg != KEY_HMAC_MD5)) + return (-ns_r_badkey); + + /* Read the time signed and fudge. */ + BOUNDS_CHECK(cp, INT16SZ + INT32SZ + INT16SZ); + cp += INT16SZ; + GETLONG(timesigned, cp); + GETSHORT(fudge, cp); + + /* Read the signature. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(sigfieldlen, cp); + BOUNDS_CHECK(cp, sigfieldlen); + sigstart = cp; + cp += sigfieldlen; + + /* Skip id and read error. */ + BOUNDS_CHECK(cp, 2*INT16SZ); + cp += INT16SZ; + GETSHORT(error, cp); + + /* Parse the other data. */ + BOUNDS_CHECK(cp, INT16SZ); + GETSHORT(otherfieldlen, cp); + BOUNDS_CHECK(cp, otherfieldlen); + cp += otherfieldlen; + + if (cp != eom) + return (NS_TSIG_ERROR_FORMERR); + + /* + * Do the verification. + */ + + /* Digest the time signed and fudge. */ + cp2 = buf; + PUTSHORT(0, cp2); /*%< Top 16 bits of time. */ + PUTLONG(timesigned, cp2); + PUTSHORT(NS_TSIG_FUDGE, cp2); + + dst_verify_data(SIG_MODE_UPDATE, state->key, &state->ctx, + buf, cp2 - buf, NULL, 0); + + n = dst_verify_data(SIG_MODE_FINAL, state->key, &state->ctx, NULL, 0, + sigstart, sigfieldlen); + if (n < 0) + return (-ns_r_badsig); + + if (sigfieldlen > sizeof(state->sig)) + return (NS_TSIG_ERROR_NO_SPACE); + + memcpy(state->sig, sigstart, sigfieldlen); + state->siglen = sigfieldlen; + + /* Verify the time. */ + if (abs(timesigned - time(NULL)) > fudge) + return (-ns_r_badtime); + + *msglen = recstart - msg; + + if (error != NOERROR) + return (error); + + return (0); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/herror.c b/usr/src/lib/libresolv2_joy/common/resolv/herror.c new file mode 100644 index 0000000000..568ce3ce68 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/herror.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 1987, 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. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: herror.c,v 1.4 2005/04/27 04:56:41 sra Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/uio.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <netdb.h> +#include <resolv_joy.h> +#include <string.h> +#include <unistd.h> +#include <irs.h> + +#include "port_after.h" + +const char *h_errlist[] = { + "Resolver Error 0 (no error)", + "Unknown host", /*%< 1 HOST_NOT_FOUND */ + "Host name lookup failure", /*%< 2 TRY_AGAIN */ + "Unknown server error", /*%< 3 NO_RECOVERY */ + "No address associated with name", /*%< 4 NO_ADDRESS */ +}; +int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; + +#if !(__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) +#undef h_errno +int h_errno; +#endif + +/*% + * herror -- + * print the error indicated by the h_errno value. + */ +void +herror(const char *s) { + struct iovec iov[4], *v = iov; + char *t; + + if (s != NULL && *s != '\0') { + DE_CONST(s, t); + v->iov_base = t; + v->iov_len = strlen(t); + v++; + DE_CONST(": ", t); + v->iov_base = t; + v->iov_len = 2; + v++; + } + DE_CONST(hstrerror(*__h_errno()), t); + v->iov_base = t; + v->iov_len = strlen(v->iov_base); + v++; + DE_CONST("\n", t); + v->iov_base = t; + v->iov_len = 1; + writev(STDERR_FILENO, iov, (v - iov) + 1); +} + +/*% + * hstrerror -- + * return the string associated with a given "host" errno value. + */ +const char * +hstrerror(int err) { + if (err < 0) + return ("Resolver internal error"); + else if (err < h_nerr) + return (h_errlist[err]); + return ("Unknown resolver error"); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/mtctxres.c b/usr/src/lib/libresolv2_joy/common/resolv/mtctxres.c new file mode 100644 index 0000000000..2e79b1e7b4 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/mtctxres.c @@ -0,0 +1,135 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#include <port_before.h> +#ifdef DO_PTHREADS +#include <pthread.h> +#endif +#include <errno.h> +#include <netdb.h> +#include <stdlib.h> +#include <string.h> +#include <resolv_mt.h> +#include <irs.h> +#include <port_after.h> + +#ifdef DO_PTHREADS +static pthread_key_t key; +static int mt_key_initialized = 0; + +static int __res_init_ctx(void); +static void __res_destroy_ctx(void *); + +#if defined(sun) && !defined(__GNUC__) +#pragma init (_mtctxres_init) +#endif +#endif + +static mtctxres_t sharedctx; + +#ifdef DO_PTHREADS +/* + * Initialize the TSD key. By doing this at library load time, we're + * implicitly running without interference from other threads, so there's + * no need for locking. + */ +static void +_mtctxres_init(void) { + int pthread_keycreate_ret; + + pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx); + if (pthread_keycreate_ret == 0) + mt_key_initialized = 1; +} +#endif + +/* + * To support binaries that used the private MT-safe interface in + * Solaris 8, we still need to provide the __res_enable_mt() + * and __res_disable_mt() entry points. They're do-nothing routines. + */ +int +__res_enable_mt(void) { + return (-1); +} + +int +__res_disable_mt(void) { + return (0); +} + +#ifdef DO_PTHREADS +static int +__res_init_ctx(void) { + + mtctxres_t *mt; + int ret; + + + if (pthread_getspecific(key) != 0) { + /* Already exists */ + return (0); + } + + if ((mt = malloc(sizeof (mtctxres_t))) == 0) { + errno = ENOMEM; + return (-1); + } + + memset(mt, 0, sizeof (mtctxres_t)); + + if ((ret = pthread_setspecific(key, mt)) != 0) { + free(mt); + errno = ret; + return (-1); + } + + return (0); +} + +static void +__res_destroy_ctx(void *value) { + + mtctxres_t *mt = (mtctxres_t *)value; + + if (mt != 0) + free(mt); +} +#endif + +mtctxres_t * +___mtctxres(void) { +#ifdef DO_PTHREADS + mtctxres_t *mt; + + /* + * This if clause should only be executed if we are linking + * statically. When linked dynamically _mtctxres_init() should + * be called at binding time due the #pragma above. + */ + if (!mt_key_initialized) { + static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER; + if (pthread_mutex_lock(&keylock) == 0) { + _mtctxres_init(); + (void) pthread_mutex_unlock(&keylock); + } + } + + /* + * If we have already been called in this thread return the existing + * context. Otherwise recreat a new context and return it. If + * that fails return a global context. + */ + if (mt_key_initialized) { + if (((mt = pthread_getspecific(key)) != 0) || + (__res_init_ctx() == 0 && + (mt = pthread_getspecific(key)) != 0)) { + return (mt); + } + } +#endif + return (&sharedctx); +} diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_comp.c b/usr/src/lib/libresolv2_joy/common/resolv/res_comp.c new file mode 100644 index 0000000000..c82bf01eb8 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_comp.c @@ -0,0 +1,287 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * 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. + */ + +/* + * 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 (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_comp.c,v 1.5 2005/07/28 06:51:50 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "port_after.h" + +#ifndef ORIGINAL_ISC_CODE +#pragma weak __dn_skipname = dn_skipname +#pragma weak __res_dnok = res_dnok +#pragma weak __res_hnok = res_hnok +#pragma weak __res_mailok = res_mailok +#pragma weak __res_ownok = res_ownok +#endif /* ORIGINAL_ISC_CODE */ + +/*% + * Expand compressed domain name 'src' to full domain name. + * + * \li 'msg' is a pointer to the begining of the message, + * \li 'eom' points to the first location after the message, + * \li 'dst' is a pointer to a buffer of size 'dstsiz' for the result. + * \li Return size of compressed name or -1 if there was an error. + */ +int +dn_expand(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, int dstsiz) +{ + int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); + + if (n > 0 && dst[0] == '.') + dst[0] = '\0'; + return (n); +} + +/*% + * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. + * + * \li Return the size of the compressed name or -1. + * \li 'length' is the size of the array pointed to by 'comp_dn'. + */ +int +dn_comp(const char *src, u_char *dst, int dstsiz, + u_char **dnptrs, u_char **lastdnptr) +{ + return (ns_name_compress(src, dst, (size_t)dstsiz, + (const u_char **)dnptrs, + (const u_char **)lastdnptr)); +} + + +/*% + * Skip over a compressed domain name. Return the size or -1. + */ +int +dn_skipname(const u_char *ptr, const u_char *eom) { + const u_char *saveptr = ptr; + + if (ns_name_skip(&ptr, eom) == -1) + return (-1); + return (ptr - saveptr); +} + +/*% + * Verify that a domain name uses an acceptable character set. + * + * Note the conspicuous absence of ctype macros in these definitions. On + * non-ASCII hosts, we can't depend on string literals or ctype macros to + * tell us anything about network-format data. The rest of the BIND system + * is not careful about this, but for some reason, we're doing it right here. + */ +#define PERIOD 0x2e +#define hyphenchar(c) ((c) == 0x2d) +#define bslashchar(c) ((c) == 0x5c) +#ifdef SUNW_HNOK_UNDERSCORE +#define underscorechar(c) ((c) == 0x5f) +#endif /* SUNW_HNOK_UNDERSCORE */ +#define periodchar(c) ((c) == PERIOD) +#define asterchar(c) ((c) == 0x2a) +#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ + || ((c) >= 0x61 && (c) <= 0x7a)) +#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) + +#define borderchar(c) (alphachar(c) || digitchar(c)) +#ifdef SUNW_HNOK_UNDERSCORE +#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c)) +#else +#define middlechar(c) (borderchar(c) || hyphenchar(c)) +#endif /* SUNW_HNOK_UNDERSCORE */ +#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) + +int +res_hnok(const char *dn) { + int pch = PERIOD, ch = *dn++; + + while (ch != '\0') { + int nch = *dn++; + + if (periodchar(ch)) { + (void)NULL; + } else if (periodchar(pch)) { + if (!borderchar(ch)) + return (0); + } else if (periodchar(nch) || nch == '\0') { + if (!borderchar(ch)) + return (0); + } else { + if (!middlechar(ch)) + return (0); + } + pch = ch, ch = nch; + } + return (1); +} + +/*% + * hostname-like (A, MX, WKS) owners can have "*" as their first label + * but must otherwise be as a host name. + */ +int +res_ownok(const char *dn) { + if (asterchar(dn[0])) { + if (periodchar(dn[1])) + return (res_hnok(dn+2)); + if (dn[1] == '\0') + return (1); + } + return (res_hnok(dn)); +} + +/*% + * SOA RNAMEs and RP RNAMEs can have any printable character in their first + * label, but the rest of the name has to look like a host name. + */ +int +res_mailok(const char *dn) { + int ch, escaped = 0; + + /* "." is a valid missing representation */ + if (*dn == '\0') + return (1); + + /* otherwise <label>.<hostname> */ + while ((ch = *dn++) != '\0') { + if (!domainchar(ch)) + return (0); + if (!escaped && periodchar(ch)) + break; + if (escaped) + escaped = 0; + else if (bslashchar(ch)) + escaped = 1; + } + if (periodchar(ch)) + return (res_hnok(dn)); + return (0); +} + +/*% + * This function is quite liberal, since RFC1034's character sets are only + * recommendations. + */ +int +res_dnok(const char *dn) { + int ch; + + while ((ch = *dn++) != '\0') + if (!domainchar(ch)) + return (0); + return (1); +} + +#ifdef BIND_4_COMPAT +/*% + * This module must export the following externally-visible symbols: + * ___putlong + * ___putshort + * __getlong + * __getshort + * Note that one _ comes from C and the others come from us. + */ + +#ifdef SOLARIS2 +#ifdef __putlong +#undef __putlong +#endif +#ifdef __putshort +#undef __putshort +#endif +#pragma weak putlong = __putlong +#pragma weak putshort = __putshort +#endif /* SOLARIS2 */ + +void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); } +void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); } +#ifndef __ultrix__ +u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); } +u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); } +#endif /*__ultrix__*/ +#endif /*BIND_4_COMPAT*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_data.c b/usr/src/lib/libresolv2_joy/common/resolv/res_data.c new file mode 100644 index 0000000000..f1e0dd030b --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_data.c @@ -0,0 +1,322 @@ +/* + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. + */ + + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1995-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char rcsid[] = "$Id: res_data.c,v 1.7 2008/12/11 09:59:00 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <res_update.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" + +#ifndef ORIGINAL_ISC_CODE +#pragma weak __fp_nquery = fp_nquery +#pragma weak __fp_query = fp_query +#pragma weak __p_query = p_query +#pragma weak __hostalias = hostalias +#pragma weak __res_randomid = res_randomid +#endif + +const char *_res_opcodes[] = { + "QUERY", + "IQUERY", + "CQUERYM", + "CQUERYU", /*%< experimental */ + "NOTIFY", /*%< experimental */ + "UPDATE", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "ZONEINIT", + "ZONEREF", +}; + +#ifdef BIND_UPDATE +const char *_res_sectioncodes[] = { + "ZONE", + "PREREQUISITES", + "UPDATE", + "ADDITIONAL", +}; +#endif + +#undef _res +#ifndef __BIND_NOSTATIC +struct __res_state _res +# if defined(__BIND_RES_TEXT) + = { RES_TIMEOUT, } /*%< Motorola, et al. */ +# endif + ; + +#ifdef ORIGINAL_ISC_CODE +#if defined(DO_PTHREADS) || defined(__linux) +#define _res (*__res_state()) +#endif +#endif + +/* Proto. */ + +int res_ourserver_p(const res_state, const struct sockaddr_in *); + +int +res_init(void) { + extern int __res_vinit(res_state, int); + + /* + * These three fields used to be statically initialized. This made + * it hard to use this code in a shared library. It is necessary, + * now that we're doing dynamic initialization here, that we preserve + * the old semantics: if an application modifies one of these three + * fields of _res before res_init() is called, res_init() will not + * alter them. Of course, if an application is setting them to + * _zero_ before calling res_init(), hoping to override what used + * to be the static default, we can't detect it and unexpected results + * will follow. Zero for any of these fields would make no sense, + * so one can safely assume that the applications were already getting + * unexpected results. + * + * _res.options is tricky since some apps were known to diddle the bits + * before res_init() was first called. We can't replicate that semantic + * with dynamic initialization (they may have turned bits off that are + * set in RES_DEFAULT). Our solution is to declare such applications + * "broken". They could fool us by setting RES_INIT but none do (yet). + */ + if (!_res.retrans) + _res.retrans = RES_TIMEOUT; + if (!_res.retry) + _res.retry = 4; + if (!(_res.options & RES_INIT)) + _res.options = RES_DEFAULT; + + /* + * This one used to initialize implicitly to zero, so unless the app + * has set it to something in particular, we can randomize it now. + */ + if (!_res.id) + _res.id = res_nrandomid(&_res); + + return (__res_vinit(&_res, 1)); +} + +void +p_query(const u_char *msg) { + fp_query(msg, stdout); +} + +void +fp_query(const u_char *msg, FILE *file) { + fp_nquery(msg, PACKETSZ, file); +} + +void +fp_nquery(const u_char *msg, int len, FILE *file) { + if ((_res.options & RES_INIT) == 0U && res_init() == -1) + return; + + res_pquery(&_res, msg, len, file); +} + +int +res_mkquery(int op, /*!< opcode of query */ + const char *dname, /*!< domain name */ + int class, int type, /*!< class and type of query */ + const u_char *data, /*!< resource record data */ + int datalen, /*!< length of data */ + const u_char *newrr_in, /*!< new rr for modify or append */ + u_char *buf, /*!< buffer to put query */ + int buflen) /*!< size of buffer */ +{ + if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + return (res_nmkquery(&_res, op, dname, class, type, + data, datalen, + newrr_in, buf, buflen)); +} + +int +res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { + if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nmkupdate(&_res, rrecp_in, buf, buflen)); +} + +int +res_query(const char *name, /*!< domain name */ + int class, int type, /*!< class and type of query */ + u_char *answer, /*!< buffer to put answer */ + int anslen) /*!< size of answer buffer */ +{ + if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + return (res_nquery(&_res, name, class, type, answer, anslen)); +} + +void +res_send_setqhook(res_send_qhook hook) { + _res.qhook = hook; +} + +void +res_send_setrhook(res_send_rhook hook) { + _res.rhook = hook; +} + +int +res_isourserver(const struct sockaddr_in *inp) { + return (res_ourserver_p(&_res, inp)); +} + +int +res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { + if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + /* errno should have been set by res_init() in this case. */ + return (-1); + } + + return (res_nsend(&_res, buf, buflen, ans, anssiz)); +} + +int +res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, + u_char *ans, int anssiz) +{ + if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + /* errno should have been set by res_init() in this case. */ + return (-1); + } + + return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); +} + +void +res_close(void) { + res_nclose(&_res); +} + +int +res_update(ns_updrec *rrecp_in) { + if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nupdate(&_res, rrecp_in, NULL)); +} + +int +res_search(const char *name, /*!< domain name */ + int class, int type, /*!< class and type of query */ + u_char *answer, /*!< buffer to put answer */ + int anslen) /*!< size of answer */ +{ + if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nsearch(&_res, name, class, type, answer, anslen)); +} + +int +res_querydomain(const char *name, + const char *domain, + int class, int type, /*!< class and type of query */ + u_char *answer, /*!< buffer to put answer */ + int anslen) /*!< size of answer */ +{ + if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nquerydomain(&_res, name, domain, + class, type, + answer, anslen)); +} + +u_int +res_randomid(void) { + if ((_res.options & RES_INIT) == 0U && res_init() == -1) { + RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); + return (-1); + } + + return (res_nrandomid(&_res)); +} + +const char * +hostalias(const char *name) { + static char abuf[MAXDNAME]; + + return (res_hostalias(&_res, name, abuf, sizeof abuf)); +} + +#ifdef ultrix +int +local_hostname_length(const char *hostname) { + int len_host, len_domain; + + if (!*_res.defdname) + res_init(); + len_host = strlen(hostname); + len_domain = strlen(_res.defdname); + if (len_host > len_domain && + !strcasecmp(hostname + len_host - len_domain, _res.defdname) && + hostname[len_host - len_domain - 1] == '.') + return (len_host - len_domain - 1); + return (0); +} +#endif /*ultrix*/ + +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_debug.c b/usr/src/lib/libresolv2_joy/common/resolv/res_debug.c new file mode 100644 index 0000000000..e11fb29612 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_debug.c @@ -0,0 +1,1252 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Portions Copyright (C) 2004, 2005, 2008, 2009 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 1996-2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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 (c) 1985 + * 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. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_debug.c,v 1.19 2009/02/26 11:20:20 tbox Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <math.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <resolv_mt.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "port_after.h" + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +extern const char *_res_opcodes[]; +extern const char *_res_sectioncodes[]; + +#ifndef ORIGINAL_ISC_CODE +#pragma weak __dn_count_labels = dn_count_labels +#pragma weak __fp_resstat = fp_resstat +#pragma weak __loc_aton = loc_aton +#pragma weak __loc_ntoa = loc_ntoa +#pragma weak __p_cdname = p_cdname +#pragma weak __p_class = p_class +#pragma weak __p_section = p_section +#pragma weak __p_time = p_time +#pragma weak __p_type = p_type +#pragma weak __sym_ntop = sym_ntop +#pragma weak __sym_ntos = sym_ntos +#pragma weak __sym_ston = sym_ston +#endif /* ORIGINAL_ISC_CODE */ + +/*% + * Print the current options. + */ +void +fp_resstat(const res_state statp, FILE *file) { + u_long mask; + + fprintf(file, ";; res options:"); + for (mask = 1; mask != 0U; mask <<= 1) + if (statp->options & mask) + fprintf(file, " %s", p_option(mask)); + putc('\n', file); +} + +static void +do_section(const res_state statp, + ns_msg *handle, ns_sect section, + int pflag, FILE *file) +{ + int n, sflag, rrnum; + static int buflen = 2048; + char *buf; + ns_opcode opcode; + ns_rr rr; + + /* + * Print answer records. + */ + sflag = (statp->pfcode & pflag); + if (statp->pfcode && !sflag) + return; + + buf = malloc(buflen); + if (buf == NULL) { + fprintf(file, ";; memory allocation failure\n"); + return; + } + + opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode); + rrnum = 0; + for (;;) { + if (ns_parserr(handle, section, rrnum, &rr)) { + if (errno != ENODEV) + fprintf(file, ";; ns_parserr: %s\n", + strerror(errno)); + else if (rrnum > 0 && sflag != 0 && + (statp->pfcode & RES_PRF_HEAD1)) + putc('\n', file); + goto cleanup; + } + if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1)) + fprintf(file, ";; %s SECTION:\n", + p_section(section, opcode)); + if (section == ns_s_qd) + fprintf(file, ";;\t%s, type = %s, class = %s\n", + ns_rr_name(rr), + p_type(ns_rr_type(rr)), + p_class(ns_rr_class(rr))); + else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) { + u_int16_t optcode, optlen, rdatalen = ns_rr_rdlen(rr); + u_int32_t ttl = ns_rr_ttl(rr); + + fprintf(file, + "; EDNS: version: %u, udp=%u, flags=%04x\n", + (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff); + + while (rdatalen >= 4) { + const u_char *cp = ns_rr_rdata(rr); + int i; + + GETSHORT(optcode, cp); + GETSHORT(optlen, cp); + + if (optcode == NS_OPT_NSID) { + fputs("; NSID: ", file); + if (optlen == 0) { + fputs("; NSID\n", file); + } else { + fputs("; NSID: ", file); + for (i = 0; i < optlen; i++) + fprintf(file, "%02x ", + cp[i]); + fputs(" (",file); + for (i = 0; i < optlen; i++) + fprintf(file, "%c", + isprint(cp[i])? + cp[i] : '.'); + fputs(")\n", file); + } + } else { + if (optlen == 0) { + fprintf(file, "; OPT=%u\n", + optcode); + } else { + fprintf(file, "; OPT=%u: ", + optcode); + for (i = 0; i < optlen; i++) + fprintf(file, "%02x ", + cp[i]); + fputs(" (",file); + for (i = 0; i < optlen; i++) + fprintf(file, "%c", + isprint(cp[i]) ? + cp[i] : '.'); + fputs(")\n", file); + } + } + rdatalen -= 4 + optlen; + } + } else { + n = ns_sprintrr(handle, &rr, NULL, NULL, + buf, buflen); + if (n < 0) { + if (errno == ENOSPC) { + free(buf); + buf = NULL; + if (buflen < 131072) + buf = malloc(buflen += 1024); + if (buf == NULL) { + fprintf(file, + ";; memory allocation failure\n"); + return; + } + continue; + } + fprintf(file, ";; ns_sprintrr: %s\n", + strerror(errno)); + goto cleanup; + } + fputs(buf, file); + fputc('\n', file); + } + rrnum++; + } + cleanup: + if (buf != NULL) + free(buf); +} + +/*% + * Print the contents of a query. + * This is intended to be primarily a debugging routine. + */ +void +res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) { + ns_msg handle; + int qdcount, ancount, nscount, arcount; + u_int opcode, rcode, id; + + if (ns_initparse(msg, len, &handle) < 0) { + fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); + return; + } + opcode = ns_msg_getflag(handle, ns_f_opcode); + rcode = ns_msg_getflag(handle, ns_f_rcode); + id = ns_msg_id(handle); + qdcount = ns_msg_count(handle, ns_s_qd); + ancount = ns_msg_count(handle, ns_s_an); + nscount = ns_msg_count(handle, ns_s_ns); + arcount = ns_msg_count(handle, ns_s_ar); + + /* + * Print header fields. + */ + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode) + fprintf(file, + ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", + _res_opcodes[opcode], p_rcode(rcode), id); + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX)) + putc(';', file); + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) { + fprintf(file, "; flags:"); + if (ns_msg_getflag(handle, ns_f_qr)) + fprintf(file, " qr"); + if (ns_msg_getflag(handle, ns_f_aa)) + fprintf(file, " aa"); + if (ns_msg_getflag(handle, ns_f_tc)) + fprintf(file, " tc"); + if (ns_msg_getflag(handle, ns_f_rd)) + fprintf(file, " rd"); + if (ns_msg_getflag(handle, ns_f_ra)) + fprintf(file, " ra"); + if (ns_msg_getflag(handle, ns_f_z)) + fprintf(file, " ??"); + if (ns_msg_getflag(handle, ns_f_ad)) + fprintf(file, " ad"); + if (ns_msg_getflag(handle, ns_f_cd)) + fprintf(file, " cd"); + } + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) { + fprintf(file, "; %s: %d", + p_section(ns_s_qd, opcode), qdcount); + fprintf(file, ", %s: %d", + p_section(ns_s_an, opcode), ancount); + fprintf(file, ", %s: %d", + p_section(ns_s_ns, opcode), nscount); + fprintf(file, ", %s: %d", + p_section(ns_s_ar, opcode), arcount); + } + if ((!statp->pfcode) || (statp->pfcode & + (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { + putc('\n',file); + } + /* + * Print the various sections. + */ + do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file); + do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file); + do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file); + do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file); + if (qdcount == 0 && ancount == 0 && + nscount == 0 && arcount == 0) + putc('\n', file); +} + +const u_char * +p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) { + char name[MAXDNAME]; + int n; + + if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0) + return (NULL); + if (name[0] == '\0') + putc('.', file); + else + fputs(name, file); + return (cp + n); +} + +const u_char * +p_cdname(const u_char *cp, const u_char *msg, FILE *file) { + return (p_cdnname(cp, msg, PACKETSZ, file)); +} + +/*% + * Return a fully-qualified domain name from a compressed name (with + length supplied). */ + +const u_char * +p_fqnname(cp, msg, msglen, name, namelen) + const u_char *cp, *msg; + int msglen; + char *name; + int namelen; +{ + int n, newlen; + + if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0) + return (NULL); + newlen = strlen(name); + if (newlen == 0 || name[newlen - 1] != '.') { + if (newlen + 1 >= namelen) /*%< Lack space for final dot */ + return (NULL); + else + strcpy(name + newlen, "."); + } + return (cp + n); +} + +/* XXX: the rest of these functions need to become length-limited, too. */ + +const u_char * +p_fqname(const u_char *cp, const u_char *msg, FILE *file) { + char name[MAXDNAME]; + const u_char *n; + + n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name); + if (n == NULL) + return (NULL); + fputs(name, file); + return (n); +} + +/*% + * Names of RR classes and qclasses. Classes and qclasses are the same, except + * that C_ANY is a qclass but not a class. (You can ask for records of class + * C_ANY, but you can't have any records of that class in the database.) + */ +const struct res_sym __p_class_syms[] = { + {C_IN, "IN", (char *)0}, + {C_CHAOS, "CH", (char *)0}, + {C_CHAOS, "CHAOS", (char *)0}, + {C_HS, "HS", (char *)0}, + {C_HS, "HESIOD", (char *)0}, + {C_ANY, "ANY", (char *)0}, + {C_NONE, "NONE", (char *)0}, + {C_IN, (char *)0, (char *)0} +}; + +/*% + * Names of message sections. + */ +const struct res_sym __p_default_section_syms[] = { + {ns_s_qd, "QUERY", (char *)0}, + {ns_s_an, "ANSWER", (char *)0}, + {ns_s_ns, "AUTHORITY", (char *)0}, + {ns_s_ar, "ADDITIONAL", (char *)0}, + {0, (char *)0, (char *)0} +}; + +const struct res_sym __p_update_section_syms[] = { + {S_ZONE, "ZONE", (char *)0}, + {S_PREREQ, "PREREQUISITE", (char *)0}, + {S_UPDATE, "UPDATE", (char *)0}, + {S_ADDT, "ADDITIONAL", (char *)0}, + {0, (char *)0, (char *)0} +}; + +const struct res_sym __p_key_syms[] = { + {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"}, + {NS_ALG_DH, "DH", "Diffie Hellman"}, + {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"}, + {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"}, + {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"}, + {0, NULL, NULL} +}; + +const struct res_sym __p_cert_syms[] = { + {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"}, + {cert_t_spki, "SPKI", "SPKI certificate"}, + {cert_t_pgp, "PGP", "PGP certificate"}, + {cert_t_url, "URL", "URL Private"}, + {cert_t_oid, "OID", "OID Private"}, + {0, NULL, NULL} +}; + +/*% + * Names of RR types and qtypes. Types and qtypes are the same, except + * that T_ANY is a qtype but not a type. (You can ask for records of type + * T_ANY, but you can't have any records of that type in the database.) + */ +const struct res_sym __p_type_syms[] = { + {ns_t_a, "A", "address"}, + {ns_t_ns, "NS", "name server"}, + {ns_t_md, "MD", "mail destination (deprecated)"}, + {ns_t_mf, "MF", "mail forwarder (deprecated)"}, + {ns_t_cname, "CNAME", "canonical name"}, + {ns_t_soa, "SOA", "start of authority"}, + {ns_t_mb, "MB", "mailbox"}, + {ns_t_mg, "MG", "mail group member"}, + {ns_t_mr, "MR", "mail rename"}, + {ns_t_null, "NULL", "null"}, + {ns_t_wks, "WKS", "well-known service (deprecated)"}, + {ns_t_ptr, "PTR", "domain name pointer"}, + {ns_t_hinfo, "HINFO", "host information"}, + {ns_t_minfo, "MINFO", "mailbox information"}, + {ns_t_mx, "MX", "mail exchanger"}, + {ns_t_txt, "TXT", "text"}, + {ns_t_rp, "RP", "responsible person"}, + {ns_t_afsdb, "AFSDB", "DCE or AFS server"}, + {ns_t_x25, "X25", "X25 address"}, + {ns_t_isdn, "ISDN", "ISDN address"}, + {ns_t_rt, "RT", "router"}, + {ns_t_nsap, "NSAP", "nsap address"}, + {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"}, + {ns_t_sig, "SIG", "signature"}, + {ns_t_key, "KEY", "key"}, + {ns_t_px, "PX", "mapping information"}, + {ns_t_gpos, "GPOS", "geographical position (withdrawn)"}, + {ns_t_aaaa, "AAAA", "IPv6 address"}, + {ns_t_loc, "LOC", "location"}, + {ns_t_nxt, "NXT", "next valid name (unimplemented)"}, + {ns_t_eid, "EID", "endpoint identifier (unimplemented)"}, + {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"}, + {ns_t_srv, "SRV", "server selection"}, + {ns_t_atma, "ATMA", "ATM address (unimplemented)"}, + {ns_t_naptr, "NAPTR", "naptr"}, + {ns_t_kx, "KX", "key exchange"}, + {ns_t_cert, "CERT", "certificate"}, + {ns_t_a6, "A", "IPv6 address (experminental)"}, + {ns_t_dname, "DNAME", "non-terminal redirection"}, + {ns_t_opt, "OPT", "opt"}, + {ns_t_apl, "apl", "apl"}, + {ns_t_ds, "DS", "delegation signer"}, + {ns_t_sshfp, "SSFP", "SSH fingerprint"}, + {ns_t_ipseckey, "IPSECKEY", "IPSEC key"}, + {ns_t_rrsig, "RRSIG", "rrsig"}, + {ns_t_nsec, "NSEC", "nsec"}, + {ns_t_dnskey, "DNSKEY", "DNS key"}, + {ns_t_dhcid, "DHCID", "dynamic host configuration identifier"}, + {ns_t_nsec3, "NSEC3", "nsec3"}, + {ns_t_nsec3param, "NSEC3PARAM", "NSEC3 parameters"}, + {ns_t_hip, "HIP", "host identity protocol"}, + {ns_t_spf, "SPF", "sender policy framework"}, + {ns_t_tkey, "TKEY", "tkey"}, + {ns_t_tsig, "TSIG", "transaction signature"}, + {ns_t_ixfr, "IXFR", "incremental zone transfer"}, + {ns_t_axfr, "AXFR", "zone transfer"}, + {ns_t_zxfr, "ZXFR", "compressed zone transfer"}, + {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"}, + {ns_t_maila, "MAILA", "mail agent (deprecated)"}, + {ns_t_naptr, "NAPTR", "URN Naming Authority"}, + {ns_t_kx, "KX", "Key Exchange"}, + {ns_t_cert, "CERT", "Certificate"}, + {ns_t_a6, "A6", "IPv6 Address"}, + {ns_t_dname, "DNAME", "dname"}, + {ns_t_sink, "SINK", "Kitchen Sink (experimental)"}, + {ns_t_opt, "OPT", "EDNS Options"}, + {ns_t_any, "ANY", "\"any\""}, + {ns_t_dlv, "DLV", "DNSSEC look-aside validation"}, + {0, NULL, NULL} +}; + +/*% + * Names of DNS rcodes. + */ +const struct res_sym __p_rcode_syms[] = { + {ns_r_noerror, "NOERROR", "no error"}, + {ns_r_formerr, "FORMERR", "format error"}, + {ns_r_servfail, "SERVFAIL", "server failed"}, + {ns_r_nxdomain, "NXDOMAIN", "no such domain name"}, + {ns_r_notimpl, "NOTIMP", "not implemented"}, + {ns_r_refused, "REFUSED", "refused"}, + {ns_r_yxdomain, "YXDOMAIN", "domain name exists"}, + {ns_r_yxrrset, "YXRRSET", "rrset exists"}, + {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"}, + {ns_r_notauth, "NOTAUTH", "not authoritative"}, + {ns_r_notzone, "NOTZONE", "Not in zone"}, + {ns_r_max, "", ""}, + {ns_r_badsig, "BADSIG", "bad signature"}, + {ns_r_badkey, "BADKEY", "bad key"}, + {ns_r_badtime, "BADTIME", "bad time"}, + {0, NULL, NULL} +}; + +int +sym_ston(const struct res_sym *syms, const char *name, int *success) { + for ((void)NULL; syms->name != 0; syms++) { + if (strcasecmp (name, syms->name) == 0) { + if (success) + *success = 1; + return (syms->number); + } + } + if (success) + *success = 0; + return (syms->number); /*%< The default value. */ +} + +const char * +sym_ntos(const struct res_sym *syms, int number, int *success) { + char *unname = sym_ntos_unname; + + for ((void)NULL; syms->name != 0; syms++) { + if (number == syms->number) { + if (success) + *success = 1; + return (syms->name); + } + } + + sprintf(unname, "%d", number); /*%< XXX nonreentrant */ + if (success) + *success = 0; + return (unname); +} + +const char * +sym_ntop(const struct res_sym *syms, int number, int *success) { + char *unname = sym_ntop_unname; + + for ((void)NULL; syms->name != 0; syms++) { + if (number == syms->number) { + if (success) + *success = 1; + return (syms->humanname); + } + } + sprintf(unname, "%d", number); /*%< XXX nonreentrant */ + if (success) + *success = 0; + return (unname); +} + +/*% + * Return a string for the type. + */ +const char * +p_type(int type) { + int success; + const char *result; + static char typebuf[20]; + + result = sym_ntos(__p_type_syms, type, &success); + if (success) + return (result); + if (type < 0 || type > 0xffff) + return ("BADTYPE"); + sprintf(typebuf, "TYPE%d", type); + return (typebuf); +} + +/*% + * Return a string for the type. + */ +const char * +p_section(int section, int opcode) { + const struct res_sym *symbols; + + switch (opcode) { + case ns_o_update: + symbols = __p_update_section_syms; + break; + default: + symbols = __p_default_section_syms; + break; + } + return (sym_ntos(symbols, section, (int *)0)); +} + +/*% + * Return a mnemonic for class. + */ +const char * +p_class(int class) { + int success; + const char *result; + static char classbuf[20]; + + result = sym_ntos(__p_class_syms, class, &success); + if (success) + return (result); + if (class < 0 || class > 0xffff) + return ("BADCLASS"); + sprintf(classbuf, "CLASS%d", class); + return (classbuf); +} + +/*% + * Return a mnemonic for an option + */ +const char * +p_option(u_long option) { + char *nbuf = p_option_nbuf; + + switch (option) { + case RES_INIT: return "init"; + case RES_DEBUG: return "debug"; + case RES_AAONLY: return "aaonly(unimpl)"; + case RES_USEVC: return "usevc"; + case RES_PRIMARY: return "primry(unimpl)"; + case RES_IGNTC: return "igntc"; + case RES_RECURSE: return "recurs"; + case RES_DEFNAMES: return "defnam"; + case RES_STAYOPEN: return "styopn"; + case RES_DNSRCH: return "dnsrch"; + case RES_INSECURE1: return "insecure1"; + case RES_INSECURE2: return "insecure2"; + case RES_NOALIASES: return "noaliases"; + case RES_USE_INET6: return "inet6"; +#ifdef RES_USE_EDNS0 /*%< KAME extension */ + case RES_USE_EDNS0: return "edns0"; + case RES_NSID: return "nsid"; +#endif +#ifdef RES_USE_DNAME + case RES_USE_DNAME: return "dname"; +#endif +#ifdef RES_USE_DNSSEC + case RES_USE_DNSSEC: return "dnssec"; +#endif +#ifdef RES_NOTLDQUERY + case RES_NOTLDQUERY: return "no-tld-query"; +#endif +#ifdef RES_NO_NIBBLE2 + case RES_NO_NIBBLE2: return "no-nibble2"; +#endif + /* XXX nonreentrant */ + default: sprintf(nbuf, "?0x%lx?", (u_long)option); + return (nbuf); + } +} + +/*% + * Return a mnemonic for a time to live. + */ +const char * +p_time(u_int32_t value) { + char *nbuf = p_time_nbuf; + + if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0) + sprintf(nbuf, "%u", value); + return (nbuf); +} + +/*% + * Return a string for the rcode. + */ +const char * +p_rcode(int rcode) { + return (sym_ntos(__p_rcode_syms, rcode, (int *)0)); +} + +/*% + * Return a string for a res_sockaddr_union. + */ +const char * +p_sockun(union res_sockaddr_union u, char *buf, size_t size) { + char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123"]; + + switch (u.sin.sin_family) { + case AF_INET: + inet_ntop(AF_INET, &u.sin.sin_addr, ret, sizeof ret); + break; +#ifdef HAS_INET6_STRUCTS + case AF_INET6: + inet_ntop(AF_INET6, &u.sin6.sin6_addr, ret, sizeof ret); + break; +#endif + default: + sprintf(ret, "[af%d]", u.sin.sin_family); + break; + } + if (size > 0U) { + strncpy(buf, ret, size - 1); + buf[size - 1] = '0'; + } + return (buf); +} + +/*% + * routines to convert between on-the-wire RR format and zone file format. + * Does not contain conversion to/from decimal degrees; divide or multiply + * by 60*60*1000 for that. + */ + +static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, + 1000000,10000000,100000000,1000000000}; + +/*% takes an XeY precision/size value, returns a string representation. */ +static const char * +precsize_ntoa(prec) + u_int8_t prec; +{ + char *retbuf = precsize_ntoa_retbuf; + unsigned long val; + int mantissa, exponent; + + mantissa = (int)((prec >> 4) & 0x0f) % 10; + exponent = (int)((prec >> 0) & 0x0f) % 10; + + val = mantissa * poweroften[exponent]; + + (void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100); + return (retbuf); +} + +/*% converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */ +static u_int8_t +precsize_aton(const char **strptr) { + unsigned int mval = 0, cmval = 0; + u_int8_t retval = 0; + const char *cp; + int exponent; + int mantissa; + + cp = *strptr; + + while (isdigit((unsigned char)*cp)) + mval = mval * 10 + (*cp++ - '0'); + + if (*cp == '.') { /*%< centimeters */ + cp++; + if (isdigit((unsigned char)*cp)) { + cmval = (*cp++ - '0') * 10; + if (isdigit((unsigned char)*cp)) { + cmval += (*cp++ - '0'); + } + } + } + cmval = (mval * 100) + cmval; + + for (exponent = 0; exponent < 9; exponent++) + if (cmval < poweroften[exponent+1]) + break; + + mantissa = cmval / poweroften[exponent]; + if (mantissa > 9) + mantissa = 9; + + retval = (mantissa << 4) | exponent; + + *strptr = cp; + + return (retval); +} + +/*% converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */ +static u_int32_t +latlon2ul(const char **latlonstrptr, int *which) { + const char *cp; + u_int32_t retval; + int deg = 0, min = 0, secs = 0, secsfrac = 0; + + cp = *latlonstrptr; + + while (isdigit((unsigned char)*cp)) + deg = deg * 10 + (*cp++ - '0'); + + while (isspace((unsigned char)*cp)) + cp++; + + if (!(isdigit((unsigned char)*cp))) + goto fndhemi; + + while (isdigit((unsigned char)*cp)) + min = min * 10 + (*cp++ - '0'); + + while (isspace((unsigned char)*cp)) + cp++; + + if (!(isdigit((unsigned char)*cp))) + goto fndhemi; + + while (isdigit((unsigned char)*cp)) + secs = secs * 10 + (*cp++ - '0'); + + if (*cp == '.') { /*%< decimal seconds */ + cp++; + if (isdigit((unsigned char)*cp)) { + secsfrac = (*cp++ - '0') * 100; + if (isdigit((unsigned char)*cp)) { + secsfrac += (*cp++ - '0') * 10; + if (isdigit((unsigned char)*cp)) { + secsfrac += (*cp++ - '0'); + } + } + } + } + + while (!isspace((unsigned char)*cp)) /*%< if any trailing garbage */ + cp++; + + while (isspace((unsigned char)*cp)) + cp++; + + fndhemi: + switch (*cp) { + case 'N': case 'n': + case 'E': case 'e': + retval = ((unsigned)1<<31) + + (((((deg * 60) + min) * 60) + secs) * 1000) + + secsfrac; + break; + case 'S': case 's': + case 'W': case 'w': + retval = ((unsigned)1<<31) + - (((((deg * 60) + min) * 60) + secs) * 1000) + - secsfrac; + break; + default: + retval = 0; /*%< invalid value -- indicates error */ + break; + } + + switch (*cp) { + case 'N': case 'n': + case 'S': case 's': + *which = 1; /*%< latitude */ + break; + case 'E': case 'e': + case 'W': case 'w': + *which = 2; /*%< longitude */ + break; + default: + *which = 0; /*%< error */ + break; + } + + cp++; /*%< skip the hemisphere */ + while (!isspace((unsigned char)*cp)) /*%< if any trailing garbage */ + cp++; + + while (isspace((unsigned char)*cp)) /*%< move to next field */ + cp++; + + *latlonstrptr = cp; + + return (retval); +} + +/*% + * converts a zone file representation in a string to an RDATA on-the-wire + * representation. */ +int +loc_aton(ascii, binary) + const char *ascii; + u_char *binary; +{ + const char *cp, *maxcp; + u_char *bcp; + + u_int32_t latit = 0, longit = 0, alt = 0; + u_int32_t lltemp1 = 0, lltemp2 = 0; + int altmeters = 0, altfrac = 0, altsign = 1; + u_int8_t hp = 0x16; /*%< default = 1e6 cm = 10000.00m = 10km */ + u_int8_t vp = 0x13; /*%< default = 1e3 cm = 10.00m */ + u_int8_t siz = 0x12; /*%< default = 1e2 cm = 1.00m */ + int which1 = 0, which2 = 0; + + cp = ascii; + maxcp = cp + strlen(ascii); + + lltemp1 = latlon2ul(&cp, &which1); + + lltemp2 = latlon2ul(&cp, &which2); + + switch (which1 + which2) { + case 3: /*%< 1 + 2, the only valid combination */ + if ((which1 == 1) && (which2 == 2)) { /*%< normal case */ + latit = lltemp1; + longit = lltemp2; + } else if ((which1 == 2) && (which2 == 1)) { /*%< reversed */ + longit = lltemp1; + latit = lltemp2; + } else { /*%< some kind of brokenness */ + return (0); + } + break; + default: /*%< we didn't get one of each */ + return (0); + } + + /* altitude */ + if (*cp == '-') { + altsign = -1; + cp++; + } + + if (*cp == '+') + cp++; + + while (isdigit((unsigned char)*cp)) + altmeters = altmeters * 10 + (*cp++ - '0'); + + if (*cp == '.') { /*%< decimal meters */ + cp++; + if (isdigit((unsigned char)*cp)) { + altfrac = (*cp++ - '0') * 10; + if (isdigit((unsigned char)*cp)) { + altfrac += (*cp++ - '0'); + } + } + } + + alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); + + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */ + cp++; + + while (isspace((unsigned char)*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + siz = precsize_aton(&cp); + + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */ + cp++; + + while (isspace((unsigned char)*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + hp = precsize_aton(&cp); + + while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */ + cp++; + + while (isspace((unsigned char)*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + vp = precsize_aton(&cp); + + defaults: + + bcp = binary; + *bcp++ = (u_int8_t) 0; /*%< version byte */ + *bcp++ = siz; + *bcp++ = hp; + *bcp++ = vp; + PUTLONG(latit,bcp); + PUTLONG(longit,bcp); + PUTLONG(alt,bcp); + + return (16); /*%< size of RR in octets */ +} + +/*% takes an on-the-wire LOC RR and formats it in a human readable format. */ +const char * +loc_ntoa(binary, ascii) + const u_char *binary; + char *ascii; +{ + static const char *error = "?"; + static char tmpbuf[sizeof +"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"]; + const u_char *cp = binary; + + int latdeg, latmin, latsec, latsecfrac; + int longdeg, longmin, longsec, longsecfrac; + char northsouth, eastwest; + const char *altsign; + int altmeters, altfrac; + + const u_int32_t referencealt = 100000 * 100; + + int32_t latval, longval, altval; + u_int32_t templ; + u_int8_t sizeval, hpval, vpval, versionval; + + char *sizestr, *hpstr, *vpstr; + + versionval = *cp++; + + if (ascii == NULL) + ascii = tmpbuf; + + if (versionval) { + (void) sprintf(ascii, "; error: unknown LOC RR version"); + return (ascii); + } + + sizeval = *cp++; + + hpval = *cp++; + vpval = *cp++; + + GETLONG(templ, cp); + latval = (templ - ((unsigned)1<<31)); + + GETLONG(templ, cp); + longval = (templ - ((unsigned)1<<31)); + + GETLONG(templ, cp); + if (templ < referencealt) { /*%< below WGS 84 spheroid */ + altval = referencealt - templ; + altsign = "-"; + } else { + altval = templ - referencealt; + altsign = ""; + } + + if (latval < 0) { + northsouth = 'S'; + latval = -latval; + } else + northsouth = 'N'; + + latsecfrac = latval % 1000; + latval = latval / 1000; + latsec = latval % 60; + latval = latval / 60; + latmin = latval % 60; + latval = latval / 60; + latdeg = latval; + + if (longval < 0) { + eastwest = 'W'; + longval = -longval; + } else + eastwest = 'E'; + + longsecfrac = longval % 1000; + longval = longval / 1000; + longsec = longval % 60; + longval = longval / 60; + longmin = longval % 60; + longval = longval / 60; + longdeg = longval; + + altfrac = altval % 100; + altmeters = (altval / 100); + + sizestr = strdup(precsize_ntoa(sizeval)); + hpstr = strdup(precsize_ntoa(hpval)); + vpstr = strdup(precsize_ntoa(vpval)); + + sprintf(ascii, + "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm", + latdeg, latmin, latsec, latsecfrac, northsouth, + longdeg, longmin, longsec, longsecfrac, eastwest, + altsign, altmeters, altfrac, + (sizestr != NULL) ? sizestr : error, + (hpstr != NULL) ? hpstr : error, + (vpstr != NULL) ? vpstr : error); + + if (sizestr != NULL) + free(sizestr); + if (hpstr != NULL) + free(hpstr); + if (vpstr != NULL) + free(vpstr); + + return (ascii); +} + + +/*% Return the number of DNS hierarchy levels in the name. */ +int +dn_count_labels(const char *name) { + int i, len, count; + + len = strlen(name); + for (i = 0, count = 0; i < len; i++) { + /* XXX need to check for \. or use named's nlabels(). */ + if (name[i] == '.') + count++; + } + + /* don't count initial wildcard */ + if (name[0] == '*') + if (count) + count--; + + /* don't count the null label for root. */ + /* if terminating '.' not found, must adjust */ + /* count to include last label */ + if (len > 0 && name[len-1] != '.') + count++; + return (count); +} + +/*% + * Make dates expressed in seconds-since-Jan-1-1970 easy to read. + * SIG records are required to be printed like this, by the Secure DNS RFC. + */ +char * +p_secstodate (u_long secs) { + char *output = p_secstodate_output; + time_t clock = secs; + struct tm *time; +#ifdef HAVE_TIME_R + struct tm res; + + time = gmtime_r(&clock, &res); +#else + time = gmtime(&clock); +#endif + time->tm_year += 1900; + time->tm_mon += 1; + sprintf(output, "%04d%02d%02d%02d%02d%02d", + time->tm_year, time->tm_mon, time->tm_mday, + time->tm_hour, time->tm_min, time->tm_sec); + return (output); +} + +u_int16_t +res_nametoclass(const char *buf, int *successp) { + unsigned long result; + char *endptr; + int success; + + result = sym_ston(__p_class_syms, buf, &success); + if (success) + goto done; + + if (strncasecmp(buf, "CLASS", 5) != 0 || + !isdigit((unsigned char)buf[5])) + goto done; + errno = 0; + result = strtoul(buf + 5, &endptr, 10); + if (errno == 0 && *endptr == '\0' && result <= 0xffffU) + success = 1; + done: + if (successp) + *successp = success; + return (result); +} + +u_int16_t +res_nametotype(const char *buf, int *successp) { + unsigned long result; + char *endptr; + int success; + + result = sym_ston(__p_type_syms, buf, &success); + if (success) + goto done; + + if (strncasecmp(buf, "type", 4) != 0 || + !isdigit((unsigned char)buf[4])) + goto done; + errno = 0; + result = strtoul(buf + 4, &endptr, 10); + if (errno == 0 && *endptr == '\0' && result <= 0xffffU) + success = 1; + done: + if (successp) + *successp = success; + return (result); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_debug.h b/usr/src/lib/libresolv2_joy/common/resolv/res_debug.h new file mode 100644 index 0000000000..c28171d7c8 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_debug.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 _RES_DEBUG_H_ +#define _RES_DEBUG_H_ + +#ifndef DEBUG +# define Dprint(cond, args) /*empty*/ +# define DprintQ(cond, args, query, size) /*empty*/ +# define Aerror(statp, file, string, error, address) /*empty*/ +# define Perror(statp, file, string, error) /*empty*/ +#else +# define Dprint(cond, args) if (cond) {fprintf args;} else {} +# define DprintQ(cond, args, query, size) if (cond) {\ + fprintf args;\ + res_pquery(statp, query, size, stdout);\ + } else {} +#endif + +#endif /* _RES_DEBUG_H_ */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_findzonecut.c b/usr/src/lib/libresolv2_joy/common/resolv/res_findzonecut.c new file mode 100644 index 0000000000..431c0262c1 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_findzonecut.c @@ -0,0 +1,722 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: res_findzonecut.c,v 1.10 2005/10/11 00:10:16 marka Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* Import. */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/list.h> + +#include "port_after.h" + +#include <resolv_joy.h> + +/* Data structures. */ + +typedef struct rr_a { + LINK(struct rr_a) link; + union res_sockaddr_union addr; +} rr_a; +typedef LIST(rr_a) rrset_a; + +typedef struct rr_ns { + LINK(struct rr_ns) link; + const char * name; + unsigned int flags; + rrset_a addrs; +} rr_ns; +typedef LIST(rr_ns) rrset_ns; + +#define RR_NS_HAVE_V4 0x01 +#define RR_NS_HAVE_V6 0x02 + +/* Forward. */ + +static int satisfy(res_state, const char *, rrset_ns *, + union res_sockaddr_union *, int); +static int add_addrs(res_state, rr_ns *, + union res_sockaddr_union *, int); +static int get_soa(res_state, const char *, ns_class, int, + char *, size_t, char *, size_t, + rrset_ns *); +static int get_ns(res_state, const char *, ns_class, int, rrset_ns *); +static int get_glue(res_state, ns_class, int, rrset_ns *); +static int save_ns(res_state, ns_msg *, ns_sect, + const char *, ns_class, int, rrset_ns *); +static int save_a(res_state, ns_msg *, ns_sect, + const char *, ns_class, int, rr_ns *); +static void free_nsrrset(rrset_ns *); +static void free_nsrr(rrset_ns *, rr_ns *); +static rr_ns * find_ns(rrset_ns *, const char *); +static int do_query(res_state, const char *, ns_class, ns_type, + u_char *, ns_msg *); +static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2); + +/* Macros. */ + +#define DPRINTF(x) do {\ + int save_errno = errno; \ + if ((statp->options & RES_DEBUG) != 0U) res_dprintf x; \ + errno = save_errno; \ + } while (0) + +/* Public. */ + +/*% + * find enclosing zone for a <dname,class>, and some server addresses + * + * parameters: + *\li res - resolver context to work within (is modified) + *\li dname - domain name whose enclosing zone is desired + *\li class - class of dname (and its enclosing zone) + *\li zname - found zone name + *\li zsize - allocated size of zname + *\li addrs - found server addresses + *\li naddrs - max number of addrs + * + * return values: + *\li < 0 - an error occurred (check errno) + *\li = 0 - zname is now valid, but addrs[] wasn't changed + *\li > 0 - zname is now valid, and return value is number of addrs[] found + * + * notes: + *\li this function calls res_nsend() which means it depends on correctly + * functioning recursive nameservers (usually defined in /etc/resolv.conf + * or its local equivilent). + * + *\li we start by asking for an SOA<dname,class>. if we get one as an + * answer, that just means <dname,class> is a zone top, which is fine. + * more than likely we'll be told to go pound sand, in the form of a + * negative answer. + * + *\li note that we are not prepared to deal with referrals since that would + * only come from authority servers and our correctly functioning local + * recursive server would have followed the referral and got us something + * more definite. + * + *\li if the authority section contains an SOA, this SOA should also be the + * closest enclosing zone, since any intermediary zone cuts would've been + * returned as referrals and dealt with by our correctly functioning local + * recursive name server. but an SOA in the authority section should NOT + * match our dname (since that would have been returned in the answer + * section). an authority section SOA has to be "above" our dname. + * + *\li however, since authority section SOA's were once optional, it's + * possible that we'll have to go hunting for the enclosing SOA by + * ripping labels off the front of our dname -- this is known as "doing + * it the hard way." + * + *\li ultimately we want some server addresses, which are ideally the ones + * pertaining to the SOA.MNAME, but only if there is a matching NS RR. + * so the second phase (after we find an SOA) is to go looking for the + * NS RRset for that SOA's zone. + * + *\li no answer section processed by this code is allowed to contain CNAME + * or DNAME RR's. for the SOA query this means we strip a label and + * keep going. for the NS and A queries this means we just give up. + */ + +int +res_findzonecut(res_state statp, const char *dname, ns_class class, int opts, + char *zname, size_t zsize, struct in_addr *addrs, int naddrs) +{ + int result, i; + union res_sockaddr_union *u; + + + opts |= RES_IPV4ONLY; + opts &= ~RES_IPV6ONLY; + + u = calloc(naddrs, sizeof(*u)); + if (u == NULL) + return(-1); + + result = res_findzonecut2(statp, dname, class, opts, zname, zsize, + u, naddrs); + + for (i = 0; i < result; i++) { + addrs[i] = u[i].sin.sin_addr; + } + free(u); + return (result); +} + +int +res_findzonecut2(res_state statp, const char *dname, ns_class class, int opts, + char *zname, size_t zsize, union res_sockaddr_union *addrs, + int naddrs) +{ + char mname[NS_MAXDNAME]; + u_long save_pfcode; + rrset_ns nsrrs; + int n; + + DPRINTF(("START dname='%s' class=%s, zsize=%ld, naddrs=%d", + dname, p_class(class), (long)zsize, naddrs)); + save_pfcode = statp->pfcode; + statp->pfcode |= RES_PRF_HEAD2 | RES_PRF_HEAD1 | RES_PRF_HEADX | + RES_PRF_QUES | RES_PRF_ANS | + RES_PRF_AUTH | RES_PRF_ADD; + INIT_LIST(nsrrs); + + DPRINTF(("get the soa, and see if it has enough glue")); + if ((n = get_soa(statp, dname, class, opts, zname, zsize, + mname, sizeof mname, &nsrrs)) < 0 || + ((opts & RES_EXHAUSTIVE) == 0 && + (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0)) + goto done; + + DPRINTF(("get the ns rrset and see if it has enough glue")); + if ((n = get_ns(statp, zname, class, opts, &nsrrs)) < 0 || + ((opts & RES_EXHAUSTIVE) == 0 && + (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0)) + goto done; + + DPRINTF(("get the missing glue and see if it's finally enough")); + if ((n = get_glue(statp, class, opts, &nsrrs)) >= 0) + n = satisfy(statp, mname, &nsrrs, addrs, naddrs); + + done: + DPRINTF(("FINISH n=%d (%s)", n, (n < 0) ? strerror(errno) : "OK")); + free_nsrrset(&nsrrs); + statp->pfcode = save_pfcode; + return (n); +} + +/* Private. */ + +static int +satisfy(res_state statp, const char *mname, rrset_ns *nsrrsp, + union res_sockaddr_union *addrs, int naddrs) +{ + rr_ns *nsrr; + int n, x; + + n = 0; + nsrr = find_ns(nsrrsp, mname); + if (nsrr != NULL) { + x = add_addrs(statp, nsrr, addrs, naddrs); + addrs += x; + naddrs -= x; + n += x; + } + for (nsrr = HEAD(*nsrrsp); + nsrr != NULL && naddrs > 0; + nsrr = NEXT(nsrr, link)) + if (ns_samename(nsrr->name, mname) != 1) { + x = add_addrs(statp, nsrr, addrs, naddrs); + addrs += x; + naddrs -= x; + n += x; + } + DPRINTF(("satisfy(%s): %d", mname, n)); + return (n); +} + +static int +add_addrs(res_state statp, rr_ns *nsrr, + union res_sockaddr_union *addrs, int naddrs) +{ + rr_a *arr; + int n = 0; + + for (arr = HEAD(nsrr->addrs); arr != NULL; arr = NEXT(arr, link)) { + if (naddrs <= 0) + return (0); + *addrs++ = arr->addr; + naddrs--; + n++; + } + DPRINTF(("add_addrs: %d", n)); + return (n); +} + +static int +get_soa(res_state statp, const char *dname, ns_class class, int opts, + char *zname, size_t zsize, char *mname, size_t msize, + rrset_ns *nsrrsp) +{ + char tname[NS_MAXDNAME]; + u_char *resp = NULL; + int n, i, ancount, nscount; + ns_sect sect; + ns_msg msg; + u_int rcode; + + /* + * Find closest enclosing SOA, even if it's for the root zone. + */ + + /* First canonicalize dname (exactly one unescaped trailing "."). */ + if (ns_makecanon(dname, tname, sizeof tname) < 0) + goto cleanup; + dname = tname; + + resp = malloc(NS_MAXMSG); + if (resp == NULL) + goto cleanup; + + /* Now grovel the subdomains, hunting for an SOA answer or auth. */ + for (;;) { + /* Leading or inter-label '.' are skipped here. */ + while (*dname == '.') + dname++; + + /* Is there an SOA? */ + n = do_query(statp, dname, class, ns_t_soa, resp, &msg); + if (n < 0) { + DPRINTF(("get_soa: do_query('%s', %s) failed (%d)", + dname, p_class(class), n)); + goto cleanup; + } + if (n > 0) { + DPRINTF(("get_soa: CNAME or DNAME found")); + sect = ns_s_max, n = 0; + } else { + rcode = ns_msg_getflag(msg, ns_f_rcode); + ancount = ns_msg_count(msg, ns_s_an); + nscount = ns_msg_count(msg, ns_s_ns); + if (ancount > 0 && rcode == ns_r_noerror) + sect = ns_s_an, n = ancount; + else if (nscount > 0) + sect = ns_s_ns, n = nscount; + else + sect = ns_s_max, n = 0; + } + for (i = 0; i < n; i++) { + const char *t; + const u_char *rdata; + ns_rr rr; + + if (ns_parserr(&msg, sect, i, &rr) < 0) { + DPRINTF(("get_soa: ns_parserr(%s, %d) failed", + p_section(sect, ns_o_query), i)); + goto cleanup; + } + if (ns_rr_type(rr) == ns_t_cname || + ns_rr_type(rr) == ns_t_dname) + break; + if (ns_rr_type(rr) != ns_t_soa || + ns_rr_class(rr) != class) + continue; + t = ns_rr_name(rr); + switch (sect) { + case ns_s_an: + if (ns_samedomain(dname, t) == 0) { + DPRINTF( + ("get_soa: ns_samedomain('%s', '%s') == 0", + dname, t) + ); + errno = EPROTOTYPE; + goto cleanup; + } + break; + case ns_s_ns: + if (ns_samename(dname, t) == 1 || + ns_samedomain(dname, t) == 0) { + DPRINTF( + ("get_soa: ns_samename() || !ns_samedomain('%s', '%s')", + dname, t) + ); + errno = EPROTOTYPE; + goto cleanup; + } + break; + default: + abort(); + } + if (strlen(t) + 1 > zsize) { + DPRINTF(("get_soa: zname(%lu) too small (%lu)", + (unsigned long)zsize, + (unsigned long)strlen(t) + 1)); + errno = EMSGSIZE; + goto cleanup; + } + strcpy(zname, t); + rdata = ns_rr_rdata(rr); + if (ns_name_uncompress(resp, ns_msg_end(msg), rdata, + mname, msize) < 0) { + DPRINTF(("get_soa: ns_name_uncompress failed") + ); + goto cleanup; + } + if (save_ns(statp, &msg, ns_s_ns, + zname, class, opts, nsrrsp) < 0) { + DPRINTF(("get_soa: save_ns failed")); + goto cleanup; + } + free(resp); + return (0); + } + + /* If we're out of labels, then not even "." has an SOA! */ + if (*dname == '\0') + break; + + /* Find label-terminating "."; top of loop will skip it. */ + while (*dname != '.') { + if (*dname == '\\') + if (*++dname == '\0') { + errno = EMSGSIZE; + goto cleanup; + } + dname++; + } + } + DPRINTF(("get_soa: out of labels")); + errno = EDESTADDRREQ; + cleanup: + if (resp != NULL) + free(resp); + return (-1); +} + +static int +get_ns(res_state statp, const char *zname, ns_class class, int opts, + rrset_ns *nsrrsp) +{ + u_char *resp; + ns_msg msg; + int n; + + resp = malloc(NS_MAXMSG); + if (resp == NULL) + return (-1); + + /* Go and get the NS RRs for this zone. */ + n = do_query(statp, zname, class, ns_t_ns, resp, &msg); + if (n != 0) { + DPRINTF(("get_ns: do_query('%s', %s) failed (%d)", + zname, p_class(class), n)); + free(resp); + return (-1); + } + + /* Remember the NS RRs and associated A RRs that came back. */ + if (save_ns(statp, &msg, ns_s_an, zname, class, opts, nsrrsp) < 0) { + DPRINTF(("get_ns save_ns('%s', %s) failed", + zname, p_class(class))); + free(resp); + return (-1); + } + + free(resp); + return (0); +} + +static int +get_glue(res_state statp, ns_class class, int opts, rrset_ns *nsrrsp) { + rr_ns *nsrr, *nsrr_n; + u_char *resp; + + resp = malloc(NS_MAXMSG); + if (resp == NULL) + return(-1); + + /* Go and get the A RRs for each empty NS RR on our list. */ + for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = nsrr_n) { + ns_msg msg; + int n; + + nsrr_n = NEXT(nsrr, link); + + if ((nsrr->flags & RR_NS_HAVE_V4) == 0) { + n = do_query(statp, nsrr->name, class, ns_t_a, + resp, &msg); + if (n < 0) { + DPRINTF( + ("get_glue: do_query('%s', %s') failed", + nsrr->name, p_class(class))); + goto cleanup; + } + if (n > 0) { + DPRINTF(( + "get_glue: do_query('%s', %s') CNAME or DNAME found", + nsrr->name, p_class(class))); + } + if (save_a(statp, &msg, ns_s_an, nsrr->name, class, + opts, nsrr) < 0) { + DPRINTF(("get_glue: save_r('%s', %s) failed", + nsrr->name, p_class(class))); + goto cleanup; + } + } + + if ((nsrr->flags & RR_NS_HAVE_V6) == 0) { + n = do_query(statp, nsrr->name, class, ns_t_aaaa, + resp, &msg); + if (n < 0) { + DPRINTF( + ("get_glue: do_query('%s', %s') failed", + nsrr->name, p_class(class))); + goto cleanup; + } + if (n > 0) { + DPRINTF(( + "get_glue: do_query('%s', %s') CNAME or DNAME found", + nsrr->name, p_class(class))); + } + if (save_a(statp, &msg, ns_s_an, nsrr->name, class, + opts, nsrr) < 0) { + DPRINTF(("get_glue: save_r('%s', %s) failed", + nsrr->name, p_class(class))); + goto cleanup; + } + } + + /* If it's still empty, it's just chaff. */ + if (EMPTY(nsrr->addrs)) { + DPRINTF(("get_glue: removing empty '%s' NS", + nsrr->name)); + free_nsrr(nsrrsp, nsrr); + } + } + free(resp); + return (0); + + cleanup: + free(resp); + return (-1); +} + +static int +save_ns(res_state statp, ns_msg *msg, ns_sect sect, + const char *owner, ns_class class, int opts, + rrset_ns *nsrrsp) +{ + int i; + + for (i = 0; i < ns_msg_count(*msg, sect); i++) { + char tname[MAXDNAME]; + const u_char *rdata; + rr_ns *nsrr; + ns_rr rr; + + if (ns_parserr(msg, sect, i, &rr) < 0) { + DPRINTF(("save_ns: ns_parserr(%s, %d) failed", + p_section(sect, ns_o_query), i)); + return (-1); + } + if (ns_rr_type(rr) != ns_t_ns || + ns_rr_class(rr) != class || + ns_samename(ns_rr_name(rr), owner) != 1) + continue; + nsrr = find_ns(nsrrsp, ns_rr_name(rr)); + if (nsrr == NULL) { + nsrr = malloc(sizeof *nsrr); + if (nsrr == NULL) { + DPRINTF(("save_ns: malloc failed")); + return (-1); + } + rdata = ns_rr_rdata(rr); + if (ns_name_uncompress(ns_msg_base(*msg), + ns_msg_end(*msg), rdata, + tname, sizeof tname) < 0) { + DPRINTF(("save_ns: ns_name_uncompress failed") + ); + free(nsrr); + return (-1); + } + nsrr->name = strdup(tname); + if (nsrr->name == NULL) { + DPRINTF(("save_ns: strdup failed")); + free(nsrr); + return (-1); + } + INIT_LINK(nsrr, link); + INIT_LIST(nsrr->addrs); + nsrr->flags = 0; + APPEND(*nsrrsp, nsrr, link); + } + if (save_a(statp, msg, ns_s_ar, + nsrr->name, class, opts, nsrr) < 0) { + DPRINTF(("save_ns: save_r('%s', %s) failed", + nsrr->name, p_class(class))); + return (-1); + } + } + return (0); +} + +static int +save_a(res_state statp, ns_msg *msg, ns_sect sect, + const char *owner, ns_class class, int opts, + rr_ns *nsrr) +{ + int i; + + for (i = 0; i < ns_msg_count(*msg, sect); i++) { + ns_rr rr; + rr_a *arr; + + if (ns_parserr(msg, sect, i, &rr) < 0) { + DPRINTF(("save_a: ns_parserr(%s, %d) failed", + p_section(sect, ns_o_query), i)); + return (-1); + } + if ((ns_rr_type(rr) != ns_t_a && + ns_rr_type(rr) != ns_t_aaaa) || + ns_rr_class(rr) != class || + ns_samename(ns_rr_name(rr), owner) != 1 || + ns_rr_rdlen(rr) != NS_INADDRSZ) + continue; + if ((opts & RES_IPV6ONLY) != 0 && ns_rr_type(rr) != ns_t_aaaa) + continue; + if ((opts & RES_IPV4ONLY) != 0 && ns_rr_type(rr) != ns_t_a) + continue; + arr = malloc(sizeof *arr); + if (arr == NULL) { + DPRINTF(("save_a: malloc failed")); + return (-1); + } + INIT_LINK(arr, link); + memset(&arr->addr, 0, sizeof(arr->addr)); + switch (ns_rr_type(rr)) { + case ns_t_a: + arr->addr.sin.sin_family = AF_INET; +#ifdef HAVE_SA_LEN + arr->addr.sin.sin_len = sizeof(arr->addr.sin); +#endif + memcpy(&arr->addr.sin.sin_addr, ns_rr_rdata(rr), + NS_INADDRSZ); + arr->addr.sin.sin_port = htons(NAMESERVER_PORT); + nsrr->flags |= RR_NS_HAVE_V4; + break; + case ns_t_aaaa: + arr->addr.sin6.sin6_family = AF_INET6; +#ifdef HAVE_SA_LEN + arr->addr.sin6.sin6_len = sizeof(arr->addr.sin6); +#endif + memcpy(&arr->addr.sin6.sin6_addr, ns_rr_rdata(rr), 16); + arr->addr.sin.sin_port = htons(NAMESERVER_PORT); + nsrr->flags |= RR_NS_HAVE_V6; + break; + default: + abort(); + } + APPEND(nsrr->addrs, arr, link); + } + return (0); +} + +static void +free_nsrrset(rrset_ns *nsrrsp) { + rr_ns *nsrr; + + while ((nsrr = HEAD(*nsrrsp)) != NULL) + free_nsrr(nsrrsp, nsrr); +} + +static void +free_nsrr(rrset_ns *nsrrsp, rr_ns *nsrr) { + rr_a *arr; + char *tmp; + + while ((arr = HEAD(nsrr->addrs)) != NULL) { + UNLINK(nsrr->addrs, arr, link); + free(arr); + } + DE_CONST(nsrr->name, tmp); + free(tmp); + UNLINK(*nsrrsp, nsrr, link); + free(nsrr); +} + +static rr_ns * +find_ns(rrset_ns *nsrrsp, const char *dname) { + rr_ns *nsrr; + + for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = NEXT(nsrr, link)) + if (ns_samename(nsrr->name, dname) == 1) + return (nsrr); + return (NULL); +} + +static int +do_query(res_state statp, const char *dname, ns_class class, ns_type qtype, + u_char *resp, ns_msg *msg) +{ + u_char req[NS_PACKETSZ]; + int i, n; + + n = res_nmkquery(statp, ns_o_query, dname, class, qtype, + NULL, 0, NULL, req, NS_PACKETSZ); + if (n < 0) { + DPRINTF(("do_query: res_nmkquery failed")); + return (-1); + } + n = res_nsend(statp, req, n, resp, NS_MAXMSG); + if (n < 0) { + DPRINTF(("do_query: res_nsend failed")); + return (-1); + } + if (n == 0) { + DPRINTF(("do_query: res_nsend returned 0")); + errno = EMSGSIZE; + return (-1); + } + if (ns_initparse(resp, n, msg) < 0) { + DPRINTF(("do_query: ns_initparse failed")); + return (-1); + } + n = 0; + for (i = 0; i < ns_msg_count(*msg, ns_s_an); i++) { + ns_rr rr; + + if (ns_parserr(msg, ns_s_an, i, &rr) < 0) { + DPRINTF(("do_query: ns_parserr failed")); + return (-1); + } + n += (ns_rr_class(rr) == class && + (ns_rr_type(rr) == ns_t_cname || + ns_rr_type(rr) == ns_t_dname)); + } + return (n); +} + +static void +res_dprintf(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + fputs(";; res_findzonecut: ", stderr); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_init.c b/usr/src/lib/libresolv2_joy/common/resolv/res_init.c new file mode 100644 index 0000000000..10254d1931 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_init.c @@ -0,0 +1,958 @@ +/* + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. + */ + + +/* + * Copyright (c) 1985, 1989, 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 (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; +static const char rcsid[] = "$Id: res_init.c,v 1.26 2008/12/11 09:59:00 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <netdb.h> + +#ifndef HAVE_MD5 +# include "../dst/md5.h" +#else +# ifdef SOLARIS2 +# include <sys/md5.h> +# endif +#endif +#ifndef _MD5_H_ +# define _MD5_H_ 1 /*%< make sure we do not include rsaref md5.h file */ +#endif + + +#include "port_after.h" + +/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ +#include <resolv_joy.h> + +/* ISC purposely put port_after.h before <resolv.h> to force in6 stuff + * (above) so we explicitly include port_resolv.h here */ +#include "port_resolv.h" + +#include "res_private.h" + +/*% Options. Should all be left alone. */ +#define RESOLVSORT +#define DEBUG + +#ifdef SUNW_INITCHKIF +#include <net/if.h> +#include <netinet/if_ether.h> +#include <sys/sockio.h> +#define MAXIFS 8192 +#endif /* SUNW_INITCHKIF */ + +#ifdef SOLARIS2 +#include <sys/systeminfo.h> +#endif + +static void res_setoptions __P((res_state, const char *, const char *)); + +#ifdef RESOLVSORT +static const char sort_mask[] = "/&"; +#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) +static u_int32_t net_mask __P((struct in_addr)); +#endif + +#if !defined(isascii) /*%< XXX - could be a function */ +# define isascii(c) (!(c & 0200)) +#endif + +/* + * Resolver state default settings. + */ + +/*% + * Set up default settings. If the configuration file exist, the values + * there will have precedence. Otherwise, the server address is set to + * INADDR_ANY and the default domain name comes from the gethostname(). + * + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address + * since it was noted that INADDR_ANY actually meant ``the first interface + * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, + * it had to be "up" in order for you to reach your own name server. It + * was later decided that since the recommended practice is to always + * install local static routes through 127.0.0.1 for all your network + * interfaces, that we could solve this problem without a code change. + * + * The configuration file should always be used, since it is the only way + * to specify a default domain. If you are running a server on your local + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" + * in the configuration file. + * + * Return 0 if completes successfully, -1 on error + */ +int +res_ninit(res_state statp) { + extern int __res_vinit(res_state, int); + return (__res_vinit(statp, 0)); +} + +/*% This function has to be reachable by res_data.c but not publically. */ +int +__res_vinit(res_state statp, int preinit) { + register FILE *fp; + register char *cp, **pp; + register int n; + char buf[BUFSIZ]; + int nserv = 0; /*%< number of nameserver records read from file */ + int haveenv = 0; + int havesearch = 0; +#ifdef RESOLVSORT + int nsort = 0; + char *net; +#endif + int dots; + union res_sockaddr_union u[2]; + int maxns = MAXNS; + + RES_SET_H_ERRNO(statp, 0); + if (statp->_u._ext.ext != NULL) + res_ndestroy(statp); + + if (!preinit) { + statp->retrans = RES_TIMEOUT; + statp->retry = RES_DFLRETRY; + statp->options = RES_DEFAULT; + res_rndinit(statp); + statp->id = res_nrandomid(statp); + } + + memset(u, 0, sizeof(u)); +#ifdef USELOOPBACK + u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); +#else + u[nserv].sin.sin_addr.s_addr = INADDR_ANY; +#endif + u[nserv].sin.sin_family = AF_INET; + u[nserv].sin.sin_port = htons(NAMESERVER_PORT); +#ifdef HAVE_SA_LEN + u[nserv].sin.sin_len = sizeof(struct sockaddr_in); +#endif + nserv++; +#ifdef HAS_INET6_STRUCTS +#ifdef USELOOPBACK + u[nserv].sin6.sin6_addr = in6addr_loopback; +#else + u[nserv].sin6.sin6_addr = in6addr_any; +#endif + u[nserv].sin6.sin6_family = AF_INET6; + u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT); +#ifdef HAVE_SA_LEN + u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6); +#endif + nserv++; +#endif + statp->nscount = 0; + statp->ndots = 1; + statp->pfcode = 0; + statp->_vcsock = -1; + statp->_flags = 0; + statp->qhook = NULL; + statp->rhook = NULL; + statp->_u._ext.nscount = 0; + statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext)); + if (statp->_u._ext.ext != NULL) { + memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext)); + statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr; + strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa"); + strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int"); + } else { + /* + * Historically res_init() rarely, if at all, failed. + * Examples and applications exist which do not check + * our return code. Furthermore several applications + * simply call us to get the systems domainname. So + * rather then immediately fail here we store the + * failure, which is returned later, in h_errno. And + * prevent the collection of 'nameserver' information + * by setting maxns to 0. Thus applications that fail + * to check our return code wont be able to make + * queries anyhow. + */ + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + maxns = 0; + } +#ifdef RESOLVSORT + statp->nsort = 0; +#endif + res_setservers(statp, u, nserv); + +#ifdef SUNW_INITCHKIF +/* + * Short circuit res_init() if no non-loopback interfaces are up. This is + * done to avoid boot delays if "dns" comes before "files" in nsswitch.conf. + * An additional fix has been added to this code, to count all external + * interfaces, which includes the IPv6 interfaces. If no external interfaces + * are found, an additional check is carried out to determine if any deprecated + * interfaces are up. + */ + { + int s; + struct lifnum lifn; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("res_init: socket"); + goto freedata; + } + lifn.lifn_family = AF_UNSPEC; + lifn.lifn_flags = LIFC_EXTERNAL_SOURCE; + if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) { + close(s); + goto freedata; + } + if (lifn.lifn_count == 0) { + /* + * Check if there are any deprecated interfaces up + */ + struct lifconf lifc; + uchar_t *buf; + int buflen, i, int_up = 0; + + lifn.lifn_flags = 0; + if ((ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) || + (lifn.lifn_count < 1)) { + close(s); + goto freedata; + } + + buflen = lifn.lifn_count * sizeof (struct lifreq); + buf = (uchar_t *)malloc(buflen); + if (buf == NULL) { + close(s); + goto freedata; + } + + lifc.lifc_family = AF_UNSPEC; + lifc.lifc_flags = 0; + lifc.lifc_len = buflen; + lifc.lifc_lifcu.lifcu_buf = (caddr_t)buf; + if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) { + close(s); + free(buf); + goto freedata; + } + + for (i = 0; i < lifn.lifn_count; ++i) { + struct lifreq *lreqp, lreq; + + lreqp = (struct lifreq *)&lifc.lifc_req[i]; + strlcpy(lreq.lifr_name, lreqp->lifr_name, + sizeof (lreq.lifr_name)); + if (ioctl(s, SIOCGLIFFLAGS, &lreq) < 0) { + close(s); + free(buf); + goto freedata; + } + if ((lreq.lifr_flags & IFF_UP) && + !(lreq.lifr_flags & IFF_NOLOCAL) && + !(lreq.lifr_flags & IFF_NOXMIT) && + !(lreq.lifr_flags & IFF_LOOPBACK)) { + int_up = 1; + break; + } + } + free(buf); + + if (!int_up) { + close(s); + goto freedata; + } + } + close(s); + } +#endif /* SUNW_INITCHKIF */ + +#ifdef SOLARIS2 + /* + * The old libresolv derived the defaultdomain from NIS/NIS+. + * We want to keep this behaviour + */ + { + char buf[sizeof(statp->defdname)], *cp; + int ret; + + if ((ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf))) > 0 && + (unsigned int)ret <= sizeof(buf)) { + if (buf[0] == '+') + buf[0] = '.'; + cp = strchr(buf, '.'); + cp = (cp == NULL) ? buf : (cp + 1); + strncpy(statp->defdname, cp, + sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; + } + } +#endif /* SOLARIS2 */ + + /* Allow user to override the local domain definition */ + if ((cp = getenv("LOCALDOMAIN")) != NULL) { + (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; + haveenv++; + + /* + * Set search list to be blank-separated strings + * from rest of env value. Permits users of LOCALDOMAIN + * to still have a search list, and anyone to set the + * one that they want to use as an individual (even more + * important now that the rfc1535 stuff restricts searches) + */ + cp = statp->defdname; + pp = statp->dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { + if (*cp == '\n') /*%< silly backwards compat */ + break; + else if (*cp == ' ' || *cp == '\t') { + *cp = 0; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + havesearch = 1; + } + } + /* null terminate last domain if there are excess */ + while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') + cp++; + *cp = '\0'; + *pp++ = 0; + } + +#define MATCH(line, name) \ + (!strncmp(line, name, sizeof(name) - 1) && \ + (line[sizeof(name) - 1] == ' ' || \ + line[sizeof(name) - 1] == '\t')) + + nserv = 0; + if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { + /* read the config file */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + /* skip comments */ + if (*buf == ';' || *buf == '#') + continue; + /* read default domain name */ + if (MATCH(buf, "domain")) { + if (haveenv) /*%< skip if have from environ */ + continue; + cp = buf + sizeof("domain") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; + if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL) + *cp = '\0'; + havesearch = 0; + continue; + } + /* set search list */ + if (MATCH(buf, "search")) { + if (haveenv) /*%< skip if have from environ */ + continue; + cp = buf + sizeof("search") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; + if ((cp = strchr(statp->defdname, '\n')) != NULL) + *cp = '\0'; + /* + * Set search list to be blank-separated strings + * on rest of line. + */ + cp = statp->defdname; + pp = statp->dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { + if (*cp == ' ' || *cp == '\t') { + *cp = 0; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + } + } + /* null terminate last domain if there are excess */ + while (*cp != '\0' && *cp != ' ' && *cp != '\t') + cp++; + *cp = '\0'; + *pp++ = 0; + havesearch = 1; + continue; + } + /* read nameservers to query */ + if (MATCH(buf, "nameserver") && nserv < maxns) { + struct addrinfo hints, *ai; + char sbuf[NI_MAXSERV]; + const size_t minsiz = + sizeof(statp->_u._ext.ext->nsaddrs[0]); + + cp = buf + sizeof("nameserver") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + cp[strcspn(cp, ";# \t\n")] = '\0'; + if ((*cp != '\0') && (*cp != '\n')) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + sprintf(sbuf, "%u", NAMESERVER_PORT); + if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && + ai->ai_addrlen <= minsiz) { + if (statp->_u._ext.ext != NULL) { + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + ai->ai_addr, ai->ai_addrlen); + } + if (ai->ai_addrlen <= + sizeof(statp->nsaddr_list[nserv])) { + memcpy(&statp->nsaddr_list[nserv], + ai->ai_addr, ai->ai_addrlen); + } else + statp->nsaddr_list[nserv].sin_family = 0; + freeaddrinfo(ai); + nserv++; + } + } + continue; + } +#ifdef RESOLVSORT + if (MATCH(buf, "sortlist")) { + struct in_addr a; + + cp = buf + sizeof("sortlist") - 1; + while (nsort < MAXRESOLVSORT) { + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == '\0' || *cp == '\n' || *cp == ';') + break; + net = cp; + while (*cp && !ISSORTMASK(*cp) && *cp != ';' && + isascii(*cp) && !isspace((unsigned char)*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + statp->sort_list[nsort].addr = a; + if (ISSORTMASK(n)) { + *cp++ = n; + net = cp; + while (*cp && *cp != ';' && + isascii(*cp) && + !isspace((unsigned char)*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + statp->sort_list[nsort].mask = a.s_addr; + } else { + statp->sort_list[nsort].mask = + net_mask(statp->sort_list[nsort].addr); + } + } else { + statp->sort_list[nsort].mask = + net_mask(statp->sort_list[nsort].addr); + } + nsort++; + } + *cp = n; + } + continue; + } +#endif + if (MATCH(buf, "options")) { + res_setoptions(statp, buf + sizeof("options") - 1, "conf"); + continue; + } + } + if (nserv > 0) + statp->nscount = nserv; +#ifdef RESOLVSORT + statp->nsort = nsort; +#endif + (void) fclose(fp); + } +/* + * Last chance to get a nameserver. This should not normally + * be necessary + */ +#ifdef NO_RESOLV_CONF + if(nserv == 0) + nserv = get_nameservers(statp); +#endif + + if (statp->defdname[0] == 0 && + gethostname(buf, sizeof(statp->defdname) - 1) == 0 && + (cp = strchr(buf, '.')) != NULL) + strcpy(statp->defdname, cp + 1); + + /* find components of local domain that might be searched */ + if (havesearch == 0) { + pp = statp->dnsrch; + *pp++ = statp->defdname; + *pp = NULL; + + dots = 0; + for (cp = statp->defdname; *cp; cp++) + dots += (*cp == '.'); + + cp = statp->defdname; + while (pp < statp->dnsrch + MAXDFLSRCH) { + if (dots < LOCALDOMAINPARTS) + break; + cp = strchr(cp, '.') + 1; /*%< we know there is one */ + *pp++ = cp; + dots--; + } + *pp = NULL; +#ifdef DEBUG + if (statp->options & RES_DEBUG) { + printf(";; res_init()... default dnsrch list:\n"); + for (pp = statp->dnsrch; *pp; pp++) + printf(";;\t%s\n", *pp); + printf(";;\t..END..\n"); + } +#endif + } + + if ((cp = getenv("RES_OPTIONS")) != NULL) + res_setoptions(statp, cp, "env"); + statp->options |= RES_INIT; + return (statp->res_h_errno); +#ifdef SUNW_INITCHKIF +freedata: + RES_SET_H_ERRNO(statp, NETDB_INTERNAL); + if (statp->_u._ext.ext != NULL) { + free(statp->_u._ext.ext); + statp->_u._ext.ext = NULL; + } + return (-1); +#endif /* SUNW_INITCHKIF */ + +} + +static void +res_setoptions(res_state statp, const char *options, const char *source) +{ + const char *cp = options; + int i; + struct __res_state_ext *ext = statp->_u._ext.ext; + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_setoptions(\"%s\", \"%s\")...\n", + options, source); +#endif + while (*cp) { + /* skip leading and inner runs of spaces */ + while (*cp == ' ' || *cp == '\t') + cp++; + /* search for and process individual options */ + if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { + i = atoi(cp + sizeof("ndots:") - 1); + if (i <= RES_MAXNDOTS) + statp->ndots = i; + else + statp->ndots = RES_MAXNDOTS; +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";;\tndots=%d\n", statp->ndots); +#endif + } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) { + i = atoi(cp + sizeof("timeout:") - 1); + if (i <= RES_MAXRETRANS) + statp->retrans = i; + else + statp->retrans = RES_MAXRETRANS; +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";;\ttimeout=%d\n", statp->retrans); +#endif +#ifdef SOLARIS2 + } else if (!strncmp(cp, "retrans:", sizeof("retrans:") - 1)) { + /* + * For backward compatibility, 'retrans' is + * supported as an alias for 'timeout', though + * without an imposed maximum. + */ + statp->retrans = atoi(cp + sizeof("retrans:") - 1); + } else if (!strncmp(cp, "retry:", sizeof("retry:") - 1)){ + /* + * For backward compatibility, 'retry' is + * supported as an alias for 'attempts', though + * without an imposed maximum. + */ + statp->retry = atoi(cp + sizeof("retry:") - 1); +#endif /* SOLARIS2 */ + } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){ + i = atoi(cp + sizeof("attempts:") - 1); + if (i <= RES_MAXRETRY) + statp->retry = i; + else + statp->retry = RES_MAXRETRY; +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";;\tattempts=%d\n", statp->retry); +#endif + } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { +#ifdef DEBUG + if (!(statp->options & RES_DEBUG)) { + printf(";; res_setoptions(\"%s\", \"%s\")..\n", + options, source); + statp->options |= RES_DEBUG; + } + printf(";;\tdebug\n"); +#endif + } else if (!strncmp(cp, "no_tld_query", + sizeof("no_tld_query") - 1) || + !strncmp(cp, "no-tld-query", + sizeof("no-tld-query") - 1)) { + statp->options |= RES_NOTLDQUERY; + } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { + statp->options |= RES_USE_INET6; + } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { + statp->options |= RES_ROTATE; + } else if (!strncmp(cp, "no-check-names", + sizeof("no-check-names") - 1)) { + statp->options |= RES_NOCHECKNAME; + } +#ifdef RES_USE_EDNS0 + else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) { + statp->options |= RES_USE_EDNS0; + } +#endif + else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { + statp->options |= RES_USE_DNAME; + } + else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) { + if (ext == NULL) + goto skip; + cp += sizeof("nibble:") - 1; + i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1); + strncpy(ext->nsuffix, cp, i); + ext->nsuffix[i] = '\0'; + } + else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) { + if (ext == NULL) + goto skip; + cp += sizeof("nibble2:") - 1; + i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1); + strncpy(ext->nsuffix2, cp, i); + ext->nsuffix2[i] = '\0'; + } + else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) { + cp += sizeof("v6revmode:") - 1; + /* "nibble" and "bitstring" used to be valid */ + if (!strncmp(cp, "single", sizeof("single") - 1)) { + statp->options |= RES_NO_NIBBLE2; + } else if (!strncmp(cp, "both", sizeof("both") - 1)) { + statp->options &= + ~RES_NO_NIBBLE2; + } + } + else { + /* XXX - print a warning here? */ + } + skip: + /* skip to next run of spaces */ + while (*cp && *cp != ' ' && *cp != '\t') + cp++; + } +} + +#ifdef RESOLVSORT +/* XXX - should really support CIDR which means explicit masks always. */ +static u_int32_t +net_mask(in) /*!< XXX - should really use system's version of this */ + struct in_addr in; +{ + register u_int32_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (htonl(IN_CLASSA_NET)); + else if (IN_CLASSB(i)) + return (htonl(IN_CLASSB_NET)); + return (htonl(IN_CLASSC_NET)); +} +#endif + +void +res_rndinit(res_state statp) +{ + struct timeval now; + u_int32_t u32; + u_int16_t u16; + + gettimeofday(&now, NULL); + u32 = now.tv_sec; + memcpy(statp->_u._ext._rnd, &u32, 4); + u32 = now.tv_usec; + memcpy(statp->_u._ext._rnd + 4, &u32, 4); + u32 += now.tv_sec; + memcpy(statp->_u._ext._rnd + 8, &u32, 4); + u16 = getpid(); + memcpy(statp->_u._ext._rnd + 12, &u16, 2); + +} + +u_int +res_nrandomid(res_state statp) { + struct timeval now; + u_int16_t u16; + MD5_CTX ctx; + + gettimeofday(&now, NULL); + u16 = (u_int16_t) (now.tv_sec ^ now.tv_usec); + + memcpy(statp->_u._ext._rnd + 14, &u16, 2); +#ifndef HAVE_MD5 + MD5_Init(&ctx); + MD5_Update(&ctx, statp->_u._ext._rnd, 16); + MD5_Final(statp->_u._ext._rnd, &ctx); +#else + MD5Init(&ctx); + MD5Update(&ctx, statp->_u._ext._rnd, 16); + MD5Final(statp->_u._ext._rnd, &ctx); +#endif + memcpy(&u16, statp->_u._ext._rnd + 14, 2); + return ((u_int) u16); +} + +/*% + * This routine is for closing the socket if a virtual circuit is used and + * the program wants to close it. This provides support for endhostent() + * which expects to close the socket. + * + * This routine is not expected to be user visible. + */ +void +res_nclose(res_state statp) { + int ns; + + if (statp->_vcsock >= 0) { + (void) close(statp->_vcsock); + statp->_vcsock = -1; + statp->_flags &= ~(RES_F_VC | RES_F_CONN); + } + for (ns = 0; ns < statp->_u._ext.nscount; ns++) { + if (statp->_u._ext.nssocks[ns] != -1) { + (void) close(statp->_u._ext.nssocks[ns]); + statp->_u._ext.nssocks[ns] = -1; + } + } +} + +void +res_ndestroy(res_state statp) { + res_nclose(statp); + if (statp->_u._ext.ext != NULL) + free(statp->_u._ext.ext); + statp->options &= ~RES_INIT; + statp->_u._ext.ext = NULL; +} + +const char * +res_get_nibblesuffix(res_state statp) { + if (statp->_u._ext.ext) + return (statp->_u._ext.ext->nsuffix); + return ("ip6.arpa"); +} + +const char * +res_get_nibblesuffix2(res_state statp) { + if (statp->_u._ext.ext) + return (statp->_u._ext.ext->nsuffix2); + return ("ip6.int"); +} + +void +res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) { + int i, nserv; + size_t size; + + /* close open servers */ + res_nclose(statp); + + /* cause rtt times to be forgotten */ + statp->_u._ext.nscount = 0; + + nserv = 0; + for (i = 0; i < cnt && nserv < MAXNS; i++) { + switch (set->sin.sin_family) { + case AF_INET: + size = sizeof(set->sin); + if (statp->_u._ext.ext) + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + &set->sin, size); + if (size <= sizeof(statp->nsaddr_list[nserv])) + memcpy(&statp->nsaddr_list[nserv], + &set->sin, size); + else + statp->nsaddr_list[nserv].sin_family = 0; + nserv++; + break; + +#ifdef HAS_INET6_STRUCTS + case AF_INET6: + size = sizeof(set->sin6); + if (statp->_u._ext.ext) + memcpy(&statp->_u._ext.ext->nsaddrs[nserv], + &set->sin6, size); + if (size <= sizeof(statp->nsaddr_list[nserv])) + memcpy(&statp->nsaddr_list[nserv], + &set->sin6, size); + else + statp->nsaddr_list[nserv].sin_family = 0; + nserv++; + break; +#endif + + default: + break; + } + set++; + } + statp->nscount = nserv; + +} + +int +res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) { + int i; + size_t size; + u_int16_t family; + + for (i = 0; i < statp->nscount && i < cnt; i++) { + if (statp->_u._ext.ext) + family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family; + else + family = statp->nsaddr_list[i].sin_family; + + switch (family) { + case AF_INET: + size = sizeof(set->sin); + if (statp->_u._ext.ext) + memcpy(&set->sin, + &statp->_u._ext.ext->nsaddrs[i], + size); + else + memcpy(&set->sin, &statp->nsaddr_list[i], + size); + break; + +#ifdef HAS_INET6_STRUCTS + case AF_INET6: + size = sizeof(set->sin6); + if (statp->_u._ext.ext) + memcpy(&set->sin6, + &statp->_u._ext.ext->nsaddrs[i], + size); + else + memcpy(&set->sin6, &statp->nsaddr_list[i], + size); + break; +#endif + + default: + set->sin.sin_family = 0; + break; + } + set++; + } + return (statp->nscount); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_mkquery.c b/usr/src/lib/libresolv2_joy/common/resolv/res_mkquery.c new file mode 100644 index 0000000000..cf36855e9d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_mkquery.c @@ -0,0 +1,386 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Portions Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 1996, 1997, 1988, 1999, 2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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 (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. + */ + +/* + * 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_mkquery.c,v 1.10 2008/12/11 09:59:00 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/nameser.h> + +#ifdef SUNW_CONFCHECK +#include <sys/socket.h> +#include <errno.h> +#include <sys/stat.h> +#endif /* SUNW_CONFCHECK */ + + +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <string.h> +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG + +extern const char *_res_opcodes[]; + +#ifdef SUNW_CONFCHECK +static int _confcheck(res_state statp); +#endif /* SUNW_CONFCHECK */ + + +/*% + * Form all types of queries. + * Returns the size of the result or -1. + */ +int +res_nmkquery(res_state statp, + int op, /*!< opcode of query */ + const char *dname, /*!< domain name */ + int class, int type, /*!< class and type of query */ + const u_char *data, /*!< resource record data */ + int datalen, /*!< length of data */ + const u_char *newrr_in, /*!< new rr for modify or append */ + u_char *buf, /*!< buffer to put query */ + int buflen) /*!< size of buffer */ +{ + register HEADER *hp; + register u_char *cp, *ep; + register int n; + u_char *dnptrs[20], **dpp, **lastdnptr; + + UNUSED(newrr_in); + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_nmkquery(%s, %s, %s, %s)\n", + _res_opcodes[op], dname, p_class(class), p_type(type)); +#endif + +#ifdef SUNW_CONFCHECK + /* + * 1247019, 1265838, and 4034368: Check to see if we can + * bailout quickly. + */ + if (_confcheck(statp) == -1) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return(-1); + } +#endif /* SUNW_CONFCHECK */ + + /* + * Initialize header fields. + */ + if ((buf == NULL) || (buflen < HFIXEDSZ)) + return (-1); + memset(buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; + statp->id = res_nrandomid(statp); + hp->id = htons(statp->id); + hp->opcode = op; + hp->rd = (statp->options & RES_RECURSE) != 0U; + hp->rcode = NOERROR; + cp = buf + HFIXEDSZ; + ep = buf + buflen; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + /* + * perform opcode specific processing + */ + switch (op) { + case QUERY: /*FALLTHROUGH*/ + case NS_NOTIFY_OP: + if (ep - cp < QFIXEDSZ) + return (-1); + if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs, + lastdnptr)) < 0) + return (-1); + cp += n; + ns_put16(type, cp); + cp += INT16SZ; + ns_put16(class, cp); + cp += INT16SZ; + hp->qdcount = htons(1); + if (op == QUERY || data == NULL) + break; + /* + * Make an additional record for completion domain. + */ + if ((ep - cp) < RRFIXEDSZ) + return (-1); + n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ, + dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ns_put16(T_NULL, cp); + cp += INT16SZ; + ns_put16(class, cp); + cp += INT16SZ; + ns_put32(0, cp); + cp += INT32SZ; + ns_put16(0, cp); + cp += INT16SZ; + hp->arcount = htons(1); + break; + + case IQUERY: + /* + * Initialize answer section + */ + if (ep - cp < 1 + RRFIXEDSZ + datalen) + return (-1); + *cp++ = '\0'; /*%< no domain name */ + ns_put16(type, cp); + cp += INT16SZ; + ns_put16(class, cp); + cp += INT16SZ; + ns_put32(0, cp); + cp += INT32SZ; + ns_put16(datalen, cp); + cp += INT16SZ; + if (datalen) { + memcpy(cp, data, datalen); + cp += datalen; + } + hp->ancount = htons(1); + break; + + default: + return (-1); + } + return (cp - buf); +} + +#ifdef RES_USE_EDNS0 +/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */ + +int +res_nopt(res_state statp, + int n0, /*%< current offset in buffer */ + u_char *buf, /*%< buffer to put query */ + int buflen, /*%< size of buffer */ + int anslen) /*%< UDP answer buffer size */ +{ + register HEADER *hp; + register u_char *cp, *ep; + u_int16_t flags = 0; + +#ifdef DEBUG + if ((statp->options & RES_DEBUG) != 0U) + printf(";; res_nopt()\n"); +#endif + + hp = (HEADER *) buf; + cp = buf + n0; + ep = buf + buflen; + + if ((ep - cp) < 1 + RRFIXEDSZ) + return (-1); + + *cp++ = 0; /*%< "." */ + ns_put16(ns_t_opt, cp); /*%< TYPE */ + cp += INT16SZ; + ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */ + cp += INT16SZ; + *cp++ = NOERROR; /*%< extended RCODE */ + *cp++ = 0; /*%< EDNS version */ + + if (statp->options & RES_USE_DNSSEC) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_opt()... ENDS0 DNSSEC\n"); +#endif + flags |= NS_OPT_DNSSEC_OK; + } + ns_put16(flags, cp); + cp += INT16SZ; + + ns_put16(0U, cp); /*%< RDLEN */ + cp += INT16SZ; + + hp->arcount = htons(ntohs(hp->arcount) + 1); + + return (cp - buf); +} + +/* + * Construct variable data (RDATA) block for OPT psuedo-RR, append it + * to the buffer, then update the RDLEN field (previously set to zero by + * res_nopt()) with the new RDATA length. + */ +int +res_nopt_rdata(res_state statp, + int n0, /*%< current offset in buffer */ + u_char *buf, /*%< buffer to put query */ + int buflen, /*%< size of buffer */ + u_char *rdata, /*%< ptr to start of opt rdata */ + u_short code, /*%< OPTION-CODE */ + u_short len, /*%< OPTION-LENGTH */ + u_char *data) /*%< OPTION_DATA */ +{ + register u_char *cp, *ep; + +#ifdef DEBUG + if ((statp->options & RES_DEBUG) != 0U) + printf(";; res_nopt_rdata()\n"); +#endif + + cp = buf + n0; + ep = buf + buflen; + + if ((ep - cp) < (4 + len)) + return (-1); + + if (rdata < (buf + 2) || rdata >= ep) + return (-1); + + ns_put16(code, cp); + cp += INT16SZ; + + ns_put16(len, cp); + cp += INT16SZ; + + memcpy(cp, data, len); + cp += len; + + len = cp - rdata; + ns_put16(len, rdata - 2); /* Update RDLEN field */ + + return (cp - buf); +} +#endif + +#ifdef SUNW_CONFCHECK + +/* + * Time out quickly if there is no /etc/resolv.conf and a TCP connection + * to the local DNS server fails. + */ +static int _confcheck(res_state statp) +{ + int ns; + struct stat rc_stat; + struct sockaddr_in ns_sin; + + /* First, we check to see if /etc/resolv.conf exists. + * If it doesn't, then it is likely that the localhost is + * the nameserver. + */ + if (stat(_PATH_RESCONF, &rc_stat) == -1 && errno == ENOENT) { + + /* Next, we check to see if _res.nsaddr is set to loopback. + * If it isn't, it has been altered by the application + * explicitly and we then want to bail with success. + */ + if (statp->nsaddr.sin_addr.S_un.S_addr == + htonl(INADDR_LOOPBACK)) { + + /* Lastly, we try to connect to the TCP port of the + * nameserver. If this fails, then we know that + * DNS is misconfigured and we can quickly exit. + */ + ns = socket(AF_INET, SOCK_STREAM, 0); + IN_SET_LOOPBACK_ADDR(&ns_sin); + ns_sin.sin_port = htons(NAMESERVER_PORT); + if (connect(ns, (struct sockaddr *) &ns_sin, + sizeof ns_sin) == -1) { + close(ns); + return(-1); + } + else { + close(ns); + + return(0); + } + } + + return(0); + } + + return (0); +} +#endif /* SUNW_CONFCHECK */ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_mkupdate.c b/usr/src/lib/libresolv2_joy/common/resolv/res_mkupdate.c new file mode 100644 index 0000000000..8f73e281d0 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_mkupdate.c @@ -0,0 +1,1163 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*! \file + * \brief + * Based on the Dynamic DNS reference implementation by Viraj Bais + * <viraj_bais@ccm.fm.intel.com> + */ + +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: res_mkupdate.c,v 1.10 2008/12/11 09:59:00 marka Exp $"; +#endif /* not lint */ + +#include "port_before.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <res_update.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> + +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG +#define MAXPORT 1024 + +static int getnum_str(u_char **, u_char *); +static int gethexnum_str(u_char **, u_char *); +static int getword_str(char *, int, u_char **, u_char *); +static int getstr_str(char *, int, u_char **, u_char *); + +#define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2); + +/* Forward. */ + +int res_protocolnumber(const char *); +int res_servicenumber(const char *); + +/*% + * Form update packets. + * Returns the size of the resulting packet if no error + * + * On error, + * returns + *\li -1 if error in reading a word/number in rdata + * portion for update packets + *\li -2 if length of buffer passed is insufficient + *\li -3 if zone section is not the first section in + * the linked list, or section order has a problem + *\li -4 on a number overflow + *\li -5 unknown operation or no records + */ +int +res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) { + ns_updrec *rrecp_start = rrecp_in; + HEADER *hp; + u_char *cp, *sp2, *startp, *endp; + int n, i, soanum, multiline; + ns_updrec *rrecp; + struct in_addr ina; + struct in6_addr in6a; + char buf2[MAXDNAME]; + u_char buf3[MAXDNAME]; + int section, numrrs = 0, counts[ns_s_max]; + u_int16_t rtype, rclass; + u_int32_t n1, rttl; + u_char *dnptrs[20], **dpp, **lastdnptr; + int siglen, keylen, certlen; + + /* + * Initialize header fields. + */ + if ((buf == NULL) || (buflen < HFIXEDSZ)) + return (-1); + memset(buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; + statp->id = res_nrandomid(statp); + hp->id = htons(statp->id); + hp->opcode = ns_o_update; + hp->rcode = NOERROR; + cp = buf + HFIXEDSZ; + buflen -= HFIXEDSZ; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + + if (rrecp_start == NULL) + return (-5); + else if (rrecp_start->r_section != S_ZONE) + return (-3); + + memset(counts, 0, sizeof counts); + for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) { + numrrs++; + section = rrecp->r_section; + if (section < 0 || section >= ns_s_max) + return (-1); + counts[section]++; + for (i = section + 1; i < ns_s_max; i++) + if (counts[i]) + return (-3); + rtype = rrecp->r_type; + rclass = rrecp->r_class; + rttl = rrecp->r_ttl; + /* overload class and type */ + if (section == S_PREREQ) { + rttl = 0; + switch (rrecp->r_opcode) { + case YXDOMAIN: + rclass = C_ANY; + rtype = T_ANY; + rrecp->r_size = 0; + break; + case NXDOMAIN: + rclass = C_NONE; + rtype = T_ANY; + rrecp->r_size = 0; + break; + case NXRRSET: + rclass = C_NONE; + rrecp->r_size = 0; + break; + case YXRRSET: + if (rrecp->r_size == 0) + rclass = C_ANY; + break; + default: + fprintf(stderr, + "res_mkupdate: incorrect opcode: %d\n", + rrecp->r_opcode); + fflush(stderr); + return (-1); + } + } else if (section == S_UPDATE) { + switch (rrecp->r_opcode) { + case DELETE: + rclass = rrecp->r_size == 0 ? C_ANY : C_NONE; + break; + case ADD: + break; + default: + fprintf(stderr, + "res_mkupdate: incorrect opcode: %d\n", + rrecp->r_opcode); + fflush(stderr); + return (-1); + } + } + + /* + * XXX appending default domain to owner name is omitted, + * fqdn must be provided + */ + if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs, + lastdnptr)) < 0) + return (-1); + cp += n; + ShrinkBuffer(n + 2*INT16SZ); + PUTSHORT(rtype, cp); + PUTSHORT(rclass, cp); + if (section == S_ZONE) { + if (numrrs != 1 || rrecp->r_type != T_SOA) + return (-3); + continue; + } + ShrinkBuffer(INT32SZ + INT16SZ); + PUTLONG(rttl, cp); + sp2 = cp; /*%< save pointer to length byte */ + cp += INT16SZ; + if (rrecp->r_size == 0) { + if (section == S_UPDATE && rclass != C_ANY) + return (-1); + else { + PUTSHORT(0, sp2); + continue; + } + } + startp = rrecp->r_data; + endp = startp + rrecp->r_size - 1; + /* XXX this should be done centrally. */ + switch (rrecp->r_type) { + case T_A: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if (!inet_aton(buf2, &ina)) + return (-1); + n1 = ntohl(ina.s_addr); + ShrinkBuffer(INT32SZ); + PUTLONG(n1, cp); + break; + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + case ns_t_dname: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_MINFO: + case T_SOA: + case T_RP: + for (i = 0; i < 2; i++) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, + dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + } + if (rrecp->r_type == T_SOA) { + ShrinkBuffer(5 * INT32SZ); + while (isspace(*startp) || !*startp) + startp++; + if (*startp == '(') { + multiline = 1; + startp++; + } else + multiline = 0; + /* serial, refresh, retry, expire, minimum */ + for (i = 0; i < 5; i++) { + soanum = getnum_str(&startp, endp); + if (soanum < 0) + return (-1); + PUTLONG(soanum, cp); + } + if (multiline) { + while (isspace(*startp) || !*startp) + startp++; + if (*startp != ')') + return (-1); + } + } + break; + case T_MX: + case T_AFSDB: + case T_RT: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_SRV: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, NULL, NULL); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + case T_PX: + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + PUTSHORT(n, cp); + ShrinkBuffer(INT16SZ); + for (i = 0; i < 2; i++) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, + lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + } + break; + case T_WKS: { + char bm[MAXPORT/8]; + unsigned int maxbm = 0; + + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if (!inet_aton(buf2, &ina)) + return (-1); + n1 = ntohl(ina.s_addr); + ShrinkBuffer(INT32SZ); + PUTLONG(n1, cp); + + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if ((i = res_protocolnumber(buf2)) < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = i & 0xff; + + for (i = 0; i < MAXPORT/8 ; i++) + bm[i] = 0; + + while (getword_str(buf2, sizeof buf2, &startp, endp)) { + if ((n = res_servicenumber(buf2)) <= 0) + return (-1); + + if (n < MAXPORT) { + bm[n/8] |= (0x80>>(n%8)); + if ((unsigned)n > maxbm) + maxbm = n; + } else + return (-1); + } + maxbm = maxbm/8 + 1; + ShrinkBuffer(maxbm); + memcpy(cp, bm, maxbm); + cp += maxbm; + break; + } + case T_HINFO: + for (i = 0; i < 2; i++) { + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + } + break; + case T_TXT: + for (;;) { + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) { + if (cp != (sp2 + INT16SZ)) + break; + return (-1); + } + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + } + break; + case T_X25: + /* RFC1183 */ + if ((n = getstr_str(buf2, sizeof buf2, &startp, + endp)) < 0) + return (-1); + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + break; + case T_ISDN: + /* RFC1183 */ + if ((n = getstr_str(buf2, sizeof buf2, &startp, + endp)) < 0) + return (-1); + if ((n > 255) || (n == 0)) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + if ((n = getstr_str(buf2, sizeof buf2, &startp, + endp)) < 0) + n = 0; + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + break; + case T_NSAP: + if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) { + ShrinkBuffer(n); + memcpy(cp, buf2, n); + cp += n; + } else { + return (-1); + } + break; + case T_LOC: + if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) { + ShrinkBuffer(n); + memcpy(cp, buf2, n); + cp += n; + } else + return (-1); + break; + case ns_t_sig: + { + int sig_type, success, dateerror; + u_int32_t exptime, timesigned; + + /* type */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + sig_type = sym_ston(__p_type_syms, buf2, &success); + if (!success || sig_type == ns_t_any) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(sig_type, cp); + /* alg */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* labels */ + n = getnum_str(&startp, endp); + if (n <= 0 || n > 255) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* ottl & expire */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + exptime = ns_datetosecs(buf2, &dateerror); + if (!dateerror) { + ShrinkBuffer(INT32SZ); + PUTLONG(rttl, cp); + } + else { + char *ulendp; + u_int32_t ottl; + + errno = 0; + ottl = strtoul(buf2, &ulendp, 10); + if (errno != 0 || + (ulendp != NULL && *ulendp != '\0')) + return (-1); + ShrinkBuffer(INT32SZ); + PUTLONG(ottl, cp); + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + return (-1); + exptime = ns_datetosecs(buf2, &dateerror); + if (dateerror) + return (-1); + } + /* expire */ + ShrinkBuffer(INT32SZ); + PUTLONG(exptime, cp); + /* timesigned */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + timesigned = ns_datetosecs(buf2, &dateerror); + if (!dateerror) { + ShrinkBuffer(INT32SZ); + PUTLONG(timesigned, cp); + } + else + return (-1); + /* footprint */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* signer name */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + /* sig */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + siglen = b64_pton(buf2, buf3, sizeof(buf3)); + if (siglen < 0) + return (-1); + ShrinkBuffer(siglen); + memcpy(cp, buf3, siglen); + cp += siglen; + break; + } + case ns_t_key: + /* flags */ + n = gethexnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* proto */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* alg */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* key */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + keylen = b64_pton(buf2, buf3, sizeof(buf3)); + if (keylen < 0) + return (-1); + ShrinkBuffer(keylen); + memcpy(cp, buf3, keylen); + cp += keylen; + break; + case ns_t_nxt: + { + int success, nxt_type; + u_char data[32]; + int maxtype; + + /* next name */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, NULL, NULL); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + maxtype = 0; + memset(data, 0, sizeof data); + for (;;) { + if (!getword_str(buf2, sizeof buf2, &startp, + endp)) + break; + nxt_type = sym_ston(__p_type_syms, buf2, + &success); + if (!success || !ns_t_rr_p(nxt_type)) + return (-1); + NS_NXT_BIT_SET(nxt_type, data); + if (nxt_type > maxtype) + maxtype = nxt_type; + } + n = maxtype/NS_NXT_BITS+1; + ShrinkBuffer(n); + memcpy(cp, data, n); + cp += n; + break; + } + case ns_t_cert: + /* type */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* key tag */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* alg */ + n = getnum_str(&startp, endp); + if (n < 0) + return (-1); + ShrinkBuffer(1); + *cp++ = n; + /* cert */ + if ((n = getword_str(buf2, sizeof buf2, + &startp, endp)) < 0) + return (-1); + certlen = b64_pton(buf2, buf3, sizeof(buf3)); + if (certlen < 0) + return (-1); + ShrinkBuffer(certlen); + memcpy(cp, buf3, certlen); + cp += certlen; + break; + case ns_t_aaaa: + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + if (inet_pton(AF_INET6, buf2, &in6a) <= 0) + return (-1); + ShrinkBuffer(NS_IN6ADDRSZ); + memcpy(cp, &in6a, NS_IN6ADDRSZ); + cp += NS_IN6ADDRSZ; + break; + case ns_t_naptr: + /* Order Preference Flags Service Replacement Regexp */ + /* Order */ + n = getnum_str(&startp, endp); + if (n < 0 || n > 65535) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* Preference */ + n = getnum_str(&startp, endp); + if (n < 0 || n > 65535) + return (-1); + ShrinkBuffer(INT16SZ); + PUTSHORT(n, cp); + /* Flags */ + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) { + return (-1); + } + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + /* Service Classes */ + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) { + return (-1); + } + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + /* Pattern */ + if ((n = getstr_str(buf2, sizeof buf2, + &startp, endp)) < 0) { + return (-1); + } + if (n > 255) + return (-1); + ShrinkBuffer(n+1); + *cp++ = n; + memcpy(cp, buf2, n); + cp += n; + /* Replacement */ + if (!getword_str(buf2, sizeof buf2, &startp, endp)) + return (-1); + n = dn_comp(buf2, cp, buflen, NULL, NULL); + if (n < 0) + return (-1); + cp += n; + ShrinkBuffer(n); + break; + default: + return (-1); + } /*switch*/ + n = (u_int16_t)((cp - sp2) - INT16SZ); + PUTSHORT(n, sp2); + } /*for*/ + + hp->qdcount = htons(counts[0]); + hp->ancount = htons(counts[1]); + hp->nscount = htons(counts[2]); + hp->arcount = htons(counts[3]); + return (cp - buf); +} + +/*% + * Get a whitespace delimited word from a string (not file) + * into buf. modify the start pointer to point after the + * word in the string. + */ +static int +getword_str(char *buf, int size, u_char **startpp, u_char *endp) { + char *cp; + int c; + + for (cp = buf; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (cp != buf) /*%< trailing whitespace */ + break; + else { /*%< leading whitespace */ + (*startpp)++; + continue; + } + } + (*startpp)++; + if (cp >= buf+size-1) + break; + *cp++ = (u_char)c; + } + *cp = '\0'; + return (cp != buf); +} + +/*% + * get a white spae delimited string from memory. Process quoted strings + * and \\DDD escapes. Return length or -1 on error. Returned string may + * contain nulls. + */ +static char digits[] = "0123456789"; +static int +getstr_str(char *buf, int size, u_char **startpp, u_char *endp) { + char *cp; + int c, c1 = 0; + int inquote = 0; + int seen_quote = 0; + int escape = 0; + int dig = 0; + + for (cp = buf; *startpp <= endp; ) { + if ((c = **startpp) == '\0') + break; + /* leading white space */ + if ((cp == buf) && !seen_quote && isspace(c)) { + (*startpp)++; + continue; + } + + switch (c) { + case '\\': + if (!escape) { + escape = 1; + dig = 0; + c1 = 0; + (*startpp)++; + continue; + } + goto do_escape; + case '"': + if (!escape) { + inquote = !inquote; + seen_quote = 1; + (*startpp)++; + continue; + } + /* fall through */ + default: + do_escape: + if (escape) { + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + c1 = c1 * 10 + + (strchr(digits, c) - digits); + + if (++dig == 3) { + c = c1 &0xff; + break; + } + (*startpp)++; + continue; + } + escape = 0; + } else if (!inquote && isspace(c)) + goto done; + if (cp >= buf+size-1) + goto done; + *cp++ = (u_char)c; + (*startpp)++; + } + } + done: + *cp = '\0'; + return ((cp == buf)? (seen_quote? 0: -1): (cp - buf)); +} + +/*% + * Get a whitespace delimited base 16 number from a string (not file) into buf + * update the start pointer to point after the number in the string. + */ +static int +gethexnum_str(u_char **startpp, u_char *endp) { + int c, n; + int seendigit = 0; + int m = 0; + + if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0) + return getnum_str(startpp, endp); + (*startpp)+=2; + for (n = 0; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (seendigit) /*%< trailing whitespace */ + break; + else { /*%< leading whitespace */ + (*startpp)++; + continue; + } + } + if (c == ';') { + while ((*startpp <= endp) && + ((c = **startpp) != '\n')) + (*startpp)++; + if (seendigit) + break; + continue; + } + if (!isxdigit(c)) { + if (c == ')' && seendigit) { + (*startpp)--; + break; + } + return (-1); + } + (*startpp)++; + if (isdigit(c)) + n = n * 16 + (c - '0'); + else + n = n * 16 + (tolower(c) - 'a' + 10); + seendigit = 1; + } + return (n + m); +} + +/*% + * Get a whitespace delimited base 10 number from a string (not file) into buf + * update the start pointer to point after the number in the string. + */ +static int +getnum_str(u_char **startpp, u_char *endp) { + int c, n; + int seendigit = 0; + int m = 0; + + for (n = 0; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (seendigit) /*%< trailing whitespace */ + break; + else { /*%< leading whitespace */ + (*startpp)++; + continue; + } + } + if (c == ';') { + while ((*startpp <= endp) && + ((c = **startpp) != '\n')) + (*startpp)++; + if (seendigit) + break; + continue; + } + if (!isdigit(c)) { + if (c == ')' && seendigit) { + (*startpp)--; + break; + } + return (-1); + } + (*startpp)++; + n = n * 10 + (c - '0'); + seendigit = 1; + } + return (n + m); +} + +/*% + * Allocate a resource record buffer & save rr info. + */ +ns_updrec * +res_mkupdrec(int section, const char *dname, + u_int class, u_int type, u_long ttl) { + ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec)); + + if (!rrecp || !(rrecp->r_dname = strdup(dname))) { + if (rrecp) + free((char *)rrecp); + return (NULL); + } + INIT_LINK(rrecp, r_link); + INIT_LINK(rrecp, r_glink); + rrecp->r_class = (ns_class)class; + rrecp->r_type = (ns_type)type; + rrecp->r_ttl = ttl; + rrecp->r_section = (ns_sect)section; + return (rrecp); +} + +/*% + * Free a resource record buffer created by res_mkupdrec. + */ +void +res_freeupdrec(ns_updrec *rrecp) { + /* Note: freeing r_dp is the caller's responsibility. */ + if (rrecp->r_dname != NULL) + free(rrecp->r_dname); + free(rrecp); +} + +struct valuelist { + struct valuelist * next; + struct valuelist * prev; + char * name; + char * proto; + int port; +}; +static struct valuelist *servicelist, *protolist; + +static void +res_buildservicelist() { + struct servent *sp; + struct valuelist *slp; + +#ifdef MAYBE_HESIOD + setservent(0); +#else + setservent(1); +#endif + while ((sp = getservent()) != NULL) { + slp = (struct valuelist *)malloc(sizeof(struct valuelist)); + if (!slp) + break; + slp->name = strdup(sp->s_name); + slp->proto = strdup(sp->s_proto); + if ((slp->name == NULL) || (slp->proto == NULL)) { + if (slp->name) free(slp->name); + if (slp->proto) free(slp->proto); + free(slp); + break; + } + slp->port = ntohs((u_int16_t)sp->s_port); /*%< host byt order */ + slp->next = servicelist; + slp->prev = NULL; + if (servicelist) + servicelist->prev = slp; + servicelist = slp; + } + endservent(); +} + +void +res_destroyservicelist() { + struct valuelist *slp, *slp_next; + + for (slp = servicelist; slp != NULL; slp = slp_next) { + slp_next = slp->next; + free(slp->name); + free(slp->proto); + free(slp); + } + servicelist = (struct valuelist *)0; +} + +void +res_buildprotolist(void) { + struct protoent *pp; + struct valuelist *slp; + +#ifdef MAYBE_HESIOD + setprotoent(0); +#else + setprotoent(1); +#endif + while ((pp = getprotoent()) != NULL) { + slp = (struct valuelist *)malloc(sizeof(struct valuelist)); + if (!slp) + break; + slp->name = strdup(pp->p_name); + if (slp->name == NULL) { + free(slp); + break; + } + slp->port = pp->p_proto; /*%< host byte order */ + slp->next = protolist; + slp->prev = NULL; + if (protolist) + protolist->prev = slp; + protolist = slp; + } + endprotoent(); +} + +void +res_destroyprotolist(void) { + struct valuelist *plp, *plp_next; + + for (plp = protolist; plp != NULL; plp = plp_next) { + plp_next = plp->next; + free(plp->name); + free(plp); + } + protolist = (struct valuelist *)0; +} + +static int +findservice(const char *s, struct valuelist **list) { + struct valuelist *lp = *list; + int n; + + for (; lp != NULL; lp = lp->next) + if (strcasecmp(lp->name, s) == 0) { + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + return (lp->port); /*%< host byte order */ + } + if (sscanf(s, "%d", &n) != 1 || n <= 0) + n = -1; + return (n); +} + +/*% + * Convert service name or (ascii) number to int. + */ +int +res_servicenumber(const char *p) { + if (servicelist == (struct valuelist *)0) + res_buildservicelist(); + return (findservice(p, &servicelist)); +} + +/*% + * Convert protocol name or (ascii) number to int. + */ +int +res_protocolnumber(const char *p) { + if (protolist == (struct valuelist *)0) + res_buildprotolist(); + return (findservice(p, &protolist)); +} + +static struct servent * +cgetservbyport(u_int16_t port, const char *proto) { /*%< Host byte order. */ + struct valuelist **list = &servicelist; + struct valuelist *lp = *list; + static struct servent serv; + + port = ntohs(port); + for (; lp != NULL; lp = lp->next) { + if (port != (u_int16_t)lp->port) /*%< Host byte order. */ + continue; + if (strcasecmp(lp->proto, proto) == 0) { + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + serv.s_name = lp->name; + serv.s_port = htons((u_int16_t)lp->port); + serv.s_proto = lp->proto; + return (&serv); + } + } + return (0); +} + +static struct protoent * +cgetprotobynumber(int proto) { /*%< Host byte order. */ + struct valuelist **list = &protolist; + struct valuelist *lp = *list; + static struct protoent prot; + + for (; lp != NULL; lp = lp->next) + if (lp->port == proto) { /*%< Host byte order. */ + if (lp != *list) { + lp->prev->next = lp->next; + if (lp->next) + lp->next->prev = lp->prev; + (*list)->prev = lp; + lp->next = *list; + *list = lp; + } + prot.p_name = lp->name; + prot.p_proto = lp->port; /*%< Host byte order. */ + return (&prot); + } + return (0); +} + +const char * +res_protocolname(int num) { + static char number[8]; + struct protoent *pp; + + if (protolist == (struct valuelist *)0) + res_buildprotolist(); + pp = cgetprotobynumber(num); + if (pp == 0) { + (void) sprintf(number, "%d", num); + return (number); + } + return (pp->p_name); +} + +const char * +res_servicename(u_int16_t port, const char *proto) { /*%< Host byte order. */ + static char number[8]; + struct servent *ss; + + if (servicelist == (struct valuelist *)0) + res_buildservicelist(); + ss = cgetservbyport(htons(port), proto); + if (ss == 0) { + (void) sprintf(number, "%d", port); + return (number); + } + return (ss->s_name); +} diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_mkupdate.h b/usr/src/lib/libresolv2_joy/common/resolv/res_mkupdate.h new file mode 100644 index 0000000000..96c452d89e --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_mkupdate.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 _RES_MKUPDATE_H_ +#define _RES_MKUPDATE_H_ + +__BEGIN_DECLS +__END_DECLS + +#endif /* _RES_MKUPDATE_H_ */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_private.h b/usr/src/lib/libresolv2_joy/common/resolv/res_private.h new file mode 100644 index 0000000000..4e98157ced --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_private.h @@ -0,0 +1,22 @@ +#ifndef res_private_h +#define res_private_h + +struct __res_state_ext { + union res_sockaddr_union nsaddrs[MAXNS]; + struct sort_list { + int af; + union { + struct in_addr ina; + struct in6_addr in6a; + } addr, mask; + } sort_list[MAXRESOLVSORT]; + char nsuffix[64]; + char nsuffix2[64]; +}; + +extern int +res_ourserver_p(const res_state statp, const struct sockaddr *sa); + +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_query.c b/usr/src/lib/libresolv2_joy/common/resolv/res_query.c new file mode 100644 index 0000000000..09df3da1fc --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_query.c @@ -0,0 +1,440 @@ +/* + * Portions Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 1996-2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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 (c) 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_query.c,v 1.11 2008/11/14 02:36:51 marka Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "port_before.h" +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "port_after.h" + +/* Options. Leave them on. */ +#define DEBUG + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +/*% + * 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. + */ +int +res_nquery(res_state statp, + const char *name, /*%< domain name */ + int class, int type, /*%< class and type of query */ + u_char *answer, /*%< buffer to put answer */ + int anslen) /*%< size of answer buffer */ +{ + u_char buf[MAXPACKET]; + HEADER *hp = (HEADER *) answer; + u_int oflags; + u_char *rdata; + int n; + + oflags = statp->_flags; + +again: + hp->rcode = NOERROR; /*%< default */ +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_query(%s, %d, %d)\n", name, class, type); +#endif + + n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, + buf, sizeof(buf)); +#ifdef RES_USE_EDNS0 + if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 && + (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC|RES_NSID))) { + n = res_nopt(statp, n, buf, sizeof(buf), anslen); + rdata = &buf[n]; + if (n > 0 && (statp->options & RES_NSID) != 0U) { + n = res_nopt_rdata(statp, n, buf, sizeof(buf), rdata, + NS_OPT_NSID, 0, NULL); + } + } +#endif + if (n <= 0) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_query: mkquery failed\n"); +#endif + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (n); + } + + n = res_nsend(statp, buf, n, answer, anslen); + if (n < 0) { +#ifdef RES_USE_EDNS0 + /* if the query choked with EDNS0, retry without EDNS0 */ + if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U && + ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { + statp->_flags |= RES_F_EDNS0ERR; + if (statp->options & RES_DEBUG) + printf(";; res_nquery: retry without EDNS0\n"); + goto again; + } +#endif +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_query: send error\n"); +#endif + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (n); + } + + if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; rcode = (%s), counts = an:%d ns:%d ar:%d\n", + p_rcode(hp->rcode), + ntohs(hp->ancount), + ntohs(hp->nscount), + ntohs(hp->arcount)); +#endif + switch (hp->rcode) { + case NXDOMAIN: + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + break; + case SERVFAIL: + RES_SET_H_ERRNO(statp, TRY_AGAIN); + break; + case NOERROR: + RES_SET_H_ERRNO(statp, NO_DATA); + break; + case FORMERR: + case NOTIMP: + case REFUSED: + default: + RES_SET_H_ERRNO(statp, NO_RECOVERY); + break; + } + return (-1); + } + return (n); +} + +/*% + * 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. + */ +int +res_nsearch(res_state statp, + const char *name, /*%< domain name */ + int class, int type, /*%< class and type of query */ + u_char *answer, /*%< buffer to put answer */ + int anslen) /*%< size of answer */ +{ + const char *cp, * const *domain; + HEADER *hp = (HEADER *) answer; + char tmp[NS_MAXDNAME]; + u_int dots; + int trailing_dot, ret, saved_herrno; + int got_nodata = 0, got_servfail = 0, root_on_list = 0; + int tried_as_is = 0; + int searched = 0; + + errno = 0; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /*%< True if we never query. */ + dots = 0; + for (cp = name; *cp != '\0'; 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 = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) + return (res_nquery(statp, cp, class, type, answer, anslen)); + + /* + * If there are enough dots in the name, let's just give it a + * try 'as is'. The threshold can be set with the "ndots" option. + * Also, query 'as is', if there is a trailing dot in the name. + */ + saved_herrno = -1; + if (dots >= statp->ndots || trailing_dot) { + ret = res_nquerydomain(statp, name, NULL, class, type, + answer, anslen); + if (ret > 0 || trailing_dot) + return (ret); + saved_herrno = statp->res_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 && (statp->options & RES_DEFNAMES) != 0U) || + (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0U)) { + int done = 0; + + for (domain = (const char * const *)statp->dnsrch; + *domain && !done; + domain++) { + searched = 1; + + if (domain[0][0] == '\0' || + (domain[0][0] == '.' && domain[0][1] == '\0')) + root_on_list++; + + ret = res_nquerydomain(statp, name, *domain, + class, type, + answer, anslen); + 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) { + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); + } + + switch (statp->res_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 ((statp->options & RES_DNSRCH) == 0U) + done++; + } + } + + /* + * If the query has not already been tried as is then try it + * unless RES_NOTLDQUERY is set and there were no dots. + */ + if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0U) && + !(tried_as_is || root_on_list)) { + ret = res_nquerydomain(statp, name, NULL, class, type, + answer, anslen); + 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) + RES_SET_H_ERRNO(statp, saved_herrno); + else if (got_nodata) + RES_SET_H_ERRNO(statp, NO_DATA); + else if (got_servfail) + RES_SET_H_ERRNO(statp, 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. + */ +int +res_nquerydomain(res_state statp, + const char *name, + const char *domain, + int class, int type, /*%< class and type of query */ + u_char *answer, /*%< buffer to put answer */ + int anslen) /*%< size of answer */ +{ + char nbuf[MAXDNAME]; + const char *longname = nbuf; + int n, d; + +#ifdef DEBUG + if (statp->options & RES_DEBUG) + printf(";; res_nquerydomain(%s, %s, %d, %d)\n", + name, domain?domain:"<Nil>", class, type); +#endif + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name); + if (n >= MAXDNAME) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + n--; + 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) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + sprintf(nbuf, "%s.%s", name, domain); + } + return (res_nquery(statp, longname, class, type, answer, anslen)); +} + +const char * +res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { + char *file, *cp1, *cp2; + char buf[BUFSIZ]; + FILE *fp; + + if (statp->options & RES_NOALIASES) + return (NULL); + file = getenv("HOSTALIASES"); + if (file == NULL || (fp = fopen(file, "r")) == NULL) + return (NULL); + setbuf(fp, NULL); + buf[sizeof(buf) - 1] = '\0'; + while (fgets(buf, sizeof(buf), fp)) { + for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1) + ; + if (!*cp1) + break; + *cp1 = '\0'; + if (ns_samename(buf, name) == 1) { + while (isspace((unsigned char)*++cp1)) + ; + if (!*cp1) + break; + for (cp2 = cp1 + 1; *cp2 && + !isspace((unsigned char)*cp2); ++cp2) + ; + *cp2 = '\0'; + strncpy(dst, cp1, siz - 1); + dst[siz - 1] = '\0'; + fclose(fp); + return (dst); + } + } + fclose(fp); + return (NULL); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_send.c b/usr/src/lib/libresolv2_joy/common/resolv/res_send.c new file mode 100644 index 0000000000..289db4e77d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_send.c @@ -0,0 +1,1120 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 1996-2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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 (c) 1985, 1989, 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; +static const char rcsid[] = "$Id: res_send.c,v 1.22 2009/01/22 23:49:23 tbox Exp $"; +#endif /* LIBC_SCCS and not lint */ + +/*! \file + * \brief + * Send query to name server and wait for reply. + */ + +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/uio.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <isc/eventlib.h> + +#include "port_after.h" + +#ifdef USE_POLL +#ifdef HAVE_STROPTS_H +#include <stropts.h> +#endif +#include <poll.h> +#endif /* USE_POLL */ + +/* Options. Leave them on. */ +#define DEBUG +#include "res_debug.h" +#include "res_private.h" + +#define EXT(res) ((res)->_u._ext) + +#ifndef USE_POLL +static const int highestFD = FD_SETSIZE - 1; +#else +static int highestFD = 0; +#endif + +/* Forward. */ + +static int get_salen __P((const struct sockaddr *)); +static struct sockaddr * get_nsaddr __P((res_state, size_t)); +static int send_vc(res_state, const u_char *, int, + u_char *, int, int *, int); +static int send_dg(res_state, const u_char *, int, + u_char *, int, int *, int, int, + int *, int *); +static void Aerror(const res_state, FILE *, const char *, int, + const struct sockaddr *, int); +static void Perror(const res_state, FILE *, const char *, int); +static int sock_eq(struct sockaddr *, struct sockaddr *); +#if defined(NEED_PSELECT) && !defined(USE_POLL) +static int pselect(int, void *, void *, void *, + struct timespec *, + const sigset_t *); +#endif +void res_pquery(const res_state, const u_char *, int, FILE *); + +#ifndef ORIGINAL_ISC_CODE +#pragma weak __res_nameinquery = res_nameinquery +#pragma weak __res_queriesmatch = res_queriesmatch +#pragma weak res_nisourserver = res_ourserver_p +#endif /* ORIGINAL_ISC_CODE */ + +static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; + +/* Public. */ + +/*% + * looks up "ina" in _res.ns_addr_list[] + * + * returns: + *\li 0 : not found + *\li >0 : found + * + * author: + *\li paul vixie, 29may94 + */ +int +res_ourserver_p(const res_state statp, const struct sockaddr *sa) { + const struct sockaddr_in *inp, *srv; + const struct sockaddr_in6 *in6p, *srv6; + int ns; + + switch (sa->sa_family) { + case AF_INET: + inp = (const struct sockaddr_in *)sa; + for (ns = 0; ns < statp->nscount; ns++) { + srv = (struct sockaddr_in *)get_nsaddr(statp, ns); + if (srv->sin_family == inp->sin_family && + srv->sin_port == inp->sin_port && + (srv->sin_addr.s_addr == INADDR_ANY || + srv->sin_addr.s_addr == inp->sin_addr.s_addr)) + return (1); + } + break; + case AF_INET6: + if (EXT(statp).ext == NULL) + break; + in6p = (const struct sockaddr_in6 *)sa; + for (ns = 0; ns < statp->nscount; ns++) { + srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns); + if (srv6->sin6_family == in6p->sin6_family && + srv6->sin6_port == in6p->sin6_port && +#ifdef HAVE_SIN6_SCOPE_ID + (srv6->sin6_scope_id == 0 || + srv6->sin6_scope_id == in6p->sin6_scope_id) && +#endif + (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || + IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) + return (1); + } + break; + default: + break; + } + return (0); +} + +/*% + * look for (name,type,class) in the query section of packet (buf,eom) + * + * requires: + *\li buf + HFIXEDSZ <= eom + * + * returns: + *\li -1 : format error + *\li 0 : not found + *\li >0 : found + * + * author: + *\li paul vixie, 29may94 + */ +int +res_nameinquery(const char *name, int type, int class, + const u_char *buf, const u_char *eom) +{ + const u_char *cp = buf + HFIXEDSZ; + int qdcount = ntohs(((const HEADER*)buf)->qdcount); + + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + int n, ttype, tclass; + + n = dn_expand(buf, eom, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + if (cp + 2 * INT16SZ > eom) + return (-1); + ttype = ns_get16(cp); cp += INT16SZ; + tclass = ns_get16(cp); cp += INT16SZ; + if (ttype == type && tclass == class && + ns_samename(tname, name) == 1) + return (1); + } + return (0); +} + +/*% + * is there a 1:1 mapping of (name,type,class) + * in (buf1,eom1) and (buf2,eom2)? + * + * returns: + *\li -1 : format error + *\li 0 : not a 1:1 mapping + *\li >0 : is a 1:1 mapping + * + * author: + *\li paul vixie, 29may94 + */ +int +res_queriesmatch(const u_char *buf1, const u_char *eom1, + const u_char *buf2, const u_char *eom2) +{ + const u_char *cp = buf1 + HFIXEDSZ; + int qdcount = ntohs(((const HEADER*)buf1)->qdcount); + + if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) + return (-1); + + /* + * Only header section present in replies to + * dynamic update packets. + */ + if ((((const HEADER *)buf1)->opcode == ns_o_update) && + (((const HEADER *)buf2)->opcode == ns_o_update)) + return (1); + + if (qdcount != ntohs(((const HEADER*)buf2)->qdcount)) + return (0); + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + int n, ttype, tclass; + + n = dn_expand(buf1, eom1, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + if (cp + 2 * INT16SZ > eom1) + return (-1); + ttype = ns_get16(cp); cp += INT16SZ; + tclass = ns_get16(cp); cp += INT16SZ; + if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) + return (0); + } + return (1); +} + +int +res_nsend(res_state statp, + const u_char *buf, int buflen, u_char *ans, int anssiz) +{ + int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n; + char abuf[NI_MAXHOST]; + +#ifdef USE_POLL + highestFD = sysconf(_SC_OPEN_MAX) - 1; +#endif + + /* No name servers or res_init() failure */ + if (statp->nscount == 0 || EXT(statp).ext == NULL) { + errno = ESRCH; + return (-1); + } + if (anssiz < HFIXEDSZ) { + errno = EINVAL; + return (-1); + } + DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), + (stdout, ";; res_send()\n"), buf, buflen); + v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; + gotsomewhere = 0; + terrno = ETIMEDOUT; + + /* + * If the ns_addr_list in the resolver context has changed, then + * invalidate our cached copy and the associated timing data. + */ + if (EXT(statp).nscount != 0) { + int needclose = 0; + struct sockaddr_storage peer; + ISC_SOCKLEN_T peerlen; + + if (EXT(statp).nscount != statp->nscount) + needclose++; + else + for (ns = 0; ns < statp->nscount; ns++) { + if (statp->nsaddr_list[ns].sin_family && + !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns], + (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) { + needclose++; + break; + } + + if (EXT(statp).nssocks[ns] == -1) + continue; + peerlen = sizeof(peer); + if (getpeername(EXT(statp).nssocks[ns], + (struct sockaddr *)&peer, &peerlen) < 0) { + needclose++; + break; + } + if (!sock_eq((struct sockaddr *)&peer, + get_nsaddr(statp, ns))) { + needclose++; + break; + } + } + if (needclose) { + res_nclose(statp); + EXT(statp).nscount = 0; + } + } + + /* + * Maybe initialize our private copy of the ns_addr_list. + */ + if (EXT(statp).nscount == 0) { + for (ns = 0; ns < statp->nscount; ns++) { + EXT(statp).nstimes[ns] = RES_MAXTIME; + EXT(statp).nssocks[ns] = -1; + if (!statp->nsaddr_list[ns].sin_family) + continue; + EXT(statp).ext->nsaddrs[ns].sin = + statp->nsaddr_list[ns]; + } + EXT(statp).nscount = statp->nscount; + } + + /* + * Some resolvers want to even out the load on their nameservers. + * Note that RES_BLAST overrides RES_ROTATE. + */ + if ((statp->options & RES_ROTATE) != 0U && + (statp->options & RES_BLAST) == 0U) { + union res_sockaddr_union inu; + struct sockaddr_in ina; + int lastns = statp->nscount - 1; + int fd; + u_int16_t nstime; + + if (EXT(statp).ext != NULL) + inu = EXT(statp).ext->nsaddrs[0]; + ina = statp->nsaddr_list[0]; + fd = EXT(statp).nssocks[0]; + nstime = EXT(statp).nstimes[0]; + for (ns = 0; ns < lastns; ns++) { + if (EXT(statp).ext != NULL) + EXT(statp).ext->nsaddrs[ns] = + EXT(statp).ext->nsaddrs[ns + 1]; + statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; + EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; + EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; + } + if (EXT(statp).ext != NULL) + EXT(statp).ext->nsaddrs[lastns] = inu; + statp->nsaddr_list[lastns] = ina; + EXT(statp).nssocks[lastns] = fd; + EXT(statp).nstimes[lastns] = nstime; + } + + /* + * Send request, RETRY times, or until successful. + */ + for (tries = 0; tries < statp->retry; tries++) { + for (ns = 0; ns < statp->nscount; ns++) { + struct sockaddr *nsap; + int nsaplen; + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); + statp->_flags &= ~RES_F_LASTMASK; + statp->_flags |= (ns << RES_F_LASTSHIFT); + same_ns: + if (statp->qhook) { + int done = 0, loops = 0; + + do { + res_sendhookact act; + + act = (*statp->qhook)(&nsap, &buf, &buflen, + ans, anssiz, &resplen); + switch (act) { + case res_goahead: + done = 1; + break; + case res_nextns: + res_nclose(statp); + goto next_ns; + case res_done: + return (resplen); + case res_modified: + /* give the hook another try */ + if (++loops < 42) /*doug adams*/ + break; + /*FALLTHROUGH*/ + case res_error: + /*FALLTHROUGH*/ + default: + goto fail; + } + } while (!done); + } + + Dprint(((statp->options & RES_DEBUG) && + getnameinfo(nsap, nsaplen, abuf, sizeof(abuf), + NULL, 0, niflags) == 0), + (stdout, ";; Querying server (# %d) address = %s\n", + ns + 1, abuf)); + + + if (v_circuit) { + /* Use VC; at most one attempt per server. */ + tries = statp->retry; + n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, + ns); + if (n < 0) + goto fail; + if (n == 0) + goto next_ns; + resplen = n; + } else { + /* Use datagrams. */ + n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, + ns, tries, &v_circuit, &gotsomewhere); + if (n < 0) + goto fail; + if (n == 0) + goto next_ns; + if (v_circuit) + goto same_ns; + resplen = n; + } + + Dprint((statp->options & RES_DEBUG) || + ((statp->pfcode & RES_PRF_REPLY) && + (statp->pfcode & RES_PRF_HEAD1)), + (stdout, ";; got answer:\n")); + + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, "%s", ""), + ans, (resplen > anssiz) ? anssiz : resplen); + + /* + * If we have temporarily opened a virtual circuit, + * or if we haven't been asked to keep a socket open, + * close the socket. + */ + if ((v_circuit && (statp->options & RES_USEVC) == 0U) || + (statp->options & RES_STAYOPEN) == 0U) { + res_nclose(statp); + } + if (statp->rhook) { + int done = 0, loops = 0; + + do { + res_sendhookact act; + + act = (*statp->rhook)(nsap, buf, buflen, + ans, anssiz, &resplen); + switch (act) { + case res_goahead: + case res_done: + done = 1; + break; + case res_nextns: + res_nclose(statp); + goto next_ns; + case res_modified: + /* give the hook another try */ + if (++loops < 42) /*doug adams*/ + break; + /*FALLTHROUGH*/ + case res_error: + /*FALLTHROUGH*/ + default: + goto fail; + } + } while (!done); + + } + return (resplen); + next_ns: ; + } /*foreach ns*/ + } /*foreach retry*/ + res_nclose(statp); + if (!v_circuit) { + if (!gotsomewhere) + errno = ECONNREFUSED; /*%< no nameservers found */ + else + errno = ETIMEDOUT; /*%< no answer obtained */ + } else + errno = terrno; + return (-1); + fail: + res_nclose(statp); + return (-1); +} + +/* Private */ + +static int +get_salen(sa) + const struct sockaddr *sa; +{ + +#ifdef HAVE_SA_LEN + /* There are people do not set sa_len. Be forgiving to them. */ + if (sa->sa_len) + return (sa->sa_len); +#endif + + if (sa->sa_family == AF_INET) + return (sizeof(struct sockaddr_in)); + else if (sa->sa_family == AF_INET6) + return (sizeof(struct sockaddr_in6)); + else + return (0); /*%< unknown, die on connect */ +} + +/*% + * pick appropriate nsaddr_list for use. see res_init() for initialization. + */ +static struct sockaddr * +get_nsaddr(statp, n) + res_state statp; + size_t n; +{ + + if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { + /* + * - EXT(statp).ext->nsaddrs[n] holds an address that is larger + * than struct sockaddr, and + * - user code did not update statp->nsaddr_list[n]. + */ + return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; + } else { + /* + * - user code updated statp->nsaddr_list[n], or + * - statp->nsaddr_list[n] has the same content as + * EXT(statp).ext->nsaddrs[n]. + */ + return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; + } +} + +static int +send_vc(res_state statp, + const u_char *buf, int buflen, u_char *ans, int anssiz, + int *terrno, int ns) +{ + const HEADER *hp = (const HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + struct sockaddr *nsap; + int nsaplen; + int truncating, connreset, resplen, n; + struct iovec iov[2]; + u_short len; + u_char *cp; + void *tmp; +#ifdef SO_NOSIGPIPE + int on = 1; +#endif + + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); + + connreset = 0; + same_ns: + truncating = 0; + + /* Are we still talking to whom we want to talk to? */ + if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { + struct sockaddr_storage peer; + ISC_SOCKLEN_T size = sizeof peer; + + if (getpeername(statp->_vcsock, + (struct sockaddr *)&peer, &size) < 0 || + !sock_eq((struct sockaddr *)&peer, nsap)) { + res_nclose(statp); + statp->_flags &= ~RES_F_VC; + } + } + + if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { + if (statp->_vcsock >= 0) + res_nclose(statp); + + statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); + if (statp->_vcsock > highestFD) { + res_nclose(statp); + errno = ENOTSOCK; + } + if (statp->_vcsock < 0) { + switch (errno) { + case EPROTONOSUPPORT: +#ifdef EPFNOSUPPORT + case EPFNOSUPPORT: +#endif + case EAFNOSUPPORT: + Perror(statp, stderr, "socket(vc)", errno); + return (0); + default: + *terrno = errno; + Perror(statp, stderr, "socket(vc)", errno); + return (-1); + } + } +#ifdef SO_NOSIGPIPE + /* + * Disable generation of SIGPIPE when writing to a closed + * socket. Write should return -1 and set errno to EPIPE + * instead. + * + * Push on even if setsockopt(SO_NOSIGPIPE) fails. + */ + (void)setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on, + sizeof(on)); +#endif + errno = 0; + if (connect(statp->_vcsock, nsap, nsaplen) < 0) { + *terrno = errno; + Aerror(statp, stderr, "connect/vc", errno, nsap, + nsaplen); + res_nclose(statp); + return (0); + } + statp->_flags |= RES_F_VC; + } + + /* + * Send length & message + */ + ns_put16((u_short)buflen, (u_char*)&len); + iov[0] = evConsIovec(&len, INT16SZ); + DE_CONST(buf, tmp); + iov[1] = evConsIovec(tmp, buflen); + if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { + *terrno = errno; + Perror(statp, stderr, "write failed", errno); + res_nclose(statp); + return (0); + } + /* + * Receive length & response + */ + read_len: + cp = ans; + len = INT16SZ; + while ((n = read(statp->_vcsock, (char *)cp, (int)len)) > 0) { + cp += n; + if ((len -= n) == 0) + break; + } + if (n <= 0) { + *terrno = errno; + Perror(statp, stderr, "read failed", errno); + res_nclose(statp); + /* + * A long running process might get its TCP + * connection reset if the remote server was + * restarted. Requery the server instead of + * trying a new one. When there is only one + * server, this means that a query might work + * instead of failing. We only allow one reset + * per query to prevent looping. + */ + if (*terrno == ECONNRESET && !connreset) { + connreset = 1; + res_nclose(statp); + goto same_ns; + } + res_nclose(statp); + return (0); + } + resplen = ns_get16(ans); + if (resplen > anssiz) { + Dprint(statp->options & RES_DEBUG, + (stdout, ";; response truncated\n") + ); + truncating = 1; + len = anssiz; + } else + len = resplen; + if (len < HFIXEDSZ) { + /* + * Undersized message. + */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; undersized: %d\n", len)); + *terrno = EMSGSIZE; + res_nclose(statp); + return (0); + } + cp = ans; + while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){ + cp += n; + len -= n; + } + if (n <= 0) { + *terrno = errno; + Perror(statp, stderr, "read(vc)", errno); + res_nclose(statp); + return (0); + } + if (truncating) { + /* + * Flush rest of answer so connection stays in synch. + */ + anhp->tc = 1; + len = resplen - anssiz; + while (len != 0) { + char junk[PACKETSZ]; + + n = read(statp->_vcsock, junk, + (len > sizeof junk) ? sizeof junk : len); + if (n > 0) + len -= n; + else + break; + } + } + /* + * If the calling applicating has bailed out of + * a previous call and failed to arrange to have + * the circuit closed or the server has got + * itself confused, then drop the packet and + * wait for the correct one. + */ + if (hp->id != anhp->id) { + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; old answer (unexpected):\n"), + ans, (resplen > anssiz) ? anssiz: resplen); + goto read_len; + } + + /* + * All is well, or the error is fatal. Signal that the + * next nameserver ought not be tried. + */ + return (resplen); +} + +static int +send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans, + int anssiz, int *terrno, int ns, int tries, int *v_circuit, + int *gotsomewhere) +{ + const HEADER *hp = (const HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + const struct sockaddr *nsap; + int nsaplen; + struct timespec now, timeout, finish; + struct sockaddr_storage from; + ISC_SOCKLEN_T fromlen; + int resplen, seconds, n, s; +#ifdef USE_POLL + int polltimeout; + struct pollfd pollfd; +#else + fd_set dsmask; +#endif + + nsap = get_nsaddr(statp, ns); + nsaplen = get_salen(nsap); + if (EXT(statp).nssocks[ns] == -1) { + EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); + if (EXT(statp).nssocks[ns] > highestFD) { + res_nclose(statp); + errno = ENOTSOCK; + } + if (EXT(statp).nssocks[ns] < 0) { + switch (errno) { + case EPROTONOSUPPORT: +#ifdef EPFNOSUPPORT + case EPFNOSUPPORT: +#endif + case EAFNOSUPPORT: + Perror(statp, stderr, "socket(dg)", errno); + return (0); + default: + *terrno = errno; + Perror(statp, stderr, "socket(dg)", errno); + return (-1); + } + } +#ifndef CANNOT_CONNECT_DGRAM + /* + * On a 4.3BSD+ machine (client and server, + * actually), sending to a nameserver datagram + * port with no nameserver will cause an + * ICMP port unreachable message to be returned. + * If our datagram socket is "connected" to the + * server, we get an ECONNREFUSED error on the next + * socket operation, and select returns if the + * error message is received. We can thus detect + * the absence of a nameserver without timing out. + */ + if (connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) { + Aerror(statp, stderr, "connect(dg)", errno, nsap, + nsaplen); + res_nclose(statp); + return (0); + } +#endif /* !CANNOT_CONNECT_DGRAM */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; new DG socket\n")) + } + s = EXT(statp).nssocks[ns]; +#ifndef CANNOT_CONNECT_DGRAM + if (send(s, (const char*)buf, buflen, 0) != buflen) { + Perror(statp, stderr, "send", errno); + res_nclose(statp); + return (0); + } +#else /* !CANNOT_CONNECT_DGRAM */ + if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) + { + Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); + res_nclose(statp); + return (0); + } +#endif /* !CANNOT_CONNECT_DGRAM */ + + /* + * Wait for reply. + */ + seconds = (statp->retrans << tries); + if (ns > 0) + seconds /= statp->nscount; + if (seconds <= 0) + seconds = 1; + now = evNowTime(); + timeout = evConsTime(seconds, 0); + finish = evAddTime(now, timeout); + goto nonow; + wait: + now = evNowTime(); + nonow: +#ifndef USE_POLL + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); + if (evCmpTime(finish, now) > 0) + timeout = evSubTime(finish, now); + else + timeout = evConsTime(0, 0); + n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); +#else + timeout = evSubTime(finish, now); + if (timeout.tv_sec < 0) + timeout = evConsTime(0, 0); + polltimeout = 1000*timeout.tv_sec + + timeout.tv_nsec/1000000; + pollfd.fd = s; + pollfd.events = POLLRDNORM; + n = poll(&pollfd, 1, polltimeout); +#endif /* USE_POLL */ + + if (n == 0) { + Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); + *gotsomewhere = 1; + return (0); + } + if (n < 0) { + if (errno == EINTR) + goto wait; +#ifndef USE_POLL + Perror(statp, stderr, "select", errno); +#else + Perror(statp, stderr, "poll", errno); +#endif /* USE_POLL */ + res_nclose(statp); + return (0); + } + errno = 0; + fromlen = sizeof(from); + resplen = recvfrom(s, (char*)ans, anssiz,0, + (struct sockaddr *)&from, &fromlen); + if (resplen <= 0) { + Perror(statp, stderr, "recvfrom", errno); + res_nclose(statp); + return (0); + } + *gotsomewhere = 1; + if (resplen < HFIXEDSZ) { + /* + * Undersized message. + */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; undersized: %d\n", + resplen)); + *terrno = EMSGSIZE; + res_nclose(statp); + return (0); + } + if (hp->id != anhp->id) { + /* + * response from old query, ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; old answer:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + goto wait; + } + if (!(statp->options & RES_INSECURE1) && + !res_ourserver_p(statp, (struct sockaddr *)&from)) { + /* + * response from wrong server? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; not our server:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + goto wait; + } +#ifdef RES_USE_EDNS0 + if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) { + /* + * Do not retry if the server do not understand EDNS0. + * The case has to be captured here, as FORMERR packet do not + * carry query section, hence res_queriesmatch() returns 0. + */ + DprintQ(statp->options & RES_DEBUG, + (stdout, "server rejected query with EDNS0:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + /* record the error */ + statp->_flags |= RES_F_EDNS0ERR; + res_nclose(statp); + return (0); + } +#endif + if (!(statp->options & RES_INSECURE2) && + !res_queriesmatch(buf, buf + buflen, + ans, ans + anssiz)) { + /* + * response contains wrong query? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, ";; wrong query name:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + goto wait; + } + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || + anhp->rcode == REFUSED) { + DprintQ(statp->options & RES_DEBUG, + (stdout, "server rejected query:\n"), + ans, (resplen > anssiz) ? anssiz : resplen); + res_nclose(statp); + /* don't retry if called from dig */ + if (!statp->pfcode) + return (0); + } + if (!(statp->options & RES_IGNTC) && anhp->tc) { + /* + * To get the rest of answer, + * use TCP with same server. + */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; truncated answer\n")); + *v_circuit = 1; + res_nclose(statp); + return (1); + } + /* + * All is well, or the error is fatal. Signal that the + * next nameserver ought not be tried. + */ + return (resplen); +} + +static void +Aerror(const res_state statp, FILE *file, const char *string, int error, + const struct sockaddr *address, int alen) +{ + int save = errno; + char hbuf[NI_MAXHOST]; + char sbuf[NI_MAXSERV]; + + alen = alen; + + if ((statp->options & RES_DEBUG) != 0U) { + if (getnameinfo(address, alen, hbuf, sizeof(hbuf), + sbuf, sizeof(sbuf), niflags)) { + strncpy(hbuf, "?", sizeof(hbuf) - 1); + hbuf[sizeof(hbuf) - 1] = '\0'; + strncpy(sbuf, "?", sizeof(sbuf) - 1); + sbuf[sizeof(sbuf) - 1] = '\0'; + } + fprintf(file, "res_send: %s ([%s].%s): %s\n", + string, hbuf, sbuf, strerror(error)); + } + errno = save; +} + +static void +Perror(const res_state statp, FILE *file, const char *string, int error) { + int save = errno; + + if ((statp->options & RES_DEBUG) != 0U) + fprintf(file, "res_send: %s: %s\n", + string, strerror(error)); + errno = save; +} + +static int +sock_eq(struct sockaddr *a, struct sockaddr *b) { + struct sockaddr_in *a4, *b4; + struct sockaddr_in6 *a6, *b6; + + if (a->sa_family != b->sa_family) + return 0; + switch (a->sa_family) { + case AF_INET: + a4 = (struct sockaddr_in *)a; + b4 = (struct sockaddr_in *)b; + return a4->sin_port == b4->sin_port && + a4->sin_addr.s_addr == b4->sin_addr.s_addr; + case AF_INET6: + a6 = (struct sockaddr_in6 *)a; + b6 = (struct sockaddr_in6 *)b; + return a6->sin6_port == b6->sin6_port && +#ifdef HAVE_SIN6_SCOPE_ID + a6->sin6_scope_id == b6->sin6_scope_id && +#endif + IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); + default: + return 0; + } +} + +#if defined(NEED_PSELECT) && !defined(USE_POLL) +/* XXX needs to move to the porting library. */ +static int +pselect(int nfds, void *rfds, void *wfds, void *efds, + struct timespec *tsp, const sigset_t *sigmask) +{ + struct timeval tv, *tvp; + sigset_t sigs; + int n; + + if (tsp) { + tvp = &tv; + tv = evTimeVal(*tsp); + } else + tvp = NULL; + if (sigmask) + sigprocmask(SIG_SETMASK, sigmask, &sigs); + n = select(nfds, rfds, wfds, efds, tvp); + if (sigmask) + sigprocmask(SIG_SETMASK, &sigs, NULL); + if (tsp) + *tsp = evTimeSpec(tv); + return (n); +} +#endif diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_sendsigned.c b/usr/src/lib/libresolv2_joy/common/resolv/res_sendsigned.c new file mode 100644 index 0000000000..5ebc1a70eb --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_sendsigned.c @@ -0,0 +1,170 @@ +#include "port_before.h" +#include "fd_setsize.h" + +#include <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <isc/dst.h> + +#include <errno.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "port_after.h" + +#define DEBUG +#include "res_debug.h" + + +/*% res_nsendsigned */ +int +res_nsendsigned(res_state statp, const u_char *msg, int msglen, + ns_tsig_key *key, u_char *answer, int anslen) +{ + res_state nstatp; + DST_KEY *dstkey; + int usingTCP = 0; + u_char *newmsg; + int newmsglen, bufsize, siglen; + u_char sig[64]; + HEADER *hp; + time_t tsig_time; + int ret; + int len; + + dst_init(); + + nstatp = (res_state) malloc(sizeof(*statp)); + if (nstatp == NULL) { + errno = ENOMEM; + return (-1); + } + memcpy(nstatp, statp, sizeof(*statp)); + + bufsize = msglen + 1024; + newmsg = (u_char *) malloc(bufsize); + if (newmsg == NULL) { + free(nstatp); + errno = ENOMEM; + return (-1); + } + memcpy(newmsg, msg, msglen); + newmsglen = msglen; + + if (ns_samename(key->alg, NS_TSIG_ALG_HMAC_MD5) != 1) + dstkey = NULL; + else + dstkey = dst_buffer_to_key(key->name, KEY_HMAC_MD5, + NS_KEY_TYPE_AUTH_ONLY, + NS_KEY_PROT_ANY, + key->data, key->len); + if (dstkey == NULL) { + errno = EINVAL; + free(nstatp); + free(newmsg); + return (-1); + } + + nstatp->nscount = 1; + siglen = sizeof(sig); + ret = ns_sign(newmsg, &newmsglen, bufsize, NOERROR, dstkey, NULL, 0, + sig, &siglen, 0); + if (ret < 0) { + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + if (ret == NS_TSIG_ERROR_NO_SPACE) + errno = EMSGSIZE; + else if (ret == -1) + errno = EINVAL; + return (ret); + } + + if (newmsglen > PACKETSZ || nstatp->options & RES_USEVC) + usingTCP = 1; + if (usingTCP == 0) + nstatp->options |= RES_IGNTC; + else + nstatp->options |= RES_USEVC; + /* + * Stop res_send printing the answer. + */ + nstatp->options &= ~RES_DEBUG; + nstatp->pfcode &= ~RES_PRF_REPLY; + +retry: + + len = res_nsend(nstatp, newmsg, newmsglen, answer, anslen); + if (len < 0) { + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + return (len); + } + + ret = ns_verify(answer, &len, dstkey, sig, siglen, + NULL, NULL, &tsig_time, nstatp->options & RES_KEEPTSIG); + if (ret != 0) { + Dprint((statp->options & RES_DEBUG) || + ((statp->pfcode & RES_PRF_REPLY) && + (statp->pfcode & RES_PRF_HEAD1)), + (stdout, ";; got answer:\n")); + + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, "%s", ""), + answer, (anslen > len) ? len : anslen); + + if (ret > 0) { + Dprint(statp->pfcode & RES_PRF_REPLY, + (stdout, ";; server rejected TSIG (%s)\n", + p_rcode(ret))); + } else { + Dprint(statp->pfcode & RES_PRF_REPLY, + (stdout, ";; TSIG invalid (%s)\n", + p_rcode(-ret))); + } + + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + if (ret == -1) + errno = EINVAL; + else + errno = ENOTTY; + return (-1); + } + + hp = (HEADER *) answer; + if (hp->tc && !usingTCP && (statp->options & RES_IGNTC) == 0U) { + nstatp->options &= ~RES_IGNTC; + usingTCP = 1; + goto retry; + } + Dprint((statp->options & RES_DEBUG) || + ((statp->pfcode & RES_PRF_REPLY) && + (statp->pfcode & RES_PRF_HEAD1)), + (stdout, ";; got answer:\n")); + + DprintQ((statp->options & RES_DEBUG) || + (statp->pfcode & RES_PRF_REPLY), + (stdout, "%s", ""), + answer, (anslen > len) ? len : anslen); + + Dprint(statp->pfcode & RES_PRF_REPLY, (stdout, ";; TSIG ok\n")); + + free (nstatp); + free (newmsg); + dst_free_key(dstkey); + return (len); +} + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/common/resolv/res_update.c b/usr/src/lib/libresolv2_joy/common/resolv/res_update.c new file mode 100644 index 0000000000..df24aee3bd --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/resolv/res_update.c @@ -0,0 +1,213 @@ +#if !defined(lint) && !defined(SABER) +static const char rcsid[] = "$Id: res_update.c,v 1.13 2005/04/27 04:56:43 sra Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*! \file + * \brief + * Based on the Dynamic DNS reference implementation by Viraj Bais + * <viraj_bais@ccm.fm.intel.com> + */ + +#include "port_before.h" + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <res_update.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <isc/list.h> +#include <resolv_joy.h> + +#include "port_after.h" +#include "res_private.h" + +/*% + * Separate a linked list of records into groups so that all records + * in a group will belong to a single zone on the nameserver. + * Create a dynamic update packet for each zone and send it to the + * nameservers for that zone, and await answer. + * Abort if error occurs in updating any zone. + * Return the number of zones updated on success, < 0 on error. + * + * On error, caller must deal with the unsynchronized zones + * eg. an A record might have been successfully added to the forward + * zone but the corresponding PTR record would be missing if error + * was encountered while updating the reverse zone. + */ + +struct zonegrp { + char z_origin[MAXDNAME]; + ns_class z_class; + union res_sockaddr_union z_nsaddrs[MAXNS]; + int z_nscount; + int z_flags; + LIST(ns_updrec) z_rrlist; + LINK(struct zonegrp) z_link; +}; + +#define ZG_F_ZONESECTADDED 0x0001 + +/* Forward. */ + +static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2); + +/* Macros. */ + +#define DPRINTF(x) do {\ + int save_errno = errno; \ + if ((statp->options & RES_DEBUG) != 0U) res_dprintf x; \ + errno = save_errno; \ + } while (0) + +/* Public. */ + +int +res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { + ns_updrec *rrecp; + u_char answer[PACKETSZ]; + u_char *packet; + struct zonegrp *zptr, tgrp; + LIST(struct zonegrp) zgrps; + int nzones = 0, nscount = 0, n; + union res_sockaddr_union nsaddrs[MAXNS]; + + packet = malloc(NS_MAXMSG); + if (packet == NULL) { + DPRINTF(("malloc failed")); + return (0); + } + /* Thread all of the updates onto a list of groups. */ + INIT_LIST(zgrps); + memset(&tgrp, 0, sizeof (tgrp)); + for (rrecp = rrecp_in; rrecp; + rrecp = LINKED(rrecp, r_link) ? NEXT(rrecp, r_link) : NULL) { + int nscnt; + /* Find the origin for it if there is one. */ + tgrp.z_class = rrecp->r_class; + nscnt = res_findzonecut2(statp, rrecp->r_dname, tgrp.z_class, + RES_EXHAUSTIVE, tgrp.z_origin, + sizeof tgrp.z_origin, + tgrp.z_nsaddrs, MAXNS); + if (nscnt <= 0) { + DPRINTF(("res_findzonecut failed (%d)", nscnt)); + goto done; + } + tgrp.z_nscount = nscnt; + /* Find the group for it if there is one. */ + for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link)) + if (ns_samename(tgrp.z_origin, zptr->z_origin) == 1 && + tgrp.z_class == zptr->z_class) + break; + /* Make a group for it if there isn't one. */ + if (zptr == NULL) { + zptr = malloc(sizeof *zptr); + if (zptr == NULL) { + DPRINTF(("malloc failed")); + goto done; + } + *zptr = tgrp; + zptr->z_flags = 0; + INIT_LINK(zptr, z_link); + INIT_LIST(zptr->z_rrlist); + APPEND(zgrps, zptr, z_link); + } + /* Thread this rrecp onto the right group. */ + APPEND(zptr->z_rrlist, rrecp, r_glink); + } + + for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link)) { + /* Construct zone section and prepend it. */ + rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin, + zptr->z_class, ns_t_soa, 0); + if (rrecp == NULL) { + DPRINTF(("res_mkupdrec failed")); + goto done; + } + PREPEND(zptr->z_rrlist, rrecp, r_glink); + zptr->z_flags |= ZG_F_ZONESECTADDED; + + /* Marshall the update message. */ + n = res_nmkupdate(statp, HEAD(zptr->z_rrlist), + packet, NS_MAXMSG); + DPRINTF(("res_mkupdate -> %d", n)); + if (n < 0) + goto done; + + /* Temporarily replace the resolver's nameserver set. */ + nscount = res_getservers(statp, nsaddrs, MAXNS); + res_setservers(statp, zptr->z_nsaddrs, zptr->z_nscount); + + /* Send the update and remember the result. */ + if (key != NULL) + n = res_nsendsigned(statp, packet, n, key, + answer, sizeof answer); + else + n = res_nsend(statp, packet, n, answer, sizeof answer); + if (n < 0) { + DPRINTF(("res_nsend: send error, n=%d (%s)\n", + n, strerror(errno))); + goto done; + } + if (((HEADER *)answer)->rcode == NOERROR) + nzones++; + + /* Restore resolver's nameserver set. */ + res_setservers(statp, nsaddrs, nscount); + nscount = 0; + } + done: + while (!EMPTY(zgrps)) { + zptr = HEAD(zgrps); + if ((zptr->z_flags & ZG_F_ZONESECTADDED) != 0) + res_freeupdrec(HEAD(zptr->z_rrlist)); + UNLINK(zgrps, zptr, z_link); + free(zptr); + } + if (nscount != 0) + res_setservers(statp, nsaddrs, nscount); + + free(packet); + return (nzones); +} + +/* Private. */ + +static void +res_dprintf(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + fputs(";; res_nupdate: ", stderr); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +} diff --git a/usr/src/lib/libresolv2_joy/common/sunw/sunw_mtctxres.c b/usr/src/lib/libresolv2_joy/common/sunw/sunw_mtctxres.c new file mode 100644 index 0000000000..cc2a485ede --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/sunw/sunw_mtctxres.c @@ -0,0 +1,126 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <port_before.h> +#include <thread.h> +#include <errno.h> +#include <netdb.h> +#include <malloc.h> +#include <string.h> +#include <resolv_mt.h> +#include <irs.h> +#include <port_after.h> + +#pragma redefine_extname __h_errno __joy_h_errno + +/* + * much of the original version of sunw_mtxtxres.c was incorporated into + * ISC libbind as resolv/mtctxres.c. The following bits have not yet made + * it into ISC libbind. + */ + +/* + * There used to be a private, MT-safe resolver interface that used TSD + * to store per-thread _res, h_errno, etc. We continue to provide the + * access functions __res_get_res() and __res_get_h_errno() so that binaries + * that used the private interface will continue to work. + */ + +#ifdef _res +#undef _res +#endif + +extern struct __res_state *__res_state(void); + +struct __res_state * +__res_get_res(void) { + return (__res_state()); +} + + +#ifdef h_errno +#undef h_errno +#endif + +extern int *__h_errno(void); + +int * +__res_get_h_errno(void) { + return (__h_errno()); +} + + +#ifdef SUNW_HOSTS_FALLBACK + +/* + * When the name service switch calls libresolv, it doesn't want fallback + * to /etc/hosts, so we provide a method to turn it off. + */ + +void +__joy_res_set_no_hosts_fallback(void) { + ___mtctxres()->no_hosts_fallback_private = 1; +} + +void +__joy_res_unset_no_hosts_fallback(void) { + ___mtctxres()->no_hosts_fallback_private = 0; +} + +int +__res_no_hosts_fallback(void) { + return (___mtctxres()->no_hosts_fallback_private); +} + +#endif /* SUNW_HOSTS_FALLBACK */ + +#ifdef SUNW_OVERRIDE_RETRY + +/* + * The NS switch wants to be able to override the number of retries. + */ + +int +__joy_res_override_retry(int retry) { + ___mtctxres()->retry_private = retry; + /* + * This function doesn't really need a return value; saving the + * old retry setting, and restoring it, is handled by __res_retry() + * and __res_retry_reset() below. However, the nss_dns library + * must have a private version of this function to be used when + * running with an old libresolv. That private nss_dns function + * needs a return value, and a function pointer is used to select + * the right function at runtime. Thus, __res_override_retry + * must have a function prototype consistent with the private + * nss_dns function, i.e., one that returns an int. + * + * Given that we do have a return value, that value must be zero. + * That's because retry_private == 0 is used to indicate that + * no override retry value is in effect, and the way we expect + * nss_dns to call us is: + * + * int oldretry = __res_override_retry(N); + * <whatever> + * (void)__res_override_retry(old_retry); + */ + return (0); +} + +int +__res_retry(int retry) { + mtctxres_t *mt = ___mtctxres(); + + mt->retry_save = retry; + return ((mt->retry_private != 0) ? mt->retry_private : retry); +} + +int +__res_retry_reset(void) { + mtctxres_t *mt = ___mtctxres(); + + return (mt->retry_save); +} + +#endif /* SUNW_OVERRIDE_RETRY */ diff --git a/usr/src/lib/libresolv2_joy/common/sunw/sunw_updrec.c b/usr/src/lib/libresolv2_joy/common/sunw/sunw_updrec.c new file mode 100644 index 0000000000..3b0ffc49df --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/sunw/sunw_updrec.c @@ -0,0 +1,249 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * As of BIND 8.2.2, ISC (a) removed res_mkupdate(), res_update(), and + * res_mkupdrec() from what they consider the supported interface. The + * functions still exist, but their calling interface has changed, since + * the ns_updrec structure has changed. + * + * It seems probable that res_mkupdate() etc. will return, though possibly + * with other changes, in some future BIND release. In order to avoid + * going to PSARC twice (once to remove the functions, and then again to + * add them back), we retain the old interface as a wrapper around the + * new one. + */ + +#include <port_before.h> + +#include <malloc.h> +#include <strings.h> +#include <sys/types.h> +#include <netinet/in.h> + +/* get the Solaris ns_updrec before any renaming happens */ +#include <arpa/nameser.h> + +/* get the __ISC_ns_updrec */ +#include <res_update.h> + +#include <port_after.h> + +/* un-rename ns_updrec and res_* functions so we can wrap them */ +#undef ns_updrec +#undef res_mkupdate +#undef res_update +#undef res_mkupdrec +#undef res_freeupdrec +#undef res_nmkupdate +#undef res_nupdate + +void res_freeupdrec(ns_updrec *); + +static int +old2new(ns_updrec *old, __ISC_ns_updrec *new) { + + if (old->r_dname != 0) { + if ((new->r_dname = strdup(old->r_dname)) == 0) + return (-1); + } else { + new->r_dname = 0; + } + + new->r_glink.prev = + new->r_glink.next = + new->r_link.prev = + new->r_link.next = 0; + + new->r_section = old->r_section; + new->r_class = old->r_class; + new->r_type = old->r_type; + new->r_ttl = old->r_ttl; + new->r_data = old->r_data; + new->r_size = old->r_size; + new->r_opcode = old->r_opcode; + new->r_dp = old->r_dp; + new->r_deldp = old->r_deldp; + new->r_zone = old->r_zone; + + return (0); +} + + +static int +new2old(__ISC_ns_updrec *new, ns_updrec *old) { + /* XXX r_prev and r_next unchanged */ + if (new->r_dname != 0) { + if ((old->r_dname = strdup(new->r_dname)) == 0) + return (-1); + } else { + old->r_dname = 0; + } + old->r_section = new->r_section; + old->r_class = new->r_class; + old->r_type = new->r_type; + old->r_ttl = new->r_ttl; + old->r_data = new->r_data; + old->r_size = new->r_size; + old->r_opcode = new->r_opcode; + old->r_grpnext = 0; /* XXX */ + old->r_dp = new->r_dp; + old->r_deldp = new->r_deldp; + old->r_zone = new->r_zone; + + return (0); +} + + +static void +delete_list(__ISC_ns_updrec *list) { + + __ISC_ns_updrec *next; + + for (; list != 0; list = next) { + next = list->r_link.next; + __ISC_res_freeupdrec(list); + } +} + + +static __ISC_ns_updrec * +copy_list(ns_updrec *old, int do_glink) { + + __ISC_ns_updrec *list = 0, *r, *p; + + if (old == 0) + return (0); + + for (p = 0; old != 0; old = old->r_next, p = r) { + if ((r = calloc(1, sizeof (*r))) == 0 || + old2new(old, r) != 0) { + free(r); + delete_list(list); + return (0); + } + r->r_link.prev = p; + r->r_link.next = 0; + /* res_update and res_nupdate want r_glink set up like this */ + if (do_glink) { + r->r_glink.prev = p; + r->r_glink.next = 0; + } else { + r->r_glink.prev = (void *)-1; + r->r_glink.next = (void *)-1; + } + if (p != 0) { + p->r_link.next = r; + if (do_glink) { + p->r_glink.next = r; + } + } else { + list = r; + } + } + return (list); +} + + +int +res_mkupdate(ns_updrec *rrecp_in, uchar_t *buf, int length) { + + __ISC_ns_updrec *r; + int ret; + + if ((r = copy_list(rrecp_in, 1)) == 0) + return (-1); + + ret = __ISC_res_mkupdate(r, buf, length); + + delete_list(r); + + return (ret); +} + +int +res_nmkupdate(res_state statp, ns_updrec *rrecp_in, uchar_t *buf, int length) { + + __ISC_ns_updrec *r; + int ret; + + if ((r = copy_list(rrecp_in, 1)) == 0) + return (-1); + + ret = __ISC_res_nmkupdate(statp, r, buf, length); + + delete_list(r); + + return (ret); +} + + +int +res_update(ns_updrec *rrecp_in) { + + __ISC_ns_updrec *r; + int ret; + + if ((r = copy_list(rrecp_in, 0)) == 0) + return (-1); + + ret = __ISC_res_update(r); + + delete_list(r); + + return (ret); +} + +int +res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) { + + __ISC_ns_updrec *r; + int ret; + + if ((r = copy_list(rrecp_in, 0)) == 0) + return (-1); + + ret = __ISC_res_nupdate(statp, r, key); + + delete_list(r); + + return (ret); +} + + + +ns_updrec * +res_mkupdrec(int section, const char *dname, uint_t class, uint_t type, + uint_t ttl) { + + __ISC_ns_updrec *n; + ns_updrec *o; + + n = __ISC_res_mkupdrec(section, dname, class, type, ttl); + if (n == 0) + return (0); + + if ((o = calloc(1, sizeof (*o))) != 0) { + if (new2old(n, o) != 0) { + res_freeupdrec(o); + o = 0; + } + } + + __ISC_res_freeupdrec(n); + + return (o); +} + + +void +res_freeupdrec(ns_updrec *rrecp) { + if (rrecp == 0) + return; + /* Note: freeing r_dp is the caller's responsibility. */ + if (rrecp->r_dname != NULL) + free(rrecp->r_dname); + free(rrecp); +} diff --git a/usr/src/lib/libresolv2_joy/common/sunw/sunw_wrappers.c b/usr/src/lib/libresolv2_joy/common/sunw/sunw_wrappers.c new file mode 100644 index 0000000000..55bbe07024 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/common/sunw/sunw_wrappers.c @@ -0,0 +1,23 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <port_before.h> +#include <resolv_joy.h> +#include <arpa/inet.h> +#include <port_after.h> + +#undef p_option +/* extern const char * isc_p_option(); */ +const char *p_option(uint_t option) { + return (isc_p_option((ulong_t)option)); +} +#pragma weak __p_option = p_option + +#undef p_secstodate +/* extern char * isc_p_secstodate (); */ +char *p_secstodate(uint_t secs) { + return (isc_p_secstodate((ulong_t)secs)); +} +#pragma weak __p_secstodate = p_secstodate diff --git a/usr/src/lib/print/libhttp-core/sparc/Makefile b/usr/src/lib/libresolv2_joy/i386/Makefile index 0bc3313291..a333224278 100644 --- a/usr/src/lib/print/libhttp-core/sparc/Makefile +++ b/usr/src/lib/libresolv2_joy/i386/Makefile @@ -27,4 +27,4 @@ include ../Makefile.com -install: all $(ROOTLIBDIR) $(ROOTLIBS) $(ROOTLINKS) +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/print/libipp-core/Makefile b/usr/src/lib/libresolv2_joy/include/Makefile index b92d620b10..8bff3c3188 100644 --- a/usr/src/lib/print/libipp-core/Makefile +++ b/usr/src/lib/libresolv2_joy/include/Makefile @@ -18,6 +18,7 @@ # # CDDL HEADER END # + # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. @@ -25,32 +26,35 @@ # ident "%Z%%M% %I% %E% SMI" # -include ../../Makefile.lib +include ../../../Makefile.master -#HDRS = papi.h -#HDRDIR = common -SUBDIRS = $(MACH) -#$(BUILD64)SUBDIRS += $(MACH64) +HDRS= os_version.h port_ipv6.h +TMPHDRS= new_os_version.h new_port_ipv6.h -all := TARGET = all -clean := TARGET = clean -clobber := TARGET = clobber -install := TARGET = install -lint := TARGET = lint +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install .KEEP_STATE: -all clean clobber install: .WAIT $(SUBDIRS) +all lint: $(HDRS) -lint: # $(SUBDIRS) +install: all -install_h: # $(ROOTHDRS) +clean: + $(RM) $(HDRS) $(TMPHDRS) -check: # $(CHECKHDRS) +clobber: clean -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) +# os_version.h and port_ipv6.h should be rebuilt when you change OS +# revision. Since that's not easily expressed as a dependency, we +# rebuild them every time. -FRC: +os_version.h: make_os_version FRC + ./make_os_version -include ../../Makefile.targ +port_ipv6.h: probe_ipv6 FRC + CC="$(CC)" ./probe_ipv6 + +FRC: diff --git a/usr/src/lib/libresolv2_joy/include/arpa/port_inet.h b/usr/src/lib/libresolv2_joy/include/arpa/port_inet.h new file mode 100644 index 0000000000..5eb1787f56 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/arpa/port_inet.h @@ -0,0 +1,41 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * + * All rights reserved. + */ + +#ifndef _ARPA_PORT_INET_H +#define _ARPA_PORT_INET_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * these are libresolv2 functions that were made local in previous versions + * we rename them res_* because they conflict with libnsl or libsocket + */ + +#define inet_lnaof res_inet_lnaof /* libsocket */ +ulong_t inet_lnaof(struct in_addr in); + +#define inet_makeaddr res_inet_makeaddr /* libsocket */ +struct in_addr inet_makeaddr(ulong_t net, ulong_t host); + +#define inet_netof res_inet_netof /* libnsl */ +ulong_t inet_netof(struct in_addr in); + +#define inet_network res_inet_network /* libsocket */ +ulong_t inet_network(register const char *cp); + +#ifdef __cplusplus +} +#endif + + + +#endif /* _ARPA_PORT_INET_H */ diff --git a/usr/src/lib/libresolv2_joy/include/arpa/port_nameser.h b/usr/src/lib/libresolv2_joy/include/arpa/port_nameser.h new file mode 100644 index 0000000000..b40ea0d163 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/arpa/port_nameser.h @@ -0,0 +1,40 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _ARPA_PORT_NAMESER_H +#define _ARPA_PORT_NAMESER_H + +/* + * ISC changed the ns_updrec structure. However, it's a public interface + * in Solaris, so we rename it here and wrap in sunw_updrec.c + */ +#define ns_updrec __ISC_ns_updrec + + +/* + * Due to the above, the following functions need to be renamed and + * wrapped in sunw_updrec.c. + * + * For BIND 8.2.2, ISC removed the dynamic update functions, and the + * definition of the ns_updrec structure, from the public include files + * (<resolv.h>, <arpa/nameser.h>. However, res_update(), res_mkupdate(), + * and res_mkupdrec() are in the public libresolv interface in Solaris, + * so we can't easily remove them. Thus, ISC's new versions of res_mkupdate() + * etc. can't be exposed under their original names. + * + * res_nmkupdate() and res_nupdate are new. We could either change them + * to accept the <arpa/nameser.h> ns_updrec, or leave them unchanged and + * undocumented. Since ISC may change ns_updrec again, we pick the latter + * solution for now. + */ +#define res_mkupdate __ISC_res_mkupdate +#define res_update __ISC_res_update +#define res_mkupdrec __ISC_res_mkupdrec +#define res_freeupdrec __ISC_res_freeupdrec +#define res_nmkupdate __ISC_res_nmkupdate +#define res_nupdate __ISC_res_nupdate + + +#endif /* _ARPA_PORT_NAMESER_H */ diff --git a/usr/src/lib/libresolv2_joy/include/conf/sunoptions.h b/usr/src/lib/libresolv2_joy/include/conf/sunoptions.h new file mode 100644 index 0000000000..b75ff9d878 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/conf/sunoptions.h @@ -0,0 +1,30 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SUNOPTIONS_H +#define _SUNOPTIONS_H + +#define USELOOPBACK /* Resolver library defaults to 127.0.0.1 */ + +/* Additions for Solaris 2 */ + +#define SUNW_INITCHKIF /* Check if any non-loopback interface is up */ +#define SUNW_CONFCHECK /* Abort quickly if no /etc/resolv.conf or */ + /* local named */ +#define SUNW_HOSTS_FALLBACK /* Configurable /etc/hosts fallback */ +#define SUNW_HNOK_UNDERSCORE /* Allow underscore in hostnames (libresolv) */ +#define SUNW_MT_RESOLVER /* MT hot extensions (libresolv) */ +#define SUNW_SETHERRNO /* ISC does not set h_errno in gethostbyname */ +#define SUNW_OVERRIDE_RETRY /* Allow NS switch to override res->retry */ +#define SUNW_LIBMD5 /* Use md5(3EXT) instead of internal implementation */ + +/* If compiling an MT warm libresolv, we also need reentrancy */ +#if defined(SUNW_MT_RESOLVER) && !defined(_REENTRANT) +#define _REENTRANT +#endif + +/* End additions for Solaris 2 */ + +#endif /* _SUNOPTIONS_H */ diff --git a/usr/src/lib/libresolv2_joy/include/config.h b/usr/src/lib/libresolv2_joy/include/config.h new file mode 100644 index 0000000000..35fb115a0f --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/config.h @@ -0,0 +1,75 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* config.h. Generated from config.h.in by configure. */ +/* #undef _SOCKADDR_LEN */ +#define HAVE_FCNTL_H 1 +/* #undef HAVE_PATHS_H */ +#define HAVE_INTTYPES_H 1 +#define HAVE_STROPTS_H 1 +/* #undef HAVE_SYS_TIMERS_H */ +#define HAVE_SYS_SELECT_H 1 +#define HAVE_MEMORY_H 1 +/* #undef SYS_CDEFS_H */ +#define _POSIX_PTHREAD_SEMANTICS 1 +#define POSIX_GETPWUID_R 1 +#define POSIX_GETPWNAM_R 1 +#define POSIX_GETGRGID_R 1 +#define POSIX_GETGRNAM_R 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCHR 1 +/* #undef SPRINTF_CHAR */ +/* #undef VSPRINTF_CHAR */ +#define USE_SYSERROR_LIST 1 +/* #undef NEED_STRTOUL */ +/* #undef NEED_SUN4PROTOS */ +/* #undef REENABLE_SEND */ + +#define NEED_SETGROUPENT 1 +#define NEED_GETGROUPLIST 1 + +/* define if prototype for getgrnam_r() is required */ +/* #undef NEED_GETGRNAM_R */ +/* #undef NEED_GETGRGID_R */ +/* #undef NEED_GETGRENT_R */ +#define NEED_SETGRENT_R 1 +#define NEED_ENDGRENT_R 1 + +#define NEED_INNETGR_R 1 +/* #undef NEED_SETNETGRENT_R */ +#define NEED_ENDNETGRENT_R 1 + +/* #undef NEED_GETPWNAM_R */ +/* #undef NEED_GETPWUID_R */ +#define NEED_SETPWENT_R 1 +#define NEED_SETPASSENT_R 1 +#define NEED_SETPWENT_R 1 +/* #undef NEED_GETPWENT_R */ +#define NEED_ENDPWENT_R 1 + +#define NEED_SETPASSENT 1 + +/* #undef HAS_PW_CLASS */ + +/* #undef ssize_t */ +/* #undef uintptr_t */ + +/* Shut up warnings about sputaux in stdio.h on BSD/OS pre-4.1 */ +/* #undef SHUTUP_SPUTAUX */ +#ifdef SHUTUP_SPUTAUX +struct __sFILE; +extern __inline int __sputaux(int _c, struct __sFILE *_p); +#endif +#define BROKEN_IN6ADDR_INIT_MACROS 1 +#define HAVE_STRLCAT 1 +/* Shut up warnings about missing braces */ +/* #undef SHUTUP_MUTEX_INITIALIZER */ +#ifdef SHUTUP_MUTEX_INITIALIZER +#define LIBBIND_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } +#else +#define LIBBIND_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#endif + diff --git a/usr/src/lib/libresolv2_joy/include/err.h b/usr/src/lib/libresolv2_joy/include/err.h new file mode 100644 index 0000000000..45992ea336 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/err.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/*- + * Copyright (c) 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. + * + * @(#)err.h 8.1 (Berkeley) 6/2/93 + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifndef _ERR_H_ +#define _ERR_H_ + +#include <sys/cdefs.h> +#include <stdarg.h> + +__BEGIN_DECLS +__dead void err __P((int, const char *, ...)) __attribute__((__volatile)); +__dead void verr __P((int, const char *, va_list)) + __attribute__((__volatile)); +__dead void errx __P((int, const char *, ...)) __attribute__((__volatile)); +__dead void verrx __P((int, const char *, va_list)) + __attribute__((__volatile)); +void warn __P((const char *, ...)); +void vwarn __P((const char *, va_list)); +void warnx __P((const char *, ...)); +void vwarnx __P((const char *, va_list)); +__END_DECLS + +#endif /* !_ERR_H_ */ diff --git a/usr/src/lib/libresolv2_joy/include/fd_setsize.h b/usr/src/lib/libresolv2_joy/include/fd_setsize.h new file mode 100644 index 0000000000..0e21049742 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/fd_setsize.h @@ -0,0 +1,10 @@ +#ifndef _FD_SETSIZE_H +#define _FD_SETSIZE_H + +/*% + * If you need a bigger FD_SETSIZE, this is NOT the place to set it. + * This file is a fallback for BIND ports which don't specify their own. + */ + +#endif /* _FD_SETSIZE_H */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/hesiod.h b/usr/src/lib/libresolv2_joy/include/hesiod.h new file mode 100644 index 0000000000..d64c0c5e80 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/hesiod.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/*! \file + * \brief + * This file is primarily maintained by <tytso@mit.edu> and <ghudson@mit.edu>. + */ + +/* + * $Id: hesiod.h,v 1.4 2005/04/27 04:56:14 sra Exp $ + */ + +#ifndef _HESIOD_H_INCLUDED +#define _HESIOD_H_INCLUDED + +int hesiod_init __P((void **)); +void hesiod_end __P((void *)); +char * hesiod_to_bind __P((void *, const char *, const char *)); +char ** hesiod_resolve __P((void *, const char *, const char *)); +void hesiod_free_list __P((void *, char **)); +struct __res_state * __hesiod_res_get __P((void *)); +void __hesiod_res_set __P((void *, struct __res_state *, + void (*)(void *))); + +#endif /*_HESIOD_H_INCLUDED*/ diff --git a/usr/src/lib/libresolv2_joy/include/irp.h b/usr/src/lib/libresolv2_joy/include/irp.h new file mode 100644 index 0000000000..1290bd068f --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/irp.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: irp.h,v 1.4 2005/04/27 04:56:15 sra Exp $ + */ + +#ifndef _IRP_H_INCLUDED +#define _IRP_H_INCLUDED + +/*! \file */ + +#define IRPD_TIMEOUT 30 /*%< seconds */ +#define IRPD_MAXSESS 50 /*%< number of simultaneous sessions. */ +#define IRPD_PORT 6660 /*%< 10 times the number of the beast. */ +#define IRPD_PATH "/var/run/irpd" /*%< af_unix socket path */ + +/* If sets the environment variable IRPDSERVER to an IP address + (e.g. "192.5.5.1"), then that's the host the client expects irpd to be + running on. */ +#define IRPD_HOST_ENV "IRPDSERVER" + +/* Protocol response codes. */ +#define IRPD_WELCOME_CODE 200 +#define IRPD_NOT_WELCOME_CODE 500 + +#define IRPD_GETHOST_ERROR 510 +#define IRPD_GETHOST_NONE 210 +#define IRPD_GETHOST_OK 211 +#define IRPD_GETHOST_SETOK 212 + +#define IRPD_GETNET_ERROR 520 +#define IRPD_GETNET_NONE 220 +#define IRPD_GETNET_OK 221 +#define IRPD_GETNET_SETOK 222 + +#define IRPD_GETUSER_ERROR 530 +#define IRPD_GETUSER_NONE 230 +#define IRPD_GETUSER_OK 231 +#define IRPD_GETUSER_SETOK 232 + +#define IRPD_GETGROUP_ERROR 540 +#define IRPD_GETGROUP_NONE 240 +#define IRPD_GETGROUP_OK 241 +#define IRPD_GETGROUP_SETOK 242 + +#define IRPD_GETSERVICE_ERROR 550 +#define IRPD_GETSERVICE_NONE 250 +#define IRPD_GETSERVICE_OK 251 +#define IRPD_GETSERVICE_SETOK 252 + +#define IRPD_GETPROTO_ERROR 560 +#define IRPD_GETPROTO_NONE 260 +#define IRPD_GETPROTO_OK 261 +#define IRPD_GETPROTO_SETOK 262 + +#define IRPD_GETNETGR_ERROR 570 +#define IRPD_GETNETGR_NONE 270 +#define IRPD_GETNETGR_OK 271 +#define IRPD_GETNETGR_NOMORE 272 +#define IRPD_GETNETGR_MATCHES 273 +#define IRPD_GETNETGR_NOMATCH 274 +#define IRPD_GETNETGR_SETOK 275 +#define IRPD_GETNETGR_SETERR 276 + +#define irs_irp_read_body __irs_irp_read_body +#define irs_irp_read_response __irs_irp_read_response +#define irs_irp_disconnect __irs_irp_disconnect +#define irs_irp_connect __irs_irp_connect +#define irs_irp_connection_setup __irs_irp_connection_setup +#define irs_irp_send_command __irs_irp_send_command + +struct irp_p; + +char *irs_irp_read_body(struct irp_p *, size_t *); +int irs_irp_read_response(struct irp_p *, char *, size_t); +void irs_irp_disconnect(struct irp_p *); +int irs_irp_connect(struct irp_p *); +int irs_irp_is_connected(struct irp_p *); +int irs_irp_connection_setup(struct irp_p *, int *); +#ifdef __GNUC__ +int irs_irp_send_command(struct irp_p *, const char *, ...) + __attribute__((__format__(__printf__, 2, 3))); +#else +int irs_irp_send_command(struct irp_p *, const char *, ...); +#endif +int irs_irp_get_full_response(struct irp_p *, int *, char *, size_t, + char **, size_t *); +int irs_irp_read_line(struct irp_p *, char *, int); + +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/irs.h b/usr/src/lib/libresolv2_joy/include/irs.h new file mode 100644 index 0000000000..386e3cb3f6 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/irs.h @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: irs.h,v 1.5 2005/04/27 04:56:15 sra Exp $ + */ + +#ifndef _IRS_H_INCLUDED +#define _IRS_H_INCLUDED + +/*! \file */ + +#include <sys/types.h> + +#include <arpa/nameser.h> + +#include <grp.h> +#include <netdb.h> +#include <resolv_joy.h> +#include <pwd.h> + +/*% + * This is the group map class. + */ +struct irs_gr { + void * private; + void (*close) __P((struct irs_gr *)); + struct group * (*next) __P((struct irs_gr *)); + struct group * (*byname) __P((struct irs_gr *, const char *)); + struct group * (*bygid) __P((struct irs_gr *, gid_t)); + int (*list) __P((struct irs_gr *, const char *, + gid_t, gid_t *, int *)); + void (*rewind) __P((struct irs_gr *)); + void (*minimize) __P((struct irs_gr *)); + struct __res_state * (*res_get) __P((struct irs_gr *)); + void (*res_set) __P((struct irs_gr *, res_state, + void (*)(void *))); +}; + +/*% + * This is the password map class. + */ +struct irs_pw { + void * private; + void (*close) __P((struct irs_pw *)); + struct passwd * (*next) __P((struct irs_pw *)); + struct passwd * (*byname) __P((struct irs_pw *, const char *)); + struct passwd * (*byuid) __P((struct irs_pw *, uid_t)); + void (*rewind) __P((struct irs_pw *)); + void (*minimize) __P((struct irs_pw *)); + struct __res_state * (*res_get) __P((struct irs_pw *)); + void (*res_set) __P((struct irs_pw *, res_state, + void (*)(void *))); +}; + +/*% + * This is the service map class. + */ +struct irs_sv { + void * private; + void (*close) __P((struct irs_sv *)); + struct servent *(*byname) __P((struct irs_sv *, + const char *, const char *)); + struct servent *(*byport) __P((struct irs_sv *, int, const char *)); + struct servent *(*next) __P((struct irs_sv *)); + void (*rewind) __P((struct irs_sv *)); + void (*minimize) __P((struct irs_sv *)); + struct __res_state * (*res_get) __P((struct irs_sv *)); + void (*res_set) __P((struct irs_sv *, res_state, + void (*)(void *))); +}; + +/*% + * This is the protocols map class. + */ +struct irs_pr { + void * private; + void (*close) __P((struct irs_pr *)); + struct protoent *(*byname) __P((struct irs_pr *, const char *)); + struct protoent *(*bynumber) __P((struct irs_pr *, int)); + struct protoent *(*next) __P((struct irs_pr *)); + void (*rewind) __P((struct irs_pr *)); + void (*minimize) __P((struct irs_pr *)); + struct __res_state * (*res_get) __P((struct irs_pr *)); + void (*res_set) __P((struct irs_pr *, res_state, + void (*)(void *))); +}; + +/*% + * This is the hosts map class. + */ +struct irs_ho { + void * private; + void (*close) __P((struct irs_ho *)); + struct hostent *(*byname) __P((struct irs_ho *, const char *)); + struct hostent *(*byname2) __P((struct irs_ho *, const char *, int)); + struct hostent *(*byaddr) __P((struct irs_ho *, + const void *, int, int)); + struct hostent *(*next) __P((struct irs_ho *)); + void (*rewind) __P((struct irs_ho *)); + void (*minimize) __P((struct irs_ho *)); + struct __res_state * (*res_get) __P((struct irs_ho *)); + void (*res_set) __P((struct irs_ho *, res_state, + void (*)(void *))); + struct addrinfo *(*addrinfo) __P((struct irs_ho *, const char *, + const struct addrinfo *)); +}; + +/*% + * This is the networks map class. + */ +struct irs_nw { + void * private; + void (*close) __P((struct irs_nw *)); + struct nwent * (*byname) __P((struct irs_nw *, const char *, int)); + struct nwent * (*byaddr) __P((struct irs_nw *, void *, int, int)); + struct nwent * (*next) __P((struct irs_nw *)); + void (*rewind) __P((struct irs_nw *)); + void (*minimize) __P((struct irs_nw *)); + struct __res_state * (*res_get) __P((struct irs_nw *)); + void (*res_set) __P((struct irs_nw *, res_state, + void (*)(void *))); +}; + +/*% + * This is the netgroups map class. + */ +struct irs_ng { + void * private; + void (*close) __P((struct irs_ng *)); + int (*next) __P((struct irs_ng *, const char **, + const char **, const char **)); + int (*test) __P((struct irs_ng *, const char *, + const char *, const char *, + const char *)); + void (*rewind) __P((struct irs_ng *, const char *)); + void (*minimize) __P((struct irs_ng *)); +}; + +/*% + * This is the generic map class, which copies the front of all others. + */ +struct irs_map { + void * private; + void (*close) __P((void *)); +}; + +/*% + * This is the accessor class. It contains pointers to all of the + * initializers for the map classes for a particular accessor. + */ +struct irs_acc { + void * private; + void (*close) __P((struct irs_acc *)); + struct irs_gr * (*gr_map) __P((struct irs_acc *)); + struct irs_pw * (*pw_map) __P((struct irs_acc *)); + struct irs_sv * (*sv_map) __P((struct irs_acc *)); + struct irs_pr * (*pr_map) __P((struct irs_acc *)); + struct irs_ho * (*ho_map) __P((struct irs_acc *)); + struct irs_nw * (*nw_map) __P((struct irs_acc *)); + struct irs_ng * (*ng_map) __P((struct irs_acc *)); + struct __res_state * (*res_get) __P((struct irs_acc *)); + void (*res_set) __P((struct irs_acc *, res_state, + void (*)(void *))); +}; + +/*% + * This is because the official definition of "struct netent" has no + * concept of CIDR even though it allows variant address families (on + * output but not input). The compatibility stubs convert the structs + * below into "struct netent"'s. + */ +struct nwent { + char *n_name; /*%< official name of net */ + char **n_aliases; /*%< alias list */ + int n_addrtype; /*%< net address type */ + void *n_addr; /*%< network address */ + int n_length; /*%< address length, in bits */ +}; + +/*% + * Hide external function names from POSIX. + */ +#define irs_gen_acc __irs_gen_acc +#define irs_lcl_acc __irs_lcl_acc +#define irs_dns_acc __irs_dns_acc +#define irs_nis_acc __irs_nis_acc +#define irs_irp_acc __irs_irp_acc +#define irs_destroy __irs_destroy +#define irs_dns_gr __irs_dns_gr +#define irs_dns_ho __irs_dns_ho +#define irs_dns_nw __irs_dns_nw +#define irs_dns_pr __irs_dns_pr +#define irs_dns_pw __irs_dns_pw +#define irs_dns_sv __irs_dns_sv +#define irs_gen_gr __irs_gen_gr +#define irs_gen_ho __irs_gen_ho +#define irs_gen_ng __irs_gen_ng +#define irs_gen_nw __irs_gen_nw +#define irs_gen_pr __irs_gen_pr +#define irs_gen_pw __irs_gen_pw +#define irs_gen_sv __irs_gen_sv +#define irs_irp_get_full_response __irs_irp_get_full_response +#define irs_irp_gr __irs_irp_gr +#define irs_irp_ho __irs_irp_ho +#define irs_irp_is_connected __irs_irp_is_connected +#define irs_irp_ng __irs_irp_ng +#define irs_irp_nw __irs_irp_nw +#define irs_irp_pr __irs_irp_pr +#define irs_irp_pw __irs_irp_pw +#define irs_irp_read_line __irs_irp_read_line +#define irs_irp_sv __irs_irp_sv +#define irs_lcl_gr __irs_lcl_gr +#define irs_lcl_ho __irs_lcl_ho +#define irs_lcl_ng __irs_lcl_ng +#define irs_lcl_nw __irs_lcl_nw +#define irs_lcl_pr __irs_lcl_pr +#define irs_lcl_pw __irs_lcl_pw +#define irs_lcl_sv __irs_lcl_sv +#define irs_nis_gr __irs_nis_gr +#define irs_nis_ho __irs_nis_ho +#define irs_nis_ng __irs_nis_ng +#define irs_nis_nw __irs_nis_nw +#define irs_nis_pr __irs_nis_pr +#define irs_nis_pw __irs_nis_pw +#define irs_nis_sv __irs_nis_sv +#define net_data_create __net_data_create +#define net_data_destroy __net_data_destroy +#define net_data_minimize __net_data_minimize + +/*% + * Externs. + */ +extern struct irs_acc * irs_gen_acc __P((const char *, const char *)); +extern struct irs_acc * irs_lcl_acc __P((const char *)); +extern struct irs_acc * irs_dns_acc __P((const char *)); +extern struct irs_acc * irs_nis_acc __P((const char *)); +extern struct irs_acc * irs_irp_acc __P((const char *)); + +extern void irs_destroy __P((void)); + +/*% + * These forward declarations are for the semi-private functions in + * the get*.c files. Each of these funcs implements the real get* + * functionality and the standard versions are just wrappers that + * call these. Apart from the wrappers, only irpd is expected to + * call these directly, hence these decls are put here and not in + * the /usr/include replacements. + */ + +struct net_data; /*%< forward */ +/* + * net_data_create gets a singleton net_data object. net_data_init + * creates as many net_data objects as times it is called. Clients using + * the default interface will use net_data_create by default. Servers will + * probably want net_data_init (one call per client) + */ +struct net_data *net_data_create __P((const char *)); +struct net_data *net_data_init __P((const char *)); +void net_data_destroy __P((void *)); + +extern struct group *getgrent_p __P((struct net_data *)); +extern struct group *getgrnam_p __P((const char *, struct net_data *)); +extern struct group *getgrgid_p __P((gid_t, struct net_data *)); +extern int setgroupent_p __P((int, struct net_data *)); +extern void endgrent_p __P((struct net_data *)); +extern int getgrouplist_p __P((const char *, gid_t, gid_t *, int *, + struct net_data *)); + +#ifdef SETGRENT_VOID +extern void setgrent_p __P((struct net_data *)); +#else +extern int setgrent_p __P((struct net_data *)); +#endif + +extern struct hostent *gethostbyname_p __P((const char *, + struct net_data *)); +extern struct hostent *gethostbyname2_p __P((const char *, int, + struct net_data *)); +extern struct hostent *gethostbyaddr_p __P((const char *, int, int, + struct net_data *)); +extern struct hostent *gethostent_p __P((struct net_data *)); +extern void sethostent_p __P((int, struct net_data *)); +extern void endhostent_p __P((struct net_data *)); +extern struct hostent *getipnodebyname_p __P((const char *, int, int, int *, + struct net_data *)); +extern struct hostent *getipnodebyaddr_p __P((const void *, size_t, + int, int *, struct net_data *)); + +extern struct netent *getnetent_p __P((struct net_data *)); +extern struct netent *getnetbyname_p __P((const char *, struct net_data *)); +extern struct netent *getnetbyaddr_p __P((unsigned long, int, + struct net_data *)); +extern void setnetent_p __P((int, struct net_data *)); +extern void endnetent_p __P((struct net_data *)); + +extern void setnetgrent_p __P((const char *, struct net_data *)); +extern void endnetgrent_p __P((struct net_data *)); +extern int innetgr_p __P((const char *, const char *, const char *, + const char *, struct net_data *)); +extern int getnetgrent_p __P((const char **, const char **, + const char **, struct net_data *)); + +extern struct protoent *getprotoent_p __P((struct net_data *)); +extern struct protoent *getprotobyname_p __P((const char *, + struct net_data *)); +extern struct protoent *getprotobynumber_p __P((int, struct net_data *)); +extern void setprotoent_p __P((int, struct net_data *)); +extern void endprotoent_p __P((struct net_data *)); + + +extern struct passwd *getpwent_p __P((struct net_data *)); +extern struct passwd *getpwnam_p __P((const char *, struct net_data *)); +extern struct passwd *getpwuid_p __P((uid_t, struct net_data *)); +extern int setpassent_p __P((int, struct net_data *)); +extern void endpwent_p __P((struct net_data *)); + +#ifdef SETPWENT_VOID +extern void setpwent_p __P((struct net_data *)); +#else +extern int setpwent_p __P((struct net_data *)); +#endif + +extern struct servent *getservent_p __P((struct net_data *)); +extern struct servent *getservbyname_p __P((const char *, const char *, + struct net_data *)); +extern struct servent *getservbyport_p __P((int, const char *, + struct net_data *)); +extern void setservent_p __P((int, struct net_data *)); +extern void endservent_p __P((struct net_data *)); + +#endif /*_IRS_H_INCLUDED*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/isc/assertions.h b/usr/src/lib/libresolv2_joy/include/isc/assertions.h new file mode 100644 index 0000000000..68925e73b3 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/assertions.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1997-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: assertions.h,v 1.5 2008/11/14 02:36:51 marka Exp $ + */ + +#ifndef ASSERTIONS_H +#define ASSERTIONS_H 1 + +typedef enum { + assert_require, assert_ensure, assert_insist, assert_invariant +} assertion_type; + +typedef void (*assertion_failure_callback)(const char *, int, assertion_type, + const char *, int); + +/* coverity[+kill] */ +extern assertion_failure_callback __assertion_failed; +void set_assertion_failure_callback(assertion_failure_callback f); +const char *assertion_type_to_text(assertion_type type); + +#if defined(CHECK_ALL) || defined(__COVERITY__) +#define CHECK_REQUIRE 1 +#define CHECK_ENSURE 1 +#define CHECK_INSIST 1 +#define CHECK_INVARIANT 1 +#endif + +#if defined(CHECK_NONE) && !defined(__COVERITY__) +#define CHECK_REQUIRE 0 +#define CHECK_ENSURE 0 +#define CHECK_INSIST 0 +#define CHECK_INVARIANT 0 +#endif + +#ifndef CHECK_REQUIRE +#define CHECK_REQUIRE 1 +#endif + +#ifndef CHECK_ENSURE +#define CHECK_ENSURE 1 +#endif + +#ifndef CHECK_INSIST +#define CHECK_INSIST 1 +#endif + +#ifndef CHECK_INVARIANT +#define CHECK_INVARIANT 1 +#endif + +#if CHECK_REQUIRE != 0 +#define REQUIRE(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_require, \ + #cond, 0), 0))) +#define REQUIRE_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_require, \ + #cond, 1), 0))) +#else +#define REQUIRE(cond) ((void) (cond)) +#define REQUIRE_ERR(cond) ((void) (cond)) +#endif /* CHECK_REQUIRE */ + +#if CHECK_ENSURE != 0 +#define ENSURE(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_ensure, \ + #cond, 0), 0))) +#define ENSURE_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_ensure, \ + #cond, 1), 0))) +#else +#define ENSURE(cond) ((void) (cond)) +#define ENSURE_ERR(cond) ((void) (cond)) +#endif /* CHECK_ENSURE */ + +#if CHECK_INSIST != 0 +#define INSIST(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_insist, \ + #cond, 0), 0))) +#define INSIST_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_insist, \ + #cond, 1), 0))) +#else +#define INSIST(cond) ((void) (cond)) +#define INSIST_ERR(cond) ((void) (cond)) +#endif /* CHECK_INSIST */ + +#if CHECK_INVARIANT != 0 +#define INVARIANT(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_invariant, \ + #cond, 0), 0))) +#define INVARIANT_ERR(cond) \ + ((void) ((cond) || \ + ((__assertion_failed)(__FILE__, __LINE__, assert_invariant, \ + #cond, 1), 0))) +#else +#define INVARIANT(cond) ((void) (cond)) +#define INVARIANT_ERR(cond) ((void) (cond)) +#endif /* CHECK_INVARIANT */ +#endif /* ASSERTIONS_H */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/isc/ctl.h b/usr/src/lib/libresolv2_joy/include/isc/ctl.h new file mode 100644 index 0000000000..e2ba20201d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/ctl.h @@ -0,0 +1,112 @@ +#ifndef ISC_CTL_H +#define ISC_CTL_H + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1998,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: ctl.h,v 1.5 2005/04/27 04:56:17 sra Exp $ + */ + +/*! \file */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <isc/eventlib.h> + +/* Macros. */ + +#define CTL_MORE 0x0001 /*%< More will be / should be sent. */ +#define CTL_EXIT 0x0002 /*%< Close connection after this. */ +#define CTL_DATA 0x0004 /*%< Go into / this is DATA mode. */ +/* Types. */ + +struct ctl_cctx; +struct ctl_sctx; +struct ctl_sess; +struct ctl_verb; + +enum ctl_severity { ctl_debug, ctl_warning, ctl_error }; + +typedef void (*ctl_logfunc)(enum ctl_severity, const char *, ...); + +typedef void (*ctl_verbfunc)(struct ctl_sctx *, struct ctl_sess *, + const struct ctl_verb *, const char *, + u_int, const void *, void *); + +typedef void (*ctl_srvrdone)(struct ctl_sctx *, struct ctl_sess *, void *); + +typedef void (*ctl_clntdone)(struct ctl_cctx *, void *, const char *, u_int); + +struct ctl_verb { + const char * name; + ctl_verbfunc func; + const char * help; +}; + +/* General symbols. */ + +#define ctl_logger __ctl_logger + +#ifdef __GNUC__ +void ctl_logger(enum ctl_severity, const char *, ...) + __attribute__((__format__(__printf__, 2, 3))); +#else +void ctl_logger(enum ctl_severity, const char *, ...); +#endif + +/* Client symbols. */ + +#define ctl_client __ctl_client +#define ctl_endclient __ctl_endclient +#define ctl_command __ctl_command + +struct ctl_cctx * ctl_client(evContext, const struct sockaddr *, size_t, + const struct sockaddr *, size_t, + ctl_clntdone, void *, + u_int, ctl_logfunc); +void ctl_endclient(struct ctl_cctx *); +int ctl_command(struct ctl_cctx *, const char *, size_t, + ctl_clntdone, void *); + +/* Server symbols. */ + +#define ctl_server __ctl_server +#define ctl_endserver __ctl_endserver +#define ctl_response __ctl_response +#define ctl_sendhelp __ctl_sendhelp +#define ctl_getcsctx __ctl_getcsctx +#define ctl_setcsctx __ctl_setcsctx + +struct ctl_sctx * ctl_server(evContext, const struct sockaddr *, size_t, + const struct ctl_verb *, + u_int, u_int, + u_int, int, int, + ctl_logfunc, void *); +void ctl_endserver(struct ctl_sctx *); +void ctl_response(struct ctl_sess *, u_int, + const char *, u_int, const void *, + ctl_srvrdone, void *, + const char *, size_t); +void ctl_sendhelp(struct ctl_sess *, u_int); +void * ctl_getcsctx(struct ctl_sess *); +void * ctl_setcsctx(struct ctl_sess *, void *); + +#endif /*ISC_CTL_H*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/isc/dst.h b/usr/src/lib/libresolv2_joy/include/isc/dst.h new file mode 100644 index 0000000000..90a9e67468 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/dst.h @@ -0,0 +1,168 @@ +#ifndef DST_H +#define DST_H + +#ifndef HAS_DST_KEY +typedef struct dst_key { + char *dk_key_name; /*%< name of the key */ + int dk_key_size; /*%< this is the size of the key in bits */ + int dk_proto; /*%< what protocols this key can be used for */ + int dk_alg; /*%< algorithm number from key record */ + u_int32_t dk_flags; /*%< and the flags of the public key */ + u_int16_t dk_id; /*%< identifier of the key */ +} DST_KEY; +#endif /* HAS_DST_KEY */ +/* + * do not taint namespace + */ +#define dst_bsafe_init __dst_bsafe_init +#define dst_buffer_to_key __dst_buffer_to_key +#define dst_check_algorithm __dst_check_algorithm +#define dst_compare_keys __dst_compare_keys +#define dst_cylink_init __dst_cylink_init +#define dst_dnskey_to_key __dst_dnskey_to_key +#define dst_eay_dss_init __dst_eay_dss_init +#define dst_free_key __dst_free_key +#define dst_generate_key __dst_generate_key +#define dst_hmac_md5_init __dst_hmac_md5_init +#define dst_init __dst_init +#define dst_key_to_buffer __dst_key_to_buffer +#define dst_key_to_dnskey __dst_key_to_dnskey +#define dst_read_key __dst_read_key +#define dst_rsaref_init __dst_rsaref_init +#define dst_s_build_filename __dst_s_build_filename +#define dst_s_calculate_bits __dst_s_calculate_bits +#define dst_s_conv_bignum_b64_to_u8 __dst_s_conv_bignum_b64_to_u8 +#define dst_s_conv_bignum_u8_to_b64 __dst_s_conv_bignum_u8_to_b64 +#define dst_s_dns_key_id __dst_s_dns_key_id +#define dst_s_dump __dst_s_dump +#define dst_s_filename_length __dst_s_filename_length +#define dst_s_fopen __dst_s_fopen +#define dst_s_get_int16 __dst_s_get_int16 +#define dst_s_get_int32 __dst_s_get_int32 +#define dst_s_id_calc __dst_s_id_calc +#define dst_s_put_int16 __dst_s_put_int16 +#define dst_s_put_int32 __dst_s_put_int32 +#define dst_s_quick_random __dst_s_quick_random +#define dst_s_quick_random_set __dst_s_quick_random_set +#define dst_s_random __dst_s_random +#define dst_s_semi_random __dst_s_semi_random +#define dst_s_verify_str __dst_s_verify_str +#define dst_sig_size __dst_sig_size +#define dst_sign_data __dst_sign_data +#define dst_verify_data __dst_verify_data +#define dst_write_key __dst_write_key + +/* + * DST Crypto API defintions + */ +void dst_init(void); +int dst_check_algorithm(const int); + + +int dst_sign_data(const int, /*!< specifies INIT/UPDATE/FINAL/ALL */ + DST_KEY *, /*!< the key to use */ + void **, /*!< pointer to state structure */ + const u_char *, /*!< data to be signed */ + const int, /*!< length of input data */ + u_char *, /*!< buffer to write signature to */ + const int); /*!< size of output buffer */ +int dst_verify_data(const int, /*!< specifies INIT/UPDATE/FINAL/ALL */ + DST_KEY *, /*!< the key to use */ + void **, /*!< pointer to state structure */ + const u_char *, /*!< data to be verified */ + const int, /*!< length of input data */ + const u_char *, /*!< buffer containing signature */ + const int); /*!< length of signature */ +DST_KEY *dst_read_key(const char *, /*!< name of key */ + const u_int16_t, /*!< key tag identifier */ + const int, /*!< key algorithm */ + const int); /*!< Private/PublicKey wanted */ +int dst_write_key(const DST_KEY *, /*!< key to write out */ + const int); /*!< Public/Private */ +DST_KEY *dst_dnskey_to_key(const char *, /*!< KEY record name */ + const u_char *, /*!< KEY RDATA */ + const int); /*!< size of input buffer */ +int dst_key_to_dnskey(const DST_KEY *, /*!< key to translate */ + u_char *, /*!< output buffer */ + const int); /*!< size of out_storage */ +DST_KEY *dst_buffer_to_key(const char *, /*!< name of the key */ + const int, /*!< algorithm */ + const int, /*!< dns flags */ + const int, /*!< dns protocol */ + const u_char *, /*!< key in dns wire fmt */ + const int); /*!< size of key */ +int dst_key_to_buffer(DST_KEY *, u_char *, int); + +DST_KEY *dst_generate_key(const char *, /*!< name of new key */ + const int, /*!< key algorithm to generate */ + const int, /*!< size of new key */ + const int, /*!< alg dependent parameter */ + const int, /*!< key DNS flags */ + const int); /*!< key DNS protocol */ +DST_KEY *dst_free_key(DST_KEY *); +int dst_compare_keys(const DST_KEY *, const DST_KEY *); + +int dst_sig_size(DST_KEY *); + + +/* support for dns key tags/ids */ +u_int16_t dst_s_dns_key_id(const u_char *, const int); +u_int16_t dst_s_id_calc(const u_char *, const int); + +/* Used by callers as well as by the library. */ +#define RAW_KEY_SIZE 8192 /*%< large enough to store any key */ +/* DST_API control flags */ +/* These are used used in functions dst_sign_data and dst_verify_data */ +#define SIG_MODE_INIT 1 /*%< initialize digest */ +#define SIG_MODE_UPDATE 2 /*%< add data to digest */ +#define SIG_MODE_FINAL 4 /*%< generate/verify signature */ +#define SIG_MODE_ALL (SIG_MODE_INIT|SIG_MODE_UPDATE|SIG_MODE_FINAL) + +/* Flags for dst_read_private_key() */ +#define DST_FORCE_READ 0x1000000 +#define DST_CAN_SIGN 0x010F +#define DST_NO_AUTHEN 0x8000 +#define DST_EXTEND_FLAG 0x1000 +#define DST_STANDARD 0 +#define DST_PRIVATE 0x2000000 +#define DST_PUBLIC 0x4000000 +#define DST_RAND_SEMI 1 +#define DST_RAND_STD 2 +#define DST_RAND_KEY 3 +#define DST_RAND_DSS 4 + + +/* DST algorithm codes */ +#define KEY_RSA 1 +#define KEY_DH 2 +#define KEY_DSA 3 +#define KEY_PRIVATE 254 +#define KEY_EXPAND 255 +#define KEY_HMAC_MD5 157 +#define KEY_HMAC_SHA1 158 +#define UNKNOWN_KEYALG 0 +#define DST_MAX_ALGS KEY_HMAC_SHA1 + +/* DST constants to locations in KEY record changes in new KEY record */ +#define DST_FLAGS_SIZE 2 +#define DST_KEY_PROT 2 +#define DST_KEY_ALG 3 +#define DST_EXT_FLAG 4 +#define DST_KEY_START 4 + +#ifndef SIGN_F_NOKEY +#define SIGN_F_NOKEY 0xC000 +#endif + +/* error codes from dst routines */ +#define SIGN_INIT_FAILURE (-23) +#define SIGN_UPDATE_FAILURE (-24) +#define SIGN_FINAL_FAILURE (-25) +#define VERIFY_INIT_FAILURE (-26) +#define VERIFY_UPDATE_FAILURE (-27) +#define VERIFY_FINAL_FAILURE (-28) +#define MISSING_KEY_OR_SIGNATURE (-30) +#define UNSUPPORTED_KEYALG (-31) + +#endif /* DST_H */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/isc/eventlib.h b/usr/src/lib/libresolv2_joy/include/isc/eventlib.h new file mode 100644 index 0000000000..a4cfdf9092 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/eventlib.h @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1995-1999, 2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* eventlib.h - exported interfaces for eventlib + * vix 09sep95 [initial] + * + * $Id: eventlib.h,v 1.7 2008/11/14 02:36:51 marka Exp $ + */ + +#ifndef _EVENTLIB_H +#define _EVENTLIB_H + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/time.h> +#include <stdio.h> + +#include <isc/platform.h> + +#ifndef __P +# define __EVENTLIB_P_DEFINED +# ifdef __STDC__ +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +/* In the absence of branded types... */ +typedef struct { void *opaque; } evConnID; +typedef struct { void *opaque; } evFileID; +typedef struct { void *opaque; } evStreamID; +typedef struct { void *opaque; } evTimerID; +typedef struct { void *opaque; } evWaitID; +typedef struct { void *opaque; } evContext; +typedef struct { void *opaque; } evEvent; + +#define evInitID(id) ((id)->opaque = NULL) +#define evTestID(id) ((id).opaque != NULL) + +typedef void (*evConnFunc)__P((evContext, void *, int, const void *, int, + const void *, int)); +typedef void (*evFileFunc)__P((evContext, void *, int, int)); +typedef void (*evStreamFunc)__P((evContext, void *, int, int)); +typedef void (*evTimerFunc)__P((evContext, void *, + struct timespec, struct timespec)); +typedef void (*evWaitFunc)__P((evContext, void *, const void *)); + +typedef struct { unsigned char mask[256/8]; } evByteMask; +#define EV_BYTEMASK_BYTE(b) ((b) / 8) +#define EV_BYTEMASK_MASK(b) (1 << ((b) % 8)) +#define EV_BYTEMASK_SET(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] |= EV_BYTEMASK_MASK(b)) +#define EV_BYTEMASK_CLR(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] &= ~EV_BYTEMASK_MASK(b)) +#define EV_BYTEMASK_TST(bm, b) \ + ((bm).mask[EV_BYTEMASK_BYTE(b)] & EV_BYTEMASK_MASK(b)) + +#define EV_POLL 1 +#define EV_WAIT 2 +#define EV_NULL 4 + +#define EV_READ 1 +#define EV_WRITE 2 +#define EV_EXCEPT 4 + +#define EV_WASNONBLOCKING 8 /* Internal library use. */ + +/* eventlib.c */ +#define evCreate __evCreate +#define evSetDebug __evSetDebug +#define evDestroy __evDestroy +#define evGetNext __evGetNext +#define evDispatch __evDispatch +#define evDrop __evDrop +#define evMainLoop __evMainLoop +#define evHighestFD __evHighestFD +#define evGetOption __evGetOption +#define evSetOption __evSetOption + +int evCreate __P((evContext *)); +void evSetDebug __P((evContext, int, FILE *)); +int evDestroy __P((evContext)); +int evGetNext __P((evContext, evEvent *, int)); +int evDispatch __P((evContext, evEvent)); +void evDrop __P((evContext, evEvent)); +int evMainLoop __P((evContext)); +int evHighestFD __P((evContext)); +int evGetOption __P((evContext *, const char *, int *)); +int evSetOption __P((evContext *, const char *, int)); + +/* ev_connects.c */ +#define evListen __evListen +#define evConnect __evConnect +#define evCancelConn __evCancelConn +#define evHold __evHold +#define evUnhold __evUnhold +#define evTryAccept __evTryAccept + +int evListen __P((evContext, int, int, evConnFunc, void *, evConnID *)); +int evConnect __P((evContext, int, const void *, int, + evConnFunc, void *, evConnID *)); +int evCancelConn __P((evContext, evConnID)); +int evHold __P((evContext, evConnID)); +int evUnhold __P((evContext, evConnID)); +int evTryAccept __P((evContext, evConnID, int *)); + +/* ev_files.c */ +#define evSelectFD __evSelectFD +#define evDeselectFD __evDeselectFD + +int evSelectFD __P((evContext, int, int, evFileFunc, void *, evFileID *)); +int evDeselectFD __P((evContext, evFileID)); + +/* ev_streams.c */ +#define evConsIovec __evConsIovec +#define evWrite __evWrite +#define evRead __evRead +#define evTimeRW __evTimeRW +#define evUntimeRW __evUntimeRW +#define evCancelRW __evCancelRW + +struct iovec evConsIovec __P((void *, size_t)); +int evWrite __P((evContext, int, const struct iovec *, int, + evStreamFunc func, void *, evStreamID *)); +int evRead __P((evContext, int, const struct iovec *, int, + evStreamFunc func, void *, evStreamID *)); +int evTimeRW __P((evContext, evStreamID, evTimerID timer)); +int evUntimeRW __P((evContext, evStreamID)); +int evCancelRW __P((evContext, evStreamID)); + +/* ev_timers.c */ +#define evConsTime __evConsTime +#define evAddTime __evAddTime +#define evSubTime __evSubTime +#define evCmpTime __evCmpTime +#define evTimeSpec __evTimeSpec +#define evTimeVal __evTimeVal + +#define evNowTime __evNowTime +#define evUTCTime __evUTCTime +#define evLastEventTime __evLastEventTime +#define evSetTimer __evSetTimer +#define evClearTimer __evClearTimer +#define evConfigTimer __evConfigTimer +#define evResetTimer __evResetTimer +#define evSetIdleTimer __evSetIdleTimer +#define evClearIdleTimer __evClearIdleTimer +#define evResetIdleTimer __evResetIdleTimer +#define evTouchIdleTimer __evTouchIdleTimer + +struct timespec evConsTime __P((time_t sec, long nsec)); +struct timespec evAddTime __P((struct timespec, struct timespec)); +struct timespec evSubTime __P((struct timespec, struct timespec)); +struct timespec evNowTime __P((void)); +struct timespec evUTCTime __P((void)); +struct timespec evLastEventTime __P((evContext)); +struct timespec evTimeSpec __P((struct timeval)); +struct timeval evTimeVal __P((struct timespec)); +int evCmpTime __P((struct timespec, struct timespec)); +int evSetTimer __P((evContext, evTimerFunc, void *, struct timespec, + struct timespec, evTimerID *)); +int evClearTimer __P((evContext, evTimerID)); +int evConfigTimer __P((evContext, evTimerID, const char *param, + int value)); +int evResetTimer __P((evContext, evTimerID, evTimerFunc, void *, + struct timespec, struct timespec)); +int evSetIdleTimer __P((evContext, evTimerFunc, void *, struct timespec, + evTimerID *)); +int evClearIdleTimer __P((evContext, evTimerID)); +int evResetIdleTimer __P((evContext, evTimerID, evTimerFunc, void *, + struct timespec)); +int evTouchIdleTimer __P((evContext, evTimerID)); + +/* ev_waits.c */ +#define evWaitFor __evWaitFor +#define evDo __evDo +#define evUnwait __evUnwait +#define evDefer __evDefer + +int evWaitFor __P((evContext, const void *, evWaitFunc, void *, evWaitID *)); +int evDo __P((evContext, const void *)); +int evUnwait __P((evContext, evWaitID)); +int evDefer __P((evContext, evWaitFunc, void *)); + +#ifdef __EVENTLIB_P_DEFINED +# undef __P +#endif + +#endif /*_EVENTLIB_H*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/isc/heap.h b/usr/src/lib/libresolv2_joy/include/isc/heap.h new file mode 100644 index 0000000000..384d507cf5 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/heap.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1997,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +typedef int (*heap_higher_priority_func)(void *, void *); +typedef void (*heap_index_func)(void *, int); +typedef void (*heap_for_each_func)(void *, void *); + +typedef struct heap_context { + int array_size; + int array_size_increment; + int heap_size; + void **heap; + heap_higher_priority_func higher_priority; + heap_index_func index; +} *heap_context; + +#define heap_new __heap_new +#define heap_free __heap_free +#define heap_insert __heap_insert +#define heap_delete __heap_delete +#define heap_increased __heap_increased +#define heap_decreased __heap_decreased +#define heap_element __heap_element +#define heap_for_each __heap_for_each + +heap_context heap_new(heap_higher_priority_func, heap_index_func, int); +int heap_free(heap_context); +int heap_insert(heap_context, void *); +int heap_delete(heap_context, int); +int heap_increased(heap_context, int); +int heap_decreased(heap_context, int); +void * heap_element(heap_context, int); +int heap_for_each(heap_context, heap_for_each_func, void *); + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/isc/irpmarshall.h b/usr/src/lib/libresolv2_joy/include/isc/irpmarshall.h new file mode 100644 index 0000000000..244b3e3460 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/irpmarshall.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: irpmarshall.h,v 1.4 2005/04/27 04:56:17 sra Exp $ + */ + +#ifndef _IRPMARSHALL_H_INCLUDED +#define _IRPMARSHALL_H_INCLUDED + +/* Hide function names */ +#define irp_marshall_gr __irp_marshall_gr +#define irp_marshall_ho __irp_marshall_ho +#define irp_marshall_ne __irp_marshall_ne +#define irp_marshall_ng __irp_marshall_ng +#define irp_marshall_nw __irp_marshall_nw +#define irp_marshall_pr __irp_marshall_pr +#define irp_marshall_pw __irp_marshall_pw +#define irp_marshall_sv __irp_marshall_sv +#define irp_unmarshall_gr __irp_unmarshall_gr +#define irp_unmarshall_ho __irp_unmarshall_ho +#define irp_unmarshall_ne __irp_unmarshall_ne +#define irp_unmarshall_ng __irp_unmarshall_ng +#define irp_unmarshall_nw __irp_unmarshall_nw +#define irp_unmarshall_pr __irp_unmarshall_pr +#define irp_unmarshall_pw __irp_unmarshall_pw +#define irp_unmarshall_sv __irp_unmarshall_sv + +#define MAXPADDRSIZE (sizeof "255.255.255.255" + 1) +#define ADDR_T_STR(x) (x == AF_INET ? "AF_INET" :\ + (x == AF_INET6 ? "AF_INET6" : "UNKNOWN")) + +/* See comment below on usage */ +int irp_marshall_pw(const struct passwd *, char **, size_t *); +int irp_unmarshall_pw(struct passwd *, char *); +int irp_marshall_gr(const struct group *, char **, size_t *); +int irp_unmarshall_gr(struct group *, char *); +int irp_marshall_sv(const struct servent *, char **, size_t *); +int irp_unmarshall_sv(struct servent *, char *); +int irp_marshall_pr(struct protoent *, char **, size_t *); +int irp_unmarshall_pr(struct protoent *, char *); +int irp_marshall_ho(struct hostent *, char **, size_t *); +int irp_unmarshall_ho(struct hostent *, char *); +int irp_marshall_ng(const char *, const char *, const char *, + char **, size_t *); +int irp_unmarshall_ng(const char **, const char **, const char **, char *); +int irp_marshall_nw(struct nwent *, char **, size_t *); +int irp_unmarshall_nw(struct nwent *, char *); +int irp_marshall_ne(struct netent *, char **, size_t *); +int irp_unmarshall_ne(struct netent *, char *); + +/*! \file + * \brief + * Functions to marshall and unmarshall various system data structures. We + * use a printable ascii format that is as close to various system config + * files as reasonable (e.g. /etc/passwd format). + * + * We are not forgiving with unmarhsalling misformatted buffers. In + * particular whitespace in fields is not ignored. So a formatted password + * entry "brister :1364:100:...." will yield a username of "brister " + * + * We potentially do a lot of mallocs to fill fields that are of type + * (char **) like a hostent h_addr field. Building (for example) the + * h_addr field and its associated addresses all in one buffer is + * certainly possible, but not done here. + * + * The following description is true for all the marshalling functions: + * + * int irp_marshall_XX(struct yyyy *XX, char **buffer, size_t *len); + * + * The argument XX (of type struct passwd for example) is marshalled in the + * buffer pointed at by *BUFFER, which is of length *LEN. Returns 0 + * on success and -1 on failure. Failure will occur if *LEN is + * smaller than needed. + * + * If BUFFER is NULL, then *LEN is set to the size of the buffer + * needed to marshall the data and no marshalling is actually done. + * + * If *BUFFER is NULL, then a buffer large enough will be allocated + * with memget() and the size allocated will be stored in *LEN. An extra 2 + * bytes will be allocated for the client to append CRLF if wanted. The + * value of *LEN will include these two bytes. + * + * All the marshalling functions produce a buffer with the fields + * separated by colons (except for the hostent marshalling, which uses '@' + * to separate fields). Fields that have multiple subfields (like the + * gr_mem field in struct group) have their subparts separated by + * commas. + * + * int irp_unmarshall_XX(struct YYYYY *XX, char *buffer); + * + * The unmashalling functions break apart the buffer and store the + * values in the struct pointed to by XX. All pointer values inside + * XX are allocated with malloc. All arrays of pointers have a NULL + * as the last element. + */ + +#endif diff --git a/usr/src/lib/libresolv2_joy/include/isc/list.h b/usr/src/lib/libresolv2_joy/include/isc/list.h new file mode 100644 index 0000000000..5fe9031141 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/list.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1997,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 LIST_H +#define LIST_H 1 +#include <isc/assertions.h> + +#define LIST(type) struct { type *head, *tail; } +#define INIT_LIST(list) \ + do { (list).head = NULL; (list).tail = NULL; } while (0) + +#define LINK(type) struct { type *prev, *next; } +#define INIT_LINK_TYPE(elt, link, type) \ + do { \ + (elt)->link.prev = (type *)(-1); \ + (elt)->link.next = (type *)(-1); \ + } while (0) +#define INIT_LINK(elt, link) \ + INIT_LINK_TYPE(elt, link, void) +#define LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1) && \ + (void *)((elt)->link.next) != (void *)(-1)) + +#define HEAD(list) ((list).head) +#define TAIL(list) ((list).tail) +#define EMPTY(list) ((list).head == NULL) + +#define PREPEND(list, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((list).head != NULL) \ + (list).head->link.prev = (elt); \ + else \ + (list).tail = (elt); \ + (elt)->link.prev = NULL; \ + (elt)->link.next = (list).head; \ + (list).head = (elt); \ + } while (0) + +#define APPEND(list, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((list).tail != NULL) \ + (list).tail->link.next = (elt); \ + else \ + (list).head = (elt); \ + (elt)->link.prev = (list).tail; \ + (elt)->link.next = NULL; \ + (list).tail = (elt); \ + } while (0) + +#define UNLINK_TYPE(list, elt, link, type) \ + do { \ + INSIST(LINKED(elt, link));\ + if ((elt)->link.next != NULL) \ + (elt)->link.next->link.prev = (elt)->link.prev; \ + else { \ + INSIST((list).tail == (elt)); \ + (list).tail = (elt)->link.prev; \ + } \ + if ((elt)->link.prev != NULL) \ + (elt)->link.prev->link.next = (elt)->link.next; \ + else { \ + INSIST((list).head == (elt)); \ + (list).head = (elt)->link.next; \ + } \ + INIT_LINK_TYPE(elt, link, type); \ + } while (0) +#define UNLINK(list, elt, link) \ + UNLINK_TYPE(list, elt, link, void) + +#define PREV(elt, link) ((elt)->link.prev) +#define NEXT(elt, link) ((elt)->link.next) + +#define INSERT_BEFORE(list, before, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((before)->link.prev == NULL) \ + PREPEND(list, elt, link); \ + else { \ + (elt)->link.prev = (before)->link.prev; \ + (before)->link.prev = (elt); \ + (elt)->link.prev->link.next = (elt); \ + (elt)->link.next = (before); \ + } \ + } while (0) + +#define INSERT_AFTER(list, after, elt, link) \ + do { \ + INSIST(!LINKED(elt, link));\ + if ((after)->link.next == NULL) \ + APPEND(list, elt, link); \ + else { \ + (elt)->link.next = (after)->link.next; \ + (after)->link.next = (elt); \ + (elt)->link.next->link.prev = (elt); \ + (elt)->link.prev = (after); \ + } \ + } while (0) + +#define ENQUEUE(list, elt, link) APPEND(list, elt, link) +#define DEQUEUE(list, elt, link) UNLINK(list, elt, link) + +#endif /* LIST_H */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/isc/logging.h b/usr/src/lib/libresolv2_joy/include/isc/logging.h new file mode 100644 index 0000000000..c539443ff8 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/logging.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 LOGGING_H +#define LOGGING_H + +#include <sys/types.h> +#include <stdio.h> +#include <stdarg.h> +#include <unistd.h> + +#define log_critical (-5) +#define log_error (-4) +#define log_warning (-3) +#define log_notice (-2) +#define log_info (-1) +#define log_debug(level) (level) + +typedef enum { log_syslog, log_file, log_null } log_channel_type; + +#define LOG_MAX_VERSIONS 99 + +#define LOG_CLOSE_STREAM 0x0001 +#define LOG_TIMESTAMP 0x0002 +#define LOG_TRUNCATE 0x0004 +#define LOG_USE_CONTEXT_LEVEL 0x0008 +#define LOG_PRINT_LEVEL 0x0010 +#define LOG_REQUIRE_DEBUG 0x0020 +#define LOG_CHANNEL_BROKEN 0x0040 +#define LOG_PRINT_CATEGORY 0x0080 +#define LOG_CHANNEL_OFF 0x0100 + +typedef struct log_context *log_context; +typedef struct log_channel *log_channel; + +#define LOG_OPTION_DEBUG 0x01 +#define LOG_OPTION_LEVEL 0x02 + +#define log_open_stream __log_open_stream +#define log_close_stream __log_close_stream +#define log_get_stream __log_get_stream +#define log_get_filename __log_get_filename +#define log_check_channel __log_check_channel +#define log_check __log_check +#define log_vwrite __log_vwrite +#define log_write __log_write +#define log_new_context __log_new_context +#define log_free_context __log_free_context +#define log_add_channel __log_add_channel +#define log_remove_channel __log_remove_channel +#define log_option __log_option +#define log_category_is_active __log_category_is_active +#define log_new_syslog_channel __log_new_syslog_channel +#define log_new_file_channel __log_new_file_channel +#define log_set_file_owner __log_set_file_owner +#define log_new_null_channel __log_new_null_channel +#define log_inc_references __log_inc_references +#define log_dec_references __log_dec_references +#define log_get_channel_type __log_get_channel_type +#define log_free_channel __log_free_channel +#define log_close_debug_channels __log_close_debug_channels + +FILE * log_open_stream(log_channel); +int log_close_stream(log_channel); +FILE * log_get_stream(log_channel); +char * log_get_filename(log_channel); +int log_check_channel(log_context, int, log_channel); +int log_check(log_context, int, int); +#ifdef __GNUC__ +void log_vwrite(log_context, int, int, const char *, + va_list args) + __attribute__((__format__(__printf__, 4, 0))); +void log_write(log_context, int, int, const char *, ...) + __attribute__((__format__(__printf__, 4, 5))); +#else +void log_vwrite(log_context, int, int, const char *, + va_list args); +void log_write(log_context, int, int, const char *, ...); +#endif +int log_new_context(int, char **, log_context *); +void log_free_context(log_context); +int log_add_channel(log_context, int, log_channel); +int log_remove_channel(log_context, int, log_channel); +int log_option(log_context, int, int); +int log_category_is_active(log_context, int); +log_channel log_new_syslog_channel(unsigned int, int, int); +log_channel log_new_file_channel(unsigned int, int, const char *, + FILE *, unsigned int, + unsigned long); +int log_set_file_owner(log_channel, uid_t, gid_t); +log_channel log_new_null_channel(void); +int log_inc_references(log_channel); +int log_dec_references(log_channel); +log_channel_type log_get_channel_type(log_channel); +int log_free_channel(log_channel); +void log_close_debug_channels(log_context); + +#endif /* !LOGGING_H */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/isc/memcluster.h b/usr/src/lib/libresolv2_joy/include/isc/memcluster.h new file mode 100644 index 0000000000..0923deb5e7 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/memcluster.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1997,1999 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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 MEMCLUSTER_H +#define MEMCLUSTER_H + +#include <stdio.h> + +#define meminit __meminit +#ifdef MEMCLUSTER_DEBUG +#define memget(s) __memget_debug(s, __FILE__, __LINE__) +#define memput(p, s) __memput_debug(p, s, __FILE__, __LINE__) +#else /*MEMCLUSTER_DEBUG*/ +#ifdef MEMCLUSTER_RECORD +#define memget(s) __memget_record(s, __FILE__, __LINE__) +#define memput(p, s) __memput_record(p, s, __FILE__, __LINE__) +#else /*MEMCLUSTER_RECORD*/ +#define memget __memget +#define memput __memput +#endif /*MEMCLUSTER_RECORD*/ +#endif /*MEMCLUSTER_DEBUG*/ +#define memstats __memstats +#define memactive __memactive + +int meminit(size_t, size_t); +void * __memget(size_t); +void __memput(void *, size_t); +void * __memget_debug(size_t, const char *, int); +void __memput_debug(void *, size_t, const char *, int); +void * __memget_record(size_t, const char *, int); +void __memput_record(void *, size_t, const char *, int); +void memstats(FILE *); +int memactive(void); + +#endif /* MEMCLUSTER_H */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/isc/misc.h b/usr/src/lib/libresolv2_joy/include/isc/misc.h new file mode 100644 index 0000000000..b54f4ee6ed --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/misc.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1995-2001, 2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: misc.h,v 1.7 2008/11/14 02:36:51 marka Exp $ + */ + +#ifndef _ISC_MISC_H +#define _ISC_MISC_H + +/*! \file */ + +#include <stdio.h> +#include <sys/types.h> + +#define bitncmp __bitncmp +/*#define isc_movefile __isc_movefile */ + +extern int bitncmp(const void *, const void *, int); +extern int isc_movefile(const char *, const char *); + +extern int isc_gethexstring(unsigned char *, size_t, int, FILE *, + int *); +extern void isc_puthexstring(FILE *, const unsigned char *, size_t, + size_t, size_t, const char *); +extern void isc_tohex(const unsigned char *, size_t, char *); + +#endif /*_ISC_MISC_H*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/isc/platform.h b/usr/src/lib/libresolv2_joy/include/isc/platform.h new file mode 100644 index 0000000000..2fc59b61a8 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/platform.h @@ -0,0 +1,42 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: platform.h.in,v 1.3 2008/01/23 02:15:56 tbox Exp $ */ + +/*! \file */ + +#ifndef ISC_PLATFORM_H +#define ISC_PLATFORM_H + +/* + * Define if the OS does not define struct timespec. + */ +#undef ISC_PLATFORM_NEEDTIMESPEC +#ifdef ISC_PLATFORM_NEEDTIMESPEC +#include <time.h> /* For time_t */ +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; +#endif + +#endif diff --git a/usr/src/lib/libresolv2_joy/include/isc/tree.h b/usr/src/lib/libresolv2_joy/include/isc/tree.h new file mode 100644 index 0000000000..96feaca68d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/isc/tree.h @@ -0,0 +1,59 @@ +/* tree.h - declare structures used by tree library + * + * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] + * vix 27jun86 [broken out of tree.c] + * + * $Id: tree.h,v 1.3 2005/04/27 04:56:18 sra Exp $ + */ + + +#ifndef _TREE_H_INCLUDED +#define _TREE_H_INCLUDED + + +#ifndef __P +# if defined(__STDC__) || defined(__GNUC__) +# define __P(x) x +# else +# define __P(x) () +# endif +#endif + +/*% + * tree_t is our package-specific anonymous pointer. + */ +#if defined(__STDC__) || defined(__GNUC__) +typedef void *tree_t; +#else +typedef char *tree_t; +#endif + +/*% + * Do not taint namespace + */ +#define tree_add __tree_add +#define tree_delete __tree_delete +#define tree_init __tree_init +#define tree_mung __tree_mung +#define tree_srch __tree_srch +#define tree_trav __tree_trav + + +typedef struct tree_s { + tree_t data; + struct tree_s *left, *right; + short bal; + } + tree; + + +void tree_init __P((tree **)); +tree_t tree_srch __P((tree **, int (*)(), tree_t)); +tree_t tree_add __P((tree **, int (*)(), tree_t, void (*)())); +int tree_delete __P((tree **, int (*)(), tree_t, void (*)())); +int tree_trav __P((tree **, int (*)())); +void tree_mung __P((tree **, void (*)())); + + +#endif /* _TREE_H_INCLUDED */ +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/make_os_version b/usr/src/lib/libresolv2_joy/include/make_os_version new file mode 100755 index 0000000000..3654490fee --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/make_os_version @@ -0,0 +1,34 @@ +#!/bin/sh + +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" + +UNAME_R=`/usr/bin/uname -r` + +OS_MAJOR=`echo $UNAME_R | /usr/bin/sed -e 's/^\([^.]*\).*/\1/'` +OS_MINOR=`echo $UNAME_R | /usr/bin/sed -e 's/^[^.]*\.\([^.]*\).*/\1/'` +OS_VERSION=`echo $UNAME_R | tr '.' '_'` + +cat <<EOF > new_os_version.h +#ifndef OS_VERSION_H +#define OS_VERSION_H + +#define SUNOS_$OS_VERSION +#define OS_MAJOR $OS_MAJOR +#define OS_MINOR $OS_MINOR + +#endif +EOF + +if [ -f os_version.h ]; then + if /usr/bin/cmp -s new_os_version.h os_version.h; then + /usr/bin/rm -f new_os_version.h + else + /usr/bin/rm -f os_version.h + /usr/bin/mv new_os_version.h os_version.h + fi +else + /usr/bin/mv new_os_version.h os_version.h +fi diff --git a/usr/src/lib/libresolv2_joy/include/make_os_version.sh b/usr/src/lib/libresolv2_joy/include/make_os_version.sh new file mode 100644 index 0000000000..3654490fee --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/make_os_version.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +# Copyright (c) 1999 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" + +UNAME_R=`/usr/bin/uname -r` + +OS_MAJOR=`echo $UNAME_R | /usr/bin/sed -e 's/^\([^.]*\).*/\1/'` +OS_MINOR=`echo $UNAME_R | /usr/bin/sed -e 's/^[^.]*\.\([^.]*\).*/\1/'` +OS_VERSION=`echo $UNAME_R | tr '.' '_'` + +cat <<EOF > new_os_version.h +#ifndef OS_VERSION_H +#define OS_VERSION_H + +#define SUNOS_$OS_VERSION +#define OS_MAJOR $OS_MAJOR +#define OS_MINOR $OS_MINOR + +#endif +EOF + +if [ -f os_version.h ]; then + if /usr/bin/cmp -s new_os_version.h os_version.h; then + /usr/bin/rm -f new_os_version.h + else + /usr/bin/rm -f os_version.h + /usr/bin/mv new_os_version.h os_version.h + fi +else + /usr/bin/mv new_os_version.h os_version.h +fi diff --git a/usr/src/lib/libresolv2_joy/include/port_after.h b/usr/src/lib/libresolv2_joy/include/port_after.h new file mode 100644 index 0000000000..c3abf4b334 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/port_after.h @@ -0,0 +1,539 @@ +/* + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + */ + +/* + * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2001-2003 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: port_after.h.in,v 1.60 2008/02/28 05:34:17 marka Exp $ */ + +#ifndef port_after_h +#define port_after_h + +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/param.h> +#include <sys/time.h> +#if (!defined(BSD)) || (BSD < 199306) +#include <sys/bitypes.h> +#endif +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif /* HAVE_SYS_SELECT_H */ + +#ifdef REENABLE_SEND +#undef send +#endif + +#undef NEED_PSELECT +#undef HAVE_SA_LEN +#undef HAVE_MINIMUM_IFREQ +#define NEED_DAEMON 1 +#undef NEED_STRSEP +#undef NEED_STRERROR +#ifdef NEED_STRERROR +const char *isc_strerror(int); +#define strerror isc_strerror +#endif +/* HAS_INET6_STRUCTS and HAVE_SIN6_SCOPE_ID are defined by port_ipv6.h + * #define HAS_INET6_STRUCTS 1 + * #define HAVE_SIN6_SCOPE_ID 1 + */ +#include <port_ipv6.h> + +#undef NEED_IN6ADDR_ANY +#undef HAS_IN_ADDR6 +#define HAVE_SOCKADDR_STORAGE 1 +#undef NEED_GETTIMEOFDAY +#define HAVE_STRNDUP +#undef USE_FIONBIO_IOCTL +#undef INNETGR_ARGS + +#undef USE_IFNAMELINKID +#define PORT_NONBLOCK O_NONBLOCK + +#ifndef _POSIX_PATH_MAX +#define _POSIX_PATH_MAX 255 +#endif +#ifndef PATH_MAX +#define PATH_MAX _POSIX_PATH_MAX +#endif + +/* + * We need to know the IPv6 address family number even on IPv4-only systems. + * Note that this is NOT a protocol constant, and that if the system has its + * own AF_INET6, different from ours below, all of BIND's libraries and + * executables will need to be recompiled after the system <sys/socket.h> + * has had this type added. The type number below is correct on most BSD- + * derived systems for which AF_INET6 is defined. + */ +#ifndef AF_INET6 +#define AF_INET6 24 +#endif + +#ifndef PF_INET6 +#define PF_INET6 AF_INET6 +#endif + +#ifdef HAS_IN_ADDR6 +/* Map to pre-RFC structure. */ +#define in6_addr in_addr6 +#endif + +#ifndef HAS_INET6_STRUCTS +/* Replace with structure from later rev of O/S if known. */ +struct in6_addr { + u_int8_t s6_addr[16]; +}; + +#define IN6ADDR_ANY_INIT \ + {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }} + +#define IN6ADDR_LOOPBACK_INIT \ + {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }} + +/* Replace with structure from later rev of O/S if known. */ +struct sockaddr_in6 { +#ifdef HAVE_SA_LEN + u_int8_t sin6_len; /* length of this struct */ + u_int8_t sin6_family; /* AF_INET6 */ +#else + u_int16_t sin6_family; /* AF_INET6 */ +#endif + u_int16_t sin6_port; /* transport layer port # */ + u_int32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + u_int32_t sin6_scope_id; /* set of interfaces for a scope */ +}; +#endif /* HAS_INET6_STRUCTS */ + +#ifdef BROKEN_IN6ADDR_INIT_MACROS +#undef IN6ADDR_ANY_INIT +#undef IN6ADDR_LOOPBACK_INIT +#endif + +#ifdef _AIX +#ifndef IN6ADDR_ANY_INIT +#define IN6ADDR_ANY_INIT {{{ 0, 0, 0, 0 }}} +#endif +#ifndef IN6ADDR_LOOPBACK_INIT +#if BYTE_ORDER == BIG_ENDIAN +#define IN6ADDR_LOOPBACK_INIT {{{ 0, 0, 0, 1 }}} +#else +#define IN6ADDR_LOOPBACK_INIT {{{0, 0, 0, 0x01000000}}} +#endif +#endif +#endif + +#ifndef IN6ADDR_ANY_INIT +#ifdef s6_addr +#define IN6ADDR_ANY_INIT \ + {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}} +#else +#define IN6ADDR_ANY_INIT \ + {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }} +#endif + +#endif +#ifndef IN6ADDR_LOOPBACK_INIT +#ifdef s6_addr +#define IN6ADDR_LOOPBACK_INIT \ + {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}} +#else +#define IN6ADDR_LOOPBACK_INIT \ + {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }} +#endif +#endif + +#ifndef HAVE_SOCKADDR_STORAGE +#define __SS_MAXSIZE 128 +#define __SS_ALLIGSIZE (sizeof (long)) + +struct sockaddr_storage { +#ifdef HAVE_SA_LEN + u_int8_t ss_len; /* address length */ + u_int8_t ss_family; /* address family */ + char __ss_pad1[__SS_ALLIGSIZE - 2 * sizeof(u_int8_t)]; + long __ss_align; + char __ss_pad2[__SS_MAXSIZE - 2 * __SS_ALLIGSIZE]; +#else + u_int16_t ss_family; /* address family */ + char __ss_pad1[__SS_ALLIGSIZE - sizeof(u_int16_t)]; + long __ss_align; + char __ss_pad2[__SS_MAXSIZE - 2 * __SS_ALLIGSIZE]; +#endif +}; +#endif + + +#if !defined(HAS_INET6_STRUCTS) || defined(NEED_IN6ADDR_ANY) +#define in6addr_any isc_in6addr_any +extern const struct in6_addr in6addr_any; +#endif + +/* + * IN6_ARE_ADDR_EQUAL, IN6_IS_ADDR_UNSPECIFIED, IN6_IS_ADDR_V4COMPAT and + * IN6_IS_ADDR_V4MAPPED are broken in glibc 2.1. + */ +#ifdef __GLIBC__ +#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) +#undef IN6_ARE_ADDR_EQUAL +#undef IN6_IS_ADDR_UNSPECIFIED +#undef IN6_IS_ADDR_V4COMPAT +#undef IN6_IS_ADDR_V4MAPPED +#endif +#endif + +#ifndef IN6_ARE_ADDR_EQUAL +#define IN6_ARE_ADDR_EQUAL(a,b) \ + (memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0) +#endif + +#ifndef IN6_IS_ADDR_UNSPECIFIED +#define IN6_IS_ADDR_UNSPECIFIED(a) \ + IN6_ARE_ADDR_EQUAL(a, &in6addr_any) +#endif + +#ifndef IN6_IS_ADDR_LOOPBACK +extern const struct in6_addr isc_in6addr_loopback; +#define IN6_IS_ADDR_LOOPBACK(a) \ + IN6_ARE_ADDR_EQUAL(a, &isc_in6addr_loopback) +#endif + +#ifndef IN6_IS_ADDR_V4MAPPED +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((a)->s6_addr[0] == 0x00 && (a)->s6_addr[1] == 0x00 && \ + (a)->s6_addr[2] == 0x00 && (a)->s6_addr[3] == 0x00 && \ + (a)->s6_addr[4] == 0x00 && (a)->s6_addr[5] == 0x00 && \ + (a)->s6_addr[6] == 0x00 && (a)->s6_addr[9] == 0x00 && \ + (a)->s6_addr[8] == 0x00 && (a)->s6_addr[9] == 0x00 && \ + (a)->s6_addr[10] == 0xff && (a)->s6_addr[11] == 0xff) +#endif + +#ifndef IN6_IS_ADDR_SITELOCAL +#define IN6_IS_ADDR_SITELOCAL(a) \ + (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0)) +#endif + +#ifndef IN6_IS_ADDR_LINKLOCAL +#define IN6_IS_ADDR_LINKLOCAL(a) \ + (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80)) +#endif + +#ifndef IN6_IS_ADDR_MULTICAST +#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff) +#endif + +#ifndef __IPV6_ADDR_MC_SCOPE +#define __IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f) +#endif + +#ifndef __IPV6_ADDR_SCOPE_SITELOCAL +#define __IPV6_ADDR_SCOPE_SITELOCAL 0x05 +#endif +#ifndef __IPV6_ADDR_SCOPE_ORGLOCAL +#define __IPV6_ADDR_SCOPE_ORGLOCAL 0x08 +#endif + +#ifndef IN6_IS_ADDR_MC_SITELOCAL +#define IN6_IS_ADDR_MC_SITELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL)) +#endif + +#ifndef IN6_IS_ADDR_MC_ORGLOCAL +#define IN6_IS_ADDR_MC_ORGLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) && \ + (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL)) +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +#ifndef INET6_ADDRSTRLEN +/* sizeof("aaaa:bbbb:cccc:dddd:eeee:ffff:123.123.123.123") */ +#define INET6_ADDRSTRLEN 46 +#endif + +#ifndef MIN +#define MIN(x,y) (((x) <= (y)) ? (x) : (y)) +#endif + +#ifndef MAX +#define MAX(x,y) (((x) >= (y)) ? (x) : (y)) +#endif + +#ifdef NEED_DAEMON +int daemon(int nochdir, int noclose); +#endif + +#ifdef NEED_STRSEP +char * strsep(char **stringp, const char *delim); +#endif + +#ifndef ALIGN +#define ALIGN(p) (((uintptr_t)(p) + (sizeof(long) - 1)) & ~(sizeof(long) - 1)) +#endif + +#ifdef NEED_SETGROUPENT +int setgroupent(int stayopen); +#endif + +#ifdef NEED_GETGROUPLIST +int getgrouplist(GETGROUPLIST_ARGS); +#endif + +#ifdef POSIX_GETGRNAM_R +int +__posix_getgrnam_r(const char *, struct group *, char *, int, struct group **); +#endif + +#ifdef NEED_GETGRNAM_R +int +getgrnam_r(const char *, struct group *, char *, size_t, struct group **); +#endif + +#ifdef POSIX_GETGRGID_R +int +__posix_getgrgid_r(gid_t, struct group *, char *, int, struct group **) ; +#endif + +#ifdef NEED_GETGRGID_R +int +getgrgid_r(gid_t, struct group *, char *, size_t, struct group **); +#endif + +#ifdef NEED_GETGRENT_R +GROUP_R_RETURN getgrent_r(struct group *gptr, GROUP_R_ARGS); +#endif + +#ifdef NEED_SETGRENT_R +GROUP_R_SET_RETURN setgrent_r(GROUP_R_ENT_ARGS); +#endif + +#ifdef NEED_ENDGRENT_R +GROUP_R_END_RETURN endgrent_r(GROUP_R_ENT_ARGS); +#endif + +#if defined(NEED_INNETGR_R) && defined(NGR_R_RETURN) +NGR_R_RETURN +innetgr_r(const char *, const char *, const char *, const char *); +#endif + +#ifdef NEED_SETNETGRENT_R +#ifdef NGR_R_SET_ARGS +NGR_R_SET_RETURN setnetgrent_r(NGR_R_SET_CONST char *netgroup, NGR_R_SET_ARGS); +#else +NGR_R_SET_RETURN setnetgrent_r(NGR_R_SET_CONST char *netgroup); +#endif +#endif + +#ifdef NEED_ENDNETGRENT_R +#ifdef NGR_R_END_ARGS +NGR_R_END_RETURN endnetgrent_r(NGR_R_END_ARGS); +#else +NGR_R_END_RETURN endnetgrent_r(void); +#endif +#endif + +#ifdef POSIX_GETPWNAM_R +int +__posix_getpwnam_r(const char *login, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result); +#endif + +#ifdef NEED_GETPWNAM_R +int +getpwnam_r(const char *login, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result); +#endif + +#ifdef POSIX_GETPWUID_R +int +__posix_getpwuid_r(uid_t uid, struct passwd *pwptr, + char *buf, int buflen, struct passwd **result); +#endif + +#ifdef NEED_GETPWUID_R +int +getpwuid_r(uid_t uid, struct passwd *pwptr, + char *buf, size_t buflen, struct passwd **result); +#endif + +#ifdef NEED_SETPWENT_R +#ifdef PASS_R_ENT_ARGS +PASS_R_SET_RETURN setpwent_r(PASS_R_ENT_ARGS); +#else +PASS_R_SET_RETURN setpwent_r(void); +#endif + +#endif + +#ifdef NEED_SETPASSENT_R +#ifdef PASS_R_ENT_ARGS +PASS_R_SET_RETURN setpassent_r(int stayopen, PASS_R_ENT_ARGS); +#else +PASS_R_SET_RETURN setpassent_r(int stayopen); +#endif +#endif + +#ifdef NEED_GETPWENT_R +PASS_R_RETURN getpwent_r(struct passwd *pwptr, PASS_R_ARGS); +#endif + +#ifdef NEED_ENDPWENT_R +void endpwent_r(void); +#endif + +#ifdef NEED_SETPASSENT +int setpassent(int stayopen); +#endif + +#define gettimeofday isc__gettimeofday +#ifdef NEED_GETTIMEOFDAY +int isc__gettimeofday(struct timeval *tvp, struct _TIMEZONE *tzp); +#else +int isc__gettimeofday(struct timeval *tp, struct timezone *tzp); +#endif + +int getnetgrent(NGR_R_CONST char **machinep, NGR_R_CONST char **userp, + NGR_R_CONST char **domainp); + +#ifdef NGR_R_ARGS +int getnetgrent_r(NGR_R_CONST char **machinep, NGR_R_CONST char **userp, + NGR_R_CONST char **domainp, NGR_R_ARGS); +#endif + +/* setnetgrent and endnetgrent are defined in sunw_port_after.h +#ifdef SETNETGRENT_ARGS +void setnetgrent(SETNETGRENT_ARGS); +#else +void setnetgrent(const char *netgroup); +#endif + +void endnetgrent(void); +*/ + +#ifdef INNETGR_ARGS +int innetgr(INNETGR_ARGS); +#else +int innetgr(const char *netgroup, const char *machine, + const char *user, const char *domain); +#endif + +#ifdef NGR_R_SET_ARGS +NGR_R_SET_RETURN +setnetgrent_r(NGR_R_SET_CONST char *netgroup, NGR_R_SET_ARGS); +#else +NGR_R_SET_RETURN +setnetgrent_r(NGR_R_SET_CONST char *netgroup); +#endif + +#ifdef NEED_STRTOUL +unsigned long strtoul(const char *, char **, int); +#endif + +#ifdef NEED_SUN4PROTOS +#include <stdarg.h> +#ifndef __SIZE_TYPE__ +#define __SIZE_TYPE__ int +#endif +struct sockaddr; +struct iovec; +struct timeval; +struct timezone; +int fprintf(FILE *, const char *, ...); +int getsockname(int, struct sockaddr *, int *); +int getpeername(int, struct sockaddr *, int *); +int socket(int, int, int); +int connect(int, const struct sockaddr *, int); +int writev(int, struct iovec *, int); +int readv(int, struct iovec *, int); +int send(int, const char *, int, int); +void bzero(char *, int); +int recvfrom(int, char *, int, int, struct sockaddr *, int *); +int syslog(int, const char *, ... ); +int printf(const char *, ...); +__SIZE_TYPE__ fread(void *, __SIZE_TYPE__, __SIZE_TYPE__, FILE *); +__SIZE_TYPE__ fwrite(const void *, __SIZE_TYPE__, __SIZE_TYPE__, FILE *); +int fclose(FILE *); +int ungetc(int, FILE *); +int scanf(const char *, ...); +int sscanf(const char *, const char *, ... ); +int tolower(int); +int toupper(int); +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, int); +int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); +#ifdef gettimeofday +#undef gettimeofday +int gettimeofday(struct timeval *, struct timezone *); +#define gettimeofday isc__gettimeofday +#else +int gettimeofday(struct timeval *, struct timezone *); +#endif +long strtol(const char*, char **, int); +int fseek(FILE *, long, int); +int setsockopt(int, int, int, const char *, int); +int bind(int, const struct sockaddr *, int); +void bcopy(char *, char *, int); +int fputc(char, FILE *); +int listen(int, int); +int accept(int, struct sockaddr *, int *); +int getsockopt(int, int, int, char *, int *); +int vfprintf(FILE *, const char *, va_list); +int fflush(FILE *); +int fgetc(FILE *); +int fputs(const char *, FILE *); +int fchown(int, int, int); +void setbuf(FILE *, char *); +int gethostname(char *, int); +int rename(const char *, const char *); +time_t time(time_t *); +int fscanf(FILE *, const char *, ...); +int sscanf(const char *, const char *, ...); +int ioctl(int, int, caddr_t); +void perror(const char *); + +#if !defined(__USE_FIXED_PROTOTYPES__) && !defined(__cplusplus) && !defined(__STRICT_ANSI__) +/* + * 'gcc -ansi' changes the prototype for vsprintf(). + * Use this prototype when 'gcc -ansi' is not in effect. + */ +char *vsprintf(char *, const char *, va_list); +#endif +#endif + +/* Solaris-specific changes */ +#include "sunw_port_after.h" + +#endif /* port_after_h */ diff --git a/usr/src/lib/libresolv2_joy/include/port_before.h b/usr/src/lib/libresolv2_joy/include/port_before.h new file mode 100644 index 0000000000..2801139223 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/port_before.h @@ -0,0 +1,201 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Copyright (C) 2005-2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: port_before.h.in,v 1.31 2008/02/28 05:36:10 marka Exp $ */ + +#ifndef port_before_h +#define port_before_h +/* Solaris-specific changes */ +#include "sunw_port_before.h" +#include <config.h> + +#ifdef NEED_SUN4PROTOS +#define _PARAMS(x) x +#endif + +struct group; /* silence warning */ +struct passwd; /* silence warning */ +struct timeval; /* silence warning */ +struct timezone; /* silence warning */ + +#ifdef HAVE_SYS_TIMERS_H +#include <sys/timers.h> +#endif +#include <limits.h> + +#ifdef ISC_PLATFORM_NEEDTIMESPEC +#include <time.h> /* For time_t */ +struct timespec { + time_t tv_sec; /* seconds */ + long tv_nsec; /* nanoseconds */ +}; +#endif +#ifndef HAVE_MEMMOVE +#define memmove(a,b,c) bcopy(b,a,c) +#endif + +#undef WANT_IRS_GR +#undef WANT_IRS_NIS +#undef WANT_IRS_PW + +#define BSD_COMP 1 +#define USE_POLL 1 +#define HAVE_MD5 1 +#define SOLARIS2 1 + +/* DO_PTHREADS is conditionally defined in sunw_port_before.h + * #define DO_PTHREADS 1 */ +#define GETGROUPLIST_ARGS const char *name, gid_t basegid, gid_t *groups, int *ngroups +#define GETNETBYADDR_ADDR_T long +#define SETPWENT_VOID 1 +#define SETGRENT_VOID 1 + +#define NET_R_ARGS char *buf, int buflen +#define NET_R_BAD NULL +#define NET_R_COPY buf, buflen +#define NET_R_COPY_ARGS NET_R_ARGS +#define NET_R_END_RESULT(x) /*empty*/ +#define NET_R_END_RETURN void +#undef NET_R_ENT_ARGS /*empty*/ +#define NET_R_OK nptr +#define NET_R_RETURN struct netent * +#undef NET_R_SET_RESULT /*empty*/ +#undef NET_R_SETANSWER +#define NET_R_SET_RETURN void +#undef NETENT_DATA + +#define GROUP_R_RETURN struct group * +#define GROUP_R_SET_RETURN void +#undef GROUP_R_SET_RESULT /*empty*/ +#define GROUP_R_END_RETURN void +#define GROUP_R_END_RESULT(x) /*empty*/ +#define GROUP_R_ARGS char *buf, int buflen +#define GROUP_R_ENT_ARGS void +#define GROUP_R_OK gptr +#define GROUP_R_BAD NULL + +#define HOST_R_ARGS char *buf, int buflen, int *h_errnop +#define HOST_R_BAD NULL +#define HOST_R_COPY buf, buflen +#define HOST_R_COPY_ARGS char *buf, int buflen +#define HOST_R_END_RESULT(x) /*empty*/ +#define HOST_R_END_RETURN void +#undef HOST_R_ENT_ARGS /*empty*/ +#define HOST_R_ERRNO *h_errnop = h_errno +#define HOST_R_OK hptr +#define HOST_R_RETURN struct hostent * +#undef HOST_R_SETANSWER +#undef HOST_R_SET_RESULT +#define HOST_R_SET_RETURN void +#undef HOSTENT_DATA + +#define NGR_R_ARGS char *buf, int buflen +#define NGR_R_BAD (0) +#define NGR_R_COPY buf, buflen +#define NGR_R_COPY_ARGS NGR_R_ARGS +#define NGR_R_CONST +#define NGR_R_END_RESULT(x) /*empty*/ +#define NGR_R_END_RETURN void +#undef NGR_R_END_ARGS /*empty*/ +#define NGR_R_OK 1 +#define NGR_R_RETURN int +#define NGR_R_SET_CONST const +#undef NGR_R_SET_RESULT /*empty*/ +#define NGR_R_SET_RETURN void +#undef NGR_R_SET_ARGS + + +#if !defined(NGR_R_SET_ARGS) && defined(NGR_R_END_ARGS) +#define NGR_R_SET_ARGS NGR_R_END_ARGS +#endif + +#define PROTO_R_ARGS char *buf, int buflen +#define PROTO_R_BAD NULL +#define PROTO_R_COPY buf, buflen +#define PROTO_R_COPY_ARGS PROTO_R_ARGS +#define PROTO_R_END_RESULT(x) /*empty*/ +#define PROTO_R_END_RETURN void +#undef PROTO_R_ENT_ARGS /*empty*/ +#undef PROTO_R_ENT_UNUSED +#define PROTO_R_OK pptr +#undef PROTO_R_SETANSWER +#define PROTO_R_RETURN struct protoent * +#undef PROTO_R_SET_RESULT +#define PROTO_R_SET_RETURN void +#undef PROTOENT_DATA + +#define PASS_R_ARGS char *buf, int buflen +#define PASS_R_BAD NULL +#define PASS_R_COPY buf, buflen +#define PASS_R_COPY_ARGS PASS_R_ARGS +#define PASS_R_END_RESULT(x) /*empty*/ +#define PASS_R_END_RETURN void +#undef PASS_R_ENT_ARGS +#define PASS_R_OK pwptr +#define PASS_R_RETURN struct passwd * +#undef PASS_R_SET_RESULT /*empty*/ +#define PASS_R_SET_RETURN void + +#define SERV_R_ARGS char *buf, int buflen +#define SERV_R_BAD NULL +#define SERV_R_COPY buf, buflen +#define SERV_R_COPY_ARGS SERV_R_ARGS +#define SERV_R_END_RESULT(x) /*empty*/ +#define SERV_R_END_RETURN void +#undef SERV_R_ENT_ARGS /*empty*/ +#undef SERV_R_ENT_UNUSED /*empty*/ +#define SERV_R_OK sptr +#undef SERV_R_SETANSWER +#define SERV_R_RETURN struct servent * +#undef SERV_R_SET_RESULT +#define SERV_R_SET_RETURN void + + + +#define DE_CONST(konst, var) \ + do { \ + union { const void *k; void *v; } _u; \ + _u.k = konst; \ + var = _u.v; \ + } while (0) + +#define UNUSED(x) (x) = (x) + +#undef NEED_SOLARIS_BITTYPES +#define ISC_SOCKLEN_T int + +#ifdef __GNUC__ +#define ISC_FORMAT_PRINTF(fmt, args) \ + __attribute__((__format__(__printf__, fmt, args))) +#else +#define ISC_FORMAT_PRINTF(fmt, args) +#endif + +/* Pull in host order macros when _XOPEN_SOURCE_EXTENDED is defined. */ +#if defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED) +#include <sys/byteorder.h> +#endif + +#endif + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/port_netdb.h b/usr/src/lib/libresolv2_joy/include/port_netdb.h new file mode 100644 index 0000000000..a308cc7efa --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/port_netdb.h @@ -0,0 +1,188 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#ifndef _PORT_NETDB_H +#define _PORT_NETDB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* AI_NUMERICSERV is not a valid flag for getaddrinfo */ +#define AI_MASK 0x0038 /* mask of valid flags */ + +/* EAI_OVERFLOW was removed from ISC */ +#define EAI_BADHINTS 12 + +/* + * these are libresolv2 functions that were renamed in previous versions to + * res_* because they conflict with libnsl or libsocket + */ + +#define endhostent joy_res_endhostent /* libnsl */ +void endhostent __P((void)); +#define endnetent res_endnetent /* libsocket */ +void endnetent __P((void)); +#define freeaddrinfo res_freeaddrinfo /* libsocket */ +void freeaddrinfo __P((struct addrinfo *)); +#define freehostent res_freehostent /* libsocket and libnsl */ +void freehostent __P((struct hostent *)); +#define getaddrinfo res_getaddrinfo /* libsocket */ +int getaddrinfo __P((const char *, const char *, + const struct addrinfo *, struct addrinfo **)); +#define gethostbyaddr joy_res_gethostbyaddr /* libnsl */ +struct hostent *gethostbyaddr __P((const char *, int, int)); +#define gethostbyname joy_res_gethostbyname /* libnsl */ +struct hostent *gethostbyname __P((const char *)); +#define gethostbyname2 joy_res_gethostbyname2 /* lib/nsswitch/dns */ +struct hostent *gethostbyname2 __P((const char *, int)); +#define gethostent res_gethostent /* libnsl */ +struct hostent *gethostent __P((void)); +#define getipnodebyaddr res_getipnodebyaddr /* libnsl and libsocket */ +struct hostent *getipnodebyaddr __P((const void *, size_t, int, int *)); +#define getipnodebyname res_getipnodebyname /* libnsl and libsocket */ +struct hostent *getipnodebyname __P((const char *, int, int, int *)); + +#define getnetbyaddr res_getnetbyaddr /* libsocket */ +struct netent *getnetbyaddr __P((unsigned long, int)); +#define getnetbyname res_getnetbyname /* libsocket */ +struct netent *getnetbyname __P((const char *)); +#define getnetent res_getnetent /* libsocket */ +struct netent *getnetent __P((void)); +#define sethostent joy_res_sethostent /* libnsl */ +void sethostent __P((int)); +#define setnetent res_setnetent /* libsocket */ +void setnetent __P((int)); + +/* + * these are other irs functions now included in libresolv.so.2. We rename the + * ones that overlap with libsocket or libnsl + */ + +/* endprotoent is in libsocket.so.1 */ +#define endprotoent res_endprotoent +void endprotoent __P((void)); + +/* endservent is in libsocket.so.1 */ +#define endservent res_endservent +void endservent __P((void)); + +/* note: the next two symbols are variables, not functions */ + +/* gai_errlist is in libsocket.so.1 */ +#define gai_errlist res_gai_errlist + +/* gai_nerr is in libsocket.so.1 */ +#define gai_nerr res_gai_nerr + +/* gai_strerror is in libsocket.so.1 */ +#define gai_strerror res_gai_strerror +const char *gai_strerror __P((int ecode)); + +/* gethostbyaddr_r is in libnsl.so.1 */ +#define gethostbyaddr_r res_gethostbyaddr_r +struct hostent *gethostbyaddr_r __P((const char *addr, int len, int type, + struct hostent *hptr, char *buf, + int buflen, int *h_errnop)); + +/* gethostbyname_r is in libnsl.so.1 */ +#define gethostbyname_r res_gethostbyname_r +struct hostent *gethostbyname_r __P((const char *name, struct hostent *hptr, + char *buf, int buflen, int *h_errnop)); + +/* gethostent_r is in libnsl.so.1 */ +#define gethostent_r res_gethostent_r +struct hostent *gethostent_r __P((struct hostent *hptr, char *buf, int buflen, + int *h_errnop)); + +/* getnameinfo is in libsocket.so.1 */ +#define getnameinfo res_getnameinfo +int getnameinfo __P((const struct sockaddr *, size_t, char *, + size_t, char *, size_t, int)); + +/* getnetbyaddr_r is in libsocket.so.1 */ +#define getnetbyaddr_r res_getnetbyaddr_r +struct netent *getnetbyaddr_r __P((long, int, struct netent *, char *, int)); + +/* getnetbyname_r is in libsocket.so.1 */ +#define getnetbyname_r res_getnetbyname_r +struct netent *getnetbyname_r __P((const char *, struct netent *, char *, int)); + +/* getnetent_r is in libsocket.so.1 */ +#define getnetent_r res_getnetent_r +struct netent *getnetent_r __P((struct netent *, char *, int)); + +/* getprotobyname is in libsocket.so.1 */ +#define getprotobyname res_getprotobyname +struct protoent *getprotobyname __P((const char *)); + +/* getprotobyname_r is in libsocket.so.1 */ +#define getprotobyname_r res_getprotobyname_r +struct protoent *getprotobyname_r __P((const char *, struct protoent *, + char *, int)); + +/* getprotobynumber is in libsocket.so.1 */ +#define getprotobynumber res_getprotobynumber +struct protoent *getprotobynumber __P((int)); + +/* getprotobynumber_r is in libsocket.so.1 */ +#define getprotobynumber_r res_getprotobynumber_r +struct protoent *getprotobynumber_r __P((int, + struct protoent *, char *, int)); + +/* getprotoent is in libsocket.so.1 */ +#define getprotoent res_getprotoent +struct protoent *getprotoent __P((void)); + +/* getprotoent_r is in libsocket.so.1 */ +#define getprotoent_r res_getprotoent_r +struct protoent *getprotoent_r __P((struct protoent *, char *, int)); + +/* getservbyname is in libsocket.so.1 and libnsl.so.1 */ +#define getservbyname res_getservbyname +struct servent *getservbyname __P((const char *, const char *)); + +/* getservbyname_r is in libsocket.so.1 and libnsl.so.1 */ +#define getservbyname_r res_getservbyname_r +struct servent *getservbyname_r __P((const char *name, const char *, + struct servent *, char *, int)); + +/* getservbyport is in libsocket.so.1 and libnsl.so.1 */ +#define getservbyport res_getservbyport +struct servent *getservbyport __P((int, const char *)); + +/* getservbyport_r is in libsocket.so.1 and libnsl.so.1 */ +#define getservbyport_r res_getservbyport_r +struct servent *getservbyport_r __P((int port, const char *, + struct servent *, char *, int)); + +/* getservent is in libsocket.so.1 */ +#define getservent res_getservent +struct servent *getservent __P((void)); + +/* getservent_r is in libsocket.so.1 */ +#define getservent_r res_getservent_r +struct servent *getservent_r __P((struct servent *, char *, int)); + +/* innetgr is in libsocket.so.1 */ +#define innetgr res_innetgr +int innetgr __P((const char *, const char *, const char *, const char *)); + +/* setprotoent is in libsocket.so.1 */ +#define setprotoent res_setprotoent +void setprotoent __P((int)); + +/* setservent is in libsocket.so.1 */ +#define setservent res_setservent +void setservent __P((int)); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _PORT_NETDB_H */ diff --git a/usr/src/lib/libresolv2_joy/include/port_resolv.h b/usr/src/lib/libresolv2_joy/include/port_resolv.h new file mode 100644 index 0000000000..cd1a97d40c --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/port_resolv.h @@ -0,0 +1,42 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _PORT_RESOLV_H +#define _PORT_RESOLV_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* RES_NSID has the same value as RES_NO_NIBBLE, which has been deleted */ +#define RES_NSID 0x00040000 /* request name server ID */ + +/* RES_DEFAULT has a new value in libbind-6.0 */ +#undef RES_DEFAULT +#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | \ + RES_DNSRCH | RES_NO_NIBBLE2) + +#ifndef __ultrix__ +u_int16_t _getshort __P((const uchar_t *)); +u_int32_t _getlong __P((const uchar_t *)); +#endif + +/* rename functions so they can be wrapped (see sunw/sunw_wrappers.c */ +#define p_option isc_p_option +const char *p_option(ulong_t option); +#define p_secstodate isc_p_secstodate +char *p_secstodate(ulong_t secs); + +/* prevent namespace pollution */ +#define res_protocolnumber __res_protocolnumber +#define res_servicenumber __res_servicenumber + + + +#ifdef __cplusplus +} +#endif + +#endif /* _PORT_RESOLV_H */ diff --git a/usr/src/lib/libresolv2_joy/include/probe_ipv6 b/usr/src/lib/libresolv2_joy/include/probe_ipv6 new file mode 100755 index 0000000000..371ac96c55 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/probe_ipv6 @@ -0,0 +1,73 @@ +#!/bin/sh + +# Copyright 2003 by Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" + +set -e +PATH=/bin:/usr/bin:$PATH; export PATH +trap "rm -f tmp$$[abc].[oc]" 0 +target=port_ipv6 +new=new_${target}.h +old=${target}.h + +cat > tmp$$a.c <<EOF +#include <sys/types.h> +#include <netinet/in.h> +struct sockaddr_in6 xx; +EOF + +cat > tmp$$b.c <<EOF +#include <sys/types.h> +#include <netinet/in.h> +struct in6_addr xx; +EOF + +cat > tmp$$c.c <<EOF +#include <sys/types.h> +#include <netinet/in.h> +struct sockaddr_in6 xx; +main() { xx.sin6_scope_id = 0; } +EOF + +cat > ${new} <<EOF + +/* This file is automatically generated. Do Not Edit. */ + +#ifndef ${target}_h +#define ${target}_h + +EOF + +if ${CC} -c tmp$$a.c > /dev/null 2>&1 +then + echo "#define HAS_INET6_STRUCTS" >> ${new} + if ${CC} -c tmp$$b.c > /dev/null 2>&1 + then + : + else + echo "#define in6_addr in_addr6" >> ${new} + fi + if ${CC} -c tmp$$c.c > /dev/null 2>&1 + then + echo "#define HAVE_SIN6_SCOPE_ID" >> ${new} + else + echo "#undef HAVE_SIN6_SCOPE_ID" >> ${new} + fi +else + echo "#undef HAS_INET6_STRUCTS" >> ${new} +fi +echo >> ${new} +echo "#endif" >> ${new} +if [ -f ${old} ]; then + if cmp -s ${new} ${old} ; then + rm -f ${new} + else + rm -f ${old} + mv ${new} ${old} + fi +else + mv ${new} ${old} +fi +exit 0 diff --git a/usr/src/lib/libresolv2_joy/include/probe_ipv6.sh b/usr/src/lib/libresolv2_joy/include/probe_ipv6.sh new file mode 100644 index 0000000000..371ac96c55 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/probe_ipv6.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# Copyright 2003 by Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#pragma ident "%Z%%M% %I% %E% SMI" + +set -e +PATH=/bin:/usr/bin:$PATH; export PATH +trap "rm -f tmp$$[abc].[oc]" 0 +target=port_ipv6 +new=new_${target}.h +old=${target}.h + +cat > tmp$$a.c <<EOF +#include <sys/types.h> +#include <netinet/in.h> +struct sockaddr_in6 xx; +EOF + +cat > tmp$$b.c <<EOF +#include <sys/types.h> +#include <netinet/in.h> +struct in6_addr xx; +EOF + +cat > tmp$$c.c <<EOF +#include <sys/types.h> +#include <netinet/in.h> +struct sockaddr_in6 xx; +main() { xx.sin6_scope_id = 0; } +EOF + +cat > ${new} <<EOF + +/* This file is automatically generated. Do Not Edit. */ + +#ifndef ${target}_h +#define ${target}_h + +EOF + +if ${CC} -c tmp$$a.c > /dev/null 2>&1 +then + echo "#define HAS_INET6_STRUCTS" >> ${new} + if ${CC} -c tmp$$b.c > /dev/null 2>&1 + then + : + else + echo "#define in6_addr in_addr6" >> ${new} + fi + if ${CC} -c tmp$$c.c > /dev/null 2>&1 + then + echo "#define HAVE_SIN6_SCOPE_ID" >> ${new} + else + echo "#undef HAVE_SIN6_SCOPE_ID" >> ${new} + fi +else + echo "#undef HAS_INET6_STRUCTS" >> ${new} +fi +echo >> ${new} +echo "#endif" >> ${new} +if [ -f ${old} ]; then + if cmp -s ${new} ${old} ; then + rm -f ${new} + else + rm -f ${old} + mv ${new} ${old} + fi +else + mv ${new} ${old} +fi +exit 0 diff --git a/usr/src/lib/libresolv2_joy/include/res_update.h b/usr/src/lib/libresolv2_joy/include/res_update.h new file mode 100644 index 0000000000..0c6967db56 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/res_update.h @@ -0,0 +1,88 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1999 by Internet Software Consortium, Inc. + * + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* + * $Id: res_update.h,v 1.3 2005/04/27 04:56:15 sra Exp $ + */ + +#ifndef __RES_UPDATE_H +#define __RES_UPDATE_H + +/*! \file */ + +#include <sys/types.h> +#include <arpa/nameser.h> +#include <isc/list.h> +#include <resolv_joy.h> + +#ifndef ORIGINAL_ISC_CODE +/* definition of u_int32_t needed on Solaris */ +#include <sys/bitypes.h> +/* need to rename ns_updrec before we define it here */ +#include "arpa/port_nameser.h" +#endif /* ORIGINAL_ISC_CODE */ + + +/*% + * This RR-like structure is particular to UPDATE. + */ +struct ns_updrec { + LINK(struct ns_updrec) r_link, r_glink; + ns_sect r_section; /*%< ZONE/PREREQUISITE/UPDATE */ + char * r_dname; /*%< owner of the RR */ + ns_class r_class; /*%< class number */ + ns_type r_type; /*%< type number */ + u_int32_t r_ttl; /*%< time to live */ + u_char * r_data; /*%< rdata fields as text string */ + u_int r_size; /*%< size of r_data field */ + int r_opcode; /*%< type of operation */ + /* following fields for private use by the resolver/server routines */ + struct databuf *r_dp; /*%< databuf to process */ + struct databuf *r_deldp; /*%< databuf's deleted/overwritten */ + u_int r_zone; /*%< zone number on server */ +}; +typedef struct ns_updrec ns_updrec; +typedef LIST(ns_updrec) ns_updque; + +#ifdef ORIGINAL_ISC_CODE +#define res_mkupdate __res_mkupdate +#define res_update __res_update +#define res_mkupdrec __res_mkupdrec +#define res_freeupdrec __res_freeupdrec +#define res_nmkupdate __res_nmkupdate +#define res_nupdate __res_nupdate +#else +/* these are renamed in "port_nameser.h" */ +#endif /* ORIGINAL_ISC_CODE */ + + +int res_mkupdate __P((ns_updrec *, u_char *, int)); +int res_update __P((ns_updrec *)); +ns_updrec * res_mkupdrec __P((int, const char *, u_int, u_int, u_long)); +void res_freeupdrec __P((ns_updrec *)); +int res_nmkupdate __P((res_state, ns_updrec *, u_char *, int)); +int res_nupdate __P((res_state, ns_updrec *, ns_tsig_key *)); + +#endif /*__RES_UPDATE_H*/ + +/*! \file */ diff --git a/usr/src/lib/libresolv2_joy/include/resolv_mt.h b/usr/src/lib/libresolv2_joy/include/resolv_mt.h new file mode 100644 index 0000000000..500d4d764c --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/resolv_mt.h @@ -0,0 +1,47 @@ +#ifndef _RESOLV_MT_H +#define _RESOLV_MT_H + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv_joy.h> + +/* Access functions for the libresolv private interface */ + +int __res_enable_mt(void); +int __res_disable_mt(void); + +/* Per-thread context */ + +typedef struct { +int no_hosts_fallback_private; +int retry_save; +int retry_private; +char inet_nsap_ntoa_tmpbuf[255*3]; +char sym_ntos_unname[20]; +char sym_ntop_unname[20]; +char p_option_nbuf[40]; +char p_time_nbuf[40]; +char precsize_ntoa_retbuf[sizeof "90000000.00"]; +char loc_ntoa_tmpbuf[sizeof +"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"]; +char p_secstodate_output[15]; +} mtctxres_t; + +/* Thread-specific data (TSD) */ + +mtctxres_t *___mtctxres(void); +#define mtctxres (___mtctxres()) + +/* Various static data that should be TSD */ + +#define sym_ntos_unname (mtctxres->sym_ntos_unname) +#define sym_ntop_unname (mtctxres->sym_ntop_unname) +#define inet_nsap_ntoa_tmpbuf (mtctxres->inet_nsap_ntoa_tmpbuf) +#define p_option_nbuf (mtctxres->p_option_nbuf) +#define p_time_nbuf (mtctxres->p_time_nbuf) +#define precsize_ntoa_retbuf (mtctxres->precsize_ntoa_retbuf) +#define loc_ntoa_tmpbuf (mtctxres->loc_ntoa_tmpbuf) +#define p_secstodate_output (mtctxres->p_secstodate_output) + +#endif /* _RESOLV_MT_H */ diff --git a/usr/src/lib/libresolv2_joy/include/sunw_port_after.h b/usr/src/lib/libresolv2_joy/include/sunw_port_after.h new file mode 100644 index 0000000000..bff64a74c1 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/sunw_port_after.h @@ -0,0 +1,123 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SUNW_PORT_AFTER_H +#define _SUNW_PORT_AFTER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * rename setnetgrent and endnetgrent which were formerly in a separate irs + * shared library. These functions should come from libc.so + */ +#define setnetgrent res_setnetgrent +#ifdef SETNETGRENT_ARGS +void setnetgrent(SETNETGRENT_ARGS); +#else +void setnetgrent(const char *netgroup); +#endif + +#define endnetgrent res_endnetgrent +void endnetgrent(void); + + +/* + * include ports for the public header files. ISC's versions are quite different + * from those currently in OpenSolaris. + */ + +#ifdef _RESOLV_JOY_H +#include <port_resolv.h> +#endif /* _RESOLV_JOY_H */ + +#ifdef _NETDB_H +#include <port_netdb.h> +#endif /* _NETDB_H */ + +#ifdef _ARPA_INET_H +#include <arpa/port_inet.h> +#endif /* _ARPA_INET_H */ + +#ifdef _ARPA_NAMESER_H +#include <arpa/port_nameser.h> +#endif /* _ARPA_NAMESER_H */ + + +#ifdef _ARPA_NAMESER_COMPAT_H +/* no changes */ +#endif /* _ARPA_NAMESER_COMPAT_H */ + +/* version-specific defines */ +#include <os_version.h> + +/* + * Prior to 2.6, Solaris needs a prototype for gethostname(). + */ +#if (OS_MAJOR == 5 && OS_MINOR < 6) +extern int gethostname(char *, size_t); +#endif +/* + * gethostid() was not available until 2.5 + * setsockopt(SO_REUSEADDR) fails on unix domain sockets before 2.5 + * use ioctl(FIONBIO) rather than fcntl() calls to set/clear non-blocking i/o. + */ +#if (OS_MAJOR == 5 && OS_MINOR < 5) +#define GET_HOST_ID_MISSING +#define NO_UNIX_REUSEADDR +#define USE_FIONBIO_IOCTL +#endif + +#if (OS_MAJOR == 5 && OS_MINOR < 11) +#define NEED_STRSEP +extern char *strsep(char **, const char *); +#endif + + +/* + * Solaris 2.5 and later have getrlimit(), setrlimit() and getrusage(). + */ +#if (OS_MAJOR > 5 || (OS_MAJOR == 5 && OS_MINOR >= 5)) +#include <sys/resource.h> +#define HAVE_GETRUSAGE +#define RLIMIT_TYPE rlim_t +#define RLIMIT_FILE_INFINITY +#endif + +/* the default syslog facility of named/lwresd. */ +#ifndef ISC_FACILITY +#define ISC_FACILITY LOG_DAEMON +#endif + + +/* + * Solaris 8 has if_nametoindex(). + */ +#if (OS_MAJOR > 5 || (OS_MAJOR == 5 && OS_MINOR >= 8)) +#define USE_IFNAMELINKID +#endif + +#undef ALIGN +#if (OS_MAJOR == 5 && OS_MINOR > 8) +#define ALIGN(x) (((uintptr_t)(x) + (sizeof (char *) - 1UL)) & \ + ~(sizeof (char *) - 1UL)) +#else +#define ALIGN(x) (((unsigned long)(x) + (sizeof (char *) - 1UL)) & \ + ~(sizeof (char *) - 1UL)) +#endif + +#if (OS_MAJOR == 5 && OS_MINOR < 5) +#ifndef USE_FIONBIO_IOCTL +#define USE_FIONBIO_IOCTL 1 +#endif +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _SUNW_PORT_AFTER_H */ diff --git a/usr/src/lib/libresolv2_joy/include/sunw_port_before.h b/usr/src/lib/libresolv2_joy/include/sunw_port_before.h new file mode 100644 index 0000000000..776e311fcc --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/sunw_port_before.h @@ -0,0 +1,43 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _SUNW_PORT_BEFORE_H +#define _SUNW_PORT_BEFORE_H + +#ifdef SUNW_OPTIONS +#include <conf/sunoptions.h> +#endif + +/* version-specific defines */ +#include <os_version.h> +#if (OS_MAJOR == 5 && OS_MINOR < 6) +#ifndef SOLARIS_BITTYPES +#define NEED_SOLARIS_BITTYPES 1 +#endif +#endif + +#if (OS_MAJOR == 5 && OS_MINOR < 5) +#undef HAS_PTHREADS +#else +#define HAS_PTHREADS +#endif + +#if defined(HAS_PTHREADS) && defined(_REENTRANT) +#define DO_PTHREADS +#endif + +/* + * need these if we are using public versions of nameser.h, resolv.h, and + * inet.h + */ +#include <sys/param.h> +#if (!defined(BSD)) || (BSD < 199306) +#include <sys/bitypes.h> +#else +#include <sys/types.h> +#endif +#include <sys/cdefs.h> + +#endif /* _SUNW_PORT_BEFORE_H */ diff --git a/usr/src/lib/libresolv2_joy/include/sys/bitypes.h b/usr/src/lib/libresolv2_joy/include/sys/bitypes.h new file mode 100644 index 0000000000..54fb42bad7 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/sys/bitypes.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2004, 2007, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1998, 1999, 2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* $Id: bitypes.h,v 1.7 2008/11/14 02:54:35 tbox Exp $ */ + +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ + + /* + * Basic integral types. Omit the typedef if + * not possible for a machine/compiler combination. + */ + +#ifdef NEED_SOLARIS_BITTYPES + typedef /*signed*/ char int8_t; + typedef short int16_t; + typedef int int32_t; +#endif + typedef unsigned char u_int8_t; + typedef unsigned short u_int16_t; + typedef unsigned int u_int32_t; + +#endif /* __BIT_TYPES_DEFINED__ */ diff --git a/usr/src/lib/libresolv2_joy/include/sys/cdefs.h b/usr/src/lib/libresolv2_joy/include/sys/cdefs.h new file mode 100644 index 0000000000..67aac00cc7 --- /dev/null +++ b/usr/src/lib/libresolv2_joy/include/sys/cdefs.h @@ -0,0 +1,144 @@ +/* + * ++Copyright++ 1991, 1993 + * - + * Copyright (c) 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. + * - + * 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-- + */ + +/* + * @(#)cdefs.h 8.1 (Berkeley) 6/2/93 + * $Id: cdefs.h,v 1.2 2004/07/19 05:54:07 marka Exp $ + */ + +#ifndef _CDEFS_H_ +#define _CDEFS_H_ + +#if defined(__cplusplus) +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS }; +#else +#define __BEGIN_DECLS +#define __END_DECLS +#endif + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky -- make sure you don't put spaces + * in between its arguments. __CONCAT can also concatenate double-quoted + * strings produced by the __STRING macro, but this only works with ANSI C. + */ +#if defined(__STDC__) || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +#define __const const /* define reserved names to standard */ +#define __signed signed +#define __volatile volatile +#if defined(__cplusplus) +#define __inline inline /* convert to C++ keyword */ +#else +#ifndef __GNUC__ +#define __inline /* delete GCC keyword */ +#endif /* !__GNUC__ */ +#endif /* !__cplusplus */ + +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#define __CONCAT(x,y) x/**/y +#define __STRING(x) "x" + +#ifndef __GNUC__ +#define __const /* delete pseudo-ANSI C keywords */ +#define __inline +#define __signed +#define __volatile +/* + * In non-ANSI C environments, new programs will want ANSI-only C keywords + * deleted from the program and old programs will want them left alone. + * When using a compiler other than gcc, programs using the ANSI C keywords + * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS. + * When using "gcc -traditional", we assume that this is the intent; if + * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone. + */ +#ifndef NO_ANSI_KEYWORDS +#define const /* delete ANSI C keywords */ +#define inline +#define signed +#define volatile +#endif +#endif /* !__GNUC__ */ +#endif /* !(__STDC__ || __cplusplus) */ + +/* + * GCC1 and some versions of GCC2 declare dead (non-returning) and + * pure (no side effects) functions using "volatile" and "const"; + * unfortunately, these then cause warnings under "-ansi -pedantic". + * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of + * these work for GNU C++ (modulo a slight glitch in the C++ grammar + * in the distribution version of 2.5.5). + */ +#if !defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#define __dead __volatile +#define __pure __const +#endif +#endif + +/* Delete pseudo-keywords wherever they are not available or needed. */ +#ifndef __dead +#define __dead +#define __pure +#endif + +#endif /* !_CDEFS_H_ */ diff --git a/usr/src/lib/print/libipp-core/i386/Makefile b/usr/src/lib/libresolv2_joy/sparc/Makefile index 3b985583a4..a333224278 100644 --- a/usr/src/lib/print/libipp-core/i386/Makefile +++ b/usr/src/lib/libresolv2_joy/sparc/Makefile @@ -27,4 +27,4 @@ include ../Makefile.com -install: all $(ROOTLIBS) $(ROOTLINKS) # $(ROOTLINT) +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libresolv2_joy/sparcv9/Makefile b/usr/src/lib/libresolv2_joy/sparcv9/Makefile new file mode 100644 index 0000000000..ceed393e0d --- /dev/null +++ b/usr/src/lib/libresolv2_joy/sparcv9/Makefile @@ -0,0 +1,38 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +# With the adition of BIND 8.3.3, the symbol table for 64 bit went over +# the limit for Kpic, so we've added -KPIC here, for just the 64 bit +# library. This avoids compiling the 32-bit library with PIC unnecessarily. + +sparcv9_C_PICFLAGS = -K PIC +sparcv9_CC_PICFLAGS = -KPIC + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libscf/inc/libscf.h b/usr/src/lib/libscf/inc/libscf.h index 8e68b4dfcc..232fc205e0 100644 --- a/usr/src/lib/libscf/inc/libscf.h +++ b/usr/src/lib/libscf/inc/libscf.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #ifndef _LIBSCF_H @@ -831,8 +832,13 @@ int smf_notify_del_params(const char *, const char *, int32_t); /* * SMF exit status definitions + * + * The SMF_EXIT_NODAEMON exit status should be used when a method does not + * need to run any persistent process. This indicates success, abandons the + * contract, and allows dependencies to be met. */ #define SMF_EXIT_OK 0 +#define SMF_EXIT_NODAEMON 94 #define SMF_EXIT_ERR_FATAL 95 #define SMF_EXIT_ERR_CONFIG 96 #define SMF_EXIT_MON_DEGRADE 97 diff --git a/usr/src/lib/libshare/Makefile.com b/usr/src/lib/libshare/Makefile.com index 7e3c902a5e..b5f057d694 100644 --- a/usr/src/lib/libshare/Makefile.com +++ b/usr/src/lib/libshare/Makefile.com @@ -42,6 +42,8 @@ $(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) #add nfs/lib directory as part of the include path CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -I$(NFSLIB_DIR) \ + -I$(ADJUNCT_PROTO)/usr/include/libxml2 CERRWARN += -_gcc=-Wno-parentheses CERRWARN += -_gcc=-Wno-uninitialized CERRWARN += -_gcc=-Wno-switch diff --git a/usr/src/lib/libshare/autofs/Makefile.com b/usr/src/lib/libshare/autofs/Makefile.com index 41c7dfd334..0538ec55fa 100644 --- a/usr/src/lib/libshare/autofs/Makefile.com +++ b/usr/src/lib/libshare/autofs/Makefile.com @@ -46,6 +46,8 @@ LDLIBS += -lshare -lscf -lumem -lc -lxml2 #add nfs/lib directory as part of the include path CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -I$(AUTOFSSMFLIB_DIR) \ + -I$(ADJUNCT_PROTO)/usr/include/libxml2 CERRWARN += -_gcc=-Wno-switch CERRWARN += -_gcc=-Wno-unused-variable CERRWARN += -_gcc=-Wno-uninitialized diff --git a/usr/src/lib/libshare/nfs/Makefile.com b/usr/src/lib/libshare/nfs/Makefile.com index d393c5f8ba..44e661bbe2 100644 --- a/usr/src/lib/libshare/nfs/Makefile.com +++ b/usr/src/lib/libshare/nfs/Makefile.com @@ -46,6 +46,8 @@ LDLIBS += -lshare -lnsl -lscf -lumem -lc -lxml2 #add nfs/lib directory as part of the include path CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -I$(NFSLIB_DIR) \ + -I$(ADJUNCT_PROTO)/usr/include/libxml2 -I$(SRCDIR)/../common CERRWARN += -_gcc=-Wno-parentheses CERRWARN += -_gcc=-Wno-switch CERRWARN += -_gcc=-Wno-unused-variable diff --git a/usr/src/lib/libshare/nfs/libshare_nfs.c b/usr/src/lib/libshare/nfs/libshare_nfs.c index 37ea8cdf3d..0cf69a241a 100644 --- a/usr/src/lib/libshare/nfs/libshare_nfs.c +++ b/usr/src/lib/libshare/nfs/libshare_nfs.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ /* * Copyright 2013 Nexenta Systems, Inc. All rights reserved. @@ -2663,9 +2664,16 @@ nfs_init() ret = initprotofromsmf(); if (ret != SA_OK) { - (void) printf(dgettext(TEXT_DOMAIN, - "NFS plugin problem with SMF repository: %s\n"), - sa_errorstr(ret)); + /* + * This is a workaround. See the comment in + * cmd/fs.d/nfs/lib/smfcfg.c for an explanation. + */ + if (getzoneid() == GLOBAL_ZONEID || + ret != SCF_ERROR_NOT_FOUND) { + (void) printf(dgettext(TEXT_DOMAIN, + "NFS plugin problem with SMF repository: %s\n"), + sa_errorstr(ret)); + } ret = SA_OK; } add_defaults(); diff --git a/usr/src/lib/libshare/smb/Makefile.com b/usr/src/lib/libshare/smb/Makefile.com index 6b3d821684..3fe65dff3c 100644 --- a/usr/src/lib/libshare/smb/Makefile.com +++ b/usr/src/lib/libshare/smb/Makefile.com @@ -49,6 +49,7 @@ LDLIBS += -lshare -ldlpi -lnsl -lnvpair -lscf -lumem -lc all install := LDLIBS += -lxml2 CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -I$(ADJUNCT_PROTO)/usr/include/libxml2 CERRWARN += -_gcc=-Wno-char-subscripts CERRWARN += -_gcc=-Wno-switch CPPFLAGS += -D_REENTRANT -I/usr/include/libxml2 \ diff --git a/usr/src/lib/libshare/smbfs/Makefile.com b/usr/src/lib/libshare/smbfs/Makefile.com index c4b7b48117..fbd4b80000 100644 --- a/usr/src/lib/libshare/smbfs/Makefile.com +++ b/usr/src/lib/libshare/smbfs/Makefile.com @@ -41,6 +41,8 @@ LIBS = $(DYNLIB) LDLIBS += -lshare -lscf -lumem -luuid -lc -lxml2 -lsmbfs CFLAGS += $(CCVERBOSE) +CPPFLAGS += -D_REENTRANT -I$(ADJUNCT_PROTO)/usr/include/libxml2 \ + -I$(SRCDIR)/../common -I$(SRC)/lib/libsmbfs -I$(SRC)/uts/common CERRWARN += -_gcc=-Wno-switch CERRWARN += -_gcc=-Wno-uninitialized CPPFLAGS += -D_REENTRANT -I/usr/include/libxml2 -I$(SRCDIR)/../common \ diff --git a/usr/src/lib/libshell/Makefile b/usr/src/lib/libshell/Makefile index b584728d5f..1cce2316f0 100644 --- a/usr/src/lib/libshell/Makefile +++ b/usr/src/lib/libshell/Makefile @@ -64,6 +64,5 @@ $(SUBDIRS): FRC FRC: include Makefile.demo -include Makefile.doc include ../Makefile.targ diff --git a/usr/src/lib/libshell/Makefile.doc b/usr/src/lib/libshell/Makefile.doc deleted file mode 100644 index 07118f7459..0000000000 --- a/usr/src/lib/libshell/Makefile.doc +++ /dev/null @@ -1,91 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -ROOTDOCDIRBASE= $(ROOT)/usr/share/doc/ksh - -DOCFILES= \ - RELEASE \ - README \ - TYPES \ - DESIGN \ - COMPATIBILITY \ - OBSOLETE \ - shell_styleguide.docbook \ - shell_styleguide.html \ - images/tag_bourne.png \ - images/tag_i18n.png \ - images/tag_ksh88.png \ - images/tag_ksh93.png \ - images/tag_ksh.png \ - images/tag_l10n.png \ - images/tag_perf.png \ - images/callouts/1.png \ - images/callouts/2.png \ - images/callouts/3.png \ - images/callouts/4.png \ - images/callouts/5.png \ - images/callouts/6.png \ - images/callouts/7.png \ - images/callouts/8.png \ - images/callouts/9.png \ - images/callouts/10.png - -# Documentation rules -$(ROOTDOCDIRBASE)/%: common/% - $(INS.file) - -$(ROOTDOCDIRBASE)/%: misc/% - $(INS.file) - -ROOTDOCDIRS= \ - $(ROOTDOCDIRBASE) .WAIT \ - $(ROOTDOCDIRBASE)/images .WAIT \ - $(ROOTDOCDIRBASE)/images/callouts - -$(ROOTDOCDIRBASE)/%.html: misc/%.docbook - /usr/bin/xsltproc \ - --nonet \ - --stringparam generate.section.toc.level 0 \ - --stringparam toc.max.depth 3 \ - --stringparam toc.section.depth 12 \ - --xinclude \ - -o "$(@F)" \ - $(DOCBOOK_XSL_ROOT)/html/docbook.xsl \ - "$<" >xsltproc.log 2>&1 - $(INS) -s -m $(FILEMODE) -f "$(@D)" "$(@F)" - $(RM) "$(@F)" - -# Generic documentation rules -DOCFILESRCDIR= common -ROOTDOCFILES= $(DOCFILES:%=$(ROOTDOCDIRBASE)/%) -$(ROOTDOCDIRS) := OWNER = root -$(ROOTDOCDIRS) := GROUP = bin -$(ROOTDOCDIRS) := DIRMODE = 755 - -$(ROOTDOCDIRS): - $(INS.dir) - -install: $(ROOTDOCDIRS) .WAIT $(ROOTDOCFILES) diff --git a/usr/src/lib/libshell/common/COMPATIBILITY b/usr/src/lib/libshell/common/COMPATIBILITY deleted file mode 100644 index d4d645a99a..0000000000 --- a/usr/src/lib/libshell/common/COMPATIBILITY +++ /dev/null @@ -1,134 +0,0 @@ - - KSH-93 VS. KSH-88 - - -The following is a list of known incompatibilities between ksh-93 and ksh-88. -I have not include cases that are clearly bugs in ksh-88. I also have -omitted features that are completely upward compatible. - -1. Functions, defined with name() with ksh-93 are compatible with - the POSIX standard, not with ksh-88. No local variables are - permitted, and there is no separate scope. Functions defined - with the function name syntax, maintain compatibility. - This also affects function traces. - -2. ! is now a reserved word. As a result, any command by that - name will no longer work with ksh-93. - -3. The -x attribute of alias and typeset -f is no longer - effective and the ENV file is only read for interactive - shells. You need to use FPATH to make function definitions - visible to scripts. - -4. A built-in command named command has been added which is - always found before the PATH search. Any script which uses - this name as the name of a command (or function) will not - be compatible. - -5. The output format for some built-ins has changed. In particular - the output format for set, typeset and alias now have single - quotes around values that have special characters. The output - for trap without arguments has a format that can be used as input. - -6. With ksh-88, a dollar sign ($') followed by a single quote was - interpreted literally. Now it is an ANSI-C string. You - must quote the dollar sign to get the previous behavior. - Also, a $ in front of a " indicates that the string needs - to be translated for locales other than C or POSIX. The $ - is ignored in the C and POSIX locale. - -7. With ksh-88, tilde expansion did not take place inside ${...}. - with ksh-93, ${foo-~} will cause tilde expansion if foo is - not set. You need to escape the ~ for the previous behavior. - -8. Some changes in the tokenizing rules where made that might - cause some scripts with previously ambiguous use of quoting - to produce syntax errors. - -9. Programs that rely on specific exit values for the shell, - (rather than 0 or non-zero) may not be compatible. The - exit status for many shell failures has been changed. - -10. Built-ins in ksh-88 were always executed before looking for - the command in the PATH variable. This is no longer true. - Thus, with ksh-93, if you have the current directory first - in your PATH, and you have a program named test in your - directory, it will be executed when you type test; the - built-in version will be run at the point /bin is found - in your PATH. - -11. Some undocumented combinations of argument passing to ksh - builtins no longer works since ksh-93 is getopts conforming - with respect to its built-ins. For example, typeset -8i - previously would work as a synonym for typeset -i8. - -12. Command substitution and arithmetic expansion are now performed - on PS1, PS3, and ENV when they are expanded. Thus, ` and $( - as part of the value of these variables must be preceded by a \ - to preserve their previous behavior. - -13. The ERRNO variable has been dropped. - -14. If the file name following a redirection symbol contain pattern - characters they will only be expanded for interactive shells. - -15. The arguments to a dot script will be restored when it completes. - -16. The list of tracked aliases is not displayed with alias unless - the -t option is specified. - -17. The POSIX standard requires that test "$arg" have exit status - of 0, if and only if $arg is null. However, since this breaks - programs that use test -t, ksh93 treats an explicit test -t - as if the user had entered test -t 1. - -18. The ^T directive of emacs mode has been changed to work the - way it does in gnu-emacs. - -19. ksh-88 allowed unbalanced parenthes within ${name op val} whereas - ksh-93 does not. Thus, ${foo-(} needs to be written as ${foo-\(} - which works with both versions. - -20. kill -l in ksh-93 lists only the signal names, not their numerical - values. - -21. Local variables defined by typeset are statically scoped in - ksh93. In ksh88 they were dynamically scoped although this - behavior was never documented. - -22. The value of the variable given to getopts is set to ? when - the end-of-options is reached to conform to the POSIX standard. - -23. Since the POSIX standard requires that octal constants be - recongnized, doing arithmetic on typeset -Z variables can - yield different results that with ksh88. Most of these - differences were eliminated in ksh93o. - -24. Starting after ksh93l, If you run ksh name, where name does - not contain a /, the current directory will be searched - before doing a path search on name as required by the POSIX - shell standard. - -25. In ksh93, cd - will output the directory that it changes - to on standard output as required by X/Open. With ksh88, - this only happened for interactive shells. - -26. As an undocumented feature of ksh-88, a leading 0 to an - assignment of an integer variable caused that variable - to be treated as unsigned. This behavior was removed - starting in ksh93p. - -27. The getopts builtin in ksh93 requires that optstring contain - a leading + to allow options to begin with a +. - -28. In emacs/gmacs mode, control-v will not display the version when - the stty lnext character is set to control-v or is unset. - The sequence escape control-v will display the shell version. - -29. In ksh88, DEBUG traps were executed. after each command. In ksh93 - DEBUG traps are exeucted before each command. - -30. In ksh88, a redirection to a file name given by an empty string was - ignored. In ksh93, this is an error. -I am interested in expanding this list so please let me know if you -uncover any others. diff --git a/usr/src/lib/libshell/common/DESIGN b/usr/src/lib/libshell/common/DESIGN deleted file mode 100644 index c11c0aff1e..0000000000 --- a/usr/src/lib/libshell/common/DESIGN +++ /dev/null @@ -1,170 +0,0 @@ -Here is an overview of the source code organization for ksh93. - -Directory layout: - - The directory include contains header files for ksh93. - The files nval.h and shell.h are intended to be public - headers and can be used to add runtime builtin command. - The remainder are private. - - The directory data contains readonly data files for ksh93. - The man pages for built-ins are in builtins.c rather - than included as statics with the implementations in the - bltins directory because some systems don't make static const - data readonly and we want these to be shared by all running - shells. - - The directory edit contains the code for command line - editing and history. - - The fun directory contains some shell function such as - pushd, popd, and dirs. - - The directory features contains files that are used to generate - header files in the FEATURE directory. Most of these files - are in a format that is processed by iffe. - - The directory bltins contains code for most of the built-in - commands. Additional built-in commands are part of libcmd. - - The directory sh contains most of the code for ksh93. - - The directory tests contains a number of regression tests. - In most cases, when a bug gets fixed, a test is added to - one of these files. The regression tests can be run by - going to this directory and running - SHELL=shell_path shell_path shtests - where shell_path is an absolute pathname for the shell to - be tested. - - The top level directory contains the nmake Makefile, a README, - and several documentation files. The RELEASE file contains - the list of bug fixes and new features since the original - ksh93 release. The file COMPATIBILITY is a list of all - known incompatibilities with ksh88. - - The bash_pre_rc.sh is a startup script used when emulating - bash if the shell is compiled with SHOPT_BASH and the shell - is invoked as bash. The bash emulation is not complete. - -Include directory: - 1. argnod.h contains the type definitions for command - nodes, io nodes, argument nodes, and for positional - parameters.a It defines the prototypes for - all the positional parameters functions. - 2. builtins.h contains prototypes for builtins as well - as symbolic constants that refer to the name-pairs - that are associated with some of the built-ins. - It also contains prototypes for many of the strings. - 3. defs.h is the catch all for all definitions that - don't fit elsewhere and it includes several other - headers. It defines a strucuture that contains ksh - global data, sh, and a structure that contains per - function data, sh.st. - 4. edit.h contains definitions that are common to both - vi and emacs edit modes. - 5. env.h contains interfaces for creating and modifying - environment variables. - 6. fault.h contains prototypes for signal related - functions and trap and fault handling. - 7. fcin.h contains macro and function definitions for - reading from a file or string. - 8. history.h contains macros and functions definitions - related to history file processing. - 9. jobs.h contains the definitions relating to job - processing and control. - 10. lexstates.h contains the states associated with - lexical processing. - 11. name.h contains the internal definitions related - to name-value pair processing. - 12. national.h contains a few I18N definitions, mostly - obsolete. - 13. nval.h is the public interface to the name-value - pair library that is documented with nval.3. - 14. path.h contains the interface for pathname processing - and pathname searching. - 15. shell.h is the public interface for shell functions - that are documented int shell.3. - 16. shlex.h contains the lexical token definitions and - interfaces for lexical analysis. - 17. shnodes.h contains the definition of the structures - for each of the parse nodes and flags for the attributes. - 18. shtable.h contains some interfaces and functions for - table lookup. - 19. streval.h contains the interface to the arithmetic - functions. - 20. terminal.h is a header file that includes the appropriate - terminal include. - 21. test.h contains the definitions for the test and [[...]] - commands. - 22. timeout.h contains the define constant for the maximum - shell timeout. - 23. ulimit.h includes the appropriate resource header. - 24. variables.h contains symbolic constants for the built-in - shell variables. - -sh directory: - 1. args.c contains functions for parsing shell options - and for processing positional parameters. - 2. arith.c contains callback functions for the streval.c - library and the interface to shell arithmetic. - 3. array.c contains the code for indexed and associative - arrays. - 4. bash.h contains code used when compiling with SHOPT_BASH - to add bash specific features such as shopt. - 5. defs.c contains the data definitions for global symbols. - 6. deparse.c contains code to generate shell script from - a parse tree. - 7. env.c contains code to add and delete environment variables - to an environment list. - 8. expand.c contains code for file name expansion and - file name generation. - 9. fault.c contains code for signal processing, trap - handling and termination. - 10. fcin.c contains code for reading and writing a character - at a time from a file or string. - 11. init.c contains initialization code and callbacks - for get and set functions for built-in variables. - 12. io.o contains code for redirections and managing file - descriptors and file streams. - 13. jobs.c contains the code for job management. - 14. lex.c contains the code for the lexical analyzer. - 15. macro.c contains code for the $ macro expansions, including - here-documents. - 16. main.c contains the calls to initialization, profile - processing and the main evaluation loop as well as - mail processing. - 17. name.c contains the name-value pair routines that are - built on the hash library in libast. - 18. nvdisc.c contains code related to name-value pair disciplines. - 19. nvtree.c contains code for compound variables and for - walking the namespace. - 20. nvtype.c contains most of the code related to types that - are created with typeset -T. - 21. parse.c contains the code for the shell parser. - 22. path.c contains the code for pathname lookup and - some path functions. It also contains the code - that executes commands and scripts. - 23. pmain.c is just a calls sh_main() so that all of the - rest of the shell can be in a shared library. - 24. shcomp.c contains the main program to the shell - compiler. This program parses a script and creates - a file that the shell can read containing the parse tree. - 25. streval.c is an C arithmetic evaluator. - 26. string.c contains some string related functions. - 27. subshell.c contains the code to save and restore - environments so that subshells can run without creating - a new process. - 28. suid_exec.c contains the program from running execute - only and/or setuid/setgid scripts. - 29. tdump.c contains the code to dump a parse tree into - a file. - 30. timers.c contains code for multiple event timeouts. - 31. trestore contians the code for restoring the parse - tree from the file created by tdump. - 32. userinit.c contains a dummy userinit() function. - This is now obsolete with the new version of sh_main(). - 33. waitevent.c contains the sh_waitnotify function so - that builtins can handle processing events when the - shell is waiting for input or for process completion. - 34. xec.c is the main shell executuion loop. diff --git a/usr/src/lib/libshell/common/OBSOLETE b/usr/src/lib/libshell/common/OBSOLETE deleted file mode 100644 index c29cb8bb63..0000000000 --- a/usr/src/lib/libshell/common/OBSOLETE +++ /dev/null @@ -1,152 +0,0 @@ -.sp 3 -.tl ''Ksh Features That Are Obsolete in Ksh93'' -.sp 2 -.AL 1 -.LI -Using a pair of grave accents \^\fB\(ga\fR ... \fB\(ga\fR\^ -for command substition. Use \fB$(\fR ... \fB)\fR instead. -.LI -.B FCEDIT -is an obsolete name for -the default editor name for the -.B hist -command. -.B FCEDIT -is not used when -.B HISTEDIT -is set. Use -.B HISTEDIT -instead. -.LI -The newtest (\fB[[\fR ... \fB]]\fR) operator -\fB\-a\fP \fIfile\fP -is obsolete. Use -\fB\-e\fP instead. -.LI -The newtest (\fB[[\fR ... \fB]]\fR) operator -.BR = , -as used in -\fIstring\fP \fB=\fP \fIpattern\fP -is obsolete. Use -\fB==\fP instead. -.LI -The following obsolete arithmetic comparisons are also permitted: -.in +5 -.VL 20 -.LI "\fIexp1\fP \fB\-eq\fP \fIexp2\fP" -True, if -.I exp1 -is equal to -.IR exp2 . -.LI "\fIexp1\fP \fB\-ne\fP \fIexp2\fP" -True, if -.I exp1 -is not equal to -.IR exp2 . -.LI "\fIexp1\fP \fB\-lt\fP \fIexp2\fP" -True, if -.I exp1 -is less than -.IR exp2 . -.LI "\fIexp1\fP \fB\-gt\fP \fIexp2\fP" -True, if -.I exp1 -is greater than -.IR exp2 . -.LI "\fIexp1\fP \fB\-le\fP \fIexp2\fP" -True, if -.I exp1 -is less than or equal to -.IR exp2 . -.LI "\fIexp1\fP \fB\-ge\fP \fIexp2\fP" -True, if -.I exp1 -is greater than or equal to -.IR exp2 . -.LE \" End .VL -.in -5 -.LI -Using test -t or [ -t ] without specifying the file unit number. -.LI -The -.B \-k -option to the \fBset\fR builtin is obsolete. It causes -.I all\^ -variable assignment arguments are placed in the environment, -even if they occur after the command name. -The following -first prints -.B "a=b c" -and then -.BR c : -There is no alternative. -.LI -The obsolete -.B \-xf -option of the -.B typeset -command allows a function to be exported -to scripts that are executed without a separate -invocation of the shell. -Functions that need to be defined across separate -invocations of the shell should -be placed in a directory and the -.B FPATH -variable should contains the name of this directory. -They may also -be specified in the -.B ENV -file with the -.B \-xf -option of -.BR typeset . -.LI -The shell environment variable -.B FCEDIT -is obsolete. Use -.B HISTEDIT -instead. -.LI -In the -.B \-s -option -(to \fBfc\fR or \fBhist\fR command???) -( -and in obsolete versions, the editor name -.B \- -) -is used to skip the editing phase and -to re-execute the command. -.LI -The -.B \-t -option to \fBalias\fR builtin is is obsolete. It -is used to set and list tracked aliases. -There is no replacement. -.LI -The shell command line option -.B \-t -is obsolete. This option cause the shell to exit after reading -and executing one command. The is no replacement (although ending -\&"command" with the exit builtin should have the same effect). -.LI -As an obsolete feature of the "set" builtin, -if the first -.I arg\^ -is -.B \- -then the -.B \-x -and -.B \-v -options are turned off and the next -.I arg -is treated as the first argument. -Using -.B \+ -rather than -.B \- -causes these options to be turned off. -These options can also be used upon invocation of the shell. -.LE - diff --git a/usr/src/lib/libshell/common/README b/usr/src/lib/libshell/common/README deleted file mode 100644 index 1feeec8a90..0000000000 --- a/usr/src/lib/libshell/common/README +++ /dev/null @@ -1,232 +0,0 @@ -This directory, and its subdirectories contain the source code -for ksh-93; the language described in the second addition of -the book, "The KornShell Command and Programming Language," by -Morris Bolsky and David Korn which is published by Prentice Hall. -ksh-93 has been compiled and run on several machines with several -operating systems. The end of this file contains a partial list of -operating systems and machines that ksh-93 has been known to run on. - -The layout of files for ksh-93 has changed somewhat since ksh-88, -the last major release. Most of the source code for ksh remains in -the sh directory. However, the shell editing and history routines -are in the edit sub-directory. The code for shell built-ins is -in the bltins directory. The data directory contains read-only -data tables and messages that are used by the shell. The include -files remain in the include directory and the shlib directory -is gone. The features directory replaces the older install -directory. The method for generating systems specific feature -information has changed substantially. - -The Makefile file contains several compilation options that can be set -before compiling ksh. Options are of the form SHOPT_option and become -#define inside the code. These options are set to their recommended -value and some of these may disappear as options in future releases. -A value of 0, or no value represents off, 1 represents on. -Note that == is needed, not =, because these are nmake state variables -and changing their value will cause all modules that could be affected -by this change to be recompiled. -The options have the following defaults and meanings: - ACCT off Shell accounting. - ACCTFILE off Enable per user accounting info. - AUDIT off For auditing specific users - AUDITFILE "/etc/ksh_audit" - APPEND on Allows var+=val string and array append. - BASH off Bash compatibility mode. It is not fully implemented - and is experimental. - BRACEPAT on C-shell type abc{d,e}f style file generation - CMDLIB_BLTIN off Makes all commands in libcmd.a builtins. The - SH_CMDLIB_DIR nmake state variable can be used to - specify a directory. - CMDLIB_DIR off Sets CMDLIB_BLTIN=1 and provides a default value - of "/opt/ast/bin" for SH_CMDLIB_DIR. - COMPOUND_ARRAY - on Allows all components of compound variables except the - first to be any string by enclosing in [...]. It also - allows components other than the last to be arrays. - This is experimental and only partially complete. - CRNL off <cr><nl> treated as <nl> in shell grammar. - DYNAMIC on Dynamic loading of builtins. (Requires dlopen() interface.) - ECHOPRINT off Make echo equivalent to print. - ESH on Compile with emacs command line editing. The original - emacs line editor code was provided by Mike Veach at IH. - FILESCAN on Experimental option that allows fast reading of files - using while < file;do ...; done and allowing fields in - each line to be accessed as positional parameters. - FS_3D off For use with 3-D file system. Enabled automatically for - sytems with dynamic linking. - KIA off Allow generation of shell cross reference database with -I. - MULTIBYTE on Multibyte character handling. Requires mblen() and - mbctowc(). - NAMESPACE on Allows namespaces. This is experimental, incomplete - and undocumented. - OLDTERMIO off Use either termios or termio at runtime. - OO on Experimental object oriented extension. This option - should disappear soon. - OPTIMIZE on Optimize loop invariants for with for and while loops. - P_SUID off If set, all real uids, greater than or equal to this - value will require the -p flag to run suid/sgid scripts. - PFSH off Compile with support for profile shell. - RAWONLY off Turn on if the vi line mode doesn't work right unless - you do a set -o viraw. - SEVENBIT off Strip the eigth bit from characters. - SPAWN off Use spawn as combined fork/exec. May improve speed on - some systems. - STATS on Add .sh.stats compound variable. - SUID_EXEC on Execute /etc/suid_exec for setuid, setgid script. - TIMEOUT off Set this to the number of seconds for timing out and - exiting the shell when you don't enter a command. If - non-zero, TMOUT can not be set larger than this value. - TYPEDEF on Enable typeset type definitions. - VSH on Compile with vi command line editing. The original vi - line editor code was provided by Pat Sullivan at CB. - -The following compile options are set automatically by the feature testing: - DEVFD Set when /dev/fd is a directory that names open files. - SHELLMAGIC - Set on systems that recognize script beginning with #! specially. - VPIX Set on systems the have /usr/bin/vpix program for running MS-DOS. - - -In most instances, you will generate ksh from a higher level directory -which also generates libcmd and libast libraries on which ksh depends. -However, it is possible to generate ksh, with by running make -f ksh.mk -in this directory. The ksh.mk file was generated from the nmake Makefile. -If you do not have make or nmake, but do have a Version 7 UNIX compatible -shell, then you can run the script mamexec < Mamfile to build ksh. -If you have nmake, version 2.3 or later, you can use it without the -f ksh.mk. -In either case, ksh relies on libraries libast and libcmd which must be -built first. The binary for ksh becomes the file named ./ksh which can -be copied to where ever you install it. - -If you use old make or the Mamfile, and you system has dynamic shared -libraries, then you should define the variables mam_cc_static and -mam_cc_dynanamic as the compiler options that request static linking -and dynamic linking respectively. This will decrease the number of -shared libraries that ksh need and cut startup time substantially. - -The makefile should also generate shcomp, a program that will precompile -a script. ksh93 is able to recognize files in this format and process -them as scripts. You can use shcomp to send out scripts when you -don't want to give away the original script source. - -It is advisable that you put the line PWD=$HOME;export PWD into the -/etc/profile file to reduce initialization time for ksh. - -To be able to run setuid/setgid shell scripts, or scripts without read -permission, the SUID_EXEC compile option must be on, and ksh must be installed -in the /bin directory, the /usr/bin directory, the /usr/lbin directory, -or the /usr/local/bin directory and the name must end in sh. The program -suid_exec must be installed in the /etc directory, must be owned by root, -and must be a suid program. If you must install ksh in some other directory -and want to be able to run setuid/setgid and execute only scripts, then -you will have to change the source code file sh/suid_exec.c explicitly. -If you do not have ksh in one of these secure locations, /bin/sh will -be invoked with the -p options and will fail when you execute a setuid/setgid -and/or execute only script. Note, that ksh does not read the .profile -or $ENV file when it the real and effective user/group id's are not -equal. - -The tests sub-directory contains a number of regression tests for ksh. -To run all these tests with the shell you just built, go to the tests -directory and run the command - SHELL=$dir/ksh $dir/ksh shtests -where dir is the directory of the ksh you want to test. - -The file PROMO.mm is an advertisement that extolls the virtues of ksh. -The file sh.1 contains the troff (man) description of this Shell. -The file nval.3 contains the troff (man) description of the name-value -pair library that is needed for writing built-ins that need to -access shell variables. - -The file sh.memo contains a draft troff (mm) memo describing ksh. The -file RELEASE88 contains the changes made for ksh88. The file RELEASE93 -contains the changes made in this release since ksh-88. The file -RELEASE contains bug fixes made in this release since ksh-88. The file -COMPATIBILITY contains a list of incompatibilities with ksh-88. The -file bltins.mm is a draft troff (mm) memo describing how to write -built-in commands that can be loaded at run time. - -Most of the work for internationalization has been done with ksh93. -The file ksh.msg is a generated file that contains error messages -that need to be translated. In addition, the function translate() -in sh/init.c has to be completed to interface with the dictionary -lookup. The translate function takes two argument, the string -that is to be translated and a type which is - 0 when a library string needs translation. - 1 when one of the error messages in ksh.msg needs translation. - 2 when a string in a script needs translation. You use a $ in front - of a double quoted string in a script to indicate that it - needs translation. The -D option for ksh builds the dictionary. -The translate routine needs to return the translated message. -For dictionaries that need to use a numeric key, it should be -possible to use the strhash() function to generate numbers to -go along with each of the messages and to use this number both -when generating the dictionary and when converting strings. -If you encounter error messages of type 1 that are not be translated via -this translate() function send mail to the address below. - -Please report any problems or suggestions to: - -dgk@research.att.com - - -ksh93 has been compiled and alpha tested on the following. An asterisk -signifies that ksh has been installed as /bin/sh on this machine. - -* Sun OS 4.1.[123] on sparc. - Sun OS 4.1.1 on sun. - Solaris 2.[1-9] on sparc. - Solaris 2.[4-8] on X86. - HP/UX 8 on HP-9000/730. - HP/UX 9 on HP-9000/730. - HP/UX 10 on HP-9000/857. - HP/UX 11 on pa-risc. - System V Release 3 on Counterpoint C19 - System V Release 4 on AT&T Intel 486. - System V Release 4 on NCR 4850 Intel 486. - IRIX Release 4.0.? System V on SGI-MIPS. - IRIX Release 5.1 System V on SGI-MIPS. - IRIX Release 6.[1-5] System V on SGI-MIPS. - System V Release 3.2 on 3B2. - UTS 5.2.6 on Amdahl 3090,5990,580. - System V Release 3.2 on i386. - SMP_DC.OSx olivetti dcosx MIServer-S 2/128. - SMP_DC.OSx Pyramid dcosx MIServer-S 2/160 r3000. - 4.3BSD on Vax 8650. - AIX release 2 on RS6000. - AIX 3.2 on RS6000. - Linux 1.X on Intel - Linux 2.X on Intel - Linux 2.X on Alpha - Linux 2.X on Alpha - Linux 2.X on OS/390 - Linux 2.X on sparc - Linux 2.4 on intel itanium 64 - Linux Slackware on sparc64 -* Linux ARM on i-PAQ - OSF1 on DEC alpha. - OSF4 on DEC alpha. - UMIPS 4.52 on mips. - BSD-i [2-4] on X86. - OpenBSD on X86 - NetBSD on X86 - FreeBSD on X86 - NeXT on Intel X86. - NeXT on HP. -* Windows NT using UWIN on X86 -* Windows NT using UWIN on alpha - Windows NT using Cygwin on X86 - Windows NT with NutCracker libraries. - Windows NT with Portage libraries. - Windows 3.1 using custom C library. - OpenEdition on MVS - Darwin OS X on PPC - MVS on OS 390 - SCO Openserver 3.2 on X86 - Unixware 7 on X86 - -Good luck!! - -David Korn -dgk@research.att.com - diff --git a/usr/src/lib/libshell/common/RELEASE b/usr/src/lib/libshell/common/RELEASE deleted file mode 100644 index b8fc92511a..0000000000 --- a/usr/src/lib/libshell/common/RELEASE +++ /dev/null @@ -1,2204 +0,0 @@ -10-03-05 --- Release ksh93t+ --- -10-03-05 A varibale unset memory leak has been fixed and tests/leaks.sh - has been added to verify the fix. -10-03-04 Documentation, comment, and disgnostic spelling typos corrected. -10-02-14 Fix sh_getenv() initialization to cooperate with the 3d fs. -10-02-12 A bug in which the get discipline function was not invoked for - associative array subscripts for unset array elements has been fixed. -10-02-12 A bug which could occur if the last line of a script was an eval - that executed multiple commands has been fixed. -10-02-02 A buffer overflow in read and another in binary type base64 - encoding were fixed. -10-01-20 A bug in the evaluation of arithmetic expression in which the - subscript was evaluated twice for $((foo[x++]++)) has been fixed. -10-01-19 A workaround for a double-free of a trap in both a subshell and its - parent has been added. -10-01-18 A bug in type handling of typeset -H has been fixed. -10-01-15 The "adding empty subscript" warning now only emitted with -x set. -10-01-01 A bug in the parser in which '$((case i in i):;esac);:))' was not - parsed correctly was fixed. -10-01-01 A bug in the parser in which '$(( 2 , 3.6 ))' dumped core for locales - with radix char , and thousands separator . has been fixed. -09-12-28 A bug in the handling of SIGCLD on systems that generated SIGCLD - while blocked waiting for process to complete has been fixed. -09-12-24 ast setlocale() reworked to differentiate env var changes from user - override. -09-12-18 A bug with the SHOPT_BGX option set which disabled traps for signals - < SIGCHLD when a trap for a signal > SIGCHLD was set has been fixed. -09-12-18 A bug where [[ -v var ]] was incorrect for some variables (including - LC_* vars) has been fixed. -09-12-15 A bug that produced a syntax error when a multibyte character - straddled a buffer boundary has been fixed. -09-12-11 A bug where the subscript of an unset variable was not evaluated has - been fixed. -09-12-09 A bug where shcomp dumped core on certain syntax errors has been fixed. -09-12-07 A bug where a parent shell environment var reset in a subshell removed - the value in subsequent children of the parent shell has been fixed. -09-12-04 A bug in which in some cases a trap in a function executed in - a subshell could trigger twice has been fixed. -09-12-03 A bug in which SHLVL exported with some attributes could cause - the shell to abort at startup has been fixed. -09-12-02 A bug with pipefail in which the shell could hang waiting for the - writer to complete before the last reader command has been fixed. -09-11-30 A bug in which a trap could be inherited by the first element of - a pipeline when the command had more than 63 arguments that did - not contain any macro expansions has been fixed. -09-11-19 When read from a terminal was called from with a while or foo loop, - and an edit mode was on, a backspace or erase no longer will - overwrite the prompt. -09-11-17 Change .paths parse to handle BUILTIN_LIB=foo BUILTIN_LIB=foo-1.2. -09-11-17 Inside a function, typeset foo.bar will bind foo to global variable - foo if local variable foo does not exist, instead of creating a - local variable. -09-11-17 "read -n1" from the terminal has been fixed to read exactly one character. -09-11-11 Job control now works for subshell commands, (...). -09-11-11 If set -e is on for an interactive shell errors in special builtins - now cause the shell to exit. -09-11-11 A bug in which an interrupt handler processed during the read builtin - when IFS did not contain a new line has been fixed. -09-11-09 A bug in which a variable that has been unset in a subshell and then - exported from that subshell does not show up in the environment - has been fixed. -09-11-02 ``,2'' is now a valid numeric constant for locales with - decimal_point=','. -09-11-02 A bug where "return" in .profile did not restore the shell state - has been fixed. -09-10-31 A bug that corrupted saved exit status when pids wrapped around has - been fixed. -09-10-26 A bug in { LANG LC_ALL LC_category } ordering has been fixed in -last. -09-10-16 A bug where notification to libast that the environment has changed - has been fixed. -09-10-12 A bug in which a function loaded in a subshell could leave side - effects in the parent shell has been fixed. -09-10-12 A bug in converting a printf %d operand to a number when the operand - contains multiple subscripts for the same variable has been fixed. -09-10-09 A bug in the handling of the escape character \ in directory prefixes - in command completion has been fixed. -09-10-09 $PATH processing has been changed to delay dir stat() and .paths - lookup until the directory is needed in the path search. -09-09-28 Call the ast setlocale() intercept on unset too. -09-09-24 A bug in which LANG=foo; LC_ALL=foo; unset LC_ALL; did not revert - LC_CTYPE etc. to the LANG value has been fixed. -09-09-17 A bug in which unsetting SVLVL could cause a script invoked by - name without #! to core dump has been fixed. -09-09-16 A bug in which a pipeline in a here-document could hang when the - pipefail option was on has been fixed. -09-09-09 A bug in the processing of line joining in here documents which - occurred when a buffer began with <escape><new-line> has been fixed. -09-09-09 A leading ; with commands in a brace group or parenthesis group - no longer causes an error. It now is used for the "showme" option. -09-09-09 A bug in which a subshell containing a background process could - block until the background process completed has been fixed. -09-09-04 A bug in handing ${var[sub]}, where var is a nameref has been fixed. -09-09-03 A bug which caused an index array to have the wrong number of elements - when it was converted from a compound variable by adding an another - element has been fixed. -09-09-03 Specifying export for a compound variable now generates an error. -09-09-02 $"..." localizations strings are no longer recognized inside `...`. -09-09-01 A bug in the for loop optimizer in the handling of type static - variables has been fixed. -09-09-01 An error message is not displayed when * and @ are used as subscripts. -09-09-01 Several bugs in the processing for types that included an associative - array of another type has been fixed. -09-09-01 A bug in the tracing of [[ a < b ]] and [[ a > b ]] has been fixed. -09-08-26 The .sh.file variable was not being set for a script that was run - by name and didn't start with #! and this has been fixed. -09-08-25 A bug in which a function called to deeply from command substitution - did not display an error message has been fixed. -09-08-24 When processing profiles, ksh93 now violates the POSIX standard and - treats &> as a redirection operator similar to bash. -09-08-23 A bug in the handling of the trap on SIGPIPE that could lead to a - memory fault has been fixed. -09-08-21 A bug in the handling of the comma operator in arithmetic expressions - that could cause a core dump on some systems has been fixed. -09-08-20 A bug in which a compound variable containing an array of a type - that doesn't have any elements now expands correctly. -09-08-19 A bug which disabled function tracing inside a function after - a call to another function has been fixed. -09-08-19 A bug in which initializing a compound variable instance to another - compound variable by name has been fixed. -09-08-18 A bug in which compound variable instances could be lost after - an instance that invoked a type method discipline has been fixed. -09-08-18 A bug in which a discipline function for a type applied to an - array instance when invoked in a function ignored the subscript - has been fixed. -09-08-18 A scoping error with variables in arithmetic expression with - type variables when reference with a name reference has been fixed. -09-08-10 Several memory leaks were fixed primarily related to subshells. -09-08-06 A bug in which setting the trap on CHLD to ignore could cause - a script to hang has been fixed. -09-07-08 A bug in the processing of name reference assignments when it - contained pattern expansions with quoting has been fixed. -09-06-22 The default width for typeset -X has been changed so that there - should be no loss of precision when converting to a string. -09-06-19 A bug in the printing of array elements for binary variables with - printf %B has been fixed. -09-06-19 A bug which caused a core dump with trap DEBUG set with an array - assignment with no elements has been fixed. -09-06-19 A bug with read with typeset -b -Z<num> has been fixed. -09-06-19 Two bugs related to read -b for array variables has been fixed. -09-06-19 A bug with typeset for compound variables containing arrays of - compound variables has been fixed. -09-06-18 A bug in appending a compound variable to a an indexed array of - compound variables has been fixed. -09-06-18 A bug which occurs when appending a compound variable to an indexed - array element has been fixed. -09-06-18 Setting VISUAL to a value other than one ending in vi or emacs will - no longer unset the edit mode. -09-06-17 A bug in typeset -m when moving a local compound variable to a - global compound variable via a name reference has been fixed. -09-06-17 A bug in appending to nodes of an array of compound variables when - addressing them via nameref has been fixed. -09-06-17 A bug in typeset -p var, when var is an array of compound variables - in which the output only contained on array element has been fixed. -09-06-17 The prefix expansion ${!y.@} now works when y is a name - reference to an element of an array. -09-06-16 Traps on signals that are ignored when the shell is invoked - no longer display. Previously they were ignored as required but - would be listed with trap -p. -09-06-12 A bug in vi edit mode in which hitting the up arrow key at the - end of a line longer than 40 characters which caused a core dump - has been fixed. -09-06-11 A bug in which "eval non-builtin &" would create two processes, - one for the & and another for non-builtin has been fixed. -09-06-08 When var is an identifier and is unset, ${var} no longer tries to - run command substitution on the command var. -09-06-08 Process substitution arguments of the form <(command) can now be - used following the < redirection operator to redirect from command. -09-05-13 A bug in which redirections of the form 2>&1 1>&5 inside command - substitution could cause the command substitution to hang has been - fixed. -09-05-12 To conform with POSIX, the -u option only checks for unset variables - and subscript elements rather than checking for all parameters. -09-05-12 A bug which could cause a core dump when a variable whose name - begins with a . was referenced as part of a name reference inside - a function has been fixed. -09-05-01 A bug that caused a core dump when SIGWINCH was received and - both vi and emacs mode were off has been fixed. -09-04-22 Default alias compound='typeset -C' added. -09-04-15 A bug that caused ${...;} to hang for large files has been fixed. -09-04-08 A change was made in the -n option which printed out an incorrect - warning with <>. -09-04-07 The emacs edit command M-_ and M_. and the vi command _ was fixed - to handle the case there there is no history file. -09-04-05 A bug in handling new-lines with read -n has been fixed. -09-04-05 The ENV variable defaults the the file named by $HOME/.kshrc rather - then to the string $HOME/.kshrc. -09-03-31 A bug in which a nested command substitution with redirections could - leave a file descriptor open has been fixed. -09-03-24 ksh now only uses the value of the _ variable on startup if it can - verify that it was set by the invoking process rather than being - inherited by some other ancestor. -09-03-24 When ksh is invoked without -p and ruid!=euid, and the shell is - compiled without SHOPT_P_UID or ruid<SHOPT_P_UID, the shell now - enables the -p option. The previous version instead set the - euid to the ruid as it does for set +p. -09-03-24 When SHOPT_P_UID is defined at compile time and the shell is started - without -p and ruid!=euid and ruid>=SHOPT_P_UID then euid is set - to ruid. A bug that did the wrong test (ruid<SHOPT_P_UID) was fixed. -09-03-17 The sleep(1) builtin now accept and ISO 8601 PnYnMnDTnHnMnS - duration or date(1) compatible date/time operand. -09-03-10 If a variable that was left or right justified or zero-filled was - changed with a typeset statement that was left or right justified - or zero-filled, then the original justification no longer affects - the result. -09-03-10 A bug in the handling of traps when the last command in a script - is a subshell grouping command has been fixed. -09-03-03 A bug in which an expansion of the form ${!prefix@} could generate - an exception after the return from a function has been fixed. -09-02-02 A bug in restricted mode in which the value of ENV could be - changed from within a function has been fixed. -09-02-02 A bug in which an erroneous message indicating that a process - terminated with a coredump has been fixed. -09-02-02 The exit status when exit was called without an argument from - a signal handler was incorrect and has been fixed. -09-02-02 A bug in which a function autoloaded in a subshell could cause - a core dump when the subshell completed has been fixed. -09-02-02 A bug in which 2>&1 inside a command substitution wasn't working - correctly has been fixed. -09-02-02 A bug in the call stack of arithmetic function with 2 args - returning int has been fixed. -09-01-30 A bug in which 'eval print \$0' inside a function was giving the - wrong value for $0 has been fixed. -09-01-28 A bug in which a command substitution could return an exit status - of 127 when the pipefail option is enabled has been fixed. -09-01-26 ksh93 now generates an error message if you attempt to create - a global name reference to a local variable. -09-01-26 The [[ -v var ]] operator was modified to test for array elements. -09-01-23 The redirection operator <>; was added. It is similar to <> - except that if the command it is applied to succeeds, the file - is truncated to the offset at the command completion. -09-01-23 The default file descriptor for <> was changed to 1. -09-01-20 A bug in which the exit status specified in an exit trap was - not used when a process terminated with a signal has been fixed. -09-01-19 A bug in which a signal whose default action is to terminate - a process could be ignored when the process is running a sub-shell - has been fixed. -09-01-19 A bug in which sending SIGWINCH to a process that reads from a pipe - could cause a memory fault has been fixed. -09-01-16 The -R unary operator was added to [[...]] and test to check whether - a variable is a name reference. -09-01-16 The -v unary operator was added to [[...]] and test to check whether - a variable is set. -09-01-14 The unset built-in was modified to return 0 exit status when - unsetting a variable that was unset to conform with the POSIX - standard. -09-01-14 The unset built-in was modified to continue to unset variables - after encountering a variable that it could not unset to - conform to the POSIX standard. -09-01-14 The parameter expansion ${x+value} no longer expands the value of - the variable x when determining whether x is set or not. -09-01-13 A bug in which background jobs and pipelines that were not waited - for could, in rare instances, cause the shell to go into an infinite - loop or fail has been fixed. -09-01-06 A bug in indexed arrays of compound variables in which referencing - non-existent sub-variable in an arithmetic expression could cause - the sub-variable to be created has been fixed. -09-01-05 A bug in which the \ character did not escape extended regular - expression pattern characters has been fixed. -08-12-24 A bug in which killing the last element of a pipe did not cause - a write to the pipe to generate a SIGPIPE has been fixed. -08-12-19 A bug which could cause command substitution to hang when the - last element of a pipeline in a command substitution was a built-in - and the output was more that PIPE_BUFF. -08-12-18 A bug which occurs when a here documented marker embedded in a - command substitution occurs on a buffer boundary has been fixed. -08-12-17 A bug in the output of typeset -p for variables that had attributes - but did not have a value has been fixed. -08-12-16 A bug in which a name reference to a name reference variable that - references an array element has been fixed. -08-12-16 A bug in which a variable given both the -A and -C attribute along - with an initial assignment didn't work correctly has been fixed. -08-12-10 The [[ -t fd ]] test was fixed to handle fd>9. -08-12-10 A bug where function stack misalignment could cause a bus error - has been fixed. -08-12-09 Command completion was changed to use \ to quote special characters - instead of quoting the argument in single quotes. -08-12-07 A bug in typeset -m which occurred when the target node was an - associative array element has been fixed. -08-12-07 A timing bug on some systems (for example darwin), that could - cause the last process of a pipeline entered interactively to fail - with an "Exec format error" has been fixed. -08-12-04 SHOPT_BGX enables background job extensions. Noted by "J" in - the version string when enabled. (1) JOBMAX=n limits the number - of concurrent & jobs to n; the n+1 & job will block until a - running background job completes. (2) SIGCHLD traps are queued - so that each completing background job gets its own trap; $! is - set to the job pid and $? is set to the job exit status at the - beginning of the trap. (3) sleep -s added to sleep until the time - expires or until a signal is delivered. -08-12-04 The sign of floating point zero is preserved across arithmetic - function calls. -08-12-04 A bug that caused print(1) to produce garbled stdout/stderr - output has been fixed. -08-12-04 A bug in which printf "%d\n" "'<euro>'" did not output the - numerical value of the EURO symbol, 8354, has been fixed. -08-11-24 /dev/fd* and /dev/std* redirections are first attempted with - open() to preserve seek semantics; failing that the corresponding - file descriptors are dup()'d. -08-11-20 A bug which could cause a core dump if a function compiled with - shcomp was found has been fixed. -08-11-20 A bug in which jobs were not cleared from the jobs table for - interactive shells when the pipefail option is on has been fixed. -08-11-11 A bug in which a field that was unset in a type definition and later - set for an instance could appear twice when displaying the variable - has been fixed. -08-11-11 A bug in which running a simple command & inside a function would - not return the correct process id has been fixed. -08=11-10 A bug in which the exit status of a command could be lost if the pid - was that of the most recent command substitution that had completed - has been fixed. -08-11-10 The maximum depth for subshells has been increased from 256 to 65536. -08-11-06 A bug which could cause a core dump when the _ reference variable was - used as an embedded type with a compound assignment has been fixed. - -08-10-31 --- Release ksh93t --- -08-10-31 Variable scoping/initialization bugs that could dump core were fixed. -08-10-24 The lexer now accepts all RE characters for patterns prefixed - with a ksh ~(...) option expression. -08-10-24 For ${var/pat/sub} \0 in sub expands to the text matched by pat. -08-10-18 A bug in array scoping that could dump core has been fixed. -08-10-10 read -n and -N fixed to count characters in multibyte locales. -08-10-10 A bug that mishandled _.array[] type references has been fixed. -08-10-09 ${.sh.version} now contains a concatenation of the following (after - 'Version') denoting compile time features: - A SHOPT_AUDIT - B SHOPT_BASH - L SHOPT_ACCT - M SHOPT_MULTIBYTE -08-10-09 A bug that caused subshell command substitution with redirection - to hang has been fixed. -08-10-08 Output errors, other than to stderr, now result in a diagnostic. -08-10-08 ksh93 now supports types that contain arrays of other types as - members. Earlier versions core dumped in this case. -08-10-05 A bug which caused the shell to emit a syntax error for an arithmetic - statement of the form (( var.name[sub] = value)) has been fixed. -08-10-01 A bug that caused subshell command substitution to hang has - been fixed. -08-09-29 When the -p export option of typeset is used with other options, - only those variables matching the specified options are displayed. -08-09-29 When the shell reads the environment and finds variables that are - not valid shell assignments, it now passes these on to subsequent - commands rather than deleting them. -08-09-29 A bug in the display of compound variables containing an indexed - array of compound variables has been fixed. -08-09-29 A bug in the display of compound variables containing an associative - array with a subscript containing a . in the name has been fixed. -08-09-26 A core dump in the subshell environment restore has been fixed. -08-09-24 $(...) has been fixed to properly set the exit status in $?. -08-09-23 $(<...) with IFS=$'\n\n' has been fixed to retain all but the last - of multiple trailing newlines. -08-09-23 The -p option to typeset when used with other attributes, restricts - the output to variables with the specified attributes. -08-09-22 A bug that sometimes lost the exit status of a job has been fixed. -08-09-21 A bug that retained trailing command substitution newlines in - cases where the command caused the shell to fork has been fixed. -08-09-19 type, whence -v, and command -v were fixed to comply with POSIX - by writing 'not found' diagnostics to the standard error. -08-09-18 test and [...] were fixed to comply with POSIX in the case - of test '(' binop ')' where binop is a valid binary test operator. -08-09-16 If a method discipline named create is specified when defining a - type, this function will be called when an instance is created. -08-09-15 The variable _ is now set as a reference to the compound variable - when defining a compound variable or a type. -08-09-10 The shell now prints an error message when the type name specified - for an indexed array subscript is not an enumeration type. -08-09-10 A bug in which a subshell that spawned a background process could - loose output that was produced after the foreground completed - has been fixed. -08-09-10 A timing bug on some systems that could cause coprocesses started by a - subshell to not clean up and prevent other coprocesses has been fixed. -08-09-09 The typeset -m option is now able to rename array elements from - the same array. -08-09-09 The exit status of 2 from the DEBUG trap causes the next command - to be skipped. An exit value of 255 from a DEBUG trap called from - a function causes the function to return. -08-09-08 A bug in which a coprocess created in a subshell that did not - complete when the subshell terminated could prevent a coprocess - from being created in the parent shell has been fixed. -08-09-05 An assignment of the form name1=name2 where name1 and name2 - are both compound variables causes name1 to get a copy of name2. - name1+=name2 causes name2 sub-variables to be appended to name1. -08-09-05 A bug in which unsetting a compound variable did not unset all - the sub-variables has been fixed. -08-09-01 A bug in the subshell cleanup code that could cause SIGSEGV has - been fixed. -06-08-26 The SHLVL variable which is an environment variable used by bash - and zsh that gets incremented when the shell starts. -08-08-25 For an indexed array, a negative subscript now refers to offsets - from the end so that -1 refers to the last element. -08-08-24 An alignment error for shorts on 64 bit architectures has been fixed. -08-08-22 If oldvar is a compound variable, typeset -C newvar=oldvar creates - newvar as a copy of oldvar. -08-08-19 The ALRM signal no longer cause the sleep builtin to terminate. -08-08-13 When used in an arithmetic expression, the .sh.version variable - now produces a number that will be increasing for each release. -08-08-11 A bug in which type instantiation with a compound assignment in - a dot script in which the type is defined has been fixed. -08-08-07 The -m option has been added to typeset to move or rename a - variable. Not documented yet. -08-08-06 A bug in read when used in a loop when a prompt was specified - when reading from a terminal has been fixed. -08-08-01 A bug with the pipefail option in which a nested pipeline could - cause an asynchronous command to block has been fixed. -08-08-01 A for loop optimizer bug that treats .sh.lineno as an invariant - has been fixed. -08-07-30 A bug in which expanding compound variable that had a get discipline - from with a here document could cause a syntax error has been fixed. -08-07-18 A bug in which a nameref caused a local variable to be created - rather than binding to an existing variable in the global scope - has been fixed. -08-07-17 A bug which occurred when a nameref was created from within a - function that was part of a pipeline has been fixed. -08-07-14 The compile option SHOPT_STATS was added. With this option the - compound variable .sh.stats keeps usage statistics that could help - with performance tuning. -08-07-10 The output of set now always uses a single line for each variable. - For array variables, the complete set of values is now displayed. -08-07-09 The typeset -C option can be used with arrays to indicate that - each element should default to a compound variable. -08-07-08 The %B format now outputs compound variables and arrays. The - alternate flag # can be used to cause output into a single line. -08-07-03 When the window change signal, WINCH, is received, the current - edit line is redrawn in place. -08-07-01 A bug in the handling of shared variables when inside an embedded - type has been fixed. -08-06-29 A bug in multiline edit mode which occurred when the prompt length - was three characters or less has been fixed. -08-06-23 A bug in which the SIGCLD was not be triggered when background - jobs completed has been fixed. -08-06-23 KSH_VERSION added as a name reference to .sh.version. -08-06-20 type now outputs 'special builtin' for special builtins. -08-06-19 A couple of bugs in multi-dimensional arrays have been fixed. -08-06-19 A bug in which a syntax error in a dot script could generated - a syntax error in the next subsequent command has been fixed. -08-06-17 Reduced the maximum function call depth to 2048 to avoid exceptions - on some architectures. -08-06-16 A bug in which printf "%B" could generate an exception when the - specified variable was not set has been fixed. -08-06-16 When typeset -p is followed by variable names, it now displays - the attributes names and values for the specific names. -08-06-14 A bug that could effect the drawing of the screen from multiline - emacs or gmacs mode when walking up the history file has been fixed. -08-06-13 A bug in which a compound variable defined in a subshell could - have side effects into the parent shell has been fixed. -08-06-13 A number of bugs related to using .sh.level to set the stack from - for DEBUG traps have been fixed. -08-06-13 The .sh.lineno variable has been added. When .sh.level is changed - inside a DEBUG trap, the .sh.lineno contains the calling line number - for the specified stack frame. -08-06-13 The .sh.level variable has been documented and now works. -08-06-11 The -C option has been added to read for reading compound command - definitions from a file. -08-06-11 The . command is now permitted inside a compound command definition. - The dot script can contain declaration commands and dot commands. -08-06-09 Add -C option to typeset so that typeset -C foo, is equivalent - to foo=(). -08-06-09 Added -n warning message for typeset option orderings that are valid - with ksh88 but not valid with ksh93, for example Lx5. -08-06-09 A bug in which the return value for an assignment command containing - a command substitution with that failed was zero when the assignment - contained redirections has been fixed. -08-06-09 A bug in the quoting of $ inside a ERE pattern ~(E)(pattern) - has been fixed. -08-06-06 A bug when processing `` command substitution with the character - sequence \$' has been fixed. -08-06-02 When defining a type, the typeset -r attribute causes this field - to be required to be specified for each instance of the type and - does not allow a default value. -08-06-02 Several bugs in which compound variables were modified by - subshells have been fixed. -08-05-22 The ceil function has been added to the math functions. -08-05-21 A bug in which a name reference defined in a function and passed - as an argument to another function could cause an incorrect binding. -08-05-21 A bug in freeing compound variables that are local to functions - has been fixed. -08-05-19 The array expansions ${array[sub1..sub2]} and ${!array[sub1..sub2]} - to expand to the value (or subscripts) for array between sub1 and - sub2 inclusive. For associative arrays, the range is based on - location in the POSIX locale. The .. must be explicit and cannot - result from an expansion. -08-05-15 The trap on SIGCLD is no longer triggered by the completion of - the foreground job as with ksh88. -08-05-14 A bug in the implementation of the editing feature added on - 07-09-19 in emacs mode has been fixed. -08-05-12 A bug in processing the test built-in with parenthesis has been - fixed. -08-05-12 The unset built-in now returns non-zero when deleting an array - subscript that is not set. -08-05-08 Changing the value of HISTFILE or HISTSIZE will cause the old - history file to be close and reopened with the new name or size. -08-05-08 When FPATH is changed functions that were found via a path search - will be searched for again. -08-05-08 A parser bug in which reserved words and labels were recognized - inside compound indexed array assignment after a new-line has - been fixed. -08-05-07 A bug in getopts when handling numerical option arguments has - been fixed. -08-05-07 The typeset -S option was added for variables outside type - definitions to provide a storage class similar to C static - inside a function defined with function name. When outside - type definitions and outside a function, the -S option cause - the specified variable so be unset before the assignment and - before the remaining attributes are supplied. -08-05-07 A bug that affected the cursor movement in multiline mode when - a character was deleted from near the beginning of the any - line other than the first. -08-05-01 In multiline edit mode, the refresh operation will now clear - the remaining portion of the last line. -08-05-01 A bug in computing prompt widths for the edit modes for prompts - with multibyte characters has been fixed. -08-05-01 A bug in the multiline edit mode which could cause the current - line to be displayed incorrectly when moving backwards from third - or higher line to the previous line has been fixed. -08-05-01 A bug in which options set in functions declared with the function - name syntax were carried across into functions invoked by these - functions has been fixed. -08-04-30 A bug which could cause a coprocess to hang when the read end - is a builtin command has been fixed. -08-04-30 The emacs and vi editors have been modified to handle window - change commands as soon as they happen rather than waiting for - the next command. -08-04-28 A bug in which ${!x} did not expand to x when x was unset has been - fixed. -08-04-27 A bug in which the assignment x=(typeset -a foo=([0]=abc)) created - x.foo as an associative array has been fixed. -08-04-25 A bug in which $# did not report correctly when there were more - than 32K positional parameters has been fixed. -08-04-04 Choose the name _ as the sub-variable that holds type or instance - specific data used by discipline functions. -08-03-27 A bug in which the terminal group was not given back to the parent - shell when the last part of a pipeline was handled by the parent shell - and the other parts of the pipeline complete has been fixed. - The symptom was that the pipeline became uninterruptable. -08-03-25 A bug in restricted mode introduced in ksh93s that caused scripts - that did not use #! to executed in restricted mode has been fixed. -08-03-25 A bug in which the pipefail option did not work for a pipeline - within a pipeline has been fixed. -08-03-24 A bug in which OPTIND was not set correctly in subshells has - been fixed. -08-03-24 A bug which could cause a memory exception when a compound variable - containing an indexed array with only element 0 defined was expanded. -08-03-20 A bug in which ${!var[sub].*} was treated as an error has been fixed. -08-03-20 Associative array assignments of the form ([name]=value ...) - now allow ; as well as space tab and new line to separate elements. -08-03-18 A buffering problem in which standard error was sometimes - not flushed before sleep has been fixed. -08-03-17 A bug in which a signal sent to $$ while in a subshell would be - sent to the subshell rather than the parent has been fixed. -08-03-17 --default option added to set(1) to handle set +o POSIX semantics. - set --state added as a long name alias for set +o. -08-03-14 A bug in which using monitor mode from within a script could - cause the terminal group to change has been fixed. -08-03-10 The new ${...} command substitution will treat the trailing } - as a reserved word even if it is not at the beginning of a command, - for example, ${ date }. -08-03-10 If the name of the ENV begins with /./ or ././ then the - /etc/ksh.kshrc file will not be executed on systems that support - this interactive initialization file. -08-03-07 A bug in which ksh -i did not run the ENV file has been fixed. -08-03-07 A bug in which ulimit did not always produce the same output as - ulimit -fS has been fixed. -08-03-04 A bug in multiline mode in emacs and vi mode which could cause the - cursor to be on the wrong line when interrupt was hit has been fixed. -08-03-03 The change made in ksh93s+ on 07-06-18 in which braces became - optional for ${a[i]} inside [[...]] was restored in the case - where the argument can be a pattern. -08-03-03 A bug in which creating a name reference to an associative array - instance would fail when the subscript contained characters [ or - ] has been fixed. -08-02-29 The redirection operator >; has been added which for non-special - files, generates the output in a temporary file and writes the - specified file only of the command has completed successfully. -08-02-15 A bug in ${var/pattern/string} for patterns of the form ?(*) and +(*) - has bee fixed. -08-02-07 A bug in which test \( ! -e \) produced an error has been fixed. -08-02-14 The typeset -a option can now optionally be followed by the name - of an enumeration type which allows subscripts to be enumerations. -08-02-14 The enum builtin which creates enumeration types has been added. -08-02-12 The backoff logic when there are no more processes has been fixed. -08-02-07 The -X option has been added to typeset. The -X option creates - a double precision number that gets displayed using the C99 %a - format. It can be used along with -l for long double. -08-01-31 The -T option to typeset has been added for creating typed - variables. Also the -h and -S options have been added to - typeset that are only applicable when defining a type. -08-01-31 The prefix expansion operator @ has been added. ${@name} - expands to the type of name or yields the attributes. -07-11-15 A bug in the macro expander for multibyte characters in which - part of the character contains a file pattern byte has been fixed. -07-10-03 A bug in which : was not allowed as part of an alias name has been - fixed. -07-09-26 A bug in which appending a compound variable to a compound variable - or to an index array didn't work has been fixed. -07-09-19 In both emacs and vi edit mode, the escape sequence \E[A (usually - cursor up, when the cursor is at the end of the line will fetch - the most recent line starting with the current line. -07-09-18 The value of ${!var} was correct when var was a reference to an - array instance. -07-09-18 The value of ${!var[sub]} was not expanding to var[sub] and this - was fixed. It also fixed ${name} where name is a name reference - to var[sub]. -07-09-18 It is now legal to create a name reference without an initialization. - It will be bound to a variable on the first assignment. -07-08-30 A discipline function can be invoked as ${x.foo} and is equivalent - to ${ x.foo;} and can be invoked as x.foo inside ((...)). -07-07-09 A bug in which typeset -a did not list indexed arrays has been - fixed. -07-07-03 The command substitution ${ command;} has been added. It behaves - like $(command) except that command is executed in the current - shell environment. The ${ must be followed by a blank or an - operator. - -08-04-17 --- Release ksh93s+ --- -08-04-17 A bug in which umask was not being restored correctly after a - subshell has been fixed. -08-04-15 A bug in which sending a STOP signal to a job control shell started - from within a shell function caused cause the invoking shell to - terminate has been fixed. -08-04-11 A bug which caused $(exec > /dev/null) to go into an infinite loop - has been fixed. -08-03-27 A bug in which typeset -LZ was being treated as -RZ has been fixed. -08-03-06 A bug with ksh -P on systems that support the the profile shell, - in which it would exit after running a non-builtin has been fixed. -08-01-31 A bug in which command substitution inside ((...)) could cause - syntax errors or lead to core dumps has been fixed. -08-01-17 A bug in which discipline functions could be deleted when invoked - from a subshell has been fixed. -08-01-17 A bug in which a command substitution consisting only of - assignments was treated as a noop has been fixed. -08-01-17 A bug in which discipline functions invoked from withing a - compound assignment could fail has been fixed. -08-01-16 Incomplete arithmetic assignments, for example ((x += )), now - generate an error message. -08-01-16 A bug in which a set discipline defined for a variable before - an array assignment could cause a core dump has been fixed. -08-01-03 A bug in on some systems in which exit status 0 is incorrectly - returned by a process that catches the SIGCONT signal is stopped - and then continued. -07-12-13 A race condition in which a program that has been stopped and then - continued could loose the exit status has been fixed. -07-12-12 Code to check for file system out of space write errors for all - writes has been added. -07-12-11 A bug in the macro expander for multibyte characters in which - part of the character contains a file pattern byte has been fixed. -07-12-06 A bug in the emacs edit mode when multiline was set that output - a backspace before the newline to the screen has been fixed. -07-12-04 A bug in which using <n>TAB after a variable name listing expansion - in the edit modes would cause the $ to disappear has been fixed. -07-11-28 A bug in which setting IFS to readonly could cause a subsequent - command substitution to fail has been fixed. -07-11-27 A work around for a gcc 4.* C99 "feature" that could cause a job - control shell to go into an infinite loop by adding the volatile - attribute to some auto vars in functions that call setjmp(). -07-11-27 A bug in which the shell could read ahead on a pipe causing the - standard input to be incorrectly positioned has been fixed. -07-11-27 A bug in which compound variable UTF-8 multibyte values were not - expanded or traced properly has been fixed. -07-11-21 A bug where an unbalanced '[' in a command argument was not treated - properly has been fixed. -07-11-15 A bug in which compatibility mode (no long option names) getopts(1) - incorrectly set the value of OPTARG for flag options has been fixed. -07-11-15 A bug in which "hash -- name" treated "--" as an invalid name operand - has been fixed. -07-11-15 typeset now handles "-t -- [-r] [--]" for s5r4 hash(1) compatibility. -07-11-15 A bug in which the umask builtin mis-handled symbolic mode operands - has been fixed. -07-11-15 Bugs in which shell arithmetic and the printf builtin mis-handled the - signs of { -NaN -Inf -0.0 } have been fixed. -07-11-15 The full { SIGRTMIN SIGRTMIN+1 ... SIGRTMAX-1 SIGRTMAX } range - of signals, determined at runtime, are now supported. -07-11-15 A bug in which creating an index array with only subscript 0 created - only a simple variable has been fixed. -07-11-14 A bug in which appending to an indexed array using the form - name+=([sub]=value) could cause the array to become an associative - array has been fixed. -07-11-14 A bug in which typeset without arguments could coredump if a - variable is declared as in indexed array and has no elements has - been fixed. -07-11-14 A bug in which creating a local SECONDS variable with typeset in - a function could corrupt memory has been fixed. -07-11-14 A bug which could cause a core dump when a script invoked by name - from a function used compound variables has been fixed. -07-11-05 A bug in which printf %d "'AB" did not diagnose unconverted characters - has been fixed. -07-11-05 printf %g "'A" support added for all floating point formats. -07-11-01 A bug in which typeset -f fun did not display the function definition - when invoked in a subshell has been fixed. -07-10-29 The sleep builtin was fixed so that all floating point constants - are valid operands. -07-10-10 A bug in which the locale was not being restored after - LANG=value command has been fixed. -07-09-20 A bug in which a nameref to a compound variable that was local - to the calling function would not expand correctly when displaying - is value has been fixed. -07-09-19 A bug which cause cause a core dump if .sh.edchar returned - 80 characters or more from a keyboard trap has been fixed. -07-09-14 A bug in which could cause a core dump when more than 8 file - descriptors were in use has been fixed. -07-09-10 A bug in which creating a name reference to an instance of - an array when the array name is itself a reference has been fixed. -07-09-10 The file completion code has been modified so that after an = in - any word, each : will be considered a path delimiter. -07-09-06 A bug in which subprocess cleanup could corrupt the malloc() heap - has been fixed. -07-08-26 A bug in which a name reference to an associative array instance - could cause the subscript to be evaluated as an arithmetic expression - has been fixed. -07-08-22 A bug in which the value of an array instance was of a compound - variable was not expanded correctly has been fixed. -07-08-14 A bug which could cause a core dump when a compound assignment was - made to a compound variable element with a typeset -a attribute - has been fixed. -07-08-08 A bug in which a trap ignored in a subshell caused it to be - ignored by the parent has been fixed. -07-08-07 A bug in which the set command would generated erroneous output - for a variable with the -RZ attribute if the variable name had been - passed to a function has been fixed. -07-08-02 A bug in which read x[1] could core dump has been fixed. -07-08-02 A second bug in which after read x[sub] into an associative array - of an element that hasn't been assigned could lead to a core dump - has been fixed. -07-07-31 A bug in which a pipeline that completed correctly could have - an exit status of 127 when pipefail was enabled has been fixed. -07-07-09 The SHOPT_AUDIT compile option has been added for keyboard logging. -07-06-25 In vi insert mode, ksh no longer emits a backspace character - before the carriage return when the newline is entered. -07-06-25 A bug in which pipefail would cause a command to return 0 - when the pipeline was the last command and the failure happened - on a component other than the last has been fixed. -07-06-25 A bug in the expansion of ${var/pattern/rep} when pattern or rep - contained a left parenthesis in single quotes has been fixed. -07-06-18 The braces for a subscripted variable with ${var[sub]} are now - optional when inside [[...]], ((...)) or as a subscript. -07-05-28 A bug in brace expansion in which single and double quotes did - not treat the comma as a literal character has been fixed. -07-05-24 The -p option of whence now disables -v. -07-05-23 Several bug fixes in compound variables and arrays of arrays - have been made. -07-05-15 A bug in which the %B format of printf was affected by the - locale has been fixed. -07-05-14 A bug in which \ was not removed in the replacement pattern with - ${var/pattern/rep} when it was not followed by \ or a digit has - been fixed. -07-05-10 A bug in which ksh -R file core dumped if no script was specified - has been fixed. it not displays an error message. -07-05-07 Added additional Solaris signals to signal table. -07-04-30 A bug in which a pipeline with command substitution inside a - function could cause a pipeline that invokes this function to - hang when the pipefail option is on has been fixed. -07-04-30 Added -q to whence. -07-04-18 A small memory leak with each redirection of a non-builtin has - been fixed. -07-03-08 A bug in which set +o output command line options has been fixed. -07-03-08 A bug in which an error in read (for example, an invalid variable - name), could leave the terminal in raw mode has been fixed. -07-03-06 A bug in which read could core dump when specified with an array - variable with a subscript that is an arithmetic expression has - been fixed. -07-03-06 Several serious bugs with the restricted shell were reported and - fixed. -07-03-02 If a job is stopped, and subsequently restarted with a CONT - signal and exits normally, ksh93 was incorrectly exiting with - the exit status of the stop signal number. -07-02-26 M-^L added to emacs mode to clear the screen. -07-02-26 A bug in which setting a variable readonly in a subshell would - cause an unset error when the subshell completed has been fixed. -07-02-19 The format with printf uses the new = flag to center the output. -07-02-19 A bug in which ksh93 did not allow multibyte characters in - identifier names has been fixed. -07-02-19 A bug introduced in ksh93 that causes global compound variable - definitions inside functions to exit with "no parent" has been fixed. -07-02-19 A bug in which using compound commands in process redirection - arguments would give syntax errors <(...) and >(...) has been fixed. -07-01-29 A bug which caused the shell to core dump which can occur when a - built-in exits without closing files that it opens has been fixed. -07-01-26 A bug in which ~(E) in patterns containing \ that are not inside () - has been fixed. - -06-12-29 --- Release ksh93s --- -06-12-29 A bug in which the value of IFS could be changed after a command - substitution has been fixed. -06-12-22 /dev/(tcp|udp|sctp)/HOST/SEVRICE now handles IPv6 addresses on - systems that provide getaddrinfo(3). -06-12-19 A -v option was added to read. With this option the value of - the first variable name argument will become the default value - when read from a terminal device. -06-11-20 A bug in which "${foo[@]:1}}" expands a null argument (instead of - no argument), when foo[0] is not empty has been fixed. -06-11-16 The discipline functions have been modified to allow each subscript - to act independently. Currently the discipline function will not - be called when called from a discipline function of the same variable. -06-11-14 A bug which could cause a core dump if a file descriptor for - an internal file was closed from with a subshell has been fixed. -06-10-30 The redirections <# pattern, and <## pattern have been added. - Both seek forward to the beginning of the next line that contains - the pattern. The <## form copies the skipped portion to standard - output. -06-10-26 On systems that support stream control transport, the virtual file - name /dev/sctp/host/port can now be used to establish connections. -06-10-26 The printf modifier # when used with d produces units in thousands - with a single letter suffix added. The modifier # when used with - the i specification provides units of 1024 with a two letter suffix. -06-10-24 The value of $! is now set to the process id of a job put - into the background with the bg command as required by POSIX. -06-10-23 A bug in which the value of $! was affected by a background - job started from a subshell has been fixed. -06-10-23 A bug in ${var:offset:len} in multibyte locales has been fixed. -06-10-15 The remaining math functions from C99 were added for any system - that supports them. -06-10-13 The klockwork.com software detected a few coding errors that - have been fixed. -06-10-12 A bug when skipping over `...` with ${x:=`...`} when x is set - has been fixed. -06-10-11 A bug in process floating constants produced by the %a format - of printf has been fixed. -06-10-06 A bug in which IFS was not being restored correctly in some - cases after a subshell has been fixed. -06-10-06 A bug in which pipefail was not detecting some failures in - pipelines with 3 or more states has been fixed. -06-10-03 A bug in the processing of >(...) with builtins which could - cause the builtin to hang has been fixed. -06-10-03 A bug in the for loop optimizer which causes >(...) process - substitution to be ignored has been fixed. -06-09-17 The -a option was added to typeset for indexed arrays. This - is only needed when using the ([subscript]=value ...) form. -06-09-06 The showme option was added. Each simple command not beginning - with a redirection and not occurring with in the while, until, if, - select condition can be preceded by a semi-colon which will - be ignored when showme is off. When showme is on, any command - preceded by a colon will be traced but not executed. -06-08-16 As a new feature, a leading ~(N) on a pattern has no effect - except when used for file expansion. In this case if not - matches are found, the pattern is replaced by nothing rather - than itself. -06-08-11 A bug in the expansion of ${.sh.match[i]:${#.shmatch[i]}} has - been fixed. -06-08-10 The read builtin options -n and -N have been modified to treat - the size as characters rather than bytes unless storing into a - binary (typeset -B) variable. -06-07-27 When the here document operator << is followed directly by a # - rather than a -, the first line of the here-document determines - how much whitespace is removed for each line. -06-07-26 A bug in the C-shell history (enabled with set -H) in which the - history event !$ was not processed has been fixed. -06-07-21 A bug on some systems in which assigning PATH on a command line - would not take effect has been fixed. -06-07-20 Add ksh93 and rksh93 as allowable names for ksh binaries. -06-07-20 Removed the SHOPT_OO compilation option which was only partially - implemented. -06-07-20 The ability to use egrep, grep, and fgrep expressions within - shell patterns has been documented. -06-07-17 A bug with arithmetic command expressions for locales in which - the comma is a thousands separator has been fixed. -06-07-13 The default HISTSIZE was increased from 128 to 512. -06-07-13 A multibyte problem with locales that use shift codes has been fixed. -06-06-23 A number of bug fixes for command, file, and variable completion - have been mode. -06-06-20 Floating point division by zero now yields the constant Inf or -Inf - and floating functions with invalid arguments yield NaN. -06-06-20 The floating point constants Inf and NaN can be used in arithmetic - expressions. -06-06-20 The functions isinf(), isnan(), tanhl() have been added for - arithmetic expressions. -06-06-13 Internal change to use ordering for variables instead of hashing - to speed up prefix matching. -06-06-13 A window between fork/exec in which a signal could get lost - and cause a program to hang has been eliminated -06-06-13 A bug in edit completion with quoted strings has been fixed. -06-06-07 The restricted options can now be enabled by set as well as on - the command line. Once set, it can not be disabled. -06-06-04 Modified built-in binding so that for systems for which /bin - and /usr/bin are the same, a builtin bound to /bin will get - selected when either /bin or /usr/bin is scanned. -06-06-04 Added literal-next character processing for emacs/gmacs mode. - This change is not compatible with earlier versions of ksh93 - and ksh88 when the stty lnext is control-v. The sequence - escape-control-v will display the shell version. -06-05-31 Modified emacs and vi mode so that entering a TAB after a partial - TAB completion, generates a listing of possible completions. - After the second TAB, a number followed by a TAB will perform - the completion with the corresponding item. -06-05-19 Modified arithmetic so that conversions to strings default to - the maximum number of precision digits. -06-05-16 Bug fixes for multibyte locales. -06-05-10 The =~ operator was added to [[...]] and [[ string ~= ERE ]] - is equivalent to [[ string == ~(E)ERE ]]. -06-04-25 A bug in the vi edit mode which could cause the shell to core dump - when switching from emacs mode. -06-04-17 A bug in which using LANG or LC_ in assignment lists with builtins - did not restore the localed correctly has been fixed. -06-04-04 A bug in which discipline functions could not be added to variables - whose names started with .sh has been fixed. -06-03-28 The -s option to typeset was added to modify -i to indicate short - integers. -06-03-28 A bug in which variables assignment lists before functions - defined with function name were not passed on the functions - invoked by this function has been fixed. -06-03-28 A bug in which name references defined within a function defined - with function name could not be used with compound variables has - been fixed. -06-03-27 A bug in which read <&p (print >&p) would cause the coprocess input - (output) pipe to close before reading from (after writing to) - it has been fixed. -06-02-28 A bug in which stopping a job created with the hist builtin command - would create a job that could not be restarted has been fixed. - -06-01-24 --- Release ksh93r --- -06-01-24 A bug in which running commands with standard output closed would - not work as expected has been fixed. -06-01-23 A bug in which print -u<n> could fail when file descriptor <n> was - open for writing has been fixed. -06-01-19 The ?: arithmetic operator fixed to work when the operation after - the colon was an assignment. -05-12-24 A bug which could lead to a core dump when elements of a compound - variable were array elements, i.e. foo=(bar=(1 2)), has been fixed. -05-12-13 An arithmetic bug in which x+=y+=z was not working has been fixed. -05-12-13 An arithmetic bug in which x||y was returning x when x was non-zero - rather than 1 has been fixed. -05-12-07 The aliases for integer and float have been changed to use attributes - -li and -lE to handle long long and long double types. -05-12-07 The histexpand (-H) option has been added which allows C-shell - style history expansions using the history character !. -05-12-07 The multiline option was added which changes that way the edit - modes handle lines longer than the window width. Instead of - horizontal scrolling, multiple lines on the screen are used. -05-12-05 The whence builtin now returns an absolute pathname when the - command is found in the current directory. -05-11-29 A bug which caused ksh -c '[[ ! ((' to core dump rather than - report a syntax error has been fixed. -05-11-29 A bug when reading fixed length records into typeset -b variables - which caused a zero byte to terminate the value has been fixed. -05-11-22 The ability to seek to an offset within a file has been added - with the new I/O redirection operators, <# and >#. Currently, - these redirection operators must be followed by ((expr)) - but in a future release, it should be able to used to seek forward - to the specified shell pattern. In addition $(n<#) expands to the - current byte offset for file descriptor n. -05-11-22 The .sh.match array variable is now set after each [[ ... ]] - pattern match. Previously it was only set for substring matches. -05-10-17 A bug in which the library path variable could be prefixed - with a directory when a .path file was not encountered in - the directory of the executable has been fixed. -05-09-15 A for/while loop optimizer bug in which $OPTIND was not - correctly expanded has been fixed. -05-09-05 A bug in which a history command that invoked a history - command could go into an infinite loop has been fixed. -05-08-31 In the case that IFS contains to adjacent new-lines so that - new-line is not treated as a space delimiter, only a single - new-line is deleted at the end of a command substitution. -05-08-19 When a tilde substitution expands to the / directory and is - followed by a /, it is replaced by the empty string. -05-08-16 A bug in which n<&m did not synchronize m has been fixed. -05-08-16 A bug in which process substitution ( <() and >() ) was not - working within for and while loops has been fixed. -05-07-24 A bug in which the pattern ~(E)(foo|bar) was treated as a syntax - error has been fixed. -05-07-24 A bug in completion with <n>=, where n was the one of the - previous selection choices has been fixed. -05-07-21 A bug with multibyte input when no edit mode was specified which - caused the input line to shift left/right has been fixed. -05-06-24 A race condition which could cause the exit status to get lost - on some fast systems has been fixed. -05-06-21 A bug in which nested patterns of the form {m,n}(pat) would cause - syntax errors has been fixed. -05-06-21 A bug in the macro expander has been fixed which could cause a - syntax error for an expansion of the form ${x-$(...)} when - x is set and the command substitution contained certain strings. -05-06-08 On systems for which echo does not do System V style \ expansions, - the -e option was added to enable these expansion. -05-06-08 A bug in which ${var op pattern} to not work when inside an - arithmetic expression has been fixed. -05-05-23 An extension to shell patterns that allows matching of nested - groups while skipping over quoted strings has been added. -05-05-18 A bug in which the line number for errors was not correct for - functions loaded from FPATH has been fixed. -05-04-18 A bug in which the exit status $? is not set when a trap triggered - by the [[...]] command is executed has been fixed. -05-04-08 Redirection operators can be directly preceded with {varname} - with no intervening space, where varname is a variable name which - allows the shell to select a file descriptor > 10 and store it - into varname. -05-04-08 SHOPT_CMDLIB_BLTIN=1 now includes <cmdlist.h> generated table. -05-04-07 [[ -o ?option ]] is true if "option" is a supported option. -05-04-05 A bug in handling file completion with spaces in the names - has been fixed. -05-03-25 The SIGWINCH signal is caught by default to keeps the LINES and - COLUMNS variables in sync with the actual window size. -05-03-25 Building ksh with SHOPT_REMOTE=1 causes ksh to set --rc if stdin is - a socket (presumably part of a remote shell invocation.) -05-03-25 Building ksh with SHOPT_SYSRC=1 causes interactive ksh to source - /etc/ksh.kshrc (if it exists) before sourcing the $ENV file. -05-03-25 {first..last[..incr][%fmt]} sequences added to brace expansions - when braceexpand is enabled. -05-03-03 A bug where a SIGCHLD interrupt could cause a fifo open to fail has - been fixed. -05-02-25 A bug in which a builtin command run in the background could - keep a file descriptor open which could cause a foreground - process to hang has been fixed. -05-02-24 A bug where builtin library commands (e.g., date and TZ) failed to - detect environment variable changes has been fixed. -05-02-22 The read builtin and word splitting are now consistent with respect - to IFS -- both treat IFS as field delimiters. -05-02-22 The read builtin no longer strips off trailing delimiters that - are not space characters when there are fewer variables than fields. -05-02-17 A builtin bug on systems where dlsym(libcmd) returns link-time - bindings has been fixed. -05-02-12 A bug in which the lib_init() function for .paths BUILTIN_LIB - libraries was not called has been fixed. -05-02-06 A bug on some systems in which moving the write end of a co-process - to a numbered file descriptor could cause it to close has been fixed. -05-02-06 A bug in the vi-edit mode in which the character under the cursor - was not deleted in some cases with the d% directive has been fixed. -05-02-06 A bug where external builtin stdout/stderr redirection corrupted - stdout has been fixed. -05-02-04 A bug where times formatting assumed CLK_TCK==60 has been fixed. - -05-01-11 --- Release ksh93q --- -05-01-11 A bug in the integral divide by zero check has been fixed. -05-01-11 The -l option has been added to read /etc/profile and - $HOME/.profile, if they exist, before the first command. -05-01-11 An argument parsing bug that caused `kill -s x -- n' to fail has - been fixed. -05-01-11 The .paths file, introduced in ksh93m, which can appear in - any directory in PATH, now allows a line of the form 'BUILTIN_LIB=.' - When a command is searched for this directory, and the full path - matches the path of the built-in version of the command (listed - by the 'builtin' command) then the built-in version of the command - is used. When ksh is built with SHOPT_CMDLIB_DIR=1 then all libcmd - functions become builtins with the '/opt/ast/bin/' directory prefix. -05-01-10 A bug in which a nameref to a compound name caused a core dump has - been fixed. -05-01-09 A bug in which some SIGCHLD interrupts (from child processes exiting) - caused a fatal print/echo error diagnostic has been fixed. -04-12-24 A bug in which some SIGCHLD interrupts (from child processes exiting) - corrupted the internal process/job list, sometimes causing the shell - to hang, has been fixed. -04-12-01 A bug in which typeset -Fn truncated less than n digits for large - numbers has been fixed. -04-11-25 A bug in which standard error could be closed after a redirection - to /dev/stderr has been fixed. -04-11-17 A bug in which an expansion of the form ${array[@]:3} could expand - to ${array[0]} when ${array[3]} was not set has been fixed. -04-10-22 The -E or -orc command line option reads ${ENV-$HOME/.kshrc} file. -04-10-22 `-o foo' equivalent to `+o nofoo', `-o nobar' equivalent to `+o bar'. - `--foo' equivalent to `-o foo', `--nofoo' equivalent to `+o foo' -04-10-05 The .paths file, introduced in ksh93m, which can appear in - any directory in PATH, now allows a line of the form - 'BUILTIN_LIB=libname'. When a command is searched for this directory, - the shared library named by libname will first be searched for a - built-in version of the command. -04-09-03 <<< here documents now handle quotes in the word token correctly. -04-08-08 The maximum size for read -n and and read -N was increased from - 4095 to 32M. -04-08-04 printf %q was modified so that if an no operand was supplied, no - no output would be generated rather than a quoted empty string. -04-08-01 The -n and -N options of the read builtin has been modified - when reading variables with the binary attribute so that the - data is stored directly rather than through assignment. -04-08-01 The shcomp command has been modified to process alias commands - under some conditions. -04-07-31 The .sh.match variable added in ksh93l, now works like other - indexed arrays. -04-07-08 A loop optimizer bug which occurs when typeset is used in - a for or while loop inside a function has been fixed. -04-06-24 The number of subexpressions in a pattern was increased to 64 - from the current number of 20. -04-06-17 The -t option to read was modified to allow seconds to be - specified as any arithmetic expression rather than just - an integral number of seconds, for example even -t 'sin(.5)' - is now valid. -04-06-16 Two small memory leak problems were fixed. -04-06-15 A bug in ${var/pattern/"string"} which occurred when string - contained pattern matching characters has been fixed. -04-05-08 printf $'%d\n' produced an erroneous error message and has - been fixed. -04-05-24 A bug in which an associative array without any elements could - cause a core dump when a script with an associative array with - the same name was declared in a script invoked by name has - been fixed. -04-05-11 A bug in which an exec statement could close the script that - is being processed in a script that is run by name causing - a failure has been fixed. -04-04-28 If the first character of assignment to an integer variable was 0, - the variable had been treated as unsigned. This behavior was - undocumented and has been removed. -04-04-05 A bug in which the positioning of standard input could be incorrect - after reading from standard input from a subshell has been fixed. -04-03-30 A bug in the for loop optimizer which in rare cases could cause - memory corruption has been fixed. -04-03-29 The preset alias source='command .' has been added. -04-03-29 A bug introduced in ksh93p on some systems in which invoked by - name with #! on the first line would not get the signals handling - initialized correctly has been fixed. -04-03-29 A bug introduced in ksh93p in which a HUP signal received by - a shell that is a session group leader was not passed down to - its children has been fixed. - -04-02-28 --- Release ksh93p --- -04-02-28 The ability to apply an append discipline to any variable has - been added. -04-02-14 A bug in which the exportall option (set -a) would cause incorrect - results for arrays has been fixed. -04-02-02 A bug in which an exported array would pass more than - the first element to a script invoked by name has been fixed. -04-02-02 A bug on some systems in which name=value pairs preceding a script - invoked by name was not getting passed to the script has been fixed. -04-01-20 A bug in which an unset discipline function could cause a core - dump on some systems has been fixed. -04-01-12 A bug in which a continue or break called outside a loop from - inside a function defined with name() syntax could affect - the invoking function has been fixed. -04-01-08 If a command name begins with ~, only filename completion will be - attempted rather than pathname completion using the builtin editors. -04-01-08 A bug in the vi edit mode in which the wrong repeat count on - multiple word replacements with the . directive has been fixed. -04-01-06 Backspace characters are now handled correctly in prompt strings. -04-01-06 The getopts builtin has been modified to accept numerical - arguments of size long long on systems that support this. -04-01-06 A bug in which unsetting all elements of an associative array - would cause it to be treated as an indexed array has been fixed. -03-12-15 A bug in which a quoted string ending with an unescaped $ would - delete the ending $ in certain cases has been fixed. -03-12-05 A bug in which the shell could hang when set -x tracing a command - when an invalid multibyte character is encountered has been fixed. -03-12-05 On some systems, if the KEYBD trap is set, then commands that use - the meta key were not processed until return was hit. This - has been fixed. -03-12-05 A problem which occurred when the login shell was not a group - leader that could cause it to fail has been fixed. -03-12-05 A problem in which a shell could core dump after receiving a signal - that should cause it to terminate while it was in the process - of acquiring more space has been fixed. -03-12-05 If ENV is not specified, the shell will default to $HOME/.kshrc - for interactive shells. -03-11-21 A bug introduced in ksh93o in which the DEBUG trap could get - disabled after it triggered has been fixed. -03-11-04 A bug in which using arithmetic prefix operators ++ or -- on a - non-lvalue could cause a core dump has been fixed. -03-11-04 A bug in which leading zeros were stripped from variable - expansions within arithmetic computation to avoid being treated - as octal constants when they should not have, has been fixed. -03-10-08 A bug introduced in ksh93o in which a large here document inside - a function definition could get corrupted has been fixed. -03-09-22 A bug in which the .get discipline function was not being - called when a string variable was implicitly referenced from - within a numerical expression has been fixed. -03-09-22 A bug in which a script without a leading #! could get executed - by /bin/sh rather than the current shell on some systems has - been fixed. -03-09-12 To improve conformance with ksh88, leading zeros will be ignored - when getting the numerical value of a string variable so that - they will not be treated as octal constants. -03-09-03 The builtin kill command now processes obsolete invocations - such as kill -1 -pid. -03-09-02 The restriction on modifying FPATH in a restricted shell (sh -r) - has been documented. -03-09-02 The restricted shell (sh -r) has been modified to disallow - executing command -p. -03-08-07 A bug in which the KEYBD trap was not being invoked when - characters with the 8th bit set has been fixed. -03-08-02 A parser bug introduced in ksh93o which caused the character - after () in a Posix function definition to be skipped - when reading from standard input has been fixed. -03-08-01 A bug in which "${foo#pattern}(x)" treated (x) as if it were - part of the pattern has been fixed. -03-08-01 The command -x option has been modified so that any trailing - arguments that do expand to a single word will be included - on each invocation, so that commands like command -x mv * dir - work as expected. - -03-07-20 --- Release ksh93o+ --- -03-07-20 A bug in which could cause memory corruption when a posix - function invoked another one has been fixed. -03-07-15 A bug in which a file descriptor>2 could be closed before - executing a script has been fixed. -03-07-15 A parsing error for <() and >() process substitutions inside - command substitution has been fixed. -03-07-15 A parsing error for patterns of the form {...}(...) when - used inside ${...} has been fixed. -03-07-15 An error in which expanding an indexed array inside a compound - variable could cause a core dump has been fixed. -03-07-15 A bug in which on rare occasions a job completion interrupt - could cause to core dump has been fixed. -03-06-26 A bug in which process substitution embedded within command - substitution would generate a syntax error has been fixed. -03-96-23 A bug in which ${@:offset:len} could core dump when there - were no arguments has been fixed. -03-96-23 A bug in which ${X[@]:offset:len} could core dump when X - was unset has been fixed. -03-06-22 The -x option was added to the command builtin. If this - option is on, and the number of arguments would exceed ARG_MAX, - the command will be invoked multiple times with a subset of - the arguments. For example, with alias grep='command -x grep, - any number of arguments can be specified. -03-06-14 A bug in which could cause a core dump on some systems with - vi and emacs editors with the MULTIBYTE option has been fixed. -03-06-06 A bug in which the shell could core dump when a script was - run from its directory, and the script name a symlink to a file - beginning with .., has been fixed. -03-06-05 A bug in which the shell could core dump when a child process - that it is unaware of terminates while it is calling malloc() - has been fixed. -03-06-02 An option named globstar (set -G) has been added. When enabled, - during pathname expansion, any component that consists only of ** is - matches all files and any number of directory levels. -03-05-30 A bug in which the PATH search could give incorrect results when - run from directory foo and PATH contained .:foo:xxx has been fixed. -03-05-29 Some changes were made to the code that displays the prompt in edit - mode to better handle escape sequences in the prompt. -03-05-27 I added = to the list of characters that mark the beginning of - a word for edit completion so that filenames in assignments - can be completed. -03-05-20 A bug in which read -N could hang on some systems when reading - from a terminal or a pipe has been fixed. -03-05-19 A bug in which the output of uname from a command substitution - would go to the standard output of the invoking command when - uname was invoked with a non-standard option has been fixed. -03-05-19 A job control bug which would cause the shell to exit because - it hadn't take back the terminal has been fixed. The bug - could occur when running a function that contained a pipeline - whose last element was a function. -03-05-19 A job control timing bug introduced in ksh93o on some systems - which could cause a pipeline to hang if the first component - completed quickly has been fixed. -03-05-13 The read builtin has been modified so that the builtin editors - will not overwrite output from a previous incomplete line. -03-05-13 A bug in which the name of an identifier could have the string - .sh. prefixed to it after expanding a variable whose name begins - with .sh. has been fixed. -03-05-13 A bug in the expansion of $var for compound variables in which - some elements would not be output when the name was a prefix - of another name in the compound variable has been fixed. -03-05-08 The last item in the ksh93o release on 03-01-02 has been - altered slightly to preserve the leading 0's when the - preceding character is a digit. Thus, with typeset -LZ3 x=10, - $(( 1$x)) will be 1010 whereas $(( $x) will be 10. -03-04-25 A bug in which if x is a name reference, then nameref y=x.foo - did not follow x has been fixed. - -03-03-18 --- Release ksh93o --- -03-03-18 A -N unary operator was added to test and [[...]] which returns - true if the file exists and the file has been modified since it - was last read. -03-03-18 The TIMEFORMAT variable was added to control the format for - the time compound command. The formatting description is - described in the man page. -03-03-06 A -N n option was added to read which causes exactly n bytes - to be read unlike -n n which causes at most n bytes to be read. -03-03-03 Three new shell variables were added. The variable .sh.file - stores the full pathname of the file that the current command - was found in. The variable .sh.fun names the current function - that is running. The variable .sh.subshell contains the depth - of the current subshell or command substitution. -03-03-03 When the DEBUG trap is executed, the current command line after - expansions is placed in the variable .sh.command. The trap - is also now triggered before each iteration of a for, select, - and case command and before each assignment and redirection. -03-02-28 Function definitions are no longer stored in the history file so - that set -o nolog no longer has any meaning. -03-02-28 All function definitions can be displayed with typeset -f not - just those stored in the history file. In addition, typeset +f - displays the function name followed by a comment containing the - line number and the path name for the file that defined this function. -03-02-28 A bug in which the value of $LINENO was not correct when executing - command contained inside mult-line command substitutions has been - fixed. -03-02-19 Since some existing ksh88 scripts use the undocumented and - unintended ability to insert a : in front of the % and # parameter - expansion operators, ksh93 was modified to accept :% as equivalent - to % and :# as equivalent to # with ${name op word}. -03-02-14 A bug which could cause a core dump when reading from standard - error when standard error was a pty has been fixed. -03-02-14 The shell arithmetic was modified to use long double on systems - that provide this data type. -03-02-09 A bug in which a function located in the first directory in FPATH - would not be found when the last component of PATH was . and the - current directory was one of the directories in PATH has been fixed. -03-02-07 The trap and kill builtin commands now accept a leading SIG prefix - on the signal names as documented. -03-02-05 A bug in the expansion of ${var/$pattern}, when pattern contained - \[ has been fixed. -03-02-05 A bug in which .sh.match[n], n>0, was not being set for substring - matches with % and %% has been fixed. -03-01-15 A bug in which getopts did not work for numerical arguments specified - as n#var in the getopts string has been fixed. -03-01-09 A bug in which using ${.sh.match} multiple times could lead to - a memory exception has been fixed. -03-01-06 A bug in the expansion of ${var/pattern/$string} in the case that - $string contains \digit has been fixed. -03-01-02 A -P option was added for systems such as Solaris 8 that support - profile shell. -03-01-02 For backward compatibility with ksh88, arithmetic expansion - with ((...)) and let has been modified so that if x is a zero-filled - variable, $x will not be treated as an octal constant. - -02-12-05 --- Release ksh93n+ --- -02-11-30 A bug that can show up in evaluating arithmetic statements that - are in an autoloaded function when the function is autoload from - another function has been fixed. -02-11-30 An optimization bug in which an expansion of the form ${!name.@}, - which occurred inside a for or a while loop, when name is a name - reference, has been fixed. -02-11-18 A bug in which modifying array variables in a subshell could leave - side effects in the parent shell environment has been fixed. -02-11-18 A memory leak when unsetting an associative array has been fixed. -02-11-14 The code to display compound objects was rewritten to make - it easier for runtime extensions to reuse this code. -02-11-14 A change was made to allow runtime builtins to be notified when - a signal is received so that cleanup can be performed. -02-10-31 User applications can now trap the ALRM signal. Previously, - the ALRM signal was used internally and could not be used - by applications. -02-10-31 A bug in which signals received while reading from a coprocess - for which traps were set was not handled correctly has been fixed. -02-10-31 A bug in which a file opened with exec inside a subshell could - be closed before the subshell completed has been fixed. -02-10-21 A bug in which setting PATH or FPATH inside a function might not - take effect has been fixed. -02-10-21 A bug which could cause a core dump when a local SECONDS variable - is defined in a function has been fixed. -02-10-15 A bug in which the associate array name operator ${!array[@]} - could return the same name multiple times has been fixed. -02-10-15 A bug in which the zero'th element of an associative array was - not getting set when an assignment was made without a subscript - specified has been fixed. - -02-09-30 --- Release ksh93n --- -02-09-30 The maximum indexed array size was increased to 16Megs. -02-09-30 A bug which could cause a core dump when changing attributes - of associative array has been fixed. -02-09-30 A bug in which exporting an array variable would not export the - 0-th element has been fixed. -02-09-30 A bug in which an array assignment of the form a=($a ...) would unset - 'a' before the right hand side was evaluated has been fixed. -02-09-27 A bug in which the error message for ${var?message} when var was - null or unset did not contain the variable name var has been fixed. -02-09-27 A bug in which closing file descriptors 0 through 2 could - cause a subsequent here document to fail has been fixed. -02-09-14 A bug in whence which occurs when the specified name contained - a / has been fixed. -02-09-14 A bug in the parser for strings of the form name$((expr))=value - has been fixed. -02-09-14 A for loop optimization bug in which the number of elements in - an array was treated as an invariant has been fixed. -02-09-09 A bug in which redirection or closing of a file descriptor between - 3 and 9 could cause a subsequent here document to fail has been - fixed. -02-09-09 A bug in which a background job was not removed from the job list - when a subshell completed has been fixed, for example (prog&). -02-09-03 A bug in which an assignment of the form name=(integer x=3) - could be interpretted as an array assignment rather than a - compound variable assignment has been fixed. -02-08-19 A command completion bug which occurred on file systems that - are case insensitive has been fixed. -02-08-19 A bug which could lead to an exception on some systems (for - example FREEBSD) which occurred when setting PATH has been fixed. -02-08-11 A bug in arithmetic rounding in which a value input as a decimal - string would output as a rounded version of the string has - been fixed. -02-08-11 A bug in which the last character could be deleted from shell - traces and from whence when called from a multibyte locale - has been fixed. -02-08-01 A bug which could cause a core dump to occur when a shell script - is executed while a coprocess is running that has closed the - output pipe has been fixed. -02-08-01 A bug in which command completion in multibyte mode could - corrupt memory for long command lines has been fixed. - -02-06-17 --- Release ksh93n- --- -02-06-17 A bug in which user defined macros could cause a core dump in - with MULTIBYTE mode has been fixed. -02-06-17 A bug in which printf format specifiers of the form %2$s were causing - a core dump has been fixed. -02-06-17 A bug in which setting stty to noecho mode did not prevent the - echoing of characters by ksh when emacs or viraw mode - was enabled has been fixed. -02-06-17 A bug in which background job completion could cause the sleep - builtin to terminate prematurely has been fixed. -02-06-17 A bug in which the shell could core dump if getopts was called - when the OPTIND variable contained a negative value has been fixed. -02-06-10 The edit mode prompt has been modified to handle escape sequences. -02-06-10 A bug which occurred for interactive shells in which the builtin - cat command was used in command substitution on a file whose - size was larger than PIPE_BUF has been fixed. -02-06-10 A bug in which the trap on ERR was not being processed when - set inside a function has been fixed. -02-06-07 A bug in which function definitions could cause the history count - to be decremented by one (and even become negative) has been fixed. -02-06-05 A bug in read in which share mode could be enabled has been fixed. -02-05-28 A bug which could occur when the last command of a script was - a case statement and the action selected ended in ;& instead of ;; - has been fixed. -02-05-23 A bug with unary + introduced in ksh93k has been fixed. -02-05-07 A bug in substitutions of the form ${var/pattern/string} in which - a backslash was inserted in the replacement string when it contained - a special pattern character has been fixed. -02-05-01 A bug in the emacs edit mode which occurred in versions compiled - for multibyte character sets which occurred when a repeated search - was requested after a long line had been returned for the previous - search has been fixed. -02-04-02 vi and emacs edit modes were modified so that tab completion is - disabled when invoked from the read built-in. - -02-03-26 --- Release ksh93m+ --- -02-03-26 A bug in which \ was not handled correctly when used in file - expansion has been fixed. -02-02-18 A bug in which lines beginning with a # were deleted from here - documents when the here-document delimiter was followed by - a comment has been fixed. -02-12-06 An optimization bug in which ${!x[@]) was treated as invariant in - a for loop has been fixed. -02-02-06 A bug in which the ERR trap is not cleared for a script invoked - by name from within a function has been fixed. -02-01-08 A bug in which a shell script executed from within a subshell - could cause this script to have an invalid pointer leading - to a memory fault has been fixed. -02-01-07 Added here documents of the form <<< word (as per zsh) which - is equivalent to << delim\nword\ndelim. -02-01-07 A bug in which the first word of a compound assignment, - x=(word ...), was treated as a reserved word has been fixed. -02-01-07 A bug in the handling of \ when noglob was enabled and a - substitution of the form ${word op pattern} occurred in the - same word has been fixed. -02-01-07 A compilation option, CMDLIB_BLTIN in the file OPTION, has - been added. When this options is set, all commands implemented - in libcmd become shell builtin commands by default. -02-01-07 A bug in which builtin foo, where foo is already a builtin - would result in the builtin foo getting removed has been fixed. -02-01-07 A bug which the shell executed a command found in the current - directory when PATH have no valid directories has been fixed. -01-11-28 The value of $? was not being set when called with exit. -01-11-28 If the last command was of the form (...) and a trap on EXIT or - ERR was set, and the command inside () modified the trap, then - the original trap wasn't executed. -01-11-26 The value for 0 is now preceded by the base number when - the base was not 10. -01-11-26 The default has compilation mode has been changes so that - viraw mode will always be on. - -01-10-31 --- Release ksh93m --- -01-10-31 A for loop optimizer bug for subshells contained withing for - loops has been fixed. -01-10-16 typeset without arguments no longer outputs variable names - that do not have any attributes that are set. -01-10-16 A bug introduced in ksh93l in which assignments specified with - the exec built-in were not being expanded properly has been - fixed. -01-10-11 An optimization bug in which ${!x) was treated as invariant in - a for loop has been fixed. -01-10-11 Unsigned integer variables in bases other than 10 are printed now - expand in that base with the base prefix. -01-10-10 A number of typos in the self generating man pages for shell - built-ins have been fixed. -01-10-04 The self generated man pages for hist and fc were not working - correctly and have been fixed. -01-10-03 Yet another optimizer bug in which shell patterns were - treated as invariants has been fixed. -01-09-27 Two bugs relating to multibyte history searches and to find - have been fixed. -01-09-27 A bug introduced in ksh93k in which the PATH searching was - not restored after running a command with an assignment list - has been fixed. -01-09-26 A bug in which a zero filled field was treated as octal when - converted to integer has been fixed. -01-09-26 Yet another bug in the optimization of for loops related to - recursive functions with break or continue statements has been fixed. -01-09-25 The exponentiation operator ** was added to the shell arithmetic - evaluation. It has higher precedence than * and is left - associative. -01-09-25 The code was modified to use the ast multibyte macros - and functions for handing multibyte locales. -01-09-25 The expansion ${parameter:offset:length} now handles negative - offsets which cause offsets to be measured from the end. -01-09-25 Some spelling errors in the documentation were corrected. -01-09-24 The /dev/tcp/host/port and /dev/udp/host/port now allow - the ports to be specified by service name. -01-09-24 The change staring with ksh93g in which the the appropriate - library path variable is prepended with a corresponding library - directory has been modified. With the new method, only the - library path defined in the file named .paths in the directory - where the executable is found will be modified. See the - man page for more details. -01-09-23 The .fpath file (see ksh93h) is no longer looked for in each - directory on the path to locate function directories. The - file named .paths is used instead. -01-09-23 A bug in which IFS was not being restored after being changed in - a subshell has been fixed. -01-09-16 With the vi and emacs edit modes, after a list of command - or functions is generated with = or M-= respectively, - any element from the list can be pasted on the command line - by preceding the = or M-= with a numeric parameter specifying - the position on the list. -01-09-16 A bug in ksh93l caused command completion not to find aliases - and functions. Command listing from the edit mode was presented - in reverse order. This has been fixed. -01-09-13 Another bug in the optimization of for loops related to subshells - when traps were set has been fixed. -01-09-07 A change in ksh93l caused brace expansion to stop working - and this has been fixed. -01-09-04 A bug introduced in ksh93k in which an arithmetic statement - within a function that used name references did not follow the - reference has been fixed. -01-09-04 A bug introduced in ksh93l in which export -p did not prefix - each export with the word export has been fixed. -01-08-29 A bug in multibyte input which occurred when a partial multibyte - character was received has been fixed. -01-08-29 A bug introduced in ksh93l which could cause a core dump - when an assignment list containing PATH is specified inside - command substitution has been fixed. -01-08-09 Another bug in the optimization of for loops in ksh93l caused - errors in recursive functions using local variables that - contained for loops has been fixed. -01-07-27 A bug in which IFS would be unset after a command substitution - inside a here document has been fixed. -01-07-26 To conform to the POSIX standard, if you invoked ksh name, - and name does not contain a /, it will first try to run - one in the current directory whether it is executable or not - before doing a path search for an executable script. Earlier - versions first checked for an executable script using the - PATH variable. -01-07-23 A bug in which unset -f invoked in a subshell could unset a - function defined in the parent has been fixed. -01-07-16 A bug in the optimization of for loops in ksh93l caused - name references to be treated as invariants has been fixed. -01-07-09 A bug in which a discipline function applied to a local variable - could cause a shell exception has been fixed. Discipline - functions can only be specified for global variables. - -01-06-18 --- Release ksh93l --- -01-06-18 A bug in assigning integers larger than can be represented as - long integers to floating point variables has been fixed. -01-06-18 A bug in the handling of unsigned integers (typeset -ui) has - been fixed. -01-06-04 The evaluation of the PS1 prompt no longer effects the value - of the $? variable. -01-06-01 A small memory leak from subshells has been fixed. -01-05-22 A bug in which attributes for variables that did not have - values would be lost after a subshell has been fixed. -01-05-22 The %R format has been added to convert a shell pattern into - an extended regular expression. -01-05-22 The escape sequences \e, \cX, \C[.collating-element.], and - \x{hex} have been added to ASCII-C strings and to printf format - strings. -01-05-20 Patterns of the form {n}(pattern) and {m,n}(pattern) are now - recognized. The first form matches exactly n of pattern whereas, - the second form matches from m to n instances of pattern. -01-05-20 The shell allows *-(pattern), +-(pattern), ?-(pattern), - {m,n}-(pattern}, and @-(pattern) to cause the minimal - match of pattern to be selected whenever possible rather - than the maximal (greedy) match. -01-05-20 The character class [:word:] has been added to patterns. - The word class is the union of [:alnum:] and the character _. -01-05-20 Inside (...) pattern groups, the \ character is now treated - specially even when in an enclosing character class. The - sequences, \w, \d, \s are equivalent to the character classes - word, digit, and space respectively. The sequences \W, \D, - and \S are their complement sets. -01-05-20 The shell now recognizes pattern groups of the form - ~(options:pattern) where options or :pattern can be omitted. - Options use the letters + and - to enable and disable options - respectively. The option letters g (greedy), i (ignore case) - are used to cause maximal matching and to cause case - insensitive matching respectively. If :pattern is also - specified, these options are only in effect while this - pattern is being processed. Otherwise, these options remain - in effect until the end of the pattern group that they are contained - in or until another ~(...) is encountered. These pattern groups - are not counted with respect to group numbering. -01-05-14 When edit completion, expansion, or listing occurs in the - middle of a quoted string, the leading quote is ignored when - performing the completion, expansion, or listing. -01-05-14 A small memory leak from subshells has been fixed. -01-05-10 A bug in which open files were not restored after a subshell - that had used exec to replace a file has been fixed. -01-05-10 Redirection to a null file name now generates an error message. -01-05-09 The shell now rejects some invalid parameter substitutions that - were previously processed in undefined ways. -01-05-09 A bug in which the output of select was not flushed before the - read when input did not come from the terminal has been fixed. -01-05-08 A bug in which job ids would not be freed for interactive shells - when subshells ran built-ins in the background has been fixed. -01-05-08 The FPATH variable now requires an explicit . to cause the - current directory to be treated as a function directory. -01-05-08 A bug in read -n when echo mode was disabled has been fixed. -01-05-07 A bug in which function definitions could be listed as part - of the history has been fixed. -01-04-30 This release uses a new and often much faster pattern matcher than - earlier releases. -01-04-30 An optimizer now eliminates invariant parameter expansions from - for while and until loops. -01-04-30 The variable .sh.match is set after each pattern match (# % or /) - in a variable substitution. The variable .sh.match is an - indexed array with element 0 being the complete match. - The array is only valid until the next subsequent pattern - match or until the value of the variable changes which ever - comes first. -01-04-30 A self generating man page has been added to shcomp. Also, - shcomp now stops compiling when it finds an exit or exec - command and copies the remainder so that it can be used - for standard input. -01-04-30 The shcomp command was modified so that it can work in an - EBCIDIC environment and that binary scripts are portable - across environments. -01-04-30 A bug in the handling of a trailing : in PATH has been fixed. -01-04-30 A bug in which the builtin version of a command would get invoked - even though the full pathname for the command was specified - has been fixed. -01-04-30 A bug in which read would loose the last character when - reading the last line of a file that did not contain a new-line - character has been fixed. -01-04-23 A bug on some systems in which in vi mode the end of file - character and end of line character could be swapped has - been fixed. -01-04-23 A bug on some systems in which invoking a shell script that - did not have execute permission could set the exit value to - 127 rather than 126 has been fixed. -01-04-20 A bug in which read -n from a pipe would block if fewer than - n characters was received has been fixed. -01-04-09 A bug in which invalid patterns, for example, ) by itself, - was not treated as a string has been fixed so that if i=')', - then [[ $i == $i ]] is true. -01-04-09 The shell arithmetic now interprets C character constants. -01-04-09 A bug in which a non-zero return from a function defined - with the function reserved word did not trigger the ERR - trap or exit with set -e has been fixed. -01-04-02 A bug on some systems, in which characters above 127 were - not displayed correctly in vi or emacs edit mode has been fixed. -01-04-02 A bug on some systems, introduced in the 'k' point release, in - which the erase character in viraw mode was moving the cursor - to the left without erasing the character has been fixed. -01-04-02 On some systems the wcwith() function was returning a wrong - value for characters and caused characters to be displayed - incorrectly from the shell edit modes. A work around for - this problem has been added. -01-03-26 A bug in which valid scripts could produce syntax errors - when run with locales that considered characters such as "'" - to be space characters has been fixed. -01-03-20 A bug in which an syntax error in an arithmetic expression - entered interactively could cause the shell to go into - an infinite loop outputting the error message has been fixed. -01-03-10 ksh93 accepts -l as a synonym for -L in test on systems for - which /bin/test -l tests for symbolic links. -01-03-10 A bug in parsing scripts in which { and } are used in place of - in and esac in case statements embedded in compound commands - has been fixed. Use of { and } for in and esac is obsolete. -01-03-06 A bug in which an argument of the form foo=bar was not - being passed correctly to a traced function whose name - was foo has been fixed. -01-03-02 Using $(trap -p name) did not print the name of the current - trap setting for trap name. -01-02-26 Exported floating point variables gave incorrect results - when passing them to ksh88. This has been fixed. -01-02-25 A race condition in which a coprocess which completed too quickly - would not allow subsequent coprocesses to start has been fixed. -01-02-25 The 'g' format specifier is now handled by printf. It had - inadvertently been omitted. -01-02-20 The + was not being displayed during an execution trace - with the += assignment operator. -01-02-19 The error message which occurs when the interpreter name - defined on the #! line does not exist is more informative. -01-02-19 A bug in which $0 would not be set correctly when a - script with #! was invoked by full pathname from the - directory of the script has been fixed. -01-02-19 A shell script did not always pick up tty mode changes - made by external commands such as stty which could - effect the behavior of read. -01-02-19 The -u, -g, and -k unary tests did not give the correct - results when used with negation and this has been fixed. - -01-02-05 --- Release ksh93k+ --- -01-02-05 The sequence \<newline> inside $'...' was not incrementing - the line count and this has been fixed. -01-02-05 Modified expansion of "${@-}" so that if no arguments are set - it results in null string rather than nothing. -01-02-02 memory leak problem with local variables in functions fixed. -01-01-25 allow arithmetic expressions with float%int and treat them - as ((int)float)%int rather than as an error. -01-01-19 read -n1 was not working and has been fixed. -01-01-17 ksh now handles the case in which a here document in command - substitution $() is terminated by the trailing ). Previously, - a new-line was needed at the end of the delimiter word. -01-01-02 A bug in which a KEYBD trap would cause a multi-line token - to be processed incorrectly has been fixed. -00-12-10 Arithmetic integer constants can now have L and U suffices. -00-12-10 A bug in the processing of arithmetic expressions with compound - variables when the -n option is on has been fixed. -00-12-08 A bug in M-f and M-b from emacs mode has been fixed. This - bug only occurs when ksh93 is compiled without MULTIBYTE enabled. -00-11-29 A bug in which jobs -p would yield 0 for background - jobs run in a script has been fixed. -00-11-21 A bug in integer arrays in which the number of elements is - incorrect when the ++ operator is applied to a non-existing - element has been fixed. For example, integer x; ((x[3]++)). -00-11-20 A timing bug in which the shell could reset the terminal - group to the wrong value in the case that the a new process - changes the terminal group during startup has been fixed. - -00-10-27 --- Release ksh93k --- -00-10-27 Using tab for completion now works only when applied - after a non-blank character at the end of the current line. - In other case a tab is inserted. -00-10-27 A bug in the emacs edit mode for ^X^E has been fixed. - The ^X^E sequence is supposed to invoke the full editor - on the current command. -00-10-18 A bug in which expansions of the form ${var//pattern/string} - did not work correctly when pattern was '/' or "/" has - been fixed. -00-10-18 The output format for indexed arrays in compound variables - has been modified so that it can be used as input. -00-10-18 Assignments with name references (typeset -n) will now - implicitly unreference an existing name reference. -00-10-17 A bug the += append operator when a single array element - is appended to a variable that is not an array has been fixed. -00-10-16 A bug in which the SIGCONT signal was being sent to - each process will kill -0 or kill -n 0 has been fixed. -00-10-12 The arithmetic evaluation portion has been rewritten to - perform a number of optimizations. -00-10-10 A bug in which name prefix matching ${!name.*} was not - checking name to see if it was a name reference has been fixed. -00-09-26 A bug in the multibyte version in which the width of for - non-printing characters was not correct has been fixed. -00-09-12 Made changes to get multibyte editing work on UWIN for windows -00-09-12 A bug in which multibyte characters would be displayed incorrectly - has been fixed. -00-08-08 Removed build dependency on iswprint() and iswalph(). -00-07-20 In some cases the read builtin would read more than a single - line from a pipe on standard input and therefore leave the seek - position in the wrong location. -00-07-05 If the directory / is on the path, a / will not be inserted - between the directory and the file name during path searching - to avoid searching // for systems that treat this specially. -00-06-26 A bug in which on rare occasions wait could return before all - jobs have completed has been fixed. -00-06-21 A bug in which backspace did not work correctly during the - R replace directive in vi-mode has been fixed. -00-06-12 Added variable name completion/expansion/listing to the set of - completions. Variable name completions begin with $ or "$ followed - by a letter. -00-05-09 --- Release ksh93j --- -00-05-09 Modified command substitution to avoid using /tmp files when - run on read-only file systems. -00-04-17 Modified printf to handle '%..Xc' and '%..Xs' options where X - is not an alpha character. Previous versions core dumped with this. -00-04-10 Changes to multibyte editing code were made to use standard - ISO C functions rather than methods devised before the standard. -00-04-09 Add %H options to printf to output strings with <"'&\t> properly - converted for use in HTML and XML documents. -00-04-07 Modified getopts builtin to handle \f...\f in usage string - by invoking specified function. -00-04-04 Added self generating man pages for bg, fc, fg, disown, jobs, - hist, let, ., and ulimit. -00-03-30 The append operator += has been added and can be used - for all assignments, strings, arrays, and compound variables. -00-03-30 Code was modified in several places to support automatic - generation of C locale dictionaries. -00-03-28 A bug in which the set and trap commands invoked with --name - type arguments would terminate the invoking script has - been fixed. -00-03-27 A bug in which the library path variable was not updated - correctly on some systems as described in the 'g' point - release has been fixed. -00-03-07 printf now returns a non-zero exit status when one of - its arguments cannot be converted to the given type. -00-03-05 The return value and error message for a command that - was found on the path but was not executable was set - incorrectly. -00-03-05 A prototype for ioctl() was removed from the vi edit mode. - -00-01-28 --- Release ksh93i --- -00-01-28 Most of the built-in commands and ksh itself are now - self documenting. Running command --man will produce - screen output. Running command --html produces the - man page in html format. -00-01-28 The getopts builtin can process command description - strings to produce man pages. -00-01-28 A bug in which a script could terminate when getopts - encountered an error when invoked inside a function - has been fixed. -00-01-28 When a symbolic link was specified as the name of - the script to invoke by name, the value of $0 was - set to the real file name rather than the link name - in some cases and this has been fixed. -00-01-28 A bug in which the precision given as an argument - to printf was not working has been fixed. - -99-03-31 --- Release ksh93h --- -99-03-31 The PATH search algorithm has been modified to look - for a file named .fpath in each bin directory and if - found, to search for functions in this directory if - it cannot find the command in that directory. -99-03-31 When performing pathname expansion, the shell checks - to see whether each directory it reads is case sensitive - or not, and performs the matching accordingly. -99-03-31 The %T format for printing formatted date/time. -99-03-31 The emacs and vi modes now handle arrow keys when - they use standard ANSI escape sequences. -99-03-31 The TAB key can be used for completion in emacs and viraw mode. -99-03-31 A bug in setting .sh.editchar during the KEYBD trap - for the MULTIBYTE option was fixed in release ksh93h. -99-03-31 A bug in shcomp for compilation of unary operators with [[...]] - has been fixed. -99-03-31 A bug in which the value of $? was changed when executing - a keyboard trap has been fixed. -99-03-31 The handling of SIGCHLD has been changed so that the - trap is not triggered while executing trap commands - to avoid recursive trap calls. -99-03-31 A bug in which a local variable in a function declared readonly - would generated an error when the function went out of - scope has been fixed. -99-03-31 A bug in which \<new_line> entered from the keyboard - with the KEYBD trap enabled has been fixed. -99-03-31 The error message for a misplaced ((, for example print ((3), - was often garbled and has been fixed. -99-03-31 A bug in the KEYBD trap in which escape sequences of the form - <ESC>[#~ were not being handled as a unit has been fixed. -99-03-31 A bug in which ksh would consider expressions like [[ (a) ]] - as syntax errors has been fixed. -99-03-31 A function defined as foo() without a function body - was not reported as a syntax error. -99-03-31 A bug in which ksh could run out of file descriptors when - a stream was repeatedly opened with exec and read from - has been fixed. - -98-04-30 --- Release ksh93g --- -98-04-30 The pipefail option has been added. With pipefail - enabled, a pipeline will not complete until all - commands are complete, and the return value will - be that of the last command to fail, or zero if - all complete successfully. -98-04-30 The name-value pair library uses the cdt library rather - than the hash library. This change should be transparent - to applications. -98-04-30 On the U/WIN version for Window 95 and Windows NT, - when a directory beginning with a letter followed by - a colon is given to cd, it is assumed to be an absolute - directory -98-04-30 When an executable is found on a given path, - the appropriate library path variable is prepended - with a corresponding library directory. -98-04-30 A bug in which a name reference could be created to - itself and later cause the shell to get into an infinite - loop has been fixed. -98-04-30 A bug in shcomp relating to compound variables was fixed. -98-04-30 A bug introduced in ksh93e in which leading 0's in -Z - fields caused the value to be treated as octal for arithmetic - evaluation has been fixed. -98-04-30 A bug when a name reference with a shorter name than - the variable it references was the subject of a compound - assignment has been fixed. -98-04-30 A bug which in which assignment to array variables in - a subshell could effect the parent shell has been - fixed. -98-04-30 read name?prompt was putting a 0 byte at the end of the - prompt on standard error. -98-04-30 A bug in [[ string1 > string2 ]] when ksh was run with -x - has been fixed. -98-04-30 A bug in which the escape character was not processed - correctly inside {...} when brace expansion is enabled - has been fixed, for example {\$foo}. -98-04-30 A bug in line continuation in here-documents has been - fixed. -98-04-30 The default base when not specified with typeset -i is - 10 in accordance with the documentation. Previously, - the value was determined by the first assignment. -98-04-30 A parsing bug in which a # preceded alphanumeric - characters inside a command substitution caused - a syntax error to be reported has been fixed. -98-04-30 A bug in which a decimal constant represented as 10#ddd - where ddd was more than five digits generated a syntax - error has been fixed. -98-04-30 A bug in here document expansion in which ${...} expansions - were split across buffer boundaries has been fixed. -98-04-30 The sh_fun() function now takes third argument which - is an argument list for the invoked discipline function - or built-in. -98-04-30 A callback function can be installed which will give - notification of file duplications and file closes. -98-04-30 When ksh is compiled on systems that do not use fork() - current option settings where not propagated to sub-shells. - -97-06-30 --- Release ksh93f --- -97-06-30 Hostnames in addition to host addresses can be given in - /dev/tcp/host/port virtual file names. -97-06-30 File name completion and expansion now quotes special - characters in file names from both emacs and vi edit modes. -97-06-30 An empty for list behave like a for list with null expansions. - It produces a warning message with sh -n. -97-06-30 The code has been modified to work with EBCDIC as well as ASCII. -97-06-30 A bug which would cause the secondary prompt to be - displayed when a user entered a literal carriage - return has been fixed. -97-06-30 A bug which caused ksh read -s name to core dump was - fixed. -97-06-30 A bug with the expansion of \} and \] inside double - quoted strings that also contained variable expansions - has been fixed -97-06-30 Changes in the ksh93e point release caused autoload - functions invoked from within command substitution - to fail. This has been fixed. -97-06-30 A bug in the processing of here-documents that could - prevent variable substitution to occur after $(...) command - substitution for long here documents has been fixed. -97-06-30 A bug caused by a race condition that could cause SIGTERM - to be ignored by a child process has been fixed. -97-06-30 A bug which prevented the startup of a coprocess immediately - after killing a running coprocess has been fixed. -97-06-30 ulimit foobar, where foobar is not an arithmetic - expression, now gives an error message as it did with ksh88 - instead of setting the file size limit to 0. -97-06-30 A bug which could cause an interactive shell to terminate when - the last process of a pipeline was a POSIX function was fixed. -97-06-30 A bug which could cause command substitution of a shell script - to core dump has been fixed. -97-06-30 A security hole was fixed in suid_exec. -97-06-30 Arithmetic functions such as pow() that take more than - one argument, did not work if arguments other than the - first contained parenthesized sub-expression. -97-06-30 The error message from a script containing an incomplete - arithmetic expression has been corrected. -97-06-30 A bug which caused a core dump on some machines when - the value of a name reference contained a positional - parameter and the name reference was not defined inside - a function has been fixed. -97-06-30 Arithmetic expressions now correctly handle hexadecimal - constants. -97-06-30 A bug in which integer variables could be expanded - with a leading 10# when declared with typeset -i - multiple times has been corrected. -97-06-30 A bug in which IFS wasn't correctly restored when - set within command substitution has been fixed. -97-06-30 The _ character is now considered as part of a word - with the M-f and M-b emacs directives as it was in ksh88. -97-06-30 A bug in brace pattern expansions that caused expressions - such as {foo\,bar,bam} to expand incorrectly have been fixed. - - -96-07-31 --- Release ksh93e --- -96-07-31 The math functions, atan2, hypot, fmod, and pow were added. -96-07-31 When a shared library is loaded, if the function lib_init() - is defined in the library, it is invoked the first time that - the library is loaded with builtin -f library. -96-07-31 The k-shell information abstraction database option, KIA, - has been revamped. -96-07-31 Empty command substitutions of the form $() now work. - whence -v foo now gives the correct result after calling - builtin -d foo. -96-07-31 A bug in right to left arithmetic assignment for which - the arithmetic expression (( y = x = 1.5 )) did not - yield 1 for y when x was declared typeset -i was fixed. -96-07-31 printf has been fixed to handle format containing \0 - and/or \0145 correctly. In addition, characters following - %b in the format string are no longer displayed when - the operand contains \c. -96-07-31 A bug in printf that could cause the %E format to - produce unnormalized results has been fixed. -96-07-31 A bug which causes some arithmetic expressions to be - incorrectly evaluated as integer expressions rather - that floating point has been fixed. -96-07-31 Functions defined inside a subshell no longer remain - defined when the subshell completes. -96-07-31 The error message from sh -c ';echo foo' has been - corrected. -96-07-31 The format for umask -S has been changed to agree - with the specification in the POSIX standard. -96-07-31 A bug that caused side effects in subscript evaluation - when tracing was enabled for subscripts using ++ or -- - has been fixed. -96-07-31 To conform to the Posix standard getopts has been changed - so that the option char is set to ? when it returns with - a non-zero exit status. -96-07-31 The handling of \} inside ${name...} has been fixed so - that the \ quotes the }. -96-07-31 A bug that caused the read builtin to resume execution - after processing a trap has been fixed. -96-07-31 [[ -s file ]] has been fixed so that if file is open - by ksh, it is flushed first. -96-07-31 In some cases attributes and sizes for non exported - variables weren't being reset before running a script. -96-07-31 The value of TMOUT was affected by changes make to - it in a subshell. -96-07-31 The jobs command did not reflect changes make by - sending the CONT signal to a command. -96-07-31 The error message for ksh -o unknown was incorrect. -96-07-31 Functions invoked as name=value name, did not use - values from the calling scope when evaluating value. -96-07-31 A bug in which the shell would reexecute previously - executed code when a shell script or coprocess was - run in the background has been fixed. -96-07-31 A bug in which an empty here-document would leave - a file descriptor open has been fixed. -96-07-31 A bug in which $(set -A array ...) would leave a - side effect has been fixed. -96-07-31 A discipline function for a global variable defined - within a function defined with the function keyword, - incorrectly created a local variable of the same name - and applied the discipline to it. - -95-08-28 --- Release ksh93d --- -95-08-28 The \ character was not handled correctly in replacement - patterns with ${x/pattern/replace}. -95-08-28 A bug with read in which the line did not end with - a new-line has been fixed. -95-08-28 A bug in file name generation which sometimes - appended a . for filenames that ended in / has - been fixed. -95-08-28 If a process is waited for after a status has - been returned by a previous wait, wait now - returns 127. -95-08-28 A bug with hist (fc) -e which prevented a command - to re-executed after it had been edited has been fixed. -95-08-28 A bug which prevented quoting from removing the meaning - of unary test operators has been fixed. -95-08-28 A bug with typeahead and KEYBOARD traps with the - MULTIBYTE option set has been fixed. -95-08-28 Builtin functions can take a third argument which is - a void*. -95-08-28 The nv_scan() function can restrict the scope of a walk - to the top scope. - -95-04-31 --- Release ksh93c --- -95-04-31 The expansion of "$@" was incorrect when $1 was the null - string. -95-04-31 A bug which could incorrectly report a syntax error in - a backquoted expression when a $ was preceded by \\ - has been fixed. -95-04-31 A bug which prevented the shell from exiting after - reporting an error when failing to open a script - has been fixed. -95-04-31 A bug that could lead to memory corruption when a - large here document that required parameter or command - substitution was expanded has been fixed. -95-04-31 A bug that could cause a core dump on some systems - after ksh detected an error when reading a function - has been fixed. -95-04-31 A bug which could cause a coprocess to hang when - reading from a process that has terminated has been fixed. -95-04-31 A bug which caused a script to terminate when set -e - was on and the first command of and && or || list - failed has been fixed. -95-04-31 A bug with here documents inside $(...) when the delimiter - word is an identifier has been fixed. -95-04-31 A bug which caused $0 to display the wrong value when - a script was invoked as an argument to the . command - and the eval command has been fixed. -95-04-31 A bug that could cause the built-in sleep to hang - has been fixed. -95-04-31 A bug introduces in 12/28/93b which caused the backslash - to be removed when it was followed by digit inside double - quotes in some instances has been fixed. -95-04-31 A bug which could cause a core dump if ksh was invoked with - standard input closed has been fixed. -95-04-31 A bug which could cause a core dump if typeset -A was - specified for an existing variable has been fixed. -95-04-31 Variables that were unset but had attributes such as readonly - and export were not listed with readonly, export and typeset. -95-04-31 Several problems with signals have been fixed. -95-04-31 A bug which prevented ulimit -t from working has been fixed. - Also, a bug in which failed ulimits could cause a core dump - has also been fixed. -95-04-31 A bug in expansion of the form ${name/#pattern/string} and - ${name/%pattern/string} has been fixed. -95-04-31 A bug which caused read -r on a line that contained only - blanks to get a non-null value has been fixed. -95-04-31 A bug introduced in the 'a' point release in which - ${x='\\'} expanded to \ when x was unset has been fixed. -95-04-31 A bug which prevented a trap on EXIT from being executed - when the last command in a script was a function invocation - has been fixed. -95-04-31 A bug which caused an interactive shell ignore input when - standard error was redirected to a file with exec, - and then restored with exec 2>&1 has been fixed. -95-04-31 An interactive shell turns on monitor mode even when - standard error has been redirected to a file. -95-04-31 A bug which could cause standard input to be incorrectly - positioned for the last command of a script has been fixed. -95-04-31 A bug in the edit modes which allowed walking back in - the history file for more than HISTSIZE commands has - been fixed. -95-04-31 A bug which could cause a core dump if variable TMPDIR was - changed between two command substitutions has been fixed. -95-04-31. A bug which prevented a trap on EXIT from being cleared - has been fixed. -95-04-31 A bug fixed for the v directive in vi MULTIBYTE has been - fixed. -95-04-31 Code to for IFS handling of multibyte characters has - been added. -95-04-31 The displaying of multibyte strings in export, readonly, - typeset, and execution traces has been fixed. -95-04-31 Variables inside functions are now statically scoped. - The previous behavior was never documented. -95-04-31 Variables inside functions are now statically scoped. - The previous behavior was never documented. -95-04-31 A few changes have been made to the name-value library - that affect built-ins that use disciplines. The - changes allow disciplines to be shared by variables - and should make it possible to add new disciplines - without recompilation. -95-04-31 The name-value library interface has undergone significant - change for this revision. See the new nval.3 man page. - -94-12-31 --- Release ksh93b --- -94-12-31 Variables inside functions are now statically scoped. - The previous behavior was never documented. -94-12-31 If IFS contains two consecutive identical characters belonging - to the [:space:] class, then this character is treated as - a non-space delimiter so that each instance will delimit - a field. For example, IFS=$'\t\t' will cause two consecutive - tabs to delimit a null field. -94-12-31 The getopts command has a -a name option that specifies a - name that will be used for usage messages. -94-12-31 A bug which caused unset RANDOM to dump core has been - fixed. -94-12-31 A bug which prevented return for terminating a profile - or ENV file has been fixed. -94-12-31 A bug which prevented standard input from being - directed to /dev/null for background jobs when - monitor mode was turned off has been fixed. -94-12-31 Statements of the form typeset -options var[expr]=value - did not perform substitutions on expr as expected. -94-12-31 A bug which prevented the shell from sending a HUP - signal to some background jobs that were not disowned - has been fixed. -94-12-31 A bug which allowed a script to trap signals that are - ignored at the time that the shell was invoked by exec - has been fixed. -94-12-31 A bug which could cause a core dump when a discipline - function was unset within a discipline was fixed. -94-12-31 The typeset builtin now accepts a first argument of - + or - for compatibility with ksh88. -94-12-31 For compatibility with ksh88, the results of expansions - of command arguments will treat the extended character - match characters ()|& as ordinary characters. -94-12-31 A bug which caused read to fail on a file that was - open for read/write with <> when the first operation - was print or printf has been fixed. -94-12-31 When a job is suspended, it is put on the top of - the job list as required by the POSIX standard. -94-12-31 The value of OPTARG when an option that required - an argument but didn't have one was incorrect in the - case the the option string began with a :. -94-12-31 A bug which caused the terminal to get into a bad - state with some KEYBD traps in vi-mode has been fixed. -94-12-31 A bug which caused an invalid trap to cause a script - to terminate, rather than just return an error, has - been fixed. -94-12-31 Backreferencing sub-expressions in patterns and replacement - strings now works. -94-12-31 A bug in chmod which caused the -R option to fail has - been fixed. -94-12-31 More signal names have been added for Solaris - -94-06-30 --- Release ksh93a --- -94-06-30 An expansion bug which causes portions of a word after - a $((...)) expansion that contains a nested $var expansion - to be lost has been fixed. -94-06-30 A bug that caused a core dump when a script that did not - have PWD set and did a cd inside command substitution - has been fixed. -94-06-30 A bug which caused a core dump on some machines when - the LANG variable was assigned to has been fixed. -94-06-30 A bug which incorrectly handled set disciplines that - performed arithmetic evaluation when the discipline - was called from the arithmetic evaluator has been fixed. -94-06-30 A bug caused by an EXIT trap inside a function that - was executed in a subshell was fixed. -94-06-30 If foo is a function, and not a program, then command foo - now reports that foo isn't found rather than invoking foo. -94-06-30 The previous version incorrectly listed -A as an - invocation option. The -A option is only for set. -94-06-30 A bug was fixed which caused ksh to loop when execution trace - was enabled and the PS4 prompt required command substitution. -94-06-30 A bug which could cause the job control switch character - to be disabled when a script that enabled monitor mode - terminated was fixed. -94-06-30 A bug in the macro expansion global replacement operator //, - when the pattern began with a [ or +( has been fixed. -94-06-30 A bug which prevented ~ expansion from occurring when - it was terminated with a colon inside an assignment - has been fixed. -94-06-30 A bug in the dot command which prevented autoload functions - from working has been fixed. -94-06-30 A bug which caused a variable to be unset if the - its value were expanded inside a set discipline has - been fixed. -94-06-30 Whence -a now longer reports that a defined function - is undefined. -94-06-30 A bug on some systems in which $0 would be incorrect - in scripts invoked by name has been fixed. -94-06-30 Here documents with an empty body now work. -94-06-30 A bug which disabled argument passing and resetting - of options for a script invoked by name inside a - function has been fixed. -94-06-30 A bug in which an EXIT trap set the caller of a function - would be executed if a command called inside a function - was not found has been fixed. -94-06-30 A bug which allowed a script to trap signals that are - ignored at the time that the shell was invoked has - been fixed. -94-06-30 A bug which caused 2<&1- when applied to a shell built-in - to leave standard input closed has been fixed. -94-06-30 A bug which caused the shell to incorrectly parse - $() command substitutions with nested case statements - has been fixed. - diff --git a/usr/src/lib/libshell/common/TYPES b/usr/src/lib/libshell/common/TYPES deleted file mode 100644 index 6eb6f41b5e..0000000000 --- a/usr/src/lib/libshell/common/TYPES +++ /dev/null @@ -1,182 +0,0 @@ - -The ability for users to define types has been added to ksh93t. -Here is a quick summary of how types are defined and used in ksh93t. -This is still a work in progress so some changes and additions -are likely. - -A type can be defined either by a shared library or by using the new -typeset -T option to the shell. The method for defining types via -a shared library is not described here. However, the source file -bltins/enum.c is an example of a builtin that creates enumeration types. - -By convention, typenames begin with a capitol letter and end in _t. -To define a type, use - typeset -T Type_t=( - definition - ) -where definition contains assignment commands, declaration commands, -and function definitions. A declaration command (for example typeset, -readonly, and export), is a built-in that differs from other builtins in -that tilde substitution is performed on arguments after an =, assignments -do not have to precede the command name, and field splitting and pathname -expansion is not performed on the arguments. -For example, - typeset -T Pt_t=( - float -h 'length in inches' x=1 - float -h 'width in inches' y=0 - integer -S count=0 - len() - { - print -r $((sqrt(_.x*_.x + _.y*_.y))) - } - set() - { - (( _.count++)) - } - ) - -defines a type Pt_t that has three variables x, y, and count defined as well -as the discipline functions len and set. The variable x has an initial value -of 1 and the variable y has an initial value of 0. The new -h option argument, -is used for documentations purposes as described later and is ignored outside -of a type definition. - - -The variable count has the new -S attribute which means that it is shared -between all instances of the type. The -S option to typeset is ignored -outside of a type definition. Note the variable named _ that is used inside -the function definition for len and set. It will be a reference to the -instance of Pt_t that invoked the function. The functions len and set -could also have been defined with function len and function set, but -since there are no local variables, the len() and set() form are more -efficient since they don't need to set up a context for local variables -and for saving and restoring traps. - -If the discipline function named create is defined it will be -invoked when creating each instance for that type. A function named -create cannot be defined by any instance. - -When a type is defined, a declaration built-in command by this name -is added to ksh. As with other shell builtins, you can get the man page -for this newly added command by invoking Pt_t --man. The information from -the -h options will be embedded in this man page. Any functions that -use getopts to process arguments will be cross referenced on the generated -man page. - -Since Pt_t is now a declaration command it can be used in the definition -of other types, for example - typeset -T Rect_t=( Pt_t ur ll) - -Because a type definition is a command, it can be loaded on first reference -by putting the definition into a file that is found on FPATH. -Thus, if this definition is in a file named Pt_t on FPATH, then -a program can create instances of Pt_t without first including -the definition. - -A type definition is readonly and cannot be unset. Unsetting non-shared -elements of a type restores them to their default value. Unsetting a -shared element has no effect. - -The Pt_t command is used to create an instance of Pt_t. - Pt_t p1 -creates an instance named p1 with the initial value for p1.x set to 1 -and the initial value of p1.y set to 0. - Pt_t p2=(x=3 y=4) -creates an instance with the specified initial values. The len function -gives the distance of the point to the origin. Thus, p1.len will output -1 and p2.len will output 5. - -ksh93t also introduces a more efficient command substitution mechanism. -Instead of $(command), the new command substitution ${ command;} -can be used. Unlike (and ) which are always special, the { and } are -reserved words and require the space after { and a newline or ; before }. -Unlike $(), the ${ ;} command substitution executes the command in -the current shell context saving the need to save and restore -changes, therefore also allowing side effects. - -When trying to expand an element of a type, if the element does not exist, -ksh will look for a discipline function with that name and treat this as if -it were the ${ ;} command substitution. Thus, ${p1.len} is equivalent to -${ p1.len;} and within an arithmetic expression, p1.len will be expanded -via the new command substitution method. - -The type of any variable can be obtained from the new prefix -operator @. Thus, ${@p1} will output Pt_t. - -By default, each instance inherits all the discipline functions defined -by the type definition other than create. However, each instance can define -a function by the same name that will override this definition. -However, only discipline functions with the same name as those defined -by the type or the standard get, set, append, and unset disciplines -can be defined by each instance. - -Each instance of the type Pt_t behaves like a compound variable except -that only the variables defined by the type can be referenced or set. -Thus, p2.x=9 is valid, but p2.z=9 is not. Unless a set discipline function -does otherwise, the value of $p1 will be expanded to the form of a compound -variable that can be used for reinput into ksh. - -If the variables var1 and var2 are of the same type, then the assignment - var2=var1 -will create a copy of the variable var1 into var2. This is equivalent to - eval var2="$var1" -but is faster since the variable does not need to get expanded or reparsed. - -The type Pt_t can be referenced as if it were a variable using the name -.sh.type.Pt_t. To change the default point location for subsequent -instances of Pt_t, you can do - .sh.type.Pt_t=(x=5 y=12) -so that - Pt_t p3 - p3.len -would be 13. - -Types can be defined for simple variables as well as for compound -objects such as Pt_t. In this case, the variable named . inside -the definition refers to the real value for the variable. For example, -the type definition - typeset -T Time_t=( - integer .=0 - _='%H:%M:%S' - get() - { - .sh.value=$(printf "%(${_._})T" "#$((_))" ) - } - set() - { - .sh.value=$(printf "%(%#)T" "${.sh.value}") - - } - ) - -The sub-variable name _ is reserved for data used by discipline functions -and will not be included with data written with the %B option to printf. -In this case it is used to specify a date format. - -In this case - Time_t t1 t2=now -will define t1 as the time at the beginning of the epoch and t2 -as the current time. Unlike the previous case, $t2 will output -the current time in the date format specified by the value t2._. -However, the value of ${t2.} will expand the instance to a form -that can be used as input to the shell. - -Finally, types can be derived from an existing type. If the first -element in a type definition is named _, then the new type -consists of all the elements and discipline functions from the -type of _ extended by elements and discipline functions defined -by new type definition. For example, - - typeset -T Pq_t=( - Pt_t _ - float z=0. - len() - { - print -r $((sqrt(_.x*_.x + _.y*_.y + _.z*_.z))) - } - ) - -defines a new type Pq_t which is based on Pq_t and contains an additional -field z and a different len discipline function. It is also possible -to create a new type Pt_t based on the original Pt_t. In this case -the original Pt_t is no longer accessible. diff --git a/usr/src/lib/libshell/misc/images/callouts/1.png b/usr/src/lib/libshell/misc/images/callouts/1.png Binary files differdeleted file mode 100644 index 608fad3596..0000000000 --- a/usr/src/lib/libshell/misc/images/callouts/1.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/callouts/10.png b/usr/src/lib/libshell/misc/images/callouts/10.png Binary files differdeleted file mode 100644 index 39e55197cf..0000000000 --- a/usr/src/lib/libshell/misc/images/callouts/10.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/callouts/2.png b/usr/src/lib/libshell/misc/images/callouts/2.png Binary files differdeleted file mode 100644 index 5444738841..0000000000 --- a/usr/src/lib/libshell/misc/images/callouts/2.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/callouts/3.png b/usr/src/lib/libshell/misc/images/callouts/3.png Binary files differdeleted file mode 100644 index 64b87c7151..0000000000 --- a/usr/src/lib/libshell/misc/images/callouts/3.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/callouts/4.png b/usr/src/lib/libshell/misc/images/callouts/4.png Binary files differdeleted file mode 100644 index c308193ac4..0000000000 --- a/usr/src/lib/libshell/misc/images/callouts/4.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/callouts/5.png b/usr/src/lib/libshell/misc/images/callouts/5.png Binary files differdeleted file mode 100644 index 24799f0a43..0000000000 --- a/usr/src/lib/libshell/misc/images/callouts/5.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/callouts/6.png b/usr/src/lib/libshell/misc/images/callouts/6.png Binary files differdeleted file mode 100644 index 8919a670cd..0000000000 --- a/usr/src/lib/libshell/misc/images/callouts/6.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/callouts/7.png b/usr/src/lib/libshell/misc/images/callouts/7.png Binary files differdeleted file mode 100644 index e30e8a70cb..0000000000 --- a/usr/src/lib/libshell/misc/images/callouts/7.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/callouts/8.png b/usr/src/lib/libshell/misc/images/callouts/8.png Binary files differdeleted file mode 100644 index 3e35c8827c..0000000000 --- a/usr/src/lib/libshell/misc/images/callouts/8.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/callouts/9.png b/usr/src/lib/libshell/misc/images/callouts/9.png Binary files differdeleted file mode 100644 index ed2f14b4eb..0000000000 --- a/usr/src/lib/libshell/misc/images/callouts/9.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/tag_bourne.png b/usr/src/lib/libshell/misc/images/tag_bourne.png Binary files differdeleted file mode 100644 index f1f78e3a25..0000000000 --- a/usr/src/lib/libshell/misc/images/tag_bourne.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/tag_i18n.png b/usr/src/lib/libshell/misc/images/tag_i18n.png Binary files differdeleted file mode 100644 index 559929df2a..0000000000 --- a/usr/src/lib/libshell/misc/images/tag_i18n.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/tag_ksh.png b/usr/src/lib/libshell/misc/images/tag_ksh.png Binary files differdeleted file mode 100644 index b33d5a7aa1..0000000000 --- a/usr/src/lib/libshell/misc/images/tag_ksh.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/tag_ksh88.png b/usr/src/lib/libshell/misc/images/tag_ksh88.png Binary files differdeleted file mode 100644 index d36dc0f5f5..0000000000 --- a/usr/src/lib/libshell/misc/images/tag_ksh88.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/tag_ksh93.png b/usr/src/lib/libshell/misc/images/tag_ksh93.png Binary files differdeleted file mode 100644 index 357ee3c50a..0000000000 --- a/usr/src/lib/libshell/misc/images/tag_ksh93.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/tag_l10n.png b/usr/src/lib/libshell/misc/images/tag_l10n.png Binary files differdeleted file mode 100644 index be89f7a163..0000000000 --- a/usr/src/lib/libshell/misc/images/tag_l10n.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/images/tag_perf.png b/usr/src/lib/libshell/misc/images/tag_perf.png Binary files differdeleted file mode 100644 index fcb2960852..0000000000 --- a/usr/src/lib/libshell/misc/images/tag_perf.png +++ /dev/null diff --git a/usr/src/lib/libshell/misc/shell_styleguide.docbook b/usr/src/lib/libshell/misc/shell_styleguide.docbook deleted file mode 100644 index 0376912d1f..0000000000 --- a/usr/src/lib/libshell/misc/shell_styleguide.docbook +++ /dev/null @@ -1,1464 +0,0 @@ -<?xml version="1.0"?> -<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V5.0//EN" "http://www.oasis-open.org/docbook/xml/5.0b5/dtd/docbook.dtd" [ - <!ENTITY tag_bourneonly '<inlinemediaobject><imageobject><imagedata fileref="images/tag_bourne.png"></imagedata></imageobject><textobject><phrase>[Bourne]</phrase></textobject></inlinemediaobject> '> - <!ENTITY tag_kshonly '<inlinemediaobject><imageobject><imagedata fileref="images/tag_ksh.png"></imagedata></imageobject><textobject><phrase>[ksh]</phrase></textobject></inlinemediaobject> '> - <!ENTITY tag_ksh88only '<inlinemediaobject><imageobject><imagedata fileref="images/tag_ksh88.png"></imagedata></imageobject><textobject><phrase>[ksh88]</phrase></textobject></inlinemediaobject> '> - <!ENTITY tag_ksh93only '<inlinemediaobject><imageobject><imagedata fileref="images/tag_ksh93.png"></imagedata></imageobject><textobject><phrase>[ksh93]</phrase></textobject></inlinemediaobject> '> - <!ENTITY tag_performance '<inlinemediaobject><imageobject><imagedata fileref="images/tag_perf.png"></imagedata></imageobject><textobject><phrase>[perf]</phrase></textobject></inlinemediaobject> '> - <!ENTITY tag_i18n '<inlinemediaobject><imageobject><imagedata fileref="images/tag_i18n.png"></imagedata></imageobject><textobject><phrase>[i18n]</phrase></textobject></inlinemediaobject> '> - <!ENTITY tag_l10n '<inlinemediaobject><imageobject><imagedata fileref="images/tag_l10n.png"></imagedata></imageobject><textobject><phrase>[l10n]</phrase></textobject></inlinemediaobject> '> -]> -<!-- - - CDDL HEADER START - - The contents of this file are subject to the terms of the - Common Development and Distribution License (the "License"). - You may not use this file except in compliance with the License. - - You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - or http://www.opensolaris.org/os/licensing. - See the License for the specific language governing permissions - and limitations under the License. - - When distributing Covered Code, include this CDDL HEADER in each - file and include the License file at usr/src/OPENSOLARIS.LICENSE. - If applicable, add the following below this CDDL HEADER, with the - fields enclosed by brackets "[]" replaced with your own identifying - information: Portions Copyright [yyyy] [name of copyright owner] - - CDDL HEADER END - ---> - -<!-- - - Copyright 2009 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. - ---> - -<!-- tag images were created like this: -$ (text="perf" ; - pbmtext -nomargins -lspace 0 -builtin fixed "${text}" | - pbmtopgm 1 1 | - pgmtoppm 1.0,1.0,1.0-0,0,0 /dev/stdin | - ppmtogif | - giftopnm | - pnmtopng >"tag_${text}.png") ---> - -<!-- compile with: -xsltproc −−stringparam generate.section.toc.level 0 \ - −−stringparam toc.max.depth 3 \ - −−stringparam toc.section.depth 12 \ - −−xinclude -o opensolaris_shell_styleguide.html /usr/share/sgml/docbook/docbook-xsl-stylesheets-1.69.1/html/docbook.xsl opensolaris_shell_styleguide.docbook ---> - -<article - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns="http://docbook.org/ns/docbook" - xml:lang="en"> - <!-- xmlns:xi="http://www.w3.org/2001/XInclude" --> - - <info> - <title><emphasis>[DRAFT]</emphasis> Bourne/Korn Shell Coding Conventions</title> - - <!-- subtitle abuse --> - <subtitle> - This page is currently work-in-progress until it is approved by the OS/Net community. Please send any comments to - <email>shell-discuss@opensolaris.org</email>. - </subtitle> - - - <authorgroup> -<!-- - <author><personname>David G. Korn</personname><email>dgk@research.att.com</email></author> - <author><personname>Roland Mainz</personname><email>roland.mainz@nrubsig.org</email></author> - <author><personname>Mike Shapiro</personname><email>mike.shapiro@sun.com</email></author> ---> - <author><orgname>OpenSolaris.org</orgname></author> - </authorgroup> - </info> - -<section xml:id="intro"> - <title>Intro</title> - <para>This document describes the shell coding style used for all the SMF script changes integrated into (Open)Solaris.</para> - <para>All new SMF shell code should conform to this coding standard, which is intended to match our existing C coding standard.</para> - <para>When in doubt, think "what would be the C-Style equivalent ?" and "What does the POSIX (shell) standard say ?"</para> -</section><!-- end of intro --> - - -<section xml:id="rules"> - <title>Rules</title> - - - - <section xml:id="general"> - <title>General</title> - - <section xml:id="basic_format"> - <title>Basic Format</title> - <para>Similar to <literal>cstyle</literal>, the basic format is that all - lines are indented by TABs or eight spaces, and continuation lines (which - in the shell end with "\") are indented by an equivalent number of TABs - and then an additional four spaces, e.g. -<programlisting> -cp foo bar -cp some_realllllllllllllllly_realllllllllllllly_long_path \ - to_another_really_long_path -</programlisting> - </para> - <para>The encoding used for the shell scripts is either <literal>ASCII</literal> - or <literal>UTF-8</literal>, alternative encodings are only allowed when the - application requires this.</para> - </section> - - - <section xml:id="commenting"> - <title>Commenting</title> - <para>Shell comments are preceded by the '<literal>#</literal>' character. Place - single-line comments in the right-hand margin. Use an extra '<literal>#</literal>' - above and below the comment in the case of multi-line comments: -<programlisting> -cp foo bar # Copy foo to bar - -# -# Modify the permissions on bar. We need to set them to root/sys -# in order to match the package prototype. -# -chown root bar -chgrp sys bar -</programlisting> - </para> - </section> - - - <section xml:id="interpreter_magic"> - <title>Interpreter magic</title> - <para>The proper interpreter magic for your shell script should be one of these: -<programlisting> -#!/bin/sh Standard Bourne shell script -#!/bin/ksh -p Standard Korn shell 88 script. You should always write ksh - scripts with -p so that ${ENV} (if set by the user) is not - sourced into your script by the shell. -#!/bin/ksh93 Standard Korn shell 93 script (-p is not needed since ${ENV} is - only used for interactive shell sessions). -</programlisting> - </para> - </section> - - - <section xml:id="harden_your_script_against_unexpected_input"> - <title>Harden the script against unexpected (user) input</title> - <para>Harden your script against unexpected (user) input, including - command line options, filenames with blanks (or other special - characters) in the name, or file input</para> - </section> - - - <section xml:id="use_builtin_commands"> - <title>&tag_kshonly;&tag_performance;Use builtin commands if the shell provides them</title> - <para> - Use builtin commands if the shell provides them. For example ksh93s+ - (ksh93, version 's+') delivered with Solaris (as defined by PSARC 2006/550) - supports the following builtins: - <simplelist type="inline"> - <member>basename</member> - <member>cat</member> - <member>chgrp</member> - <member>chmod</member> - <member>chown</member> - <member>cmp</member> - <member>comm</member> - <member>cp</member> - <member>cut</member> - <member>date</member> - <member>dirname</member> - <member>expr</member> - <member>fds</member> - <member>fmt</member> - <member>fold</member> - <member>getconf</member> - <member>head</member> - <member>id</member> - <member>join</member> - <member>ln</member> - <member>logname</member> - <member>mkdir</member> - <member>mkfifo</member> - <member>mv</member> - <member>paste</member> - <member>pathchk</member> - <member>rev</member> - <member>rm</member> - <member>rmdir</member> - <member>stty</member> - <member>tail</member> - <member>tee</member> - <member>tty</member> - <member>uname</member> - <member>uniq</member> - <member>wc</member> - <member>sync</member> - </simplelist> - Those builtins can be enabled via <literal>$ builtin name_of_builtin #</literal> in shell - scripts (note that ksh93 builtins implement exact POSIX behaviour - some - commands in Solaris <filename>/usr/bin/</filename> directory implement pre-POSIX behaviour. - Add <literal>/usr/xpg6/bin/:/usr/xpg4/bin</literal> before - <filename>/usr/bin/</filename> in <envar>${PATH}</envar> to test whether your script works with - the XPG6/POSIX versions) - </para> - </section> - - - <section xml:id="use_blocks_not_subshells"> - <title>&tag_performance;Use blocks and not subshells if possible</title> - <para>Use blocks and not subshells if possible, e.g. use - <literal>$ { print "foo" ; print "bar" ; }</literal> instead of - <literal>$ (print "foo" ; print "bar") #</literal> - blocks are - faster since they do not require to save the subshell context (ksh93) or - trigger a shell child process (Bourne shell, bash, ksh88 etc.) - </para> - </section> - - - <section xml:id="use_long_options_for_set_builtin"> - <title>&tag_kshonly; use long options for "<literal>set</literal>"</title> - <para>use long options for "<literal>set</literal>", for example instead of <literal>$ set -x #</literal> - use <literal>$ set -o xtrace #</literal> to make the code more readable.</para> - </section> - - - <section xml:id="use_posix_command_substitutions_syntax"> - <title>&tag_kshonly; Use <literal>$(...)</literal> instead of <literal>`...`</literal> command substitutions</title> - <para>Use <literal>$(...)</literal> instead of <literal>`...`</literal> - <literal>`...`</literal> - is an obsolete construct in ksh+POSIX sh scripts and <literal>$(...)</literal>.is a cleaner design, - requires no escaping rules, allows easy nesting etc.</para> - - <note><title>&tag_ksh93only; <literal>${ ...;}</literal>-style command substitutions</title> - <para>ksh93 has support for an alternative version of command substitutions with the - syntax <literal>${ ...;}</literal> which do not run in a subshell. - </para></note> - </section> - - - <section xml:id="put_command_substitution_result_in_quotes"> - <title>&tag_kshonly; Always put the result of a <literal>$(...)</literal> or - <literal>$( ...;)</literal> command substitution in quotes</title> - <para>Always put the result of <literal>$( ... )</literal> or <literal>$( ...;)</literal> in - quotes (e.g. <literal>foo="$( ... )"</literal> or <literal>foo="$( ...;)"</literal>) unless - there is a very good reason for not doing it</para> - </section> - - - <section xml:id="always_set_path"> - <title>Scripts should always set their <envar>PATH</envar></title> - <para>Scripts should always set their <envar>PATH</envar> to make sure they do not use - alternative commands by accident (unless the value of <envar>PATH</envar> is well-known - and guaranteed to be set by the caller)</para> - </section> - - - <section xml:id="make_sure_commands_are_available"> - <title>Make sure that commands from other packages/applications are really installed on the machine</title> - <para>Scripts should make sure that commands in optional packages are really - there, e.g. add a "precheck" block in scipts to avoid later failure when - doing the main job</para> - </section> - - - <section xml:id="check_usage_of_boolean_variables"> - <title>Check how boolean values are used/implemented in your application</title> - <para>Check how boolean values are used in your application.</para> - <para>For example: -<programlisting> -mybool=0 -# do something -if [ $mybool -eq 1 ] ; then do_something_1 ; fi -</programlisting> -could be rewritten like this: -<programlisting> -mybool=false # (valid values are "true" or "false", pointing -# to the builtin equivalents of /bin/true or /bin/false) -# do something -if ${mybool} ; then do_something_1 ; fi -</programlisting> -or -<programlisting> -integer mybool=0 # values are 0 or 1 -# do something -if (( mybool==1 )) ; then do_something_1 ; fi -</programlisting> - </para> - </section> - - <section xml:id="shell_uses_characters_not_bytes"> - <title>&tag_i18n;The shell always operates on <emphasis>characters</emphasis> not bytes</title> - <para>Shell scripts operate on characters and <emphasis>not</emphasis> bytes. - Some locales use multiple bytes (called "multibyte locales") to represent one character</para> - - <note><para>ksh93 has support for binary variables which explicitly - operate on bytes, not characters. This is the <emphasis>only</emphasis> allowed - exception.</para></note> - </section> - - - <section xml:id="multibyte_locale_input"> - <title>&tag_i18n;Multibyte locales and input</title> - <para>Think about whether your application has to handle file names or - variables in multibyte locales and make sure all commands used in your - script can handle such characters (e.g. lots of commands in Solaris's - <filename>/usr/bin/</filename> are <emphasis>not</emphasis> able to handle such values - either use ksh93 - builtin constructs (which are guaranteed to be multibyte-aware) or - commands from <filename>/usr/xpg4/bin/</filename> and/or <filename>/usr/xpg6/bin</filename>) - </para> - </section> - - - <section xml:id="use_external_filters_only_for_large_datasets"> - <title>&tag_performance;Only use external filters like <literal>grep</literal>/<literal>sed</literal>/<literal>awk</literal>/etc. - if you want to process lots of data with them</title> - <para>Only use external filters like <literal>grep</literal>/<literal>sed</literal>/<literal>awk</literal>/etc. - if a significant amount of data is processed by the filter or if - benchmarking shows that the use of builtin commands is significantly slower - (otherwise the time and resources needed to start the filter are - far greater then the amount of data being processed, - creating a performance problem).</para> - <para>For example: -<programlisting> -if [ "$(echo "$x" | egrep '.*foo.*')" != "" ] ; then - do_something ; -done -</programlisting> -can be re-written using ksh93 builtin constructs, saving several -<literal>|fork()|+|exec()|</literal>'s: -<programlisting> -if [[ "${x}" == ~(E).*foo.* ]] ; then - do_something ; -done -</programlisting> - </para> - </section> - - - <section xml:id="use_dashdash_if_first_arg_is_variable"> - <title>If the first operand of a command is a variable, use <literal>--</literal></title> - <para>If the first operand of a command is a variable, use <literal>--</literal> - for any command that accepts this as end of argument to - avoid problems if the variable expands to a value starting with <literal>-</literal>. - </para> - <note><para> - At least - <simplelist type="inline"> - <member>print</member> - <member>/usr/bin/fgrep</member><member>/usr/xpg4/bin/fgrep</member> - <member>/usr/bin/grep</member> <member>/usr/xpg4/bin/grep</member> - <member>/usr/bin/egrep</member><member>/usr/xpg4/bin/egrep</member> - </simplelist> - support <literal>--</literal> as "end of arguments"-terminator. - </para></note> - </section> - - <section xml:id="use_export"> - <title>&tag_kshonly;&tag_performance;Use <literal>$ export FOOBAR=val #</literal> instead of - <literal>$ FOOBAR=val ; export FOOBAR #</literal></title> - <para>Use <literal>$ export FOOBAR=val # instead of $ FOOBAR=val ; export FOOBAR #</literal> - - this is much faster.</para> - </section> - - - <section xml:id="use_subshell_around_set_dashdash_usage"> - <title>Use a subshell (e.g. <literal>$ ( mycmd ) #</literal>) around places which use - <literal>set -- $(mycmd)</literal> and/or <literal>shift</literal></title> - <para>Use a subshell (e.g. <literal>$ ( mycmd ) #</literal>) around places which use - <literal>set -- $(mycmd)</literal> and/or <literal>shift</literal> unless the variable - affected is either a local one or if it's guaranteed that this variable will no longer be used - (be careful for loadable functions, e.g. ksh/ksh93's <literal>autoload</literal> !!!!) - </para> - </section> - - - <section xml:id="be_careful_with_tabs_in_script_code"> - <title>Be careful with using TABS in script code, they are not portable - between editors or platforms</title> - <para>Be careful with using TABS in script code, they are not portable - between editors or platforms.</para> - <para>If you use ksh93 use <literal>$'\t'</literal> to include TABs in sources, not the TAB character itself.</para> - </section> - - - <section xml:id="centralise_error_exit"> - <title>If you have multiple points where your application exits with an error - message create a central function for this purpose</title> - <para>If you have multiple points where your application exits with an error - message create a central function for this, e.g. -<programlisting> -if [ -z "$tmpdir" ] ; then - print -u2 "mktemp failed to produce output; aborting." - exit 1 -fi -if [ ! -d $tmpdir ] ; then - print -u2 "mktemp failed to create a directory; aborting." - exit 1 -fi -</programlisting> -should be replaced with -<programlisting> -function fatal_error -{ - print -u2 "${progname}: $*" - exit 1 -} -# do something (and save ARGV[0] to variable "progname") -if [ -z "$tmpdir" ] ; then - fatal_error "mktemp failed to produce output; aborting." -fi -if [ ! -d "$tmpdir" ] ; then - fatal_error "mktemp failed to create a directory; aborting." -fi -</programlisting> - </para> - </section> - - - <section xml:id="use_set_o_nounset"> - <title>&tag_kshonly; Think about using <literal>$ set -o nounset #</literal> by default</title> - <para>Think about using <literal>$ set -o nounset #</literal> by default (or at least during the - script's development phase) to catch errors where variables are used - when they are not set (yet), e.g. -<screen> -$ <userinput>(set -o nounset ; print ${foonotset})</userinput> -<computeroutput>/bin/ksh93: foonotset: parameter not set</computeroutput> -</screen> - </para> - </section> - - - <section xml:id="avoid_eval_builtin"> - <title>Avoid using <literal>eval</literal> unless absolutely necessary</title> - <para>Avoid using <literal>eval</literal> unless absolutely necessary. Subtle things - can happen when a string is passed back through the shell - parser. You can use name references to avoid uses such as - <literal>eval $name="$value"</literal>. - </para> - </section> - - - <section xml:id="use_concatenation_operator"> - <title>&tag_ksh93only;Use the string/array concatenation operator <literal>+=</literal></title> - <para>Use <literal>+=</literal> instead of manually adding strings/array elements, e.g. -<programlisting> -foo="" -foo="${foo}a" -foo="${foo}b" -foo="${foo}c" -</programlisting> -should be replaced with -<programlisting> -foo="" -foo+="a" -foo+="b" -foo+="c" -</programlisting> - </para> - </section> - - <section xml:id="use_source_not_dot"> - <title>&tag_ksh93only;Use <literal>source</literal> instead of '<literal>.</literal> '(dot) - to include other shell script fragments</title> - <para>Use <literal>source</literal> instead of '<literal>.</literal>' - (dot) to include other shell script fragments - the new form is much - more readable than the tiny dot and a failure can be caught within the script.</para> - </section> - - - <section xml:id="use_builtin_localisation_support"> - <title>&tag_ksh93only;&tag_performance;&tag_l10n;Use <literal>$"..."</literal> instead of - <literal>gettext ... "..."</literal> for strings that need to be localized for different locales</title> - <para>Use $"..." instead of <literal>gettext ... "..."</literal> for strings that need to be - localized for different locales. <literal>gettext</literal> will require a - <literal>fork()+exec()</literal> and - reads the whole catalog each time it's called, creating a huge overhead for localisation - (and the <literal>$"..."</literal> is easier to use, e.g. you only have to put a - <literal>$</literal> in front of the catalog and the string will be localised). - </para> - </section> - - - <section xml:id="use_set_o_noglob"> - <title>&tag_kshonly;&tag_performance;Use <literal>set -o noglob</literal> if you do not need to expand files</title> - <para>If you don't expect to expand files, you can do set <literal>-f</literal> - (<literal>set -o noglob</literal>) as well. This way the need to use <literal>""</literal> is - greatly reduced.</para> - </section> - - - <section xml:id="use_empty_ifs_to_handle_spaces"> - <title>&tag_ksh93only;Use <literal>IFS=</literal> to avoid problems with spaces in filenames</title> - <para>Unless you want to do word splitting, put <literal>IFS=</literal> - at the beginning of a command. This way spaces in - file names won't be a problem. You can do - <literal>IFS='delims' read -r</literal> line - to override <envar>IFS</envar> just for the <literal>read</literal> command. However, - you can't do this for the <literal>set</literal> builtin.</para> - </section> - - - <section xml:id="set_locale_when_comparing_against_localised_output"> - <title>Set the message locale if you process output of tools which may be localised</title> - <para>Set the message locale (<envar>LC_MESSAGES</envar>) if you process output of tools which may be localised</para> - <example><title>Set <envar>LC_MESSAGES</envar> when testing for specific outout of the <filename>/usr/bin/file</filename> utility:</title> -<programlisting> -# set french as default message locale -export LC_MESSAGES=fr_FR.UTF-8 - -... - -# test whether the file "/tmp" has the filetype "directory" or not -# we set LC_MESSAGES to "C" to ensure the returned message is in english -if [[ "$(LC_MESSAGES=C file /tmp)" = *directory ]] ; then - print "is a directory" -fi -</programlisting> - <note><para>The environment variable <envar>LC_ALL</envar> always - overrides any other <envar>LC_*</envar> environment variables - (and <envar>LANG</envar>, too), - including <envar>LC_MESSAGES</envar>. - if there is the chance that <envar>LC_ALL</envar> may be set - replace <envar>LC_MESSAGES</envar> with <envar>LC_ALL</envar> - in the example above.</para></note> - </example> - </section> - - <section xml:id="cleanup_after_yourself"> - <title>Cleanup after yourself.</title> - <para>Cleanup after yourself. For example ksh/ksh93 have an <literal>EXIT</literal> trap which - is very useful for this. - </para> - <note><para> - Note that the <literal>EXIT</literal> trap is executed for a subshell and each subshell - level can run it's own <literal>EXIT</literal> trap, for example -<screen> -$ <userinput>(trap "print bam" EXIT ; (trap "print snap" EXIT ; print "foo"))</userinput> -<computeroutput>foo -snap -bam</computeroutput> -</screen> - </para></note> - </section> - - <section xml:id="use_proper_exit_code"> - <title>Use a proper <literal>exit</literal> code</title> - <para>Explicitly set the exit code of a script, otherwise the exit code - from the last command executed will be used which may trigger problems - if the value is unexpected.</para> - </section> - - - <section xml:id="shell_lint"> - <title>&tag_ksh93only;Use <literal>shcomp -n scriptname.sh /dev/null</literal> to check for common errors</title> - <para>Use <literal>shcomp -n scriptname.sh /dev/null</literal> to - check for common problems (such as insecure, depreciated or ambiguous constructs) in shell scripts.</para> - </section> - </section><!-- end of general --> - - - - - - <section xml:id="functions"> - <title>Functions</title> - - <section xml:id="use_functions"> - <title>Use functions to break up your code</title> - <para>Use functions to break up your code into smaller, logical blocks.</para> - </section> - - <section xml:id="do_not_reserved_keywords_for_function_names"> - <title>Do not use function names which are reserved keywords in C/C++/JAVA or the POSIX shell standard</title> - <para>Do not use function names which are reserved keywords (or function names) in C/C++/JAVA or the POSIX shell standard - (to avoid confusion and/or future changes/updates to the shell language). - </para> - </section> - - <section xml:id="use_ksh_style_function_syntax"> - <title>&tag_kshonly;&tag_performance;Use ksh-style <literal>function</literal></title> - <para>It is <emphasis>highly</emphasis> recommended to use ksh style functions - (<literal>function foo { ... }</literal>) instead - of Bourne-style functions (<literal>foo() { ... }</literal>) if possible - (and local variables instead of spamming the global namespace).</para> - - <warning><para> - The difference between old-style Bourne functions and ksh functions is one of the major differences - between ksh88 and ksh93 - ksh88 allowed variables to be local for Bourne-style functions while ksh93 - conforms to the POSIX standard and will use a function-local scope for variables declared in - Bourne-style functions.</para> - <para>Example (note that "<literal>integer</literal>" is an alias for "<literal>typeset -li</literal>"): -<programlisting> -# new style function with local variable -$ ksh93 -c 'integer x=2 ; function foo { integer x=5 ; } ; print "x=$x" -; foo ; print "x=$x" ;' -x=2 -x=2 -# old style function with an attempt to create a local variable -$ ksh93 -c 'integer x=2 ; foo() { integer x=5 ; } ; print "x=$x" ; foo ; -print "x=$x" ;' -x=2 -x=5 -</programlisting> - - <uri xlink:href="http://www.opensolaris.org/os/project/ksh93-integration/docs/ksh93r/general/compatibility/">usr/src/lib/libshell/common/COMPATIBILITY</uri> - says about this issue: -<blockquote><para> -Functions, defined with name() with ksh-93 are compatible with -the POSIX standard, not with ksh-88. No local variables are -permitted, and there is no separate scope. Functions defined -with the function name syntax, maintain compatibility. -This also affects function traces. -</para></blockquote> -(this issue also affects <filename>/usr/xpg4/bin/sh</filename> in Solaris 10 because it is based on ksh88. This is a bug.). - </para></warning> - - </section> - - - <section xml:id="use_proper_return_code"> - <title>Use a proper <literal>return</literal> code</title> - <para>Explicitly set the return code of a function - otherwise the exit code - from the last command executed will be used which may trigger problems - if the value is unexpected.</para> - <para>The only allowed exception is if a function uses the shell's <literal>errexit</literal> mode to leave - a function, subshell or the script if a command returns a non-zero exit code. - </para> - </section> - - <section xml:id="use_fpath_to_load_common_code"> - <title>&tag_kshonly;Use <envar>FPATH</envar> to load common functions, not <literal>source</literal></title> - <para> - Use the ksh <envar>FPATH</envar> (function path) feature to load functions which are shared between scripts - and not <literal>source</literal> - this allows to load such a function on demand and not all at once.</para> - </section> - - </section><!-- end of functions --> - - - - - <section xml:id="if_for_while"> - <title><literal>if</literal>, <literal>for</literal> and <literal>while</literal></title> - - <section xml:id="if_for_while_format"> - <title>Format</title> - <para>To match <literal>cstyle</literal>, the shell token equivalent to the <literal>C</literal> - "<literal>{</literal>" should appear on the same line, separated by a - "<literal>;</literal>", as in: -<programlisting> -if [ "$x" = "hello" ] ; then - echo $x -fi - -if [[ "$x" = "hello" ]] ; then - print $x -fi - -for i in 1 2 3; do - echo $i -done - -for ((i=0 ; i < 3 ; i++)); do - print $i -done - -while [ $# -gt 0 ]; do - echo $1 - shift -done - -while (( $# > 0 )); do - print $1 - shift -done -</programlisting> - </para> - </section> - - - <section xml:id="test_builtin"> - <title><literal>test</literal> Builtin</title> - <para>DO NOT use the test builtin. Sorry, executive decision.</para> - <para>In our Bourne shell, the <literal>test</literal> built-in is the same as the "[" - builtin (if you don't believe me, try "type test" or refer to <filename>usr/src/cmd/sh/msg.c</filename>).</para> - <para> - So please do not write: -<programlisting> -if test $# -gt 0 ; then -</programlisting> -instead use: -<programlisting> -if [ $# -gt 0 ] ; then -</programlisting> - </para> - </section> - - - <section xml:id="use_ksh_test_syntax"> - <title>&tag_kshonly;&tag_performance;Use "<literal>[[ expr ]]</literal>" instead of "<literal>[ expr ]</literal>"</title> - <para>Use "<literal>[[ expr ]]</literal>" instead of "<literal>[ expr ]</literal>" if possible - since it avoids going through the whole pattern expansion/etc. machinery and - adds additional operators not available in the Bourne shell, such as short-circuit - <literal>&&</literal> and <literal>||</literal>. - </para> - </section> - - - <section xml:id="use_posix_arithmetic_expressions"> - <title>&tag_kshonly; Use "<literal>(( ... ))</literal>" for arithmetic expressions</title> - <para>Use "<literal>(( ... ))</literal>" instead of "<literal>[ expr ]</literal>" - or "<literal>[[ expr ]]</literal>" expressions. - </para> - <para> - Example: Replace -<programlisting> -i=5 -# do something -if [ $i -gt 5 ] ; then -</programlisting> -with -<programlisting> -i=5 -# do something -if (( i > 5 )) ; then -</programlisting> - </para> - </section> - - - <section xml:id="compare_exit_code_using_math"> - <title>&tag_kshonly;&tag_performance;Compare exit code using arithmetic expressions expressions</title> - <para>Use POSIX arithmetic expressions to test for exit/return codes of commands and functions. - For example turn -<programlisting> -if [ $? -gt 0 ] ; then -</programlisting> -into -<programlisting> -if (( $? > 0 )) ; then -</programlisting> - </para> - </section> - - - <section xml:id="use_builtin_commands_in_loops"> - <title>&tag_bourneonly; Use builtin commands in conditions for <literal>while</literal> endless loops</title> - <para>Make sure that your shell has a "<literal>true</literal>" builtin (like ksh93) when - executing endless loops like <literal>$ while true ; do do_something ; done #</literal> - - otherwise each loop cycle runs a <literal>|fork()|+|exec()|</literal>-cycle to run - <filename>/bin/true</filename> - </para> - </section> - - - <section xml:id="single_line_if_statements"> - <title>Single-line if-statements</title> - <para>It is permissible to use <literal>&&</literal> and <literal>||</literal> to construct - shorthand for an "<literal>if</literal>" statement in the case where the if statement has a - single consequent line: -<programlisting> -[ $# -eq 0 ] && exit 0 -</programlisting> -instead of the longer: -<programlisting> -if [ $# -eq 0 ]; then - exit 0 -fi -</programlisting> - </para> - </section> - - - <section xml:id="exit_status_and_if_for_while"> - <title>Exit Status and <literal>if</literal>/<literal>while</literal> statements</title> - <para>Recall that "<literal>if</literal>" and "<literal>while</literal>" - operate on the exit status of the statement - to be executed. In the shell, zero (0) means true and non-zero means false. - The exit status of the last command which was executed is available in the $? - variable. When using "<literal>if</literal>" and "<literal>while</literal>", - it is typically not necessary to use - <literal>$?</literal> explicitly, as in: -<programlisting> -grep foo /etc/passwd >/dev/null 2>&1 -if [ $? -eq 0 ]; then - echo "found" -fi -</programlisting> -Instead, you can more concisely write: -<programlisting> -if grep foo /etc/passwd >/dev/null 2>&1; then - echo "found" -fi -</programlisting> -Or, when appropriate: -<programlisting> -grep foo /etc/passwd >/dev/null 2>&1 && echo "found" -</programlisting> - </para> - </section> - - </section><!-- end of if/for/while --> - - - - - - - <section xml:id="variables"> - <title>Variable types, naming and usage</title> - - <section xml:id="names_should_be_lowercase"> - <title>Names of local, non-environment, non-constant variables should be lowercase</title> - <para>Names of variables local to the current script which are not exported to the environment - should be lowercase while variable names which are exported to the - environment should be uppercase.</para> - <para>The only exception are global constants (=global readonly variables, - e.g. <literal>$ float -r M_PI=3.14159265358979323846 #</literal> (taken from <math.h>)) - which may be allowed to use uppercase names, too. - </para> - - <warning><para> - Uppercase variable names should be avoided because there is a good chance - of naming collisions with either special variable names used by the shell - (e.g. <literal>PWD</literal>, <literal>SECONDS</literal> etc.). - </para></warning> - </section> - - <section xml:id="do_not_reserved_keywords_for_variable_names"> - <title>Do not use variable names which are reserved keywords/variable names in C/C++/JAVA or the POSIX shell standard</title> - <para>Do not use variable names which are reserved keywords in C/C++/JAVA or the POSIX shell standard - (to avoid confusion and/or future changes/updates to the shell language). - </para> - <note> - <para>The Korn Shell and the POSIX shell standard have many more - reserved variable names than the original Bourne shell. All - these reserved variable names are spelled uppercase. - </para> - </note> - </section> - - <section xml:id="use_brackets_around_long_names"> - <title>Always use <literal>'{'</literal>+<literal>'}'</literal> when using variable - names longer than one character</title> - <para>Always use <literal>'{'</literal>+<literal>'}'</literal> when using - variable names longer than one character unless a simple variable name is - followed by a blank, <literal>/</literal>, <literal>;</literal>, or <literal>$</literal> - character (to avoid problems with array, - compound variables or accidental misinterpretation by users/shell) -<programlisting> -print "$foo=info" -</programlisting> -should be rewritten to -<programlisting> -print "${foo}=info" -</programlisting> - </para> - </section> - - - <section xml:id="quote_variables_containing_filenames_or_userinput"> - <title><emphasis>Always</emphasis> put variables into quotes when handling filenames or user input</title> - <para><emphasis>Always</emphasis> put variables into quotes when handling filenames or user input, even if - the values are hardcoded or the values appear to be fixed. Otherwise at - least two things may go wrong: - <itemizedlist> - <listitem><para>a malicious user may be able to exploit a script's inner working to - infect his/her own code</para></listitem> - <listitem><para>a script may (fatally) misbehave for unexpected input (e.g. file names - with blanks and/or special symbols which are interpreted by the shell)</para></listitem> - </itemizedlist> - </para> - - <note><para> - As alternative a script may set <literal>IFS='' ; set -o noglob</literal> to turn off the - interpretation of any field seperators and the pattern globbing. - </para></note> - </section> - - - - <section xml:id="use_typed_variables"> - <title>&tag_kshonly;&tag_performance;Use typed variables if possible.</title> - <para>For example the following is very - inefficient since it transforms the integer values to strings and back - several times: -<programlisting> -a=0 -b=1 -c=2 -# more code -if [ $a -lt 5 -o $b -gt c ] ; then do_something ; fi -</programlisting> -This could be rewritten using ksh constructs: -<programlisting> -integer a=0 -integer b=1 -integer c=2 -# more code -if (( a < 5 || b > c )) ; then do_something ; fi -</programlisting> - </para> - </section> - - - <section xml:id="store_lists_in_arrays"> - <title>&tag_ksh93only; Store lists in arrays or associative arrays</title> - <para>Store lists in arrays or associative arrays - this is usually easier - to manage.</para> - <para> - For example: -<programlisting> -x=" -/etc/foo -/etc/bar -/etc/baz -" -echo $x -</programlisting> -can be replaced with -<programlisting> -typeset -a mylist -mylist[0]="/etc/foo" -mylist[1]="/etc/bar" -mylist[2]="/etc/baz" -print "${mylist[@]}" -</programlisting> -or (ksh93-style append entries to a normal (non-associative) array) -<programlisting> -typeset -a mylist -mylist+=( "/etc/foo" ) -mylist+=( "/etc/bar" ) -mylist+=( "/etc/baz" ) -print "${mylist[@]}" -</programlisting> - </para> - <note> - <title>Difference between expanding arrays with mylist[@] and mylist[*] subscript operators</title> - <para> - Arrays may be expanded using two similar subscript operators, @ and *. These subscripts - differ only when the variable expansion appears within double quotes. If the variable expansion - is between double-quotes, "${mylist[*]}" expands to a single string with the value of each array - member separated by the first character of the <envar>IFS</envar> variable, and "${mylist[@]}" - expands each element of name to a separate string. - </para> - <example><title>Difference between [@] and [*] when expanding arrays</title> -<programlisting> -typeset -a mylist -mylist+=( "/etc/foo" ) -mylist+=( "/etc/bar" ) -mylist+=( "/etc/baz" ) -IFS="," -printf "mylist[*]={ 0=|%s| 1=|%s| 2=|%s| 3=|%s| }\n" "${mylist[*]}" -printf "mylist[@]={ 0=|%s| 1=|%s| 2=|%s| 3=|%s| }\n" "${mylist[@]}" -</programlisting> -<para>will print:</para> -<screen> -<computeroutput>mylist[*]={ 0=|/etc/foo,/etc/bar,/etc/baz| 1=|| 2=|| 3=|| } -mylist[@]={ 0=|/etc/foo| 1=|/etc/bar| 2=|/etc/baz| 3=|| } -</computeroutput> -</screen> - </example> - </note> - </section> - - - <section xml:id="use_compound_variables_or_lists_for_grouping"> - <title>&tag_ksh93only; Use compound variables or associative arrays to group similar variables together</title> - <para>Use compound variables or associative arrays to group similar variables together.</para> - <para> - For example: -<programlisting> -box_width=56 -box_height=10 -box_depth=19 -echo "${box_width} ${box_height} ${box_depth}" -</programlisting> -could be rewritten to ("associative array"-style) -<programlisting> -typeset -A -E box=( [width]=56 [height]=10 [depth]=19 ) -print -- "${box[width]} ${box[height]} ${box[depth]}" -</programlisting> -or ("compound variable"-style -<programlisting> -box=( - float width=56 - float height=10 - float depth=19 - ) -print -- "${box.width} ${box.height} ${box.depth}" -</programlisting> - </para> - </section> - </section><!-- end of variables --> - - - - - - - - <section xml:id="io"> - <title>I/O</title> - - <section xml:id="avoid_echo"> - <title>Avoid using the "<literal>echo</literal>" command for output</title> - <para>The behaviour of "<literal>echo</literal>" is not portable - (e.g. System V, BSD, UCB and ksh93/bash shell builtin versions all - slightly differ in functionality) and should be avoided if possible. - POSIX defines the "<literal>printf</literal>" command as replacement - which provides more flexible and portable behaviour.</para> - - <note> - <title>&tag_kshonly;Use "<literal>print</literal>" and not "<literal>echo</literal>" in Korn Shell scripts</title> - <para>Korn shell scripts should prefer the "<literal>print</literal>" - builtin which was introduced as replacement for "<literal>echo</literal>".</para> - <caution> - <para>Use <literal>$ print -- ${varname}" #</literal> when there is the slightest chance that the - variable "<literal>varname</literal>" may contain symbols like "-". Or better use "<literal>printf</literal>" - instead, for example -<programlisting> -integer fx -# do something -print $fx -</programlisting> -may fail if "f" contains a negative value. A better way may be to use -<programlisting> -integer fx -# do something -printf "%d\n" fx -</programlisting> - </para> - </caution> - </note> - </section> - - <section xml:id="use_redirect_not_exec_to_open_files"> - <title>&tag_ksh93only;Use <literal>redirect</literal> and not <literal>exec</literal> to open files</title> - <para>Use <literal>redirect</literal> and not <literal>exec</literal> to open files - <literal>exec</literal> - will terminate the current function or script if an error occurs while <literal>redirect</literal> - just returns a non-zero exit code which can be caught.</para> -<para>Example: -<programlisting> -if redirect 5</etc/profile ; then - print "file open ok" - head <&5 -else - print "could not open file" -fi -</programlisting> - </para> - </section> - - <section xml:id="group_identical_redirections_together"> - <title>&tag_performance;Avoid redirections per command when the output goes into the same file, - e.g. <literal>$ echo "foo" >xxx ; echo "bar" >>xxx ; echo "baz" >>xxx #</literal></title> - <para>Each of the redirections above trigger an - <literal>|open()|,|write()|,|close()|</literal>-sequence. It is much - more efficient (and faster) to group the rediction into a block, - e.g. <literal>{ echo "foo" ; echo "bar" ; echo "baz" } >xxx #</literal></para> - </section> - - - <section xml:id="avoid_using_temporary_files"> - <title>&tag_performance;Avoid the creation of temporary files and store the values in variables instead</title> - <para>Avoid the creation of temporary files and store the values in variables instead if possible</para> - <para> - Example: -<programlisting> -ls -1 >xxx -for i in $(cat xxx) ; do - do_something ; -done -</programlisting> -can be replaced with -<programlisting> -x="$(ls -1)" -for i in ${x} ; do - do_something ; -done -</programlisting> - </para> - <note><para>ksh93 supports binary variables (e.g. <literal>typeset -b varname</literal>) which can hold any value.</para></note> - </section> - - - <section xml:id="create_subdirs_for_multiple_temporary_files"> - <title>If you create more than one temporary file create an unique subdir</title> - <para>If you create more than one temporary file create an unique subdir for - these files and make sure the dir is writable. Make sure you cleanup - after yourself (unless you are debugging). - </para> - </section> - - - <section xml:id="use_dynamic_file_descriptors"> - <title>&tag_ksh93only;Use {n}<file instead of fixed file descriptor numbers</title> - <para>When opening a file use {n}<file, where <envar>n</envar> is an - integer variable rather than specifying a fixed descriptor number.</para> - <para>This is highly recommended in functions to avoid that fixed file - descriptor numbers interfere with the calling script.</para> -<example><title>Open a network connection and store the file descriptor number in a variable</title> -<programlisting> -function cat_http -{ - integer netfd - -... - - # open TCP channel - redirect {netfd}<>"/dev/tcp/${host}/${port}" - - # send HTTP request - request="GET /${path} HTTP/1.1\n" - request+="Host: ${host}\n" - request+="User-Agent: demo code/ksh93 (2007-08-30; $(uname -s -r -p))\n" - request+="Connection: close\n" - print "${request}\n" >&${netfd} - - # collect response and send it to stdout - cat <&${netfd} - - # close connection - exec {netfd}<&- - -... - -} -</programlisting> -</example> - </section> - - - <section xml:id="use_inline_here_documents"> - <title>&tag_ksh93only;&tag_performance;Use inline here documents - instead of <literal>echo "$x" | command</literal></title> - <para>Use inline here documents, for example -<programlisting> -command <<< $x -</programlisting> - rather than -<programlisting> -print -r -- "$x" | command -</programlisting> - </para> - </section> - - - <section xml:id="use_read_r"> - <title>&tag_ksh93only;Use the <literal>-r</literal> option of <literal>read</literal> to read a line</title> - <para>Use the <literal>-r</literal> option of <literal>read</literal> to read a line. - You never know when a line will end in <literal>\</literal> and without a - <literal>-r</literal> multiple - lines can be read.</para> - </section> - - - <section xml:id="print_compound_variables_using_print_C"> - <title>&tag_ksh93only;Print compound variables using <literal>print -C varname</literal> or <literal>print -v varname</literal></title> - <para>Print compound variables using <literal>print -C varname</literal> or - <literal>print -v varname</literal> to make sure that non-printable characters - are correctly encoded.</para> -<example><title>Print compound variable with non-printable characters</title> -<programlisting> -compound x=( - a=5 - b="hello" - c=( - d=9 - e="$(printf "1\v3")" <co xml:id="co.vertical_tab1" /> - ) -) -print -v x -</programlisting> -<para>will print:</para> -<screen> -<computeroutput>( - a=5 - b=hello - c=( - d=9 - e=$'1\0133' <co xml:id="co.vertical_tab2" /> - ) -)</computeroutput> -</screen> -<calloutlist> - <callout arearefs="co.vertical_tab1 co.vertical_tab2"> - <para>vertical tab, <literal>\v</literal>, octal=<literal>\013</literal>.</para> - </callout> -</calloutlist> -</example> - </section> - - <section xml:id="command_name_before_redirections"> - <title>Put the command name and arguments before redirections</title> - <para>Put the command name and arguments before redirections. - You can legally do <literal>$ > file date</literal> instead of <literal>date > file</literal> - but don't do it.</para> - </section> - - <section xml:id="enable_gmacs_editor_mode_for_user_prompts"> - <title>&tag_ksh93only;Enable the <literal>gmacs</literal> editor - mode when reading user input using the <literal>read</literal> builtin</title> - <para>Enable the <literal>gmacs</literal>editor mode before reading user - input using the <literal>read</literal> builtin to enable the use of - cursor+backspace+delete keys in the edit line</para> -<example><title>Prompt user for a string with gmacs editor mode enabled</title> -<programlisting> -set -o gmacs <co xml:id="co.enable_gmacs" /> -typeset inputstring="default value" -... -read -v<co xml:id="co.read_v" /> inputstring<co xml:id="co.readvar" />?"Please enter a string: "<co xml:id="co.prompt" /> -... -printf "The user entered the following string: '%s'\n" "${inputstring}" - -... -</programlisting> -<calloutlist> - <callout arearefs="co.enable_gmacs"> - <para>Enable gmacs editor mode.</para> - </callout> - <callout arearefs="co.read_v"> - <para>The value of the variable is displayed and used as a default value.</para> - </callout> - <callout arearefs="co.readvar"> - <para>Variable used to store the result.</para> - </callout> - <callout arearefs="co.prompt"> - <para>Prompt string which is displayed in stderr.</para> - </callout> -</calloutlist> -</example> - </section> - </section><!-- end of I/O --> - - - - - - - <section xml:id="math"> - <title>Math</title> - - <section xml:id="use_builtin_arithmetic_expressions"> - <title>&tag_kshonly;&tag_performance;Use builtin arithmetic expressions instead of external applications</title> - <para>Use builtin (POSIX shell) arithmetic expressions instead of - <filename>expr</filename>, - <filename>bc</filename>, - <filename>dc</filename>, - <filename>awk</filename>, - <filename>nawk</filename> or - <filename>perl</filename>. - </para> - <note> - <para>ksh93 supports C99-like floating-point arithmetic including special values - such as - <simplelist type="inline"> - <member>+Inf</member> - <member>-Inf</member> - <member>+NaN</member> - <member>-NaN</member> - </simplelist>. - </para> - </note> - </section> - - - <section xml:id="use_floating_point_arithmetic_expressions"> - <title>&tag_ksh93only; Use floating-point arithmetic expressions if - calculations may trigger a division by zero or other exceptions</title> - <para>Use floating-point arithmetic expressions if calculations may - trigger a division by zero or other exceptions - floating point arithmetic expressions in - ksh93 support special values such as <literal>+Inf</literal>/<literal>-Inf</literal> and - <literal>+NaN</literal>/<literal>-NaN</literal> which can greatly simplify testing for - error conditions, e.g. instead of a <literal>trap</literal> or explicit - <literal>if ... then... else</literal> checks for every sub-expression - you can check the results for such special values. - </para> - <para>Example: -<screen> -$ <userinput>ksh93 -c 'integer i=0 j=5 ; print -- "x=$((j/i)) "'</userinput> -<computeroutput>ksh93: line 1: j/i: divide by zero</computeroutput> -$ <userinput>ksh93 -c 'float i=0 j=-5 ; print -- "x=$((j/i)) "'</userinput> -<computeroutput>x=-Inf</computeroutput> -</screen> - </para> - </section> - - - <section xml:id="use_printf_a_for_passing_float_values"> - <title>&tag_ksh93only; Use <literal>printf "%a"</literal> when passing floating-point values</title> - <para>Use <literal>printf "%a"</literal> when passing floating-point values between scripts or - as output of a function to avoid rounding errors when converting between - bases.</para> - <para> - Example: -<programlisting> -function xxx -{ - float val - - (( val=sin(5.) )) - printf "%a\n" val -} -float out -(( out=$(xxx) )) -xxx -print -- $out -</programlisting> -This will print: -<programlisting> --0.9589242747 --0x1.eaf81f5e09933226af13e5563bc6p-01 -</programlisting> - </para> - </section> - - - <section xml:id="put_constants_into_readonly_variables"> - <title>&tag_kshonly;&tag_performance;Put constant values into readonly variables</title> - <para>Put constant values into readonly variables</para> - <para>For example: -<programlisting> -float -r M_PI=3.14159265358979323846 -</programlisting> -or -<programlisting> -float M_PI=3.14159265358979323846 -readonly M_PI -</programlisting> - </para> - </section> - - - <section xml:id="avoid_unnecessary_string_number_conversions"> - <title>&tag_kshonly;&tag_performance;Avoid string to number - (and/or number to string) conversions in arithmetic expressions - expressions</title> - <para>Avoid string to number and/or number to string conversions in - arithmetic expressions expressions to avoid performance degradation - and rounding errors.</para> - <example><title>(( x=$x*2 )) vs. (( x=x*2 ))</title> -<programlisting> -float x -... -(( x=$x*2 )) -</programlisting> -<para> -will convert the variable "x" (stored in the machine's native -<literal>|long double|</literal> datatype) to a string value in base10 format, -apply pattern expansion (globbing), then insert this string into the -arithmetic expressions and parse the value which converts it into the internal |long double| datatype format again. -This is both slow and generates rounding errors when converting the floating-point value between -the internal base2 and the base10 representation of the string. -</para> -<para> -The correct usage would be: -</para> -<programlisting> -float x -... -(( x=x*2 )) -</programlisting> -<para> -e.g. omit the '$' because it's (at least) redundant within arithmetic expressions. -</para> - </example> - - - <example><title>x=$(( y+5.5 )) vs. (( x=y+5.5 ))</title> -<programlisting> -float x -float y=7.1 -... -x=$(( y+5.5 )) -</programlisting> -<para> -will calculate the value of <literal>y+5.5</literal>, convert it to a -base-10 string value amd assign the value to the floating-point variable -<literal>x</literal> again which will convert the string value back to the -internal |long double| datatype format again. -</para> -<para> -The correct usage would be: -</para> -<programlisting> -float x -float y=7.1 -... -(( x=y+5.5 )) -</programlisting> -<para> -i.e. this will save the string conversions and avoid any base2-->base10-->base2-conversions. -</para> - </example> - </section> - - - <section xml:id="set_lc_numeric_when_using_floating_point"> - <title>&tag_ksh93only;Set <envar>LC_NUMERIC</envar> when using floating-point constants</title> - <para>Set <envar>LC_NUMERIC</envar> when using floating-point constants to avoid problems with radix-point - representations which differ from the representation used in the script, for example the <literal>de_DE.*</literal> locale - use ',' instead of '.' as default radix point symbol.</para> - <para>For example: -<programlisting> -# Make sure all math stuff runs in the "C" locale to avoid problems with alternative -# radix point representations (e.g. ',' instead of '.' in de_DE.*-locales). This -# needs to be set _before_ any floating-point constants are defined in this script) -if [[ "${LC_ALL}" != "" ]] ; then - export \ - LC_MONETARY="${LC_ALL}" \ - LC_MESSAGES="${LC_ALL}" \ - LC_COLLATE="${LC_ALL}" \ - LC_CTYPE="${LC_ALL}" - unset LC_ALL -fi -export LC_NUMERIC=C -... -float -r M_PI=3.14159265358979323846 -</programlisting> - </para> - - <note><para>The environment variable <envar>LC_ALL</envar> always overrides all other <envar>LC_*</envar> variables, - including <envar>LC_NUMERIC</envar>. The script should always protect itself against custom <envar>LC_NUMERIC</envar> and - <envar>LC_ALL</envar> values as shown in the example above. - </para></note> - </section> - - - - </section><!-- end of math --> - - - - - - - <section xml:id="misc"> - <title>Misc</title> - - <section xml:id="debug_use_lineno_in_ps4"> - <title>Put <literal>[${LINENO}]</literal> in your <envar>PS4</envar></title> - <para>Put <literal>[${LINENO}]</literal> in your <envar>PS4</envar> prompt so that you will get line - numbers with you run with <literal>-x</literal>. If you are looking at performance - issues put <literal>$SECONDS</literal> in the <envar>PS4</envar> prompt as well.</para> - </section> - - </section><!-- end of misc --> - - - - -</section><!-- end of RULES --> - - - - -</article> diff --git a/usr/src/lib/libsldap/Makefile.com b/usr/src/lib/libsldap/Makefile.com index d03823deb8..0d35b1f794 100644 --- a/usr/src/lib/libsldap/Makefile.com +++ b/usr/src/lib/libsldap/Makefile.com @@ -47,7 +47,7 @@ SRCDIR = ../common CFLAGS += $(CCVERBOSE) LOCFLAGS += -D_REENTRANT -DSUNW_OPTIONS CPPFLAGS += -I../common -I$(SRC)/lib/libldap5/include/ldap \ - -I/usr/include/mps $(LOCFLAGS) + -I$(ADJUNCT_PROTO)/usr/include/mps $(LOCFLAGS) LINTFLAGS += -erroff=E_BAD_PTR_CAST_ALIGN LINTFLAGS64 += -erroff=E_BAD_PTR_CAST_ALIGN diff --git a/usr/src/lib/libsmartsshd/Makefile b/usr/src/lib/libsmartsshd/Makefile new file mode 100644 index 0000000000..50d9545ef1 --- /dev/null +++ b/usr/src/lib/libsmartsshd/Makefile @@ -0,0 +1,48 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2011 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.lib + +SUBDIRS= $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +all clean clobber install lint: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +_msg: + +FRC: + +include ../Makefile.targ diff --git a/usr/src/lib/libsmartsshd/Makefile.com b/usr/src/lib/libsmartsshd/Makefile.com new file mode 100644 index 0000000000..914aab055b --- /dev/null +++ b/usr/src/lib/libsmartsshd/Makefile.com @@ -0,0 +1,47 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2011 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +LIBRARY= libsmartsshd.a +VERS= .1 +OBJECTS= sshd-plugin.o + +include ../../Makefile.lib +include ../../Makefile.rootfs + +SRCDIR = ../common +SRCS = $(OBJECTS:%.o=$(SRCDIR)/%.c) + +CPPFLAGS += -I$(SRCDIR) -D_REENTRANT -D_FILE_OFFSET_BITS=64 +LIBS = $(DYNLIB) $(LINTLIB) +LDLIBS += -lc -ldoor + +$(LINTLIB) := SRCS= $(SRCDIR)/$(LINTSRC) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include ../../Makefile.targ diff --git a/usr/src/lib/libsmartsshd/amd64/Makefile b/usr/src/lib/libsmartsshd/amd64/Makefile new file mode 100644 index 0000000000..31be0ef7e6 --- /dev/null +++ b/usr/src/lib/libsmartsshd/amd64/Makefile @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2011 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/libsmartsshd/common/llib-lsmartsshd b/usr/src/lib/libsmartsshd/common/llib-lsmartsshd new file mode 100644 index 0000000000..ace7017d41 --- /dev/null +++ b/usr/src/lib/libsmartsshd/common/llib-lsmartsshd @@ -0,0 +1,32 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/*LINTLIBRARY*/ +/*PROTOLIB1*/ +/* + * + * Copyright 2011 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + * + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + diff --git a/usr/src/lib/print/libipp-listener/common/mapfile b/usr/src/lib/libsmartsshd/common/mapfile-vers index 8aaaebddb2..ce5fc7a9c0 100644 --- a/usr/src/lib/print/libipp-listener/common/mapfile +++ b/usr/src/lib/libsmartsshd/common/mapfile-vers @@ -18,13 +18,7 @@ # # CDDL HEADER END # - -# -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# $Id: mapfile 151 2006-04-25 16:55:34Z njacobs $ +# Copyright (c) 2011, Joyent Inc. All rights reserved. # # @@ -43,10 +37,9 @@ $mapfile_version 2 -SYMBOL_VERSION SUNWprivate_1.0 { - global: - ipp_configure_operation; - ipp_process_request; - local: - *; +SYMBOL_VERSION SUNWprivate_1.1 { + global: + sshd_user_rsa_key_allowed; + local: + *; }; diff --git a/usr/src/lib/libsmartsshd/common/sshd-plugin.c b/usr/src/lib/libsmartsshd/common/sshd-plugin.c new file mode 100644 index 0000000000..4f0f0bc1ad --- /dev/null +++ b/usr/src/lib/libsmartsshd/common/sshd-plugin.c @@ -0,0 +1,123 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2011 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <alloca.h> +#include <door.h> +#include <errno.h> +#include <fcntl.h> +#include <pwd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <openssl/rsa.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define LOG_OOM(SZ) fprintf(stderr, "Unable to alloca %d bytes\n", SZ) + +static const char *DOOR = "/var/tmp/._joyent_sshd_key_is_authorized"; +static const char *REQ_FMT_STR = "%s %d %s"; /* name uid fp */ +static const int RETURN_SZ = 2; + +static const int MAX_ATTEMPTS = 2; +static const int SLEEP_PERIOD = 1; + +static int +sshd_allowed_in_capi(struct passwd *pw, const char *fp) +{ + int allowed = 0; + int fd = -1; + int blen = 0; + int attempts = 0; + char *buf = NULL; + door_arg_t door_args = {0}; + + if (pw == NULL || fp == NULL) + return (0); + + blen = snprintf(NULL, 0, REQ_FMT_STR, pw->pw_name, pw->pw_uid, fp) + 1; + + buf = (char *)alloca(blen); + if (buf == NULL) { + LOG_OOM(blen); + return (0); + } + + (void) snprintf(buf, blen, REQ_FMT_STR, pw->pw_name, pw->pw_uid, fp); + door_args.data_ptr = buf; + door_args.data_size = blen; + + door_args.rsize = RETURN_SZ; + door_args.rbuf = alloca(RETURN_SZ); + if (door_args.rbuf == NULL) { + LOG_OOM(RETURN_SZ); + return (0); + } + memset(door_args.rbuf, 0, RETURN_SZ); + + do { + fd = open(DOOR, O_RDWR); + if (fd < 0) + perror("smartplugin: open (of door FD) failed"); + + if (door_call(fd, &door_args) < 0) { + perror("smartplugin: door_call failed"); + } else { + allowed = atoi(door_args.rbuf); + munmap(door_args.rbuf, door_args.rsize); + return (allowed); + } + if (++attempts < MAX_ATTEMPTS) + sleep(SLEEP_PERIOD); + } while (attempts < MAX_ATTEMPTS); + + return (0); +} + +int +sshd_user_rsa_key_allowed(struct passwd *pw, RSA *key, const char *fp) +{ + return sshd_allowed_in_capi(pw, fp); +} + +int +sshd_user_dsa_key_allowed(struct passwd *pw, DSA *key, const char *fp) +{ + return sshd_allowed_in_capi(pw, fp); +} + + +#ifdef __cplusplus +} +#endif diff --git a/usr/src/lib/libsmartsshd/i386/Makefile b/usr/src/lib/libsmartsshd/i386/Makefile new file mode 100644 index 0000000000..2bfe8001d9 --- /dev/null +++ b/usr/src/lib/libsmartsshd/i386/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2011 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libumem/Makefile.com b/usr/src/lib/libumem/Makefile.com index 0e726c5646..9c10ded585 100644 --- a/usr/src/lib/libumem/Makefile.com +++ b/usr/src/lib/libumem/Makefile.com @@ -22,6 +22,8 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright (c) 2012, Joyent, Inc. All rights reserved. +# # # The build process for libumem is sightly different from that used by other @@ -65,10 +67,12 @@ SRCS_standalone = $(OBJECTS_standalone:%.o=../common/%.c) # Architecture-dependent files common to both versions of libumem OBJECTS_common_isadep = \ - asm_subr.o + asm_subr.o \ + umem_genasm.o SRCS_common_isadep = \ - $(ISASRCDIR)/asm_subr.s + $(ISASRCDIR)/asm_subr.s \ + $(ISASRCDIR)/umem_genasm.c # Architecture-independent files common to both versions of libumem OBJECTS_common_common = \ @@ -115,6 +119,8 @@ MAPFILE_SUPPLEMENTAL = $(MAPFILE_SUPPLEMENTAL_$(CURTYPE)) LDLIBS += -lc +DYNFLAGS += -Wl,-Plibumem_trampoline.so.1 + LDFLAGS_standalone = $(ZNOVERSION) $(BREDUCE) -M../common/mapfile-vers \ -M$(MAPFILE_SUPPLEMENTAL) -dy -r LDFLAGS = $(LDFLAGS_$(CURTYPE)) diff --git a/usr/src/lib/libumem/amd64/umem_genasm.c b/usr/src/lib/libumem/amd64/umem_genasm.c new file mode 100644 index 0000000000..7dad57505b --- /dev/null +++ b/usr/src/lib/libumem/amd64/umem_genasm.c @@ -0,0 +1,609 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + */ + +/* + * Don't Panic! If you find the blocks of assembly that follow confusing and + * you're questioning why they exist, please go read section 8 of the umem.c big + * theory statement. Next familiarize yourself with the malloc and free + * implementations in libumem's malloc.c. + * + * What follows is the amd64 implementation of the thread caching automatic + * assembly generation. The amd64 calling conventions are documented in the + * 64-bit System V ABI. For our purposes what matters is that our first argument + * will come in rdi. Our functions have to preserve rbp, rbx, and r12->r15. We + * are free to do whatever we want with rax, rcx, rdx, rsi, rdi, and r8->r11. + * + * For both our implementation of malloc and free we only use the registers we + * don't have to preserve. + * + * Malloc register usage: + * o. rdi: Original size to malloc. This never changes and is preserved. + * o. rsi: Adjusted malloc size for malloc_data_tag(s). + * o. rcx: Pointer to the tmem_t in the ulwp_t. + * o. rdx: Pointer to the tmem_t array of roots + * o. r8: Size of the cache + * o. r9: Scratch register + * + * Free register usage: + * o. rdi: Original buffer to free. This never changes and is preserved. + * o. rax: The actual buffer, adjusted for the hidden malloc_data_t(s). + * o. rcx: Pointer to the tmem_t in the ulwp_t. + * o. rdx: Pointer to the tmem_t array of roots + * o. r8: Size of the cache + * o. r9: Scratch register + * + * Once we determine what cache we are using, we increment %rdx to the + * appropriate offset and set %r8 with the size of the cache. This means that + * when we break out to the normal buffer allocation point %rdx contains the + * head of the linked list and %r8 is the amount that we have to adjust the + * thread's cached amount by. + * + * Each block of assembly has psuedocode that describes its purpose. + */ + +#include <atomic.h> +#include <inttypes.h> +#include <sys/types.h> +#include <strings.h> +#include <umem_impl.h> +#include "umem_base.h" + +int umem_genasm_supported = 1; +uintptr_t umem_genasm_mptr; +uintptr_t umem_genasm_msize; +uintptr_t umem_genasm_fptr; +uintptr_t umem_genasm_fsize; +static uintptr_t umem_genasm_omptr; +static uintptr_t umem_genasm_ofptr; + +#define UMEM_GENASM_MAX64 (UINT32_MAX / sizeof (uintptr_t)) +#define PTC_JMPADDR(dest, src) (dest - (src + 4)) +#define PTC_ROOT_SIZE sizeof (uintptr_t) +#define MULTINOP 0x0000441f0f + +/* + * void *ptcmalloc(size_t orig_size); + * + * size_t size = orig_size + 8; + * if (size > UMEM_SECOND_ALIGN) + * size += 8; + * + * if (size < orig_size) + * goto tomalloc; ! This is overflow + * + * if (size > cache_max) + * goto tomalloc + * + * tmem_t *t = (uintptr_t)curthread() + umem_thr_offset; + * void **roots = t->tm_roots; + */ +#define PTC_MALINIT_JOUT 0x13 +#define PTC_MALINIT_MCS 0x1a +#define PTC_MALINIT_JOV 0x20 +#define PTC_MALINIT_SOFF 0x30 +static const uint8_t malinit[] = { + 0x48, 0x8d, 0x77, 0x08, /* leaq 0x8(%rdi),%rsi */ + 0x48, 0x83, 0xfe, 0x10, /* cmpq $0x10, %rsi */ + 0x76, 0x04, /* jbe +0x4 */ + 0x48, 0x8d, 0x77, 0x10, /* leaq 0x10(%rdi),%rsi */ + 0x48, 0x39, 0xfe, /* cmpq %rdi,%rsi */ + 0x0f, 0x82, 0x00, 0x00, 0x00, 0x00, /* jb +errout */ + 0x48, 0x81, 0xfe, + 0x00, 0x00, 0x00, 0x00, /* cmpq sizeof ($CACHE), %rsi */ + 0x0f, 0x87, 0x00, 0x00, 0x00, 0x00, /* ja +errout */ + 0x64, 0x48, 0x8b, 0x0c, 0x25, + 0x00, 0x00, 0x00, 0x00, /* movq %fs:0x0,%rcx */ + 0x48, 0x81, 0xc1, + 0x00, 0x00, 0x00, 0x00, /* addq $SOFF, %rcx */ + 0x48, 0x8d, 0x51, 0x08, /* leaq 0x8(%rcx),%rdx */ +}; + +/* + * void ptcfree(void *buf); + * + * if (buf == NULL) + * return; + * + * malloc_data_t *tag = buf; + * tag--; + * int size = tag->malloc_size; + * int tagval = UMEM_MALLOC_DECODE(tag->malloc_tag, size); + * if (tagval == MALLOC_SECOND_MAGIC) { + * tag--; + * } else if (tagval != MALLOC_MAGIC) { + * goto tofree; + * } + * + * if (size > cache_max) + * goto tofree; + * + * tmem_t *t = (uintptr_t)curthread() + umem_thr_offset; + * void **roots = t->tm_roots; + */ +#define PTC_FRINI_JDONE 0x05 +#define PTC_FRINI_JFREE 0x25 +#define PTC_FRINI_MCS 0x30 +#define PTC_FRINI_JOV 0x36 +#define PTC_FRINI_SOFF 0x46 +static const uint8_t freeinit[] = { + 0x48, 0x85, 0xff, /* testq %rdi,%rdi */ + 0x0f, 0x84, 0x00, 0x00, 0x00, 0x00, /* jmp $JDONE (done) */ + 0x8b, 0x77, 0xf8, /* movl -0x8(%rdi),%esi */ + 0x8b, 0x47, 0xfc, /* movl -0x4(%rdi),%eax */ + 0x01, 0xf0, /* addl %esi,%eax */ + 0x3d, 0x00, 0x70, 0xba, 0x16, /* cmpl $MALLOC_2_MAGIC, %eax */ + 0x75, 0x06, /* jne +0x6 (checkover) */ + 0x48, 0x8d, 0x47, 0xf0, /* leaq -0x10(%rdi),%eax */ + 0xeb, 0x0f, /* jmp +0xf (freebuf) */ + 0x3d, 0x00, 0xc0, 0x10, 0x3a, /* cmpl $MALLOC_MAGIC, %eax */ + 0x0f, 0x85, 0x00, 0x00, 0x00, 0x00, /* jmp +JFREE (goto torfree) */ + 0x48, 0x8d, 0x47, 0xf8, /* leaq -0x8(%rdi),%rax */ + 0x48, 0x81, 0xfe, + 0x00, 0x00, 0x00, 0x00, /* cmpq sizeof ($CACHE), %rsi */ + 0x0f, 0x87, 0x00, 0x00, 0x00, 0x00, /* ja +errout */ + 0x64, 0x48, 0x8b, 0x0c, 0x25, + 0x00, 0x00, 0x00, 0x00, /* movq %fs:0x0,%rcx */ + 0x48, 0x81, 0xc1, + 0x00, 0x00, 0x00, 0x00, /* addq $SOFF, %rcx */ + 0x48, 0x8d, 0x51, 0x08, /* leaq 0x8(%rcx),%rdx */ +}; + +/* + * if (size <= $CACHE_SIZE) { + * csize = $CACHE_SIZE; + * } else ... ! goto next cache + */ +#define PTC_INICACHE_CMP 0x03 +#define PTC_INICACHE_SIZE 0x0c +#define PTC_INICACHE_JMP 0x11 +static const uint8_t inicache[] = { + 0x48, 0x81, 0xfe, + 0x00, 0x00, 0x00, 0x00, /* cmpq sizeof ($CACHE), %rsi */ + 0x77, 0x0c, /* ja +0xc (next cache) */ + 0x49, 0xc7, 0xc0, + 0x00, 0x00, 0x00, 0x00, /* movq sizeof ($CACHE), %r8 */ + 0xe9, 0x00, 0x00, 0x00, 0x00, /* jmp $JMP (allocbuf) */ +}; + +/* + * if (size <= $CACHE_SIZE) { + * csize = $CACHE_SIZE; + * roots += $CACHE_NUM; + * } else ... ! goto next cache + */ +#define PTC_GENCACHE_CMP 0x03 +#define PTC_GENCACHE_SIZE 0x0c +#define PTC_GENCACHE_NUM 0x13 +#define PTC_GENCACHE_JMP 0x18 +static const uint8_t gencache[] = { + 0x48, 0x81, 0xfe, + 0x00, 0x00, 0x00, 0x00, /* cmpq sizeof ($CACHE), %rsi */ + 0x77, 0x14, /* ja +0xc (next cache) */ + 0x49, 0xc7, 0xc0, + 0x00, 0x00, 0x00, 0x00, /* movq sizeof ($CACHE), %r8 */ + 0x48, 0x81, 0xc2, + 0x00, 0x00, 0x00, 0x00, /* addq $8*ii, %rdx */ + 0xe9, 0x00, 0x00, 0x00, 0x00 /* jmp +$JMP (allocbuf ) */ +}; + +/* + * else if (size <= $CACHE_SIZE) { + * csize = $CACHE_SIZE; + * roots += $CACHE_NUM; + * } else { + * goto tofunc; ! goto tomalloc if ptcmalloc. + * } ! goto tofree if ptcfree. + */ +#define PTC_FINCACHE_CMP 0x03 +#define PTC_FINCACHE_JMP 0x08 +#define PTC_FINCACHE_SIZE 0x0c +#define PTC_FINCACHE_NUM 0x13 +static const uint8_t fincache[] = { + 0x48, 0x81, 0xfe, + 0x00, 0x00, 0x00, 0x00, /* cmpq sizeof ($CACHE), %rsi */ + 0x77, 0x00, /* ja +JMP (to real malloc) */ + 0x49, 0xc7, 0xc0, + 0x00, 0x00, 0x00, 0x00, /* movq sizeof ($CACHE), %r8 */ + 0x48, 0x81, 0xc2, + 0x00, 0x00, 0x00, 0x00, /* addq $8*ii, %rdx */ + +}; + +/* + * if (*root == NULL) + * goto tomalloc; + * + * malloc_data_t *ret = *root; + * *root = *(void **)ret; + * t->tm_size += csize; + * ret->malloc_size = size; + * + * if (size > UMEM_SECOND_ALIGN) { + * ret->malloc_data = UMEM_MALLOC_ENCODE(MALLOC_SECOND_MAGIC, size); + * ret += 2; + * } else { + * ret->malloc_data = UMEM_MALLOC_ENCODE(MALLOC_SECOND_MAGIC, size); + * ret += 1; + * } + * + * return ((void *)ret); + * tomalloc: + * return (malloc(orig_size)); + */ +#define PTC_MALFINI_ALLABEL 0x00 +#define PTC_MALFINI_JMLABEL 0x40 +#define PTC_MALFINI_JMADDR 0x41 +static const uint8_t malfini[] = { + 0x48, 0x8b, 0x02, /* movl (%rdx),%rax */ + 0x48, 0x85, 0xc0, /* testq %rax,%rax */ + 0x74, 0x38, /* je +0x38 (errout) */ + 0x4c, 0x8b, 0x08, /* movq (%rax),%r9 */ + 0x4c, 0x89, 0x0a, /* movq %r9,(%rdx) */ + 0x4c, 0x29, 0x01, /* subq %rsi,(%rcx) */ + 0x48, 0x83, 0xfe, 0x10, /* cmpq $0x10,%rsi */ + 0x76, 0x15, /* jbe +0x15 */ + 0x41, 0xb9, 0x00, 0x70, 0xba, 0x16, /* movl $MALLOC_MAGIC_2, %r9d */ + 0x89, 0x70, 0x08, /* movl %r9d,0x8(%rax) */ + 0x41, 0x29, 0xf1, /* subl %esi, %r9d */ + 0x44, 0x89, 0x48, 0x0c, /* movl %r9d, 0xc(%rax) */ + 0x48, 0x83, 0xc0, 0x10, /* addq $0x10, %rax */ + 0xc3, /* ret */ + 0x41, 0xb9, 0x00, 0xc0, 0x10, 0x3a, /* movl %MALLOC_MAGIC, %r9d */ + 0x89, 0x30, /* movl %esi,(%rax) */ + 0x41, 0x29, 0xf1, /* subl %esi,%r9d */ + 0x44, 0x89, 0x48, 0x04, /* movl %r9d,0x4(%rax) */ + 0x48, 0x83, 0xc0, 0x08, /* addq $0x8,%rax */ + 0xc3, /* ret */ + 0xe9, 0x00, 0x00, 0x00, 0x00 /* jmp $MALLOC */ +}; + +/* + * if (t->tm_size + csize > umem_ptc_size) + * goto tofree; + * + * t->tm_size += csize + * *(void **)tag = *root; + * *root = tag; + * return; + * tofree: + * free(buf); + * return; + */ +#define PTC_FRFINI_RBUFLABEL 0x00 +#define PTC_FRFINI_CACHEMAX 0x09 +#define PTC_FRFINI_DONELABEL 0x1b +#define PTC_FRFINI_JFLABEL 0x1c +#define PTC_FRFINI_JFADDR 0x1d +static const uint8_t freefini[] = { + 0x4c, 0x8b, 0x09, /* movq (%rcx),%r9 */ + 0x4d, 0x01, 0xc1, /* addq %r8, %r9 */ + 0x49, 0x81, 0xf9, + 0x00, 0x00, 0x00, 0x00, /* cmpl $THR_CACHE_MAX, %r9 */ + 0x77, 0x0d, /* jae +0xd (torfree) */ + 0x4c, 0x01, 0x01, /* addq %r8,(%rcx) */ + 0x4c, 0x8b, 0x0a, /* movq (%rdx),%r9 */ + 0x4c, 0x89, 0x08, /* movq %r9,(%rax) */ + 0x48, 0x89, 0x02, /* movq %rax,(%rdx) */ + 0xc3, /* ret */ + 0xe9, 0x00, 0x00, 0x00, 0x00 /* jmp free */ +}; + +/* + * Construct the initial part of malloc. off contains the offset from curthread + * to the root of the tmem structure. ep is the address of the label to error + * and jump to free. csize is the size of the largest umem_cache in ptcumem. + */ +static int +genasm_malinit(uint8_t *bp, uint32_t off, uint32_t ep, uint32_t csize) +{ + uint32_t addr; + + bcopy(malinit, bp, sizeof (malinit)); + addr = PTC_JMPADDR(ep, PTC_MALINIT_JOUT); + bcopy(&addr, bp + PTC_MALINIT_JOUT, sizeof (addr)); + bcopy(&csize, bp + PTC_MALINIT_MCS, sizeof (csize)); + addr = PTC_JMPADDR(ep, PTC_MALINIT_JOV); + bcopy(&addr, bp + PTC_MALINIT_JOV, sizeof (addr)); + bcopy(&off, bp + PTC_MALINIT_SOFF, sizeof (off)); + + return (sizeof (malinit)); +} + +static int +genasm_frinit(uint8_t *bp, uint32_t off, uint32_t dp, uint32_t ep, uint32_t mcs) +{ + uint32_t addr; + + bcopy(freeinit, bp, sizeof (freeinit)); + addr = PTC_JMPADDR(dp, PTC_FRINI_JDONE); + bcopy(&addr, bp + PTC_FRINI_JDONE, sizeof (addr)); + addr = PTC_JMPADDR(ep, PTC_FRINI_JFREE); + bcopy(&addr, bp + PTC_FRINI_JFREE, sizeof (addr)); + bcopy(&mcs, bp + PTC_FRINI_MCS, sizeof (mcs)); + addr = PTC_JMPADDR(ep, PTC_FRINI_JOV); + bcopy(&addr, bp + PTC_FRINI_JOV, sizeof (addr)); + bcopy(&off, bp + PTC_FRINI_SOFF, sizeof (off)); + return (sizeof (freeinit)); +} + + +/* + * Create the initial cache entry of the specified size. The value of ap tells + * us what the address of the label to try and allocate a buffer. This value is + * an offset from the current base to that value. + */ +static int +genasm_firstcache(uint8_t *bp, uint32_t csize, uint32_t ap) +{ + uint32_t addr; + + bcopy(inicache, bp, sizeof (inicache)); + bcopy(&csize, bp + PTC_INICACHE_CMP, sizeof (csize)); + bcopy(&csize, bp + PTC_INICACHE_SIZE, sizeof (csize)); + addr = PTC_JMPADDR(ap, PTC_INICACHE_JMP); + ASSERT(addr != 0); + bcopy(&addr, bp + PTC_INICACHE_JMP, sizeof (addr)); + + return (sizeof (inicache)); +} + +static int +genasm_gencache(uint8_t *bp, int num, uint32_t csize, uint32_t ap) +{ + uint32_t addr; + uint32_t coff; + + ASSERT(UINT32_MAX / PTC_ROOT_SIZE > num); + ASSERT(num != 0); + bcopy(gencache, bp, sizeof (gencache)); + bcopy(&csize, bp + PTC_GENCACHE_CMP, sizeof (csize)); + bcopy(&csize, bp + PTC_GENCACHE_SIZE, sizeof (csize)); + coff = num * PTC_ROOT_SIZE; + bcopy(&coff, bp + PTC_GENCACHE_NUM, sizeof (coff)); + addr = PTC_JMPADDR(ap, PTC_GENCACHE_JMP); + bcopy(&addr, bp + PTC_GENCACHE_JMP, sizeof (addr)); + + return (sizeof (gencache)); +} + +static int +genasm_lastcache(uint8_t *bp, int num, uint32_t csize, uint32_t ep) +{ + uint8_t eap; + uint32_t coff; + + ASSERT(ep <= 0xff && ep > 7); + ASSERT(UINT32_MAX / PTC_ROOT_SIZE > num); + bcopy(fincache, bp, sizeof (fincache)); + bcopy(&csize, bp + PTC_FINCACHE_CMP, sizeof (csize)); + bcopy(&csize, bp + PTC_FINCACHE_SIZE, sizeof (csize)); + coff = num * PTC_ROOT_SIZE; + bcopy(&coff, bp + PTC_FINCACHE_NUM, sizeof (coff)); + eap = ep - PTC_FINCACHE_JMP - 1; + bcopy(&eap, bp + PTC_FINCACHE_JMP, sizeof (eap)); + + return (sizeof (fincache)); +} + +static int +genasm_malfini(uint8_t *bp, uintptr_t mptr) +{ + uint32_t addr; + + bcopy(malfini, bp, sizeof (malfini)); + addr = PTC_JMPADDR(mptr, ((uintptr_t)bp + PTC_MALFINI_JMADDR)); + bcopy(&addr, bp + PTC_MALFINI_JMADDR, sizeof (addr)); + + return (sizeof (malfini)); +} + +static int +genasm_frfini(uint8_t *bp, uint32_t maxthr, uintptr_t fptr) +{ + uint32_t addr; + + bcopy(freefini, bp, sizeof (freefini)); + bcopy(&maxthr, bp + PTC_FRFINI_CACHEMAX, sizeof (maxthr)); + addr = PTC_JMPADDR(fptr, ((uintptr_t)bp + PTC_FRFINI_JFADDR)); + bcopy(&addr, bp + PTC_FRFINI_JFADDR, sizeof (addr)); + + return (sizeof (freefini)); +} + +/* + * The malloc inline assembly is constructed as follows: + * + * o Malloc prologue assembly + * o Generic first-cache check + * o n Generic cache checks (where n = _tmem_get_entries() - 2) + * o Generic last-cache check + * o Malloc epilogue assembly + * + * Generally there are at least three caches. When there is only one cache we + * only use the generic last-cache. In the case where there are two caches, we + * just leave out the middle ones. + */ +static int +genasm_malloc(void *base, size_t len, int nents, int *umem_alloc_sizes) +{ + int ii, off; + uint8_t *bp; + size_t total; + uint32_t allocoff, erroff; + + total = sizeof (malinit) + sizeof (malfini) + sizeof (fincache); + + if (nents >= 2) + total += sizeof (inicache) + sizeof (gencache) * (nents - 2); + + if (total > len) + return (1); + + erroff = total - sizeof (malfini) + PTC_MALFINI_JMLABEL; + allocoff = total - sizeof (malfini) + PTC_MALFINI_ALLABEL; + + bp = base; + + off = genasm_malinit(bp, umem_tmem_off, erroff, + umem_alloc_sizes[nents-1]); + bp += off; + allocoff -= off; + erroff -= off; + + if (nents > 1) { + off = genasm_firstcache(bp, umem_alloc_sizes[0], allocoff); + bp += off; + allocoff -= off; + erroff -= off; + } + + for (ii = 1; ii < nents - 1; ii++) { + off = genasm_gencache(bp, ii, umem_alloc_sizes[ii], allocoff); + bp += off; + allocoff -= off; + erroff -= off; + } + + bp += genasm_lastcache(bp, nents - 1, umem_alloc_sizes[nents - 1], + erroff); + bp += genasm_malfini(bp, umem_genasm_omptr); + ASSERT(((uintptr_t)bp - total) == (uintptr_t)base); + + return (0); +} + +static int +genasm_free(void *base, size_t len, int nents, int *umem_alloc_sizes) +{ + uint8_t *bp; + int ii, off; + size_t total; + uint32_t rbufoff, retoff, erroff; + + /* Assume that nents has already been audited for us */ + total = sizeof (freeinit) + sizeof (freefini) + sizeof (fincache); + if (nents >= 2) + total += sizeof (inicache) + sizeof (gencache) * (nents - 2); + + if (total > len) + return (1); + + erroff = total - (sizeof (freefini) - PTC_FRFINI_JFLABEL); + rbufoff = total - (sizeof (freefini) - PTC_FRFINI_RBUFLABEL); + retoff = total - (sizeof (freefini) - PTC_FRFINI_DONELABEL); + + bp = base; + + off = genasm_frinit(bp, umem_tmem_off, retoff, erroff, + umem_alloc_sizes[nents - 1]); + bp += off; + erroff -= off; + rbufoff -= off; + + if (nents > 1) { + off = genasm_firstcache(bp, umem_alloc_sizes[0], rbufoff); + bp += off; + erroff -= off; + rbufoff -= off; + } + + for (ii = 1; ii < nents - 1; ii++) { + off = genasm_gencache(bp, ii, umem_alloc_sizes[ii], rbufoff); + bp += off; + rbufoff -= off; + erroff -= off; + } + + bp += genasm_lastcache(bp, nents - 1, umem_alloc_sizes[nents - 1], + erroff); + bp += genasm_frfini(bp, umem_ptc_size, umem_genasm_ofptr); + ASSERT(((uintptr_t)bp - total) == (uintptr_t)base); + + return (0); +} + +/*ARGSUSED*/ +int +umem_genasm(int *cp, umem_cache_t **caches, int nc) +{ + int nents, i; + uint8_t *mptr; + uint8_t *fptr; + uint32_t *ptr; + uint64_t v, *vptr; + + mptr = (void *)((uintptr_t)&umem_genasm_mptr + 5); + fptr = (void *)((uintptr_t)&umem_genasm_fptr + 5); + if (umem_genasm_mptr == 0 || umem_genasm_msize == 0 || + umem_genasm_fptr == 0 || umem_genasm_fsize == 0) + return (1); + + /* + * The total number of caches that we can service is the minimum of: + * o the amount supported by libc + * o the total number of umem caches + * o we use a single byte addl, so its MAX_UINT32 / sizeof (uintptr_t). + * For 64-bit, this is MAX_UINT32 >> 3, a lot. + */ + nents = _tmem_get_nentries(); + + if (UMEM_GENASM_MAX64 < nents) + nents = UMEM_GENASM_MAX64; + + if (nc < nents) + nents = nc; + + /* Based on our constraints, this is not an error */ + if (nents == 0 || umem_ptc_size == 0) + return (0); + + /* Grab the original malloc and free locations */ + ptr = (void *)(mptr - 4); + umem_genasm_omptr = *ptr + (uintptr_t)mptr; + ptr = (void *)(fptr - 4); + umem_genasm_ofptr = *ptr + (uintptr_t)fptr; + + /* Take into account the jump */ + if (genasm_malloc(mptr, umem_genasm_fsize - 5, nents, cp) != 0) + return (1); + + if (genasm_free(fptr, umem_genasm_fsize - 5, nents, cp) != 0) + return (1); + + /* nop out the jump with a multibyte jump */ + vptr = (void *)&umem_genasm_mptr; + v = MULTINOP; + v |= *vptr & (0xffffffULL << 40); + (void) atomic_swap_64(vptr, v); + vptr = (void *)&umem_genasm_fptr; + v = MULTINOP; + v |= *vptr & (0xffffffULL << 40); + (void) atomic_swap_64(vptr, v); + + + for (i = 0; i < nents; i++) + caches[i]->cache_flags |= UMF_PTC; + + return (0); +} diff --git a/usr/src/lib/libumem/common/envvar.c b/usr/src/lib/libumem/common/envvar.c index fc3d490a01..2fdf7824c3 100644 --- a/usr/src/lib/libumem/common/envvar.c +++ b/usr/src/lib/libumem/common/envvar.c @@ -25,6 +25,10 @@ * Copyright 2012 Joyent, Inc. All rights reserved. */ +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + */ + #include <ctype.h> #include <errno.h> #include <limits.h> @@ -151,7 +155,10 @@ static umem_env_item_t umem_options_items[] = { NULL, 0, NULL, &vmem_sbrk_pagesize }, #endif - + { "perthread_cache", "Evolving", ITEM_SIZE, + "Size (in bytes) of per-thread allocation cache", + NULL, 0, NULL, &umem_ptc_size + }, { NULL, "-- end of UMEM_OPTIONS --", ITEM_INVALID } }; diff --git a/usr/src/lib/libumem/common/mapfile-vers b/usr/src/lib/libumem/common/mapfile-vers index 102bd989f7..6a05f0cfaa 100644 --- a/usr/src/lib/libumem/common/mapfile-vers +++ b/usr/src/lib/libumem/common/mapfile-vers @@ -20,6 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, Joyent, Inc. All rights reserved. # # @@ -72,6 +73,10 @@ SYMBOL_VERSION SUNWprivate_1.1 { vmem_walk; vmem_xalloc; vmem_xfree; + umem_genasm_mptr; + umem_genasm_fptr; + umem_genasm_fsize; + umem_genasm_msize; local: *; }; diff --git a/usr/src/lib/libumem/common/stub_stand.c b/usr/src/lib/libumem/common/stub_stand.c index 54635558c3..1a90c6be75 100644 --- a/usr/src/lib/libumem/common/stub_stand.c +++ b/usr/src/lib/libumem/common/stub_stand.c @@ -23,6 +23,9 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ /* * Stubs for the standalone to reduce the dependence on external libraries @@ -125,3 +128,29 @@ issetugid(void) { return (1); } + +int +_tmem_get_nentries(void) +{ + return (0); +} + +uintptr_t +_tmem_get_base(void) +{ + return (0); +} + +/*ARGSUSED*/ +void +_tmem_set_cleanup(void (*f)(int, void *)) +{ +} + +uint64_t +atomic_swap_64(volatile uint64_t *t, uint64_t v) +{ + uint64_t old = *t; + *t = v; + return (old); +} diff --git a/usr/src/lib/libumem/common/umem.c b/usr/src/lib/libumem/common/umem.c index a3eb0b8e6c..e22106e979 100644 --- a/usr/src/lib/libumem/common/umem.c +++ b/usr/src/lib/libumem/common/umem.c @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + */ /* * based on usr/src/uts/common/os/kmem.c r1.64 from 2001/12/18 @@ -44,7 +46,7 @@ * * 1. Overview * ----------- - * umem is very close to kmem in implementation. There are four major + * umem is very close to kmem in implementation. There are seven major * areas of divergence: * * * Initialization @@ -57,6 +59,10 @@ * * * lock ordering * + * * changing UMEM_MAXBUF + * + * * Per-thread caching for malloc/free + * * 2. Initialization * ----------------- * kmem is initialized early on in boot, and knows that no one will call @@ -355,6 +361,248 @@ * umem_log_header_t's: * lh_cpu[*].clh_lock * lh_lock + * + * 7. Changing UMEM_MAXBUF + * ----------------------- + * + * When changing UMEM_MAXBUF extra care has to be taken. It is not sufficient to + * simply increase this number. First, one must update the umem_alloc_table to + * have the appropriate number of entires based upon the new size. If this is + * not done, this will lead to libumem blowing an assertion. + * + * The second place to update, which is not required, is the umem_alloc_sizes. + * These determine the default cache sizes that we're going to support. + * + * 8. Per-thread caching for malloc/free + * ------------------------------------- + * + * "Time is an illusion. Lunchtime doubly so." -- Douglas Adams + * + * Time may be an illusion, but CPU cycles aren't. While libumem is designed + * to be a highly scalable allocator, that scalability comes with a fixed cycle + * penalty even in the absence of contention: libumem must acquire (and release + * a per-CPU lock for each allocation. When contention is low and malloc(3C) + * frequency is high, this overhead can dominate execution time. To alleviate + * this, we allow for per-thread caching, a lock-free means of caching recent + * deallocations on a per-thread basis for use in satisfying subsequent calls + * + * In addition to improving performance, we also want to: + * * Minimize fragmentation + * * Not add additional memory overhead (no larger malloc tags) + * + * In the ulwp_t of each thread there is a private data structure called a + * umem_t that looks like: + * + * typedef struct { + * size_t tm_size; + * void *tm_roots[NTMEMBASE]; (Currently 16) + * } tmem_t; + * + * Each of the roots is treated as the head of a linked list. Each entry in the + * list can be thought of as a void ** which points to the next entry, until one + * of them points to NULL. If the head points to NULL, the list is empty. + * + * Each head corresponds to a umem_cache. Currently there is a linear mapping + * where the first root corresponds to the first cache, second root to the + * second cache, etc. This works because every allocation that malloc makes to + * umem_alloc that can be satisified by a umem_cache will actually return a + * number of bytes equal to the size of that cache. Because of this property and + * a one to one mapping between caches and roots we can guarantee that every + * entry in a given root's list will be able to satisfy the same requests as the + * corresponding cache. + * + * The maximum amount of memory that can be cached in each thread is determined + * by the perthread_cache UMEM_OPTION. It corresponds to the umem_ptc_size + * value. The default value for this is currently 1 MB. Once umem_init() has + * finished this cannot be directly tuned without directly modifying the + * instruction text. If, upon calling free(3C), the amount cached would exceed + * this maximum, we instead actually return the buffer to the umem_cache instead + * of holding onto it in the thread. + * + * When a thread calls malloc(3C) it first determines which umem_cache it + * would be serviced by. If the allocation is not covered by ptcumem it goes to + * the normal malloc instead. Next, it checks if the tmem_root's list is empty + * or not. If it is empty, we instead go and allocate the memory from + * umem_alloc. If it is not empty, we remove the head of the list, set the + * appropriate malloc tags, and return that buffer. + * + * When a thread calls free(3C) it first looks at the malloc tag and if it is + * invalid or the allocation exceeds the largest cache in ptcumem and sends it + * off to the original free() to handle and clean up appropriately. Next, it + * checks if the allocation size is covered by one of the per-thread roots and + * if it isn't, it passes it off to the original free() to be released. Finally, + * before it inserts this buffer as the head, it checks if adding this buffer + * would put the thread over its maximum cache size. If it would, it frees the + * buffer back to the umem_cache. Otherwise it increments the threads total + * cached amount and makes the buffer the new head of the appropriate tm_root. + * + * When a thread exits, all of the buffers that it has in its per-thread cache + * will be passed to umem_free() and returned to the appropriate umem_cache. + * + * 8.1 Handling addition and removal of umem_caches + * ------------------------------------------------ + * + * The set of umem_caches that are used to back calls to umem_alloc() and + * ultimately malloc() are determined at program execution time. The default set + * of caches is defined below in umem_alloc_sizes[]. Various umem_options exist + * that modify the set of caches: size_add, size_clear, and size_remove. Because + * the set of caches can only be determined once umem_init() has been called and + * we have the additional goals of minimizing additional fragmentation and + * metadata space overhead in the malloc tags, this forces our hand to go down a + * slightly different path: the one tread by fasttrap and trapstat. + * + * During umem_init we're going to dynamically construct a new version of + * malloc(3C) and free(3C) that utilizes the known cache sizes and then ensure + * that ptcmalloc and ptcfree replace malloc and free as entries in the plt. If + * ptcmalloc and ptcfree cannot handle a request, they simply jump to the + * original libumem implementations. + * + * After creating all of the umem_caches, but before making them visible, + * umem_cache_init checks that umem_genasm_supported is non-zero. This value is + * set by each architecture in $ARCH/umem_genasm.c to indicate whether or not + * they support this. If the value is zero, then this process is skipped. + * Similarly, if the cache size has been tuned to zero by UMEM_OPTIONS, then + * this is also skipped. + * + * In umem_genasm.c, each architecture's implementation implements a single + * function called umem_genasm() that is responsible for generating the + * appropriate versions of ptcmalloc() and ptcfree(), placing them in the + * appropriate memory location, and finally doing the switch from malloc() and + * free() to ptcmalloc() and ptcfree(). Once the change has been made, there is + * no way to switch back, short of restarting the program or modifying program + * text with mdb. + * + * 8.2 Modifying the Procedure Linkage Table (PLT) + * ----------------------------------------------- + * + * The last piece of this puzzle is how we actually jam ptcmalloc() into the + * PLT. The dyanmic linker has support for global and local audit libraries. + * For the full explanation of audit libraries consult the Linkers and Libraries + * guide or the linker source. A local auditer can attach to a single library + * and interpose on all of the relocations that come in from and leave to that + * same library. To facilitate our work, we have created a local audit library + * for libumem that is called libumem_trampoline and is located in + * lib/libumem_trampoline/. + * + * When any resolution is done to malloc(), the audit library allows us to + * replace the address with an address that it specifies. There are two 4k + * sections in the libumem_trampoline's bss which we use as the stomping grounds + * for ptcmalloc and ptcfree. When the audit library audits the malloc and free + * functions from libumem, it encodes their address and sets its buffers to + * contain a simple trampoline which consists of a jmp instruction and a four + * byte offset to the original malloc and free. libumem_trampoline's mapfile + * explicitly makes its bss rwx instead of rw to support this. + * + * When umem_genasm() is called, it uses a similar mechanism to get the address + * and size of the trampoline libraries malloc (mbuf) and free (fbuf) buffers. + * After validating that the size will be able to contain all of the + * instructions, it starts laying out ptcmalloc and ptcfree at mbuf[4] and + * fbuf[4]. Once both have been successfully generated, umem_genasm() stores a + * single five byte nop over the original jump. + * + * 8.3 umem_genasm() + * ----------------- + * + * umem_genasm() is currently implemented for i386 and amd64. This section + * describes the theory behind the construction. For specific byte code to + * assembly instructions and niceish C and asm versions of ptcmalloc and + * ptcfree, see the individual umem_genasm.c files. The layout consists of the + * following sections: + * + * o. function-specfic prologue + * o. function-generic cache-selecting elements + * o. function-specific epilogue + * + * There are three different generic cache elements that exist: + * + * o. the last or only cache + * o. the intermediary caches if more than two + * o. the first one if more than one cache + * + * The malloc and free prologues and epilogues mimic the necessary portions of + * libumem's malloc and free. This includes things like checking for size + * overflow, setting and verifying the malloc tags. + * + * It is an important constraint that these functions do not make use of the + * call instruction. The only jmp outside of the individual functions is to the + * original libumem malloc and free respectively. Because doing things like + * setting errno or raising an internal umem error on improper malloc tags would + * require using calls into the PLT, whenever we encounter one of those cases we + * just jump to the original malloc and free functions reusing the same stack + * frame. + * + * Each of the above sections, the three caches, and the malloc and free + * prologue and epilogue are implemented as blocks of machine code with the + * corresponding assembly in comments. There are known offsets into each block + * that corresponds to locations of data and addresses that we only know at run + * time. These blocks are copied as necessary and the blanks filled in + * appropriately. + * + * As mentioned in section 8.2, the trampoline library uses specifically named + * variables to communicate the buffers and size to use. These variables are: + * + * o. umem_genasm_mptr: The buffer for ptcmalloc + * o. umem_genasm_msize: The size in bytes of the above buffer + * o. umem_genasm_fptr: The buffer for ptcfree + * o. umem_genasm_fsize: The size in bytes of the above buffer + * + * Finally, to enable the generated assembly we need to remove the previous jump + * to the actual malloc that exists at the start of these buffers. This is a + * five byte region. We could zero out the jump offset to be a jmp +0, but + * using nops can be faster. We specifically use a single five byte nop which is + * faster. The opcode for the five byte nop is 0x 0f 1f 44 00 00. On x86, + * remember integers are little endian, so it will be written the other way + * around. + * + * 8.4 Interface with libc.so + * -------------------------- + * + * The tmem_t structure as described in the beginning of section 8, is part of a + * private interface with libc. There are three functions that exist to cover + * this. They are not documented in man pages or header files. They are in the + * SUNWprivate part of libc's makefile. + * + * o. _tmem_get_base(void) + * + * Returns the offset from the ulwp_t (curthread) to the tmem_t structure. + * This is a constant for all threads and is effectively a way to to do + * ::offsetof ulwp_t ul_tmem without having to know the specifics of the + * structure outside of libc. + * + * o. _tmem_get_nentries(void) + * + * Returns the number of roots that exist in the tmem_t. This is one part + * of the cap on the number of umem_caches that we can back with tmem. + * + * o. _tmem_set_cleanup(void (*)(void *, int)) + * + * This sets a clean up handler that gets called back when a thread exits. + * There is one call per buffer, the void * is a pointer to the buffer on + * the list, the int is the index into the roots array for this buffer. + * + * 8.5 Tuning and disabling per-thread caching + * ------------------------------------------- + * + * There is only one tunable for per-thread caching: the amount of memory each + * thread should be able to cache. This is specified via the perthread_cache + * UMEM_OPTION option. No attempt is made to to sanity check the specified + * value; the limit is simply the maximum value of a size_t. + * + * If the perthread_cache UMEM_OPTION is set to zero, nomagazines was requested, + * or UMEM_DEBUG has been turned on then we will never call into umem_genasm; + * however, the trampoline audit library and jump will still be in place. + * + * 8.6 Observing efficacy of per-thread caching + * -------------------------------------------- + * + * To understand the efficacy of per-thread caching, use the ::umastat dcmd + * to see the percentage of capacity consumed on a per-thread basis, the + * degree to which each umem cache contributes to per-thread cache consumption, + * and the number of buffers in per-thread caches on a per-umem cache basis. + * If more detail is required, the specific buffers in a per-thread cache can + * be iterated over with the umem_ptc_* walkers. (These walkers allow an + * optional ulwp_t to be specified to iterate only over a particular thread's + * cache.) */ #include <umem_impl.h> @@ -420,7 +668,9 @@ static int umem_alloc_sizes[] = { P2ALIGN(8192 / 2, 64), 4544, P2ALIGN(8192 / 1, 64), 9216, 4096 * 3, - UMEM_MAXBUF, /* = 8192 * 2 */ + 8192 * 2, /* = 8192 * 2 */ + 24576, 32768, 40960, 49152, 57344, 65536, 73728, 81920, + 90112, 98304, 106496, 114688, 122880, UMEM_MAXBUF, /* 128k */ /* 24 slots for user expansion */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -461,8 +711,10 @@ size_t umem_lite_minsize = 0; /* minimum buffer size for UMF_LITE */ size_t umem_lite_maxalign = 1024; /* maximum buffer alignment for UMF_LITE */ size_t umem_maxverify; /* maximum bytes to inspect in debug routines */ size_t umem_minfirewall; /* hardware-enforced redzone threshold */ +size_t umem_ptc_size = 1048576; /* size of per-thread cache (in bytes) */ uint_t umem_flags = 0; +uintptr_t umem_tmem_off; mutex_t umem_init_lock; /* locks initialization */ cond_t umem_init_cv; /* initialization CV */ @@ -470,6 +722,8 @@ thread_t umem_init_thr; /* thread initializing */ int umem_init_env_ready; /* environ pre-initted */ int umem_ready = UMEM_READY_STARTUP; +int umem_ptc_enabled; /* per-thread caching enabled */ + static umem_nofail_callback_t *nofail_callback; static mutex_t umem_nofail_exit_lock; static thread_t umem_nofail_exit_thr; @@ -592,6 +846,20 @@ umem_cache_t umem_null_cache = { static umem_cache_t *umem_alloc_table[UMEM_MAXBUF >> UMEM_ALIGN_SHIFT] = { ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, + ALLOC_TABLE_1024, ALLOC_TABLE_1024 }; @@ -2812,6 +3080,24 @@ umem_alloc_sizes_remove(size_t size) umem_alloc_sizes[i] = 0; } +/* + * We've been called back from libc to indicate that thread is terminating and + * that it needs to release the per-thread memory that it has. We get to know + * which entry in the thread's tmem array the allocation came from. Currently + * this refers to first n umem_caches which makes this a pretty simple indexing + * job. + */ +static void +umem_cache_tmem_cleanup(void *buf, int entry) +{ + size_t size; + umem_cache_t *cp; + + size = umem_alloc_sizes[entry]; + cp = umem_alloc_table[(size - 1) >> UMEM_ALIGN_SHIFT]; + _umem_cache_free(cp, buf); +} + static int umem_cache_init(void) { @@ -2927,6 +3213,16 @@ umem_cache_init(void) umem_alloc_caches[i] = cp; } + umem_tmem_off = _tmem_get_base(); + _tmem_set_cleanup(umem_cache_tmem_cleanup); + + if (umem_genasm_supported && !(umem_flags & UMF_DEBUG) && + !(umem_flags & UMF_NOMAGAZINE) && + umem_ptc_size > 0) { + umem_ptc_enabled = umem_genasm(umem_alloc_sizes, + umem_alloc_caches, i) == 0 ? 1 : 0; + } + /* * Initialization cannot fail at this point. Make the caches * visible to umem_alloc() and friends. diff --git a/usr/src/lib/libumem/common/umem_base.h b/usr/src/lib/libumem/common/umem_base.h index e78bebfb58..26e00bc282 100644 --- a/usr/src/lib/libumem/common/umem_base.h +++ b/usr/src/lib/libumem/common/umem_base.h @@ -22,12 +22,13 @@ * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ #ifndef _UMEM_BASE_H #define _UMEM_BASE_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <umem_impl.h> #ifdef __cplusplus @@ -75,6 +76,8 @@ extern volatile uint32_t umem_reaping; #define UMEM_REAP_ADDING 0x00000001 /* umem_reap() is active */ #define UMEM_REAP_ACTIVE 0x00000002 /* update thread is reaping */ +extern uintptr_t umem_tmem_off; + /* * umem.c: tunables */ @@ -97,6 +100,7 @@ extern size_t umem_lite_minsize; extern size_t umem_lite_maxalign; extern size_t umem_maxverify; extern size_t umem_minfirewall; +extern size_t umem_ptc_size; extern uint32_t umem_flags; @@ -139,6 +143,12 @@ extern int umem_create_update_thread(void); void umem_setup_envvars(int); void umem_process_envvars(void); +/* + * umem_genasm.c: private interfaces + */ +extern int umem_genasm_supported; +extern int umem_genasm(int *, umem_cache_t **, int); + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libumem/common/umem_impl.h b/usr/src/lib/libumem/common/umem_impl.h index c6481d9751..f63246e166 100644 --- a/usr/src/lib/libumem/common/umem_impl.h +++ b/usr/src/lib/libumem/common/umem_impl.h @@ -24,11 +24,13 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + */ + #ifndef _UMEM_IMPL_H #define _UMEM_IMPL_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <umem.h> #include <sys/sysmacros.h> @@ -64,6 +66,7 @@ extern "C" { #define UMF_HASH 0x00000200 /* cache has hash table */ #define UMF_RANDOMIZE 0x00000400 /* randomize other umem_flags */ +#define UMF_PTC 0x00000800 /* cache has per-thread caching */ #define UMF_BUFTAG (UMF_DEADBEEF | UMF_REDZONE) #define UMF_TOUCH (UMF_BUFTAG | UMF_LITE | UMF_CONTENTS) @@ -353,7 +356,7 @@ typedef struct umem_cpu { uint32_t cpu_number; } umem_cpu_t; -#define UMEM_MAXBUF 16384 +#define UMEM_MAXBUF 131072 #define UMEM_ALIGN 8 /* min guaranteed alignment */ #define UMEM_ALIGN_SHIFT 3 /* log2(UMEM_ALIGN) */ @@ -396,6 +399,13 @@ extern void umem_startup(caddr_t, size_t, size_t, caddr_t, caddr_t); extern int umem_add(caddr_t, size_t); #endif +/* + * Private interface with libc for tcumem. + */ +extern uintptr_t _tmem_get_base(void); +extern int _tmem_get_nentries(void); +extern void _tmem_set_cleanup(void(*)(void *, int)); + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libumem/i386/umem_genasm.c b/usr/src/lib/libumem/i386/umem_genasm.c new file mode 100644 index 0000000000..0bfa338e2b --- /dev/null +++ b/usr/src/lib/libumem/i386/umem_genasm.c @@ -0,0 +1,603 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + */ + +/* + * Don't Panic! If you find the blocks of assembly that follow confusing and + * you're questioning why they exist, please go read section 8 of the umem.c big + * theory statement. Next familiarize yourself with the malloc and free + * implementations in libumem's malloc.c. + * + * What follows is the i386 implementation of the thread caching automatic + * assembly generation. With i386 a function only has three registers its + * allowed to change without restoring them: eax, ecx, and edx. All others have + * to be preserved. Since the set of registers we have available is so small, we + * have to make use of esi, ebx, and edi and save their original values to the + * stack. + * + * Malloc register usage: + * o. esi: Size of the malloc (passed into us and modified) + * o. edi: Size of the cache + * o. eax: Buffer to return + * o. ebx: Scratch space and temporary values + * o. ecx: Pointer to the tmem_t in the ulwp_t. + * o. edx: Pointer to the tmem_t array of roots + * + * Free register usage: + * o. esi: Size of the malloc (passed into us and modified) + * o. edi: Size of the cache + * o. eax: Buffer to free + * o. ebx: Scratch space and temporary values + * o. ecx: Pointer to the tmem_t in the ulwp_t. + * o. edx: Pointer to the tmem_t array of roots + * + * Once we determine what cache we are using, we increment %edx to the + * appropriate offset and set %edi with the size of the cache. This means that + * when we break out to the normal buffer allocation point %edx contains the + * head of the linked list and %edi is the amount that we have to adjust the + * total amount cached by the thread. + * + * Each block of assembly has psuedocode that describes its purpose. + */ + +#include <inttypes.h> +#include <strings.h> +#include <umem_impl.h> +#include "umem_base.h" + +#include <atomic.h> + +int umem_genasm_supported = 1; +uintptr_t umem_genasm_mptr; +size_t umem_genasm_msize; +uintptr_t umem_genasm_fptr; +size_t umem_genasm_fsize; +static uintptr_t umem_genasm_omptr; +static uintptr_t umem_genasm_ofptr; + +/* + * The maximum number of caches we can support. We use a single byte addl so + * this is 255 (UINT8_MAX) / sizeof (uintptr_t). In this case 63 + */ +#define UMEM_GENASM_MAX32 63 + +#define PTC_JMPADDR(dest, src) (dest - (src + 4)) +#define PTC_ROOT_SIZE sizeof (uintptr_t) +#define MULTINOP 0x0000441f0f + +/* + * void *ptcmalloc(size_t orig_size); + * + * size_t size = orig_size + 8; + * + * if (size < orig_size) + * goto tomalloc; ! This is overflow + * + * if (size > cache_size) + * goto tomalloc; + * + * tmem_t *t = (uintptr_t)curthread() + umem_thr_offset; + * void **roots = t->tm_roots; + */ +#define PTC_MALINIT_JOUT 0x0e +#define PTC_MALINIT_MCS 0x14 +#define PTC_MALINIT_JOV 0x1a +#define PTC_MALINIT_SOFF 0x27 +static const uint8_t malinit[] = { + 0x55, /* pushl %ebp */ + 0x89, 0xe5, /* movl %esp, %ebp */ + 0x57, /* pushl %edi */ + 0x56, /* pushl %esi */ + 0x53, /* pushl %ebx */ + 0x8b, 0x75, 0x08, /* movl 0x8(%ebp), %esi */ + 0x83, 0xc6, 0x08, /* addl $0x8,%esi */ + 0x0f, 0x82, 0x00, 0x00, 0x00, 0x00, /* jc +$JMP (errout) */ + 0x81, 0xfe, 0x00, 0x00, 0x00, 0x00, /* cmpl sizeof ($C0), %esi */ + 0x0f, 0x87, 0x00, 0x00, 0x00, 0x00, /* ja +$JMP (errout) */ + 0x65, 0x8b, 0x0d, 0x00, 0x0, 0x00, 0x00, /* movl %gs:0x0,%ecx */ + 0x81, 0xc1, 0x00, 0x00, 0x00, 0x00, /* addl $OFF, %ecx */ + 0x8d, 0x51, 0x04 /* leal 0x4(%ecx), %edx */ +}; + +/* + * void ptcfree(void *buf); + * + * if (buf == NULL) + * return; + * + * malloc_data_t *tag = buf; + * tag--; + * int size = tag->malloc_size; + * int tagtval = UMEM_MALLOC_DECODE(tag->malloc_tag, size); + * + * if (tagval != MALLOC_MAGIC) + * goto tofree; + * + * if (size > cache_max) + * goto tofree; + * + * tmem_t *t = (uintptr_t)curthread() + umem_thr_offset; + * void **roots = t->tm_roots; + */ +#define PTC_FRINI_JDONE 0x0d +#define PTC_FRINI_JFREE 0x23 +#define PTC_FRINI_MCS 0x29 +#define PTC_FRINI_JOV 0x2f +#define PTC_FRINI_SOFF 0x3c +static const uint8_t freeinit[] = { + 0x55, /* pushl %ebp */ + 0x89, 0xe5, /* movl %esp, %ebp */ + 0x57, /* pushl %edi */ + 0x56, /* pushl %esi */ + 0x53, /* pushl %ebx */ + 0x8b, 0x45, 0x08, /* movl 0x8(%ebp), %eax */ + 0x85, 0xc0, /* testl %eax, %eax */ + 0x0f, 0x84, 0x00, 0x00, 0x00, 0x00, /* je $JDONE (done) */ + 0x83, 0xe8, 0x08, /* subl $0x8,%eax */ + 0x8b, 0x30, /* movl (%eax),%esi */ + 0x8b, 0x50, 0x04, /* movl 0x4(%eax),%edx */ + 0x01, 0xf2, /* addl %esi,%edx */ + 0x81, 0xfa, 0x00, 0xc0, 0x10, 0x3a, /* cmpl MAGIC32, %edx */ + 0x0f, 0x85, 0x00, 0x00, 0x00, 0x00, /* jne +JFREE (goto freebuf) */ + + 0x81, 0xfe, 0x00, 0x00, 0x00, 0x00, /* cmpl sizeof ($C0), %esi */ + 0x0f, 0x87, 0x00, 0x00, 0x00, 0x00, /* ja +$JMP (errout) */ + 0x65, 0x8b, 0x0d, 0x00, 0x0, 0x00, 0x00, /* movl %gs:0x0,%ecx */ + 0x81, 0xc1, 0x00, 0x00, 0x00, 0x00, /* addl $0xOFF, %ecx */ + 0x8d, 0x51, 0x04 /* leal 0x4(%ecx),%edx */ +}; + +/* + * if (size <= $CACHE_SIZE) { + * csize = $CACHE_SIZE; + * } else ... ! goto next cache + */ +#define PTC_INICACHE_CMP 0x02 +#define PTC_INICACHE_SIZE 0x09 +#define PTC_INICACHE_JMP 0x0e +static const uint8_t inicache[] = { + 0x81, 0xfe, 0xff, 0x00, 0x00, 0x00, /* cmpl sizeof ($C0), %esi */ + 0x77, 0x0a, /* ja +0xa */ + 0xbf, 0xff, 0x00, 0x00, 0x00, /* movl sizeof ($C0), %edi */ + 0xe9, 0x00, 0x00, 0x00, 0x00 /* jmp +$JMP (allocbuf) */ +}; + +/* + * if (size <= $CACHE_SIZE) { + * csize = $CACHE_SIZE; + * roots += $CACHE_NUM; + * } else ... ! goto next cache + */ +#define PTC_GENCACHE_CMP 0x02 +#define PTC_GENCACHE_NUM 0x0a +#define PTC_GENCACHE_SIZE 0x0c +#define PTC_GENCACHE_JMP 0x11 +static const uint8_t gencache[] = { + 0x81, 0xfe, 0x00, 0x00, 0x00, 0x00, /* cmpl sizeof ($CACHE), %esi */ + 0x77, 0x0d, /* ja +0xd (next cache) */ + 0x83, 0xc2, 0x00, /* addl $4*$ii, %edx */ + 0xbf, 0x00, 0x00, 0x00, 0x00, /* movl sizeof ($CACHE), %edi */ + 0xe9, 0x00, 0x00, 0x00, 0x00 /* jmp +$JMP (allocbuf) */ +}; + +/* + * else if (size <= $CACHE_SIZE) { + * csize = $CACHE_SIZE; + * roots += $CACHE_NUM; + * } else { + * goto tofunc; ! goto tomalloc if ptcmalloc. + * } ! goto tofree if ptcfree. + */ +#define PTC_FINCACHE_CMP 0x02 +#define PTC_FINCACHE_JMP 0x07 +#define PTC_FINCACHE_NUM 0x0a +#define PTC_FINCACHE_SIZE 0x0c +static const uint8_t fincache[] = { + 0x81, 0xfe, 0xff, 0x00, 0x00, 0x00, /* cmpl sizeof ($CLAST), %esi */ + 0x77, 0x00, /* ja +$JMP (to errout) */ + 0x83, 0xc2, 0x00, /* addl $4*($NCACHES-1), %edx */ + 0xbf, 0x00, 0x00, 0x00, 0x00, /* movl sizeof ($CLAST), %edi */ +}; + +/* + * if (*root == NULL) + * goto tomalloc; + * + * malloc_data_t *ret = *root; + * *root = *(void **)ret; + * t->tm_size += csize; + * ret->malloc_size = size; + * + * ret->malloc_data = UMEM_MALLOC_ENCODE(MALLOC_SECOND_MAGIC, size); + * ret++; + * + * return ((void *)ret); + * tomalloc: + * return (malloc(orig_size)); + */ +#define PTC_MALFINI_ALLABEL 0x00 +#define PTC_MALFINI_JMLABEL 0x20 +#define PTC_MALFINI_JMADDR 0x25 +static const uint8_t malfini[] = { + /* allocbuf: */ + 0x8b, 0x02, /* movl (%edx), %eax */ + 0x85, 0xc0, /* testl %eax, %eax */ + 0x74, 0x1a, /* je +0x1a (errout) */ + 0x8b, 0x18, /* movl (%eax), %esi */ + 0x89, 0x1a, /* movl %esi, (%edx) */ + 0x29, 0x39, /* subl %edi, (%ecx) */ + 0x89, 0x30, /* movl %esi, ($eax) */ + 0xba, 0x00, 0xc0, 0x10, 0x3a, /* movl $0x3a10c000,%edx */ + 0x29, 0xf2, /* subl %esi, %edx */ + 0x89, 0x50, 0x04, /* movl %edx, 0x4(%eax) */ + 0x83, 0xc0, 0x08, /* addl %0x8, %eax */ + 0x5b, /* popl %ebx */ + 0x5e, /* popl %esi */ + 0x5f, /* popl %edi */ + 0xc9, /* leave */ + 0xc3, /* ret */ + /* errout: */ + 0x5b, /* popl %ebx */ + 0x5e, /* popl %esi */ + 0x5f, /* popl %edi */ + 0xc9, /* leave */ + 0xe9, 0x00, 0x00, 0x00, 0x00 /* jmp $malloc */ +}; + +/* + * if (t->tm_size + csize > umem_ptc_size) + * goto tofree; + * + * t->tm_size += csize + * *(void **)tag = *root; + * *root = tag; + * return; + * tofree: + * free(buf); + * return; + */ +#define PTC_FRFINI_RBUFLABEL 0x00 +#define PTC_FRFINI_CACHEMAX 0x06 +#define PTC_FRFINI_DONELABEL 0x14 +#define PTC_FRFINI_JFLABEL 0x19 +#define PTC_FRFINI_JFADDR 0x1e +static const uint8_t freefini[] = { + /* freebuf: */ + 0x8b, 0x19, /* movl (%ecx),%ebx */ + 0x01, 0xfb, /* addl %edi,%ebx */ + 0x81, 0xfb, 0x00, 0x00, 0x00, 0x00, /* cmpl maxsize, %ebx */ + 0x73, 0x0d, /* jae +0xd <tofree> */ + 0x01, 0x39, /* addl %edi,(%ecx) */ + 0x8b, 0x3a, /* movl (%edx),%edi */ + 0x89, 0x38, /* movl %edi,(%eax) */ + 0x89, 0x02, /* movl %eax,(%edx) */ + /* done: */ + 0x5b, /* popl %ebx */ + 0x5e, /* popl %esi */ + 0x5f, /* popl %edi */ + 0xc9, /* leave */ + 0xc3, /* ret */ + /* realfree: */ + 0x5b, /* popl %ebx */ + 0x5e, /* popl %esi */ + 0x5f, /* popl %edi */ + 0xc9, /* leave */ + 0xe9, 0x00, 0x00, 0x00, 0x00 /* jmp free */ +}; + +/* + * Construct the initial part of malloc. off contains the offset from curthread + * to the root of the tmem structure. ep is the address of the label to error + * and jump to free. csize is the size of the largest umem_cache in ptcumem. + */ +static int +genasm_malinit(uint8_t *bp, uint32_t off, uint32_t ep, uint32_t csize) +{ + uint32_t addr; + + bcopy(malinit, bp, sizeof (malinit)); + addr = PTC_JMPADDR(ep, PTC_MALINIT_JOUT); + bcopy(&addr, bp + PTC_MALINIT_JOUT, sizeof (addr)); + bcopy(&csize, bp + PTC_MALINIT_MCS, sizeof (csize)); + addr = PTC_JMPADDR(ep, PTC_MALINIT_JOV); + bcopy(&addr, bp + PTC_MALINIT_JOV, sizeof (addr)); + bcopy(&off, bp + PTC_MALINIT_SOFF, sizeof (off)); + + return (sizeof (malinit)); +} + +static int +genasm_frinit(uint8_t *bp, uint32_t off, uint32_t dp, uint32_t ep, uint32_t mc) +{ + uint32_t addr; + + bcopy(freeinit, bp, sizeof (freeinit)); + addr = PTC_JMPADDR(dp, PTC_FRINI_JDONE); + bcopy(&addr, bp + PTC_FRINI_JDONE, sizeof (addr)); + addr = PTC_JMPADDR(ep, PTC_FRINI_JFREE); + bcopy(&addr, bp + PTC_FRINI_JFREE, sizeof (addr)); + bcopy(&mc, bp + PTC_FRINI_MCS, sizeof (mc)); + addr = PTC_JMPADDR(ep, PTC_FRINI_JOV); + bcopy(&addr, bp + PTC_FRINI_JOV, sizeof (addr)); + bcopy(&off, bp + PTC_FRINI_SOFF, sizeof (off)); + return (sizeof (freeinit)); +} + +/* + * Create the initial cache entry of the specified size. The value of ap tells + * us what the address of the label to try and allocate a buffer. This value is + * an offset from the current base to that value. + */ +static int +genasm_firstcache(uint8_t *bp, uint32_t csize, uint32_t ap) +{ + uint32_t addr; + + bcopy(inicache, bp, sizeof (inicache)); + bcopy(&csize, bp + PTC_INICACHE_CMP, sizeof (csize)); + bcopy(&csize, bp + PTC_INICACHE_SIZE, sizeof (csize)); + addr = PTC_JMPADDR(ap, PTC_INICACHE_JMP); + ASSERT(addr != 0); + bcopy(&addr, bp + PTC_INICACHE_JMP, sizeof (addr)); + + return (sizeof (inicache)); +} + +static int +genasm_gencache(uint8_t *bp, int num, uint32_t csize, uint32_t ap) +{ + uint32_t addr; + uint8_t coff; + + ASSERT(256 / PTC_ROOT_SIZE > num); + ASSERT(num != 0); + bcopy(gencache, bp, sizeof (gencache)); + bcopy(&csize, bp + PTC_GENCACHE_CMP, sizeof (csize)); + bcopy(&csize, bp + PTC_GENCACHE_SIZE, sizeof (csize)); + coff = num * PTC_ROOT_SIZE; + bcopy(&coff, bp + PTC_GENCACHE_NUM, sizeof (coff)); + addr = PTC_JMPADDR(ap, PTC_GENCACHE_JMP); + bcopy(&addr, bp + PTC_GENCACHE_JMP, sizeof (addr)); + + return (sizeof (gencache)); +} + +static int +genasm_lastcache(uint8_t *bp, int num, uint32_t csize, uint32_t ep) +{ + uint8_t addr; + + ASSERT(ep <= 0xff && ep > 7); + ASSERT(256 / PTC_ROOT_SIZE > num); + bcopy(fincache, bp, sizeof (fincache)); + bcopy(&csize, bp + PTC_FINCACHE_CMP, sizeof (csize)); + bcopy(&csize, bp + PTC_FINCACHE_SIZE, sizeof (csize)); + addr = num * PTC_ROOT_SIZE; + bcopy(&addr, bp + PTC_FINCACHE_NUM, sizeof (addr)); + addr = ep - PTC_FINCACHE_JMP - 1; + bcopy(&addr, bp + PTC_FINCACHE_JMP, sizeof (addr)); + + return (sizeof (fincache)); +} + +static int +genasm_malfini(uint8_t *bp, uintptr_t mptr) +{ + uint32_t addr; + + bcopy(malfini, bp, sizeof (malfini)); + addr = PTC_JMPADDR(mptr, ((uintptr_t)bp + PTC_MALFINI_JMADDR)); + bcopy(&addr, bp + PTC_MALFINI_JMADDR, sizeof (addr)); + + return (sizeof (malfini)); +} + +static int +genasm_frfini(uint8_t *bp, uint32_t maxthr, uintptr_t fptr) +{ + uint32_t addr; + + bcopy(freefini, bp, sizeof (freefini)); + bcopy(&maxthr, bp + PTC_FRFINI_CACHEMAX, sizeof (maxthr)); + addr = PTC_JMPADDR(fptr, ((uintptr_t)bp + PTC_FRFINI_JFADDR)); + bcopy(&addr, bp + PTC_FRFINI_JFADDR, sizeof (addr)); + + return (sizeof (freefini)); +} + +/* + * The malloc inline assembly is constructed as follows: + * + * o Malloc prologue assembly + * o Generic first-cache check + * o n Generic cache checks (where n = _tmem_get_entries() - 2) + * o Generic last-cache check + * o Malloc epilogue assembly + * + * Generally there are at least three caches. When there is only one cache we + * only use the generic last-cache. In the case where there are two caches, we + * just leave out the middle ones. + */ +static int +genasm_malloc(void *base, size_t len, int nents, int *umem_alloc_sizes) +{ + int ii, off; + uint8_t *bp; + size_t total; + uint32_t allocoff, erroff; + + total = sizeof (malinit) + sizeof (malfini) + sizeof (fincache); + + if (nents >= 2) + total += sizeof (inicache) + sizeof (gencache) * (nents - 2); + + if (total > len) + return (1); + + erroff = total - sizeof (malfini) + PTC_MALFINI_JMLABEL; + allocoff = total - sizeof (malfini) + PTC_MALFINI_ALLABEL; + + bp = base; + + off = genasm_malinit(bp, umem_tmem_off, erroff, + umem_alloc_sizes[nents-1]); + bp += off; + allocoff -= off; + erroff -= off; + + if (nents > 1) { + off = genasm_firstcache(bp, umem_alloc_sizes[0], allocoff); + bp += off; + allocoff -= off; + erroff -= off; + } + + for (ii = 1; ii < nents - 1; ii++) { + off = genasm_gencache(bp, ii, umem_alloc_sizes[ii], allocoff); + bp += off; + allocoff -= off; + erroff -= off; + } + + bp += genasm_lastcache(bp, nents - 1, umem_alloc_sizes[nents - 1], + erroff); + bp += genasm_malfini(bp, umem_genasm_omptr); + ASSERT(((uintptr_t)bp - total) == (uintptr_t)base); + + return (0); +} + +static int +genasm_free(void *base, size_t len, int nents, int *umem_alloc_sizes) +{ + uint8_t *bp; + int ii, off; + size_t total; + uint32_t rbufoff, retoff, erroff; + + /* Assume that nents has already been audited for us */ + total = sizeof (freeinit) + sizeof (freefini) + sizeof (fincache); + if (nents >= 2) + total += sizeof (inicache) + sizeof (gencache) * (nents - 2); + + if (total > len) + return (1); + + erroff = total - (sizeof (freefini) - PTC_FRFINI_JFLABEL); + rbufoff = total - (sizeof (freefini) - PTC_FRFINI_RBUFLABEL); + retoff = total - (sizeof (freefini) - PTC_FRFINI_DONELABEL); + + bp = base; + + off = genasm_frinit(bp, umem_tmem_off, retoff, erroff, + umem_alloc_sizes[nents - 1]); + bp += off; + erroff -= off; + rbufoff -= off; + + if (nents > 1) { + off = genasm_firstcache(bp, umem_alloc_sizes[0], rbufoff); + bp += off; + erroff -= off; + rbufoff -= off; + } + + for (ii = 1; ii < nents - 1; ii++) { + off = genasm_gencache(bp, ii, umem_alloc_sizes[ii], rbufoff); + bp += off; + rbufoff -= off; + erroff -= off; + } + + bp += genasm_lastcache(bp, nents - 1, umem_alloc_sizes[nents - 1], + erroff); + bp += genasm_frfini(bp, umem_ptc_size, umem_genasm_ofptr); + ASSERT(((uintptr_t)bp - total) == (uintptr_t)base); + + return (0); +} + +int +umem_genasm(int *alloc_sizes, umem_cache_t **caches, int ncaches) +{ + int nents, i; + uint8_t *mptr; + uint8_t *fptr; + uint32_t *ptr; + uint64_t v, *vptr; + + mptr = (void *)((uintptr_t)&umem_genasm_mptr + 5); + fptr = (void *)((uintptr_t)&umem_genasm_fptr + 5); + if (umem_genasm_mptr == 0 || umem_genasm_msize == 0 || + umem_genasm_fptr == 0 || umem_genasm_fsize == 0) + return (1); + + /* + * The total number of caches that we can service is the minimum of: + * o the amount supported by libc + * o the total number of umem caches + * o we use a single byte addl, so its 255 / sizeof (uintptr_t). For + * 32-bit, this is 63. + */ + nents = _tmem_get_nentries(); + + if (UMEM_GENASM_MAX32 < nents) + nents = UMEM_GENASM_MAX32; + + if (ncaches < nents) + nents = ncaches; + + /* Based on our constraints, this is not an error */ + if (nents == 0 || umem_ptc_size == 0) + return (0); + + /* Grab the original malloc and free locations */ + ptr = (void *)(mptr - 4); + umem_genasm_omptr = *ptr + (uintptr_t)mptr; + ptr = (void *)(fptr - 4); + umem_genasm_ofptr = *ptr + (uintptr_t)fptr; + + /* Take into account the jump */ + if (genasm_malloc(mptr, umem_genasm_fsize - 5, nents, + alloc_sizes) != 0) + return (1); + + if (genasm_free(fptr, umem_genasm_fsize - 5, nents, + alloc_sizes) != 0) + return (1); + + /* nop out the jump with a multibyte jump */ + vptr = (void *)&umem_genasm_mptr; + v = MULTINOP; + v |= *vptr & (0xffffffULL << 40); + (void) atomic_swap_64(vptr, v); + vptr = (void *)&umem_genasm_fptr; + v = MULTINOP; + v |= *vptr & (0xffffffULL << 40); + (void) atomic_swap_64(vptr, v); + + for (i = 0; i < nents; i++) + caches[i]->cache_flags |= UMF_PTC; + + return (0); +} diff --git a/usr/src/lib/libumem/sparc/umem_genasm.c b/usr/src/lib/libumem/sparc/umem_genasm.c new file mode 100644 index 0000000000..77dcc4a6a5 --- /dev/null +++ b/usr/src/lib/libumem/sparc/umem_genasm.c @@ -0,0 +1,38 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + */ + +/* + * Don't Panic! If you wonder why this seemingly empty file exists, it's because + * there is no sparc implementation for ptcumem. Go read libumem's big theory + * statement in lib/libumem/common/umem.c, particularly section eight. + */ + +int umem_genasm_supported = 0; + +/*ARGSUSED*/ +int +umem_genasm(int *cp, int nc) +{ + return (1); +} diff --git a/usr/src/lib/print/libprint/Makefile b/usr/src/lib/libumem_trampoline/Makefile index 55847e0be0..e1140efa8c 100644 --- a/usr/src/lib/print/libprint/Makefile +++ b/usr/src/lib/libumem_trampoline/Makefile @@ -19,36 +19,32 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright (c) 2012 Joyent, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# -include ../../Makefile.lib +include ../Makefile.lib -SUBDIRS = $(MACH) -#$(BUILD64)SUBDIRS += $(MACH64) +SUBDIRS= $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) -all := TARGET = all -clean := TARGET = clean -clobber := TARGET = clobber -install := TARGET = install -lint := TARGET = lint +all := TARGET= all +clean := TARGET= clean +clobber := TARGET= clobber +install := TARGET= install +lint := TARGET= lint .KEEP_STATE: -all clean clobber install: .WAIT $(SUBDIRS) - -lint: # $(SUBDIRS) +all clean clobber install lint: $(SUBDIRS) -install_h: +install_h: $(ROOTHDRS) -check: +check: $(CHECKHDRS) -$(SUBDIRS): FRC +$(SUBDIRS): FRC @cd $@; pwd; $(MAKE) $(TARGET) FRC: -include ../../Makefile.targ +include ../Makefile.targ diff --git a/usr/src/lib/libumem_trampoline/Makefile.com b/usr/src/lib/libumem_trampoline/Makefile.com new file mode 100644 index 0000000000..a43fad0fd5 --- /dev/null +++ b/usr/src/lib/libumem_trampoline/Makefile.com @@ -0,0 +1,49 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2012 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +LIBRARY = libumem_trampoline.a +VERS = .1 +OBJECTS = trampoline.o + +include ../../Makefile.lib + +# install this library in the root filesystem +include ../../Makefile.rootfs + +LIBS = $(DYNLIB) $(LINTLIB) + +SRCDIR = ../common + +$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC) + +CFLAGS += $(CCVERBOSE) + +.KEEP_STATE: + +all: $(LIBS) + +lint: lintcheck + +include ../../Makefile.targ diff --git a/usr/src/lib/print/libhttp-core/i386/Makefile b/usr/src/lib/libumem_trampoline/amd64/Makefile index 0bc3313291..132720332b 100644 --- a/usr/src/lib/print/libhttp-core/i386/Makefile +++ b/usr/src/lib/libumem_trampoline/amd64/Makefile @@ -19,12 +19,11 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2012 (c) Joyent, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# include ../Makefile.com +include ../../Makefile.lib.64 -install: all $(ROOTLIBDIR) $(ROOTLIBS) $(ROOTLINKS) +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libumem_trampoline/common/llib-lumem_trampoline b/usr/src/lib/libumem_trampoline/common/llib-lumem_trampoline new file mode 100644 index 0000000000..8fda64fc80 --- /dev/null +++ b/usr/src/lib/libumem_trampoline/common/llib-lumem_trampoline @@ -0,0 +1,28 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* LINTLIBRARY */ +/* PROTOLIB1 */ diff --git a/usr/src/lib/libumem_trampoline/common/mapfile-vers b/usr/src/lib/libumem_trampoline/common/mapfile-vers new file mode 100644 index 0000000000..c52eeda977 --- /dev/null +++ b/usr/src/lib/libumem_trampoline/common/mapfile-vers @@ -0,0 +1,62 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright (c) 2012, Joyent, Inc. All rights reserved. +# + +# +# MAPFILE HEADER START +# +# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. +# Object versioning must comply with the rules detailed in +# +# usr/src/lib/README.mapfiles +# +# You should not be making modifications here until you've read the most current +# copy of that file. If you need help, contact a gatekeeper for guidance. +# +# MAPFILE HEADER END +# + +$mapfile_version 2 + +# +# The BSS must me executable for ptcumem to work properly. If it is not, +# programs will get a SEGV. For more information read section of 8 libumem's big +# theory statement in lib/libumem/common/umem.c. +# +LOAD_SEGMENT bss { + FLAGS = READ WRITE EXECUTE; +}; + +SYMBOL_VERSION SUNWprivate_1.1 { + global: + la_version; + la_objopen; +$if _ELF32 + la_symbind32; +$endif +$if _ELF64 + la_symbind64; +$endif + local: + *; +}; diff --git a/usr/src/lib/libumem_trampoline/common/trampoline.c b/usr/src/lib/libumem_trampoline/common/trampoline.c new file mode 100644 index 0000000000..200f32aabc --- /dev/null +++ b/usr/src/lib/libumem_trampoline/common/trampoline.c @@ -0,0 +1,166 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2012 Joyent, Inc. All rights reserved. + */ + +/* + * This is a local link auditing library for libumem(3LIB). It provides a means + * for us to implement the per-thread caching component of libumem. When any + * binary or library attempts to bind to libumem's malloc and free symbols we + * instead point them to a private buffer in our own BSS. Our mapfile ensures + * that this BSS is readable, writeable, and executable. By default these + * private buffers contain a jmp instruction to the original libumem malloc and + * free. + * + * When libumem tries to generate its assembly, we key off of private symbol + * names and replace their values with pointers to our values. For more + * information on this process, see section 8 of the big theory statement for + * libumem in lib/libumem/common/umem.c. + * + * Note that this is very x86 specific currently. This includes x86 instructions + * and making assumptions about alignment of variables, see the lint warnings. + * By the current construction, SPARC is basically a no-op. + */ +#include <dlfcn.h> +#include <unistd.h> +#include <sys/types.h> +#include <libelf.h> +#include <link.h> + +#if defined(__i386) || defined(__amd64) +#define LIBUMEM_TRAMPOLINE_JMP32 0xe9 +#endif /* defined(__i386) || defined(__amd64) */ + +/* + * This is our malloc trampoline. We give it the name "malloc" to make it + * appear somewhat like malloc. + */ +static uint8_t malloc[4096]; +static uint8_t free[4096]; +static size_t msize = sizeof (malloc); +static size_t fsize = sizeof (free); + +/* + * We don't want to link against libc, so we define our own versions of the + * string functions as necessary. + */ +static int +la_strcmp(const char *s1, const char *s2) +{ + if (s1 == s2) + return (0); + while (*s1 == *s2++) + if (*s1++ == '\0') + return (0); + + return (*(unsigned char *)s1 - *(unsigned char *)--s2); +} + +static char * +la_strrchr(char *str, char c) +{ + char *r; + + r = NULL; + do { + if (*str == c) + r = str; + } while (*str++); + return (r); +} + +/*ARGSUSED*/ +uint_t +la_version(uint_t version) +{ + return (LAV_CURRENT); +} + +/*ARGSUSED*/ +uint_t +la_objopen(Link_map *lmp, Lmid_t lmid, uintptr_t *cookie) +{ +#if defined(__i386) || defined(__amd64) + char *objname; + + if ((objname = la_strrchr(lmp->l_name, '/')) == NULL || + *(++objname) == '\0') + objname = lmp->l_name; + + if (la_strcmp(objname, "libumem.so.1") == 0 || + la_strcmp(objname, "libumem.so") == 0) + return (LA_FLG_BINDFROM | LA_FLG_BINDTO); +#endif /* defined(__i386) || defined(__amd64) */ + + return (0); +} + +#if defined(_LP64) +/*ARGSUSED*/ +uintptr_t +la_symbind64(Elf64_Sym *symp, uint_t symndx, uintptr_t *refcook, + uintptr_t *defcook, uint_t *sb_flags, char const *sym_name) +#else +/*ARGSUSED*/ +uintptr_t +la_symbind32(Elf32_Sym *symp, uint_t symndx, uintptr_t *refcook, + uintptr_t *defcook, uint_t *sb_flags) +#endif +{ +#if defined(__i386) || defined(__amd64) + int i = 0; + +#if !defined(_LP64) + char const *sym_name = (char const *) symp->st_name; +#endif + + if (la_strcmp(sym_name, "malloc") == 0) { + if (malloc[i] == '\0') { + malloc[i++] = LIBUMEM_TRAMPOLINE_JMP32; + /*LINTED E_BAD_PTR_CAST_ALIGN*/ + *(uint32_t *)&malloc[i] = (uint32_t)(symp->st_value - + (uintptr_t)&malloc[i + sizeof (uint32_t)]); + } + + return ((uintptr_t)malloc); + } else if (la_strcmp(sym_name, "free") == 0) { + if (free[i] == '\0') { + free[i++] = LIBUMEM_TRAMPOLINE_JMP32; + /*LINTED E_BAD_PTR_CAST_ALIGN*/ + *(uint32_t *)&free[i] = (uint32_t)(symp->st_value - + (uintptr_t)&free[i + sizeof (uint32_t)]); + } + + return ((uintptr_t)free); + } else if (la_strcmp(sym_name, "umem_genasm_mptr") == 0) { + return ((uintptr_t)malloc); + } else if (la_strcmp(sym_name, "umem_genasm_msize") == 0) { + return ((uintptr_t)&msize); + } else if (la_strcmp(sym_name, "umem_genasm_fptr") == 0) { + return ((uintptr_t)free); + } else if (la_strcmp(sym_name, "umem_genasm_fsize") == 0) { + return ((uintptr_t)&fsize); + } else { + return (symp->st_value); + } +#endif /* defined(__i386) || defined(__amd64) */ +} diff --git a/usr/src/lib/libumem_trampoline/i386/Makefile b/usr/src/lib/libumem_trampoline/i386/Makefile new file mode 100644 index 0000000000..76c3ccc672 --- /dev/null +++ b/usr/src/lib/libumem_trampoline/i386/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2012 (c) Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libumem_trampoline/sparc/Makefile b/usr/src/lib/libumem_trampoline/sparc/Makefile new file mode 100644 index 0000000000..76c3ccc672 --- /dev/null +++ b/usr/src/lib/libumem_trampoline/sparc/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2012 (c) Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libumem_trampoline/sparcv9/Makefile b/usr/src/lib/libumem_trampoline/sparcv9/Makefile new file mode 100644 index 0000000000..132720332b --- /dev/null +++ b/usr/src/lib/libumem_trampoline/sparcv9/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2012 (c) Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) diff --git a/usr/src/lib/libvrrpadm/common/libvrrpadm.c b/usr/src/lib/libvrrpadm/common/libvrrpadm.c index 2e9cb06aaf..15365864a1 100644 --- a/usr/src/lib/libvrrpadm/common/libvrrpadm.c +++ b/usr/src/lib/libvrrpadm/common/libvrrpadm.c @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2012, Joyent, Inc. All rights reserved. + */ + #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> @@ -692,7 +696,8 @@ lookup_vnic(dladm_handle_t dh, datalink_id_t vnicid, void *arg) if (vrrp_is_vrrp_vnic(lva->lva_vh, vnicid, &linkid, &vid, &vrid, &af) && lva->lva_vrid == vrid && lva->lva_linkid == linkid && - lva->lva_vid == vid && lva->lva_af == af) { + (lva->lva_vid == VLAN_ID_NONE || lva->lva_vid == vid) && + lva->lva_af == af) { if (dladm_datalink_id2info(dh, vnicid, NULL, NULL, NULL, lva->lva_vnic, sizeof (lva->lva_vnic)) == DLADM_STATUS_OK) { return (DLADM_WALK_TERMINATE); @@ -714,6 +719,7 @@ vrrp_get_vnicname(vrrp_handle_t vh, vrid_t vrid, int af, char *link, uint16_t vid = VLAN_ID_NONE; datalink_class_t class; dladm_vlan_attr_t vlan_attr; + dladm_vnic_attr_t vnic_attr; struct lookup_vnic_arg lva; uint32_t media; @@ -736,11 +742,20 @@ vrrp_get_vnicname(vrrp_handle_t vh, vrid_t vrid, int af, char *link, } } + if (class == DATALINK_CLASS_VNIC) { + if (dladm_vnic_info(vh->vh_dh, linkid, &vnic_attr, + DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) { + return (VRRP_EINVAL); + } + linkid = vnic_attr.va_link_id; + vid = vnic_attr.va_vid; + } + /* - * For now, Only VRRP over aggr and physical ethernet links is supported + * Only VRRP over vnics, aggrs and physical ethernet links is supported */ - if ((class != DATALINK_CLASS_PHYS && class != DATALINK_CLASS_AGGR) || - media != DL_ETHER) { + if ((class != DATALINK_CLASS_PHYS && class != DATALINK_CLASS_AGGR && + class != DATALINK_CLASS_VNIC) || media != DL_ETHER) { return (VRRP_EINVAL); } diff --git a/usr/src/lib/libwanboot/Makefile.com b/usr/src/lib/libwanboot/Makefile.com index ed69ec0b8a..1e6310f9ba 100644 --- a/usr/src/lib/libwanboot/Makefile.com +++ b/usr/src/lib/libwanboot/Makefile.com @@ -60,7 +60,7 @@ include ../../Makefile.lib LIBS += $(LINTLIB) LDLIBS += -lnvpair -lresolv -lnsl -lsocket -ldevinfo -ldhcputil \ - -linetutil -lc -lcrypto -lssl + -linetutil -lc -lsunw_crypto -lsunw_ssl CPPFLAGS = -I$(SRC)/common/net/wanboot/crypt $(CPPFLAGS.master) CERRWARN += -_gcc=-Wno-switch CERRWARN += -_gcc=-Wno-parentheses diff --git a/usr/src/lib/libzdoor/Makefile b/usr/src/lib/libzdoor/Makefile new file mode 100644 index 0000000000..50d9545ef1 --- /dev/null +++ b/usr/src/lib/libzdoor/Makefile @@ -0,0 +1,48 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2011 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.lib + +SUBDIRS= $(MACH) +$(BUILD64)SUBDIRS += $(MACH64) + +all := TARGET = all +clean := TARGET = clean +clobber := TARGET = clobber +install := TARGET = install +lint := TARGET = lint + +.KEEP_STATE: + +all clean clobber install lint: $(SUBDIRS) + +$(SUBDIRS): FRC + @cd $@; pwd; $(MAKE) $(TARGET) + +_msg: + +FRC: + +include ../Makefile.targ diff --git a/usr/src/lib/print/libpapi-common/Makefile.com b/usr/src/lib/libzdoor/Makefile.com index 7948a2261e..09bde0f1b4 100644 --- a/usr/src/lib/print/libpapi-common/Makefile.com +++ b/usr/src/lib/libzdoor/Makefile.com @@ -18,34 +18,28 @@ # # CDDL HEADER END # -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2011 Joyent, Inc. All rights reserved. # Use is subject to license terms. # -LIBRARY = libpapi-common.a -VERS = .0 -OBJECTS = attribute.o common.o library.o list.o misc.o status.o uri.o - -include ../../../Makefile.lib -include ../../../Makefile.rootfs +LIBRARY= libzdoor.a +VERS= .1 +OBJECTS= zdoor.o \ + zdoor-int.o \ + ztree.o \ + zerror.o -ROOTLIBDIR= $(ROOT)/usr/lib +include ../../Makefile.lib +include ../../Makefile.rootfs SRCDIR = ../common +SRCS = $(OBJECTS:%.o=$(SRCDIR)/%.c) -LIBS = $(DYNLIB) - -$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRCDIR) - -CERRWARN += -_gcc=-Wno-switch - -MAPFILES = $(SRCDIR)/mapfile +CPPFLAGS += -I$(SRCDIR) -D_REENTRANT -D_FILE_OFFSET_BITS=64 +LIBS = $(DYNLIB) $(LINTLIB) +LDLIBS += -lc -lzonecfg -lcontract -LDLIBS += -lc -lsocket -lnsl +$(LINTLIB) := SRCS= $(SRCDIR)/$(LINTSRC) .KEEP_STATE: @@ -53,4 +47,4 @@ all: $(LIBS) lint: lintcheck -include ../../../Makefile.targ +include ../../Makefile.targ diff --git a/usr/src/lib/libzdoor/amd64/Makefile b/usr/src/lib/libzdoor/amd64/Makefile new file mode 100644 index 0000000000..31be0ef7e6 --- /dev/null +++ b/usr/src/lib/libzdoor/amd64/Makefile @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2011 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com +include ../../Makefile.lib.64 + +install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) diff --git a/usr/src/lib/libzdoor/common/llib-lzdoor b/usr/src/lib/libzdoor/common/llib-lzdoor new file mode 100644 index 0000000000..a21a904b11 --- /dev/null +++ b/usr/src/lib/libzdoor/common/llib-lzdoor @@ -0,0 +1,34 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/*LINTLIBRARY*/ +/*PROTOLIB1*/ +/* + * + * Copyright 2011 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + * + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <zdoor.h> diff --git a/usr/src/lib/print/libipp-core/common/mapfile b/usr/src/lib/libzdoor/common/mapfile-vers index 19a947feb5..38eba57ee2 100644 --- a/usr/src/lib/print/libipp-core/common/mapfile +++ b/usr/src/lib/libzdoor/common/mapfile-vers @@ -18,13 +18,7 @@ # # CDDL HEADER END # - -# -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# $Id: mapfile 151 2006-04-25 16:55:34Z njacobs $ +# Copyright (c) 2011, Joyent Inc. All rights reserved. # # @@ -43,18 +37,12 @@ $mapfile_version 2 -# -# Common interfaces that are most likely to be shared amongst the various -# PAPI implementations. -# - -SYMBOL_VERSION SUNWprivate_1.0 { +SYMBOL_VERSION SUNWprivate_1.1 { global: - ipp_read_message ; - ipp_write_message ; - ipp_validate_request ; - ipp_set_status ; - + zdoor_handle_init; + zdoor_handle_destroy; + zdoor_open; + zdoor_close; local: - * ; -} ; + *; +}; diff --git a/usr/src/lib/libzdoor/common/zdoor-int.c b/usr/src/lib/libzdoor/common/zdoor-int.c new file mode 100644 index 0000000000..f77c1453d4 --- /dev/null +++ b/usr/src/lib/libzdoor/common/zdoor-int.c @@ -0,0 +1,324 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2012 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <errno.h> +#include <fcntl.h> +#include <sys/fork.h> +#include <libcontract.h> +#include <libzonecfg.h> +#include <sys/contract/process.h> +#include <sys/ctfs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "zdoor-int.h" +#include "zerror.h" + +#define ZDOOR_FMT_STR "/var/tmp/.%s" + + +static int +init_template(void) +{ + int fd = 0; + int err = 0; + + fd = open64(CTFS_ROOT "/process/template", O_RDWR); + if (fd == -1) + return (-1); + + err |= ct_tmpl_set_critical(fd, 0); + err |= ct_tmpl_set_informative(fd, 0); + err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR); + err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT); + if (err || ct_tmpl_activate(fd)) { + (void) close(fd); + return (-1); + } + + return (fd); +} + +static int +contract_latest(ctid_t *id) +{ + int cfd = 0; + int r = 0; + ct_stathdl_t st = {0}; + ctid_t result = {0}; + + if ((cfd = open64(CTFS_ROOT "/process/latest", O_RDONLY)) == -1) + return (errno); + if ((r = ct_status_read(cfd, CTD_COMMON, &st)) != 0) { + (void) close(cfd); + return (r); + } + + result = ct_status_get_id(st); + ct_status_free(st); + (void) close(cfd); + + *id = result; + return (0); +} + +static int +close_on_exec(int fd) +{ + int flags = fcntl(fd, F_GETFD, 0); + if ((flags != -1) && (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1)) + return (0); + return (-1); +} + +static int +contract_open(ctid_t ctid, const char *type, const char *file, int oflag) +{ + char path[PATH_MAX]; + int n = 0; + int fd = 0; + + if (type == NULL) + type = "all"; + + n = snprintf(path, PATH_MAX, CTFS_ROOT "/%s/%ld/%s", type, ctid, file); + if (n >= sizeof (path)) { + errno = ENAMETOOLONG; + return (-1); + } + + fd = open64(path, oflag); + if (fd != -1) { + if (close_on_exec(fd) == -1) { + int err = errno; + (void) close(fd); + errno = err; + return (-1); + } + } + return (fd); +} + +static int +contract_abandon_id(ctid_t ctid) +{ + int fd = 0; + int err = 0; + + fd = contract_open(ctid, "all", "ctl", O_WRONLY); + if (fd == -1) + return (errno); + + err = ct_ctl_abandon(fd); + (void) close(fd); + + return (err); +} + +/* + * zdoor_fattach(zone,service,door,detach_only) is heavily borrowed from + * zonestatd. Basically this forks, zone_enter's the targeted zone, + * fattaches to /var/tmp/.<service> with the door you've opened. + * detach_only gets passed in on door_stop to fdetach in the targeted zone. + * Note that this code really does require all the contract calls, which are + * all the static functions preceding this (have a look at zone_enter; without + * that code zone_enter will kick back EINVAL). + */ +int +zdoor_fattach(zoneid_t zoneid, const char *service, int door, int detach_only) +{ + int fd = 0; + int len = 0; + int pid = 0; + int stat = 0; + int tmpl_fd = 0; + char path[MAXPATHLEN] = {0}; + ctid_t ct = -1; + + if (zoneid < 0) { + zdoor_debug("zdoor_fattach: zoneid < 0"); + return (ZDOOR_ARGS_ERROR); + } + + if (service == NULL) { + zdoor_debug("zdoor_fattach: NULL service"); + return (ZDOOR_ARGS_ERROR); + } + + if ((tmpl_fd = init_template()) < 0) { + zdoor_warn("zdoor_fattach: init contract for %d:%s failed", + zoneid, service); + return (ZDOOR_ERROR); + } + + len = snprintf(NULL, 0, ZDOOR_FMT_STR, service) + 1; + if (len > MAXPATHLEN) + return (ZDOOR_ARGS_ERROR); + (void) snprintf(path, len, ZDOOR_FMT_STR, service); + + zdoor_info("zdoor_fattach: ensuring %s", path); + + pid = fork(); + if (pid < 0) { + (void) ct_tmpl_clear(tmpl_fd); + zdoor_error("zdoor_fattach: unable to fork for zone_enter: %s", + strerror(errno)); + return (ZDOOR_OK); + } + + if (pid == 0) { + zdoor_debug("zdoor_fattach(CHILD): starting"); + (void) ct_tmpl_clear(tmpl_fd); + (void) close(tmpl_fd); + if (zone_enter(zoneid) != 0) { + zdoor_debug("zdoor_fattach(CHILD): zone_enter fail %s", + strerror(errno)); + if (errno == EINVAL) { + _exit(0); + } + _exit(1); + } + (void) fdetach(path); + (void) unlink(path); + if (detach_only) { + zdoor_debug("zdoor_fattach(CHILD): detach only, done"); + _exit(0); + } + fd = open(path, O_CREAT|O_RDWR, 0644); + if (fd < 0) { + zdoor_debug("zdoor_fattach(CHILD): open failed: %s", + strerror(errno)); + _exit(2); + } + if (fattach(door, path) != 0) { + zdoor_debug("zdoor_fattach(CHILD): fattach failed: %s", + strerror(errno)); + _exit(3); + } + _exit(0); + } + if (contract_latest(&ct) == -1) + ct = -1; + (void) ct_tmpl_clear(tmpl_fd); + (void) close(tmpl_fd); + (void) contract_abandon_id(ct); + + zdoor_debug("zdoor_fattach: waiting for child..."); + while (waitpid(pid, &stat, 0) != pid) + ; + if (WIFEXITED(stat) && WEXITSTATUS(stat) == 0) { + zdoor_debug(" child exited with success"); + zdoor_debug("zdoor_fattach: returning ZDOOR_OK"); + return (ZDOOR_OK); + } + + zdoor_debug(" child exited with %d", WEXITSTATUS(stat)); + zdoor_debug("zdoor_fattach: returning ZDOOR_ERROR"); + return (ZDOOR_ERROR); +} + +/* + * zdoor_zone_is_running(zone) returns 1 if the specified zone is running, or 0 + * if it is any other state. It additionally eats any other errors it + * encounters and returns 0 upon encountering them. + */ +boolean_t +zdoor_zone_is_running(zoneid_t zoneid) +{ + zone_state_t state; + char zone[ZONENAME_MAX]; + if (zoneid < 0) + return (B_FALSE); + + if (getzonenamebyid(zoneid, zone, ZONENAME_MAX) < 0) + return (B_FALSE); + + if (!zone_get_state((char *)zone, &state) == Z_OK) + return (B_FALSE); + + return (state == ZONE_STATE_RUNNING); +} + +/* + * zdoor_cookie_create simply allocates and initializes + * memory. Returns NULL on any error. + */ +zdoor_cookie_t * +zdoor_cookie_create(const char *zonename, const char *service, +const void *biscuit) +{ + zdoor_cookie_t *cookie = NULL; + + if (zonename == NULL || service == NULL) + return (NULL); + + cookie = (zdoor_cookie_t *)calloc(1, sizeof (zdoor_cookie_t)); + if (cookie == NULL) { + OUT_OF_MEMORY(); + return (NULL); + } + cookie->zdc_biscuit = (void *)biscuit; + cookie->zdc_zonename = strdup((char *)zonename); + if (cookie->zdc_zonename == NULL) { + zdoor_cookie_free(cookie); + OUT_OF_MEMORY(); + return (NULL); + } + cookie->zdc_service = strdup((char *)service); + if (cookie->zdc_service == NULL) { + zdoor_cookie_free(cookie); + OUT_OF_MEMORY(); + return (NULL); + } + + return (cookie); +} + +/* + * zdoor_cookie_free(cookie) cleans up any memory associated with the + * specified cookie. + */ +void +zdoor_cookie_free(zdoor_cookie_t *cookie) +{ + if (cookie == NULL) + return; + + if (cookie->zdc_zonename != NULL) { + free(cookie->zdc_zonename); + cookie->zdc_zonename = NULL; + } + + if (cookie->zdc_service != NULL) { + free(cookie->zdc_service); + cookie->zdc_service = NULL; + } + + free(cookie); +} diff --git a/usr/src/lib/print/libpapi-common/common/uri.h b/usr/src/lib/libzdoor/common/zdoor-int.h index 5dd714a199..782452c426 100644 --- a/usr/src/lib/print/libpapi-common/common/uri.h +++ b/usr/src/lib/libzdoor/common/zdoor-int.h @@ -18,49 +18,47 @@ * * CDDL HEADER END */ - /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2011 Joyent, Inc. All rights reserved. * Use is subject to license terms. - * */ -#ifndef _URI_H -#define _URI_H +#ifndef _ZDOOR_INT_H +#define _ZDOOR_INT_H -/* $Id: uri.h 146 2006-03-24 00:26:54Z njacobs $ */ +#pragma ident "%Z%%M% %I% %E% SMI" -#pragma ident "%Z%%M% %I% %E% SMI" +#include <pthread.h> +#include <zdoor.h> #ifdef __cplusplus extern "C" { #endif -/* - * scheme://[[user[:password]@]host[:port]]/path[[#fragment]|[?query]] - */ -typedef struct { - char *scheme; - char *scheme_part; - char *user; - char *password; - char *host; - char *port; - char *path; - char *fragment; - char *query; - /* really for testing, but left in */ - char *user_part; - char *host_part; - char *path_part; -} uri_t; +typedef enum zdoor_action_t { + ZDOOR_ACTION_NOOP, + ZDOOR_ACTION_STOP, + ZDOOR_ACTION_START +} zdoor_action_t; + +struct zdoor_handle { + pthread_mutex_t zdh_lock; + void *zdh_zonecfg_handle; + void *zdh_ztree; +}; + +zdoor_cookie_t *zdoor_cookie_create(const char *zonename, const char *service, + const void *biscuit); + +void zdoor_cookie_free(zdoor_cookie_t *cookie); + +boolean_t zdoor_zone_is_running(zoneid_t zoneid); -extern int uri_from_string(char *string, uri_t **uri); -extern int uri_to_string(uri_t *uri, char *buffer, size_t buflen); -extern void uri_free(uri_t *uri); +int zdoor_fattach(zoneid_t zoneid, const char *service, int door, + int detach_only); #ifdef __cplusplus } #endif -#endif /* _URI_H */ +#endif /* _ZDOOR_INT_H */ diff --git a/usr/src/lib/libzdoor/common/zdoor.c b/usr/src/lib/libzdoor/common/zdoor.c new file mode 100644 index 0000000000..f2996b4e2d --- /dev/null +++ b/usr/src/lib/libzdoor/common/zdoor.c @@ -0,0 +1,437 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2011 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <alloca.h> +#include <door.h> +#include <errno.h> +#include <fcntl.h> +#include <libzonecfg.h> +#include <pthread.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <syslog.h> +#include <stdlib.h> +#include <string.h> +#include <stropts.h> +#include <unistd.h> +#include <zdoor.h> +#include <zone.h> + +#include "zdoor-int.h" +#include "zerror.h" +#include "ztree.h" + +extern void * +zonecfg_notify_bind(int(*func)(const char *zonename, zoneid_t zid, + const char *newstate, const char *oldstate, + hrtime_t when, void *p), void *p); + +extern void +zonecfg_notify_unbind(void *handle); + +/* + * _callback(cookie, door_args...) is our private function that we tell + * the Solaris door API about. This function does some sanity checking on + * arguments and issues a callback to the owner of this door. That API + * will return us memory that needs to be sent back to the client on the + * other end of the door, but since the door_return API never gives you + * back control of the function, this does a simple alloca/memcpy and + * frees up the memory pointed to by the parent. While this really doesn't + * let a client do much other than pass a simple struct of primitives (or + * more likely more common a char *), that's the way the door API works, + * and so this isn't really imposing any restriction that didn't already + * need to be dealt with by someone. This is why the zdoor_result structure + * takes a char *, rather than a void * for the data pointer. + */ +static void +_callback(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, + uint_t n_desc) +{ + zdoor_result_t *result = NULL; + void *door_response = NULL; + int size = 0; + dtree_entry_t *entry = (dtree_entry_t *)cookie; + + if (entry == NULL) { + zdoor_warn("_callback: NULL cookie? door_returning"); + (void) door_return(NULL, 0, NULL, 0); + } + + (void) pthread_mutex_lock(&entry->dte_parent->zte_parent->zdh_lock); + zdoor_debug("_callback: calling back with %p", entry->dte_cookie); + result = entry->dte_callback(entry->dte_cookie, argp, arg_size); + zdoor_debug("_callback: app callback returned %p", result); + (void) pthread_mutex_unlock(&entry->dte_parent->zte_parent->zdh_lock); + + if (result == NULL) { + zdoor_debug("_callback: door_returning NULL"); + (void) door_return(NULL, 0, NULL, 0); + } + + if (result->zdr_data != NULL && result->zdr_size > 0) { + door_response = alloca(result->zdr_size); + if (door_response != NULL) { + size = result->zdr_size; + (void) memcpy(door_response, + (void *) result->zdr_data, size); + } + } + + if (result->zdr_data != NULL) + free(result->zdr_data); + free(result); + + zdoor_debug("_callback: door_returning %p, %d", door_response, size); + (void) door_return(door_response, size, NULL, 0); +} + +static void +zdoor_stop(dtree_entry_t *entry) +{ + zoneid_t zid = -1; + + if (entry == NULL) { + zdoor_debug("zdoor_stop: NULL arguments"); + return; + } + + zdoor_debug("zdoor_stop: entry=%p, zone=%s, service=%s", + entry, entry->dte_parent->zte_zonename, entry->dte_service); + + zid = getzoneidbyname(entry->dte_parent->zte_zonename); + (void) zdoor_fattach(zid, entry->dte_service, entry->dte_door, 1); + (void) door_revoke(entry->dte_door); + entry->dte_door = -1; + + zdoor_debug("zdoor_stop returning"); +} + +/* + * zdoor_create is called both by the main API + * call zdoor_open, as well as by the zone_monitor code upon a zone restart + * (assuming it already has a door in it). This code assumes that the + * permissions were correct (e.g., the target door is not a GZ, that this + * program is being run out of the GZ), but does not assume that the target + * door file has not changed out from under us, so that is explicitly rechecked. + * + * This also assumes the parent has already locked handle. + */ +static int +zdoor_create(dtree_entry_t *entry) +{ + int status = ZDOOR_OK; + zoneid_t zid = -1; + zdoor_handle_t handle = NULL; + + if (entry == NULL) { + zdoor_debug("zdoor_create: NULL arguments"); + return (ZDOOR_ARGS_ERROR); + } + + zdoor_debug("zdoor_create: entry=%p, zone=%s, service=%s", + entry, entry->dte_parent->zte_zonename, entry->dte_service); + + handle = entry->dte_parent->zte_parent; + + zid = getzoneidbyname(entry->dte_parent->zte_zonename); + if (zid < 0) { + zdoor_info("zdoor_create: %s is a non-existient zone", + entry->dte_parent->zte_zonename); + return (ZDOOR_ERROR); + } + if (!zdoor_zone_is_running(zid)) { + zdoor_debug("zdoor_create: %s is not running", + entry->dte_parent->zte_zonename); + return (ZDOOR_ZONE_NOT_RUNNING); + } + + entry->dte_door = door_create(_callback, entry, 0); + zdoor_info("zdoor_create: door_create returned %d", entry->dte_door); + if (entry->dte_door < 0) { + zdoor_stop(entry); + return (ZDOOR_ERROR); + } + + status = zdoor_fattach(zid, entry->dte_service, entry->dte_door, 0); + + zdoor_debug("zdoor_create: returning %d", status); + return (status); +} + + +/* + * door_visitor(entry) is a callback from the ztree code that checks whether + * or not we should be taking some action on a given door. Note that the + * callpath to this API is: + * SYSTEM -> + * zone_monitor -> + * ztree_walk -> + * door_visitor + * + * Which is important to note that this API assumes that all things needing + * locking are locked by a parent caller (which is the zone_monitor). + */ +static void +zdoor_visitor(dtree_entry_t *entry) +{ + if (entry == NULL) { + zdoor_info("zdoor_visitor: entered with NULL entry"); + return; + } + + zdoor_debug("zdoor_visitor: entered for entry=%p, service=%s", + entry, entry->dte_service); + + if (entry->dte_parent->zte_action == ZDOOR_ACTION_STOP) { + zdoor_debug(" stopping zdoor"); + zdoor_stop(entry); + } else if (entry->dte_parent->zte_action == ZDOOR_ACTION_START) { + zdoor_debug(" starting zdoor"); + if (zdoor_create(entry) != ZDOOR_OK) { + zdoor_error("door_visitor: Unable to restart zdoor\n"); + } + } +} + +/* + * zone_monitor(zonename, zid, newstate, oldstate, when, cookie) is our + * registered callback with libzonecfg to notify us of any changes to a + * given zone. This activates a walk on all doors for a zone iff the state + * is changing from running or into running. + */ +static int +zone_monitor(const char *zonename, zoneid_t zid, const char *newstate, + const char *oldstate, hrtime_t when, void *p) +{ + zdoor_handle_t handle = (zdoor_handle_t)p; + ztree_entry_t *entry = NULL; + + if (handle == NULL) { + zdoor_warn("zone_monitor: entered with NULL handle?"); + return (-1); + } + + zdoor_info("zone_monitor: zone=%s, zid=%d, newst=%s, oldst=%s, p=%p", + zonename, zid, newstate, oldstate, p); + + (void) pthread_mutex_lock(&(handle->zdh_lock)); + entry = ztree_zone_find(handle, zonename); + if (entry != NULL) { + zdoor_debug(" found entry in ztree"); + entry->zte_action = ZDOOR_ACTION_NOOP; + if (strcmp("running", newstate) == 0) { + if (strcmp("ready", oldstate) == 0) + entry->zte_action = ZDOOR_ACTION_START; + } else if (strcmp("shutting_down", newstate) == 0) { + if (strcmp("running", oldstate) == 0) + entry->zte_action = ZDOOR_ACTION_STOP; + } + zdoor_debug(" set state to: %d", entry->zte_action); + if (entry->zte_action != ZDOOR_ACTION_NOOP) + ztree_walk_doors(handle, zonename); + } + (void) pthread_mutex_unlock(&(handle->zdh_lock)); + + zdoor_info("zone_monitor: returning"); + return (0); +} + +zdoor_handle_t +zdoor_handle_init() +{ + zdoor_handle_t handle = NULL; + + zdoor_debug("zdoor_handle_init entered"); + + handle = (zdoor_handle_t)calloc(1, sizeof (struct zdoor_handle)); + if (handle == NULL) { + OUT_OF_MEMORY(); + return (NULL); + } + + (void) pthread_mutex_init(&(handle->zdh_lock), NULL); + handle->zdh_zonecfg_handle = zonecfg_notify_bind(zone_monitor, handle); + if (handle->zdh_zonecfg_handle == NULL) { + zdoor_error("zonecfg_notify_bind failure: %s", strerror(errno)); + return (NULL); + } + + zdoor_debug("zdoor_handle_init returning %p", handle); + return (handle); +} + +void +zdoor_handle_destroy(zdoor_handle_t handle) +{ + if (handle == NULL) { + zdoor_debug("zdoor_handle_destroy: NULL arguments"); + return; + } + + zdoor_debug("zdoor_handle_destroy: handle=%p", handle); + + (void) pthread_mutex_lock(&(handle->zdh_lock)); + zonecfg_notify_unbind(handle->zdh_zonecfg_handle); + (void) pthread_mutex_unlock(&(handle->zdh_lock)); + (void) pthread_mutex_destroy(&(handle->zdh_lock)); + free(handle); +} + +/* + * zdoor_open(zone, service, biscuit, callback) is the main public facing API in + * libzdoor. It will open a door with the name .[service] under + * [zonepath]/root/var/tmp, where [zonepath] is resolved on the fly. Note this + * API can only be invoked from the global zone, and will not allow you to open + * a zdoor in the global zone. + */ +int +zdoor_open(zdoor_handle_t handle, const char *zonename, const char *service, + void *biscuit, zdoor_callback callback) +{ + zdoor_cookie_t *zdoor_cookie = NULL; + int rc = -1; + int status = ZDOOR_OK; + zoneid_t zid = -1; + dtree_entry_t *entry = NULL; + + if (handle == NULL || zonename == NULL || + service == NULL || callback == NULL) { + zdoor_debug("zdoor_open: NULL arguments"); + return (ZDOOR_ARGS_ERROR); + } + zdoor_debug("zdoor_open: entered: handle=%p, zone=%s, service=%s", + handle, zonename, service); + + if (getzoneid() != GLOBAL_ZONEID) { + zdoor_warn("zdoor_open: not invoked from global zone"); + return (ZDOOR_NOT_GLOBAL_ZONE); + } + + + zid = getzoneidbyname(zonename); + if (zid < 0) { + zdoor_info("zdoor_open: %s is a non-existent zone", zonename); + return (ZDOOR_ARGS_ERROR); + } + + if (zid == GLOBAL_ZONEID) { + zdoor_warn("zdoor_open: zdoors not allowed in global zone"); + return (ZDOOR_ZONE_FORBIDDEN); + } + + if (!zdoor_zone_is_running(zid)) { + zdoor_info("zdoor_open: %s is not running", zonename); + return (ZDOOR_ZONE_NOT_RUNNING); + } + + zdoor_cookie = zdoor_cookie_create(zonename, service, biscuit); + if (zdoor_cookie == NULL) { + OUT_OF_MEMORY(); + return (ZDOOR_OUT_OF_MEMORY); + } + + (void) pthread_mutex_lock(&(handle->zdh_lock)); + rc = ztree_zone_add(handle, zonename, zdoor_visitor); + if (rc != ZTREE_SUCCESS && rc != ZTREE_ALREADY_EXISTS) { + zdoor_debug("zdoor_open: unable to add zone to ztree: %d", rc); + status = ZDOOR_ERROR; + goto out; + } + rc = ztree_door_add(handle, zonename, service, callback, + zdoor_cookie); + if (rc != ZTREE_SUCCESS) { + zdoor_debug("zdoor_open: unable to add door to ztree: %d", rc); + if (rc == ZTREE_ALREADY_EXISTS) { + zdoor_warn("service %s already has a zdoor", service); + } + status = ZDOOR_ERROR; + goto out; + } + + entry = ztree_door_find(handle, zonename, service); + if (entry == NULL) { + zdoor_debug("zdoor_open: unable to find door in ztree?"); + status = ZDOOR_ERROR; + goto out; + } + if (zdoor_create(entry) != ZDOOR_OK) { + zdoor_info("zdoor_open: zdoor_create failed."); + status = ZDOOR_ERROR; + goto out; + } +out: + if (status != ZDOOR_OK) { + zdoor_debug("zdoor_open: status not ok, stopping and cleaning"); + zdoor_stop(entry); + ztree_door_remove(handle, entry); + zdoor_cookie_free(zdoor_cookie); + } + (void) pthread_mutex_unlock(&(handle->zdh_lock)); + zdoor_debug("zdoor_open: returning %d", status); + return (status); +} + +/* + * zdoor_close(zone, service) unregisters a previously created zdoor, and + * returns the biscuit provided at creation time, so the caller can free it. + * Returns NULL on any error. + */ +void * +zdoor_close(zdoor_handle_t handle, const char *zonename, const char *service) +{ + dtree_entry_t *entry = NULL; + zdoor_cookie_t *cookie = NULL; + void *biscuit = NULL; + + if (handle == NULL || zonename == NULL || service == NULL) { + zdoor_debug("zdoor_close: NULL arguments"); + return (NULL); + } + + zdoor_debug("zdoor_close: entered handle=%p, zone=%s, service=%s", + handle, zonename, service); + + (void) pthread_mutex_lock(&(handle->zdh_lock)); + + entry = ztree_door_find(handle, zonename, service); + if (entry != NULL) { + zdoor_debug("zdoor_close: found door in ztree, stopping"); + zdoor_stop(entry); + cookie = ztree_door_remove(handle, entry); + if (cookie != NULL) { + biscuit = cookie->zdc_biscuit; + zdoor_cookie_free(cookie); + } + } else { + zdoor_debug("zdoor_close: didn't find door in ztree"); + } + + (void) pthread_mutex_unlock(&(handle->zdh_lock)); + + zdoor_debug("zdoor_close: returning %p", biscuit); + return (biscuit); +} diff --git a/usr/src/lib/libzdoor/common/zerror.c b/usr/src/lib/libzdoor/common/zerror.c new file mode 100644 index 0000000000..5ccb449e1b --- /dev/null +++ b/usr/src/lib/libzdoor/common/zerror.c @@ -0,0 +1,117 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2011 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <pthread.h> +#include <sys/types.h> +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "zerror.h" + +static const char *PREFIX = "%s ZDOOR:%s:T(%d): "; + +static const char *DEBUG_ENV_VAR = "ZDOOR_TRACE"; + +static boolean_t +is_debug_enabled() +{ + boolean_t enabled = B_FALSE; + const char *_envp = getenv(DEBUG_ENV_VAR); + if (_envp != NULL && atoi(_envp) >= 2) + enabled = B_TRUE; + + return (enabled); +} + +static boolean_t +is_info_enabled() +{ + boolean_t enabled = B_FALSE; + const char *_envp = getenv(DEBUG_ENV_VAR); + if (_envp != NULL && atoi(_envp) >= 1) + enabled = B_TRUE; + + return (enabled); +} + +void +zdoor_debug(const char *fmt, ...) +{ + va_list alist; + + if (!is_debug_enabled()) + return; + + va_start(alist, fmt); + + (void) fprintf(stderr, PREFIX, __TIME__, "DEBUG", pthread_self()); + (void) vfprintf(stderr, fmt, alist); + (void) fprintf(stderr, "\n"); + va_end(alist); +} + +void +zdoor_info(const char *fmt, ...) +{ + va_list alist; + + if (!is_info_enabled()) + return; + + va_start(alist, fmt); + + (void) fprintf(stderr, PREFIX, __TIME__, "INFO", pthread_self()); + (void) vfprintf(stderr, fmt, alist); + (void) fprintf(stderr, "\n"); + va_end(alist); +} + +void +zdoor_warn(const char *fmt, ...) +{ + va_list alist; + + va_start(alist, fmt); + + (void) fprintf(stderr, PREFIX, __TIME__, "WARN", pthread_self()); + (void) vfprintf(stderr, fmt, alist); + (void) fprintf(stderr, "\n"); + va_end(alist); +} + +void +zdoor_error(const char *fmt, ...) +{ + va_list alist; + + va_start(alist, fmt); + + (void) fprintf(stderr, PREFIX, __TIME__, "ERROR", pthread_self()); + (void) vfprintf(stderr, fmt, alist); + (void) fprintf(stderr, "\n"); + va_end(alist); +} diff --git a/usr/src/lib/print/libprint/common/list.h b/usr/src/lib/libzdoor/common/zerror.h index cb9b62df78..afc848fcea 100644 --- a/usr/src/lib/print/libprint/common/list.h +++ b/usr/src/lib/libzdoor/common/zerror.h @@ -19,32 +19,30 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2011 Joyent, Inc. All rights reserved. * Use is subject to license terms. */ -#ifndef _LIST_H -#define _LIST_H +#ifndef _ZERROR_H +#define _ZERROR_H -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/va_list.h> +#include <stdio.h> +#include <stdlib.h> #ifdef __cplusplus extern "C" { #endif -#define VFUNC_T int (*)(void *, __va_list) /* for casting */ -#define COMP_T int (*)(void *, void *) /* for casting */ +extern void zdoor_debug(const char *fmt, ...); +extern void zdoor_info(const char *fmt, ...); +extern void zdoor_warn(const char *fmt, ...); +extern void zdoor_error(const char *fmt, ...); -extern void **list_append(void **, void *); -extern void **list_append_unique(void **, void *, int (*)(void *, void*)); -extern void **list_concatenate(void **, void **); -extern void * list_locate(void **, int (*)(void *, void *), void *); -extern int list_iterate(void **, int (*)(void *, __va_list), ...); +#define OUT_OF_MEMORY() \ + zdoor_error("Out of Memory at %s:%d", __FILE__, __LINE__) #ifdef __cplusplus } #endif -#endif /* _LIST_H */ +#endif /* _ZERROR_H */ diff --git a/usr/src/lib/libzdoor/common/ztree.c b/usr/src/lib/libzdoor/common/ztree.c new file mode 100644 index 0000000000..25c67f62fb --- /dev/null +++ b/usr/src/lib/libzdoor/common/ztree.c @@ -0,0 +1,344 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2011 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include <search.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "zerror.h" +#include "ztree.h" + + +/* + * ztree is just a helpful wrapper over a tsearch binary tree that deals with + * all of the libzdoor types. + * + * So what this ztree actually is is a tree of trees. The outer tree is a tree + * of zones, and each node holds a tree of doors. + */ + +/* + * _ztree_compare(p1, p2) is the tsearch callback for comparing the "outer" + * tree (e.g., the one of zones). + */ +static int +_ztree_compare(const void *p1, const void *p2) +{ + ztree_entry_t *z1 = (ztree_entry_t *)p1; + ztree_entry_t *z2 = (ztree_entry_t *)p2; + + if (z1 == NULL && z2 == NULL) + return (0); + if (z1 == NULL && z2 != NULL) + return (-1); + if (z1 != NULL && z2 == NULL) + return (1); + + return (strcmp(z1->zte_zonename, z2->zte_zonename)); +} + +/* + * _dtree_compare(p1, p2) is the tsearch callback for comparing the "inner" + * tree (e.g., the one of doors). + */ +static int +_dtree_compare(const void *p1, const void *p2) +{ + dtree_entry_t *d1 = (dtree_entry_t *)p1; + dtree_entry_t *d2 = (dtree_entry_t *)p2; + + if (d1 == NULL && d2 == NULL) + return (0); + if (d1 == NULL && d2 != NULL) + return (-1); + if (d1 != NULL && d2 == NULL) + return (1); + + return (strcmp(d1->dte_service, d2->dte_service)); +} + +static void +ztree_entry_free(ztree_entry_t *entry) +{ + if (entry == NULL) + return; + + if (entry->zte_zonename != NULL) + free(entry->zte_zonename); + + free(entry); +} + +static void +dtree_entry_free(dtree_entry_t *entry) +{ + if (entry == NULL) + return; + + if (entry->dte_service) + free(entry->dte_service); + + free(entry); +} + + +/* + * ztree_zone_add inserts a new zone into the tree iff + * there is not already an entry for that zone. This method returns one of + * four possible return codes, ZTREE_SUCCESS on :), ZTREE_ARGUMENT_ERROR if + * zone is NULL, ZTREE_ERROR if there is internal failure (e.g., OOM), and + * ZTREE_ALREADY_EXISTS if the zone is already in the tree. + */ +int +ztree_zone_add(struct zdoor_handle *handle, const char *zonename, +ztree_door_visitor visitor) +{ + ztree_entry_t *entry = NULL; + void *ret = NULL; + int status = ZTREE_SUCCESS; + + if (handle == NULL || zonename == NULL) + return (ZTREE_ARGUMENT_ERROR); + + entry = (ztree_entry_t *)calloc(1, sizeof (ztree_entry_t)); + if (entry == NULL) { + OUT_OF_MEMORY(); + return (ZTREE_ERROR); + } + entry->zte_zonename = strdup(zonename); + if (entry->zte_zonename == NULL) { + ztree_entry_free(entry); + OUT_OF_MEMORY(); + return (ZTREE_ERROR); + } + entry->zte_action = ZDOOR_ACTION_NOOP; + entry->zte_parent = handle; + entry->zte_visitor = visitor; + + ret = tsearch(entry, &(handle->zdh_ztree), _ztree_compare); + if (ret == NULL) { + ztree_entry_free(entry); + status = ZTREE_ERROR; + OUT_OF_MEMORY(); + } else if ((*(ztree_entry_t **)ret) != entry) { + ztree_entry_free(entry); + status = ZTREE_ALREADY_EXISTS; + } + + return (status); +} + + +/* + * ztree_zone_find returns the entry in the "outer" tree representing + * this zone, if it exists, NULL otherwise. + */ +ztree_entry_t * +ztree_zone_find(struct zdoor_handle *handle, const char *zonename) +{ + ztree_entry_t key = {0}; + void *ret = NULL; + + if (handle == NULL || zonename == NULL) + return (NULL); + + key.zte_zonename = (char *)zonename; + ret = tfind(&key, &(handle->zdh_ztree), _ztree_compare); + + return (ret != NULL ? *(ztree_entry_t **)ret : NULL); +} + + +/* + * ztree_zone_remove removes an entry from the "outer" zone iff the + * zone exists. The cookie set by the creator is returned. + */ +void +ztree_zone_remove(struct zdoor_handle *handle, ztree_entry_t *entry) +{ + if (handle == NULL || entry == NULL) + return; + + tdelete(entry, &(handle->zdh_ztree), _ztree_compare); + ztree_entry_free(entry); +} + + +/* + * ztree_door_add inserts a new door into the inner tree iff + * there is not already an entry for that door. This method returns one of + * four possible return codes, ZTREE_SUCCESS on :), ZTREE_ARGUMENT_ERROR if + * zone is NULL, ZTREE_ERROR if there is internal failure (e.g., OOM), and + * ZTREE_ALREADY_EXISTS if the door is already in the tree. + */ +int +ztree_door_add(struct zdoor_handle *handle, const char *zonename, +const char *service, zdoor_callback callback, zdoor_cookie_t *cookie) +{ + dtree_entry_t *entry = NULL; + ztree_entry_t *znode = NULL; + void *ret = NULL; + int status = ZTREE_SUCCESS; + + if (handle == NULL || zonename == NULL || service == NULL) + return (ZTREE_ARGUMENT_ERROR); + + znode = ztree_zone_find(handle, zonename); + if (znode == NULL) + return (ZTREE_NOT_FOUND); + + entry = (dtree_entry_t *)calloc(1, sizeof (dtree_entry_t)); + if (entry == NULL) { + OUT_OF_MEMORY(); + return (ZTREE_ERROR); + } + entry->dte_parent = znode; + entry->dte_callback = callback; + entry->dte_cookie = cookie; + entry->dte_service = strdup(service); + if (entry->dte_service == NULL) { + free(entry); + OUT_OF_MEMORY(); + return (ZTREE_ERROR); + } + + ret = tsearch(entry, &(znode->zte_door_tree), _dtree_compare); + if (ret == NULL) { + dtree_entry_free(entry); + OUT_OF_MEMORY(); + status = ZTREE_ERROR; + } else if ((*(dtree_entry_t **)ret) != entry) { + dtree_entry_free(entry); + status = ZTREE_ALREADY_EXISTS; + } else { + znode->zte_num_doors++; + } + + return (status); +} + + +/* + * ztree_door_find returns the entry in the "inner" tree + * representing this zone, if it exists, NULL otherwise. + */ +dtree_entry_t * +ztree_door_find(struct zdoor_handle *handle, const char *zonename, +const char *service) +{ + dtree_entry_t key = {0}; + ztree_entry_t *znode = NULL; + void *ret = NULL; + + if (handle == NULL || zonename == NULL || service == NULL) + return (NULL); + + znode = ztree_zone_find(handle, zonename); + if (znode == NULL) + return (NULL); + + key.dte_service = (char *)service; + ret = tfind(&key, &(znode->zte_door_tree), _dtree_compare); + + return (ret != NULL ? *(dtree_entry_t **)ret : NULL); +} + + +/* + * ztree_door_remove(zone, door) removes a node from the inner tree iff + * both the door and zone exist. Note this frees the node as well. The + * cookie set by the creator is returned. + */ +zdoor_cookie_t * +ztree_door_remove(struct zdoor_handle *handle, dtree_entry_t *entry) +{ + zdoor_cookie_t *cookie = NULL; + ztree_entry_t *znode = NULL; + + if (handle == NULL || entry == NULL) + return (NULL); + + znode = entry->dte_parent; + cookie = entry->dte_cookie; + + tdelete(entry, &(znode->zte_door_tree), _dtree_compare); + dtree_entry_free(entry); + + znode->zte_num_doors--; + if (znode->zte_num_doors == 0) { + zdoor_debug("ztree: zone %s has no doors left, removing", + znode->zte_zonename); + ztree_zone_remove(handle, znode); + } + + return (cookie); +} + + +/* + * _ztree_door_visitor(nodep, which, depth) is the private function we use + * to wrap up tsearch's goofy API. We're really just using this to ensure + * zdoor doesn't get called > 1 times for a given entity in the ztree. + */ +static void +_ztree_door_visitor(const void *nodep, const VISIT which, const int depth) +{ + dtree_entry_t *entry = *(dtree_entry_t **)nodep; + + if (entry == NULL) + return; + + switch (which) { + case preorder: + case endorder: + break; + case postorder: + case leaf: + if (entry->dte_parent->zte_visitor != NULL) + entry->dte_parent->zte_visitor(entry); + break; + } +} + + +/* + * ztree_walk_doors(zone) will proceed to visit every node in the "inner" tree + * for this zone, and callback the visitor that was registered on tree creation. + */ +void +ztree_walk_doors(struct zdoor_handle *handle, const char *zonename) +{ + ztree_entry_t *znode = NULL; + + if (handle == NULL || zonename == NULL) + return; + + znode = ztree_zone_find(handle, zonename); + if (znode == NULL) + return; + + twalk(znode->zte_door_tree, _ztree_door_visitor); +} diff --git a/usr/src/lib/libzdoor/common/ztree.h b/usr/src/lib/libzdoor/common/ztree.h new file mode 100644 index 0000000000..b46dace287 --- /dev/null +++ b/usr/src/lib/libzdoor/common/ztree.h @@ -0,0 +1,88 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2011 Joyent, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _ZTREE_H +#define _ZTREE_H + +#include <zdoor.h> +#include <zone.h> +#include "zdoor-int.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct dtree_entry; + +typedef void (*ztree_door_visitor)(struct dtree_entry *entry); + +typedef struct ztree_entry { + char *zte_zonename; + zdoor_action_t zte_action; + int zte_num_doors; + void *zte_door_tree; + ztree_door_visitor zte_visitor; + struct zdoor_handle *zte_parent; +} ztree_entry_t; + +typedef struct dtree_entry { + char *dte_service; + int dte_door; + zdoor_callback dte_callback; + zdoor_cookie_t *dte_cookie; + ztree_entry_t *dte_parent; +} dtree_entry_t; + +#define ZTREE_SUCCESS 0 +#define ZTREE_ERROR -1 +#define ZTREE_ARGUMENT_ERROR -2 +#define ZTREE_ALREADY_EXISTS -3 +#define ZTREE_NOT_FOUND -4 + +extern int ztree_zone_add(struct zdoor_handle *handle, + const char *zonename, ztree_door_visitor visitor); + +extern ztree_entry_t *ztree_zone_find(struct zdoor_handle *handle, + const char *zonename); + +extern void ztree_zone_remove(struct zdoor_handle *handle, + ztree_entry_t *entry); + +extern int ztree_door_add(struct zdoor_handle *handle, const char *zonename, + const char *service, zdoor_callback callback, zdoor_cookie_t *cookie); + +extern dtree_entry_t *ztree_door_find(struct zdoor_handle *handle, + const char *zonename, const char *service); + +extern zdoor_cookie_t *ztree_door_remove(struct zdoor_handle *handle, + dtree_entry_t *entry); + +extern void ztree_walk_doors(struct zdoor_handle *handle, const char *zonename); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZTREE_H */ diff --git a/usr/src/lib/libzdoor/i386/Makefile b/usr/src/lib/libzdoor/i386/Makefile new file mode 100644 index 0000000000..2bfe8001d9 --- /dev/null +++ b/usr/src/lib/libzdoor/i386/Makefile @@ -0,0 +1,31 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +# Copyright 2011 Joyent, Inc. All rights reserved. +# Use is subject to license terms. +# +# ident "%Z%%M% %I% %E% SMI" +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h index cb84b62c34..87ac9e9861 100644 --- a/usr/src/lib/libzfs/common/libzfs.h +++ b/usr/src/lib/libzfs/common/libzfs.h @@ -63,6 +63,7 @@ typedef enum zfs_error { EZFS_PROPTYPE, /* property does not apply to dataset type */ EZFS_PROPNONINHERIT, /* property is not inheritable */ EZFS_PROPSPACE, /* bad quota or reservation */ + EZFS_PROPCACHED, /* prop unavail since cachedprops flag set */ EZFS_BADTYPE, /* dataset is not of appropriate type */ EZFS_BUSY, /* pool or dataset is busy */ EZFS_EXISTS, /* pool or dataset already exists */ @@ -183,6 +184,7 @@ extern libzfs_handle_t *zpool_get_handle(zpool_handle_t *); extern libzfs_handle_t *zfs_get_handle(zfs_handle_t *); extern void libzfs_print_on_error(libzfs_handle_t *, boolean_t); +extern void libzfs_set_cachedprops(libzfs_handle_t *, boolean_t); extern void zfs_save_arguments(int argc, char **, char *, int); extern int zpool_log_history(libzfs_handle_t *, const char *); @@ -265,7 +267,7 @@ extern int zpool_label_disk(libzfs_handle_t *, zpool_handle_t *, char *); */ extern int zpool_set_prop(zpool_handle_t *, const char *, const char *); extern int zpool_get_prop(zpool_handle_t *, zpool_prop_t, char *, - size_t proplen, zprop_source_t *); + size_t proplen, zprop_source_t *, boolean_t); extern uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t, zprop_source_t *); diff --git a/usr/src/lib/libzfs/common/libzfs_dataset.c b/usr/src/lib/libzfs/common/libzfs_dataset.c index 58af6dfa04..3371af7ee1 100644 --- a/usr/src/lib/libzfs/common/libzfs_dataset.c +++ b/usr/src/lib/libzfs/common/libzfs_dataset.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved. * Copyright 2012 Nexenta Systems, Inc. All rights reserved. @@ -328,6 +329,10 @@ get_stats_ioctl(zfs_handle_t *zhp, zfs_cmd_t *zc) { libzfs_handle_t *hdl = zhp->zfs_hdl; + if (hdl->libzfs_cachedprops && + libzfs_cmd_set_cachedprops(hdl, zc) != 0) + return (-1); + (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name)); while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, zc) != 0) { @@ -1824,6 +1829,11 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src, case ZFS_PROP_NORMALIZE: case ZFS_PROP_UTF8ONLY: case ZFS_PROP_CASE: + if (zhp->zfs_hdl->libzfs_cachedprops) { + return (zfs_error(zhp->zfs_hdl, EZFS_PROPCACHED, + "property unavailable since not cached")); + } + if (!zfs_prop_valid_for_type(prop, zhp->zfs_head_type) || zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) return (-1); @@ -2060,6 +2070,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, char *str; const char *strval; boolean_t received = zfs_is_recvd_props_mode(zhp); + boolean_t printerr; /* * Check to see if this property applies to our object @@ -2070,6 +2081,16 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, if (received && zfs_prop_readonly(prop)) return (-1); + if (zhp->zfs_hdl->libzfs_cachedprops && + zfs_prop_cacheable(prop)) { + printerr = zhp->zfs_hdl->libzfs_printerr; + libzfs_print_on_error(zhp->zfs_hdl, B_FALSE); + (void) zfs_error(zhp->zfs_hdl, EZFS_PROPCACHED, + "property unavailable since not cached"); + libzfs_print_on_error(zhp->zfs_hdl, printerr); + return (-1); + } + if (src) *src = ZPROP_SRC_NONE; @@ -2127,8 +2148,8 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, } if ((zpool_get_prop(zhp->zpool_hdl, - ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL)) || - (strcmp(root, "-") == 0)) + ZPOOL_PROP_ALTROOT, buf, MAXPATHLEN, NULL, + B_FALSE)) || (strcmp(root, "-") == 0)) root[0] = '\0'; /* * Special case an alternate root of '/'. This will diff --git a/usr/src/lib/libzfs/common/libzfs_impl.h b/usr/src/lib/libzfs/common/libzfs_impl.h index 576b2af5d2..62793dcda1 100644 --- a/usr/src/lib/libzfs/common/libzfs_impl.h +++ b/usr/src/lib/libzfs/common/libzfs_impl.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. */ @@ -79,6 +80,7 @@ struct libzfs_handle { libzfs_fru_t **libzfs_fru_hash; libzfs_fru_t *libzfs_fru_list; char libzfs_chassis_id[256]; + boolean_t libzfs_cachedprops; }; #define ZFSSHARE_MISS 0x01 /* Didn't find entry in cache */ @@ -149,6 +151,7 @@ int zpool_standard_error_fmt(libzfs_handle_t *, int, const char *, ...); int get_dependents(libzfs_handle_t *, boolean_t, const char *, char ***, size_t *); zfs_handle_t *make_dataset_handle_zc(libzfs_handle_t *, zfs_cmd_t *); +int libzfs_cmd_set_cachedprops(libzfs_handle_t *, zfs_cmd_t *); int zprop_parse_value(libzfs_handle_t *, nvpair_t *, int, zfs_type_t, diff --git a/usr/src/lib/libzfs/common/libzfs_iter.c b/usr/src/lib/libzfs/common/libzfs_iter.c index be5767f542..48333df7d9 100644 --- a/usr/src/lib/libzfs/common/libzfs_iter.c +++ b/usr/src/lib/libzfs/common/libzfs_iter.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2010 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. */ @@ -110,6 +111,10 @@ zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) if (zhp->zfs_type != ZFS_TYPE_FILESYSTEM) return (0); + if (zhp->zfs_hdl->libzfs_cachedprops && + libzfs_cmd_set_cachedprops(zhp->zfs_hdl, &zc) != 0) + return (-1); + if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) return (-1); @@ -120,9 +125,8 @@ zfs_iter_filesystems(zfs_handle_t *zhp, zfs_iter_f func, void *data) * that the pool has since been removed. */ if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl, - &zc)) == NULL) { + &zc)) == NULL) continue; - } if ((ret = func(nzhp, data)) != 0) { zcmd_free_nvlists(&zc); @@ -146,15 +150,19 @@ zfs_iter_snapshots(zfs_handle_t *zhp, zfs_iter_f func, void *data) if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) return (0); + if (zhp->zfs_hdl->libzfs_cachedprops && + libzfs_cmd_set_cachedprops(zhp->zfs_hdl, &zc) != 0) + return (-1); + if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0) return (-1); + while ((ret = zfs_do_list_ioctl(zhp, ZFS_IOC_SNAPSHOT_LIST_NEXT, &zc)) == 0) { if ((nzhp = make_dataset_handle_zc(zhp->zfs_hdl, - &zc)) == NULL) { + &zc)) == NULL) continue; - } if ((ret = func(nzhp, data)) != 0) { zcmd_free_nvlists(&zc); diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c index 19d1ff7bdb..0fd5f5738c 100644 --- a/usr/src/lib/libzfs/common/libzfs_pool.c +++ b/usr/src/lib/libzfs/common/libzfs_pool.c @@ -23,6 +23,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ #include <ctype.h> @@ -211,7 +212,7 @@ zpool_state_to_name(vdev_state_t state, vdev_aux_t aux) */ int zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len, - zprop_source_t *srctype) + zprop_source_t *srctype, boolean_t literal) { uint64_t intval; const char *strval; @@ -271,6 +272,12 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len, case PROP_TYPE_NUMBER: intval = zpool_get_prop_int(zhp, prop, &src); + if (literal && prop != ZPOOL_PROP_HEALTH) { + (void) snprintf(buf, len, "%llu", + (u_longlong_t)intval); + break; + } + switch (prop) { case ZPOOL_PROP_SIZE: case ZPOOL_PROP_ALLOCATED: @@ -310,6 +317,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len, default: (void) snprintf(buf, len, "%llu", intval); } + break; case PROP_TYPE_INDEX: @@ -376,7 +384,7 @@ zpool_is_bootable(zpool_handle_t *zhp) char bootfs[ZPOOL_MAXNAMELEN]; return (zpool_get_prop(zhp, ZPOOL_PROP_BOOTFS, bootfs, - sizeof (bootfs), NULL) == 0 && strncmp(bootfs, "-", + sizeof (bootfs), NULL, B_FALSE) == 0 && strncmp(bootfs, "-", sizeof (bootfs)) != 0); } @@ -774,7 +782,7 @@ zpool_expand_proplist(zpool_handle_t *zhp, zprop_list_t **plp) if (entry->pl_prop != ZPROP_INVAL && zpool_get_prop(zhp, entry->pl_prop, buf, sizeof (buf), - NULL) == 0) { + NULL, B_FALSE) == 0) { if (strlen(buf) > entry->pl_width) entry->pl_width = strlen(buf); } @@ -3958,9 +3966,7 @@ supported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf) uint_t children, c; verify(nvlist_lookup_string(config, ZPOOL_CONFIG_TYPE, &type) == 0); - if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 || - strcmp(type, VDEV_TYPE_FILE) == 0 || - strcmp(type, VDEV_TYPE_LOG) == 0 || + if (strcmp(type, VDEV_TYPE_FILE) == 0 || strcmp(type, VDEV_TYPE_HOLE) == 0 || strcmp(type, VDEV_TYPE_MISSING) == 0) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, @@ -3979,8 +3985,12 @@ supported_dump_vdev_type(libzfs_handle_t *hdl, nvlist_t *config, char *errbuf) } /* - * check if this zvol is allowable for use as a dump device; zero if - * it is, > 0 if it isn't, < 0 if it isn't a zvol + * Check if this zvol is allowable for use as a dump device; zero if + * it is, > 0 if it isn't, < 0 if it isn't a zvol. + * + * Allowable storage configurations include mirrors, all raidz variants, and + * pools with log, cache, and spare devices. Pools which are backed by files or + * have missing/hole vdevs are not suitable. */ int zvol_check_dump_config(char *arg) @@ -4042,12 +4052,6 @@ zvol_check_dump_config(char *arg) verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, &top, &toplevels) == 0); - if (toplevels != 1) { - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, - "'%s' has multiple top level vdevs"), poolname); - (void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf); - goto out; - } if (!supported_dump_vdev_type(hdl, top[0], errbuf)) { goto out; diff --git a/usr/src/lib/libzfs/common/libzfs_util.c b/usr/src/lib/libzfs/common/libzfs_util.c index 41e25e9100..8706a6fdbb 100644 --- a/usr/src/lib/libzfs/common/libzfs_util.c +++ b/usr/src/lib/libzfs/common/libzfs_util.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. * Copyright (c) 2012 by Delphix. All rights reserved. */ @@ -81,6 +82,9 @@ libzfs_error_description(libzfs_handle_t *hdl) return (dgettext(TEXT_DOMAIN, "property cannot be inherited")); case EZFS_PROPSPACE: return (dgettext(TEXT_DOMAIN, "invalid quota or reservation")); + case EZFS_PROPCACHED: + return (dgettext(TEXT_DOMAIN, "property unavailable since " + "cachedprops flag set")); case EZFS_BADTYPE: return (dgettext(TEXT_DOMAIN, "operation not applicable to " "datasets of this type")); @@ -609,6 +613,42 @@ libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr) hdl->libzfs_printerr = printerr; } +/* + * Set the value of the cachedprops flag. If the cachedprops flag is set, + * operations which get ZFS properties will only retrieve a property if the + * property is cached somewhere in memory. + * + * Consumers of libzfs should take care when setting this flag, as they will + * prevent themselves from listing the full set of ZFS properties. + * + * ZFS properties which always require disk I/O are ZPL properties (utf8only, + * normalization, etc.) and the volsize and volblocksize properties for volumes. + */ +void +libzfs_set_cachedprops(libzfs_handle_t *hdl, boolean_t cachedprops) +{ + hdl->libzfs_cachedprops = cachedprops; +} + +/* + * Adds a src nvlist to a zfs_cmd_t which specifies that only cached (i.e., will + * not require a disk access) properties should be retrieved. + */ +int +libzfs_cmd_set_cachedprops(libzfs_handle_t *hdl, zfs_cmd_t *zc) +{ + nvlist_t *nvl; + int ret; + + if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || + nvlist_add_boolean_value(nvl, "cachedpropsonly", B_TRUE) != 0) + return (no_memory(hdl)); + + ret = zcmd_write_src_nvlist(hdl, zc, nvl); + nvlist_free(nvl); + return (ret); +} + libzfs_handle_t * libzfs_init(void) { @@ -644,6 +684,8 @@ libzfs_init(void) zpool_feature_init(); libzfs_mnttab_init(hdl); + hdl->libzfs_cachedprops = B_FALSE; + return (hdl); } diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers index 1cc52f5f79..d2ce523cf8 100644 --- a/usr/src/lib/libzfs/common/mapfile-vers +++ b/usr/src/lib/libzfs/common/mapfile-vers @@ -21,6 +21,7 @@ # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. # Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright (c) 2012 by Delphix. All rights reserved. +# Copyright (c) 2012, Joyent, Inc. All rights reserved. # # MAPFILE HEADER START # @@ -59,6 +60,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { libzfs_init; libzfs_mnttab_cache; libzfs_print_on_error; + libzfs_set_cachedprops; spa_feature_table; zfs_allocatable_devs; zfs_asprintf; @@ -101,6 +103,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { zfs_path_to_zhandle; zfs_promote; zfs_prop_align_right; + zfs_prop_cacheable; zfs_prop_column_name; zfs_prop_default_numeric; zfs_prop_default_string; diff --git a/usr/src/lib/libzonecfg/Makefile.com b/usr/src/lib/libzonecfg/Makefile.com index 4c94fe6dd6..ce29f58a9b 100644 --- a/usr/src/lib/libzonecfg/Makefile.com +++ b/usr/src/lib/libzonecfg/Makefile.com @@ -35,6 +35,7 @@ LDLIBS += -lc -lsocket -lnsl -luuid -lnvpair -lsysevent -lsec -lbrand \ $(DYNLIB) := LDLIBS += -lxml2 SRCDIR = ../common +CPPFLAGS += -I$(ADJUNCT_PROTO)/usr/include/libxml2 -I$(SRCDIR) -D_REENTRANT CPPFLAGS += -I/usr/include/libxml2 -I$(SRCDIR) -D_REENTRANT CERRWARN += -_gcc=-Wno-uninitialized CERRWARN += -_gcc=-Wno-parentheses diff --git a/usr/src/lib/libzonecfg/common/getzoneent.c b/usr/src/lib/libzonecfg/common/getzoneent.c index 8155f7272a..76664fcc92 100644 --- a/usr/src/lib/libzonecfg/common/getzoneent.c +++ b/usr/src/lib/libzonecfg/common/getzoneent.c @@ -403,14 +403,6 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) */ if (ze->zone_state >= 0) { zone_state = zone_state_str(ze->zone_state); - - /* - * If the caller is uninstalling this zone, - * then wipe out the uuid. The zone's contents - * are no longer known. - */ - if (ze->zone_state < ZONE_STATE_INSTALLED) - zone_uuid = ""; } /* If a new name is supplied, use it. */ @@ -419,6 +411,12 @@ putzoneent(struct zoneent *ze, zoneent_op_t operation) if (ze->zone_path[0] != '\0') zone_path = ze->zone_path; + + /* If new UUID provided, replace it */ + if (!uuid_is_null(ze->zone_uuid)) { + uuid_unparse(ze->zone_uuid, uuidstr); + zone_uuid = uuidstr; + } break; case PZE_REMOVE: diff --git a/usr/src/lib/libzonecfg/common/libzonecfg.c b/usr/src/lib/libzonecfg/common/libzonecfg.c index 9a664b8824..71da0ffb9a 100644 --- a/usr/src/lib/libzonecfg/common/libzonecfg.c +++ b/usr/src/lib/libzonecfg/common/libzonecfg.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent Inc. All rights reserved. */ #include <libsysevent.h> @@ -77,6 +78,8 @@ #define ZONE_EVENT_PING_SUBCLASS "ping" #define ZONE_EVENT_PING_PUBLISHER "solaris" +#define DEBUGID_FILE "/etc/zones/did.txt" + /* Hard-code the DTD element/attribute/entity names just once, here. */ #define DTD_ELEM_ATTR (const xmlChar *) "attr" #define DTD_ELEM_COMMENT (const xmlChar *) "comment" @@ -84,6 +87,7 @@ #define DTD_ELEM_FS (const xmlChar *) "filesystem" #define DTD_ELEM_FSOPTION (const xmlChar *) "fsoption" #define DTD_ELEM_NET (const xmlChar *) "network" +#define DTD_ELEM_NETATTR (const xmlChar *) "net-attr" #define DTD_ELEM_RCTL (const xmlChar *) "rctl" #define DTD_ELEM_RCTLVALUE (const xmlChar *) "rctl-value" #define DTD_ELEM_ZONE (const xmlChar *) "zone" @@ -103,10 +107,12 @@ #define DTD_ATTR_IPTYPE (const xmlChar *) "ip-type" #define DTD_ATTR_DEFROUTER (const xmlChar *) "defrouter" #define DTD_ATTR_DIR (const xmlChar *) "directory" +#define DTD_ATTR_GNIC (const xmlChar *) "global-nic" #define DTD_ATTR_LIMIT (const xmlChar *) "limit" #define DTD_ATTR_LIMITPRIV (const xmlChar *) "limitpriv" #define DTD_ATTR_BOOTARGS (const xmlChar *) "bootargs" #define DTD_ATTR_SCHED (const xmlChar *) "scheduling-class" +#define DTD_ATTR_MAC (const xmlChar *) "mac-addr" #define DTD_ATTR_MATCH (const xmlChar *) "match" #define DTD_ATTR_NAME (const xmlChar *) "name" #define DTD_ATTR_PHYSICAL (const xmlChar *) "physical" @@ -116,6 +122,7 @@ #define DTD_ATTR_SPECIAL (const xmlChar *) "special" #define DTD_ATTR_TYPE (const xmlChar *) "type" #define DTD_ATTR_VALUE (const xmlChar *) "value" +#define DTD_ATTR_VLANID (const xmlChar *) "vlan-id" #define DTD_ATTR_ZONEPATH (const xmlChar *) "zonepath" #define DTD_ATTR_NCPU_MIN (const xmlChar *) "ncpu_min" #define DTD_ATTR_NCPU_MAX (const xmlChar *) "ncpu_max" @@ -128,6 +135,7 @@ #define DTD_ATTR_MODE (const xmlChar *) "mode" #define DTD_ATTR_ACL (const xmlChar *) "acl" #define DTD_ATTR_BRAND (const xmlChar *) "brand" +#define DTD_ATTR_DID (const xmlChar *) "debugid" #define DTD_ATTR_HOSTID (const xmlChar *) "hostid" #define DTD_ATTR_USER (const xmlChar *) "user" #define DTD_ATTR_AUTHS (const xmlChar *) "auths" @@ -174,9 +182,12 @@ static struct alias { {ALIAS_MAXSEMIDS, "zone.max-sem-ids", "privileged", "deny", 0}, {ALIAS_MAXLOCKEDMEM, "zone.max-locked-memory", "privileged", "deny", 0}, {ALIAS_MAXSWAP, "zone.max-swap", "privileged", "deny", 0}, + {ALIAS_MAXPHYSMEM, "zone.max-physical-memory", "privileged", "deny", + 1048576}, {ALIAS_SHARES, "zone.cpu-shares", "privileged", "none", 0}, {ALIAS_CPUCAP, "zone.cpu-cap", "privileged", "deny", 0}, {ALIAS_MAXPROCS, "zone.max-processes", "privileged", "deny", 100}, + {ALIAS_ZFSPRI, "zone.zfs-io-priority", "privileged", "none", 0}, {NULL, NULL, NULL, NULL, 0} }; @@ -2064,6 +2075,32 @@ zonecfg_ifname_exists(sa_family_t af, char *ifname) } /* + * Turn an addr that looks like f:2:0:44:5:6C into 0f:02:00:44:05:6c + * We're expecting a dst of at least MAXMACADDRLEN size here. + */ +static void +normalize_mac_addr(char *dst, const char *src, int len) +{ + char *p, *e, *sep = ""; + long n; + char buf[MAXMACADDRLEN], tmp[4]; + + *dst = '\0'; + (void) strlcpy(buf, src, sizeof (buf)); + p = strtok(buf, ":"); + while (p != NULL) { + n = strtol(p, &e, 16); + if (*e != NULL || n > 0xff) + return; + (void) snprintf(tmp, sizeof (tmp), "%s%02x", sep, n); + (void) strlcat(dst, tmp, len); + + sep = ":"; + p = strtok(NULL, ":"); + } +} + +/* * Determines whether there is a net resource with the physical interface, IP * address, and default router specified by 'tabptr' in the zone configuration * to which 'handle' refers. 'tabptr' must have an interface, an address, a @@ -2082,13 +2119,18 @@ zonecfg_ifname_exists(sa_family_t af, char *ifname) int zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) { - xmlNodePtr cur; + xmlNodePtr cur, val; xmlNodePtr firstmatch; int err; char address[INET6_ADDRSTRLEN]; char physical[LIFNAMSIZ]; + char mac[MAXMACADDRLEN]; + char norm_mac[MAXMACADDRLEN]; + char gnic[LIFNAMSIZ]; size_t addrspec; /* nonzero if tabptr has IP addr */ size_t physspec; /* nonzero if tabptr has interface */ + size_t macspec; /* nonzero if tabptr has mac addr */ + size_t gnicspec; /* nonzero if tabptr has gnic */ size_t defrouterspec; /* nonzero if tabptr has def. router */ size_t allowed_addrspec; zone_iptype_t iptype; @@ -2100,17 +2142,20 @@ zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) * Determine the fields that will be searched. There must be at least * one. * - * zone_nwif_address, zone_nwif_physical, and zone_nwif_defrouter are + * zone_nwif_address, zone_nwif_physical, zone_nwif_defrouter, + * zone_nwif_mac, zone_nwif_vlan_id and zone_nwif_gnic are * arrays, so no NULL checks are necessary. */ addrspec = strlen(tabptr->zone_nwif_address); physspec = strlen(tabptr->zone_nwif_physical); + macspec = strlen(tabptr->zone_nwif_mac); + gnicspec = strlen(tabptr->zone_nwif_gnic); defrouterspec = strlen(tabptr->zone_nwif_defrouter); allowed_addrspec = strlen(tabptr->zone_nwif_allowed_address); if (addrspec != 0 && allowed_addrspec != 0) return (Z_INVAL); /* can't specify both */ if (addrspec == 0 && physspec == 0 && defrouterspec == 0 && - allowed_addrspec == 0) + allowed_addrspec == 0 && macspec == 0 && gnicspec == 0) return (Z_INSUFFICIENT_SPEC); if ((err = operation_prep(handle)) != Z_OK) @@ -2137,6 +2182,19 @@ zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) physical, sizeof (physical)) != Z_OK || strcmp(tabptr->zone_nwif_physical, physical) != 0)) continue; + if (iptype == ZS_EXCLUSIVE && macspec != 0) { + if (fetchprop(cur, DTD_ATTR_MAC, mac, sizeof (mac)) != + Z_OK) + continue; + normalize_mac_addr(norm_mac, mac, sizeof (norm_mac)); + if (strcmp(tabptr->zone_nwif_mac, norm_mac) != 0) + continue; + } + if (iptype == ZS_EXCLUSIVE && gnicspec != 0 && + (fetchprop(cur, DTD_ATTR_GNIC, gnic, + sizeof (gnic)) != Z_OK || + strcmp(tabptr->zone_nwif_gnic, gnic) != 0)) + continue; if (iptype == ZS_SHARED && addrspec != 0 && (fetchprop(cur, DTD_ATTR_ADDRESS, address, sizeof (address)) != Z_OK || @@ -2179,6 +2237,21 @@ zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) return (err); if (iptype == ZS_EXCLUSIVE && + (err = fetchprop(cur, DTD_ATTR_MAC, tabptr->zone_nwif_mac, + sizeof (tabptr->zone_nwif_mac))) != Z_OK) + return (err); + + if (iptype == ZS_EXCLUSIVE && + (err = fetchprop(cur, DTD_ATTR_VLANID, tabptr->zone_nwif_vlan_id, + sizeof (tabptr->zone_nwif_vlan_id))) != Z_OK) + return (err); + + if (iptype == ZS_EXCLUSIVE && + (err = fetchprop(cur, DTD_ATTR_GNIC, tabptr->zone_nwif_gnic, + sizeof (tabptr->zone_nwif_gnic))) != Z_OK) + return (err); + + if (iptype == ZS_EXCLUSIVE && (err = fetchprop(cur, DTD_ATTR_ALLOWED_ADDRESS, tabptr->zone_nwif_allowed_address, sizeof (tabptr->zone_nwif_allowed_address))) != Z_OK) @@ -2189,13 +2262,40 @@ zonecfg_lookup_nwif(zone_dochandle_t handle, struct zone_nwiftab *tabptr) sizeof (tabptr->zone_nwif_defrouter))) != Z_OK) return (err); + tabptr->zone_nwif_attrp = NULL; + for (val = cur->xmlChildrenNode; val != NULL; val = val->next) { + struct zone_res_attrtab *valptr; + + valptr = (struct zone_res_attrtab *)malloc( + sizeof (struct zone_res_attrtab)); + if (valptr == NULL) + return (Z_NOMEM); + + valptr->zone_res_attr_name[0] = + valptr->zone_res_attr_value[0] = '\0'; + if (zonecfg_add_res_attr(&(tabptr->zone_nwif_attrp), valptr) + != Z_OK) { + free(valptr); + break; + } + + if ((fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name, + sizeof (valptr->zone_res_attr_name)) != Z_OK)) + break; + if ((fetchprop(val, DTD_ATTR_VALUE, + valptr->zone_res_attr_value, + sizeof (valptr->zone_res_attr_value)) != Z_OK)) + break; + } + return (Z_OK); } static int zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) { - xmlNodePtr newnode, cur = handle->zone_dh_cur; + xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode; + struct zone_res_attrtab *valptr; int err; newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_NET, NULL); @@ -2211,13 +2311,40 @@ zonecfg_add_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) tabptr->zone_nwif_physical)) != Z_OK) return (err); /* - * Do not add this property when it is not set, for backwards - * compatibility and because it is optional. + * Do not add these properties when they are not set, for backwards + * compatibility and because they are optional. */ if ((strlen(tabptr->zone_nwif_defrouter) > 0) && ((err = newprop(newnode, DTD_ATTR_DEFROUTER, tabptr->zone_nwif_defrouter)) != Z_OK)) return (err); + if (strlen(tabptr->zone_nwif_mac) > 0 && + (err = newprop(newnode, DTD_ATTR_MAC, + tabptr->zone_nwif_mac)) != Z_OK) + return (err); + if (strlen(tabptr->zone_nwif_vlan_id) > 0 && + (err = newprop(newnode, DTD_ATTR_VLANID, + tabptr->zone_nwif_vlan_id)) != Z_OK) + return (err); + if (strlen(tabptr->zone_nwif_gnic) > 0 && + (err = newprop(newnode, DTD_ATTR_GNIC, + tabptr->zone_nwif_gnic)) != Z_OK) + return (err); + + for (valptr = tabptr->zone_nwif_attrp; valptr != NULL; + valptr = valptr->zone_res_attr_next) { + valnode = xmlNewTextChild(newnode, NULL, DTD_ELEM_NETATTR, + NULL); + err = newprop(valnode, DTD_ATTR_NAME, + valptr->zone_res_attr_name); + if (err != Z_OK) + return (err); + err = newprop(valnode, DTD_ATTR_VALUE, + valptr->zone_res_attr_value); + if (err != Z_OK) + return (err); + } + return (Z_OK); } @@ -2242,7 +2369,8 @@ static int zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) { xmlNodePtr cur = handle->zone_dh_cur; - boolean_t addr_match, phys_match, allowed_addr_match; + boolean_t addr_match, phys_match, allowed_addr_match, mac_match, + gnic_match; for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { if (xmlStrcmp(cur->name, DTD_ELEM_NET)) @@ -2254,8 +2382,13 @@ zonecfg_delete_nwif_core(zone_dochandle_t handle, struct zone_nwiftab *tabptr) tabptr->zone_nwif_allowed_address); phys_match = match_prop(cur, DTD_ATTR_PHYSICAL, tabptr->zone_nwif_physical); + mac_match = match_prop(cur, DTD_ATTR_MAC, + tabptr->zone_nwif_mac); + gnic_match = match_prop(cur, DTD_ATTR_GNIC, + tabptr->zone_nwif_gnic); - if ((addr_match || allowed_addr_match) && phys_match) { + if ((addr_match || allowed_addr_match || mac_match || + gnic_match) && phys_match) { xmlUnlinkNode(cur); xmlFreeNode(cur); return (Z_OK); @@ -2304,6 +2437,58 @@ zonecfg_modify_nwif( return (Z_OK); } +void +zonecfg_free_res_attr_list(struct zone_res_attrtab *valtab) +{ + if (valtab == NULL) + return; + zonecfg_free_res_attr_list(valtab->zone_res_attr_next); + free(valtab); +} + +int +zonecfg_add_res_attr(struct zone_res_attrtab **headptr, + struct zone_res_attrtab *valtabptr) +{ + struct zone_res_attrtab *last, *old, *new; + + last = *headptr; + for (old = last; old != NULL; old = old->zone_res_attr_next) + last = old; /* walk to the end of the list */ + new = valtabptr; /* alloc'd by caller */ + new->zone_res_attr_next = NULL; + if (last == NULL) + *headptr = new; + else + last->zone_res_attr_next = new; + return (Z_OK); +} + +int +zonecfg_remove_res_attr(struct zone_res_attrtab **headptr, + struct zone_res_attrtab *valtabptr) +{ + struct zone_res_attrtab *last, *this, *next; + + last = *headptr; + for (this = last; this != NULL; this = this->zone_res_attr_next) { + if (strcmp(this->zone_res_attr_name, + valtabptr->zone_res_attr_name) == 0 && + strcmp(this->zone_res_attr_value, + valtabptr->zone_res_attr_value) == 0) { + next = this->zone_res_attr_next; + if (this == *headptr) + *headptr = next; + else + last->zone_res_attr_next = next; + free(this); + return (Z_OK); + } else + last = this; + } + return (Z_NO_PROPERTY_ID); +} + /* * Must be a comma-separated list of alpha-numeric file system names. */ @@ -2322,7 +2507,7 @@ zonecfg_valid_fs_allowed(const char *fsallowedp) while (*cp != '\0') { p = cp; while (*p != '\0' && *p != ',') { - if (!isalnum(*p)) + if (!isalnum(*p) && *p != '-') return (Z_INVALID_PROPERTY); p++; } @@ -2453,7 +2638,7 @@ zonecfg_set_hostid(zone_dochandle_t handle, const char *hostidp) int zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) { - xmlNodePtr cur, firstmatch; + xmlNodePtr cur, val, firstmatch; int err; char match[MAXPATHLEN]; @@ -2498,13 +2683,40 @@ zonecfg_lookup_dev(zone_dochandle_t handle, struct zone_devtab *tabptr) sizeof (tabptr->zone_dev_match))) != Z_OK) return (err); + tabptr->zone_dev_attrp = NULL; + for (val = cur->xmlChildrenNode; val != NULL; val = val->next) { + struct zone_res_attrtab *valptr; + + valptr = (struct zone_res_attrtab *)malloc( + sizeof (struct zone_res_attrtab)); + if (valptr == NULL) + return (Z_NOMEM); + + valptr->zone_res_attr_name[0] = + valptr->zone_res_attr_value[0] = '\0'; + if (zonecfg_add_res_attr(&(tabptr->zone_dev_attrp), valptr) + != Z_OK) { + free(valptr); + break; + } + + if ((fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name, + sizeof (valptr->zone_res_attr_name)) != Z_OK)) + break; + if ((fetchprop(val, DTD_ATTR_VALUE, + valptr->zone_res_attr_value, + sizeof (valptr->zone_res_attr_value)) != Z_OK)) + break; + } + return (Z_OK); } static int zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr) { - xmlNodePtr newnode, cur = handle->zone_dh_cur; + xmlNodePtr newnode, cur = handle->zone_dh_cur, valnode; + struct zone_res_attrtab *valptr; int err; newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_DEVICE, NULL); @@ -2513,6 +2725,21 @@ zonecfg_add_dev_core(zone_dochandle_t handle, struct zone_devtab *tabptr) tabptr->zone_dev_match)) != Z_OK) return (err); + for (valptr = tabptr->zone_dev_attrp; valptr != NULL; + valptr = valptr->zone_res_attr_next) { + valnode = xmlNewTextChild(newnode, NULL, DTD_ELEM_NETATTR, + NULL); + err = newprop(valnode, DTD_ATTR_NAME, + valptr->zone_res_attr_name); + if (err != Z_OK) + return (err); + err = newprop(valnode, DTD_ATTR_VALUE, + valptr->zone_res_attr_value); + if (err != Z_OK) + return (err); + } + + return (Z_OK); } @@ -4572,7 +4799,7 @@ get_pool_sched_class(char *poolname, char *class, int clsize) pool_conf_t *poolconf; pool_t *pool; pool_elem_t *pe; - pool_value_t *pv = pool_value_alloc(); + pool_value_t *pv; const char *sched_str; if (pool_get_status(&status) != PO_SUCCESS || status != POOL_ENABLED) @@ -4593,15 +4820,23 @@ get_pool_sched_class(char *poolname, char *class, int clsize) return (Z_NO_POOL); } + if ((pv = pool_value_alloc()) == NULL) { + (void) pool_conf_close(poolconf); + pool_conf_free(poolconf); + return (Z_NO_POOL); + } + pe = pool_to_elem(poolconf, pool); if (pool_get_property(poolconf, pe, "pool.scheduler", pv) != POC_STRING) { (void) pool_conf_close(poolconf); + pool_value_free(pv); pool_conf_free(poolconf); return (Z_NO_ENTRY); } (void) pool_value_get_string(pv, &sched_str); (void) pool_conf_close(poolconf); + pool_value_free(pv); pool_conf_free(poolconf); if (strlcpy(class, sched_str, clsize) >= clsize) return (Z_TOO_BIG); @@ -4710,7 +4945,8 @@ zonecfg_setnwifent(zone_dochandle_t handle) int zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr) { - xmlNodePtr cur; + xmlNodePtr cur, val; + struct zone_res_attrtab *valptr; int err; if (handle == NULL) @@ -4746,6 +4982,24 @@ zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr) return (err); } + if ((err = fetchprop(cur, DTD_ATTR_MAC, tabptr->zone_nwif_mac, + sizeof (tabptr->zone_nwif_mac))) != Z_OK) { + handle->zone_dh_cur = handle->zone_dh_top; + return (err); + } + + if ((err = fetchprop(cur, DTD_ATTR_VLANID, tabptr->zone_nwif_vlan_id, + sizeof (tabptr->zone_nwif_vlan_id))) != Z_OK) { + handle->zone_dh_cur = handle->zone_dh_top; + return (err); + } + + if ((err = fetchprop(cur, DTD_ATTR_GNIC, tabptr->zone_nwif_gnic, + sizeof (tabptr->zone_nwif_gnic))) != Z_OK) { + handle->zone_dh_cur = handle->zone_dh_top; + return (err); + } + if ((err = fetchprop(cur, DTD_ATTR_DEFROUTER, tabptr->zone_nwif_defrouter, sizeof (tabptr->zone_nwif_defrouter))) != Z_OK) { @@ -4753,6 +5007,29 @@ zonecfg_getnwifent(zone_dochandle_t handle, struct zone_nwiftab *tabptr) return (err); } + tabptr->zone_nwif_attrp = NULL; + for (val = cur->xmlChildrenNode; val != NULL; val = val->next) { + valptr = (struct zone_res_attrtab *)malloc( + sizeof (struct zone_res_attrtab)); + if (valptr == NULL) + return (Z_NOMEM); + + valptr->zone_res_attr_name[0] = + valptr->zone_res_attr_value[0] = '\0'; + if (zonecfg_add_res_attr(&(tabptr->zone_nwif_attrp), valptr) + != Z_OK) { + free(valptr); + break; + } + + if (fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name, + sizeof (valptr->zone_res_attr_name)) != Z_OK) + break; + if (fetchprop(val, DTD_ATTR_VALUE, valptr->zone_res_attr_value, + sizeof (valptr->zone_res_attr_value)) != Z_OK) + break; + } + handle->zone_dh_cur = cur->next; return (Z_OK); } @@ -4772,7 +5049,7 @@ zonecfg_setdevent(zone_dochandle_t handle) int zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr) { - xmlNodePtr cur; + xmlNodePtr cur, val; int err; if (handle == NULL) @@ -4795,6 +5072,31 @@ zonecfg_getdevent(zone_dochandle_t handle, struct zone_devtab *tabptr) return (err); } + tabptr->zone_dev_attrp = NULL; + for (val = cur->xmlChildrenNode; val != NULL; val = val->next) { + struct zone_res_attrtab *valptr; + + valptr = (struct zone_res_attrtab *)malloc( + sizeof (struct zone_res_attrtab)); + if (valptr == NULL) + return (Z_NOMEM); + + valptr->zone_res_attr_name[0] = + valptr->zone_res_attr_value[0] = '\0'; + if (zonecfg_add_res_attr(&(tabptr->zone_dev_attrp), valptr) + != Z_OK) { + free(valptr); + break; + } + + if ((fetchprop(val, DTD_ATTR_NAME, valptr->zone_res_attr_name, + sizeof (valptr->zone_res_attr_name)) != Z_OK)) + break; + if ((fetchprop(val, DTD_ATTR_VALUE, valptr->zone_res_attr_value, + sizeof (valptr->zone_res_attr_value)) != Z_OK)) + break; + } + handle->zone_dh_cur = cur->next; return (Z_OK); } @@ -5523,6 +5825,164 @@ zone_get_brand(char *zone_name, char *brandname, size_t rp_sz) } /* + * Atomically get a new zone_did value. The currently allocated value + * is stored in /etc/zones/did.txt. Lock the file, read the current value, + * increment, save the new value and unlock the file. Return the new value + * or -1 if there was an error. The ID namespace is large enough that we + * don't worry about recycling an ID when a zone is deleted. + */ +static zoneid_t +new_zone_did() +{ + int fd; + int len; + int val; + struct flock lck; + char buf[80]; + + if ((fd = open(DEBUGID_FILE, O_RDWR | O_CREAT, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) { + perror("new_zone_did open failed"); + return (-1); + } + + /* Initialize the lock. */ + lck.l_whence = SEEK_SET; + lck.l_start = 0; + lck.l_len = 0; + + /* Wait until we acquire an exclusive lock on the file. */ + lck.l_type = F_WRLCK; + if (fcntl(fd, F_SETLKW, &lck) == -1) { + perror("new_zone_did lock failed"); + (void) close(fd); + return (-1); + } + + /* Get currently allocated value */ + len = read(fd, buf, sizeof (buf)); + if (len == -1) { + perror("new_zone_did read failed"); + val = -1; + } else { + if (lseek(fd, 0L, SEEK_SET) == -1) { + perror("new_zone_did seek failed"); + val = -1; + } else { + if (len == 0) { + /* Just created the file, initialize at 1 */ + val = 1; + } else { + val = atoi(buf); + val++; + } + + (void) snprintf(buf, sizeof (buf), "%d\n", val); + len = strlen(buf); + + /* Save newly allocated value */ + if (write(fd, buf, len) == -1) { + perror("new_zone_did write failed"); + val = -1; + } + } + } + + /* Release the file lock. */ + lck.l_type = F_UNLCK; + if (fcntl(fd, F_SETLK, &lck) == -1) { + perror("new_zone_did unlock failed"); + val = -1; + } + + if (close(fd) != 0) + perror("new_zone_did close failed"); + + return (val); +} + +/* + * Called by zoneadmd to get the zone's debug ID. + * If the zone doesn't already have an ID, a new one is generated and + * persistently saved onto the zone. Normally either zoneadm or zonecfg + * will assign a new ID for the zone, so zoneadmd should never have to + * generate one, but we also handle that here just to be paranoid. + */ +zoneid_t +zone_get_did(char *zone_name) +{ + int res; + zoneid_t new_did; + zone_dochandle_t handle; + char did_str[80]; + + if ((handle = zonecfg_init_handle()) == NULL) + return (getpid()); + + if (zonecfg_get_handle((char *)zone_name, handle) != Z_OK) + return (getpid()); + + res = getrootattr(handle, DTD_ATTR_DID, did_str, sizeof (did_str)); + + /* If the zone already has an assigned debug ID, return it. */ + if (res == Z_OK && did_str[0] != '\0') { + zonecfg_fini_handle(handle); + return (atoi(did_str)); + } + + /* + * The zone doesn't have an assigned debug ID yet, generate one and + * save it as part of the zone definition. + */ + if ((new_did = new_zone_did()) == -1) { + /* + * We should really never hit this block of code. + * Generating a new ID failed for some reason. Use the current + * pid as a temporary ID so that the zone can continue to boot + * but we don't persistently save this temporary ID on the zone. + */ + zonecfg_fini_handle(handle); + return (getpid()); + } + + /* Now persistently save this new ID onto the zone. */ + (void) snprintf(did_str, sizeof (did_str), "%d", new_did); + (void) setrootattr(handle, DTD_ATTR_DID, did_str); + (void) zonecfg_save(handle); + + zonecfg_fini_handle(handle); + return (new_did); +} + +zoneid_t +zonecfg_get_did(zone_dochandle_t handle) +{ + char did_str[80]; + int err; + zoneid_t did; + + err = getrootattr(handle, DTD_ATTR_DID, did_str, sizeof (did_str)); + if (err == Z_OK && did_str[0] != '\0') + did = atoi(did_str); + else + did = -1; + + return (did); +} + +void +zonecfg_set_did(zone_dochandle_t handle) +{ + zoneid_t new_did; + char did_str[80]; + + if ((new_did = new_zone_did()) == -1) + return; + (void) snprintf(did_str, sizeof (did_str), "%d", new_did); + (void) setrootattr(handle, DTD_ATTR_DID, did_str); +} + +/* * Return the appropriate root for the active /dev. * For normal zone, the path is $ZONEPATH/root; * for scratch zone, the dev path is $ZONEPATH/lu. @@ -5805,6 +6265,30 @@ zonecfg_get_uuid(const char *zonename, uuid_t uuid) } /* + * Changes a zone's UUID to the given value. Returns an error if the UUID is + * malformed or if the zone cannot be located. + */ +int +zonecfg_set_uuid(const char *zonename, const char *zonepath, + const char *uuid) +{ + int err; + struct zoneent ze; + + bzero(&ze, sizeof (ze)); + ze.zone_state = -1; /* Preserve existing state in index */ + (void) strlcpy(ze.zone_name, zonename, sizeof (ze.zone_name)); + (void) strlcpy(ze.zone_path, zonepath, sizeof (ze.zone_path)); + if (uuid_parse((char *)uuid, ze.zone_uuid) == -1) + return (Z_INVALID_PROPERTY); + + if ((err = putzoneent(&ze, PZE_MODIFY)) != Z_OK) + return (err); + + return (Z_OK); +} + +/* * File-system convenience functions. */ boolean_t @@ -6838,131 +7322,49 @@ zonecfg_getpsetent(zone_dochandle_t handle, struct zone_psettab *tabptr) return (err); } -static int -add_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr) -{ - xmlNodePtr newnode, cur = handle->zone_dh_cur; - int err; - - newnode = xmlNewTextChild(cur, NULL, DTD_ELEM_MCAP, NULL); - if ((err = newprop(newnode, DTD_ATTR_PHYSCAP, tabptr->zone_physmem_cap)) - != Z_OK) - return (err); - - return (Z_OK); -} - -int -zonecfg_delete_mcap(zone_dochandle_t handle) -{ - int err; - xmlNodePtr cur = handle->zone_dh_cur; - - if ((err = operation_prep(handle)) != Z_OK) - return (err); - - for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { - if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) != 0) - continue; - - xmlUnlinkNode(cur); - xmlFreeNode(cur); - return (Z_OK); - } - return (Z_NO_RESOURCE_ID); -} - -int -zonecfg_modify_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr) -{ - int err; - - if (tabptr == NULL) - return (Z_INVAL); - - err = zonecfg_delete_mcap(handle); - /* it is ok if there is no mcap entry */ - if (err != Z_OK && err != Z_NO_RESOURCE_ID) - return (err); - - if ((err = add_mcap(handle, tabptr)) != Z_OK) - return (err); - - return (Z_OK); -} - +/* + * Cleanup obsolete constructs in the configuration. + * Return true of the config has been updated and must be commited. + */ int -zonecfg_lookup_mcap(zone_dochandle_t handle, struct zone_mcaptab *tabptr) +zonecfg_fix_obsolete(zone_dochandle_t handle) { + int res = 0; + int add_physmem_rctl = 0; xmlNodePtr cur; - int err; - - if (tabptr == NULL) - return (Z_INVAL); + char zone_physmem_cap[MAXNAMELEN]; - if ((err = operation_prep(handle)) != Z_OK) - return (err); + if (operation_prep(handle) != Z_OK) + return (res); + /* + * If an obsolete mcap entry exists, convert it to the rctl. + */ cur = handle->zone_dh_cur; for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) { if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) != 0) continue; - if ((err = fetchprop(cur, DTD_ATTR_PHYSCAP, - tabptr->zone_physmem_cap, - sizeof (tabptr->zone_physmem_cap))) != Z_OK) { - handle->zone_dh_cur = handle->zone_dh_top; - return (err); + + if (fetchprop(cur, DTD_ATTR_PHYSCAP, + zone_physmem_cap, sizeof (zone_physmem_cap)) == Z_OK) { + res = 1; + add_physmem_rctl = 1; } - return (Z_OK); + xmlUnlinkNode(cur); + xmlFreeNode(cur); + break; } - return (Z_NO_ENTRY); -} - -static int -getmcapent_core(zone_dochandle_t handle, struct zone_mcaptab *tabptr) -{ - xmlNodePtr cur; - int err; - - if (handle == NULL) - return (Z_INVAL); - - if ((cur = handle->zone_dh_cur) == NULL) - return (Z_NO_ENTRY); - - for (; cur != NULL; cur = cur->next) - if (xmlStrcmp(cur->name, DTD_ELEM_MCAP) == 0) - break; - if (cur == NULL) { - handle->zone_dh_cur = handle->zone_dh_top; - return (Z_NO_ENTRY); - } + if (add_physmem_rctl) { + uint64_t cap; + char *endp; - if ((err = fetchprop(cur, DTD_ATTR_PHYSCAP, tabptr->zone_physmem_cap, - sizeof (tabptr->zone_physmem_cap))) != Z_OK) { - handle->zone_dh_cur = handle->zone_dh_top; - return (err); + cap = strtoull(zone_physmem_cap, &endp, 10); + (void) zonecfg_set_aliased_rctl(handle, ALIAS_MAXPHYSMEM, cap); } - handle->zone_dh_cur = cur->next; - return (Z_OK); -} - -int -zonecfg_getmcapent(zone_dochandle_t handle, struct zone_mcaptab *tabptr) -{ - int err; - - if ((err = zonecfg_setent(handle)) != Z_OK) - return (err); - - err = getmcapent_core(handle, tabptr); - - (void) zonecfg_endent(handle); - - return (err); + return (res); } /* diff --git a/usr/src/lib/libzonecfg/common/mapfile-vers b/usr/src/lib/libzonecfg/common/mapfile-vers index b908a28174..7265b06a1f 100644 --- a/usr/src/lib/libzonecfg/common/mapfile-vers +++ b/usr/src/lib/libzonecfg/common/mapfile-vers @@ -20,6 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, Joyent Inc. All rights reserved. # # @@ -53,6 +54,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_add_fs_option; zonecfg_add_admin; zonecfg_add_nwif; + zonecfg_add_res_attr; zonecfg_add_pkg; zonecfg_add_pset; zonecfg_add_rctl; @@ -79,7 +81,6 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_delete_dev; zonecfg_delete_ds; zonecfg_delete_filesystem; - zonecfg_delete_mcap; zonecfg_delete_nwif; zonecfg_delete_pset; zonecfg_delete_rctl; @@ -104,7 +105,9 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_find_mounts; zonecfg_find_scratch; zonecfg_fini_handle; + zonecfg_fix_obsolete; zonecfg_free_fs_option_list; + zonecfg_free_res_attr_list; zonecfg_free_rctl_value_list; zonecfg_get_aliased_rctl; zonecfg_get_attach_handle; @@ -118,6 +121,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_get_bootargs; zonecfg_get_brand; zonecfg_get_dflt_sched_class; + zonecfg_get_did; zonecfg_getdevent; zonecfg_getdevperment; zonecfg_getdsent; @@ -127,7 +131,6 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_get_hostid; zonecfg_get_iptype; zonecfg_get_limitpriv; - zonecfg_getmcapent; zonecfg_get_name; zonecfg_get_name_by_uuid; zonecfg_getnwifent; @@ -160,7 +163,6 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_lookup_dev; zonecfg_lookup_ds; zonecfg_lookup_filesystem; - zonecfg_lookup_mcap; zonecfg_lookup_nwif; zonecfg_lookup_pset; zonecfg_lookup_rctl; @@ -169,7 +171,6 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_modify_dev; zonecfg_modify_ds; zonecfg_modify_filesystem; - zonecfg_modify_mcap; zonecfg_modify_nwif; zonecfg_modify_pset; zonecfg_modify_rctl; @@ -183,6 +184,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_ping_zoneadmd; zonecfg_release_lock_file; zonecfg_remove_fs_option; + zonecfg_remove_res_attr; zonecfg_remove_rctl_value; zonecfg_remove_userauths; zonecfg_reverse_scratch; @@ -196,6 +198,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_set_autoboot; zonecfg_set_bootargs; zonecfg_set_brand; + zonecfg_set_did; zonecfg_setdevent; zonecfg_setdevperment; zonecfg_setdsent; @@ -211,6 +214,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_set_root; zonecfg_set_sched; zonecfg_set_swinv; + zonecfg_set_uuid; zonecfg_set_zonepath; zonecfg_strerror; zonecfg_str_to_bytes; @@ -229,6 +233,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { zonecfg_verify_save; zonecfg_warn_poold; zone_get_brand; + zone_get_did; zone_get_devroot; zone_get_id; zone_get_rootpath; diff --git a/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 b/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 index d94bb09c5f..3c7198efef 100644 --- a/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 +++ b/usr/src/lib/libzonecfg/dtd/zonecfg.dtd.1 @@ -21,6 +21,7 @@ CDDL HEADER END Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2011, Joyent Inc. All rights reserved. --> @@ -46,14 +47,21 @@ <!ATTLIST inherited-pkg-dir directory CDATA #REQUIRED> -<!ELEMENT network EMPTY> +<!ELEMENT net-attr EMPTY> +<!ATTLIST net-attr name CDATA #REQUIRED + value CDATA #REQUIRED> + +<!ELEMENT network (net-attr)*> <!ATTLIST network address CDATA "" allowed-address CDATA "" defrouter CDATA "" - physical CDATA #REQUIRED> + global-nic CDATA "" + mac-addr CDATA "" + physical CDATA #REQUIRED + vlan-id CDATA ""> -<!ELEMENT device EMPTY> +<!ELEMENT device (net-attr)*> <!ATTLIST device match CDATA #REQUIRED> @@ -156,6 +164,7 @@ limitpriv CDATA "" bootargs CDATA "" brand CDATA "" + debugid CDATA "" scheduling-class CDATA "" fs-allowed CDATA "" version NMTOKEN #FIXED '1'> diff --git a/usr/src/lib/lvm/libsvm/Makefile.com b/usr/src/lib/lvm/libsvm/Makefile.com index 7df4a4b39f..2457a10b69 100644 --- a/usr/src/lib/lvm/libsvm/Makefile.com +++ b/usr/src/lib/lvm/libsvm/Makefile.com @@ -46,7 +46,7 @@ LDLIBS += -lmeta -ldevid -lc # XXX There isn't a lint library for libspmicommon. For now, we work # around this by only using the library when we build (as opposed to lint). # -all debug install := LDLIBS += -L/usr/snadm/lib -lspmicommon +all debug install := LDLIBS += -L$(ADJUNCT_PROTO)/usr/snadm/lib -lspmicommon DYNFLAGS += -R/usr/snadm/lib CPPFLAGS += -D_FILE_OFFSET_BITS=64 diff --git a/usr/src/lib/nsswitch/dns/Makefile.com b/usr/src/lib/nsswitch/dns/Makefile.com index 23c89c32f8..0366633c0c 100644 --- a/usr/src/lib/nsswitch/dns/Makefile.com +++ b/usr/src/lib/nsswitch/dns/Makefile.com @@ -22,8 +22,6 @@ # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# # lib/nsswitch/dns/Makefile.com LIBRARY = libnss_dns.a @@ -46,5 +44,5 @@ CPPFLAGS += -DNSS_DNS_LIBRESOLV=\"libresolv.so.2\" LINTFLAGS += -erroff=E_GLOBAL_COULD_BE_STATIC2 -LDLIBS += -lnsl +LDLIBS += -lnsl -lresolv_joy -lsocket DYNLIB1 = nss_dns.so$(VERS) diff --git a/usr/src/lib/nsswitch/dns/common/dns_common.c b/usr/src/lib/nsswitch/dns/common/dns_common.c index a9195f9f68..0195b1847c 100644 --- a/usr/src/lib/nsswitch/dns/common/dns_common.c +++ b/usr/src/lib/nsswitch/dns/common/dns_common.c @@ -22,22 +22,19 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ /* * dns_common.c */ #include "dns_common.h" - -#pragma weak dn_expand -#pragma weak res_ninit -#pragma weak res_ndestroy -#pragma weak res_nsearch -#pragma weak res_nclose -#pragma weak ns_get16 -#pragma weak ns_get32 -#pragma weak __ns_get16 -#pragma weak __ns_get32 +#include <sys/types.h> +#include <sys/socket.h> +#include <ifaddrs.h> +#include <net/if.h> #define DNS_ALIASES 0 #define DNS_ADDRLIST 1 @@ -321,6 +318,52 @@ name_is_alias(char *aliases_ptr, char *name_ptr) { return (NSS_NOTFOUND); } + +static int +_nss_has_interfaces(int *v4, int *v6) +{ + struct ifaddrs *ifp, *i; + struct in_addr in4; + struct in6_addr in6; + const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; + + *v4 = *v6 = 0; + + if (getifaddrs(&ifp) != 0) + return (-1); + + for (i = ifp; i != NULL; i = i->ifa_next) { + if (i->ifa_flags & IFF_LOOPBACK) + continue; + if ((i->ifa_flags & IFF_UP) == 0) + continue; + + if (i->ifa_addr->sa_family == AF_INET) { + if (*v4 != 0) + continue; + + if (((struct sockaddr_in *)i->ifa_addr)-> + sin_addr.s_addr == INADDR_ANY) + continue; + *v4 = 1; + } + + if (i->ifa_addr->sa_family == AF_INET6) { + if (*v6 != 0) + continue; + + if (memcmp(&in6addr_any, + &((struct sockaddr_in6 *)i->ifa_addr)->sin6_addr, + sizeof (struct in6_addr)) == 0) + continue; + *v6 = 1; + } + } + + freeifaddrs(ifp); + return (0); +} + /* * nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) * nss2 get hosts/ipnodes with ttl backend DNS search engine. @@ -331,13 +374,6 @@ name_is_alias(char *aliases_ptr, char *name_ptr) { * Additionally in the extended results a nssuint_t ttl is placed. * This ttl is the lessor of the ttl's extracted from the result. * - * ***Currently the first version of this API only performs simple - * single res_nsearch lookups for with T_A or T_AAAA results. - * Other searches are deferred to the generic API w/t ttls. - * - * This function is not a generic res_* operation. It only performs - * a single T_A or T_AAAA lookups*** - * * RETURNS: NSS_SUCCESS or NSS_ERROR * If an NSS_ERROR result is returned, nscd is expected * to resubmit the gethosts request using the old style @@ -384,11 +420,14 @@ _nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) int af; char *ap, *apc; int hlen = 0, alen, iplen, len, isans; + int has_v4 = 0, has_v6 = 0; + int flags, family, pass2 = 0; statp = &stat; (void) memset(statp, '\0', sizeof (struct __res_state)); - if (res_ninit(statp) == -1) + if (res_ninit(statp) == -1) { return (NSS_ERROR); + } ap = apc = (char *)aliases; alen = 0; @@ -404,33 +443,139 @@ _nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) return (NSS_ERROR); } + /* + * There may be flags set when we are handling ipnode. There are three + * different values for flags: + * + * o AI_V4MAPPED + * o AI_ALL + * o AI_ADDRCONFIG + * + * The first two only have a meaning when af_family is ipv6. The latter + * means something in both cases. These flags are documented in + * getipnodebyname(3SOCKET), though the combinations leave a little + * something to be desired. It would be great if we could actually use + * getipnodebyname directly here since it already knows how to handle + * this kind of logic; however, we're not quite so lucky. Ideally we + * would add such an interface to libresolv.so.2 to handle this kind of + * thing, but that's rather painful as well. We'll summarize what has to + * happen below: + * + * AI_ALL is only meaningful when AI_V4MAPPED is also specified. Both + * are ignored if the family is not AF_INET6 + * + * family == AF_INET, flags | AI_ADDRCONFIG + * - lookup A records iff we have v4 plumbed + * family == AF_INET, !(flags | AI_ADDRCONFIG) + * - lookup A records + * family == AF_INET6, flags == 0 || flags == AI_ALL + * - lookup AAAA records + * family == AF_INET6, flags | AI_V4MAPPED + * - lookup AAAA, if none, lookup A + * family == AF_INET6, flags | AI_ADDRCONFIG + * - lookup AAAA records if ipv6 + * family == AF_INET6, flags | AI_V4MAPPED && flags | AI_ALL + * - lookup AAAA records, lookup A records + * family == AF_INET6, flags | AI_V4MAPPED && flags | AI_ADDRCONFIG + * - lookup AAAA records if ipv6 + * - If no AAAA && ipv4 exists, lookup A + * family == AF_INET6, flags | AI_V4MAPPED && flags | AI_ADDRCONFIG && + * flags | AI_ALL + * - lookup AAAA records if ipv6 + * - loookup A records if ipv4 + */ if (ipnode) { /* initially only handle the simple cases */ - if (arg.key.ipnode.flags != 0) { - res_ndestroy(statp); - return (NSS_ERROR); - } name = arg.key.ipnode.name; - if (arg.key.ipnode.af_family == AF_INET6) - qtype = T_AAAA; - else - qtype = T_A; + flags = arg.key.ipnode.flags; + family = arg.key.ipnode.af_family; + if (flags != 0) { + /* + * Figure out our first pass. We'll determine if we need + * to do a second pass afterwards once we successfully + * finish our first pass. + */ + if ((flags & AI_ADDRCONFIG) != 0) { + if (_nss_has_interfaces(&has_v4, &has_v6) != + 0) { + res_ndestroy(statp); + return (NSS_ERROR); + } + /* Impossible situations... */ + if (family == AF_INET && has_v4 == 0) { + res_ndestroy(statp); + return (NSS_NOTFOUND); + } + if (family == AF_INET6 && has_v6 == 0 && + !(flags & AI_V4MAPPED)) { + res_ndestroy(statp); + return (NSS_NOTFOUND); + } + if (family == AF_INET6 && has_v6) + qtype = T_AAAA; + if (family == AF_INET || (family == AF_INET6 && + has_v6 == 0 && flags & AI_V4MAPPED)) + qtype = T_A; + } else { + has_v4 = has_v6 = 1; + if (family == AF_INET6) + qtype = T_AAAA; + else + qtype = T_A; + } + } else { + if (family == AF_INET6) + qtype = T_AAAA; + else + qtype = T_A; + } } else { name = arg.key.name; qtype = T_A; } + +searchagain: ret = res_nsearch(statp, name, C_IN, qtype, resbuf.buf, NS_MAXMSG); if (ret == -1) { - if (statp->res_h_errno == HOST_NOT_FOUND) { + /* + * We want to continue on unless we got NO_RECOVERY. Otherwise, + * HOST_NOT_FOUND, TRY_AGAIN, and NO_DATA all suggest to me that + * we should keep going. + */ + if (statp->res_h_errno == NO_RECOVERY) { + /* else lookup error - handle in general code */ + res_ndestroy(statp); + return (NSS_ERROR); + } + + /* + * We found something on our first pass. Make sure that we do + * not clobber this information. This ultimately means that we + * were successful. + */ + if (pass2 == 2) + goto out; + + if (pass2 == 1 || flags == 0 || family == AF_INET || + (family == AF_INET6 && !(flags & AI_V4MAPPED))) { pbuf->p_herrno = HOST_NOT_FOUND; pbuf->p_status = NSS_NOTFOUND; pbuf->data_len = 0; res_ndestroy(statp); return (NSS_NOTFOUND); } - /* else lookup error - handle in general code */ - res_ndestroy(statp); - return (NSS_ERROR); + if ((flags & AI_ADDRCONFIG) && !(flags & AI_ALL) && + has_v4 == 0) { + pbuf->p_herrno = HOST_NOT_FOUND; + pbuf->p_status = NSS_NOTFOUND; + pbuf->data_len = 0; + res_ndestroy(statp); + return (NSS_NOTFOUND); + } + qtype = T_A; + flags = 0; + pass2 = 1; + goto searchagain; } cp = resbuf.buf; @@ -579,6 +724,15 @@ _nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) *bptr++ = '\n'; blen++; } + + /* Depending on our flags we may need to go back another time. */ + if (qtype == T_AAAA && family == AF_INET6 && + ((flags & AI_V4MAPPED) != 0) && ((flags & AI_ALL) != 0) && has_v4) { + qtype = T_A; + pass2 = 2; /* Indicate that we found data this pass */ + goto searchagain; + } + /* Presumably the buffer is now filled. */ len = ROUND_UP(blen, sizeof (nssuint_t)); /* still room? */ @@ -587,6 +741,7 @@ _nss_dns_gethost_withttl(void *buffer, size_t bufsize, int ipnode) res_ndestroy(statp); return (NSS_ERROR); } +out: pbuf->ext_off = pbuf->data_off + len; pbuf->ext_len = sizeof (nssuint_t); pbuf->data_len = blen; diff --git a/usr/src/lib/nsswitch/dns/common/dns_common.h b/usr/src/lib/nsswitch/dns/common/dns_common.h index 717f56d70f..83d486cf57 100644 --- a/usr/src/lib/nsswitch/dns/common/dns_common.h +++ b/usr/src/lib/nsswitch/dns/common/dns_common.h @@ -31,8 +31,6 @@ #ifndef _DNS_COMMON_H #define _DNS_COMMON_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <ctype.h> #include <sys/types.h> @@ -43,7 +41,7 @@ #include <thread.h> #include <arpa/inet.h> #include <arpa/nameser.h> -#include <resolv.h> +#include <resolv_joy.h> #include <syslog.h> #include <nsswitch.h> #include <nss_common.h> diff --git a/usr/src/lib/nsswitch/dns/common/dns_mt.c b/usr/src/lib/nsswitch/dns/common/dns_mt.c index 128b1bde75..4af3f671c0 100644 --- a/usr/src/lib/nsswitch/dns/common/dns_mt.c +++ b/usr/src/lib/nsswitch/dns/common/dns_mt.c @@ -23,8 +23,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ /* * dns_mt.c @@ -49,52 +50,41 @@ static void _nss_dns_init(void); extern struct hostent *res_gethostbyname(const char *); -#pragma weak res_gethostbyname -#define RES_SET_NO_HOSTS_FALLBACK "__res_set_no_hosts_fallback" -extern void __res_set_no_hosts_fallback(void); -#pragma weak __res_set_no_hosts_fallback +#define RES_SET_NO_HOSTS_FALLBACK "__joy_res_set_no_hosts_fallback" +extern void __joy_res_set_no_hosts_fallback(void); -#define RES_UNSET_NO_HOSTS_FALLBACK "__res_unset_no_hosts_fallback" -extern void __res_unset_no_hosts_fallback(void); -#pragma weak __res_unset_no_hosts_fallback +#define RES_UNSET_NO_HOSTS_FALLBACK "__joy_res_unset_no_hosts_fallback" +extern void __joy_res_unset_no_hosts_fallback(void); #define RES_GET_RES "__res_get_res" extern struct __res_state *__res_get_res(void); -#pragma weak __res_get_res #define RES_ENABLE_MT "__res_enable_mt" extern int __res_enable_mt(void); -#pragma weak __res_enable_mt #define RES_DISABLE_MT "__res_disable_mt" extern int __res_disable_mt(void); -#pragma weak __res_disable_mt #define RES_GET_H_ERRNO "__res_get_h_errno" extern int *__res_get_h_errno(); -#pragma weak __res_get_h_errno -#define __H_ERRNO "__h_errno" -extern int *__h_errno(void); -#pragma weak __h_errno +#define __H_ERRNO "__joy_h_errno" +extern int *__joy_h_errno(void); -#define RES_OVERRIDE_RETRY "__res_override_retry" -extern int __res_override_retry(int); -#pragma weak __res_override_retry +#define RES_OVERRIDE_RETRY "__joy_res_override_retry" +extern int __joy_res_override_retry(int); static void __fallback_set_no_hosts(void); -static int *__fallback_h_errno(void); -static int __fallback_override_retry(int); static int __is_mt_safe(void); void (*set_no_hosts_fallback)(void) = __fallback_set_no_hosts; void (*unset_no_hosts_fallback)(void) = __fallback_set_no_hosts; struct __res_state *(*set_res_retry)() = 0; -int (*enable_mt)() = 0; -int (*disable_mt)() = 0; -int *(*get_h_errno)(void) = 0; -int (*override_retry)(int) = 0; +int (*enable_mt)() = __is_mt_safe; +int (*disable_mt)() = __is_mt_safe; +int *(*get_h_errno)(void) = __joy_h_errno; +int (*override_retry)(int) = __joy_res_override_retry; /* Usually set from the Makefile */ #ifndef NSS_DNS_LIBRESOLV @@ -106,91 +96,12 @@ extern int h_errno; mutex_t one_lane = DEFAULTMUTEX; +/* Because we link against libresolv_joy.so.2, this is relatively easy. */ void _nss_dns_init(void) { - void *reslib, (*f_void_ptr)(); - - /* If no libresolv library, then load one */ - if (res_gethostbyname == 0) { - if ((reslib = - dlopen(NSS_DNS_LIBRESOLV, RTLD_LAZY|RTLD_GLOBAL)) != 0) { - /* Turn off /etc/hosts fall back in libresolv */ - if ((f_void_ptr = (void (*)(void))dlsym(reslib, - RES_SET_NO_HOSTS_FALLBACK)) != 0) { - set_no_hosts_fallback = f_void_ptr; - } - if ((f_void_ptr = (void (*)(void))dlsym(reslib, - RES_SET_NO_HOSTS_FALLBACK)) != 0) { - unset_no_hosts_fallback = f_void_ptr; - } - /* Set number of resolver retries */ - if ((override_retry = (int (*)(int))dlsym(reslib, - RES_OVERRIDE_RETRY)) == 0) { - set_res_retry = - (struct __res_state *(*)(void))dlsym(reslib, - RES_GET_RES); - override_retry = __fallback_override_retry; - } - /* - * Select h_errno retrieval function. A BIND 8.2.2 - * libresolv.so.2 will have __h_errno, a BIND 8.1.2 - * one will have __res_get_h_errno, and other - * versions may have nothing at all. - * - * Also try to bind to the relevant MT enable/disable - * functions which are also dependent on the version - * of the BIND libresolv.so.2 being used. - */ - if ((get_h_errno = (int *(*)(void))dlsym(reslib, - __H_ERRNO)) != 0) { - /* BIND 8.2.2 libresolv.so.2 is MT safe. */ - enable_mt = __is_mt_safe; - disable_mt = __is_mt_safe; - } else { - if ((get_h_errno = - (int *(*)(void))dlsym(reslib, - RES_GET_H_ERRNO)) == 0) { - get_h_errno = __fallback_h_errno; - } - /* - * Pre-BIND 8.2.2 was not MT safe. Try to - * bind the MT enable/disable functions. - */ - if ((enable_mt = (int (*)(void))dlsym(reslib, - RES_ENABLE_MT)) != 0 && - (disable_mt = (int (*)(void))dlsym(reslib, - RES_DISABLE_MT)) == 0) { - enable_mt = 0; - } - } - } - } else { - /* Libresolv already loaded */ - if ((f_void_ptr = __res_set_no_hosts_fallback) != 0) { - set_no_hosts_fallback = f_void_ptr; - } - if ((f_void_ptr = __res_unset_no_hosts_fallback) != 0) { - unset_no_hosts_fallback = f_void_ptr; - } - if ((override_retry = __res_override_retry) == 0) { - set_res_retry = __res_get_res; - override_retry = __fallback_override_retry; - } - if ((get_h_errno = __h_errno) == 0 && - (get_h_errno = __res_get_h_errno) == 0) { - get_h_errno = __fallback_h_errno; - } - if (get_h_errno == __h_errno) { - enable_mt = __is_mt_safe; - disable_mt = __is_mt_safe; - } else { - if ((enable_mt = __res_enable_mt) != 0 && - (disable_mt = __res_disable_mt) == 0) { - enable_mt = 0; - } - } - } + enable_mt = __is_mt_safe; + disable_mt = __is_mt_safe; } @@ -228,36 +139,6 @@ __is_mt_safe(void) { } -/* - * Return pointer to the global h_errno variable - */ -static int * -__fallback_h_errno(void) { - return (&h_errno); -} - - -/* - * This function is called when the resolver library doesn't provide its - * own function to establish an override retry. If we can get a pointer - * to the per-thread _res (i.e., set_res_retry != 0), we set the retries - * directly, and return the previous number of retries. Otherwise, there's - * nothing to do. - */ -static int -__fallback_override_retry(int retry) { - struct __res_state *res; - int old_retry = 0; - - if (set_res_retry != 0) { - res = set_res_retry(); - old_retry = res->retry; - res->retry = retry; - } - return (old_retry); -} - - static void __fallback_set_no_hosts(void) { } diff --git a/usr/src/lib/nsswitch/dns/common/gethostent.c b/usr/src/lib/nsswitch/dns/common/gethostent.c index 648ea8ba01..d321dd24c6 100644 --- a/usr/src/lib/nsswitch/dns/common/gethostent.c +++ b/usr/src/lib/nsswitch/dns/common/gethostent.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * gethostent.c * @@ -53,12 +51,6 @@ static struct hostent *_gethostbyaddr(int *h_errnop, const char *addr, int len, int type); struct hostent *_nss_dns_gethostbyname2(int *h_errnop, const char *name); -#pragma weak res_gethostbyname -#pragma weak res_gethostbyname2 -#pragma weak res_gethostbyaddr -#pragma weak res_sethostent -#pragma weak res_endhostent - nss_backend_t *_nss_dns_constr(dns_backend_op_t ops[], int n_ops); nss_status_t __nss_dns_getbyaddr(dns_backend_ptr_t, void *); diff --git a/usr/src/lib/nsswitch/dns/common/gethostent6.c b/usr/src/lib/nsswitch/dns/common/gethostent6.c index ee85832073..f3efc4eae6 100644 --- a/usr/src/lib/nsswitch/dns/common/gethostent6.c +++ b/usr/src/lib/nsswitch/dns/common/gethostent6.c @@ -24,8 +24,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * This is the DNS backend for IPv6 addresses. * getbyname() is a local routine, but getbyaddr() actually shares the @@ -50,8 +48,6 @@ */ -#pragma weak res_endhostent - extern struct hostent *_gethostbyname(int *, const char *); extern struct hostent *_nss_dns_gethostbyname2(int *, const char *); diff --git a/usr/src/lib/pkcs11/pkcs11_tpm/Makefile.com b/usr/src/lib/pkcs11/pkcs11_tpm/Makefile.com index 22082a1fb8..0d723c023a 100644 --- a/usr/src/lib/pkcs11/pkcs11_tpm/Makefile.com +++ b/usr/src/lib/pkcs11/pkcs11_tpm/Makefile.com @@ -66,14 +66,14 @@ ROOTLIBDIR64=$(ROOT)/usr/lib/security/$(MACH64) LIBS=$(DYNLIB) $(DYNLIB64) -TSSROOT= +TSSROOT=$(ADJUNCT_PROTO) TSPILIBDIR=$(TSSROOT)/usr/lib TSPIINCDIR=$(TSSROOT)/usr/include TSSLIB=-L$(TSPILIBDIR) TSSLIB64=-L$(TSPILIBDIR)/$(MACH64) TSSINC=-I$(TSPIINCDIR) -LDLIBS += $(TSSLIB) -L/lib -lc -luuid -lmd -ltspi -lcrypto +LDLIBS += $(TSSLIB) -L$(ADJUNCT_PROTO)/lib -lc -luuid -lmd -ltspi -lsunw_crypto CPPFLAGS += -xCC -D_POSIX_PTHREAD_SEMANTICS $(TSSINC) CPPFLAGS64 += $(CPPFLAGS) C99MODE= $(C99_ENABLE) diff --git a/usr/src/lib/policykit/Makefile.policykit b/usr/src/lib/policykit/Makefile.policykit index 8b8cff0fe1..eca0c0d026 100644 --- a/usr/src/lib/policykit/Makefile.policykit +++ b/usr/src/lib/policykit/Makefile.policykit @@ -29,8 +29,11 @@ POLICYKIT_VERSION = 0.2 -POLICYKIT_DBUS_CPPFLAGS = -DDBUS_API_SUBJECT_TO_CHANGE -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -POLICYKIT_GLIB_CPPFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include +POLICYKIT_DBUS_CPPFLAGS = -DDBUS_API_SUBJECT_TO_CHANGE \ + -I$(ADJUNCT_PROTO)/usr/include/dbus-1.0 \ + -I$(ADJUNCT_PROTO)/usr/lib/dbus-1.0/include +POLICYKIT_GLIB_CPPFLAGS = -I$(ADJUNCT_PROTO)/usr/include/glib-2.0 \ + -I$(ADJUNCT_PROTO)/usr/lib/glib-2.0/include POLICYKIT_DBUS_LDLIBS = -ldbus-1 POLICYKIT_GLIB_LDLIBS = -lglib-2.0 diff --git a/usr/src/lib/print/Makefile b/usr/src/lib/print/Makefile deleted file mode 100644 index fd931373e8..0000000000 --- a/usr/src/lib/print/Makefile +++ /dev/null @@ -1,94 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -SUBDIRS = \ - libprint \ - libpapi-common \ - libpapi-dynamic \ - libpapi-lpd \ - libipp-core \ - libhttp-core \ - libpapi-ipp \ - libipp-listener \ - mod_ipp - -all := TARGET = all -clean := TARGET = clean -clobber := TARGET = clobber -install := TARGET = install -install_h := TARGET = install_h -lint := TARGET = lint - -include $(SRC)/Makefile.master - -TEXT_DOMAIN= SUNW_OST_OSLIB -POFILE= print-lib.po - -.KEEP_STATE: - -all: $(TXTS) $(SUBDIRS) - -# -# Each message catalog file is generated in each sub -# directory and copied to the usr/src/cmd/lp/ directory. -# Those message catalog files are consolidated into one -# message catalog file. The consolidated one will be copied -# into the $(ROOT)/catalog/SUNW_OST_OSCMD/ directory. -# - -_msg: $(MSGDOMAIN) - @$(RM) $(POFILE) - $(XGETTEXT) -s `/bin/find . -type d -name SCCS -prune -o -type f -name '*.c' -print` - @/bin/cat messages.po | sed '/domain/d' > $(POFILE) - @$(RM) messages.po - $(RM) $(MSGDOMAIN)/$(POFILE) - /bin/cp $(POFILE) $(MSGDOMAIN) - -install: $(ROOTDIRS) $(ROOTSYMLINKDIRS) $(SUBDIRS) - -install_h clean strip lint: $(SUBDIRS) - -clobber: $(SUBDIRS) local_clobber - -local_clobber: - $(RM) $(CLOBBERFILES) $(POFILE) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: - -include $(SRC)/Makefile.msg.targ - -# Dependencies -libpapi-dynamic: libpapi-common -libpapi-lpd: libpapi-dynamic -libipp-core: libpapi-common -libpapi-ipp: libpapi-common libipp-core libhttp-core -libipp-listener: libpapi-dynamic libipp-core -mod_ipp: libipp-listener - diff --git a/usr/src/lib/print/libhttp-core/Makefile b/usr/src/lib/print/libhttp-core/Makefile deleted file mode 100644 index b92d620b10..0000000000 --- a/usr/src/lib/print/libhttp-core/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../../Makefile.lib - -#HDRS = papi.h -#HDRDIR = common -SUBDIRS = $(MACH) -#$(BUILD64)SUBDIRS += $(MACH64) - -all := TARGET = all -clean := TARGET = clean -clobber := TARGET = clobber -install := TARGET = install -lint := TARGET = lint - -.KEEP_STATE: - -all clean clobber install: .WAIT $(SUBDIRS) - -lint: # $(SUBDIRS) - -install_h: # $(ROOTHDRS) - -check: # $(CHECKHDRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: - -include ../../Makefile.targ diff --git a/usr/src/lib/print/libhttp-core/Makefile.com b/usr/src/lib/print/libhttp-core/Makefile.com deleted file mode 100644 index cfb8ae8730..0000000000 --- a/usr/src/lib/print/libhttp-core/Makefile.com +++ /dev/null @@ -1,63 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -LIBRARY = libhttp-core.a -VERS = .1 -OBJECTS = http-addr.o http-support.o http.o - -ROOTLIBDIR = $(ROOT)/usr/lib/print - -include ../../../Makefile.lib -include ../../../Makefile.rootfs - -SRCDIR = ../common - -ROOTLIBDIR= $(ROOT)/usr/lib/print -ROOTLIBDIR64= $(ROOT)/usr/lib/print/$(MACH) - -LIBS = $(DYNLIB) - -$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRCDIR) -CPPFLAGS += -I../../libpapi-common/common - -MAPFILES = $(SRCDIR)/mapfile - -LDLIBS += -lsocket -lnsl -lc - -.KEEP_STATE: - -all: $(LIBS) - -lint: lintcheck - -$(ROOTLIBDIR): - $(INS.dir) - -include ../../../Makefile.targ diff --git a/usr/src/lib/print/libhttp-core/common/LICENSE.txt b/usr/src/lib/print/libhttp-core/common/LICENSE.txt deleted file mode 100644 index 797ee5db95..0000000000 --- a/usr/src/lib/print/libhttp-core/common/LICENSE.txt +++ /dev/null @@ -1,964 +0,0 @@ - Common UNIX Printing System License Agreement - - Copyright 1997-2006 by Easy Software Products - 44141 AIRPORT VIEW DR STE 204 - HOLLYWOOD, MARYLAND 20636 USA - - Voice: +1.301.373.9600 - Email: cups-info@cups.org - WWW: http://www.cups.org - - -INTRODUCTION - -The Common UNIX Printing System(tm), ("CUPS(tm)"), is provided -under the GNU General Public License ("GPL") and GNU Library -General Public License ("LGPL"), Version 2, with exceptions for -Apple operating systems and the OpenSSL toolkit. A copy of the -exceptions and licenses follow this introduction. - -The GNU LGPL applies to the CUPS API library, located in the -"cups" subdirectory of the CUPS source distribution and in the -"cups" include directory and library files in the binary -distributions. The GNU GPL applies to the remainder of the CUPS -distribution, including the "pdftops" filter which is based upon -Xpdf and the CUPS imaging library. - -For those not familiar with the GNU GPL, the license basically -allows you to: - - - Use the CUPS software at no charge. - - Distribute verbatim copies of the software in source or - binary form. - - Sell verbatim copies of the software for a media fee, or - sell support for the software. - - Distribute or sell printer drivers and filters that use - CUPS so long as source code is made available under the - GPL. - -What this license *does not* allow you to do is make changes or -add features to CUPS and then sell a binary distribution without -source code. You must provide source for any new drivers, -changes, or additions to the software, and all code must be -provided under the GPL or LGPL as appropriate. The only -exceptions to this are the portions of the CUPS software covered -by the Apple operating system license exceptions outlined later -in this license agreement. - -The GNU LGPL relaxes the "link-to" restriction, allowing you to -develop applications that use the CUPS API library under other -licenses and/or conditions as appropriate for your application. - - -LICENSE EXCEPTIONS - -In addition, as the copyright holder of CUPS, Easy Software -Products grants the following special exceptions: - - 1. Apple Operating System Development License Exception; - - a. Software that is developed by any person or entity - for an Apple Operating System ("Apple OS-Developed - Software"), including but not limited to Apple and - third party printer drivers, filters, and backends - for an Apple Operating System, that is linked to the - CUPS imaging library or based on any sample filters - or backends provided with CUPS shall not be - considered to be a derivative work or collective work - based on the CUPS program and is exempt from the - mandatory source code release clauses of the GNU GPL. - You may therefore distribute linked combinations of - the CUPS imaging library with Apple OS-Developed - Software without releasing the source code of the - Apple OS-Developed Software. You may also use sample - filters and backends provided with CUPS to develop - Apple OS-Developed Software without releasing the - source code of the Apple OS-Developed Software. - - b. An Apple Operating System means any operating system - software developed and/or marketed by Apple Computer, - Inc., including but not limited to all existing - releases and versions of Apple's Darwin, Mac OS X, - and Mac OS X Server products and all follow-on - releases and future versions thereof. - - c. This exception is only available for Apple - OS-Developed Software and does not apply to software - that is distributed for use on other operating - systems. - - d. All CUPS software that falls under this license - exception have the following text at the top of each - source file: - - This file is subject to the Apple OS-Developed - Software exception. - - 2. OpenSSL Toolkit License Exception; - - a. Easy Software Products explicitly allows the - compilation and distribution of the CUPS software - with the OpenSSL Toolkit. - -No developer is required to provide these exceptions in a -derived work. - - -TRADEMARKS - -Easy Software Products has trademarked the Common UNIX Printing -System, CUPS, and CUPS logo. You may use these names and logos -in any direct port or binary distribution of CUPS. Please -contact Easy Software Products for written permission to use -them in derivative products. Our intention is to protect the -value of these trademarks and ensure that any derivative product -meets the same high-quality standards as the original. - - -BINARY DISTRIBUTION RIGHTS - -Easy Software Products also sells rights to the CUPS source code -under a binary distribution license for vendors that are unable -to release source code for their drivers, additions, and -modifications to CUPS under the GNU GPL and LGPL. For -information please contact us at the address shown above. - -The Common UNIX Printing System provides a "pdftops" filter that -is based on the Xpdf software. For binary distribution licensing -of this software, please contact: - - Derek B. Noonburg - Email: derekn@glyphandcog.com - WWW: http://www.glyphandcog.com/ - - -SUPPORT - -Easy Software Products sells software support for CUPS as well -as a commercial printing product based on CUPS called ESP Print -Pro. You can find out more at our web site: - - http://www.easysw.com/ - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) 19yy <name of author> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - <signature of Ty Coon>, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. - - GNU LIBRARY GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - [This is the first released version of the library GPL. It is - numbered 2 because it goes with version 2 of the ordinary GPL.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Library General Public License, applies to some -specially designated Free Software Foundation software, and to any -other libraries whose authors decide to use it. You can use it for -your libraries, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if -you distribute copies of the library, or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link a program with the library, you must provide -complete object files to the recipients so that they can relink them -with the library, after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - Our method of protecting your rights has two steps: (1) copyright -the library, and (2) offer you this license which gives you legal -permission to copy, distribute and/or modify the library. - - Also, for each distributor's protection, we want to make certain -that everyone understands that there is no warranty for this free -library. If the library is modified by someone else and passed on, we -want its recipients to know that what they have is not the original -version, so that any problems introduced by others will not reflect on -the original authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that companies distributing free -software will individually obtain patent licenses, thus in effect -transforming the program into proprietary software. To prevent this, -we have made it clear that any patent must be licensed for everyone's -free use or not licensed at all. - - Most GNU software, including some libraries, is covered by the ordinary -GNU General Public License, which was designed for utility programs. This -license, the GNU Library General Public License, applies to certain -designated libraries. This license is quite different from the ordinary -one; be sure to read it in full, and don't assume that anything in it is -the same as in the ordinary license. - - The reason we have a separate public license for some libraries is that -they blur the distinction we usually make between modifying or adding to a -program and simply using it. Linking a program with a library, without -changing the library, is in some sense simply using the library, and is -analogous to running a utility program or application program. However, in -a textual and legal sense, the linked executable is a combined work, a -derivative of the original library, and the ordinary General Public License -treats it as such. - - Because of this blurred distinction, using the ordinary General -Public License for libraries did not effectively promote software -sharing, because most developers did not use the libraries. We -concluded that weaker conditions might promote sharing better. - - However, unrestricted linking of non-free programs would deprive the -users of those programs of all benefit from the free status of the -libraries themselves. This Library General Public License is intended to -permit developers of non-free programs to use free libraries, while -preserving your freedom as a user of such programs to change the free -libraries that are incorporated in them. (We have not seen how to achieve -this as regards changes in header files, but we have achieved it as regards -changes in the actual functions of the Library.) The hope is that this -will lead to faster development of free libraries. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, while the latter only -works together with the library. - - Note that it is possible for a library to be covered by the ordinary -General Public License rather than by this special one. - - GNU LIBRARY GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library which -contains a notice placed by the copyright holder or other authorized -party saying it may be distributed under the terms of this Library -General Public License (also called "this License"). Each licensee is -addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also compile or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - c) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - d) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the source code distributed need not include anything that is normally -distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Library General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - Appendix: How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - <one line to give the library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! diff --git a/usr/src/lib/print/libhttp-core/common/LICENSE.txt.descrip b/usr/src/lib/print/libhttp-core/common/LICENSE.txt.descrip deleted file mode 100644 index 7c846a0987..0000000000 --- a/usr/src/lib/print/libhttp-core/common/LICENSE.txt.descrip +++ /dev/null @@ -1 +0,0 @@ -CUPS diff --git a/usr/src/lib/print/libhttp-core/common/debug.h b/usr/src/lib/print/libhttp-core/common/debug.h deleted file mode 100644 index aebc790017..0000000000 --- a/usr/src/lib/print/libhttp-core/common/debug.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * "$Id: debug.h 148 2006-04-25 16:54:17Z njacobs $ - * - * Debugging macros for the Common UNIX Printing System (CUPS). - * - * Copyright 1997-2005 by Easy Software Products. - * - * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file - * "LICENSE.txt" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org - * - * This file is subject to the Apple OS-Developed Software exception. - */ - -#ifndef _CUPS_DEBUG_H_ -#define _CUPS_DEBUG_H_ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Include necessary headers... - */ - -# include <stdio.h> - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * The debug macros are used if you compile with DEBUG defined. - * - * Usage: - * - * DEBUG_puts("string") - * DEBUG_printf(("format string", arg, arg, ...)); - * - * Note the extra parenthesis around the DEBUG_printf macro... - */ - -# ifdef DEBUG -# define DEBUG_puts(x) puts(x) -# define DEBUG_printf(x) printf x -# else -# define DEBUG_puts(x) -# define DEBUG_printf(x) -# endif /* DEBUG */ - -#ifdef __cplusplus -} -#endif - -#endif /* !_CUPS_DEBUG_H_ */ - -/* - * End of "$Id: debug.h 148 2006-04-25 16:54:17Z njacobs $" - */ diff --git a/usr/src/lib/print/libhttp-core/common/http-addr.c b/usr/src/lib/print/libhttp-core/common/http-addr.c deleted file mode 100644 index a872d4d3fd..0000000000 --- a/usr/src/lib/print/libhttp-core/common/http-addr.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * "$Id: http-addr.c 148 2006-04-25 16:54:17Z njacobs $" - * - * HTTP address routines for the Common UNIX Printing System (CUPS). - * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file - * "LICENSE.txt" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org - * - * Contents: - * - * httpAddrAny() - Check for the "any" address. - * httpAddrEqual() - Compare two addresses. - * httpAddrLoad() - Load a host entry address into an HTTP address. - * httpAddrLocalhost() - Check for the local loopback address. - * httpAddrLookup() - Lookup the hostname associated with the address. - * httpAddrString() - Convert an IP address to a dotted string. - * httpGetHostByName() - Lookup a hostname or IP address, and return - * address records for the specified name. - */ - -/* - * Include necessary headers... - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include "http.h" -#include "debug.h" -#include "string.h" -#include <ctype.h> - - -/* - * 'httpAddrAny()' - Check for the "any" address. - */ - -int /* O - 1 if "any", 0 otherwise */ -httpAddrAny(const http_addr_t *addr) /* I - Address to check */ -{ -#ifdef AF_INET6 - if (addr->addr.sa_family == AF_INET6 && - IN6_IS_ADDR_UNSPECIFIED(&(addr->ipv6.sin6_addr))) - return (1); -#endif /* AF_INET6 */ - - if (addr->addr.sa_family == AF_INET && - ntohl(addr->ipv4.sin_addr.s_addr) == 0x00000000) - return (1); - - return (0); -} - - -/* - * 'httpAddrEqual()' - Compare two addresses. - */ - -int /* O - 1 if equal, 0 if != */ -httpAddrEqual(const http_addr_t *addr1, /* I - First address */ - const http_addr_t *addr2) /* I - Second address */ -{ - if (addr1->addr.sa_family != addr2->addr.sa_family) - return (0); - -#ifdef AF_INET6 - if (addr1->addr.sa_family == AF_INET6) - return (memcmp(&(addr1->ipv6.sin6_addr), &(addr2->ipv6.sin6_addr), 16) == 0); -#endif /* AF_INET6 */ - - return (addr1->ipv4.sin_addr.s_addr == addr2->ipv4.sin_addr.s_addr); -} - - -/* - * 'httpAddrLoad()' - Load a host entry address into an HTTP address. - */ - -void -httpAddrLoad(const struct hostent *host, /* I - Host entry */ - int port, /* I - Port number */ - int n, /* I - Index into host entry */ - http_addr_t *addr) /* O - Address to load */ -{ -#ifdef AF_INET6 - if (host->h_addrtype == AF_INET6) - { -# ifdef WIN32 - addr->ipv6.sin6_port = htons((u_short)port); -# else - addr->ipv6.sin6_port = htons(port); -# endif /* WIN32 */ - - memcpy((char *)&(addr->ipv6.sin6_addr), host->h_addr_list[n], - host->h_length); - addr->ipv6.sin6_family = AF_INET6; - } - else -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - if (host->h_addrtype == AF_LOCAL) - { - addr->un.sun_family = AF_LOCAL; - strlcpy(addr->un.sun_path, host->h_addr_list[n], sizeof(addr->un.sun_path)); - } - else -#endif /* AF_LOCAL */ - if (host->h_addrtype == AF_INET) - { -# ifdef WIN32 - addr->ipv4.sin_port = htons((u_short)port); -# else - addr->ipv4.sin_port = htons(port); -# endif /* WIN32 */ - - memcpy((char *)&(addr->ipv4.sin_addr), host->h_addr_list[n], - host->h_length); - addr->ipv4.sin_family = AF_INET; - } -} - - -/* - * 'httpAddrLocalhost()' - Check for the local loopback address. - */ - -int /* O - 1 if local host, 0 otherwise */ -httpAddrLocalhost(const http_addr_t *addr) - /* I - Address to check */ -{ -#ifdef AF_INET6 - if (addr->addr.sa_family == AF_INET6 && - IN6_IS_ADDR_LOOPBACK(&(addr->ipv6.sin6_addr))) - return (1); -#endif /* AF_INET6 */ - -#ifdef AF_LOCAL - if (addr->addr.sa_family == AF_LOCAL) - return (1); -#endif /* AF_LOCAL */ - - if (addr->addr.sa_family == AF_INET && - ntohl(addr->ipv4.sin_addr.s_addr) == 0x7f000001) - return (1); - - return (0); -} - - -#ifdef __sgi -# define ADDR_CAST (struct sockaddr *) -#else -# define ADDR_CAST (char *) -#endif /* __sgi */ - - -/* - * 'httpAddrLookup()' - Lookup the hostname associated with the address. - */ - -char * /* O - Host name */ -httpAddrLookup(const http_addr_t *addr, /* I - Address to lookup */ - char *name, /* I - Host name buffer */ - int namelen) /* I - Size of name buffer */ -{ - struct hostent *host; /* Host from name service */ - - - DEBUG_printf(("httpAddrLookup(addr=%p, name=%p, namelen=%d)\n", - addr, name, namelen)); - -#ifdef AF_INET6 - if (addr->addr.sa_family == AF_INET6) - host = gethostbyaddr(ADDR_CAST &(addr->ipv6.sin6_addr), - sizeof(struct in6_addr), AF_INET6); - else -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - if (addr->addr.sa_family == AF_LOCAL) - { - strlcpy(name, addr->un.sun_path, namelen); - return (name); - } - else -#endif /* AF_LOCAL */ - if (addr->addr.sa_family == AF_INET) - host = gethostbyaddr(ADDR_CAST &(addr->ipv4.sin_addr), - sizeof(struct in_addr), AF_INET); - else - host = NULL; - - if (host == NULL) - { - httpAddrString(addr, name, namelen); - return (NULL); - } - - strlcpy(name, host->h_name, namelen); - - return (name); -} - - -/* - * 'httpAddrString()' - Convert an IP address to a dotted string. - */ - -char * /* O - IP string */ -httpAddrString(const http_addr_t *addr, /* I - Address to convert */ - char *s, /* I - String buffer */ - int slen) /* I - Length of string */ -{ - DEBUG_printf(("httpAddrString(addr=%p, s=%p, slen=%d)\n", - addr, s, slen)); - -#ifdef AF_INET6 - if (addr->addr.sa_family == AF_INET6) - snprintf(s, slen, "%u.%u.%u.%u", - ntohl(addr->ipv6.sin6_addr.s6_addr32[0]), - ntohl(addr->ipv6.sin6_addr.s6_addr32[1]), - ntohl(addr->ipv6.sin6_addr.s6_addr32[2]), - ntohl(addr->ipv6.sin6_addr.s6_addr32[3])); - else -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - if (addr->addr.sa_family == AF_LOCAL) - strlcpy(s, addr->un.sun_path, slen); - else -#endif /* AF_LOCAL */ - if (addr->addr.sa_family == AF_INET) - { - unsigned temp; /* Temporary address */ - - - temp = ntohl(addr->ipv4.sin_addr.s_addr); - - snprintf(s, slen, "%d.%d.%d.%d", (temp >> 24) & 255, - (temp >> 16) & 255, (temp >> 8) & 255, temp & 255); - } - else - strlcpy(s, "UNKNOWN", slen); - - DEBUG_printf(("httpAddrString: returning \"%s\"...\n", s)); - - return (s); -} - - -/* - * 'httpGetHostByName()' - Lookup a hostname or IP address, and return - * address records for the specified name. - */ - -struct hostent * /* O - Host entry */ -httpGetHostByName(const char *name) /* I - Hostname or IP address */ -{ - const char *nameptr; /* Pointer into name */ - unsigned ip[4]; /* IP address components */ - static unsigned packed_ip; /* Packed IPv4 address */ - static char *packed_ptr[2]; /* Pointer to packed address */ - static struct hostent host_ip; /* Host entry for IP/domain address */ - - - DEBUG_printf(("httpGetHostByName(name=\"%s\")\n", name)); - -#if defined(__APPLE__) - /* OS X hack to avoid it's ocassional long delay in lookupd */ - static const char sLoopback[] = "127.0.0.1"; - if (strcmp(name, "localhost") == 0) - name = sLoopback; -#endif /* __APPLE__ */ - - /* - * This function is needed because some operating systems have a - * buggy implementation of gethostbyname() that does not support - * IP addresses. If the first character of the name string is a - * number, then sscanf() is used to extract the IP components. - * We then pack the components into an IPv4 address manually, - * since the inet_aton() function is deprecated. We use the - * htonl() macro to get the right byte order for the address. - * - * We also support domain sockets when supported by the underlying - * OS... - */ - -#ifdef AF_LOCAL - if (name[0] == '/') - { - /* - * A domain socket address, so make an AF_LOCAL entry and return it... - */ - - host_ip.h_name = (char *)name; - host_ip.h_aliases = NULL; - host_ip.h_addrtype = AF_LOCAL; - host_ip.h_length = strlen(name) + 1; - host_ip.h_addr_list = packed_ptr; - packed_ptr[0] = (char *)name; - packed_ptr[1] = NULL; - - DEBUG_puts("httpGetHostByName: returning domain socket address..."); - - return (&host_ip); - } -#endif /* AF_LOCAL */ - - for (nameptr = name; isdigit(*nameptr & 255) || *nameptr == '.'; nameptr ++); - - if (!*nameptr) - { - /* - * We have an IP address; break it up and provide the host entry - * to the caller. Currently only supports IPv4 addresses, although - * it should be trivial to support IPv6 in CUPS 1.2. - */ - - if (sscanf(name, "%u.%u.%u.%u", ip, ip + 1, ip + 2, ip + 3) != 4) - return (NULL); /* Must have 4 numbers */ - - if (ip[0] > 255 || ip[1] > 255 || ip[2] > 255 || ip[3] > 255) - return (NULL); /* Invalid byte ranges! */ - - packed_ip = htonl(((((((ip[0] << 8) | ip[1]) << 8) | ip[2]) << 8) | ip[3])); - - /* - * Fill in the host entry and return it... - */ - - host_ip.h_name = (char *)name; - host_ip.h_aliases = NULL; - host_ip.h_addrtype = AF_INET; - host_ip.h_length = 4; - host_ip.h_addr_list = packed_ptr; - packed_ptr[0] = (char *)(&packed_ip); - packed_ptr[1] = NULL; - - DEBUG_puts("httpGetHostByName: returning IPv4 address..."); - - return (&host_ip); - } - else - { - /* - * Use the gethostbyname() function to get the IP address for - * the name... - */ - - DEBUG_puts("httpGetHostByName: returning domain lookup address(es)..."); - - return (gethostbyname(name)); - } -} - - -/* - * End of "$Id: http-addr.c 148 2006-04-25 16:54:17Z njacobs $". - */ diff --git a/usr/src/lib/print/libhttp-core/common/http-private.h b/usr/src/lib/print/libhttp-core/common/http-private.h deleted file mode 100644 index a11b8bbb5e..0000000000 --- a/usr/src/lib/print/libhttp-core/common/http-private.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * "$Id: http-private.h 148 2006-04-25 16:54:17Z njacobs $" - * - * Private HTTP definitions for the Common UNIX Printing System (CUPS). - * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file - * "LICENSE.txt" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org - * - * This file is subject to the Apple OS-Developed Software exception. - */ - -#ifndef _CUPS_HTTP_PRIVATE_H_ -#define _CUPS_HTTP_PRIVATE_H_ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Include necessary headers... - */ -#ifdef __cplusplus -extern "C" { -#endif - - -# include "config.h" - - -# ifdef __sun -/* - * Define FD_SETSIZE to CUPS_MAX_FDS on Solaris to get the correct version of - * select() for large numbers of file descriptors. - */ - -#define CUPS_MAX_FDS 1024 - -# define FD_SETSIZE CUPS_MAX_FDS -# include <sys/select.h> -# endif /* __sun */ - -# include "http.h" - -# if defined HAVE_LIBSSL -/* - * The OpenSSL library provides its own SSL/TLS context structure for its - * IO and protocol management... - */ - -# include <openssl/err.h> -# include <openssl/rand.h> -# include <openssl/ssl.h> - -typedef SSL http_tls_t; - -# elif defined HAVE_GNUTLS -/* - * The GNU TLS library is more of a "bare metal" SSL/TLS library... - */ -# include <gnutls/gnutls.h> - -typedef struct -{ - gnutls_session session; /* GNU TLS session object */ - void *credentials; /* GNU TLS credentials object */ -} http_tls_t; - -# elif defined(HAVE_CDSASSL) -/* - * Darwin's Security framework provides its own SSL/TLS context structure - * for its IO and protocol management... - */ - -# include <Security/SecureTransport.h> - -typedef SSLConnectionRef http_tls_t; - -# endif /* HAVE_LIBSSL */ - -/* - * Some OS's don't have hstrerror(), most notably Solaris... - */ - -# ifndef HAVE_HSTRERROR -extern const char *cups_hstrerror(int error); -# define hstrerror cups_hstrerror -# elif defined(_AIX) || defined(__osf__) -/* - * AIX and Tru64 UNIX don't provide a prototype but do provide the function... - */ -extern const char *hstrerror(int error); -# endif /* !HAVE_HSTRERROR */ - -#ifdef __cplusplus -} -#endif - -#endif /* !_CUPS_HTTP_PRIVATE_H_ */ - -/* - * End of "$Id: http-private.h 148 2006-04-25 16:54:17Z njacobs $" - */ diff --git a/usr/src/lib/print/libhttp-core/common/http-support.c b/usr/src/lib/print/libhttp-core/common/http-support.c deleted file mode 100644 index 2ef3911058..0000000000 --- a/usr/src/lib/print/libhttp-core/common/http-support.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * "$Id: http-support.c 148 2006-04-25 16:54:17Z njacobs $" - * - * HTTP support routines for the Common UNIX Printing System (CUPS) scheduler. - * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file - * "LICENSE.txt" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org - * - * This file is subject to the Apple OS-Developed Software exception. - * - * Contents: - * - * httpSeparate() - Separate a Universal Resource Identifier into its - * components. - * httpSeparate2() - Separate a Universal Resource Identifier into its - * components. - * httpStatus() - Return a short string describing a HTTP status code. - * cups_hstrerror() - hstrerror() emulation function for Solaris and others... - * http_copy_decode() - Copy and decode a URI. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Include necessary headers... - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <ctype.h> -#include "string.h" - -#include "http.h" - - -/* - * Local functions... - */ - -static const char *http_copy_decode(char *dst, const char *src, - int dstsize, const char *term); - - -/* - * 'httpSeparate()' - Separate a Universal Resource Identifier into its - * components. - */ - -void -httpSeparate(const char *uri, /* I - Universal Resource Identifier */ - char *method, /* O - Method [32] (http, https, etc.) */ - char *username, /* O - Username [1024] */ - char *host, /* O - Hostname [1024] */ - int *port, /* O - Port number to use */ - char *resource) /* O - Resource/filename [1024] */ -{ - httpSeparate2(uri, method, 32, username, HTTP_MAX_URI, host, HTTP_MAX_URI, - port, resource, HTTP_MAX_URI); -} - - -/* - * 'httpSeparate2()' - Separate a Universal Resource Identifier into its - * components. - */ - -void -httpSeparate2(const char *uri, /* I - Universal Resource Identifier */ - char *method, /* O - Method (http, https, etc.) */ - int methodlen, /* I - Size of method buffer */ - char *username, /* O - Username */ - int usernamelen, /* I - Size of username buffer */ - char *host, /* O - Hostname */ - int hostlen, /* I - Size of hostname buffer */ - int *port, /* O - Port number to use */ - char *resource, /* O - Resource/filename */ - int resourcelen) /* I - Size of resource buffer */ -{ - char *ptr; /* Pointer into string... */ - const char *atsign, /* @ sign */ - *slash; /* Separator */ - - - /* - * Range check input... - */ - - if (uri == NULL || method == NULL || username == NULL || host == NULL || - port == NULL || resource == NULL) - return; - - /* - * Grab the method portion of the URI... - */ - - if (strncmp(uri, "//", 2) == 0) - { - /* - * Workaround for HP IPP client bug... - */ - - strlcpy(method, "ipp", methodlen); - } - else - { - /* - * Standard URI with method... - */ - - uri = http_copy_decode(host, uri, hostlen, ":"); - - if (*uri == ':') - uri ++; - - /* - * If the method contains a period or slash, then it's probably - * hostname/filename... - */ - - if (strchr(host, '.') != NULL || strchr(host, '/') != NULL || *uri == '\0') - { - if ((ptr = strchr(host, '/')) != NULL) - { - strlcpy(resource, ptr, resourcelen); - *ptr = '\0'; - } - else - resource[0] = '\0'; - - if (isdigit(*uri & 255)) - { - /* - * OK, we have "hostname:port[/resource]"... - */ - - *port = strtol(uri, (char **)&uri, 10); - - if (*uri == '/') - strlcpy(resource, uri, resourcelen); - } - else - *port = 631; - - strlcpy(method, "http", methodlen); - username[0] = '\0'; - return; - } - else - strlcpy(method, host, methodlen); - } - - /* - * If the method starts with less than 2 slashes then it is a local resource... - */ - - if (strncmp(uri, "//", 2) != 0) - { - strlcpy(resource, uri, resourcelen); - - username[0] = '\0'; - host[0] = '\0'; - *port = 0; - return; - } - - /* - * Grab the username, if any... - */ - - uri += 2; - - if ((slash = strchr(uri, '/')) == NULL) - slash = uri + strlen(uri); - - if ((atsign = strchr(uri, '@')) != NULL && atsign < slash) - { - /* - * Got a username:password combo... - */ - - uri = http_copy_decode(username, uri, usernamelen, "@") + 1; - } - else - username[0] = '\0'; - - /* - * Grab the hostname... - */ - - uri = http_copy_decode(host, uri, hostlen, ":/"); - - if (*uri != ':') - { - if (strcasecmp(method, "http") == 0) - *port = 80; - else if (strcasecmp(method, "https") == 0) - *port = 443; - else if (strcasecmp(method, "ipp") == 0) - *port = 631; - else if (strcasecmp(method, "lpd") == 0) - *port = 515; - else if (strcasecmp(method, "socket") == 0) /* Not registered yet... */ - *port = 9100; - else - *port = 0; - } - else - { - /* - * Parse port number... - */ - - *port = strtol(uri + 1, (char **)&uri, 10); - } - - if (*uri == '\0') - { - /* - * Hostname but no port or path... - */ - - resource[0] = '/'; - resource[1] = '\0'; - return; - } - - /* - * The remaining portion is the resource string... - */ - - http_copy_decode(resource, uri, resourcelen, ""); -} - - -/* - * 'httpStatus()' - Return a short string describing a HTTP status code. - */ - -const char * /* O - String or NULL */ -httpStatus(http_status_t status) /* I - HTTP status code */ -{ - switch (status) - { - case HTTP_CONTINUE : - return ("Continue"); - case HTTP_SWITCHING_PROTOCOLS : - return ("Switching Protocols"); - case HTTP_OK : - return ("OK"); - case HTTP_CREATED : - return ("Created"); - case HTTP_ACCEPTED : - return ("Accepted"); - case HTTP_NO_CONTENT : - return ("No Content"); - case HTTP_NOT_MODIFIED : - return ("Not Modified"); - case HTTP_BAD_REQUEST : - return ("Bad Request"); - case HTTP_UNAUTHORIZED : - return ("Unauthorized"); - case HTTP_FORBIDDEN : - return ("Forbidden"); - case HTTP_NOT_FOUND : - return ("Not Found"); - case HTTP_REQUEST_TOO_LARGE : - return ("Request Entity Too Large"); - case HTTP_URI_TOO_LONG : - return ("URI Too Long"); - case HTTP_UPGRADE_REQUIRED : - return ("Upgrade Required"); - case HTTP_NOT_IMPLEMENTED : - return ("Not Implemented"); - case HTTP_NOT_SUPPORTED : - return ("Not Supported"); - default : - return ("Unknown"); - } -} - - -#ifndef HAVE_HSTRERROR -/* - * 'cups_hstrerror()' - hstrerror() emulation function for Solaris and others... - */ - -const char * /* O - Error string */ -cups_hstrerror(int error) /* I - Error number */ -{ - static const char * const errors[] = /* Error strings */ - { - "OK", - "Host not found.", - "Try again.", - "Unrecoverable lookup error.", - "No data associated with name." - }; - - - if (error < 0 || error > 4) - return ("Unknown hostname lookup error."); - else - return (errors[error]); -} -#endif /* !HAVE_HSTRERROR */ - - -/* - * 'http_copy_decode()' - Copy and decode a URI. - */ - -static const char * /* O - New source pointer */ -http_copy_decode(char *dst, /* O - Destination buffer */ - const char *src, /* I - Source pointer */ - int dstsize, /* I - Destination size */ - const char *term) /* I - Terminating characters */ -{ - char *ptr, /* Pointer into buffer */ - *end; /* End of buffer */ - int quoted; /* Quoted character */ - - - /* - * Copy the src to the destination until we hit a terminating character - * or the end of the string. - */ - - for (ptr = dst, end = dst + dstsize - 1; *src && !strchr(term, *src); src ++) - if (ptr < end) - { - if (*src == '%' && isxdigit(src[1] & 255) && isxdigit(src[2] & 255)) - { - /* - * Grab a hex-encoded character... - */ - - src ++; - if (isalpha(*src)) - quoted = (tolower(*src) - 'a' + 10) << 4; - else - quoted = (*src - '0') << 4; - - src ++; - if (isalpha(*src)) - quoted |= tolower(*src) - 'a' + 10; - else - quoted |= *src - '0'; - - *ptr++ = quoted; - } - else - *ptr++ = *src; - } - - *ptr = '\0'; - - return (src); -} - - -/* - * End of "$Id: http-support.c 148 2006-04-25 16:54:17Z njacobs $" - */ diff --git a/usr/src/lib/print/libhttp-core/common/http.c b/usr/src/lib/print/libhttp-core/common/http.c deleted file mode 100644 index b32b1eb3bc..0000000000 --- a/usr/src/lib/print/libhttp-core/common/http.c +++ /dev/null @@ -1,2569 +0,0 @@ -/* - * "$Id: http.c 148 2006-04-25 16:54:17Z njacobs $" - * - * HTTP routines for the Common UNIX Printing System (CUPS). - * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file - * "LICENSE.txt" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org - * - * This file is subject to the Apple OS-Developed Software exception. - * - * Contents: - * - * httpInitialize() - Initialize the HTTP interface library and set the - * default HTTP proxy (if any). - * httpCheck() - Check to see if there is a pending response from - * the server. - * httpClearCookie() - Clear the cookie value(s). - * httpClose() - Close an HTTP connection... - * httpConnect() - Connect to a HTTP server. - * httpConnectEncrypt() - Connect to a HTTP server using encryption. - * httpEncryption() - Set the required encryption on the link. - * httpReconnect() - Reconnect to a HTTP server... - * httpGetSubField() - Get a sub-field value. - * httpSetField() - Set the value of an HTTP header. - * httpDelete() - Send a DELETE request to the server. - * httpGet() - Send a GET request to the server. - * httpHead() - Send a HEAD request to the server. - * httpOptions() - Send an OPTIONS request to the server. - * httpPost() - Send a POST request to the server. - * httpPut() - Send a PUT request to the server. - * httpTrace() - Send an TRACE request to the server. - * httpFlush() - Flush data from a HTTP connection. - * httpRead() - Read data from a HTTP connection. - * httpSetCookie() - Set the cookie value(s)... - * httpWait() - Wait for data available on a connection. - * httpWrite() - Write data to a HTTP connection. - * httpGets() - Get a line of text from a HTTP connection. - * httpPrintf() - Print a formatted string to a HTTP connection. - * httpGetDateString() - Get a formatted date/time string from a time value. - * httpGetDateTime() - Get a time value from a formatted date/time string. - * httpUpdate() - Update the current HTTP state for incoming data. - * httpDecode64() - Base64-decode a string. - * httpDecode64_2() - Base64-decode a string. - * httpEncode64() - Base64-encode a string. - * httpEncode64_2() - Base64-encode a string. - * httpGetLength() - Get the amount of data remaining from the - * content-length or transfer-encoding fields. - * http_field() - Return the field index for a field name. - * http_send() - Send a request with all fields and the trailing - * blank line. - * http_wait() - Wait for data available on a connection. - * http_upgrade() - Force upgrade to TLS encryption. - * http_setup_ssl() - Set up SSL/TLS on a connection. - * http_shutdown_ssl() - Shut down SSL/TLS on a connection. - * http_read_ssl() - Read from a SSL/TLS connection. - * http_write_ssl() - Write to a SSL/TLS connection. - * CDSAReadFunc() - Read function for CDSA decryption code. - * CDSAWriteFunc() - Write function for CDSA encryption code. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Include necessary headers... - */ - -#include "http-private.h" - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <ctype.h> -#include "string.h" -#include <fcntl.h> -#include <errno.h> - -#include "http.h" -#include "debug.h" - -#ifndef WIN32 -# include <signal.h> -# include <sys/time.h> -# include <sys/resource.h> -#endif /* !WIN32 */ - - -/* - * Some operating systems have done away with the Fxxxx constants for - * the fcntl() call; this works around that "feature"... - */ - -#ifndef FNONBLK -# define FNONBLK O_NONBLOCK -#endif /* !FNONBLK */ - - -/* - * Local functions... - */ - -static http_field_t http_field(const char *name); -static int http_send(http_t *http, http_state_t request, - const char *uri); -static int http_wait(http_t *http, int msec); -#ifdef HAVE_SSL -static int http_upgrade(http_t *http); -static int http_setup_ssl(http_t *http); -static void http_shutdown_ssl(http_t *http); -static int http_read_ssl(http_t *http, char *buf, int len); -static int http_write_ssl(http_t *http, const char *buf, int len); -# ifdef HAVE_CDSASSL -static OSStatus CDSAReadFunc(SSLConnectionRef connection, void *data, size_t *dataLength); -static OSStatus CDSAWriteFunc(SSLConnectionRef connection, const void *data, size_t *dataLength); -# endif /* HAVE_CDSASSL */ -#endif /* HAVE_SSL */ - - -/* - * Local globals... - */ - -static const char * const http_fields[] = - { - "Accept-Language", - "Accept-Ranges", - "Authorization", - "Connection", - "Content-Encoding", - "Content-Language", - "Content-Length", - "Content-Location", - "Content-MD5", - "Content-Range", - "Content-Type", - "Content-Version", - "Date", - "Host", - "If-Modified-Since", - "If-Unmodified-since", - "Keep-Alive", - "Last-Modified", - "Link", - "Location", - "Range", - "Referer", - "Retry-After", - "Transfer-Encoding", - "Upgrade", - "User-Agent", - "WWW-Authenticate" - }; -static const char * const days[7] = - { - "Sun", - "Mon", - "Tue", - "Wed", - "Thu", - "Fri", - "Sat" - }; -static const char * const months[12] = - { - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec" - }; - -void -httpDumpData(FILE *fp, const char *tag, const char *buffer, int bytes) -{ - int i, j, ch; - - fprintf(fp, "%s %d(0x%x) bytes...\n", tag, bytes, bytes); - for (i = 0; i < bytes; i += 16) { - fprintf(fp, "%s ", (tag ? tag : "")); - - for (j = 0; j < 16 && (i + j) < bytes; j ++) - fprintf(fp, " %02X", buffer[i + j] & 255); - - while (j < 16) { - fprintf(fp, " "); - j++; - } - - fprintf(fp, " "); - for (j = 0; j < 16 && (i + j) < bytes; j ++) { - ch = buffer[i + j] & 255; - if (ch < ' ' || ch == 127) - ch = '.'; - putc(ch, fp); - } - putc('\n', fp); - } -} - - -/* - * 'httpInitialize()' - Initialize the HTTP interface library and set the - * default HTTP proxy (if any). - */ - -void -httpInitialize(void) -{ -#ifdef HAVE_LIBSSL -# ifndef WIN32 - struct timeval curtime; /* Current time in microseconds */ -# endif /* !WIN32 */ - int i; /* Looping var */ - unsigned char data[1024]; /* Seed data */ -#endif /* HAVE_LIBSSL */ - -#ifdef WIN32 - WSADATA winsockdata; /* WinSock data */ - static int initialized = 0; /* Has WinSock been initialized? */ - - - if (!initialized) - WSAStartup(MAKEWORD(1,1), &winsockdata); -#elif defined(HAVE_SIGSET) - sigset(SIGPIPE, SIG_IGN); -#elif defined(HAVE_SIGACTION) - struct sigaction action; /* POSIX sigaction data */ - - - /* - * Ignore SIGPIPE signals... - */ - - memset(&action, 0, sizeof(action)); - action.sa_handler = SIG_IGN; - sigaction(SIGPIPE, &action, NULL); -#else - signal(SIGPIPE, SIG_IGN); -#endif /* WIN32 */ - -#ifdef HAVE_GNUTLS - gnutls_global_init(); -#endif /* HAVE_GNUTLS */ - -#ifdef HAVE_LIBSSL - SSL_load_error_strings(); - SSL_library_init(); - - /* - * Using the current time is a dubious random seed, but on some systems - * it is the best we can do (on others, this seed isn't even used...) - */ - -#ifdef WIN32 -#else - gettimeofday(&curtime, NULL); - srand(curtime.tv_sec + curtime.tv_usec); -#endif /* WIN32 */ - - for (i = 0; i < sizeof(data); i ++) - data[i] = rand(); /* Yes, this is a poor source of random data... */ - - RAND_seed(&data, sizeof(data)); -#endif /* HAVE_LIBSSL */ -} - - -/* - * 'httpCheck()' - Check to see if there is a pending response from the server. - */ - -int /* O - 0 = no data, 1 = data available */ -httpCheck(http_t *http) /* I - HTTP connection */ -{ - return (httpWait(http, 0)); -} - - -/* - * 'httpClearCookie()' - Clear the cookie value(s). - */ - -void -httpClearCookie(http_t *http) /* I - Connection */ -{ - if (!http) - return; - - if (http->cookie) - { - free(http->cookie); - http->cookie = NULL; - } -} - - -/* - * 'httpClose()' - Close an HTTP connection... - */ - -void -httpClose(http_t *http) /* I - Connection to close */ -{ - DEBUG_printf(("httpClose(http=%p)\n", http)); - - if (!http) - return; - - if (http->input_set) - free(http->input_set); - - if (http->cookie) - free(http->cookie); - -#ifdef HAVE_SSL - if (http->tls) - http_shutdown_ssl(http); -#endif /* HAVE_SSL */ - -#ifdef WIN32 - closesocket(http->fd); -#else - close(http->fd); -#endif /* WIN32 */ - - free(http); -} - - -/* - * 'httpConnect()' - Connect to a HTTP server. - */ - -http_t * /* O - New HTTP connection */ -httpConnect(const char *host, /* I - Host to connect to */ - int port) /* I - Port number */ -{ - http_encryption_t encrypt; /* Type of encryption to use */ - - - /* - * Set the default encryption status... - */ - - if (port == 443) - encrypt = HTTP_ENCRYPT_ALWAYS; - else - encrypt = HTTP_ENCRYPT_IF_REQUESTED; - - return (httpConnectEncrypt(host, port, encrypt)); -} - - -/* - * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption. - */ - -http_t * /* O - New HTTP connection */ -httpConnectEncrypt(const char *host, /* I - Host to connect to */ - int port, /* I - Port number */ - http_encryption_t encrypt) - /* I - Type of encryption to use */ -{ - int i; /* Looping var */ - http_t *http; /* New HTTP connection */ - struct hostent *hostaddr; /* Host address data */ - - - DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encrypt=%d)\n", - host ? host : "(null)", port, encrypt)); - - if (!host) - return (NULL); - - httpInitialize(); - - /* - * Lookup the host... - */ - - if ((hostaddr = httpGetHostByName(host)) == NULL) - { - /* - * This hack to make users that don't have a localhost entry in - * their hosts file or DNS happy... - */ - - if (strcasecmp(host, "localhost") != 0) - return (NULL); - else if ((hostaddr = httpGetHostByName("127.0.0.1")) == NULL) - return (NULL); - } - - /* - * Verify that it is an IPv4, IPv6, or domain address... - */ - - if ((hostaddr->h_addrtype != AF_INET || hostaddr->h_length != 4) -#ifdef AF_INET6 - && (hostaddr->h_addrtype != AF_INET6 || hostaddr->h_length != 16) -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - && (hostaddr->h_addrtype != AF_LOCAL) -#endif /* AF_LOCAL */ - ) - return (NULL); - - /* - * Allocate memory for the structure... - */ - - http = calloc(sizeof(http_t), 1); - if (http == NULL) - return (NULL); - - http->version = HTTP_1_1; - http->blocking = 1; - http->activity = time(NULL); - http->fd = -1; - - /* - * Set the encryption status... - */ - - if (port == 443) /* Always use encryption for https */ - http->encryption = HTTP_ENCRYPT_ALWAYS; - else - http->encryption = encrypt; - - /* - * Loop through the addresses we have until one of them connects... - */ - - strlcpy(http->hostname, host, sizeof(http->hostname)); - - for (i = 0; hostaddr->h_addr_list[i]; i ++) - { - /* - * Load the address... - */ - - httpAddrLoad(hostaddr, port, i, &(http->hostaddr)); - - /* - * Connect to the remote system... - */ - - if (!httpReconnect(http)) - return (http); - } - - /* - * Could not connect to any known address - bail out! - */ - - free(http); - return (NULL); -} - - -/* - * 'httpEncryption()' - Set the required encryption on the link. - */ - -int /* O - -1 on error, 0 on success */ -httpEncryption(http_t *http, /* I - HTTP data */ - http_encryption_t e) /* I - New encryption preference */ -{ - DEBUG_printf(("httpEncryption(http=%p, e=%d)\n", http, e)); - -#ifdef HAVE_SSL - if (!http) - return (0); - - http->encryption = e; - - if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) || - (http->encryption == HTTP_ENCRYPT_NEVER && http->tls)) - return (httpReconnect(http)); - else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls) - return (http_upgrade(http)); - else - return (0); -#else - if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED) - return (-1); - else - return (0); -#endif /* HAVE_SSL */ -} - - -/* - * 'httpReconnect()' - Reconnect to a HTTP server... - */ - -int /* O - 0 on success, non-zero on failure */ -httpReconnect(http_t *http) /* I - HTTP data */ -{ - int val; /* Socket option value */ - int status; /* Connect status */ - - - DEBUG_printf(("httpReconnect(http=%p)\n", http)); - - if (!http) - return (-1); - -#ifdef HAVE_SSL - if (http->tls) - http_shutdown_ssl(http); -#endif /* HAVE_SSL */ - - /* - * Close any previously open socket... - */ - - if (http->fd >= 0) -#ifdef WIN32 - closesocket(http->fd); -#else - close(http->fd); -#endif /* WIN32 */ - - /* - * Create the socket and set options to allow reuse. - */ - - if ((http->fd = socket(http->hostaddr.addr.sa_family, SOCK_STREAM, 0)) < 0) - { -#ifdef WIN32 - http->error = WSAGetLastError(); -#else - http->error = errno; -#endif /* WIN32 */ - http->status = HTTP_ERROR; - return (-1); - } - -#ifdef FD_CLOEXEC - fcntl(http->fd, F_SETFD, FD_CLOEXEC); /* Close this socket when starting * - * other processes... */ -#endif /* FD_CLOEXEC */ - - val = 1; - setsockopt(http->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); - -#ifdef SO_REUSEPORT - val = 1; - setsockopt(http->fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)); -#endif /* SO_REUSEPORT */ - - /* - * Using TCP_NODELAY improves responsiveness, especially on systems - * with a slow loopback interface... Since we write large buffers - * when sending print files and requests, there shouldn't be any - * performance penalty for this... - */ - - val = 1; -#ifdef WIN32 - setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); -#else - setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); -#endif /* WIN32 */ - - /* - * Connect to the server... - */ - -#ifdef AF_INET6 - if (http->hostaddr.addr.sa_family == AF_INET6) - status = connect(http->fd, (struct sockaddr *)&(http->hostaddr), - sizeof(http->hostaddr.ipv6)); - else -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - if (http->hostaddr.addr.sa_family == AF_LOCAL) - status = connect(http->fd, (struct sockaddr *)&(http->hostaddr), - SUN_LEN(&(http->hostaddr.un))); - else -#endif /* AF_LOCAL */ - status = connect(http->fd, (struct sockaddr *)&(http->hostaddr), - sizeof(http->hostaddr.ipv4)); - - if (status < 0) - { -#ifdef WIN32 - http->error = WSAGetLastError(); -#else - http->error = errno; -#endif /* WIN32 */ - http->status = HTTP_ERROR; - -#ifdef WIN32 - closesocket(http->fd); -#else - close(http->fd); -#endif - - http->fd = -1; - - return (-1); - } - - http->error = 0; - http->status = HTTP_CONTINUE; - -#ifdef HAVE_SSL - if (http->encryption == HTTP_ENCRYPT_ALWAYS) - { - /* - * Always do encryption via SSL. - */ - - if (http_setup_ssl(http) != 0) - { -#ifdef WIN32 - closesocket(http->fd); -#else - close(http->fd); -#endif /* WIN32 */ - - return (-1); - } - } - else if (http->encryption == HTTP_ENCRYPT_REQUIRED) - return (http_upgrade(http)); -#endif /* HAVE_SSL */ - - return (0); -} - - -/* - * 'httpGetSubField()' - Get a sub-field value. - */ - -char * /* O - Value or NULL */ -httpGetSubField(http_t *http, /* I - HTTP data */ - http_field_t field, /* I - Field index */ - const char *name, /* I - Name of sub-field */ - char *value) /* O - Value string */ -{ - const char *fptr; /* Pointer into field */ - char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */ - *ptr; /* Pointer into string buffer */ - - - DEBUG_printf(("httpGetSubField(http=%p, field=%d, name=\"%s\", value=%p)\n", - http, field, name, value)); - - if (http == NULL || - field < HTTP_FIELD_ACCEPT_LANGUAGE || - field > HTTP_FIELD_WWW_AUTHENTICATE || - name == NULL || value == NULL) - return (NULL); - - for (fptr = http->fields[field]; *fptr;) - { - /* - * Skip leading whitespace... - */ - - while (isspace(*fptr & 255)) - fptr ++; - - if (*fptr == ',') - { - fptr ++; - continue; - } - - /* - * Get the sub-field name... - */ - - for (ptr = temp; - *fptr && *fptr != '=' && !isspace(*fptr & 255) && ptr < (temp + sizeof(temp) - 1); - *ptr++ = *fptr++); - - *ptr = '\0'; - - DEBUG_printf(("httpGetSubField: name=\"%s\"\n", temp)); - - /* - * Skip trailing chars up to the '='... - */ - - while (isspace(*fptr & 255)) - fptr ++; - - if (!*fptr) - break; - - if (*fptr != '=') - continue; - - /* - * Skip = and leading whitespace... - */ - - fptr ++; - - while (isspace(*fptr & 255)) - fptr ++; - - if (*fptr == '\"') - { - /* - * Read quoted string... - */ - - for (ptr = value, fptr ++; - *fptr && *fptr != '\"' && ptr < (value + HTTP_MAX_VALUE - 1); - *ptr++ = *fptr++); - - *ptr = '\0'; - - while (*fptr && *fptr != '\"') - fptr ++; - - if (*fptr) - fptr ++; - } - else - { - /* - * Read unquoted string... - */ - - for (ptr = value; - *fptr && !isspace(*fptr & 255) && *fptr != ',' && ptr < (value + HTTP_MAX_VALUE - 1); - *ptr++ = *fptr++); - - *ptr = '\0'; - - while (*fptr && !isspace(*fptr & 255) && *fptr != ',') - fptr ++; - } - - DEBUG_printf(("httpGetSubField: value=\"%s\"\n", value)); - - /* - * See if this is the one... - */ - - if (strcmp(name, temp) == 0) - return (value); - } - - value[0] = '\0'; - - return (NULL); -} - - -/* - * 'httpSetField()' - Set the value of an HTTP header. - */ - -void -httpSetField(http_t *http, /* I - HTTP data */ - http_field_t field, /* I - Field index */ - const char *value) /* I - Value */ -{ - if (http == NULL || - field < HTTP_FIELD_ACCEPT_LANGUAGE || - field > HTTP_FIELD_WWW_AUTHENTICATE || - value == NULL) - return; - - strlcpy(http->fields[field], value, HTTP_MAX_VALUE); -} - - -/* - * 'httpDelete()' - Send a DELETE request to the server. - */ - -int /* O - Status of call (0 = success) */ -httpDelete(http_t *http, /* I - HTTP data */ - const char *uri) /* I - URI to delete */ -{ - return (http_send(http, HTTP_DELETE, uri)); -} - - -/* - * 'httpGet()' - Send a GET request to the server. - */ - -int /* O - Status of call (0 = success) */ -httpGet(http_t *http, /* I - HTTP data */ - const char *uri) /* I - URI to get */ -{ - return (http_send(http, HTTP_GET, uri)); -} - - -/* - * 'httpHead()' - Send a HEAD request to the server. - */ - -int /* O - Status of call (0 = success) */ -httpHead(http_t *http, /* I - HTTP data */ - const char *uri) /* I - URI for head */ -{ - return (http_send(http, HTTP_HEAD, uri)); -} - - -/* - * 'httpOptions()' - Send an OPTIONS request to the server. - */ - -int /* O - Status of call (0 = success) */ -httpOptions(http_t *http, /* I - HTTP data */ - const char *uri) /* I - URI for options */ -{ - return (http_send(http, HTTP_OPTIONS, uri)); -} - - -/* - * 'httpPost()' - Send a POST request to the server. - */ - -int /* O - Status of call (0 = success) */ -httpPost(http_t *http, /* I - HTTP data */ - const char *uri) /* I - URI for post */ -{ - httpGetLength(http); - - return (http_send(http, HTTP_POST, uri)); -} - - -/* - * 'httpPut()' - Send a PUT request to the server. - */ - -int /* O - Status of call (0 = success) */ -httpPut(http_t *http, /* I - HTTP data */ - const char *uri) /* I - URI to put */ -{ - httpGetLength(http); - - return (http_send(http, HTTP_PUT, uri)); -} - - -/* - * 'httpTrace()' - Send an TRACE request to the server. - */ - -int /* O - Status of call (0 = success) */ -httpTrace(http_t *http, /* I - HTTP data */ - const char *uri) /* I - URI for trace */ -{ - return (http_send(http, HTTP_TRACE, uri)); -} - - -/* - * 'httpFlush()' - Flush data from a HTTP connection. - */ - -void -httpFlush(http_t *http) /* I - HTTP data */ -{ - char buffer[8192]; /* Junk buffer */ - - - DEBUG_printf(("httpFlush(http=%p), state=%d\n", http, http->state)); - - while (httpRead(http, buffer, sizeof(buffer)) > 0); -} - - -/* - * 'httpRead()' - Read data from a HTTP connection. - */ - -int /* O - Number of bytes read */ -httpRead(http_t *http, /* I - HTTP data */ - char *buffer, /* I - Buffer for data */ - int length) /* I - Maximum number of bytes */ -{ - int bytes; /* Bytes read */ - char len[32]; /* Length string */ - - - DEBUG_printf(("httpRead(http=%p, buffer=%p, length=%d)\n", - http, buffer, length)); - - if (http == NULL || buffer == NULL) - return (-1); - - http->activity = time(NULL); - - if (length <= 0) - return (0); - - if (http->data_encoding == HTTP_ENCODE_CHUNKED && - http->data_remaining <= 0) - { - DEBUG_puts("httpRead: Getting chunk length..."); - - if (httpGets(len, sizeof(len), http) == NULL) - { - DEBUG_puts("httpRead: Could not get length!"); - return (0); - } - - http->data_remaining = strtol(len, NULL, 16); - if (http->data_remaining < 0) - { - DEBUG_puts("httpRead: Negative chunk length!"); - return (0); - } - } - - DEBUG_printf(("httpRead: data_remaining=%d\n", http->data_remaining)); - - if (http->data_remaining <= 0) - { - /* - * A zero-length chunk ends a transfer; unless we are reading POST - * data, go idle... - */ - - if (http->data_encoding == HTTP_ENCODE_CHUNKED) - httpGets(len, sizeof(len), http); - - if (http->state == HTTP_POST_RECV) - http->state ++; - else - http->state = HTTP_WAITING; - - /* - * Prevent future reads for this request... - */ - - http->data_encoding = HTTP_ENCODE_LENGTH; - - return (0); - } - else if (length > http->data_remaining) - length = http->data_remaining; - - if (http->used == 0 && length <= 256) - { - /* - * Buffer small reads for better performance... - */ - - if (!http->blocking && !httpWait(http, 1000)) - return (0); - - if (http->data_remaining > sizeof(http->buffer)) - bytes = sizeof(http->buffer); - else - bytes = http->data_remaining; - -#ifdef HAVE_SSL - if (http->tls) - bytes = http_read_ssl(http, http->buffer, bytes); - else -#endif /* HAVE_SSL */ - { - DEBUG_printf(("httpRead: reading %d bytes from socket into buffer...\n", - bytes)); - - bytes = recv(http->fd, http->buffer, bytes, 0); - - DEBUG_printf(("httpRead: read %d bytes from socket into buffer...\n", - bytes)); -#ifdef DEBUG_HTTP - httpDumpData(stdout, "httpRead:", http->buffer, bytes); -#endif - } - - if (bytes > 0) - http->used = bytes; - else if (bytes < 0) - { -#ifdef WIN32 - http->error = WSAGetLastError(); - return (-1); -#else - if (errno != EINTR) - { - http->error = errno; - return (-1); - } -#endif /* WIN32 */ - } - else - { - http->error = EPIPE; - return (0); - } - } - - if (http->used > 0) - { - if (length > http->used) - length = http->used; - - bytes = length; - - DEBUG_printf(("httpRead: grabbing %d bytes from input buffer...\n", bytes)); - - memcpy(buffer, http->buffer, length); - http->used -= length; - - if (http->used > 0) - memmove(http->buffer, http->buffer + length, http->used); - } -#ifdef HAVE_SSL - else if (http->tls) - { - if (!http->blocking && !httpWait(http, 1000)) - return (0); - - bytes = http_read_ssl(http, buffer, length); - } -#endif /* HAVE_SSL */ - else - { - if (!http->blocking && !httpWait(http, 1000)) - return (0); - - DEBUG_printf(("httpRead: reading %d bytes from socket...\n", length)); - - while ((bytes = recv(http->fd, buffer, length, 0)) < 0) - if (errno != EINTR) - break; - DEBUG_printf(("httpRead: read %d bytes from socket...\n", bytes)); - } -#ifdef DEBUG_HTTP - httpDumpData(stdout, "httpRead:", buffer, bytes); -#endif - - if (bytes > 0) - http->data_remaining -= bytes; - else if (bytes < 0) - { -#ifdef WIN32 - http->error = WSAGetLastError(); -#else - if (errno == EINTR) - bytes = 0; - else - http->error = errno; -#endif /* WIN32 */ - } - else - { - http->error = EPIPE; - return (0); - } - - if (http->data_remaining == 0) - { - if (http->data_encoding == HTTP_ENCODE_CHUNKED) - httpGets(len, sizeof(len), http); - - if (http->data_encoding != HTTP_ENCODE_CHUNKED) - { - if (http->state == HTTP_POST_RECV) - http->state ++; - else - http->state = HTTP_WAITING; - } - } - - return (bytes); -} - - -/* - * 'httpSetCookie()' - Set the cookie value(s)... - */ - -void -httpSetCookie(http_t *http, /* I - Connection */ - const char *cookie) /* I - Cookie string */ -{ - if (!http) - return; - - if (http->cookie) - free(http->cookie); - - if (cookie) - http->cookie = strdup(cookie); - else - http->cookie = NULL; -} - - -/* - * 'httpWait()' - Wait for data available on a connection. - */ - -int /* O - 1 if data is available, 0 otherwise */ -httpWait(http_t *http, /* I - HTTP data */ - int msec) /* I - Milliseconds to wait */ -{ - /* - * First see if there is data in the buffer... - */ - - if (http == NULL) - return (0); - - if (http->used) - return (1); - - /* - * If not, check the SSL/TLS buffers and do a select() on the connection... - */ - - return (http_wait(http, msec)); -} - - -/* - * 'httpWrite()' - Write data to a HTTP connection. - */ - -int /* O - Number of bytes written */ -httpWrite(http_t *http, /* I - HTTP data */ - const char *buffer, /* I - Buffer for data */ - int length) /* I - Number of bytes to write */ -{ - int tbytes, /* Total bytes sent */ - bytes; /* Bytes sent */ - - - if (http == NULL || buffer == NULL) - return (-1); - - http->activity = time(NULL); - - if (http->data_encoding == HTTP_ENCODE_CHUNKED) - { - if (httpPrintf(http, "%x\r\n", length) < 0) - return (-1); - - if (length == 0) - { - /* - * A zero-length chunk ends a transfer; unless we are sending POST - * or PUT data, go idle... - */ - - DEBUG_printf(("httpWrite: changing states from %d", http->state)); - - if (http->state == HTTP_POST_RECV) - http->state ++; - else if (http->state == HTTP_PUT_RECV) - http->state = HTTP_STATUS; - else - http->state = HTTP_WAITING; - DEBUG_printf((" to %d\n", http->state)); - - if (httpPrintf(http, "\r\n") < 0) - return (-1); - - return (0); - } - } - - tbytes = 0; - - while (length > 0) - { -#ifdef HAVE_SSL - if (http->tls) - bytes = http_write_ssl(http, buffer, length); - else -#endif /* HAVE_SSL */ - bytes = send(http->fd, buffer, length, 0); - -#ifdef DEBUG_HTTP - if (bytes >= 0) - httpDumpData(stdout, "httpWrite:", buffer, bytes); -#endif /* DEBUG */ - - - if (bytes < 0) - { -#ifdef WIN32 - if (WSAGetLastError() != http->error) - { - http->error = WSAGetLastError(); - continue; - } -#else - if (errno == EINTR) - continue; - else if (errno != http->error && errno != ECONNRESET) - { - http->error = errno; - continue; - } -#endif /* WIN32 */ - - DEBUG_puts("httpWrite: error writing data...\n"); - - return (-1); - } - - buffer += bytes; - tbytes += bytes; - length -= bytes; - if (http->data_encoding == HTTP_ENCODE_LENGTH) - http->data_remaining -= bytes; - } - - if (http->data_encoding == HTTP_ENCODE_CHUNKED) - if (httpPrintf(http, "\r\n") < 0) - return (-1); - - if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODE_LENGTH) - { - /* - * Finished with the transfer; unless we are sending POST or PUT - * data, go idle... - */ - - DEBUG_printf(("httpWrite: changing states from %d", http->state)); - - if (http->state == HTTP_POST_RECV) - http->state ++; - else if (http->state == HTTP_PUT_RECV) - http->state = HTTP_STATUS; - else - http->state = HTTP_WAITING; - - DEBUG_printf((" to %d\n", http->state)); - } - - return (tbytes); -} - - -/* - * 'httpGets()' - Get a line of text from a HTTP connection. - */ - -char * /* O - Line or NULL */ -httpGets(char *line, /* I - Line to read into */ - int length, /* I - Max length of buffer */ - http_t *http) /* I - HTTP data */ -{ - char *lineptr, /* Pointer into line */ - *bufptr, /* Pointer into input buffer */ - *bufend; /* Pointer to end of buffer */ - int bytes; /* Number of bytes read */ - - - DEBUG_printf(("httpGets(line=%p, length=%d, http=%p)\n", line, length, http)); - - if (http == NULL || line == NULL) - return (NULL); - - /* - * Pre-scan the buffer and see if there is a newline in there... - */ - -#ifdef WIN32 - WSASetLastError(0); -#else - errno = 0; -#endif /* WIN32 */ - - do - { - bufptr = http->buffer; - bufend = http->buffer + http->used; - - while (bufptr < bufend) - if (*bufptr == 0x0a) - break; - else - bufptr ++; - - if (bufptr >= bufend && http->used < HTTP_MAX_BUFFER) - { - /* - * No newline; see if there is more data to be read... - */ - - if (!http->blocking && !http_wait(http, 1000)) - return (NULL); - -#ifdef HAVE_SSL - if (http->tls) - bytes = http_read_ssl(http, bufend, HTTP_MAX_BUFFER - http->used); - else -#endif /* HAVE_SSL */ - bytes = recv(http->fd, bufend, HTTP_MAX_BUFFER - http->used, 0); - - DEBUG_printf(("httpGets: read %d bytes...\n", bytes)); -#ifdef DEBUG_HTTP - httpDumpData(stdout, "httpGets:", bufend, bytes); -#endif - - if (bytes < 0) - { - /* - * Nope, can't get a line this time... - */ - -#ifdef WIN32 - if (WSAGetLastError() != http->error) - { - http->error = WSAGetLastError(); - continue; - } - - DEBUG_printf(("httpGets: recv() error %d!\n", WSAGetLastError())); -#else - DEBUG_printf(("httpGets: recv() error %d!\n", errno)); - - if (errno == EINTR) - continue; - else if (errno != http->error) - { - http->error = errno; - continue; - } -#endif /* WIN32 */ - - return (NULL); - } - else if (bytes == 0) - { - http->error = EPIPE; - - return (NULL); - } - - /* - * Yup, update the amount used and the end pointer... - */ - - http->used += bytes; - bufend += bytes; - bufptr = bufend; - } - } - while (bufptr >= bufend && http->used < HTTP_MAX_BUFFER); - - http->activity = time(NULL); - - /* - * Read a line from the buffer... - */ - - lineptr = line; - bufptr = http->buffer; - bytes = 0; - length --; - - while (bufptr < bufend && bytes < length) - { - bytes ++; - - if (*bufptr == 0x0a) - { - bufptr ++; - break; - } - else if (*bufptr == 0x0d) - bufptr ++; - else - *lineptr++ = *bufptr++; - } - - if (bytes > 0) - { - *lineptr = '\0'; - - http->used -= bytes; - if (http->used > 0) - memmove(http->buffer, bufptr, http->used); - - DEBUG_printf(("httpGets: Returning \"%s\"\n", line)); - return (line); - } - - DEBUG_puts("httpGets: No new line available!"); - - return (NULL); -} - - -/* - * 'httpPrintf()' - Print a formatted string to a HTTP connection. - */ - -int /* O - Number of bytes written */ -httpPrintf(http_t *http, /* I - HTTP data */ - const char *format, /* I - printf-style format string */ - ...) /* I - Additional args as needed */ -{ - int bytes, /* Number of bytes to write */ - nbytes, /* Number of bytes written */ - tbytes; /* Number of bytes all together */ - char buf[HTTP_MAX_BUFFER], /* Buffer for formatted string */ - *bufptr; /* Pointer into buffer */ - va_list ap; /* Variable argument pointer */ - - - DEBUG_printf(("httpPrintf: httpPrintf(http=%p, format=\"%s\", ...)\n", http, format)); - - va_start(ap, format); - bytes = vsnprintf(buf, sizeof(buf), format, ap); - va_end(ap); - - DEBUG_printf(("httpPrintf: %s", buf)); - - for (tbytes = 0, bufptr = buf; tbytes < bytes; tbytes += nbytes, bufptr += nbytes) - { -#ifdef HAVE_SSL - if (http->tls) - nbytes = http_write_ssl(http, bufptr, bytes - tbytes); - else -#endif /* HAVE_SSL */ - nbytes = send(http->fd, bufptr, bytes - tbytes, 0); - -#ifdef DEBUG_HTTP - if (nbytes >= 0) - httpDumpData(stdout, "httpPrintf:", bufptr, nbytes); -#endif - - if (nbytes < 0) - { - nbytes = 0; - -#ifdef WIN32 - if (WSAGetLastError() != http->error) - { - http->error = WSAGetLastError(); - continue; - } -#else - if (errno == EINTR) - continue; - else if (errno != http->error) - { - http->error = errno; - continue; - } -#endif /* WIN32 */ - - return (-1); - } - } - - return (bytes); -} - - -/* - * 'httpGetDateString()' - Get a formatted date/time string from a time value. - */ - -const char * /* O - Date/time string */ -httpGetDateString(time_t t) /* I - UNIX time */ -{ - struct tm *tdate; - static char datetime[256]; - - - tdate = gmtime(&t); - snprintf(datetime, sizeof(datetime), "%s, %02d %s %d %02d:%02d:%02d GMT", - days[tdate->tm_wday], tdate->tm_mday, months[tdate->tm_mon], - tdate->tm_year + 1900, tdate->tm_hour, tdate->tm_min, tdate->tm_sec); - - return (datetime); -} - - -/* - * 'httpGetDateTime()' - Get a time value from a formatted date/time string. - */ - -time_t /* O - UNIX time */ -httpGetDateTime(const char *s) /* I - Date/time string */ -{ - int i; /* Looping var */ - struct tm tdate; /* Time/date structure */ - char mon[16]; /* Abbreviated month name */ - int day, year; /* Day of month and year */ - int hour, min, sec; /* Time */ - - - if (sscanf(s, "%*s%d%15s%d%d:%d:%d", &day, mon, &year, &hour, &min, &sec) < 6) - return (0); - - for (i = 0; i < 12; i ++) - if (strcasecmp(mon, months[i]) == 0) - break; - - if (i >= 12) - return (0); - - tdate.tm_mon = i; - tdate.tm_mday = day; - tdate.tm_year = year - 1900; - tdate.tm_hour = hour; - tdate.tm_min = min; - tdate.tm_sec = sec; - tdate.tm_isdst = 0; - - return (mktime(&tdate)); -} - - -/* - * 'httpUpdate()' - Update the current HTTP state for incoming data. - */ - -http_status_t /* O - HTTP status */ -httpUpdate(http_t *http) /* I - HTTP data */ -{ - char line[1024], /* Line from connection... */ - *value; /* Pointer to value on line */ - http_field_t field; /* Field index */ - int major, minor, /* HTTP version numbers */ - status; /* Request status */ - - - DEBUG_printf(("httpUpdate(http=%p), state=%d\n", http, http->state)); - - /* - * If we haven't issued any commands, then there is nothing to "update"... - */ - - if (http->state == HTTP_WAITING) - return (HTTP_CONTINUE); - - /* - * Grab all of the lines we can from the connection... - */ - - line[0] = '\0'; - while (httpGets(line, sizeof(line), http) != NULL) - { - DEBUG_printf(("httpUpdate: Got \"%s\"\n", line)); - - if (line[0] == '\0') - { - /* - * Blank line means the start of the data section (if any). Return - * the result code, too... - * - * If we get status 100 (HTTP_CONTINUE), then we *don't* change states. - * Instead, we just return HTTP_CONTINUE to the caller and keep on - * tryin'... - */ - - if (http->status == HTTP_CONTINUE) - return (http->status); - - if (http->status < HTTP_BAD_REQUEST) - http->digest_tries = 0; - -#ifdef HAVE_SSL - if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls) - { - if (http_setup_ssl(http) != 0) - { -# ifdef WIN32 - closesocket(http->fd); -# else - close(http->fd); -# endif /* WIN32 */ - - return (HTTP_ERROR); - } - - return (HTTP_CONTINUE); - } -#endif /* HAVE_SSL */ - - httpGetLength(http); - - switch (http->state) - { - case HTTP_GET : - case HTTP_POST : - case HTTP_POST_RECV : - case HTTP_PUT : - http->state ++; - case HTTP_POST_SEND : - break; - - default : - http->state = HTTP_WAITING; - break; - } - - return (http->status); - } - else if (strncmp(line, "HTTP/", 5) == 0) - { - /* - * Got the beginning of a response... - */ - - if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3) - return (HTTP_ERROR); - - http->version = (http_version_t)(major * 100 + minor); - http->status = (http_status_t)status; - } - else if ((value = strchr(line, ':')) != NULL) - { - /* - * Got a value... - */ - - *value++ = '\0'; - while (isspace(*value & 255)) - value ++; - - /* - * Be tolerants of servers that send unknown attribute fields... - */ - - if (!strcasecmp(line, "expect")) - { - /* - * "Expect: 100-continue" or similar... - */ - - http->expect = (http_status_t)atoi(value); - } - else if (!strcasecmp(line, "cookie")) - { - /* - * "Cookie: name=value[; name=value ...]" - replaces previous cookies... - */ - - httpSetCookie(http, value); - } - else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN) - { - DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line)); - continue; - } - else - httpSetField(http, field, value); - } - else - { - http->status = HTTP_ERROR; - return (HTTP_ERROR); - } - } - - /* - * See if there was an error... - */ - - if (http->error == EPIPE && http->status > HTTP_CONTINUE) - return (http->status); - - if (http->error) - { - DEBUG_printf(("httpUpdate: socket error %d - %s\n", http->error, - strerror(http->error))); - http->status = HTTP_ERROR; - return (HTTP_ERROR); - } - - /* - * If we haven't already returned, then there is nothing new... - */ - - return (HTTP_CONTINUE); -} - - -/* - * 'httpDecode64()' - Base64-decode a string. - */ - -char * /* O - Decoded string */ -httpDecode64(char *out, /* I - String to write to */ - const char *in) /* I - String to read from */ -{ - int outlen; /* Output buffer length */ - - - /* - * Use the old maximum buffer size for binary compatibility... - */ - - outlen = 512; - - return (httpDecode64_2(out, &outlen, in)); -} - - -/* - * 'httpDecode64_2()' - Base64-decode a string. - */ - -char * /* O - Decoded string */ -httpDecode64_2(char *out, /* I - String to write to */ - int *outlen, /* IO - Size of output string */ - const char *in) /* I - String to read from */ -{ - int pos, /* Bit position */ - base64; /* Value of this character */ - char *outptr, /* Output pointer */ - *outend; /* End of output buffer */ - - - /* - * Range check input... - */ - - if (!out || !outlen || *outlen < 1 || !in || !*in) - return (NULL); - - /* - * Convert from base-64 to bytes... - */ - - for (outptr = out, outend = out + *outlen - 1, pos = 0; *in != '\0'; in ++) - { - /* - * Decode this character into a number from 0 to 63... - */ - - if (*in >= 'A' && *in <= 'Z') - base64 = *in - 'A'; - else if (*in >= 'a' && *in <= 'z') - base64 = *in - 'a' + 26; - else if (*in >= '0' && *in <= '9') - base64 = *in - '0' + 52; - else if (*in == '+') - base64 = 62; - else if (*in == '/') - base64 = 63; - else if (*in == '=') - break; - else - continue; - - /* - * Store the result in the appropriate chars... - */ - - switch (pos) - { - case 0 : - if (outptr < outend) - *outptr = base64 << 2; - pos ++; - break; - case 1 : - if (outptr < outend) - *outptr++ |= (base64 >> 4) & 3; - if (outptr < outend) - *outptr = (base64 << 4) & 255; - pos ++; - break; - case 2 : - if (outptr < outend) - *outptr++ |= (base64 >> 2) & 15; - if (outptr < outend) - *outptr = (base64 << 6) & 255; - pos ++; - break; - case 3 : - if (outptr < outend) - *outptr++ |= base64; - pos = 0; - break; - } - } - - *outptr = '\0'; - - /* - * Return the decoded string and size... - */ - - *outlen = (int)(outptr - out); - - return (out); -} - - -/* - * 'httpEncode64()' - Base64-encode a string. - */ - -char * /* O - Encoded string */ -httpEncode64(char *out, /* I - String to write to */ - const char *in) /* I - String to read from */ -{ - return (httpEncode64_2(out, 512, in, strlen(in))); -} - - -/* - * 'httpEncode64_2()' - Base64-encode a string. - */ - -char * /* O - Encoded string */ -httpEncode64_2(char *out, /* I - String to write to */ - int outlen, /* I - Size of output string */ - const char *in, /* I - String to read from */ - int inlen) /* I - Size of input string */ -{ - char *outptr, /* Output pointer */ - *outend; /* End of output buffer */ - static const char base64[] = /* Base64 characters... */ - { - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789" - "+/" - }; - - - /* - * Range check input... - */ - - if (!out || outlen < 1 || !in || inlen < 1) - return (NULL); - - /* - * Convert bytes to base-64... - */ - - for (outptr = out, outend = out + outlen - 1; inlen > 0; in ++, inlen --) - { - /* - * Encode the up to 3 characters as 4 Base64 numbers... - */ - - if (outptr < outend) - *outptr ++ = base64[(in[0] & 255) >> 2]; - if (outptr < outend) - *outptr ++ = base64[(((in[0] & 255) << 4) | ((in[1] & 255) >> 4)) & 63]; - - in ++; - inlen --; - if (inlen <= 0) - { - if (outptr < outend) - *outptr ++ = '='; - if (outptr < outend) - *outptr ++ = '='; - break; - } - - if (outptr < outend) - *outptr ++ = base64[(((in[0] & 255) << 2) | ((in[1] & 255) >> 6)) & 63]; - - in ++; - inlen --; - if (inlen <= 0) - { - if (outptr < outend) - *outptr ++ = '='; - break; - } - - if (outptr < outend) - *outptr ++ = base64[in[0] & 63]; - } - - *outptr = '\0'; - - /* - * Return the encoded string... - */ - - return (out); -} - - -/* - * 'httpGetLength()' - Get the amount of data remaining from the - * content-length or transfer-encoding fields. - */ - -int /* O - Content length */ -httpGetLength(http_t *http) /* I - HTTP data */ -{ - DEBUG_printf(("httpGetLength(http=%p), state=%d\n", http, http->state)); - - if (strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked") == 0) - { - DEBUG_puts("httpGetLength: chunked request!"); - - http->data_encoding = HTTP_ENCODE_CHUNKED; - http->data_remaining = 0; - } - else - { - http->data_encoding = HTTP_ENCODE_LENGTH; - - /* - * The following is a hack for HTTP servers that don't send a - * content-length or transfer-encoding field... - * - * If there is no content-length then the connection must close - * after the transfer is complete... - */ - - if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0') - http->data_remaining = 2147483647; - else - http->data_remaining = atoi(http->fields[HTTP_FIELD_CONTENT_LENGTH]); - - DEBUG_printf(("httpGetLength: content_length=%d\n", http->data_remaining)); - } - - return (http->data_remaining); -} - - -/* - * 'http_field()' - Return the field index for a field name. - */ - -static http_field_t /* O - Field index */ -http_field(const char *name) /* I - String name */ -{ - int i; /* Looping var */ - - - for (i = 0; i < HTTP_FIELD_MAX; i ++) - if (strcasecmp(name, http_fields[i]) == 0) - return ((http_field_t)i); - - return (HTTP_FIELD_UNKNOWN); -} - - -/* - * 'http_send()' - Send a request with all fields and the trailing blank line. - */ - -static int /* O - 0 on success, non-zero on error */ -http_send(http_t *http, /* I - HTTP data */ - http_state_t request, /* I - Request code */ - const char *uri) /* I - URI */ -{ - int i; /* Looping var */ - char *ptr, /* Pointer in buffer */ - buf[1024]; /* Encoded URI buffer */ - static const char * const codes[] = - { /* Request code strings */ - NULL, - "OPTIONS", - "GET", - NULL, - "HEAD", - "POST", - NULL, - NULL, - "PUT", - NULL, - "DELETE", - "TRACE", - "CLOSE" - }; - static const char hex[] = "0123456789ABCDEF"; - /* Hex digits */ - - - DEBUG_printf(("http_send(http=%p, request=HTTP_%s, uri=\"%s\")\n", - http, codes[request], uri)); - - if (http == NULL || uri == NULL) - return (-1); - - /* - * Encode the URI as needed... - */ - - for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++) - if (*uri <= ' ' || *uri >= 127) - { - if (ptr < (buf + sizeof(buf) - 1)) - *ptr ++ = '%'; - if (ptr < (buf + sizeof(buf) - 1)) - *ptr ++ = hex[(*uri >> 4) & 15]; - if (ptr < (buf + sizeof(buf) - 1)) - *ptr ++ = hex[*uri & 15]; - } - else - *ptr ++ = *uri; - - *ptr = '\0'; - - /* - * See if we had an error the last time around; if so, reconnect... - */ - - if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST) - httpReconnect(http); - - /* - * Send the request header... - */ - - http->state = request; - if (request == HTTP_POST || request == HTTP_PUT) - http->state ++; - - http->status = HTTP_CONTINUE; - -#ifdef HAVE_SSL - if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls) - { - httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade"); - httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0"); - } -#endif /* HAVE_SSL */ - - if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1) - { - http->status = HTTP_ERROR; - return (-1); - } - - for (i = 0; i < HTTP_FIELD_MAX; i ++) - if (http->fields[i][0] != '\0') - { - DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i])); - - if (httpPrintf(http, "%s: %s\r\n", http_fields[i], http->fields[i]) < 1) - { - http->status = HTTP_ERROR; - return (-1); - } - } - - if (httpPrintf(http, "\r\n") < 1) - { - http->status = HTTP_ERROR; - return (-1); - } - - httpClearFields(http); - - return (0); -} - - -/* - * 'http_wait()' - Wait for data available on a connection. - */ - -static int /* O - 1 if data is available, 0 otherwise */ -http_wait(http_t *http, /* I - HTTP data */ - int msec) /* I - Milliseconds to wait */ -{ -#ifndef WIN32 - struct rlimit limit; /* Runtime limit */ -#endif /* !WIN32 */ - struct timeval timeout; /* Timeout */ - int nfds; /* Result from select() */ - int set_size; /* Size of select set */ - - - DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec)); - - /* - * Check the SSL/TLS buffers for data first... - */ - -#ifdef HAVE_SSL - if (http->tls) - { -# ifdef HAVE_LIBSSL - if (SSL_pending((SSL *)(http->tls))) - return (1); -# elif defined(HAVE_GNUTLS) - if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session)) - return (1); -# elif defined(HAVE_CDSASSL) - size_t bytes; /* Bytes that are available */ - - if (!SSLGetBufferedReadSize((SSLContextRef)http->tls, &bytes) && bytes > 0) - return; -# endif /* HAVE_LIBSSL */ - } -#endif /* HAVE_SSL */ - - /* - * Then try doing a select() to poll the socket... - */ - - if (!http->input_set) - { -#ifdef WIN32 - /* - * Windows has a fixed-size select() structure, different (surprise, - * surprise!) from all UNIX implementations. Just allocate this - * fixed structure... - */ - - http->input_set = calloc(1, sizeof(fd_set)); -#else - /* - * Allocate the select() input set based upon the max number of file - * descriptors available for this process... - */ - - getrlimit(RLIMIT_NOFILE, &limit); - - set_size = (limit.rlim_cur + 31) / 8 + 4; - if (set_size < sizeof(fd_set)) - set_size = sizeof(fd_set); - - http->input_set = calloc(1, set_size); -#endif /* WIN32 */ - - if (!http->input_set) - return (0); - } - - do - { - FD_SET(http->fd, http->input_set); - - if (msec >= 0) - { - timeout.tv_sec = msec / 1000; - timeout.tv_usec = (msec % 1000) * 1000; - - nfds = select(http->fd + 1, http->input_set, NULL, NULL, &timeout); - } - else - nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL); - } -#ifdef WIN32 - while (nfds < 0 && WSAGetLastError() == WSAEINTR); -#else - while (nfds < 0 && errno == EINTR); -#endif /* WIN32 */ - - FD_CLR(http->fd, http->input_set); - - return (nfds > 0); -} - - -#ifdef HAVE_SSL -/* - * 'http_upgrade()' - Force upgrade to TLS encryption. - */ - -static int /* O - Status of connection */ -http_upgrade(http_t *http) /* I - HTTP data */ -{ - int ret; /* Return value */ - http_t myhttp; /* Local copy of HTTP data */ - - - DEBUG_printf(("http_upgrade(%p)\n", http)); - - /* - * Copy the HTTP data to a local variable so we can do the OPTIONS - * request without interfering with the existing request data... - */ - - memcpy(&myhttp, http, sizeof(myhttp)); - - /* - * Send an OPTIONS request to the server, requiring SSL or TLS - * encryption on the link... - */ - - httpClearFields(&myhttp); - httpSetField(&myhttp, HTTP_FIELD_CONNECTION, "upgrade"); - httpSetField(&myhttp, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0"); - - if ((ret = httpOptions(&myhttp, "*")) == 0) - { - /* - * Wait for the secure connection... - */ - - while (httpUpdate(&myhttp) == HTTP_CONTINUE); - } - - httpFlush(&myhttp); - - /* - * Copy the HTTP data back over, if any... - */ - - http->fd = myhttp.fd; - http->error = myhttp.error; - http->activity = myhttp.activity; - http->status = myhttp.status; - http->version = myhttp.version; - http->keep_alive = myhttp.keep_alive; - http->used = myhttp.used; - - if (http->used) - memcpy(http->buffer, myhttp.buffer, http->used); - - http->auth_type = myhttp.auth_type; - http->nonce_count = myhttp.nonce_count; - - memcpy(http->nonce, myhttp.nonce, sizeof(http->nonce)); - - http->tls = myhttp.tls; - http->encryption = myhttp.encryption; - - /* - * See if we actually went secure... - */ - - if (!http->tls) - { - /* - * Server does not support HTTP upgrade... - */ - - DEBUG_puts("Server does not support HTTP upgrade!"); - -# ifdef WIN32 - closesocket(http->fd); -# else - close(http->fd); -# endif - - http->fd = -1; - - return (-1); - } - else - return (ret); -} - - -/* - * 'http_setup_ssl()' - Set up SSL/TLS support on a connection. - */ - -static int /* O - Status of connection */ -http_setup_ssl(http_t *http) /* I - HTTP data */ -{ -# ifdef HAVE_LIBSSL - SSL_CTX *context; /* Context for encryption */ - SSL *conn; /* Connection for encryption */ -# elif defined(HAVE_GNUTLS) - http_tls_t *conn; /* TLS session object */ - gnutls_certificate_client_credentials *credentials; - /* TLS credentials */ -# elif defined(HAVE_CDSASSL) - SSLContextRef conn; /* Context for encryption */ - OSStatus error; /* Error info */ -# endif /* HAVE_LIBSSL */ - - - DEBUG_printf(("http_setup_ssl(http=%p)\n", http)); - -# ifdef HAVE_LIBSSL - context = SSL_CTX_new(SSLv23_client_method()); - - SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */ - - conn = SSL_new(context); - - SSL_set_fd(conn, http->fd); - if (SSL_connect(conn) != 1) - { -# ifdef DEBUG - unsigned long error; /* Error code */ - - while ((error = ERR_get_error()) != 0) - printf("http_setup_ssl: %s\n", ERR_error_string(error, NULL)); -# endif /* DEBUG */ - - SSL_CTX_free(context); - SSL_free(conn); - -# ifdef WIN32 - http->error = WSAGetLastError(); -# else - http->error = errno; -# endif /* WIN32 */ - http->status = HTTP_ERROR; - - return (HTTP_ERROR); - } - -# elif defined(HAVE_GNUTLS) - conn = (http_tls_t *)malloc(sizeof(http_tls_t)); - - if (conn == NULL) - { - http->error = errno; - http->status = HTTP_ERROR; - - return (-1); - } - - credentials = (gnutls_certificate_client_credentials *) - malloc(sizeof(gnutls_certificate_client_credentials)); - if (credentials == NULL) - { - free(conn); - - http->error = errno; - http->status = HTTP_ERROR; - - return (-1); - } - - gnutls_certificate_allocate_credentials(credentials); - - gnutls_init(&(conn->session), GNUTLS_CLIENT); - gnutls_set_default_priority(conn->session); - gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials); - gnutls_transport_set_ptr(conn->session, http->fd); - - if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS) - { - http->error = errno; - http->status = HTTP_ERROR; - - return (-1); - } - - conn->credentials = credentials; - -# elif defined(HAVE_CDSASSL) - error = SSLNewContext(false, &conn); - - if (!error) - error = SSLSetIOFuncs(conn, CDSAReadFunc, CDSAWriteFunc); - - if (!error) - error = SSLSetConnection(conn, (SSLConnectionRef)http->fd); - - if (!error) - error = SSLSetAllowsExpiredCerts(conn, true); - - if (!error) - error = SSLSetAllowsAnyRoot(conn, true); - - if (!error) - error = SSLHandshake(conn); - - if (error != 0) - { - http->error = error; - http->status = HTTP_ERROR; - - SSLDisposeContext(conn); - - close(http->fd); - - return (-1); - } -# endif /* HAVE_CDSASSL */ - - http->tls = conn; - return (0); -} - - -/* - * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection. - */ - -static void -http_shutdown_ssl(http_t *http) /* I - HTTP data */ -{ -# ifdef HAVE_LIBSSL - SSL_CTX *context; /* Context for encryption */ - SSL *conn; /* Connection for encryption */ - - - conn = (SSL *)(http->tls); - context = SSL_get_SSL_CTX(conn); - - SSL_shutdown(conn); - SSL_CTX_free(context); - SSL_free(conn); - -# elif defined(HAVE_GNUTLS) - http_tls_t *conn; /* Encryption session */ - gnutls_certificate_client_credentials *credentials; - /* TLS credentials */ - - - conn = (http_tls_t *)(http->tls); - credentials = (gnutls_certificate_client_credentials *)(conn->credentials); - - gnutls_bye(conn->session, GNUTLS_SHUT_RDWR); - gnutls_deinit(conn->session); - gnutls_certificate_free_credentials(*credentials); - free(credentials); - free(conn); - -# elif defined(HAVE_CDSASSL) - SSLClose((SSLContextRef)http->tls); - SSLDisposeContext((SSLContextRef)http->tls); -# endif /* HAVE_LIBSSL */ - - http->tls = NULL; -} - - -/* - * 'http_read_ssl()' - Read from a SSL/TLS connection. - */ - -static int /* O - Bytes read */ -http_read_ssl(http_t *http, /* I - HTTP data */ - char *buf, /* I - Buffer to store data */ - int len) /* I - Length of buffer */ -{ -# if defined(HAVE_LIBSSL) - return (SSL_read((SSL *)(http->tls), buf, len)); - -# elif defined(HAVE_GNUTLS) - return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len)); - -# elif defined(HAVE_CDSASSL) - OSStatus error; /* Error info */ - size_t processed; /* Number of bytes processed */ - - - error = SSLRead((SSLContextRef)http->tls, buf, len, &processed); - - if (error == 0) - return (processed); - else - { - http->error = error; - - return (-1); - } -# endif /* HAVE_LIBSSL */ -} - - -/* - * 'http_write_ssl()' - Write to a SSL/TLS connection. - */ - -static int /* O - Bytes written */ -http_write_ssl(http_t *http, /* I - HTTP data */ - const char *buf, /* I - Buffer holding data */ - int len) /* I - Length of buffer */ -{ -# if defined(HAVE_LIBSSL) - return (SSL_write((SSL *)(http->tls), buf, len)); - -# elif defined(HAVE_GNUTLS) - return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len)); -# elif defined(HAVE_CDSASSL) - OSStatus error; /* Error info */ - size_t processed; /* Number of bytes processed */ - - - error = SSLWrite((SSLContextRef)http->tls, buf, len, &processed); - - if (error == 0) - return (processed); - else - { - http->error = error; - return (-1); - } -# endif /* HAVE_LIBSSL */ -} - - -# if defined(HAVE_CDSASSL) -/* - * 'CDSAReadFunc()' - Read function for CDSA decryption code. - */ - -static OSStatus /* O - -1 on error, 0 on success */ -CDSAReadFunc(SSLConnectionRef connection, /* I - SSL/TLS connection */ - void *data, /* I - Data buffer */ - size_t *dataLength) /* IO - Number of bytes */ -{ - ssize_t bytes; /* Number of bytes read */ - -#ifdef DEBUG_HTTP - httpDumpData(stdout, "CDSAReadFunc:", data, *dataLength); -#endif - bytes = recv((int)connection, data, *dataLength, 0); - if (bytes >= 0) - { - *dataLength = bytes; - return (0); - } - else - return (-1); -} - - -/* - * 'CDSAWriteFunc()' - Write function for CDSA encryption code. - */ - -static OSStatus /* O - -1 on error, 0 on success */ -CDSAWriteFunc(SSLConnectionRef connection, /* I - SSL/TLS connection */ - const void *data, /* I - Data buffer */ - size_t *dataLength) /* IO - Number of bytes */ -{ - ssize_t bytes; - - - bytes = write((int)connection, data, *dataLength); - if (bytes >= 0) - { - *dataLength = bytes; - return (0); - } - else - return (-1); -} -# endif /* HAVE_CDSASSL */ -#endif /* HAVE_SSL */ - - -/* - * End of "$Id: http.c 148 2006-04-25 16:54:17Z njacobs $" - */ diff --git a/usr/src/lib/print/libhttp-core/common/http.h b/usr/src/lib/print/libhttp-core/common/http.h deleted file mode 100644 index 593b7b68f6..0000000000 --- a/usr/src/lib/print/libhttp-core/common/http.h +++ /dev/null @@ -1,439 +0,0 @@ -/* - * "$Id: http.h 148 2006-04-25 16:54:17Z njacobs $" - * - * Hyper-Text Transport Protocol definitions for the Common UNIX Printing - * System (CUPS). - * - * Copyright 1997-2005 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Easy Software Products and are protected by Federal - * copyright law. Distribution and use rights are outlined in the file - * "LICENSE.txt" which should have been included with this file. If this - * file is missing or damaged please contact Easy Software Products - * at: - * - * Attn: CUPS Licensing Information - * Easy Software Products - * 44141 Airport View Drive, Suite 204 - * Hollywood, Maryland 20636 USA - * - * Voice: (301) 373-9600 - * EMail: cups-info@cups.org - * WWW: http://www.cups.org - * - * This file is subject to the Apple OS-Developed Software exception. - */ - -#ifndef _CUPS_HTTP_H_ -#define _CUPS_HTTP_H_ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Include necessary headers... - */ - -# include <string.h> -# include <time.h> -# ifdef WIN32 -# include <winsock.h> -# else -# include <unistd.h> -# include <sys/time.h> -# include <sys/types.h> -# include <sys/socket.h> -# include <netdb.h> -# include <netinet/in.h> -# include <arpa/inet.h> -# include <netinet/in_systm.h> -# include <netinet/ip.h> -# if !defined(__APPLE__) || !defined(TCP_NODELAY) -# include <netinet/tcp.h> -# endif /* !__APPLE__ || !TCP_NODELAY */ -# ifdef AF_LOCAL -# include <sys/un.h> -# endif /* AF_LOCAL */ -# endif /* WIN32 */ - - -/* - * C++ magic... - */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Oh, the wonderful world of IPv6 compatibility. Apparently some - * implementations expose the (more logical) 32-bit address parts - * to everyone, while others only expose it to kernel code... To - * make supporting IPv6 even easier, each vendor chose different - * core structure and union names, so the same defines or code - * can't be used on all platforms. - * - * The following will likely need tweeking on new platforms that - * support IPv6 - the "s6_addr32" define maps to the 32-bit integer - * array in the in6_addr union, which is named differently on various - * platforms. - */ - -#if defined(AF_INET6) && !defined(s6_addr32) -# if defined(__sun) -# define s6_addr32 _S6_un._S6_u32 -# elif defined(__FreeBSD__) || defined(__APPLE__) -# define s6_addr32 __u6_addr.__u6_addr32 -# endif /* __sun */ -#endif /* AF_INET6 && !s6_addr32 */ - - -/* - * Limits... - */ - -# define HTTP_MAX_URI 1024 /* Max length of URI string */ -# define HTTP_MAX_HOST 256 /* Max length of hostname string */ -# define HTTP_MAX_BUFFER 2048 /* Max length of data buffer */ -# define HTTP_MAX_VALUE 256 /* Max header field value length */ - - -/* - * HTTP state values... - */ - -typedef enum /* States are server-oriented */ -{ - HTTP_WAITING, /* Waiting for command */ - HTTP_OPTIONS, /* OPTIONS command, waiting for blank line */ - HTTP_GET, /* GET command, waiting for blank line */ - HTTP_GET_SEND, /* GET command, sending data */ - HTTP_HEAD, /* HEAD command, waiting for blank line */ - HTTP_POST, /* POST command, waiting for blank line */ - HTTP_POST_RECV, /* POST command, receiving data */ - HTTP_POST_SEND, /* POST command, sending data */ - HTTP_PUT, /* PUT command, waiting for blank line */ - HTTP_PUT_RECV, /* PUT command, receiving data */ - HTTP_DELETE, /* DELETE command, waiting for blank line */ - HTTP_TRACE, /* TRACE command, waiting for blank line */ - HTTP_CLOSE, /* CLOSE command, waiting for blank line */ - HTTP_STATUS /* Command complete, sending status */ -} http_state_t; - - -/* - * HTTP version numbers... - */ - -typedef enum -{ - HTTP_0_9 = 9, /* HTTP/0.9 */ - HTTP_1_0 = 100, /* HTTP/1.0 */ - HTTP_1_1 = 101 /* HTTP/1.1 */ -} http_version_t; - - -/* - * HTTP keep-alive values... - */ - -typedef enum -{ - HTTP_KEEPALIVE_OFF = 0, - HTTP_KEEPALIVE_ON -} http_keepalive_t; - - -/* - * HTTP transfer encoding values... - */ - -typedef enum -{ - HTTP_ENCODE_LENGTH, /* Data is sent with Content-Length */ - HTTP_ENCODE_CHUNKED /* Data is chunked */ -} http_encoding_t; - - -/* - * HTTP encryption values... - */ - -typedef enum -{ - HTTP_ENCRYPT_IF_REQUESTED, /* Encrypt if requested (TLS upgrade) */ - HTTP_ENCRYPT_NEVER, /* Never encrypt */ - HTTP_ENCRYPT_REQUIRED, /* Encryption is required (TLS upgrade) */ - HTTP_ENCRYPT_ALWAYS /* Always encrypt (SSL) */ -} http_encryption_t; - - -/* - * HTTP authentication types... - */ - -typedef enum -{ - HTTP_AUTH_NONE, /* No authentication in use */ - HTTP_AUTH_BASIC, /* Basic authentication in use */ - HTTP_AUTH_MD5, /* Digest authentication in use */ - HTTP_AUTH_MD5_SESS, /* MD5-session authentication in use */ - HTTP_AUTH_MD5_INT, /* Digest authentication in use for body */ - HTTP_AUTH_MD5_SESS_INT /* MD5-session authentication in use for body */ -} http_auth_t; - - -/* - * HTTP status codes... - */ - -typedef enum -{ - HTTP_ERROR = -1, /* An error response from httpXxxx() */ - - HTTP_CONTINUE = 100, /* Everything OK, keep going... */ - HTTP_SWITCHING_PROTOCOLS, /* HTTP upgrade to TLS/SSL */ - - HTTP_OK = 200, /* OPTIONS/GET/HEAD/POST/TRACE command was successful */ - HTTP_CREATED, /* PUT command was successful */ - HTTP_ACCEPTED, /* DELETE command was successful */ - HTTP_NOT_AUTHORITATIVE, /* Information isn't authoritative */ - HTTP_NO_CONTENT, /* Successful command, no new data */ - HTTP_RESET_CONTENT, /* Content was reset/recreated */ - HTTP_PARTIAL_CONTENT, /* Only a partial file was recieved/sent */ - - HTTP_MULTIPLE_CHOICES = 300, /* Multiple files match request */ - HTTP_MOVED_PERMANENTLY, /* Document has moved permanently */ - HTTP_MOVED_TEMPORARILY, /* Document has moved temporarily */ - HTTP_SEE_OTHER, /* See this other link... */ - HTTP_NOT_MODIFIED, /* File not modified */ - HTTP_USE_PROXY, /* Must use a proxy to access this URI */ - - HTTP_BAD_REQUEST = 400, /* Bad request */ - HTTP_UNAUTHORIZED, /* Unauthorized to access host */ - HTTP_PAYMENT_REQUIRED, /* Payment required */ - HTTP_FORBIDDEN, /* Forbidden to access this URI */ - HTTP_NOT_FOUND, /* URI was not found */ - HTTP_METHOD_NOT_ALLOWED, /* Method is not allowed */ - HTTP_NOT_ACCEPTABLE, /* Not Acceptable */ - HTTP_PROXY_AUTHENTICATION, /* Proxy Authentication is Required */ - HTTP_REQUEST_TIMEOUT, /* Request timed out */ - HTTP_CONFLICT, /* Request is self-conflicting */ - HTTP_GONE, /* Server has gone away */ - HTTP_LENGTH_REQUIRED, /* A content length or encoding is required */ - HTTP_PRECONDITION, /* Precondition failed */ - HTTP_REQUEST_TOO_LARGE, /* Request entity too large */ - HTTP_URI_TOO_LONG, /* URI too long */ - HTTP_UNSUPPORTED_MEDIATYPE, /* The requested media type is unsupported */ - HTTP_UPGRADE_REQUIRED = 426, /* Upgrade to SSL/TLS required */ - - HTTP_SERVER_ERROR = 500, /* Internal server error */ - HTTP_NOT_IMPLEMENTED, /* Feature not implemented */ - HTTP_BAD_GATEWAY, /* Bad gateway */ - HTTP_SERVICE_UNAVAILABLE, /* Service is unavailable */ - HTTP_GATEWAY_TIMEOUT, /* Gateway connection timed out */ - HTTP_NOT_SUPPORTED /* HTTP version not supported */ -} http_status_t; - - -/* - * HTTP field names... - */ - -typedef enum -{ - HTTP_FIELD_UNKNOWN = -1, - HTTP_FIELD_ACCEPT_LANGUAGE, - HTTP_FIELD_ACCEPT_RANGES, - HTTP_FIELD_AUTHORIZATION, - HTTP_FIELD_CONNECTION, - HTTP_FIELD_CONTENT_ENCODING, - HTTP_FIELD_CONTENT_LANGUAGE, - HTTP_FIELD_CONTENT_LENGTH, - HTTP_FIELD_CONTENT_LOCATION, - HTTP_FIELD_CONTENT_MD5, - HTTP_FIELD_CONTENT_RANGE, - HTTP_FIELD_CONTENT_TYPE, - HTTP_FIELD_CONTENT_VERSION, - HTTP_FIELD_DATE, - HTTP_FIELD_HOST, - HTTP_FIELD_IF_MODIFIED_SINCE, - HTTP_FIELD_IF_UNMODIFIED_SINCE, - HTTP_FIELD_KEEP_ALIVE, - HTTP_FIELD_LAST_MODIFIED, - HTTP_FIELD_LINK, - HTTP_FIELD_LOCATION, - HTTP_FIELD_RANGE, - HTTP_FIELD_REFERER, - HTTP_FIELD_RETRY_AFTER, - HTTP_FIELD_TRANSFER_ENCODING, - HTTP_FIELD_UPGRADE, - HTTP_FIELD_USER_AGENT, - HTTP_FIELD_WWW_AUTHENTICATE, - HTTP_FIELD_MAX -} http_field_t; - - -/* - * HTTP address structure (makes using IPv6 a little easier and more portable.) - */ - -typedef union -{ - struct sockaddr addr; /* Base structure for family value */ - struct sockaddr_in ipv4; /* IPv4 address */ -#ifdef AF_INET6 - struct sockaddr_in6 ipv6; /* IPv6 address */ -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - struct sockaddr_un un; /* Domain socket file */ -#endif /* AF_LOCAL */ - char pad[128]; /* Pad to ensure binary compatibility */ -} http_addr_t; - -/* - * HTTP connection structure... - */ - -typedef struct -{ - int fd; /* File descriptor for this socket */ - int blocking; /* To block or not to block */ - int error; /* Last error on read */ - time_t activity; /* Time since last read/write */ - http_state_t state; /* State of client */ - http_status_t status; /* Status of last request */ - http_version_t version; /* Protocol version */ - http_keepalive_t keep_alive; /* Keep-alive supported? */ - struct sockaddr_in oldaddr; /* Address of connected host */ - char hostname[HTTP_MAX_HOST], - /* Name of connected host */ - fields[HTTP_FIELD_MAX][HTTP_MAX_VALUE]; - /* Field values */ - char *data; /* Pointer to data buffer */ - http_encoding_t data_encoding; /* Chunked or not */ - int data_remaining; /* Number of bytes left */ - int used; /* Number of bytes used in buffer */ - char buffer[HTTP_MAX_BUFFER]; - /* Buffer for messages */ - int auth_type; /* Authentication in use */ - char nonce[HTTP_MAX_VALUE]; - /* Nonce value */ - int nonce_count; /* Nonce count */ - void *tls; /* TLS state information */ - http_encryption_t encryption; /* Encryption requirements */ - /**** New in CUPS 1.1.19 ****/ - fd_set *input_set; /* select() set for httpWait() */ - http_status_t expect; /* Expect: header */ - char *cookie; /* Cookie value(s) */ - /**** New in CUPS 1.1.20 ****/ - char authstring[HTTP_MAX_VALUE], - /* Current Authentication value */ - userpass[HTTP_MAX_VALUE]; - /* Username:password string */ - int digest_tries; /* Number of tries for digest auth */ - /**** New in CUPS 1.2 ****/ - http_addr_t hostaddr; /* Host address and port */ -} http_t; - - -/* - * Prototypes... - */ - -# define httpBlocking(http,b) (http)->blocking = (b) -extern int httpCheck(http_t *http); -# define httpClearFields(http) memset((http)->fields, 0, sizeof((http)->fields)),\ - httpSetField((http), HTTP_FIELD_HOST, (http)->hostname) -extern void httpClose(http_t *http); -extern http_t *httpConnect(const char *host, int port); -extern http_t *httpConnectEncrypt(const char *host, int port, - http_encryption_t encrypt); -extern int httpDelete(http_t *http, const char *uri); -extern int httpEncryption(http_t *http, http_encryption_t e); -# define httpError(http) ((http)->error) -extern void httpFlush(http_t *http); -extern int httpGet(http_t *http, const char *uri); -extern char *httpGets(char *line, int length, http_t *http); -extern const char *httpGetDateString(time_t t); -extern time_t httpGetDateTime(const char *s); -# define httpGetField(http,field) (http)->fields[field] -extern struct hostent *httpGetHostByName(const char *name); -extern char *httpGetSubField(http_t *http, http_field_t field, - const char *name, char *value); -extern int httpHead(http_t *http, const char *uri); -extern void httpInitialize(void); -extern int httpOptions(http_t *http, const char *uri); -extern int httpPost(http_t *http, const char *uri); -extern int httpPrintf(http_t *http, const char *format, ...) -# ifdef __GNUC__ -__attribute__ ((__format__ (__printf__, 2, 3))) -# endif /* __GNUC__ */ -; -extern int httpPut(http_t *http, const char *uri); -extern int httpRead(http_t *http, char *buffer, int length); -extern int httpReconnect(http_t *http); -extern void httpSeparate(const char *uri, char *method, - char *username, char *host, int *port, - char *resource); -extern void httpSetField(http_t *http, http_field_t field, - const char *value); -extern const char *httpStatus(http_status_t status); -extern int httpTrace(http_t *http, const char *uri); -extern http_status_t httpUpdate(http_t *http); -extern int httpWrite(http_t *http, const char *buffer, int length); -extern char *httpEncode64(char *out, const char *in); -extern char *httpDecode64(char *out, const char *in); -extern int httpGetLength(http_t *http); -extern char *httpMD5(const char *, const char *, const char *, - char [33]); -extern char *httpMD5Final(const char *, const char *, const char *, - char [33]); -extern char *httpMD5String(const unsigned char *, char [33]); - -/**** New in CUPS 1.1.19 ****/ -extern void httpClearCookie(http_t *http); -#define httpGetCookie(http) ((http)->cookie) -extern void httpSetCookie(http_t *http, const char *cookie); -extern int httpWait(http_t *http, int msec); - -/**** New in CUPS 1.1.21 ****/ -extern char *httpDecode64_2(char *out, int *outlen, const char *in); -extern char *httpEncode64_2(char *out, int outlen, const char *in, - int inlen); -extern void httpSeparate2(const char *uri, - char *method, int methodlen, - char *username, int usernamelen, - char *host, int hostlen, int *port, - char *resource, int resourcelen); - -/**** New in CUPS 1.2 ****/ -extern int httpAddrAny(const http_addr_t *addr); -extern int httpAddrEqual(const http_addr_t *addr1, - const http_addr_t *addr2); -extern void httpAddrLoad(const struct hostent *host, int port, - int n, http_addr_t *addr); -extern int httpAddrLocalhost(const http_addr_t *addr); -extern char *httpAddrLookup(const http_addr_t *addr, - char *name, int namelen); -extern char *httpAddrString(const http_addr_t *addr, - char *s, int slen); - -#include <stdio.h> -extern void httpDumpData(FILE *, const char *, const char *, int); - - -/* - * C++ magic... - */ - -#ifdef __cplusplus -} -#endif - -#endif /* !_CUPS_HTTP_H_ */ - -/* - * End of "$Id: http.h 148 2006-04-25 16:54:17Z njacobs $" - */ diff --git a/usr/src/lib/print/libipp-core/Makefile.com b/usr/src/lib/print/libipp-core/Makefile.com deleted file mode 100644 index 26f48c2dbb..0000000000 --- a/usr/src/lib/print/libipp-core/Makefile.com +++ /dev/null @@ -1,59 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY = libipp-core.a -VERS = .0 -OBJECTS = ipp.o ipp_types.o read.o strings.o write.o - -include ../../../Makefile.lib -include ../../../Makefile.rootfs - -SRCDIR = ../common - -ROOTLIBDIR= $(ROOT)/usr/lib - -LIBS = $(DYNLIB) - -$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRCDIR) -CPPFLAGS += -I../../libpapi-common/common - -CERRWARN += -_gcc=-Wno-unused-variable -CERRWARN += -_gcc=-Wno-char-subscripts -CERRWARN += -_gcc=-Wno-switch - -MAPFILES = $(SRCDIR)/mapfile - -LDLIBS += -lpapi-common -lc - -.KEEP_STATE: - -all: $(LIBS) - -lint: lintcheck - -include ../../../Makefile.targ diff --git a/usr/src/lib/print/libipp-core/common/ipp.c b/usr/src/lib/print/libipp-core/common/ipp.c deleted file mode 100644 index 133fb0ad13..0000000000 --- a/usr/src/lib/print/libipp-core/common/ipp.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: ipp.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdarg.h> -#include <papi.h> -#include "ipp.h" - -/* - * IPP requests/responses are represented as attribute lists. An IPP request - * attribute list will contain header information attributes: - * version-major (int) - * version-minor (int) - * request-id (int) - * operation-id (int) - * It will also contain 1 or more attribute groups (collections) - * operational-attribute-group - * ... - * this routine validates that the request falls within the guidelines of - * the protocol specification (or some other level of conformance if the - * restrictions have been specified at the top level of the request using - * a "conformance" attribute. - */ -papi_status_t -ipp_validate_request(papi_attribute_t **request, papi_attribute_t ***response) -{ - papi_attribute_t **attributes = NULL; - papi_status_t result = PAPI_OK; - char *s; - - if ((request == NULL) || (response == NULL) || (*response == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* validate the operational attributes group */ - result = papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &attributes); - if (result != PAPI_OK) { - ipp_set_status(response, result, - "operational attribute group: %s", - papiStatusString(result)); - return (result); - } - - result = papiAttributeListGetString(attributes, NULL, - "attributes-charset", &s); - if (result != PAPI_OK) { - ipp_set_status(response, result, "attributes-charset: %s", - papiStatusString(result)); - return (result); - } - - result = papiAttributeListGetString(attributes, NULL, - "attributes-natural-language", &s); - if (result != PAPI_OK) { - ipp_set_status(response, result, - "attributes-natural-language: %s", - papiStatusString(result)); - return (result); - } - - return (result); -} - -/* - * Add/Modify the statuse-code and status-message in an IPP response's - * operational attributes group. - */ -void -ipp_set_status(papi_attribute_t ***message, papi_status_t status, - char *format, ...) -{ - if (message == NULL) - return; - - if (format != NULL) { - papi_attribute_t **operational = NULL; - papi_attribute_t **saved; - char mesg[256]; /* status-message is type text(255) */ - va_list ap; - - (void) papiAttributeListGetCollection(*message, NULL, - "operational-attributes-group", - &operational); - saved = operational; - - va_start(ap, format); - (void) vsnprintf(mesg, sizeof (mesg), format, ap); - va_end(ap); - - (void) papiAttributeListAddString(&operational, - PAPI_ATTR_APPEND, "status-message", mesg); - - /* - * We need to check and see if adding the status-message caused - * the operational attributes group to be relocated in memory. - * If it has been, we will need to re-add the collection to - * the message. - */ - if (saved != operational) - (void) papiAttributeListAddCollection(message, - PAPI_ATTR_REPLACE, - "operational-attributes-group", - operational); - } - - (void) papiAttributeListAddInteger(message, PAPI_ATTR_APPEND, - "status-code", status); -} diff --git a/usr/src/lib/print/libipp-core/common/ipp.h b/usr/src/lib/print/libipp-core/common/ipp.h deleted file mode 100644 index c13728e334..0000000000 --- a/usr/src/lib/print/libipp-core/common/ipp.h +++ /dev/null @@ -1,348 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -#ifndef _IPP_H -#define _IPP_H - -/* $Id: ipp.h 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdarg.h> -#include <sys/time.h> -#include <papi.h> -#include <inttypes.h> - - -typedef ssize_t (*ipp_reader_t)(void *fd, void *buffer, size_t buffer_size); -typedef ssize_t (*ipp_writer_t)(void *fd, void *buffer, size_t buffer_size); - -enum { - IPP_TYPE_UNKNOWN = 0, - IPP_TYPE_REQUEST = 1, - IPP_TYPE_RESPONSE = 2 -}; - -/* - * How closely do we conform to the spec when parsing? Do we - * a) Stop parsing only when we encounter an error that prevents us from - * continuing parsing (a server error or ridiculously malformed request)? - * b) Stop parsing when we know the server wouldn't be able to act on the - * response correctly, even if we can make sense of some of the data? - * c) Jawohl, Mein IPP Spec! - * The answer will usually be b, though a will be useful for debugging. - */ -enum { - IPP_PARSE_CONFORMANCE_RASH = 0, - IPP_PARSE_CONFORMANCE_LOOSE = 1, - IPP_PARSE_CONFORMANCE_STRICT = 2 -}; - - -/* Operation IDs */ -enum { - OPID_MIN = 0x0000, /* 0x0000 */ - OPID_RESERVED_0000 = 0x0000, /* 0x0000 */ - OPID_RESERVED_0001, /* 0x0001 */ - OPID_PRINT_JOB, /* 0x0002 */ - OPID_PRINT_URI, /* 0x0003 */ - OPID_VALIDATE_JOB, /* 0x0004 */ - OPID_CREATE_JOB, /* 0x0005 */ - OPID_SEND_DOCUMENT, /* 0x0006 */ - OPID_SEND_URI, /* 0x0007 */ - OPID_CANCEL_JOB, /* 0x0008 */ - OPID_GET_JOB_ATTRIBUTES, /* 0x0009 */ - OPID_GET_JOBS, /* 0x000a */ - OPID_GET_PRINTER_ATTRIBUTES, /* 0x000b */ - OPID_HOLD_JOB, /* 0x000c */ - OPID_RELEASE_JOB, /* 0x000d */ - OPID_RESTART_JOB, /* 0x000e */ - OPID_RESERVED_000F, /* 0x000f */ - OPID_PAUSE_PRINTER, /* 0x0010 */ - OPID_RESUME_PRINTER, /* 0x0011 */ - OPID_PURGE_JOBS, /* 0x0012 */ - OPID_SET_PRINTER_ATTRIBUTES, /* 0x0013 */ - OPID_SET_JOB_ATTRIBUTES, /* 0x0014 */ - OPID_GET_PRINTER_SUPPORTED_VALUES, /* 0x0015 */ - OPID_CREATE_PRINTER_SUBSCRIPTION, /* 0x0016 */ - OPID_CREATE_JOB_SUBSCRIPTION, /* 0x0017 */ - OPID_GET_SUBSCRIPTION_ATTRIBUTES, /* 0x0018 */ - OPID_GET_SUBSCRIPTIONS, /* 0x0019 */ - OPID_RENEW_SUBSCRIPTION, /* 0x001a */ - OPID_CANCEL_SUBSCRIPTION, /* 0x001b */ - OPID_GET_NOTIFICATIONS, /* 0x001c */ - OPID_SEND_NOTIFICATIONS, /* 0x001d */ - OPID_GET_RESOURCE_ATTRIBUTES, /* 0x001e */ - OPID_GET_RESOURCE_DATA, /* 0x001f */ - OPID_GET_RESOURCES, /* 0x0020 */ - OPID_GET_PRINT_SUPPORT_FILES, /* 0x0021 */ - OPID_ENABLE_PRINTER, /* 0x0022 */ - OPID_DISABLE_PRINTER, /* 0x0023 */ - OPID_PAUSE_PRINTER_AFTER_CURRENT_JOB, /* 0x0024 */ - OPID_HOLD_NEW_JOBS, /* 0x0025 */ - OPID_RELEASE_HELD_NEW_JOBS, /* 0x0026 */ - OPID_DEACTIVATE_PRINTER, /* 0x0027 */ - OPID_ACTIVATE_PRINTER, /* 0x0028 */ - OPID_RESTART_PRINTER, /* 0x0029 */ - OPID_SHUTDOWN_PRINTER, /* 0x002a */ - OPID_STARTUP_PRINTER, /* 0x002b */ - OPID_REPROCESS_JOB, /* 0x002c */ - OPID_CANCEL_CURRENT_JOB, /* 0x002d */ - OPID_SUSPEND_CURRENT_JOB, /* 0x002e */ - OPID_RESUME_JOB, /* 0x002f */ - OPID_PROMOTE_JOB, /* 0x0030 */ - OPID_SCHEDULE_JOB_AFTER, /* 0x0031 */ - OPID_RESERVED_MIN, /* 0x0032 */ - OPID_RESERVED_0032 = 0x0032, /* 0x0032 */ - /* ... */ - OPID_RESERVED_3FFF = 0x3fff, /* 0x3fff */ - OPID_RESERVED_MAX = 0x3fff, /* 0x3fff */ - OPID_RESERVED_VENDOR_MIN = 0x4000, /* 0x4000 */ - OPID_RESERVED_VENDOR_4000 = 0x4000, /* 0x4000 */ - /* ... */ - OPID_RESERVED_VENDOR_8FFF = 0x8fff, /* 0x8fff */ - OPID_RESERVED_VENDOR_MAX = 0x8fff, /* 0x8fff */ - OPID_MAX = 0x8fff /* 0x8fff */ -}; - -enum { - /* Delimiter Tags */ - DTAG_MIN = 0x00, /* 0x00 */ - DTAG_RESERVED_DELIMITER_00 = 0x00, /* 0x00 */ - DTAG_OPERATION_ATTRIBUTES, /* 0x01 */ - DTAG_JOB_ATTRIBUTES, /* 0x02 */ - DTAG_END_OF_ATTRIBUTES, /* 0x03 */ - DTAG_PRINTER_ATTRIBUTES, /* 0x04 */ - DTAG_UNSUPPORTED_ATTRIBUTES, /* 0x05 */ - DTAG_SUBSCRIPTION_ATTRIBUTES, /* 0x06 */ - DTAG_EVENT_NOTIFICATION_ATTRIBUTES, /* 0x07 */ - DTAG_RESERVED_DELIMITER_08, /* 0x08 */ - DTAG_RESERVED_DELIMITER_09, /* 0x09 */ - DTAG_RESERVED_DELIMITER_0A, /* 0x0a */ - DTAG_RESERVED_DELIMITER_0B, /* 0x0b */ - DTAG_RESERVED_DELIMITER_0C, /* 0x0c */ - DTAG_RESERVED_DELIMITER_0D, /* 0x0d */ - DTAG_RESERVED_DELIMITER_0E, /* 0x0e */ - DTAG_RESERVED_DELIMITER_0F, /* 0x0f */ - DTAG_MAX = 0x0f, /* 0x0f */ - - /* Value Tags */ - VTAG_MIN = 0x10, /* 0x10 */ - VTAG_UNSUPPORTED = 0x10, /* 0x10 */ - VTAG_RESERVED_DEFAULT, /* 0x11 */ - VTAG_UNKNOWN, /* 0x12 */ - VTAG_NOVALUE, /* 0x13 */ - VTAG_RESERVED_OOB_14, /* 0x14 */ - VTAG_NOT_SETTABLE, /* 0x15 */ - VTAG_DELETE_ATTRIBUTE, /* 0x16 */ - VTAG_ADMIN_DEFINE, /* 0x17 */ - VTAG_RESERVED_OOB_18, /* 0x18 */ - VTAG_RESERVED_OOB_19, /* 0x19 */ - VTAG_RESERVED_OOB_1A, /* 0x1a */ - VTAG_RESERVED_OOB_1B, /* 0x1b */ - VTAG_RESERVED_OOB_1C, /* 0x1c */ - VTAG_RESERVED_OOB_1D, /* 0x1d */ - VTAG_RESERVED_OOB_1E, /* 0x1e */ - VTAG_RESERVED_OOB_1F, /* 0x1f */ - VTAG_RESERVED_INT_GEN, /* 0x20 */ - VTAG_INTEGER, /* 0x21 */ - VTAG_BOOLEAN, /* 0x22 */ - VTAG_ENUM, /* 0x23 */ - VTAG_RESERVED_INT_24, /* 0x24 */ - VTAG_RESERVED_INT_25, /* 0x25 */ - VTAG_RESERVED_INT_26, /* 0x26 */ - VTAG_RESERVED_INT_27, /* 0x27 */ - VTAG_RESERVED_INT_28, /* 0x28 */ - VTAG_RESERVED_INT_29, /* 0x29 */ - VTAG_RESERVED_INT_2A, /* 0x2a */ - VTAG_RESERVED_INT_2B, /* 0x2b */ - VTAG_RESERVED_INT_2C, /* 0x2c */ - VTAG_RESERVED_INT_2D, /* 0x2d */ - VTAG_RESERVED_INT_2E, /* 0x2e */ - VTAG_RESERVED_INT_2F, /* 0x2f */ - VTAG_OCTET_STRING, /* 0x30 */ - VTAG_DATE_TIME, /* 0x31 */ - VTAG_RESOLUTION, /* 0x32 */ - VTAG_RANGE_OF_INTEGER, /* 0x33 */ - VTAG_BEGIN_COLLECTION, /* 0x34 */ - VTAG_TEXT_WITH_LANGUAGE, /* 0x35 */ - VTAG_NAME_WITH_LANGUAGE, /* 0x36 */ - VTAG_END_COLLECTION, /* 0x37 */ - VTAG_RESERVED_STRING_38, /* 0x38 */ - VTAG_RESERVED_STRING_39, /* 0x39 */ - VTAG_RESERVED_STRING_3A, /* 0x3a */ - VTAG_RESERVED_STRING_3B, /* 0x3b */ - VTAG_RESERVED_STRING_3C, /* 0x3c */ - VTAG_RESERVED_STRING_3D, /* 0x3d */ - VTAG_RESERVED_STRING_3E, /* 0x3e */ - VTAG_RESERVED_STRING_3F, /* 0x3f */ - VTAG_RESERVED_CHAR_GEN, /* 0x40 */ - VTAG_TEXT_WITHOUT_LANGUAGE, /* 0x41 */ - VTAG_NAME_WITHOUT_LANGUAGE, /* 0x42 */ - VTAG_RESERVED_43, /* 0x43 */ - VTAG_KEYWORD, /* 0x44 */ - VTAG_URI, /* 0x45 */ - VTAG_URI_SCHEME, /* 0x46 */ - VTAG_CHARSET, /* 0x47 */ - VTAG_NATURAL_LANGUAGE, /* 0x48 */ - VTAG_MIME_MEDIA_TYPE, /* 0x49 */ - VTAG_MEMBER_ATTR_NAME, /* 0x4a */ - VTAG_RESERVED_STRING_4B, /* 0x4b */ - VTAG_RESERVED_STRING_4C, /* 0x4c */ - VTAG_RESERVED_STRING_4D, /* 0x4d */ - VTAG_RESERVED_STRING_4E, /* 0x4e */ - VTAG_RESERVED_STRING_4F, /* 0x4f */ - VTAG_RESERVED_STRING_50, /* 0x50 */ - VTAG_RESERVED_STRING_51, /* 0x51 */ - VTAG_RESERVED_STRING_52, /* 0x52 */ - VTAG_RESERVED_STRING_53, /* 0x53 */ - VTAG_RESERVED_STRING_54, /* 0x54 */ - VTAG_RESERVED_STRING_55, /* 0x55 */ - VTAG_RESERVED_STRING_56, /* 0x56 */ - VTAG_RESERVED_STRING_57, /* 0x57 */ - VTAG_RESERVED_STRING_58, /* 0x58 */ - VTAG_RESERVED_STRING_59, /* 0x59 */ - VTAG_RESERVED_STRING_5A, /* 0x5a */ - VTAG_RESERVED_STRING_5B, /* 0x5b */ - VTAG_RESERVED_STRING_5C, /* 0x5c */ - VTAG_RESERVED_STRING_5D, /* 0x5d */ - VTAG_RESERVED_STRING_5E, /* 0x5e */ - VTAG_RESERVED_STRING_5F, /* 0x5f */ - VTAG_RESERVED_MAX = 0x5f, /* 0x5f */ - VTAG_MAX = 0x5f, /* 0x5f */ - VTAG_EXTEND = 0x7f /* 0x7f */ -}; - -/* Response codes */ -enum { - IPP_OK_MIN = 0x0000, - IPP_OK = 0x0000, /* 0x0000 */ - IPP_OK_IGNORED_ATTRIBUTES, /* 0x0001 */ - IPP_OK_CONFLICTING_ATTRIBUTES, /* 0x0002 */ - IPP_OK_IGNORED_SUBSCRIPTIONS, /* 0x0003 */ - IPP_OK_IGNORED_NOTIFICATIONS, /* 0x0004 */ - IPP_OK_TOO_MANY_EVENTS, /* 0x0005 */ - IPP_OK_BUT_CANCEL_SUBSCRIPTION, /* 0x0006 */ - IPP_OK_MAX = IPP_OK_BUT_CANCEL_SUBSCRIPTION, - - IPP_REDIR_MIN = 0x0300, - IPP_REDIR_OTHER_SIZE = 0x0300, /* 0x0300 */ - IPP_REDIR_MAX = 0x0300, - - IPP_CERR_MIN = 0x0400, - IPP_CERR_BAD_REQUEST = 0x0400, /* 0x0400 */ - IPP_CERR_FORBIDDEN, /* 0x0401 */ - IPP_CERR_NOT_AUTHENTICATED, /* 0x0402 */ - IPP_CERR_NOT_AUTHORIZED, /* 0x0403 */ - IPP_CERR_NOT_POSSIBLE, /* 0x0404 */ - IPP_CERR_TIMEOUT, /* 0x0405 */ - IPP_CERR_NOT_FOUND, /* 0x0406 */ - IPP_CERR_GONE, /* 0x0407 */ - IPP_CERR_REQUEST_ENTITY, /* 0x0408 */ - IPP_CERR_REQUEST_VALUE, /* 0x0409 */ - IPP_CERR_DOCUMENT_FORMAT, /* 0x040a */ - IPP_CERR_ATTRIBUTES, /* 0x040b */ - IPP_CERR_URI_SCHEME, /* 0x040c */ - IPP_CERR_CHARSET, /* 0x040d */ - IPP_CERR_CONFLICT, /* 0x040e */ - IPP_CERR_COMPRESSION_NOT_SUPPORTED, /* 0x040f */ - IPP_CERR_COMPRESSION_ERROR, /* 0x0410 */ - IPP_CERR_DOCUMENT_FORMAT_ERROR, /* 0x0411 */ - IPP_CERR_DOCUMENT_ACCESS_ERROR, /* 0x0412 */ - IPP_CERR_ATTRIBUTES_NOT_SETTABLE, /* 0x0413 */ - IPP_CERR_IGNORED_ALL_SUBSCRIPTIONS, /* 0x0414 */ - IPP_CERR_TOO_MANY_SUBSCRIPTIONS, /* 0x0415 */ - IPP_CERR_IGNORED_ALL_NOTIFICATIONS, /* 0x0416 */ - IPP_CERR_PRINT_SUPPORT_FILE_NOT_FOUND, /* 0x0417 */ - IPP_CERR_MAX = IPP_CERR_PRINT_SUPPORT_FILE_NOT_FOUND, - - IPP_SERR_MIN = 0x0500, - IPP_SERR_INTERNAL = 0x0500, /* 0x0500 */ - IPP_SERR_OPERATION_NOT_SUPPORTED, /* 0x0501 */ - IPP_SERR_SERVICE_UNAVAILABLE, /* 0x0502 */ - IPP_SERR_VERSION_NOT_SUPPORTED, /* 0x0503 */ - IPP_SERR_DEVICE_ERROR, /* 0x0504 */ - IPP_SERR_TEMPORARY_ERROR, /* 0x0505 */ - IPP_SERR_NOT_ACCEPTING, /* 0x0506 */ - IPP_SERR_BUSY, /* 0x0507 */ - IPP_SERR_CANCELLED, /* 0x0508 */ - IPP_SERR_MULTIPLE_DOCS_NOT_SUPPORTED, /* 0x0509 */ - IPP_SERR_PRINTER_IS_DEACTIVATED, /* 0x050a */ - IPP_SERR_MAX = IPP_SERR_PRINTER_IS_DEACTIVATED -}; - -/* Job state codes */ -enum { - IPP_JOB_STATE_PENDING = 3, - IPP_JOB_STATE_PENDING_HELD = 4, - IPP_JOB_STATE_PROCESSING = 5, - IPP_JOB_STATE_PROCESSING_STOPPED = 6, - IPP_JOB_STATE_CANCELED = 7, - IPP_JOB_STATE_ABORTED = 8, - IPP_JOB_STATE_COMPLETED = 9 -}; - -/* exported functions */ -extern papi_status_t ipp_read_message(ipp_reader_t iread, void *fd, - papi_attribute_t ***message, char type); - -extern papi_status_t ipp_write_message(ipp_writer_t iwrite, void *fd, - papi_attribute_t **message); - -/* internal functions shared between modules */ -extern void ipp_set_status(papi_attribute_t ***message, papi_status_t status, - char *format, ...); -extern papi_status_t ipp_validate_request(papi_attribute_t **request, - papi_attribute_t ***response); - -extern int ipp_severity(int16_t status); - -extern int16_t ipp_charset_supported(char *charset); - -extern void *string_to_ipp_attr_value(int8_t type, char *value); - -extern char *ipp_uri_to_printer(char *uri); -extern void *papi_attribute_to_ipp_attr(int8_t type, papi_attribute_t *attr); - -extern int8_t name_to_ipp_type(char *name); -extern char *job_template[]; -extern char *job_description[]; -extern char *printer_description[]; -extern char *ipp_tag_string(int8_t tag, char *buf, size_t bufsiz); -extern size_t min_val_len(int8_t type, char *name); -extern size_t max_val_len(int8_t type, char *name); -extern int is_keyword(char *value); - -#ifdef __cplusplus -} -#endif - -#endif /* _IPP_H */ diff --git a/usr/src/lib/print/libipp-core/common/ipp_types.c b/usr/src/lib/print/libipp-core/common/ipp_types.c deleted file mode 100644 index 47fc32c259..0000000000 --- a/usr/src/lib/print/libipp-core/common/ipp_types.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: ipp_types.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <ipp.h> -#include <errno.h> -#include <values.h> - -#ifndef MININT -#define MININT (-MAXINT - 1) -#endif - -typedef struct { - char *name; - int8_t ipp_type; - int min; - int max; -} attr_info_list_t; - -static attr_info_list_t attr_list[] = { - {"operation-attribute-group", DTAG_OPERATION_ATTRIBUTES, 0, 0}, - {"job-attribute-group", DTAG_JOB_ATTRIBUTES, 0, 0}, - {"printer-attribute-group", DTAG_PRINTER_ATTRIBUTES, 0, 0}, - {"unsupported-attribute-group", DTAG_UNSUPPORTED_ATTRIBUTES, 0, 0}, - {"subscription-attribute-group", DTAG_SUBSCRIPTION_ATTRIBUTES, 0, 0}, - {"even-notificaton-attribute-group", - DTAG_EVENT_NOTIFICATION_ATTRIBUTES, 0, 0}, - {"attributes-charset", VTAG_CHARSET, 0, 255}, - {"attributes-natural-language", VTAG_NATURAL_LANGUAGE, 0, 255}, - {"charset-configured", VTAG_CHARSET, 0, 255}, - {"charset-supported", VTAG_CHARSET, 0, 255}, - {"color-supported", VTAG_BOOLEAN, 0, 1}, - {"compression", VTAG_KEYWORD, 1, 255}, - {"compression-supported", VTAG_KEYWORD, 1, 255}, - {"copies", VTAG_INTEGER, 1, MAXINT}, - {"copies-default", VTAG_INTEGER, 1, MAXINT}, - {"copies-supported", VTAG_RANGE_OF_INTEGER, 1, MAXINT}, - {"date-at-completed", VTAG_DATE_TIME, 0, 0}, - {"date-at-creation", VTAG_DATE_TIME, 0, 0}, - {"date-at-processing", VTAG_DATE_TIME, 0, 0}, - {"detailed-status-message", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 1023}, - {"document-access-error", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 1023}, - {"document-format", VTAG_MIME_MEDIA_TYPE, 0, 255}, - {"document-format-default", VTAG_MIME_MEDIA_TYPE, 0, 255}, - {"document-format-supported", VTAG_MIME_MEDIA_TYPE, 0, 255}, - {"document-name", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"document-name", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"document-natural-language", VTAG_NATURAL_LANGUAGE, 0, 255}, - {"finishing", VTAG_ENUM, 3, 31}, - {"finishing-default", VTAG_ENUM, 3, 31}, - {"finishing-supported", VTAG_ENUM, 3, 31}, - {"generated-natural-language-supported", VTAG_NATURAL_LANGUAGE, 0, 255}, - {"ipp-attribute-fidelity", VTAG_BOOLEAN, 0, 1}, - {"ipp-versions-supported", VTAG_KEYWORD, 1, 255}, - {"job-detailed-status-messages", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 1023}, - {"job-document-access-errors", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 1023}, - {"job-hold-until", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"job-hold-until-default", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"job-hold-until-supported", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"job-id", VTAG_INTEGER, 1, MAXINT}, - {"job-impressions", VTAG_INTEGER, 0, MAXINT}, - {"job-impressions-completed", VTAG_INTEGER, 0, MAXINT}, - {"job-impressions-supported", VTAG_RANGE_OF_INTEGER, 0, MAXINT}, - {"job-k-octets", VTAG_INTEGER, 0, MAXINT}, - {"job-k-octets-processed", VTAG_INTEGER, 0, MAXINT}, - {"job-k-octets-supported", VTAG_RANGE_OF_INTEGER, 0, MAXINT}, - {"job-media-sheets", VTAG_INTEGER, 0, MAXINT}, - {"job-media-sheets-completed", VTAG_INTEGER, 0, MAXINT}, - {"job-media-sheets-supported", VTAG_RANGE_OF_INTEGER, 0, MAXINT}, - {"job-message-from-operator", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 127}, - {"job-more-info", VTAG_URI, 0, 1023}, - {"job-name", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"job-originating-user-name", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"job-printer-up-time", VTAG_INTEGER, 1, MAXINT}, - {"job-printer-uri", VTAG_URI, 0, 1023}, - {"job-priority", VTAG_INTEGER, 1, 100}, - {"job-priority-default", VTAG_INTEGER, 1, 100}, - {"job-priority-supported", VTAG_INTEGER, 1, 100}, - {"job-sheets", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"job-sheets-default", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"job-sheets-supported", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"job-state", VTAG_ENUM, 3, 9}, - {"job-state-message", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 1023}, - {"job-state-reasons", VTAG_KEYWORD, 1, 255}, - {"job-uri", VTAG_URI, 0, 1023}, - {"last-document", VTAG_BOOLEAN, 0, 1}, - {"limit", VTAG_INTEGER, 1, MAXINT}, - {"media", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"media-default", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"media-supported", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"message", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 127}, - {"multiple-document-handling", VTAG_KEYWORD, 1, 255}, - {"multiple-document-handling-default", VTAG_KEYWORD, 1, 255}, - {"multiple-document-handling-supported", VTAG_KEYWORD, 1, 255}, - {"multiple-document-jobs-supported", VTAG_BOOLEAN, 0, 1}, - {"multiple-operation-time-out", VTAG_INTEGER, 1, MAXINT}, - {"my-jobs", VTAG_BOOLEAN, 0, 1}, - {"natural-language-configured", VTAG_NATURAL_LANGUAGE, 0, 255}, - {"number-of-documents", VTAG_INTEGER, 0, MAXINT}, - {"number-of-intervening-jobs", VTAG_INTEGER, 0, MAXINT}, - {"number-up", VTAG_INTEGER, 1, MAXINT}, - {"number-up-default", VTAG_INTEGER, 1, MAXINT}, - {"number-up-supported", VTAG_INTEGER, 1, MAXINT}, - {"operations-supported", VTAG_ENUM, 1, 0x8FFF}, - {"orientation-requested", VTAG_ENUM, 3, 6}, - {"orientation-requested-default", VTAG_ENUM, 3, 6}, - {"orientation-requested-supported", VTAG_ENUM, 3, 6}, - {"output-device-assigned", VTAG_NAME_WITHOUT_LANGUAGE, 0, 127}, - {"page-ranges", VTAG_RANGE_OF_INTEGER, 1, MAXINT}, - {"page-ranges-supported", VTAG_BOOLEAN, 0, 1}, - {"pages-per-minute", VTAG_INTEGER, 0, MAXINT}, - {"pages-per-minute-color", VTAG_INTEGER, 0, MAXINT}, - {"pdl-override-supported", VTAG_KEYWORD, 1, 255}, - {"print-quality", VTAG_ENUM, 3, 5}, - {"print-quality-default", VTAG_ENUM, 3, 5}, - {"print-quality-supported", VTAG_ENUM, 3, 5}, - {"printer-current-time", VTAG_DATE_TIME, 0, 1}, - {"printer-driver-installer", VTAG_URI, 0, 1023}, - {"printer-id", VTAG_INTEGER, 1, MAXINT}, - {"printer-info", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 127}, - {"printer-is-accepting-jobs", VTAG_BOOLEAN, 0, 1}, - {"printer-location", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 127}, - {"printer-make-and-model", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 127}, - {"printer-message-from-operator", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 127}, - {"printer-more-info", VTAG_URI, 0, 1023}, - {"printer-more-info-manufacturer", VTAG_URI, 0, 1023}, - {"printer-name", VTAG_NAME_WITHOUT_LANGUAGE, 0, 127}, - {"printer-resolution", VTAG_RESOLUTION, 0, 0}, - {"printer-resolution-default", VTAG_RESOLUTION, 0, 0}, - {"printer-resolution-supported", VTAG_RESOLUTION, 0, 0}, - {"printer-state", VTAG_ENUM, 3, 5}, - {"printer-state-message", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 1023}, - {"printer-state-reasons", VTAG_KEYWORD, 1, 255}, - {"printer-up-time", VTAG_INTEGER, 1, MAXINT}, - {"printer-uri", VTAG_URI, 0, 1023}, - {"printer-uri-supported", VTAG_URI, 0, 1023}, - {"queued-job-count", VTAG_INTEGER, 0, MAXINT}, - {"reference-uri-schemes-supported", VTAG_URI_SCHEME, 0, 63}, - {"requested-attributes", VTAG_KEYWORD, 1, 255}, - {"requesting-user-name", VTAG_NAME_WITHOUT_LANGUAGE, 0, 255}, - {"sides", VTAG_KEYWORD, 1, 255}, - {"sides-default", VTAG_KEYWORD, 1, 255}, - {"sides-supported", VTAG_KEYWORD, 1, 255}, - {"status-code", VTAG_ENUM, 1, 0x7FFF}, - {"status-message", VTAG_TEXT_WITHOUT_LANGUAGE, 0, 255}, - {"time-at-completed", VTAG_INTEGER, MININT, MAXINT}, - {"time-at-creation", VTAG_INTEGER, MININT, MAXINT}, - {"time-at-processing", VTAG_INTEGER, MININT, MAXINT}, - {"uri-authentication-supported", VTAG_KEYWORD, 1, 255}, - {"uri-security-supported", VTAG_KEYWORD, 1, 255}, - {"which-jobs", VTAG_KEYWORD, 1, 255}, - {NULL, 0, 0, 0} -}; - - -static attr_info_list_t * -get_attr_info_by_name(char *name) -{ - if (name != NULL) { - int i; - - for (i = 0; attr_list[i].name != NULL; i++) - if (strcasecmp(attr_list[i].name, name) == 0) - return (&attr_list[i]); - } - - return (NULL); -} - -size_t -max_val_len(int8_t type, char *name) -{ - attr_info_list_t *t; - int result; - - switch (type) { - case VTAG_INTEGER: - case VTAG_RANGE_OF_INTEGER: - case VTAG_ENUM: - result = MAXINT; - break; - case VTAG_URI: - case VTAG_OCTET_STRING: - case VTAG_TEXT_WITHOUT_LANGUAGE: - result = 1023; - break; - case VTAG_NATURAL_LANGUAGE: - case VTAG_URI_SCHEME: - case VTAG_CHARSET: - result = 63; - break; - case VTAG_NAME_WITHOUT_LANGUAGE: - case VTAG_MIME_MEDIA_TYPE: - case VTAG_KEYWORD: - result = 255; - break; - default: - result = MAXINT; - } - -#define min(a, b) ((a < b) ? a : b) - if ((t = get_attr_info_by_name(name)) != NULL) - result = min(t->max, result); -#undef min - - return (result); -} - -size_t -min_val_len(int8_t type, char *name) -{ - attr_info_list_t *t; - int result; - - switch (type) { - case VTAG_INTEGER: - case VTAG_RANGE_OF_INTEGER: - result = MININT; - break; - case VTAG_ENUM: - result = 1; - break; - case VTAG_URI: - case VTAG_OCTET_STRING: - case VTAG_TEXT_WITHOUT_LANGUAGE: - case VTAG_MIME_MEDIA_TYPE: - case VTAG_NAME_WITHOUT_LANGUAGE: - case VTAG_URI_SCHEME: - case VTAG_CHARSET: - case VTAG_NATURAL_LANGUAGE: - result = 0; - break; - case VTAG_KEYWORD: - result = 1; - break; - default: - result = MININT; - } - -#define max(a, b) ((a > b) ? a : b) - if ((t = get_attr_info_by_name(name)) != NULL) - result = max(t->min, result); -#undef max - - return (result); -} - -int -is_keyword(char *k) -{ - /* [a-z][a-z0-9._-]* */ - if (*k < 'a' && *k > 'z') - return (0); - while (*(++k) != '\0') - if (*k < 'a' && *k > 'z' && *k < '0' && *k > '9' && - *k != '.' && *k != '_' && *k != '-') - return (0); - return (1); -} - -int8_t -name_to_ipp_type(char *name) -{ - int i; - - if (name != NULL) - for (i = 0; attr_list[i].name != NULL; i++) - if (strcasecmp(attr_list[i].name, name) == 0) - return (attr_list[i].ipp_type); - - return (0); -} diff --git a/usr/src/lib/print/libipp-core/common/read.c b/usr/src/lib/print/libipp-core/common/read.c deleted file mode 100644 index 6127958f66..0000000000 --- a/usr/src/lib/print/libipp-core/common/read.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: read.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <alloca.h> -#include <string.h> -#include <stdarg.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <inttypes.h> - -#include <papi.h> -#include <ipp.h> - - -#define _ipp_tag_string(id) ipp_tag_string((id), buf, sizeof (buf)) - -static papi_status_t -read_name_with_language(ipp_reader_t iread, void *fd, - papi_attribute_t ***message) -{ - char *string; - uint16_t size; - - /* read the language */ - if (iread(fd, &size, 2) != 2) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "read failed: lang len\n"); - return (PAPI_BAD_REQUEST); - } - size = (uint16_t)ntohs(size); - - if ((string = alloca(size + 1)) == NULL) { - ipp_set_status(message, PAPI_TEMPORARY_ERROR, - "Memory allocation failed"); - return (PAPI_TEMPORARY_ERROR); - } - if (iread(fd, string, size) != size) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "read failed: lang\n"); - return (PAPI_BAD_REQUEST); - } - - /* read the text */ - if (iread(fd, &size, 2) != 2) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "read failed: text len\n"); - return (PAPI_BAD_REQUEST); - } - size = (uint16_t)ntohs(size); - - if ((string = alloca(size + 1)) == NULL) { - ipp_set_status(message, PAPI_TEMPORARY_ERROR, - "Memory allocation failed"); - return (PAPI_TEMPORARY_ERROR); - } - if (iread(fd, string, size) != size) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "read failed: text\n"); - return (PAPI_BAD_REQUEST); - } - - return (PAPI_OK); -} - - -static struct { - int8_t ipp_type; - int8_t size; -} type_info[] = { - { VTAG_INTEGER, 4 }, - { VTAG_ENUM, 4 }, - { VTAG_BOOLEAN, 1 }, - { VTAG_RANGE_OF_INTEGER, 8 }, - { VTAG_RESOLUTION, 9 }, - { VTAG_DATE_TIME, 11 }, - { DTAG_MIN, 0 } -}; - -/* verify that the IPP type and size are compatible */ -static int -validate_length(int8_t type, int8_t size) -{ - int i; - - for (i = 0; type_info[i].ipp_type != DTAG_MIN; i++) - if (type_info[i].ipp_type == type) - return ((type_info[i].size == size) ? 0 : -1); - return (0); -} - -/* convert tyep IPP type to a type that is marginally compatible */ -static int8_t -base_type(int8_t i) -{ - switch (i) { - case VTAG_ENUM: - case VTAG_INTEGER: - return (VTAG_INTEGER); - case VTAG_URI: - case VTAG_OCTET_STRING: - case VTAG_TEXT_WITHOUT_LANGUAGE: - case VTAG_URI_SCHEME: - case VTAG_CHARSET: - case VTAG_NATURAL_LANGUAGE: - case VTAG_MIME_MEDIA_TYPE: - case VTAG_NAME_WITHOUT_LANGUAGE: - case VTAG_KEYWORD: - return (VTAG_TEXT_WITHOUT_LANGUAGE); - case VTAG_BOOLEAN: - case VTAG_RANGE_OF_INTEGER: - case VTAG_DATE_TIME: - case VTAG_RESOLUTION: - default: - return (i); - } -} - -/* verify that the IPP type is correct for the named attribute */ -static papi_status_t -validate_type(char *name, int8_t type) -{ - int8_t t = name_to_ipp_type(name); - - if (t == 0) /* The attribute is not defined in the RFC */ - return (PAPI_NOT_FOUND); - else if (t == type) /* The supplied type matched the RFC type */ - return (PAPI_OK); - else { /* The supplied type doesn't match the RFC */ - if (base_type(t) == base_type(type)) - return (PAPI_OK); - - return (PAPI_CONFLICT); - } -} - -/* verify that the IPP value is within specification for the named attribute */ -static int -validate_value(papi_attribute_t ***message, char *name, int8_t type, ...) -{ -#define within(a, b, c) ((b >= a) && (b <= c)) - va_list ap; - int rc = -1; - int min = min_val_len(type, name), - max = max_val_len(type, name); - char buf[64]; /* For _ipp_<...>_string() */ - - va_start(ap, type); - switch (type) { - case VTAG_ENUM: - case VTAG_INTEGER: { - int32_t i = (int32_t)va_arg(ap, int32_t); - - if (within(min, i, max)) - rc = 0; - else - ipp_set_status(message, PAPI_BAD_ARGUMENT, - "%s(%s): %d: out of range (%d - %d)", name, - _ipp_tag_string(type), i, min, max); - } - break; - case VTAG_BOOLEAN: { - int8_t v = (int8_t)va_arg(ap, int); - - if (within(0, v, 1)) - rc = 0; - else - ipp_set_status(message, PAPI_BAD_ARGUMENT, - "%s(%s): %d: out of range (0 - 1)", name, - _ipp_tag_string(type), v); - } - break; - case VTAG_RANGE_OF_INTEGER: { - int32_t lower = (int32_t)va_arg(ap, int32_t); - int32_t upper = (int32_t)va_arg(ap, int32_t); - - if (within(min, lower, max) && - within(min, upper, max)) - rc = 0; - else - ipp_set_status(message, PAPI_BAD_ARGUMENT, - "%s(%s): %d - %d: out of range (%d - %d)", name, - _ipp_tag_string(type), lower, upper, min, max); - } - break; - case VTAG_URI: - case VTAG_OCTET_STRING: - case VTAG_TEXT_WITHOUT_LANGUAGE: - case VTAG_URI_SCHEME: - case VTAG_CHARSET: - case VTAG_NATURAL_LANGUAGE: - case VTAG_MIME_MEDIA_TYPE: - case VTAG_NAME_WITHOUT_LANGUAGE: { - char *v = (char *)va_arg(ap, char *); - - if (strlen(v) < max) - rc = 0; - else - ipp_set_status(message, PAPI_BAD_ARGUMENT, - "%s(%s): %s: too long (max length: %d)", name, - _ipp_tag_string(type), v, max); - } - break; - case VTAG_KEYWORD: { - char *v = (char *)va_arg(ap, char *); - - if (strlen(v) >= max) - ipp_set_status(message, PAPI_BAD_ARGUMENT, - "%s(%s): %s: too long (max length: %d)", name, - _ipp_tag_string(type), v, max); - else if (is_keyword(v) == 0) - ipp_set_status(message, PAPI_BAD_ARGUMENT, - "%s(%s): %s: invalid keyword", name, - _ipp_tag_string(type), v); - else - rc = 0; - } - break; - case VTAG_DATE_TIME: - case VTAG_RESOLUTION: - default: - rc = 0; - } - va_end(ap); - - return (rc); -#undef within -} - -/* - * read_attr_group() reads in enough of the message data to parse an entire - * attribute group. Since to determine that the group is finished you have to - * read the character that determines the type of the next group, this function - * must return that character, in order that our caller knows how to call us for - * the next group. Thus type is used both as an input parameter (the type of - * attribute group to read in) and an output parameter (the type of the next - * attribute group). - */ - -static papi_status_t -ipp_read_attribute_group(ipp_reader_t iread, void *fd, int8_t *type, - papi_attribute_t ***message) -{ - int8_t value_tag; - uint16_t name_length, value_length; - papi_attribute_t **attributes = NULL; - char *name = NULL; - int i; - char buf[64]; /* For _ipp_<...>_string() */ - - /* - * RFC2910 3.3 says we need to handle `An expected but missing - * "begin-attribute-group-tag" field. How? - */ - if (*type > DTAG_MAX) { - /* Scream bloody murder, or assign a new type? */ - ipp_set_status(message, PAPI_BAD_REQUEST, - "Bad attribute group tag 0x%.2hx (%s)", - *type, _ipp_tag_string(*type)); - return (PAPI_BAD_REQUEST); - } - - /* This loops through *values* not *attributes*! */ - for (i = 0; ; i++) { - papi_status_t valid = PAPI_OK; - if (iread(fd, &value_tag, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: value tag\n"); - return (PAPI_BAD_REQUEST); - } - /* are we done with this group ? */ - if (value_tag <= DTAG_MAX) - break; - - if (iread(fd, &name_length, 2) != 2) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: name length\n"); - return (PAPI_BAD_REQUEST); - } - name_length = (uint16_t)ntohs(name_length); - - /* Not just another value for the previous attribute */ - if (name_length != 0) { - if ((name = alloca(name_length + 1)) == NULL) { - ipp_set_status(message, PAPI_TEMPORARY_ERROR, - "alloca(): failed\n"); - return (PAPI_TEMPORARY_ERROR); - } - (void) memset(name, 0, name_length + 1); - - if (iread(fd, name, name_length) != name_length) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: name\n"); - return (PAPI_BAD_REQUEST); - } - } - - valid = validate_type(name, value_tag); - if ((valid != PAPI_OK) && (valid != PAPI_NOT_FOUND)) - ipp_set_status(message, valid, "%s(%s): %s", name, - _ipp_tag_string(value_tag), - papiStatusString(valid)); - - if (iread(fd, &value_length, 2) != 2) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: value length\n"); - return (PAPI_BAD_REQUEST); - } - value_length = (uint16_t)ntohs(value_length); - - if (validate_length(value_tag, value_length) < 0) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "Bad value length (%d) for type %s", - value_length, _ipp_tag_string(value_tag)); - return (PAPI_BAD_REQUEST); - } - - switch (value_tag) { - case VTAG_INTEGER: - case VTAG_ENUM: { - int32_t v; - - if (iread(fd, &v, value_length) != value_length) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: int/enum\n"); - return (PAPI_BAD_REQUEST); - } - v = (int32_t)ntohl(v); - (void) validate_value(message, name, value_tag, v); - papiAttributeListAddInteger(&attributes, - PAPI_ATTR_APPEND, name, v); - - } - break; - case VTAG_BOOLEAN: { - int8_t v; - - if (iread(fd, &v, value_length) != value_length) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: boolean\n"); - return (PAPI_BAD_REQUEST); - } - (void) validate_value(message, name, value_tag, v); - papiAttributeListAddBoolean(&attributes, - PAPI_ATTR_APPEND, name, v); - } - break; - case VTAG_RANGE_OF_INTEGER: { - int32_t min, max; - - if (iread(fd, &min, 4) != 4) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: min\n"); - return (PAPI_BAD_REQUEST); - } - if (iread(fd, &max, 4) != 4) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: max\n"); - return (PAPI_BAD_REQUEST); - } - min = (int32_t)ntohl(min); - max = (int32_t)ntohl(max); - (void) validate_value(message, name, value_tag, - min, max); - papiAttributeListAddRange(&attributes, PAPI_ATTR_APPEND, - name, min, max); - } - break; - case VTAG_RESOLUTION: { - int32_t x, y; - int8_t units; - - if (iread(fd, &x, 4) != 4) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: x\n"); - return (PAPI_BAD_REQUEST); - } - if (iread(fd, &y, 4) != 4) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: y\n"); - return (PAPI_BAD_REQUEST); - } - if (iread(fd, &units, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: units\n"); - return (PAPI_BAD_REQUEST); - } - x = (int32_t)ntohl(x); - y = (int32_t)ntohl(y); - papiAttributeListAddResolution(&attributes, - PAPI_ATTR_APPEND, name, x, y, - (papi_resolution_unit_t)units); - } - break; - case VTAG_DATE_TIME: { - struct tm tm; - time_t v; - int8_t c; - uint16_t s; - - (void) memset(&tm, 0, sizeof (tm)); - if (iread(fd, &s, 2) != 2) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: year\n"); - return (PAPI_BAD_REQUEST); - } - tm.tm_year = (uint16_t)ntohs(s) - 1900; - if (iread(fd, &c, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: month\n"); - return (PAPI_BAD_REQUEST); - } - tm.tm_mon = c - 1; - if (iread(fd, &c, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: day\n"); - return (PAPI_BAD_REQUEST); - } - tm.tm_mday = c; - if (iread(fd, &c, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: hour\n"); - return (PAPI_BAD_REQUEST); - } - tm.tm_hour = c; - if (iread(fd, &c, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: minutes\n"); - return (PAPI_BAD_REQUEST); - } - tm.tm_min = c; - if (iread(fd, &c, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: seconds\n"); - return (PAPI_BAD_REQUEST); - } - tm.tm_sec = c; - if (iread(fd, &c, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: decisec\n"); - return (PAPI_BAD_REQUEST); - } - /* tm.deciseconds = c; */ - if (iread(fd, &c, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: utc_dir\n"); - return (PAPI_BAD_REQUEST); - } - /* tm.utc_dir = c; */ - if (iread(fd, &c, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: utc_hour\n"); - return (PAPI_BAD_REQUEST); - } - /* tm.utc_hours = c; */ - if (iread(fd, &c, 1) != 1) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: utc_min\n"); - return (PAPI_BAD_REQUEST); - } - /* tm.utc_minutes = c; */ - - v = mktime(&tm); - - (void) validate_value(message, name, value_tag, v); - papiAttributeListAddDatetime(&attributes, - PAPI_ATTR_APPEND, name, v); - } - break; - case VTAG_NAME_WITH_LANGUAGE: - case VTAG_TEXT_WITH_LANGUAGE: - /* - * we are dropping this because we don't support - * name with language at this time. - */ - (void) read_name_with_language(iread, fd, message); - break; - case VTAG_NAME_WITHOUT_LANGUAGE: - case VTAG_TEXT_WITHOUT_LANGUAGE: - case VTAG_URI: - case VTAG_KEYWORD: - case VTAG_CHARSET: { - char *v; - - if ((v = calloc(1, value_length + 1)) == NULL) { - ipp_set_status(message, PAPI_TEMPORARY_ERROR, - "calloc(): failed\n"); - return (PAPI_TEMPORARY_ERROR); - } -#ifdef NOTDEF - if (iread(fd, v, value_length) != value_length) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: stringy\n"); - return (PAPI_BAD_REQUEST); - } -#else - { - int rc, i = value_length; - char *p = v; - - while ((rc = iread(fd, p, i)) != i) { - if (rc <= 0) { - ipp_set_status(message, - PAPI_BAD_REQUEST, - "bad read: stringy\n"); - return (PAPI_BAD_REQUEST); - } - i -= rc; - p += rc; - } - } -#endif - (void) validate_value(message, name, value_tag, v); - papiAttributeListAddString(&attributes, - PAPI_ATTR_APPEND, name, v); - } - break; - case VTAG_UNKNOWN: - case VTAG_NOVALUE: - case VTAG_UNSUPPORTED: - papiAttributeListAddValue(&attributes, PAPI_ATTR_EXCL, - name, PAPI_COLLECTION, NULL); - break; - default: { - char *v; - - if ((v = calloc(1, value_length + 1)) == NULL) { - ipp_set_status(message, PAPI_TEMPORARY_ERROR, - "calloc(): failed\n"); - return (PAPI_TEMPORARY_ERROR); - } - if (iread(fd, v, value_length) != value_length) { - ipp_set_status(message, PAPI_BAD_REQUEST, - "bad read: other\n"); - return (PAPI_BAD_REQUEST); - } - papiAttributeListAddString(&attributes, - PAPI_ATTR_APPEND, name, v); - } - break; - } - } - - if (attributes != NULL) { - char name[32]; - - (void) ipp_tag_string(*type, name, sizeof (name)); - papiAttributeListAddCollection(message, PAPI_ATTR_APPEND, name, - attributes); - } - - *type = value_tag; - - return (PAPI_OK); -} - - -static papi_status_t -ipp_read_header(ipp_reader_t iread, void *fd, papi_attribute_t ***message, - char type) -{ - char *attr_name = "status-code"; /* default to a response */ - char buf[8]; - int8_t c; - uint16_t s; - int32_t i; - - if ((iread == NULL) || (fd == NULL) || (message == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* - * Apache 1.X uses the buffer supplied to it's read call to read in - * the chunk size when chunking is used. This causes problems - * reading the header a piece at a time, because we don't have - * enough room to read in the chunk size prior to reading the - * chunk. - */ - - if (iread(fd, buf, 8) != 8) - return (PAPI_BAD_REQUEST); - - c = buf[0]; - (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE, - "version-major", c); - - c = buf[1]; - (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE, - "version-minor", c); - - memcpy(&s, &buf[2], 2); - s = (uint16_t)ntohs(s); - if (type == IPP_TYPE_REQUEST) - attr_name = "operation-id"; - (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE, - attr_name, s); - - memcpy(&i, &buf[4], 4); - i = (uint32_t)ntohl(i); - (void) papiAttributeListAddInteger(message, PAPI_ATTR_REPLACE, - "request-id", i); - - return (PAPI_OK); -} - -static papi_status_t -ipp_read_attribute_groups(ipp_reader_t iread, void *fd, - papi_attribute_t ***message) -{ - papi_status_t result = PAPI_OK; - int8_t tag; - - /* start reading the attribute groups */ - if (iread(fd, &tag, 1) != 1) /* prime the pump */ - return (PAPI_BAD_REQUEST); - - while ((tag != DTAG_END_OF_ATTRIBUTES) && (result == PAPI_OK)) { - result = ipp_read_attribute_group(iread, fd, &tag, message); - } - - return (result); -} - -papi_status_t -ipp_read_message(ipp_reader_t iread, void *fd, papi_attribute_t ***message, - char type) -{ - papi_status_t result = PAPI_OK; - - if ((iread == NULL) || (fd == NULL) || (message == NULL)) - return (PAPI_BAD_ARGUMENT); - - result = ipp_read_header(iread, fd, message, type); - if (result == PAPI_OK) - result = ipp_read_attribute_groups(iread, fd, message); - - return (result); -} diff --git a/usr/src/lib/print/libipp-core/common/strings.c b/usr/src/lib/print/libipp-core/common/strings.c deleted file mode 100644 index b47449b8cc..0000000000 --- a/usr/src/lib/print/libipp-core/common/strings.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: strings.c 151 2006-04-25 16:55:34Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "ipp.h" - -static char *tag_strings[] = { - /* delimiter tags */ - "reserved-delimiter-00", - "operational-attributes-group", - "job-attributes-group", - "end-of-attributes-group", - "printer-attributes-group", - "unsupported-attributes-group", - "subscription-attributes-group", - "event-notification-attributes-group", - "reserved-delimiter-08", - "reserved-delimiter-09", - "reserved-delimiter-0a", - "reserved-delimiter-0b", - "reserved-delimiter-0c", - "reserved-delimiter-0d", - "reserved-delimiter-0e", - "reserved-delimiter-0f", - /* value tags */ - "unsupported", - "reserved-default", - "unknown", - "no-value", - "reserved-out-of-band-14", - "not-settable", - "delete-attribute", - "admin-define", - "reserved-out-of-band-18", - "reserved-out-of-band-19", - "reserved-out-of-band-1a", - "reserved-out-of-band-1b", - "reserved-out-of-band-1c", - "reserved-out-of-band-1d", - "reserved-out-of-band-1e", - "reserved-out-of-band-1f", - "reserved", - "integer", - "boolean", - "enum", - "reserved-integer-type-24", - "reserved-integer-type-25", - "reserved-integer-type-26", - "reserved-integer-type-27", - "reserved-integer-type-28", - "reserved-integer-type-29", - "reserved-integer-type-2a", - "reserved-integer-type-2b", - "reserved-integer-type-2c", - "reserved-integer-type-2d", - "reserved-integer-type-2e", - "reserved-integer-type-2f", - "octetString", - "dateTime", - "resolution", - "rangeOfInteger", - "begCollection", - "textWithLanguage", - "nameWithLanguage", - "endCollection", - "reserved-octetString-38", - "reserved-octetString-39", - "reserved-octetString-3a", - "reserved-octetString-3b", - "reserved-octetString-3c", - "reserved-octetString-3d", - "reserved-octetString-3e", - "reserved-octetString-3f", - "reserved", - "textWithoutLanguage", - "nameWithoutLanguage", - "reserved", - "keyword", - "uri", - "uriScheme", - "charset", - "naturalLanguage", - "mimeMediaType", - "memberAttrName", - "reserved-charString-4b", - "reserved-charString-4c", - "reserved-charString-4d", - "reserved-charString-4e", - "reserved-charString-4f", - "reserved-charString-50", - "reserved-charString-51", - "reserved-charString-52", - "reserved-charString-53", - "reserved-charString-54", - "reserved-charString-55", - "reserved-charString-56", - "reserved-charString-57", - "reserved-charString-58", - "reserved-charString-59", - "reserved-charString-5a", - "reserved-charString-5b", - "reserved-charString-5c", - "reserved-charString-5d", - "reserved-charString-5e", - "reserved-charString-5f", -}; - -static char *opid_strings[] = { - "reserved-0x0000", - "reserved-0x0001", - "Print-Job", - "Print-URI", - "Validate-Job", - "Create-Job", - "Send-Document", - "Send-URI", - "Cancel-Job", - "Get-Job-Attributes", - "Get-Jobs", - "Get-Printer-Attributes", - "Hold-Job", - "Release-Job", - "Restart-Job", - "reserved-0x000f", - "Pause-Printer", - "Resume-Printer", - "Purge-Jobs", - "Set-Printer-Attributes", - "Set-Job-Attributes", - "Get-Printer-Supported-Values", - "Create-Printer-Subscription", - "Create-Job-Subscription", - "Get-Subscription-Attributes", - "Get-Subscriptions", - "Renew-Subscription", - "Cancel-Subscription", - "Get-Notifications", - "Send-Notifications", - "Get-Resource-Attributes-deleted", - "Get-Resource-Data-deleted", - "Get-Resources-deleted", - "Get-Print-Support-Files", - "Disable-Printer", - "Pause-Printer-After-Current-Job", - "Hold-New-Jobs", - "Release-Held-New-Jobs", - "Deactivate-Printer", - "Activate-Printer", - "Restart-Printer", - "Shutdown-Printer", - "Startup-Printer", - "Reprocess-Job", - "Cancel-Current-Job", - "Suspend-Current-Job", - "Resume-Job", - "Promote-Job", - "Schedule-Job-After", - NULL -}; - -static char *res_opid_strings[] = { - "Microsoft-0x4000", - "CUPS-Get-Default", - "CUPS-Get-Printers", - "CUPS-Add-Printer", - "CUPS-Delete-Printer", - "CUPS-Get-Classes", - "CUPS-Add-Class", - "CUPS-Delete-Class", - "CUPS-Accept-Jobs", - "CUPS-Reject-Jobs", - "CUPS-Set-Default", - "CUPS-Get-Devices", - "CUPS-Get-PPDs", - "CUPS-Move-Job", - "CUPS-0x400e", - "CUPS-0x400f", - "Peerless-0x4010", - NULL -}; -#define KNOWN_RESERVED_MIN 0x4000 -#define KNOWN_RESERVED_MAX 0x4010 - -static char *ok_status_strings[] = { - "successful-ok", - "successful-ok-ignored-or-substituted-attributes", - "successful-ok-conflicting-attributes", - "successful-ok-ignored-subscriptions", - "successful-ok-ignored-notifications", - "successful-ok-too-many-events", - "successful-ok-but-cancel-subscription" -}; - -static char *redir_status_strings[] = { - "redirection-other-site" -}; - -static char *client_error_status_strings[] = { - "client-error-bad-request", - "client-error-forbidden", - "client-error-not-authenticated", - "client-error-not-authorized", - "client-error-not-possible", - "client-error-timeout", - "client-error-not-found", - "client-error-gone", - "client-error-request-entity-too-large", - "client-error-request-value-too-long", - "client-error-document-format-not-supported", - "client-error-attributes-or-values-not-supported", - "client-error-uri-scheme-not-supported", - "client-error-charset-not-supported", - "client-error-conflicting-attributes", - "client-error-compression-not-supported", - "client-error-compression-error", - "client-error-document-format-error", - "client-error-document-access-error", - "client-error-attributes-not-settable", - "client-error-ignored-all-subscriptions", - "client-error-too-many-subscriptions", - "client-error-ignored-all-notifications", - "client-error-print-support-file-not-found" -}; - -static char *server_error_status_strings[] = { - "server-error-internal-error", - "server-error-operation-not-supported", - "server-error-service-unavailable", - "server-error-version-not-supported", - "server-error-device-error", - "server-error-temporary-error", - "server-error-not-accepting-jobs", - "server-error-busy", - "server-error-job-canceled", - "server-error-multiple-document-jobs-not-supported", - "server-error-printer-is-deactivated" -}; - -char * -ipp_tag_string(int8_t id, char *ret, size_t len) -{ - if (id < VTAG_MAX) - (void) strlcpy(ret, tag_strings[id], len); - else if (id == VTAG_EXTEND) - (void) strlcpy(ret, "extension", len); - else - (void) snprintf(ret, len, "bogus-0x%.2x", id); - - return (ret); -} - -char * -ipp_opid_string(int16_t id, char *ret, size_t len) -{ - if (id < OPID_RESERVED_MIN) - (void) strlcpy(ret, opid_strings[id], len); - else if (id < OPID_RESERVED_VENDOR_MIN) - (void) snprintf(ret, len, "reserved-0x%.4x", id); - else if (id <= KNOWN_RESERVED_MAX) - (void) strlcpy(ret, - res_opid_strings[id - KNOWN_RESERVED_MIN], len); - else /* if (id <= OPID_RESERVED_VENDOR_MAX) */ - (void) snprintf(ret, len, "reserved-vendor-0x%.4x", id); - - return (ret); -} - -int16_t -ipp_string_opid(char *string) -{ - int i; - - for (i = 0; opid_strings[i] != NULL; i++) - if (strcasecmp(opid_strings[i], string) == 0) - return (i); - - for (i = 0; res_opid_strings[i] != NULL; i++) - if (strcasecmp(res_opid_strings[i], string) == 0) - return (0x4000 + i); - - return (-1); -} - -char * -ipp_status_string(int16_t id, char *ret, size_t len) -{ - if (id <= IPP_OK_MAX) - (void) strlcpy(ret, ok_status_strings[id], len); - else if (id >= IPP_REDIR_MIN && id <= IPP_REDIR_MAX) - (void) strlcpy(ret, - redir_status_strings[id - IPP_REDIR_MIN], len); - else if (id >= IPP_CERR_MIN && id <= IPP_CERR_MAX) - (void) strlcpy(ret, - client_error_status_strings[id - IPP_CERR_MIN], len); - else if (id >= IPP_SERR_MIN && id <= IPP_SERR_MAX) - (void) strlcpy(ret, - server_error_status_strings[id - IPP_SERR_MIN], len); - else - (void) snprintf(ret, len, "bogus-0x%.4hx", id); - - return (ret); -} - - - -/* - * attribute template handling routines - */ -char *job_template[] = { - "copies", - "finishing", - "job-hold-until", - "job-priority", - "job-sheets", - "media", - "multiple-document-handling", - "number-up", - "page-ranges-supported", - "print-quality", - "printer-resoultion", - "sides", - NULL -}; - -char *job_description[] = { - "copies-default", "copies-supported", - "finishing-default", "finishing-supported", - "job-hold-until-default", "job-hold-until-supported", - "job-priority-default", "job-priority-supported", - "job-sheets-default", "job-sheets-supported", - "media-default", "media-supported", - "multiple-document-handling-default", - "multiple-document-handling-supported", - "number-up-default", "number-up-supported", - "page-ranges-supported", - "print-quality-default", "print-quality-supported", - "printer-resoultion-default", "printer-resoultion-supported", - "sides-default", "sides-supported", - NULL -}; - -char *printer_description[] = { - "printer-uri-supported", - "uri-security-supported", - "uri-authentication-supported", - "printer-name", - "printer-location", - "printer-info", - "printer-more-info", - "printer-driver-installer", - "printer-make-and-model", - "printer-more-info-manufacturer", - "printer-state", - "printer-state-reasons", - "printer-state-message", - "ipp-versions-supported", - "multiple-document-jobs-supported", - "charset-configured", - "charset-supported", - "natural-language-configured", - "generated-natural-language-supported", - "document-format-default", - "document-format-supported", - "printer-is-accepting-jobs", - "queued-job-count", - "printer-message-from-operator", - "color-supported", - "reference-uri-schemes-supported", - "pdl-override-supported", - "printer-up-time", - "printer-current-time", - "multiple-operation-time-out", - "compression-supported", - "job-k-octets-supported", - "job-impressions-supported", - "job-media-sheets-supported", - "pages-per-minute", - "pages-per-minute-color", - NULL -}; diff --git a/usr/src/lib/print/libipp-core/common/write.c b/usr/src/lib/print/libipp-core/common/write.c deleted file mode 100644 index aef693a365..0000000000 --- a/usr/src/lib/print/libipp-core/common/write.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: write.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <inttypes.h> - -#include <papi.h> -#include <ipp.h> - -static int8_t -papi_attribute_to_ipp_type(papi_attribute_value_type_t type) -{ - switch (type) { - case PAPI_INTEGER: - return (VTAG_INTEGER); - case PAPI_BOOLEAN: - return (VTAG_BOOLEAN); - case PAPI_RANGE: - return (VTAG_RANGE_OF_INTEGER); - case PAPI_RESOLUTION: - return (VTAG_RESOLUTION); - case PAPI_DATETIME: - return (VTAG_DATE_TIME); - case PAPI_STRING: - return (VTAG_TEXT_WITHOUT_LANGUAGE); - } - - return (0); -} - -static papi_status_t -papi_ipp_type_match(papi_attribute_value_type_t papi, int8_t ipp) -{ - switch (papi) { - case PAPI_STRING: - switch (ipp) { - case VTAG_URI: - case VTAG_OCTET_STRING: - case VTAG_TEXT_WITHOUT_LANGUAGE: - case VTAG_URI_SCHEME: - case VTAG_CHARSET: - case VTAG_NATURAL_LANGUAGE: - case VTAG_MIME_MEDIA_TYPE: - case VTAG_NAME_WITHOUT_LANGUAGE: - case VTAG_KEYWORD: - break; - default: - return (PAPI_CONFLICT); - } - break; - case PAPI_INTEGER: - switch (ipp) { - case VTAG_ENUM: - case VTAG_INTEGER: - break; - default: - return (PAPI_CONFLICT); - } - break; - case PAPI_BOOLEAN: - if (ipp != VTAG_BOOLEAN) - return (PAPI_CONFLICT); - break; - case PAPI_RANGE: - if (ipp != VTAG_RANGE_OF_INTEGER) - return (PAPI_CONFLICT); - break; - case PAPI_RESOLUTION: - if (ipp != VTAG_RESOLUTION) - return (PAPI_CONFLICT); - break; - case PAPI_DATETIME: - if (ipp != VTAG_DATE_TIME) - return (PAPI_CONFLICT); - break; - case PAPI_COLLECTION: - /* don't need to match */ - break; - } - - return (PAPI_OK); -} - -static papi_status_t -ipp_write_attribute(ipp_writer_t iwrite, void *fd, papi_attribute_t *attribute) -{ - papi_status_t status; - papi_attribute_value_t **values; - int8_t type; - int i; - char *name; - - name = attribute->name; - values = attribute->values; - - if ((type = name_to_ipp_type(name)) == 0) - type = papi_attribute_to_ipp_type(attribute->type); - - /* The types don't match, so don't send the attribute */ - if ((status = papi_ipp_type_match(attribute->type, type)) != PAPI_OK) - return (status); - - if (values == NULL) { - uint16_t length; - - type = VTAG_UNSUPPORTED; - if (iwrite(fd, &type, 1) != 1) - return (PAPI_DEVICE_ERROR); - - if (name != NULL) { /* first value gets named */ - length = (uint16_t)htons(strlen(name)); - - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - if (iwrite(fd, name, strlen(name)) != strlen(name)) - return (PAPI_DEVICE_ERROR); - } - - length = (uint16_t)htons(0); - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - - return (PAPI_OK); - } - - - - for (i = 0; values[i] != NULL; i++) { - papi_attribute_value_t *value = values[i]; - uint16_t length = 0; - - if (iwrite(fd, &type, 1) != 1) - return (PAPI_DEVICE_ERROR); - - if (name != NULL) { /* first value gets named */ - length = (uint16_t)htons(strlen(name)); - - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - if (iwrite(fd, name, strlen(name)) != strlen(name)) - return (PAPI_DEVICE_ERROR); - name = NULL; - } else { - length = (uint16_t)htons(0); - - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - } - - switch (attribute->type) { - case PAPI_STRING: { - char *v = (char *)value->string; - - if (v != NULL) { - size_t str_length = strlen(v); - - /* - * if the length is more than 16 bits can - * express, send what can be represented - * in 16 bits. IPP "strings" can only be - * that large. - */ - if (str_length > 0xFFFF) - str_length = 0xFFFF; - - length = (uint16_t)htons(str_length); - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - if (iwrite(fd, v, str_length) != str_length) - return (PAPI_DEVICE_ERROR); - } else - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - } - break; - case PAPI_BOOLEAN: { - int8_t v = (int8_t)value->boolean; - - length = (uint16_t)htons(1); - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - if (iwrite(fd, &v, 1) != 1) - return (PAPI_DEVICE_ERROR); - } - break; - case PAPI_INTEGER: { - int32_t v = (int32_t)value->integer; - - length = (uint16_t)htons(4); - v = (int32_t)htonl(v); - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - if (iwrite(fd, &v, 4) != 4) - return (PAPI_DEVICE_ERROR); - } - break; - case PAPI_RANGE: { - int32_t min = (int32_t)htonl((int)(value->range).lower), - max = (int32_t)htonl((int)(value->range).upper); - - length = (uint16_t)htons(8); - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - if (iwrite(fd, &min, 4) != 4) - return (PAPI_DEVICE_ERROR); - if (iwrite(fd, &max, 4) != 4) - return (PAPI_DEVICE_ERROR); - } - break; - case PAPI_RESOLUTION: { - int32_t x = (int)(value->resolution).xres, - y = (int)(value->resolution).yres; - int8_t units = (int8_t)(value->resolution).units; - - length = (uint16_t)htons(9); - x = (int32_t)htonl(x); - y = (int32_t)htonl(y); - - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - if (iwrite(fd, &x, 4) != 4) - return (PAPI_DEVICE_ERROR); - if (iwrite(fd, &y, 4) != 4) - return (PAPI_DEVICE_ERROR); - if (iwrite(fd, &units, 1) != 1) - return (PAPI_DEVICE_ERROR); - } - break; - case PAPI_DATETIME: { - struct tm *v = gmtime(&value->datetime); - int8_t c; - uint16_t s; - - length = (uint16_t)htons(11); - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - s = (uint16_t)htons(v->tm_year + 1900); - if (iwrite(fd, &s, 2) != 2) - return (PAPI_DEVICE_ERROR); - c = v->tm_mon + 1; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - c = v->tm_mday; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - c = v->tm_hour; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - c = v->tm_min; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - c = v->tm_sec; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - c = /* v->deciseconds */ 0; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - c = /* v->utc_dir */ 0; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - c = /* v->utc_hours */ 0; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - c = /* v->utc_minutes */ 0; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - } - break; - default: { - /* - * If there is a value, it is not one of our - * types, so we couldn't use it anyway. We assume - * that it was an OOB type with no value - */ - length = (uint16_t)htons(0); - if (iwrite(fd, &length, 2) != 2) - return (PAPI_DEVICE_ERROR); - } - break; - } - } - - return (PAPI_OK); -} - -static papi_status_t -ipp_write_attribute_group(ipp_writer_t iwrite, void *fd, int8_t type, - papi_attribute_t **attributes) -{ - papi_status_t result = PAPI_OK; - int i; - - /* write group tag */ - if (iwrite(fd, &type, 1) != 1) - return (PAPI_DEVICE_ERROR); - - /* write values */ - for (i = 0; ((attributes[i] != NULL) && (result == PAPI_OK)); i++) - result = ipp_write_attribute(iwrite, fd, attributes[i]); - - return (result); -} - -static papi_status_t -ipp_write_attribute_groups(ipp_writer_t iwrite, void *fd, - papi_attribute_t **groups) -{ - papi_status_t result = PAPI_OK; - int8_t c; - - for (c = DTAG_MIN; c <= DTAG_MAX; c++) { - papi_status_t status; - papi_attribute_t **group = NULL; - void *iter = NULL; - char name[32]; - - (void) ipp_tag_string(c, name, sizeof (name)); - for (status = papiAttributeListGetCollection(groups, &iter, - name, &group); - ((status == PAPI_OK) && (result == PAPI_OK)); - status = papiAttributeListGetCollection(groups, &iter, - NULL, &group)) - result = ipp_write_attribute_group(iwrite, fd, - c, group); - } - - c = DTAG_END_OF_ATTRIBUTES; - if (iwrite(fd, &c, 1) != 1) - result = PAPI_DEVICE_ERROR; - - return (result); -} - -static papi_status_t -ipp_write_message_header(ipp_writer_t iwrite, void *fd, - papi_attribute_t **message) -{ - int tmp; - int8_t c; - uint16_t s; - int32_t i; - - /* write the version */ - papiAttributeListGetInteger(message, NULL, "version-major", &tmp); - c = tmp; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - - papiAttributeListGetInteger(message, NULL, "version-minor", &tmp); - c = tmp; - if (iwrite(fd, &c, 1) != 1) - return (PAPI_DEVICE_ERROR); - - /* write the request/status code */ - papiAttributeListGetInteger(message, NULL, "status-code", &tmp); - papiAttributeListGetInteger(message, NULL, "operation-id", &tmp); - s = (uint16_t)htons(tmp); - if (iwrite(fd, &s, 2) != 2) - return (PAPI_DEVICE_ERROR); - - /* write the request id */ - papiAttributeListGetInteger(message, NULL, "request-id", &tmp); - i = (uint32_t)htonl(tmp); - if (iwrite(fd, &i, 4) != 4) - return (PAPI_DEVICE_ERROR); - - return (PAPI_OK); -} - -papi_status_t -ipp_write_message(ipp_writer_t iwrite, void *fd, papi_attribute_t **message) -{ - papi_status_t result; - - if ((iwrite == NULL) || (fd == NULL) || (message == NULL)) - return (PAPI_BAD_ARGUMENT); - - result = ipp_write_message_header(iwrite, fd, message); - if (result == PAPI_OK) - result = ipp_write_attribute_groups(iwrite, fd, message); - - return (result); -} diff --git a/usr/src/lib/print/libipp-listener/Makefile.com b/usr/src/lib/print/libipp-listener/Makefile.com deleted file mode 100644 index 4db2966ceb..0000000000 --- a/usr/src/lib/print/libipp-listener/Makefile.com +++ /dev/null @@ -1,68 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# - -LIBRARY = libipp-listener.a -VERS = .0 -OBJECTS = \ - cancel-job.o common.o create-job.o cups-accept-jobs.o \ - cups-get-classes.o cups-get-default.o cups-get-printers.o \ - cups-move-job.o cups-reject-jobs.o disable-printer.o enable-printer.o \ - get-job-attributes.o get-jobs.o get-printer-attributes.o hold-job.o \ - ipp-listener.o pause-printer.o print-job.o purge-jobs.o release-job.o \ - restart-job.o resume-printer.o send-document.o set-job-attributes.o \ - set-printer-attributes.o validate-job.o - -include ../../../Makefile.lib -include ../../../Makefile.rootfs - -SRCDIR = ../common - -ROOTLIBDIR= $(ROOT)/usr/lib - -LIBS = $(DYNLIB) - -$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -DSOLARIS_PRIVATE_POST_0_9 -CPPFLAGS += -I$(SRCDIR) -CPPFLAGS += -I../../libpapi-common/common -CPPFLAGS += -I../../libipp-core/common - -CERRWARN += -_gcc=-Wno-unused-variable -CERRWARN += -_gcc=-Wno-uninitialized - -MAPFILES = $(SRCDIR)/mapfile - -LDLIBS += -lipp-core -lpapi -lc -lsocket -lnsl - -.KEEP_STATE: - -all: $(LIBS) - -lint: lintcheck - -include ../../../Makefile.targ diff --git a/usr/src/lib/print/libipp-listener/common/cancel-job.c b/usr/src/lib/print/libipp-listener/common/cancel-job.c deleted file mode 100644 index 49ad1980f8..0000000000 --- a/usr/src/lib/print/libipp-listener/common/cancel-job.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: cancel-job.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_cancel_job(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - - char *message = NULL; - char *queue = NULL; - int id = -1; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * the operational-attributes-group must contain: - * job-uri (or printer-uri/job-id) - */ - get_printer_id(operational, &queue, &id); - if (id < 0) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing job-uri or job-id"); - return (PAPI_BAD_REQUEST); - } else if (queue == NULL) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing printer-uri or job-uri"); - return (PAPI_BAD_REQUEST); - } - - /* - * the operational-attributes-group may contain: - * message - */ - (void) papiAttributeListGetString(operational, NULL, - "message", &message); - - status = papiJobCancel(svc, queue, id); - if (status != PAPI_OK) { - ipp_set_status(response, status, - "cancel failed: %s-%d: %s", - (queue ? queue : "(null)"), id, - ipp_svc_status_mesg(svc, status)); - } else if (message != NULL) { /* add unsupported attribute group */ - papi_attribute_t **unsupported = NULL; - - papiAttributeListAddValue(&unsupported, PAPI_ATTR_EXCL, - "message", PAPI_COLLECTION, NULL); - (void) papiAttributeListAddCollection(response, - PAPI_ATTR_REPLACE, "unsupported-attributes-group", - unsupported); - papiAttributeListFree(unsupported); - - status = PAPI_OK_SUBST; - ipp_set_status(response, status, - "unsupported attribute in request"); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/common.c b/usr/src/lib/print/libipp-listener/common/common.c deleted file mode 100644 index a8fbe45098..0000000000 --- a/usr/src/lib/print/libipp-listener/common/common.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: common.c 155 2006-04-26 02:34:54Z ktou $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> -#include <sys/types.h> -#include <unistd.h> -#include <papi.h> -#include <ipp-listener.h> - -char * -ipp_svc_status_mesg(papi_service_t svc, papi_status_t status) -{ - char *mesg = papiServiceGetStatusMessage(svc); - - if (mesg == NULL) - mesg = papiStatusString(status); - - return (mesg); -} - -char * -destination_from_printer_uri(char *uri) -{ - static char buf[64]; - char *result = NULL; - - if (uri != NULL) - result = strrchr(uri, '/'); - - if (result == NULL) - result = uri; - else - result++; - -#ifdef FORCE_LPSCHED_URI - snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s", result); - result = buf; -#endif /* FORCE_LPSCHED_URI */ - - return (result); -} - -void -get_printer_id(papi_attribute_t **attributes, char **printer, int *id) -{ - papi_status_t result; - char *job = NULL; - char *fodder; - int junk; - - if (printer == NULL) - printer = &fodder; - if (id == NULL) - id = &junk; - - *printer = NULL; - *id = -1; - - result = papiAttributeListGetString(attributes, NULL, "job-uri", &job); - if (result != PAPI_OK) { - result = papiAttributeListGetString(attributes, NULL, - "printer-uri", printer); - if (result == PAPI_OK) - papiAttributeListGetInteger(attributes, NULL, - "job-id", id); - } else { - *printer = job; - if ((job = strrchr(*printer, '/')) != NULL) { - *job = '\0'; - *id = atoi(++job); - } - } -} - -void -get_string_list(papi_attribute_t **attributes, char *name, char ***values) -{ - papi_status_t result; - - void *iterator = NULL; - char *value = NULL; - - for (result = papiAttributeListGetString(attributes, &iterator, - name, &value); - result == PAPI_OK; - result = papiAttributeListGetString(attributes, &iterator, - NULL, &value)) - list_append(values, value); -} - -void -add_default_attributes(papi_attribute_t ***attributes) -{ - - (void) papiAttributeListAddString(attributes, PAPI_ATTR_APPEND, - "ipp-versions-supported", "1.0"); - (void) papiAttributeListAddString(attributes, PAPI_ATTR_APPEND, - "ipp-versions-supported", "1.1"); - (void) papiAttributeListAddBoolean(attributes, PAPI_ATTR_EXCL, - "multiple-document-jobs-supported", 0); - /* - * Should be able to ask the web server if it supports SSL or TLS, but - * for now, we pick only "none" - */ - (void) papiAttributeListAddString(attributes, PAPI_ATTR_EXCL, - "uri-security-supported", "none"); - - /* - * For now, we only "none". As we support more authentication methods, - * we will need to add the associated uri for each. Valid values would - * be: - * "none", "requesting-user-name", "basic", "digest", "certificate" - * See RFC2911 page 127 for more information. - */ - (void) papiAttributeListAddString(attributes, PAPI_ATTR_EXCL, - "uri-authentication-supported", "requesting-user-name"); - (void) papiAttributeListAddString(attributes, PAPI_ATTR_EXCL, - "uri-security-supported", "none"); - /* printer-uri-supported is added in the service based attributes */ - - (void) papiAttributeListAddInteger(attributes, PAPI_ATTR_EXCL, - "multiple-operation-time-out", 60); - - /* I18N related */ - (void) papiAttributeListAddString(attributes, PAPI_ATTR_EXCL, - "charset-configured", "utf-8"); - (void) papiAttributeListAddString(attributes, PAPI_ATTR_EXCL, - "charset-supported", "utf-8"); - (void) papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, - "natural-language-configured", "en-us"); -} - -static void -massage_printer_attributes_group(papi_attribute_t **group, char *printer_uri) -{ - if (papiAttributeListFind(group, "printer-uri-supported") != NULL) - papiAttributeListAddString(&group, PAPI_ATTR_REPLACE, - "printer-uri-supported", printer_uri); -} - -static void -massage_job_attributes_group(papi_attribute_t **group, char *printer_uri) -{ - if (papiAttributeListFind(group, "job-printer-uri") != NULL) - papiAttributeListAddString(&group, PAPI_ATTR_REPLACE, - "job-printer-uri", printer_uri); - - if (papiAttributeListFind(group, "job-printer-uri") != NULL) { - char buf[BUFSIZ]; - int32_t id = -1; - - papiAttributeListGetInteger(group, NULL, "job-id", &id); - snprintf(buf, sizeof (buf), "%s/%d", printer_uri, id); - papiAttributeListAddString(&group, PAPI_ATTR_REPLACE, - "job-uri", buf); - } -} - -/* - * This function will replace the job/printer URIs with the requested - * uri because the print service may return a URI that isn't IPP based. - */ -void -massage_response(papi_attribute_t **request, papi_attribute_t **response) -{ - papi_status_t status; - papi_attribute_t **group = NULL; - void *iter = NULL; - char *host = "localhost"; - char *path = "/printers/"; - int port = 631; - char buf[BUFSIZ]; - - (void) papiAttributeListGetString(request, NULL, "uri-host", &host); - (void) papiAttributeListGetString(request, NULL, "uri-path", &path); - (void) papiAttributeListGetInteger(request, NULL, "uri-port", &port); - - if (port == 631) - snprintf(buf, sizeof (buf), "ipp://%s%s", host, path); - else - snprintf(buf, sizeof (buf), "http://%s:%d%s", host, port, path); - - for (status = papiAttributeListGetCollection(response, &iter, - "printer-attributes-group", &group); - status == PAPI_OK; - status = papiAttributeListGetCollection(NULL, &iter, - NULL, &group)) - massage_printer_attributes_group(group, buf); - - iter = NULL; - for (status = papiAttributeListGetCollection(response, &iter, - "job-attributes-group", &group); - status == PAPI_OK; - status = papiAttributeListGetCollection(NULL, &iter, - NULL, &group)) - massage_job_attributes_group(group, buf); -} - -/* - * This walks through the locale tab and returns the installed - * locales. There must be a better way. - */ -void -add_supported_locales(papi_attribute_t ***attributes) -{ - FILE *fp; - - papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, - "generated-natural-language-supported", "en-us"); - -#ifndef __linux__ /* this is Solaris specific */ - if ((fp = fopen("/usr/lib/locale/lcttab", "r")) != NULL) { - char buf[1024]; - - while (fgets(buf, sizeof (buf), fp) != NULL) { - char *name, *file; - int i, passed = 1; - - name = strtok(buf, " \t\n"); - - for (i = 0; ((passed == 1) && (name[i] != NULL)); i++) - if (isalpha(name[i]) != 0) - name[i] = tolower(name[i]); - else if ((name[i] == '_') || (name[i] == '-')) - name[i] = '-'; - else - passed = 0; - - if ((passed == 1) && - ((file = strtok(NULL, " \t\n")) != NULL)) { - char path[1024]; - - snprintf(path, sizeof (path), - "/usr/lib/locale/%s", file); - - if (access(path, F_OK) == 0) - papiAttributeListAddString(attributes, - PAPI_ATTR_APPEND, - "generated-natural-language-supported", - name); - } - } - } -#endif -} - -void -papi_to_ipp_printer_group(papi_attribute_t ***response, - papi_attribute_t **request, int flags, papi_printer_t p) -{ - papi_attribute_t **ipp_group = NULL; - - copy_attributes(&ipp_group, papiPrinterGetAttributeList(p)); - - /* Windows clients appear to have a problem with very large values */ - papiAttributeListDelete(&ipp_group, "lpsched-printer-ppd-contents"); - - add_default_attributes(&ipp_group); - ipp_operations_supported(&ipp_group, request); - - (void) papiAttributeListAddCollection(response, flags, - "printer-attributes-group", ipp_group); - papiAttributeListFree(ipp_group); -} - -void -papi_to_ipp_job_group(papi_attribute_t ***response, - papi_attribute_t **request, int flags, papi_job_t j) -{ - papi_attribute_t **ipp_group = NULL; - - copy_attributes(&ipp_group, papiJobGetAttributeList(j)); - - (void) papiAttributeListAddCollection(response, flags, - "job-attributes-group", ipp_group); - papiAttributeListFree(ipp_group); -} diff --git a/usr/src/lib/print/libipp-listener/common/create-job.c b/usr/src/lib/print/libipp-listener/common/create-job.c deleted file mode 100644 index 996b235cea..0000000000 --- a/usr/src/lib/print/libipp-listener/common/create-job.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: create-job.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_create_job(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_job_t j = NULL; - papi_attribute_t **operational = NULL; - papi_attribute_t **job_attributes = NULL; - char *queue = NULL; - char *keys[] = { "attributes-natural-language", "attributes-charset", - "printer-uri", NULL }; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - /* - * The operational-attributes-group may contain: - * job-name - * ipp-attribute-fidelity - * document-name - * compression - * document-format - * document-natural-language - * job-k-octets - * job-impressions - * job-media-sheets - * Simply copy the entire contents of the operational-attributes-group - * for the PAPI call's possible use. - */ - - /* copy the pointers only, not the elements */ - split_and_copy_attributes(keys, operational, NULL, &job_attributes); - - /* copy any job-attributes-group attributes for the PAPI call */ - if (papiAttributeListGetCollection(request, NULL, - "job-attributes-group", &operational) == PAPI_OK) - copy_attributes(&job_attributes, operational); - - /* - * request job creation, using Sun extention to PAPI. The - * functionality in this extension is expected to make the - * next revision of the PAPI. - */ - status = papiJobCreate(svc, queue, job_attributes, NULL, &j); - papiAttributeListFree(job_attributes); - if (status != PAPI_OK) { - ipp_set_status(response, status, "job creation: %s", - ipp_svc_status_mesg(svc, status)); - return (status); - } - - /* add the job attributes to the response in a job-attributes-group */ - if (j != NULL) { - papi_to_ipp_job_group(response, request, PAPI_ATTR_REPLACE, j); - papiJobFree(j); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/cups-accept-jobs.c b/usr/src/lib/print/libipp-listener/common/cups-accept-jobs.c deleted file mode 100644 index 01a91ba5fd..0000000000 --- a/usr/src/lib/print/libipp-listener/common/cups-accept-jobs.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: cups-accept-jobs.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -cups_accept_jobs(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - - char *queue = NULL; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - if ((status = papiPrinterResume(svc, queue)) != PAPI_OK) { - ipp_set_status(response, status, "accept failed: %s: %s", - (queue ? queue : "(null)"), - ipp_svc_status_mesg(svc, status)); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/cups-get-classes.c b/usr/src/lib/print/libipp-listener/common/cups-get-classes.c deleted file mode 100644 index a6aea61908..0000000000 --- a/usr/src/lib/print/libipp-listener/common/cups-get-classes.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: cups-get-classes.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -cups_get_classes(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_printer_t *p = NULL; - papi_attribute_t **operational = NULL; - papi_filter_t filt; - - char **req_attrs = NULL; - int limit = 0; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group may contain: - * limit - * printer-info - * printer-location - * printer-type - * printer-type-mask - * requested-attributes - */ - - papiAttributeListGetInteger(operational, NULL, "limit", &limit); - - get_string_list(operational, "requested-attributes", &req_attrs); - - /* only ask for the classes */ - filt.type = PAPI_FILTER_BITMASK; - filt.filter.bitmask.mask = ~PAPI_PRINTER_CLASS; - filt.filter.bitmask.value = PAPI_PRINTER_CLASS; - - status = papiPrintersList(svc, req_attrs, &filt, &p); - if (status != PAPI_OK) { - ipp_set_status(response, status, "query printers: %s", - ipp_svc_status_mesg(svc, status)); - papiPrinterFree(p); /* we shouldn't have a printer */ - return (status); - } - - if (p != NULL) { - int i; - - for (i = 0; p[i] != NULL; i++) - papi_to_ipp_printer_group(response, request, - PAPI_ATTR_APPEND, p[i]); - papiPrinterListFree(p); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/cups-get-default.c b/usr/src/lib/print/libipp-listener/common/cups-get-default.c deleted file mode 100644 index 0bb084ac9e..0000000000 --- a/usr/src/lib/print/libipp-listener/common/cups-get-default.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: cups-get-default.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -#include <config-site.h> - -papi_status_t -cups_get_default(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_printer_t p = NULL; - papi_attribute_t **operational = NULL; - papi_attribute_t **printer_attributes = NULL; - - char **req_attrs = NULL; - int limit = 0; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group may contain: - * requested-attributes - */ - get_string_list(operational, "requested-attributes", &req_attrs); - - status = papiPrinterQuery(svc, DEFAULT_DEST, req_attrs, NULL, &p); - if (status != PAPI_OK) { - ipp_set_status(response, status, "query default: %s", - ipp_svc_status_mesg(svc, status)); - papiPrinterFree(p); /* we shouldn't have a printer */ - return (status); - } - - /* - * add the printer attributes to the response in a - * printer-attributes-group - */ - printer_attributes = papiPrinterGetAttributeList(p); - add_default_attributes(&printer_attributes); - (void) papiAttributeListAddCollection(response, PAPI_ATTR_REPLACE, - "printer-attributes-group", printer_attributes); - - papiPrinterFree(p); - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/cups-get-printers.c b/usr/src/lib/print/libipp-listener/common/cups-get-printers.c deleted file mode 100644 index e883543381..0000000000 --- a/usr/src/lib/print/libipp-listener/common/cups-get-printers.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: cups-get-printers.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -cups_get_printers(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_printer_t *p = NULL; - papi_attribute_t **operational = NULL; - papi_filter_t filt; - - char **req_attrs = NULL; - int limit = 0; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group may contain: - * limit - * printer-info - * printer-location - * printer-type - * printer-type-mask - * requested-attributes - */ - - papiAttributeListGetInteger(operational, NULL, "limit", &limit); - - get_string_list(operational, "requested-attributes", &req_attrs); - - /* only ask for the classes */ - filt.type = PAPI_FILTER_BITMASK; - filt.filter.bitmask.mask = ~PAPI_PRINTER_CLASS; - filt.filter.bitmask.value = PAPI_PRINTER_LOCAL | PAPI_PRINTER_REMOTE; - - /* query the print service for printers information */ - status = papiPrintersList(svc, req_attrs, &filt, &p); - if (status != PAPI_OK) { - ipp_set_status(response, status, "query printers: %s", - ipp_svc_status_mesg(svc, status)); - papiPrinterListFree(p); /* we shouldn't have any printers */ - return (status); - } - - if (p != NULL) { - int i; - - for (i = 0; p[i] != NULL; i++) - papi_to_ipp_printer_group(response, request, - PAPI_ATTR_APPEND, p[i]); - papiPrinterListFree(p); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/cups-move-job.c b/usr/src/lib/print/libipp-listener/common/cups-move-job.c deleted file mode 100644 index 137a507f93..0000000000 --- a/usr/src/lib/print/libipp-listener/common/cups-move-job.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: cups-move-job.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -cups_move_job(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL, **job = NULL; - - char *message = NULL; - char *job_printer_uri = NULL; - char *queue = NULL; - char *dest = NULL; - int id = -1; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * Get job attributes from the request - */ - status = papiAttributeListGetCollection(request, NULL, - "job-attributes-group", &job); - if (status != PAPI_OK) { - ipp_set_status(response, status, - "job-attributes-group: %s", - papiStatusString(status)); - return (status); - } - - /* - * the operational-attributes-group must contain: - * job-uri (or printer-uri/job-id) - */ - get_printer_id(operational, &queue, &id); - if (id < 0) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing job-uri or job-id"); - return (PAPI_BAD_REQUEST); - } else if (queue == NULL) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing printer-uri or job-uri"); - return (PAPI_BAD_REQUEST); - } - - /* - * the job-attributes-group must contain: - * job-printer-uri - */ - job_printer_uri = NULL; - (void) papiAttributeListGetString(job, NULL, - "job-printer-uri", &job_printer_uri); - if (job_printer_uri == NULL) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing job-printer-uri"); - return (PAPI_BAD_REQUEST); - } else - dest = destination_from_printer_uri(job_printer_uri); - - if ((status = papiJobMove(svc, queue, id, dest)) != PAPI_OK) - ipp_set_status(response, status, - "move failed: %s-%d to %s: %s", - (queue ? queue : "(null)"), id, - (dest ? dest : "(null)"), - ipp_svc_status_mesg(svc, status)); - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/cups-reject-jobs.c b/usr/src/lib/print/libipp-listener/common/cups-reject-jobs.c deleted file mode 100644 index 1a35acdf62..0000000000 --- a/usr/src/lib/print/libipp-listener/common/cups-reject-jobs.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: cups-reject-jobs.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -cups_reject_jobs(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - - char *queue = NULL; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - if ((status = papiPrinterPause(svc, queue, NULL)) != PAPI_OK) { - ipp_set_status(response, status, "pause failed: %s: %s", - (queue ? queue : "(null)"), - ipp_svc_status_mesg(svc, status)); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/disable-printer.c b/usr/src/lib/print/libipp-listener/common/disable-printer.c deleted file mode 100644 index e1c2fd3b5c..0000000000 --- a/usr/src/lib/print/libipp-listener/common/disable-printer.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: disable-printer.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_disable_printer(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - - char *queue = NULL; - char *message = NULL; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - /* - * The operational-attributes-group may contain: - * printer-message-from-operator - */ - (void) papiAttributeListGetString(operational, NULL, - "printer-message-from-operator", &message); - - if ((status = papiPrinterDisable(svc, queue, message)) != PAPI_OK) { - ipp_set_status(response, status, "disable failed: %s: %s", - (queue ? queue : "(null)"), - ipp_svc_status_mesg(svc, status)); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/enable-printer.c b/usr/src/lib/print/libipp-listener/common/enable-printer.c deleted file mode 100644 index 0d5419d51d..0000000000 --- a/usr/src/lib/print/libipp-listener/common/enable-printer.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: enable-printer.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_enable_printer(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - - char *queue = NULL; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - if ((status = papiPrinterEnable(svc, queue)) != PAPI_OK) { - ipp_set_status(response, status, "enable failed: %s: %s", - (queue ? queue : "(null)"), - ipp_svc_status_mesg(svc, status)); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/get-job-attributes.c b/usr/src/lib/print/libipp-listener/common/get-job-attributes.c deleted file mode 100644 index 7f74054ebe..0000000000 --- a/usr/src/lib/print/libipp-listener/common/get-job-attributes.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: get-job-attributes.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_get_job_attributes(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_job_t j = NULL; - papi_attribute_t **operational = NULL; - papi_attribute_t **job_attributes = NULL; - - char **req_attrs = NULL; - char *queue = NULL; - int id = -1; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * the operational-attributes-group must contain: - * job-uri (or printer-uri/job-id) - */ - get_printer_id(operational, &queue, &id); - if (id < 0) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing job-uri or job-id"); - return (PAPI_BAD_REQUEST); - } else if (queue == NULL) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing printer-uri or job-uri"); - return (PAPI_BAD_REQUEST); - } - - /* - * the operational-attributes-group should contain: - * requested-attributes - */ - get_string_list(operational, "requested-attributes", &req_attrs); - - if ((status = papiJobQuery(svc, queue, id, req_attrs, &j)) != PAPI_OK) { - ipp_set_status(response, status, "query job: %s", - ipp_svc_status_mesg(svc, status)); - papiJobFree(j); /* we shouldn't have a job, but just in case */ - return (status); - } - - /* add the job attributes to the response in a job-attributes-group */ - if (j != NULL) { - papi_to_ipp_job_group(response, request, PAPI_ATTR_REPLACE, j); - papiJobFree(j); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/get-jobs.c b/usr/src/lib/print/libipp-listener/common/get-jobs.c deleted file mode 100644 index 0e5e56f44c..0000000000 --- a/usr/src/lib/print/libipp-listener/common/get-jobs.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: get-jobs.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_get_jobs(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_job_t *j = NULL; - papi_attribute_t **operational = NULL; - - char **req_attrs = NULL; - char *queue = NULL; - int limit = 0; - char my_jobs = PAPI_FALSE; - char *which; - int type = 0; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - /* - * The operational-attributes-group may contain: - * limit - * requested-attributes - * which-jobs - * my-jobs - */ - (void) papiAttributeListGetString(operational, NULL, - "which-jobs", &which); - (void) papiAttributeListGetBoolean(operational, NULL, - "my-jobs", &my_jobs); - (void) papiAttributeListGetInteger(operational, NULL, "limit", &limit); - get_string_list(operational, "requested-attributes", &req_attrs); - - status = papiPrinterListJobs(svc, queue, req_attrs, type, limit, &j); - if (status != PAPI_OK) { - ipp_set_status(response, status, "query jobs: %s", - ipp_svc_status_mesg(svc, status)); - return (status); - } - - /* add any job's attributes to the response in job-attribute-groups */ - if (j != NULL) { - int i; - - for (i = 0; j[i] != NULL; i++) - papi_to_ipp_job_group(response, request, - PAPI_ATTR_APPEND, j[i]); - papiJobListFree(j); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/get-printer-attributes.c b/usr/src/lib/print/libipp-listener/common/get-printer-attributes.c deleted file mode 100644 index 2f33d0039c..0000000000 --- a/usr/src/lib/print/libipp-listener/common/get-printer-attributes.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: get-printer-attributes.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_get_printer_attributes(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_printer_t p = NULL; - papi_attribute_t **operational = NULL; - papi_attribute_t **printer_attributes = NULL; - - char **req_attrs = NULL; - char *doc_fmt = NULL; - char *queue = NULL; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - /* - * The operational-attributes-group may contain: - * requested-attributes - * document-format - */ - get_string_list(operational, "requested-attributes", &req_attrs); - (void) papiAttributeListGetString(operational, NULL, - "document-format", &doc_fmt); - status = papiPrinterQuery(svc, queue, req_attrs, NULL, &p); - if (status != PAPI_OK) { - ipp_set_status(response, status, "query printer: %s", - ipp_svc_status_mesg(svc, status)); - papiPrinterFree(p); /* we shouldn't have a printer */ - return (status); - } - - /* - * add the printer attributes to the response in a - * printer-attributes-group - */ - if (p != NULL) { - papi_to_ipp_printer_group(response, request, - PAPI_ATTR_REPLACE, p); - papiPrinterFree(p); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/hold-job.c b/usr/src/lib/print/libipp-listener/common/hold-job.c deleted file mode 100644 index fcb1409df6..0000000000 --- a/usr/src/lib/print/libipp-listener/common/hold-job.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: hold-job.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_hold_job(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - - char *message = NULL; - char *queue = NULL; - int id = -1; - - /* Get operational attributes from the request */ - papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * the operational-attributes-group must contain: - * job-uri (or printer-uri/job-id) - */ - get_printer_id(operational, &queue, &id); - if (id < 0) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing job-uri or job-id"); - return (PAPI_BAD_REQUEST); - } else if (queue == NULL) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing printer-uri or job-uri"); - return (PAPI_BAD_REQUEST); - } - - /* - * the operational-attributes-group may contain: - * message - * job-hold-until (ingored) - */ - (void) papiAttributeListGetString(operational, NULL, - "message", &message); - - if ((status = papiJobHold(svc, queue, id)) != PAPI_OK) { - ipp_set_status(response, status, - "hold failed: %s-%d: %s", - (queue ? queue : "(null)"), id, - ipp_svc_status_mesg(svc, status)); - } else if (message != NULL) { /* add unsupported attribute group */ - papi_attribute_t **unsupported = NULL; - - papiAttributeListAddValue(&unsupported, PAPI_ATTR_EXCL, - "message", PAPI_COLLECTION, NULL); - (void) papiAttributeListAddCollection(response, - PAPI_ATTR_REPLACE, "unsupported-attributes-group", - unsupported); - papiAttributeListFree(unsupported); - - status = PAPI_OK_SUBST; - ipp_set_status(response, status, - "unsupported attribute in request"); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/ipp-listener.c b/usr/src/lib/print/libipp-listener/common/ipp-listener.c deleted file mode 100644 index 42f23f85e7..0000000000 --- a/usr/src/lib/print/libipp-listener/common/ipp-listener.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: ipp-listener.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <netinet/in.h> -#include <assert.h> -#include <errno.h> -#include <syslog.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/systeminfo.h> - -#include <papi.h> -#include <ipp-listener.h> -#include <uri.h> - -typedef papi_status_t (ipp_handler_t)(papi_service_t svc, - papi_attribute_t **request, - papi_attribute_t ***response, - ipp_reader_t iread, void *fd); - -/* - * protocol request handlers are inserted below. The handler must be - * declared extern immediately below this comment and then an entry - * must be inserted in the "handlers" table a little further down. - */ -extern ipp_handler_t ipp_print_job; -extern ipp_handler_t ipp_validate_job; -extern ipp_handler_t ipp_create_job; -extern ipp_handler_t ipp_get_printer_attributes; -extern ipp_handler_t ipp_get_jobs; -extern ipp_handler_t ipp_pause_printer; -extern ipp_handler_t ipp_resume_printer; -extern ipp_handler_t ipp_disable_printer; -extern ipp_handler_t ipp_enable_printer; -extern ipp_handler_t ipp_purge_jobs; -extern ipp_handler_t ipp_send_document; -extern ipp_handler_t ipp_cancel_job; -extern ipp_handler_t ipp_get_job_attributes; -extern ipp_handler_t ipp_release_job; -extern ipp_handler_t ipp_hold_job; -extern ipp_handler_t ipp_restart_job; -extern ipp_handler_t ipp_set_job_attributes; -extern ipp_handler_t ipp_set_printer_attributes; -extern ipp_handler_t cups_get_default; -extern ipp_handler_t cups_get_printers; -extern ipp_handler_t cups_get_classes; -extern ipp_handler_t cups_accept_jobs; -extern ipp_handler_t cups_reject_jobs; -extern ipp_handler_t cups_move_job; - -/* ARGSUSED0 */ -static papi_status_t -default_handler(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response, ipp_reader_t iread, void *fd) -{ - int result = (int)PAPI_INTERNAL_ERROR; - - if (response != NULL) - (void) papiAttributeListGetInteger(*response, NULL, - "status-code", &result); - - return ((papi_status_t)result); -} - -static struct { - int16_t id; - char *name; - ipp_handler_t *function; - enum { OP_REQUIRED, OP_OPTIONAL, OP_VENDOR } type; -} handlers[] = { - /* Printer Operations */ - { 0x0002, "print-job", ipp_print_job, OP_REQUIRED }, - { 0x0003, "print-uri", NULL, OP_OPTIONAL }, - { 0x0004, "validate-job", ipp_validate_job, - OP_REQUIRED }, - { 0x0005, "create-job", ipp_create_job, OP_OPTIONAL }, - { 0x000a, "get-jobs", ipp_get_jobs, OP_REQUIRED }, - { 0x000b, "get-printer-attributes", ipp_get_printer_attributes, - OP_REQUIRED }, - { 0x0010, "pause-printer", ipp_pause_printer, - OP_OPTIONAL }, - { 0x0011, "resume-printer", ipp_resume_printer, - OP_OPTIONAL }, - { 0x0012, "purge-jobs", ipp_purge_jobs, OP_OPTIONAL }, - { 0x0013, "set-printer-attributes", ipp_set_printer_attributes, - OP_OPTIONAL }, - { 0x0014, "set-job-attributes", ipp_set_job_attributes, - OP_OPTIONAL }, - { 0x0022, "enable-printer", ipp_enable_printer, - OP_OPTIONAL }, - { 0x0023, "disable-printer", ipp_disable_printer, - OP_OPTIONAL }, - /* Job Operations */ - { 0x0006, "send-document", ipp_send_document, - OP_OPTIONAL }, - { 0x0007, "send-uri", NULL, OP_OPTIONAL }, - { 0x0008, "cancel-job", ipp_cancel_job, OP_REQUIRED }, - { 0x0009, "get-job-attributes", ipp_get_job_attributes, - OP_REQUIRED }, - { 0x000c, "hold-job", ipp_hold_job, OP_OPTIONAL }, - { 0x000d, "release-job", ipp_release_job, - OP_OPTIONAL }, - { 0x000e, "restart-job", ipp_restart_job, - OP_OPTIONAL }, - /* Other Operations */ - { 0x4001, "cups-get-default", cups_get_default, - OP_VENDOR }, - { 0x4002, "cups-get-printers", cups_get_printers, - OP_VENDOR }, - { 0x4005, "cups-get-classes", cups_get_classes, - OP_VENDOR }, - { 0x4008, "cups-accept-jobs", cups_accept_jobs, - OP_VENDOR }, - { 0x4009, "cups-reject-jobs", cups_reject_jobs, - OP_VENDOR }, - { 0x400D, "cups-move-job", cups_move_job, OP_VENDOR }, - { 0, NULL, NULL, OP_VENDOR } -}; - -static int -ipp_operation_name_to_index(char *name) -{ - int i; - - for (i = 0; handlers[i].name != NULL; i++) - if (strcasecmp(name, handlers[i].name) == 0) - return (i); - - return (-1); -} - -static int -ipp_operation_id_to_index(int16_t id) -{ - int i; - - for (i = 0; handlers[i].name != NULL; i++) - if (id == handlers[i].id) - return (i); - - return (-1); -} - -static ipp_handler_t * -ipp_operation_handler(papi_attribute_t **request, papi_attribute_t ***response) -{ - int id = 0; - int index; - papi_attribute_t **ops = NULL; - papi_status_t status; - char configured = PAPI_FALSE; - - /* get the operation from the request */ - status = papiAttributeListGetInteger(request, NULL, - "operation-id", &id); - if (status != PAPI_OK) { - ipp_set_status(response, PAPI_BAD_ARGUMENT, - "no operation specified in request"); - return (default_handler); - } - - /* find the operation in the handler table */ - index = ipp_operation_id_to_index(id); -#ifdef DEBUG - if (index == -1) - fprintf(stderr, "Operation: 0x%4.4x\n", id); - else - fprintf(stderr, "Operation: 0x%4.4x(%s)\n", id, - handlers[index].name); - fflush(stderr); -#endif - - if ((index == -1) || (handlers[index].function == NULL)) { - ipp_set_status(response, PAPI_OPERATION_NOT_SUPPORTED, - "operation (0x%4.4x) not implemented by server", - id); - return (default_handler); - } - - /* find the configured operations */ - status = papiAttributeListGetCollection(request, NULL, - "operations", &ops); - if (status != PAPI_OK) { /* this should not be possible */ - ipp_set_status(response, PAPI_INTERNAL_ERROR, - "sofware error, no operations configured"); - return (default_handler); - } - - /* check if the requested operation is configured */ - status = papiAttributeListGetBoolean(ops, NULL, - handlers[index].name, &configured); - if ((status != PAPI_OK) || (configured != PAPI_TRUE)) { - ipp_set_status(response, PAPI_OPERATION_NOT_SUPPORTED, - "operation (%s 0x%4.4x) not enabled on server", - handlers[index].name, id); - return (default_handler); - } - - return (handlers[index].function); -} - -static char -type_to_boolean(char *type) -{ - char result = PAPI_FALSE; - - if ((strcasecmp(type, "true") == 0) || - (strcasecmp(type, "yes") == 0) || - (strcasecmp(type, "on") == 0) || - (strcasecmp(type, "enable") == 0)) - result = PAPI_TRUE; - - return (result); -} - -static papi_status_t -ipp_configure_required_operations(papi_attribute_t ***list, char boolean) -{ - papi_status_t result = PAPI_OK; - int i; - - for (i = 0; ((result == PAPI_OK) && (handlers[i].name != NULL)); i++) - if (handlers[i].type == OP_REQUIRED) - result = papiAttributeListAddBoolean(list, - PAPI_ATTR_REPLACE, handlers[i].name, - boolean); - - return (result); - -} - -static papi_status_t -ipp_configure_all_operations(papi_attribute_t ***list, char boolean) -{ - papi_status_t result = PAPI_OK; - int i; - - for (i = 0; ((result == PAPI_OK) && (handlers[i].name != NULL)); i++) - result = papiAttributeListAddBoolean(list, PAPI_ATTR_REPLACE, - handlers[i].name, boolean); - - return (result); -} - -papi_status_t -ipp_configure_operation(papi_attribute_t ***list, char *operation, char *type) -{ - papi_status_t result = PAPI_OPERATION_NOT_SUPPORTED; - char boolean = PAPI_FALSE; - - if ((list == NULL) || (operation == NULL) || (type == NULL)) - return (PAPI_BAD_ARGUMENT); - - boolean = type_to_boolean(type); - - if (strcasecmp(operation, "all") == 0) { - result = ipp_configure_all_operations(list, boolean); - } else if (strcasecmp(operation, "required") == 0) { - result = ipp_configure_required_operations(list, boolean); - } else if (ipp_operation_name_to_index(operation) != -1) { - result = papiAttributeListAddBoolean(list, PAPI_ATTR_REPLACE, - operation, boolean); - } - - return (result); -} - -void -ipp_operations_supported(papi_attribute_t ***list, papi_attribute_t **request) -{ - papi_attribute_t **group = NULL; - - (void) papiAttributeListGetCollection(request, NULL, - "operations", &group); - if (group != NULL) { - int i; - - for (i = 0; handlers[i].name != NULL; i++) { - char boolean = PAPI_FALSE; - (void) papiAttributeListGetBoolean(group, NULL, - handlers[i].name, &boolean); - - if (boolean == PAPI_TRUE) - (void) papiAttributeListAddInteger(list, - PAPI_ATTR_APPEND, - "operations-supported", - handlers[i].id); - } - } -} - -static papi_status_t -ipp_initialize_response(papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_attribute_t **operational = NULL; - int i; - - if ((request == NULL) || (response == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* If the response was initialized, start over */ - if (*response != NULL) { - papiAttributeListFree(*response); - *response = NULL; - } - - /* Add the basic ipp header information to the response */ - (void) papiAttributeListGetInteger(request, NULL, "version-major", &i); - (void) papiAttributeListAddInteger(response, PAPI_ATTR_REPLACE, - "version-major", i); - (void) papiAttributeListGetInteger(request, NULL, "version-minor", &i); - (void) papiAttributeListAddInteger(response, PAPI_ATTR_REPLACE, - "version-minor", i); - - (void) papiAttributeListGetInteger(request, NULL, "request-id", &i); - (void) papiAttributeListAddInteger(response, PAPI_ATTR_REPLACE, - "request-id", i); - - /* Add a default operational attributes group to the response */ - (void) papiAttributeListAddString(&operational, PAPI_ATTR_EXCL, - "attributes-charset", "utf-8"); - (void) papiAttributeListAddString(&operational, PAPI_ATTR_EXCL, - "attributes-natural-language", "en-us"); - - (void) papiAttributeListAddCollection(response, PAPI_ATTR_REPLACE, - "operational-attributes-group", operational); - papiAttributeListFree(operational); - - return (PAPI_OK); -} - -/* simplistic check for cyclical service references */ -static int -cyclical_service_check(char *svc_name, int port) -{ - papi_attribute_t **list; - char buf[BUFSIZ]; - uri_t *uri = NULL; - char *s = NULL; - - /* was there a service_uri? */ - if (svc_name == NULL) - return (0); - - if ((list = getprinterbyname(svc_name, NULL)) == NULL) - return (0); /* if it doesnt' resolve, we will fail later */ - - papiAttributeListGetString(list, NULL, "printer-uri-supported", &s); - if ((s == NULL) || (strcasecmp(svc_name, s) != 0)) - return (0); /* they don't match */ - - /* is it in uri form? */ - if (uri_from_string(s, &uri) < 0) - return (0); - - if ((uri == NULL) || (uri->scheme == NULL) || (uri->host == NULL)) { - uri_free(uri); - return (0); - } - - /* is it ipp form */ - if (strcasecmp(uri->scheme, "ipp") != 0) { - uri_free(uri); - return (0); - } - - /* does the host match up */ - if (is_localhost(uri->host) != 0) { - uri_free(uri); - return (0); - } - - /* does the port match our own */ - if (((uri->port == NULL) && (port != 631)) || - ((uri->port != NULL) && (atoi(uri->port) != port))) { - uri_free(uri); - return (0); - } - - uri_free(uri); - - return (1); -} - -static papi_status_t -print_service_connect(papi_service_t *svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - char *printer_uri = NULL; - char *svc_name = NULL; - char *user = NULL; - int port = 631; - - /* Get the operational attributes group from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* get the user name */ - (void) papiAttributeListGetString(request, NULL, "default-user", &user); - (void) papiAttributeListGetString(operational, NULL, - "requesting-user-name", &user); - - /* get the printer or service name */ - (void) papiAttributeListGetString(request, NULL, - "default-service", &svc_name); - get_printer_id(operational, &svc_name, NULL); - - /* get the port that we are listening on */ - (void) papiAttributeListGetInteger(request, NULL, "uri-port", &port); - - if (cyclical_service_check(svc_name, port) != 0) { - status = PAPI_NOT_POSSIBLE; - ipp_set_status(response, status, "printer-uri is cyclical"); - return (status); - } - - status = papiServiceCreate(svc, svc_name, user, NULL, NULL, - PAPI_ENCRYPT_NEVER, NULL); - if (status != PAPI_OK) { - ipp_set_status(response, status, "print service: %s", - papiStatusString(status)); - return (status); - } - - /* - * Trusted Solaris can't be trusting of intermediaries. Pass - * the socket connection to the print service to retrieve the - * sensativity label off of a multi-level port. - */ - { - int fd = -1; - - (void) papiAttributeListGetInteger(request, NULL, - "peer-socket", &fd); - if (fd != -1) - papiServiceSetPeer(*svc, fd); - } - - return (status); -} - -papi_status_t -ipp_process_request(papi_attribute_t **request, papi_attribute_t ***response, - ipp_reader_t iread, void *fd) -{ - papi_status_t result = PAPI_OK; - - ipp_initialize_response(request, response); - -#ifdef DEBUG - fprintf(stderr, "REQUEST:"); - papiAttributeListPrint(stderr, request, " %d ", getpid()); - fprintf(stderr, "\n"); -#endif - - /* verify that the request is "well-formed" */ - if ((result = ipp_validate_request(request, response)) == PAPI_OK) { - papi_service_t svc = NULL; - ipp_handler_t *handler; - - result = print_service_connect(&svc, request, response); - handler = ipp_operation_handler(request, response); - - /* process the request */ - if ((result == PAPI_OK) && (handler != NULL)) - result = (handler)(svc, request, response, iread, fd); -#ifdef DEBUG - fprintf(stderr, "RESULT: %s\n", papiStatusString(result)); -#endif - papiServiceDestroy(svc); - } - - (void) papiAttributeListAddInteger(response, PAPI_ATTR_EXCL, - "status-code", result); - massage_response(request, *response); - -#ifdef DEBUG - fprintf(stderr, "RESPONSE:"); - papiAttributeListPrint(stderr, *response, " %d ", getpid()); - fprintf(stderr, "\n"); -#endif - - return (result); -} diff --git a/usr/src/lib/print/libipp-listener/common/ipp-listener.h b/usr/src/lib/print/libipp-listener/common/ipp-listener.h deleted file mode 100644 index 5a8718477e..0000000000 --- a/usr/src/lib/print/libipp-listener/common/ipp-listener.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -#ifndef _IPP_LISTENER_H -#define _IPP_LISTENER_H - -/* $Id: ipp-listener.h 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <ipp.h> - -/* exported functions */ -extern papi_status_t ipp_configure_operation(papi_attribute_t ***list, - char *operation, char *type); -extern papi_status_t ipp_process_request(papi_attribute_t **request, - papi_attribute_t ***response, - ipp_reader_t iread, void *fd); - -/* shared internal functions */ -extern char *ipp_svc_status_mesg(papi_service_t svc, papi_status_t status); -extern char *destination_from_printer_uri(char *); -extern void get_printer_id(papi_attribute_t **attributes, char **printer, - int *id); -extern void ipp_operations_supported(papi_attribute_t ***list, - papi_attribute_t **request); -extern void get_string_list(papi_attribute_t **attributes, char *name, - char ***values); -extern void add_default_attributes(papi_attribute_t ***attributes); -extern void papi_to_ipp_printer_group(papi_attribute_t ***response, - papi_attribute_t **request, int flags, - papi_printer_t p); -extern void papi_to_ipp_job_group(papi_attribute_t ***response, - papi_attribute_t **request, int flags, papi_job_t j); -extern void massage_response(papi_attribute_t **request, - papi_attribute_t **response); - -#ifdef __cplusplus -} -#endif - -#endif /* _IPP_LISTENER_H */ diff --git a/usr/src/lib/print/libipp-listener/common/pause-printer.c b/usr/src/lib/print/libipp-listener/common/pause-printer.c deleted file mode 100644 index 0afe4aadf0..0000000000 --- a/usr/src/lib/print/libipp-listener/common/pause-printer.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: pause-printer.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_pause_printer(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - - char *queue = NULL; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - if ((status = papiPrinterPause(svc, queue, NULL)) != PAPI_OK) { - ipp_set_status(response, status, "pause failed: %s: %s", - (queue ? queue : "(null)"), - ipp_svc_status_mesg(svc, status)); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/print-job.c b/usr/src/lib/print/libipp-listener/common/print-job.c deleted file mode 100644 index 29d6b5c5be..0000000000 --- a/usr/src/lib/print/libipp-listener/common/print-job.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: print-job.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#include <stdio.h> -#include <stdlib.h> -#include <netdb.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_print_job(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response, ipp_reader_t iread, void *fd) -{ - papi_status_t status; - papi_stream_t s = NULL; - papi_job_t j = NULL; - papi_attribute_t **operational = NULL; - papi_attribute_t **job_attributes = NULL; - char *queue = NULL; - ssize_t rc; - char buf[BUFSIZ]; - char *host = NULL; - int fp = -1; - char *keys[] = { "attributes-natural-language", "attributes-charset", - "printer-uri", NULL }; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - /* - * The operational-attributes-group may contain: - * job-name - * ipp-attribute-fidelity - * document-name - * compression - * document-format - * document-natural-language - * job-k-octets - * job-impressions - * job-media-sheets - * Simply copy the entire contents of the operational-attributes-group - * for the PAPI call's possible use. - */ - split_and_copy_attributes(keys, operational, NULL, &job_attributes); - - /* copy any job-attributes-group attributes for the PAPI call */ - if (papiAttributeListGetCollection(request, NULL, - "job-attributes-group", &operational) == PAPI_OK) { - char *user = NULL; - - copy_attributes(&job_attributes, operational); - - if (papiAttributeListGetString(operational, NULL, - "requesting-user-name", &user) == PAPI_OK) { - papiAttributeListAddString(&job_attributes, - PAPI_ATTR_REPLACE, "requesting-user-name", user); - } - } - - /* Set "job-originating-host-name" in next block */ - (void) papiAttributeListGetInteger(request, NULL, - "peer-socket", &fp); - - if (fp != -1) { - struct sockaddr_in peer; - socklen_t peer_len = sizeof (peer); - - /* who is our peer ? */ - if (getpeername(fp, (struct sockaddr *)&peer, - &peer_len) == 0) { - struct hostent *he; - int error_num; - - /* - * get their name or return a string containing - * their address - */ - if ((he = getipnodebyaddr((const char *)&peer.sin_addr, - sizeof (peer.sin_addr), peer.sin_family, - &error_num)) == NULL) { - char tmp_buf[INET6_ADDRSTRLEN]; - papiAttributeListAddString( - &job_attributes, - PAPI_ATTR_REPLACE, - "job-originating-host-name", - (char *)inet_ntop(peer.sin_family, - &peer.sin_addr, tmp_buf, - sizeof (tmp_buf))); - - } else { - if (is_localhost(he->h_name) != 0) - papiAttributeListAddString( - &job_attributes, - PAPI_ATTR_REPLACE, - "job-originating-host-name", - "localhost"); - else if (he->h_name != NULL) - papiAttributeListAddString( - &job_attributes, - PAPI_ATTR_REPLACE, - "job-originating-host-name", - he->h_name); - } - } - } - - /* request job creation with a resulting stream that we can write to */ - status = papiJobStreamOpen(svc, queue, job_attributes, NULL, &s); - papiAttributeListFree(job_attributes); - if (status != PAPI_OK) { - ipp_set_status(response, status, "job submission: %s", - ipp_svc_status_mesg(svc, status)); - return (status); - } - - /* copy the document data from the IPP connection to the stream */ - while ((status == PAPI_OK) && ((rc = iread(fd, buf, sizeof (buf))) > 0)) - status = papiJobStreamWrite(svc, s, buf, rc); - if (status != PAPI_OK) { - ipp_set_status(response, status, "write job data: %s", - ipp_svc_status_mesg(svc, status)); - return (status); - } - - /* close the stream, committing the job */ - status = papiJobStreamClose(svc, s, &j); - if (status != PAPI_OK) { - ipp_set_status(response, status, "close job stream: %s", - ipp_svc_status_mesg(svc, status)); - papiJobFree(j); /* we shouldn't have a job, but just in case */ - return (status); - } - - /* add the job attributes to the response in a job-attributes-group */ - if (j != NULL) { - papi_to_ipp_job_group(response, request, PAPI_ATTR_REPLACE, j); - papiJobFree(j); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/purge-jobs.c b/usr/src/lib/print/libipp-listener/common/purge-jobs.c deleted file mode 100644 index 7128595844..0000000000 --- a/usr/src/lib/print/libipp-listener/common/purge-jobs.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: purge-jobs.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_purge_jobs(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_job_t *jobs = NULL; - papi_attribute_t **operational = NULL; - - char *queue = NULL; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - if ((status = papiPrinterPurgeJobs(svc, queue, &jobs)) != PAPI_OK) { - ipp_set_status(response, status, "purge failed: %s: %s", - (queue ? queue : "(null)"), - ipp_svc_status_mesg(svc, status)); - } - - papiJobListFree(jobs); - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/release-job.c b/usr/src/lib/print/libipp-listener/common/release-job.c deleted file mode 100644 index 0ae16906a6..0000000000 --- a/usr/src/lib/print/libipp-listener/common/release-job.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: release-job.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_release_job(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - - char *message = NULL; - char *queue = NULL; - int id = -1; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * the operational-attributes-group must contain: - * job-uri (or printer-uri/job-id) - */ - get_printer_id(operational, &queue, &id); - if (id < 0) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing job-uri or job-id"); - return (PAPI_BAD_REQUEST); - } else if (queue == NULL) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing printer-uri or job-uri"); - return (PAPI_BAD_REQUEST); - } - - /* - * the operational-attributes-group may contain: - * message - */ - (void) papiAttributeListGetString(operational, NULL, - "message", &message); - - if ((status = papiJobRelease(svc, queue, id)) != PAPI_OK) { - ipp_set_status(response, status, - "release failed: %s-%d: %s", - (queue ? queue : "(null)"), id, - ipp_svc_status_mesg(svc, status)); - } else if (message != NULL) { /* add unsupported attribute group */ - papi_attribute_t **unsupported = NULL; - - papiAttributeListAddValue(&unsupported, PAPI_ATTR_EXCL, - "message", PAPI_COLLECTION, NULL); - (void) papiAttributeListAddCollection(response, - PAPI_ATTR_REPLACE, "unsupported-attributes-group", - unsupported); - papiAttributeListFree(unsupported); - - status = PAPI_OK_SUBST; - ipp_set_status(response, status, - "unsupported attribute in request"); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/restart-job.c b/usr/src/lib/print/libipp-listener/common/restart-job.c deleted file mode 100644 index d78967b0f2..0000000000 --- a/usr/src/lib/print/libipp-listener/common/restart-job.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: restart-job.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_restart_job(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - - char *message = NULL; - char *hold_until = NULL; - char *queue = NULL; - int id = -1; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * the operational-attributes-group must contain: - * job-uri (or printer-uri/job-id) - */ - get_printer_id(operational, &queue, &id); - if (id < 0) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing job-uri or job-id"); - return (PAPI_BAD_REQUEST); - } else if (queue == NULL) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing printer-uri or job-uri"); - return (PAPI_BAD_REQUEST); - } - - /* - * the operational-attributes-group may contain: - * message - * job-hold-until - */ - (void) papiAttributeListGetString(operational, NULL, - "job-hold-until", &hold_until); - (void) papiAttributeListGetString(operational, NULL, - "message", &message); - - if ((status = papiJobRestart(svc, queue, id)) != PAPI_OK) { - ipp_set_status(response, status, - "restart failed: %s-%d: %s", - (queue ? queue : "(null)"), id, - ipp_svc_status_mesg(svc, status)); - } else if ((message != NULL) || (hold_until != NULL)) { - /* add unsupported attribute group */ - papi_attribute_t **unsupported = NULL; - - if (message != NULL) - (void) papiAttributeListAddValue(&unsupported, - PAPI_ATTR_EXCL, "message", - PAPI_COLLECTION, NULL); - if (hold_until != NULL) - (void) papiAttributeListAddValue(&unsupported, - PAPI_ATTR_EXCL, "hold-until", - PAPI_COLLECTION, NULL); - (void) papiAttributeListAddCollection(response, - PAPI_ATTR_REPLACE, "unsupported-attributes-group", - unsupported); - papiAttributeListFree(unsupported); - - status = PAPI_OK_SUBST; - ipp_set_status(response, status, - "unsupported attribute in request"); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/resume-printer.c b/usr/src/lib/print/libipp-listener/common/resume-printer.c deleted file mode 100644 index 8d48ee9adb..0000000000 --- a/usr/src/lib/print/libipp-listener/common/resume-printer.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: resume-printer.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_resume_printer(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - papi_status_t status; - papi_attribute_t **operational = NULL; - - char *queue = NULL; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - if ((status = papiPrinterResume(svc, queue)) != PAPI_OK) { - ipp_set_status(response, status, "resume failed: %s: %s", - (queue ? queue : "(null)"), - ipp_svc_status_mesg(svc, status)); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/send-document.c b/usr/src/lib/print/libipp-listener/common/send-document.c deleted file mode 100644 index 4a4d3a4314..0000000000 --- a/usr/src/lib/print/libipp-listener/common/send-document.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: send-document.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -/* - * When the PAPI supports papiJobCreate(), papiJobStreamAdd() and - * papiJobClose(), this will be much cleaner and more efficient, but in the - * meantime, we are using a private, non-standard interface to do this. - */ -papi_status_t -ipp_send_document(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response, ipp_reader_t iread, void *fd) -{ - papi_status_t status; - papi_stream_t s = NULL; - papi_job_t j = NULL; - papi_attribute_t **operational = NULL; - papi_attribute_t **job_attributes = NULL; - char *queue = NULL; - ssize_t rc; - int id = -1; - char buf[BUFSIZ]; - char last = PAPI_FALSE; - char *keys[] = { "attributes-natural-language", "attributes-charset", - "printer-uri", "job-id", "job-uri", "last-document", - NULL }; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * the operational-attributes-group must contain: - * job-uri (or printer-uri/job-id) - * last-document - */ - get_printer_id(operational, &queue, &id); - if (id < 0) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing job-uri or job-id"); - return (PAPI_BAD_REQUEST); - } else if (queue == NULL) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing printer-uri or job-uri"); - return (PAPI_BAD_REQUEST); - } - - status = papiAttributeListGetBoolean(operational, NULL, - "last-document", &last); - if (status != PAPI_OK) { - ipp_set_status(response, status, "last-document: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - /* - * the operational-attributes-group may contain: - * document-name - * compression - * document-format - * document-natural-language - * Simply copy the entire contents of the operational-attributes-group - * for the PAPI call's possible use. - */ - split_and_copy_attributes(keys, operational, NULL, &job_attributes); - - /* copy any job-attributes-group attributes for the PAPI call */ - if (papiAttributeListGetCollection(request, NULL, - "job-attributes-group", &operational) == PAPI_OK) - copy_attributes(&job_attributes, operational); - - /* create a stream to write the document data on */ - status = papiJobStreamAdd(svc, queue, id, &s); - papiAttributeListFree(job_attributes); - if (status != PAPI_OK) { - ipp_set_status(response, status, "job submission: %s", - ipp_svc_status_mesg(svc, status)); - return (status); - } - - /* copy the document data from the IPP connection to the stream */ - while ((status == PAPI_OK) && ((rc = iread(fd, buf, sizeof (buf))) > 0)) - status = papiJobStreamWrite(svc, s, buf, rc); - if (status != PAPI_OK) { - ipp_set_status(response, status, "write job data: %s", - ipp_svc_status_mesg(svc, status)); - return (status); - } - - /* close the stream */ - status = papiJobStreamClose(svc, s, &j); - if (status != PAPI_OK) { - ipp_set_status(response, status, "close job stream: %s", - ipp_svc_status_mesg(svc, status)); - papiJobFree(j); /* we shouldn't have a job, but just in case */ - return (status); - } - - /* if it's the last document, commit the job */ - if (last == PAPI_TRUE) { - status = papiJobCommit(svc, queue, id); - } - - /* add the job attributes to the response in a job-attributes-group */ - if (j != NULL) { - papi_to_ipp_job_group(response, request, PAPI_ATTR_REPLACE, j); - papiJobFree(j); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/set-job-attributes.c b/usr/src/lib/print/libipp-listener/common/set-job-attributes.c deleted file mode 100644 index 57c0b899f3..0000000000 --- a/usr/src/lib/print/libipp-listener/common/set-job-attributes.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: set-job-attributes.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_set_job_attributes(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response, ipp_reader_t iread, void *fd) -{ - papi_status_t status; - papi_stream_t s = NULL; - papi_job_t j = NULL; - papi_attribute_t **operational = NULL; - papi_attribute_t **job_attributes = NULL; - - char *queue = NULL; - int32_t id = -1; - ssize_t rc; - char buf[BUFSIZ]; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * job-uri - */ - get_printer_id(operational, &queue, &id); - if (id < 0) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing job-uri or job-id"); - return (PAPI_BAD_REQUEST); - } else if (queue == NULL) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing printer-uri or job-uri"); - return (PAPI_BAD_REQUEST); - } - - /* get the job-attributes-group attributes for the PAPI call */ - papiAttributeListGetCollection(request, NULL, - "job-attributes-group", &job_attributes); - - /* request job modification */ - status = papiJobModify(svc, queue, id, job_attributes, &j); - if (status != PAPI_OK) { - ipp_set_status(response, status, "job modification: %s", - ipp_svc_status_mesg(svc, status)); - return (status); - } - - /* add the job attributes to the response in a job-attributes-group */ - if (j != NULL) { - papi_to_ipp_job_group(response, request, PAPI_ATTR_REPLACE, j); - papiJobFree(j); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/set-printer-attributes.c b/usr/src/lib/print/libipp-listener/common/set-printer-attributes.c deleted file mode 100644 index 7d80864961..0000000000 --- a/usr/src/lib/print/libipp-listener/common/set-printer-attributes.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: set-printer-attributes.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_set_printer_attributes(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response, ipp_reader_t iread, void *fd) -{ - papi_status_t status; - papi_printer_t p = NULL; - papi_attribute_t **operational = NULL; - papi_attribute_t **printer_attributes = NULL; - - char *queue = NULL; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, PAPI_BAD_REQUEST, - "missing printer-uri or job-uri"); - return (PAPI_BAD_REQUEST); - } - - /* get the printer-attributes-group attributes for the PAPI call */ - papiAttributeListGetCollection(request, NULL, - "printer-attributes-group", &printer_attributes); - - /* request job modification */ - status = papiPrinterModify(svc, queue, printer_attributes, &p); - if (status != PAPI_OK) { - ipp_set_status(response, status, "printer modification: %s", - ipp_svc_status_mesg(svc, status)); - return (status); - } - - /* add the job attributes to the response in a job-attributes-group */ - if (p != NULL) { - papi_to_ipp_printer_group(response, request, - PAPI_ATTR_REPLACE, p); - papiPrinterFree(p); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/common/validate-job.c b/usr/src/lib/print/libipp-listener/common/validate-job.c deleted file mode 100644 index 8ea72ee38b..0000000000 --- a/usr/src/lib/print/libipp-listener/common/validate-job.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: validate-job.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <papi.h> -#include <ipp.h> -#include <ipp-listener.h> - -papi_status_t -ipp_validate_job(papi_service_t svc, papi_attribute_t **request, - papi_attribute_t ***response, ipp_reader_t iread, void *fd) -{ - papi_status_t status; - papi_job_t j = NULL; - papi_attribute_t **operational = NULL; - papi_attribute_t **job_attributes = NULL; - char *queue = NULL; - char *files[] = { "/etc/syslog.conf", NULL }; - ssize_t rc; - char buf[BUFSIZ]; - char *keys[] = { "attributes-natural-language", "attributes-charset", - "printer-uri", NULL }; - - /* Get operational attributes from the request */ - (void) papiAttributeListGetCollection(request, NULL, - "operational-attributes-group", &operational); - - /* - * The operational-attributes-group must contain: - * printer-uri - */ - get_printer_id(operational, &queue, NULL); - if (queue == NULL) { - ipp_set_status(response, status, "printer-uri: %s", - papiStatusString(status)); - return (PAPI_BAD_REQUEST); - } - - /* - * The operational-attributes-group may contain: - * job-name - * ipp-attribute-fidelity - * document-name - * compression - * document-format - * document-natural-language - * job-k-octets - * job-impressions - * job-media-sheets - * Simply copy the entire contents of the operational-attributes-group - * for the PAPI call's possible use. - */ - split_and_copy_attributes(keys, operational, NULL, &job_attributes); - - /* copy any job-attributes-group attributes for the PAPI call */ - if (papiAttributeListGetCollection(request, NULL, - "job-attributes-group", &operational) == PAPI_OK) - copy_attributes(&job_attributes, operational); - - /* request job validation */ - status = papiJobValidate(svc, queue, job_attributes, NULL, files, &j); - papiAttributeListFree(job_attributes); - - if (status != PAPI_OK) { - ipp_set_status(response, status, "validating job: %s", - ipp_svc_status_mesg(svc, status)); - papiJobFree(j); /* we shouldn't have a job, but just in case */ - return (status); - } - - /* add the job attributes to the response in a job-attributes-group */ - if (j != NULL) { - papi_to_ipp_job_group(response, request, PAPI_ATTR_REPLACE, j); - papiJobFree(j); - } - - return (status); -} diff --git a/usr/src/lib/print/libipp-listener/i386/Makefile b/usr/src/lib/print/libipp-listener/i386/Makefile deleted file mode 100644 index 3b985583a4..0000000000 --- a/usr/src/lib/print/libipp-listener/i386/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBS) $(ROOTLINKS) # $(ROOTLINT) diff --git a/usr/src/lib/print/libipp-listener/sparc/Makefile b/usr/src/lib/print/libipp-listener/sparc/Makefile deleted file mode 100644 index 3b985583a4..0000000000 --- a/usr/src/lib/print/libipp-listener/sparc/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBS) $(ROOTLINKS) # $(ROOTLINT) diff --git a/usr/src/lib/print/libpapi-common/Makefile b/usr/src/lib/print/libpapi-common/Makefile deleted file mode 100644 index ef7e964b85..0000000000 --- a/usr/src/lib/print/libpapi-common/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../../Makefile.lib - -HDRS = papi.h -HDRDIR = common -SUBDIRS = $(MACH) -#$(BUILD64)SUBDIRS += $(MACH64) - -all := TARGET = all -clean := TARGET = clean -clobber := TARGET = clobber -install := TARGET = install -lint := TARGET = lint - -.KEEP_STATE: - -all clean clobber: .WAIT $(SUBDIRS) -install: .WAIT $(SUBDIRS) install_h - -lint: # $(SUBDIRS) - -install_h: $(ROOTHDRS) - -check: $(CHECKHDRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: - -include ../../Makefile.targ diff --git a/usr/src/lib/print/libpapi-common/common/attribute.c b/usr/src/lib/print/libpapi-common/common/attribute.c deleted file mode 100644 index 244e54555d..0000000000 --- a/usr/src/lib/print/libpapi-common/common/attribute.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: attribute.c 157 2006-04-26 15:07:55Z ktou $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <ctype.h> -#include <alloca.h> -#include <papi.h> -#include <regex.h> - -#define MAX_PAGES 32767 -/* - * Assuming the maximum number of pages in - * a document to be 32767 - */ - -static void papiAttributeFree(papi_attribute_t *attribute); - -static void -papiAttributeValueFree(papi_attribute_value_type_t type, - papi_attribute_value_t *value) -{ - if (value != NULL) { - switch (type) { - case PAPI_STRING: - if (value->string != NULL) - free(value->string); - break; - case PAPI_COLLECTION: - if (value->collection != NULL) { - int i; - - for (i = 0; value->collection[i] != NULL; i++) - papiAttributeFree(value->collection[i]); - - free(value->collection); - } - break; - default: /* don't need to free anything extra */ - break; - } - - free(value); - } -} - -static void -papiAttributeValuesFree(papi_attribute_value_type_t type, - papi_attribute_value_t **values) -{ - if (values != NULL) { - int i; - - for (i = 0; values[i] != NULL; i++) - papiAttributeValueFree(type, values[i]); - - free(values); - } -} - -static void -papiAttributeFree(papi_attribute_t *attribute) -{ - if (attribute != NULL) { - if (attribute->name != NULL) - free(attribute->name); - if (attribute->values != NULL) - papiAttributeValuesFree(attribute->type, - attribute->values); - free(attribute); - } -} - -void -papiAttributeListFree(papi_attribute_t **list) -{ - if (list != NULL) { - int i; - - for (i = 0; list[i] != NULL; i++) - papiAttributeFree(list[i]); - - free(list); - } -} - -static papi_attribute_t ** -collection_dup(papi_attribute_t **collection) -{ - papi_attribute_t **result = NULL; - - /* allows a NULL collection that is "empty" or "no value" */ - if (collection != NULL) { - papi_status_t status = PAPI_OK; - int i; - - for (i = 0; ((collection[i] != NULL) && (status == PAPI_OK)); - i++) { - papi_attribute_t *a = collection[i]; - - status = papiAttributeListAddValue(&result, - PAPI_ATTR_APPEND, a->name, a->type, - NULL); - if ((status == PAPI_OK) && (a->values != NULL)) { - int j; - - for (j = 0; ((a->values[j] != NULL) && - (status == PAPI_OK)); j++) - status = papiAttributeListAddValue( - &result, - PAPI_ATTR_APPEND, - a->name, a->type, - a->values[j]); - } - } - if (status != PAPI_OK) { - papiAttributeListFree(result); - result = NULL; - } - } - - return (result); -} - -static papi_attribute_value_t * -papiAttributeValueDup(papi_attribute_value_type_t type, - papi_attribute_value_t *v) -{ - papi_attribute_value_t *result = NULL; - - if ((v != NULL) && ((result = calloc(1, sizeof (*result))) != NULL)) { - switch (type) { - case PAPI_STRING: - if (v->string == NULL) { - free(result); - result = NULL; - } else - result->string = strdup(v->string); - break; - case PAPI_INTEGER: - result->integer = v->integer; - break; - case PAPI_BOOLEAN: - result->boolean = v->boolean; - break; - case PAPI_RANGE: - result->range.lower = v->range.lower; - result->range.upper = v->range.upper; - break; - case PAPI_RESOLUTION: - result->resolution.xres = v->resolution.xres; - result->resolution.yres = v->resolution.yres; - result->resolution.units = v->resolution.units; - break; - case PAPI_DATETIME: - result->datetime = v->datetime; - break; - case PAPI_COLLECTION: - result->collection = collection_dup(v->collection); - break; - case PAPI_METADATA: - result->metadata = v->metadata; - break; - default: /* unknown type, fail to duplicate */ - free(result); - result = NULL; - } - } - - return (result); -} - -static papi_attribute_t * -papiAttributeAlloc(char *name, papi_attribute_value_type_t type) -{ - papi_attribute_t *result = NULL; - - if ((result = calloc(1, sizeof (*result))) != NULL) { - result->name = strdup(name); - result->type = type; - } - - return (result); -} - -static papi_status_t -papiAttributeListAppendValue(papi_attribute_value_t ***values, - papi_attribute_value_type_t type, - papi_attribute_value_t *value) -{ - - if (values == NULL) - return (PAPI_BAD_ARGUMENT); - - if (value != NULL) { /* this allows "empty" attributes */ - papi_attribute_value_t *tmp = NULL; - - if ((tmp = papiAttributeValueDup(type, value)) == NULL) - return (PAPI_TEMPORARY_ERROR); - - list_append(values, tmp); - } - - return (PAPI_OK); -} - -papi_status_t -papiAttributeListAddValue(papi_attribute_t ***list, int flgs, - char *name, papi_attribute_value_type_t type, - papi_attribute_value_t *value) -{ - papi_status_t result; - int flags = flgs; - papi_attribute_t *attribute = NULL; - papi_attribute_value_t **values = NULL; - - if ((list == NULL) || (name == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((type == PAPI_RANGE) && (value != NULL) && - (value->range.lower > value->range.upper)) - return (PAPI_BAD_ARGUMENT); /* RANGE must have min <= max */ - - if (flags == 0) /* if it wasn't set, set a default behaviour */ - flags = PAPI_ATTR_APPEND; - - /* look for an existing one */ - attribute = papiAttributeListFind(*list, name); - - if (((flags & PAPI_ATTR_EXCL) != 0) && (attribute != NULL)) - return (PAPI_CONFLICT); /* EXISTS */ - - if (((flags & PAPI_ATTR_REPLACE) == 0) && (attribute != NULL) && - (attribute->type != type)) - return (PAPI_CONFLICT); /* TYPE CONFLICT */ - - /* if we don't have one, create it and add it to the list */ - if ((attribute == NULL) && - ((attribute = papiAttributeAlloc(name, type)) != NULL)) - list_append(list, attribute); - - /* if we don't have one by now, it's most likely an alloc fail */ - if (attribute == NULL) - return (PAPI_TEMPORARY_ERROR); - - /* - * if we are replacing, clear any existing values, but don't free - * until after we have replaced the values, in case we are replacing - * a collection with a relocated version of the original collection. - */ - if (((flags & PAPI_ATTR_REPLACE) != 0) && (attribute->values != NULL)) { - values = attribute->values; - attribute->values = NULL; - } - - attribute->type = type; - - result = papiAttributeListAppendValue(&attribute->values, type, value); - - /* free old values if we replaced them */ - if (values != NULL) - papiAttributeValuesFree(type, values); - - return (result); -} - -papi_status_t -papiAttributeListAddString(papi_attribute_t ***list, int flags, - char *name, char *string) -{ - papi_attribute_value_t v; - - v.string = (char *)string; - return (papiAttributeListAddValue(list, flags, name, PAPI_STRING, &v)); -} - -papi_status_t -papiAttributeListAddInteger(papi_attribute_t ***list, int flags, - char *name, int integer) -{ - papi_attribute_value_t v; - - v.integer = integer; - return (papiAttributeListAddValue(list, flags, name, PAPI_INTEGER, &v)); -} - -papi_status_t -papiAttributeListAddBoolean(papi_attribute_t ***list, int flags, - char *name, char boolean) -{ - papi_attribute_value_t v; - - v.boolean = boolean; - return (papiAttributeListAddValue(list, flags, name, PAPI_BOOLEAN, &v)); -} - -papi_status_t -papiAttributeListAddRange(papi_attribute_t ***list, int flags, - char *name, int lower, int upper) -{ - papi_attribute_value_t v; - - v.range.lower = lower; - v.range.upper = upper; - return (papiAttributeListAddValue(list, flags, name, PAPI_RANGE, &v)); -} - -papi_status_t -papiAttributeListAddResolution(papi_attribute_t ***list, int flags, - char *name, int xres, int yres, - papi_resolution_unit_t units) -{ - papi_attribute_value_t v; - - v.resolution.xres = xres; - v.resolution.yres = yres; - v.resolution.units = units; - return (papiAttributeListAddValue(list, flags, name, - PAPI_RESOLUTION, &v)); -} - -papi_status_t -papiAttributeListAddDatetime(papi_attribute_t ***list, int flags, - char *name, time_t datetime) -{ - papi_attribute_value_t v; - - v.datetime = datetime; - return (papiAttributeListAddValue(list, flags, name, - PAPI_DATETIME, &v)); -} - -papi_status_t -papiAttributeListAddCollection(papi_attribute_t ***list, int flags, - char *name, papi_attribute_t **collection) -{ - papi_attribute_value_t v; - - v.collection = (papi_attribute_t **)collection; - return (papiAttributeListAddValue(list, flags, name, - PAPI_COLLECTION, &v)); -} - -papi_status_t -papiAttributeListAddMetadata(papi_attribute_t ***list, int flags, - char *name, papi_metadata_t metadata) -{ - papi_attribute_value_t v; - - v.metadata = metadata; - return (papiAttributeListAddValue(list, flags, name, - PAPI_METADATA, &v)); -} - -papi_status_t -papiAttributeListDelete(papi_attribute_t ***list, char *name) -{ - papi_attribute_t *attribute; - - if ((list == NULL) || (name == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((attribute = papiAttributeListFind(*list, name)) == NULL) - return (PAPI_NOT_FOUND); - - list_remove(list, attribute); - papiAttributeFree(attribute); - - return (PAPI_OK); -} - -papi_attribute_t * -papiAttributeListFind(papi_attribute_t **list, char *name) -{ - int i; - if ((list == NULL) || (name == NULL)) - return (NULL); - - for (i = 0; list[i] != NULL; i++) - if (strcasecmp(list[i]->name, name) == 0) - return ((papi_attribute_t *)list[i]); - - return (NULL); -} - -papi_attribute_t * -papiAttributeListGetNext(papi_attribute_t **list, void **iter) -{ - papi_attribute_t **tmp, *result; - - if ((list == NULL) && (iter == NULL)) - return (NULL); - - if (*iter == NULL) - *iter = list; - - tmp = *iter; - result = *tmp; - *iter = ++tmp; - - return (result); -} - -papi_status_t -papiAttributeListGetValue(papi_attribute_t **list, void **iter, - char *name, papi_attribute_value_type_t type, - papi_attribute_value_t **value) -{ - papi_attribute_value_t **tmp; - void *fodder = NULL; - - if ((list == NULL) || ((name == NULL) && (iter == NULL)) || - (value == NULL)) - return (PAPI_BAD_ARGUMENT); - - if (iter == NULL) - iter = &fodder; - - if ((iter == NULL) || (*iter == NULL)) { - papi_attribute_t *attr = papiAttributeListFind(list, name); - - if (attr == NULL) - return (PAPI_NOT_FOUND); - - if (attr->type != type) - return (PAPI_NOT_POSSIBLE); - - tmp = attr->values; - } else - tmp = *iter; - - if (tmp == NULL) - return (PAPI_NOT_FOUND); - - *value = *tmp; - *iter = ++tmp; - - if (*value == NULL) - return (PAPI_GONE); - - return (PAPI_OK); -} - -papi_status_t -papiAttributeListGetString(papi_attribute_t **list, void **iter, - char *name, char **vptr) -{ - papi_status_t status; - papi_attribute_value_t *value = NULL; - - if (vptr == NULL) - return (PAPI_BAD_ARGUMENT); - - status = papiAttributeListGetValue(list, iter, name, - PAPI_STRING, &value); - if (status == PAPI_OK) - *vptr = value->string; - - return (status); -} - -papi_status_t -papiAttributeListGetInteger(papi_attribute_t **list, void **iter, - char *name, int *vptr) -{ - papi_status_t status; - papi_attribute_value_t *value = NULL; - - if (vptr == NULL) - return (PAPI_BAD_ARGUMENT); - - status = papiAttributeListGetValue(list, iter, name, - PAPI_INTEGER, &value); - if (status == PAPI_OK) - *vptr = value->integer; - - return (status); -} - -papi_status_t -papiAttributeListGetBoolean(papi_attribute_t **list, void **iter, - char *name, char *vptr) -{ - papi_status_t status; - papi_attribute_value_t *value = NULL; - - if (vptr == NULL) - return (PAPI_BAD_ARGUMENT); - - status = papiAttributeListGetValue(list, iter, name, - PAPI_BOOLEAN, &value); - if (status == PAPI_OK) - *vptr = value->boolean; - - return (status); -} - -papi_status_t -papiAttributeListGetRange(papi_attribute_t **list, void **iter, - char *name, int *min, int *max) -{ - papi_status_t status; - papi_attribute_value_t *value = NULL; - - if ((min == NULL) || (max == NULL)) - return (PAPI_BAD_ARGUMENT); - - status = papiAttributeListGetValue(list, iter, name, - PAPI_RANGE, &value); - if (status == PAPI_OK) { - *min = value->range.lower; - *max = value->range.upper; - } - - return (status); -} - -papi_status_t -papiAttributeListGetResolution(papi_attribute_t **list, void **iter, - char *name, int *x, int *y, - papi_resolution_unit_t *units) -{ - papi_status_t status; - papi_attribute_value_t *value = NULL; - - if ((x == NULL) || (y == NULL) || (units == NULL)) - return (PAPI_BAD_ARGUMENT); - - status = papiAttributeListGetValue(list, iter, name, - PAPI_RESOLUTION, &value); - if (status == PAPI_OK) { - *x = value->resolution.xres; - *y = value->resolution.yres; - *units = value->resolution.units; - } - - return (status); -} - -papi_status_t -papiAttributeListGetDatetime(papi_attribute_t **list, void **iter, - char *name, time_t *dt) -{ - papi_status_t status; - papi_attribute_value_t *value = NULL; - - if (dt == NULL) - return (PAPI_BAD_ARGUMENT); - - status = papiAttributeListGetValue(list, iter, name, - PAPI_DATETIME, &value); - if (status == PAPI_OK) { - *dt = value->datetime; - } - - return (status); -} - -papi_status_t -papiAttributeListGetCollection(papi_attribute_t **list, void **iter, - char *name, papi_attribute_t ***collection) -{ - papi_status_t status; - papi_attribute_value_t *value = NULL; - - if (collection == NULL) - return (PAPI_BAD_ARGUMENT); - - status = papiAttributeListGetValue(list, iter, name, - PAPI_COLLECTION, &value); - if (status == PAPI_OK) { - *collection = value->collection; - } - - return (status); -} - -papi_status_t -papiAttributeListGetMetadata(papi_attribute_t **list, void **iter, - char *name, papi_metadata_t *vptr) -{ - papi_status_t status; - papi_attribute_value_t *value = NULL; - - if (vptr == NULL) - return (PAPI_BAD_ARGUMENT); - - status = papiAttributeListGetValue(list, iter, name, - PAPI_METADATA, &value); - if (status == PAPI_OK) - *vptr = value->metadata; - - return (status); -} - - -/* The string is modified by this call */ -static char * -regvalue(regmatch_t match, char *string) -{ - char *result = NULL; - if (match.rm_so != match.rm_eo) { - result = string + match.rm_so; - *(result + (match.rm_eo - match.rm_so)) = '\0'; - } - return (result); -} - -static papi_attribute_value_type_t -_process_value(char *string, char ***parts) -{ - int i; - static struct { - papi_attribute_value_type_t type; - size_t vals; - char *expression; - int compiled; - regex_t re; - } types[] = { - { PAPI_BOOLEAN, 1, "^(true|false|yes|no)$", 0 }, - { PAPI_COLLECTION, 1, "^\\{(.+)\\}$", 0 }, - /* PAPI_DATETIME is unsupported, too much like an integer */ - { PAPI_INTEGER, 1, "^([+-]{0,1}[[:digit:]]+)$", 0 }, - { PAPI_RANGE, 3, "^([[:digit:]]*)-([[:digit:]]*)$", 0 }, - { PAPI_RESOLUTION, 4, "^([[:digit:]]+)x([[:digit:]]+)dp(i|c)$", - 0 }, - NULL - }; - regmatch_t matches[4]; - - for (i = 0; i < 5; i++) { - int j; - - if (types[i].compiled == 0) { - (void) regcomp(&(types[i].re), types[i].expression, - REG_EXTENDED|REG_ICASE); - types[i].compiled = 1; - } - if (regexec(&(types[i].re), string, (size_t)types[i].vals, - matches, 0) == REG_NOMATCH) - continue; - - for (j = 0 ; j < types[i].vals; j++) - list_append(parts, regvalue(matches[j], string)); - return (types[i].type); - } - - list_append(parts, string); - return (PAPI_STRING); -} - -static void -_add_attribute_value(papi_attribute_value_t ***list, - papi_attribute_value_type_t type, - papi_attribute_value_type_t dtype, char **parts) -{ - papi_attribute_value_t *value = calloc(1, sizeof (*value)); - - switch(type) { - case PAPI_STRING: - value->string = strdup(parts[0]); - list_append(list, value); - break; - case PAPI_BOOLEAN: - value->boolean = PAPI_TRUE; - if ((strcasecmp(parts[0], "false") == 0) || - (strcasecmp(parts[0], "no") == 0)) - value->boolean = PAPI_FALSE; - list_append(list, value); - break; - case PAPI_INTEGER: - value->integer = atoi(parts[0]); - list_append(list, value); - break; - case PAPI_RANGE: - if (dtype == PAPI_INTEGER) { - if (atoi(parts[0]) < 0) { - /* - * Handles -P -x case - * which prints from page number 1 - * till page number x - */ - value->range.lower = 1; - value->range.upper = 0 - (atoi(parts[0])); - } else { - value->range.lower = value->range.upper - = atoi(parts[0]); - } - } else if (dtype == PAPI_RANGE) { - if (parts[2] == NULL) { - value->range.lower = atoi(parts[1]); - /* - * Imposing an artificial limit on - * the upper bound for page range. - */ - value->range.upper = MAX_PAGES; - } else if ((parts[1] != NULL) && (parts[2] != NULL)) { - value->range.lower = atoi(parts[1]); - value->range.upper = atoi(parts[2]); - } - } - list_append(list, value); - break; - case PAPI_RESOLUTION: - value->resolution.xres = atoi(parts[1]); - value->resolution.yres = atoi(parts[2]); - if (parts[3][0] == 'i') - value->resolution.units = PAPI_RES_PER_INCH; - else - value->resolution.units = PAPI_RES_PER_CM; - list_append(list, value); - break; - case PAPI_COLLECTION: - papiAttributeListFromString(&(value->collection), 0, parts[0]); - list_append(list, value); - break; - } -} - -static papi_status_t -_papiAttributeFromStrings(papi_attribute_t ***list, int flags, - char *key, char **values) -{ - int i; - papi_status_t result = PAPI_OK; - papi_attribute_t *attr = calloc(1, sizeof (*attr)); - - /* these are specified in the papi spec as ranges */ - char *ranges[] = { "copies-supported", "job-impressions-supported", - "job-k-octets-supported", - "job-media-sheets-supported", "page-ranges", - NULL }; - - if ((attr == NULL) || ((attr->name = strdup(key)) == NULL)) - return (PAPI_TEMPORARY_ERROR); - - attr->type = PAPI_METADATA; - /* these are known ranges */ - for (i = 0; ranges[i] != NULL; i++) - if (strcasecmp(attr->name, ranges[i]) == 0) { - attr->type = PAPI_RANGE; - break; - } - - if (values != NULL) { - papi_attribute_value_t **vals = NULL; - - for (i = 0; values[i] != NULL; i++) { - papi_attribute_value_type_t dtype; - char **parts = NULL; - - dtype = _process_value(values[i], &parts); - if (attr->type == PAPI_METADATA) - attr->type = dtype; - _add_attribute_value(&vals, attr->type, dtype, parts); - free(parts); - } - attr->values = vals; - } - - list_append(list, attr); - - return (result); -} - -static papi_status_t -_parse_attribute_list(papi_attribute_t ***list, int flags, char *string) -{ - papi_status_t result = PAPI_OK; - char *ptr; - - if ((list == NULL) || (string == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((ptr = strdup(string)) == NULL) - return (PAPI_TEMPORARY_ERROR); - - while ((*ptr != '\0') && (result == PAPI_OK)) { - char *key, **values = NULL; - - /* strip any leading whitespace */ - while (isspace(*ptr) != 0) - ptr++; - - /* Get the name: name[=value] */ - key = ptr; - while ((*ptr != '\0') && (*ptr != '=') && (isspace(*ptr) == 0)) - ptr++; - - if (*ptr == '=') { - *ptr++ = '\0'; - - while ((*ptr != '\0') && (isspace(*ptr) == 0)) { - char *value = ptr; - - if ((*ptr == '\'') || (*ptr == '"')) { - char q = *ptr++; - - /* quoted string value */ - while ((*ptr != '\0') && (*ptr != q)) - ptr++; - if (*ptr == q) - ptr++; - } else if (*ptr == '{') { - /* collection */ - while ((*ptr != '\0') && (*ptr != '}')) - ptr++; - if (*ptr == '}') - ptr++; - } else { - /* value */ - while ((*ptr != '\0') && - (*ptr != ',') && - (isspace(*ptr) == 0)) - ptr++; - } - if (*ptr == ',') - *ptr++ = '\0'; - list_append(&values, value); - } - } else { /* boolean "[no]key" */ - char *value = "true"; - - if (strncasecmp(key, "no", 2) == 0) { - key += 2; - value = "false"; - } - list_append(&values, value); - } - if (*ptr != '\0') - *ptr++ = '\0'; - - result = _papiAttributeFromStrings(list, flags, key, values); - free(values); - } - - return (result); -} - -papi_status_t -papiAttributeListFromString(papi_attribute_t ***attrs, - int flags, char *string) -{ - papi_status_t result = PAPI_OK; - - if ((attrs != NULL) && (string != NULL) && - ((flags & ~(PAPI_ATTR_APPEND+PAPI_ATTR_REPLACE+PAPI_ATTR_EXCL)) - == 0)) { - result = _parse_attribute_list(attrs, flags, string); - } else { - result = PAPI_BAD_ARGUMENT; - } - - return (result); -} - -static papi_status_t -papiAttributeToString(papi_attribute_t *attribute, char *delim, - char *buffer, size_t buflen) -{ - papi_attribute_value_t **values = attribute->values; - int rc, i; - - if ((attribute->type == PAPI_BOOLEAN) && (values[1] == NULL)) { - if (values[0]->boolean == PAPI_FALSE) { - if (isupper(attribute->name[0]) == 0) - strlcat(buffer, "no", buflen); - else - strlcat(buffer, "No", buflen); - } - rc = strlcat(buffer, attribute->name, buflen); - } else { - strlcat(buffer, attribute->name, buflen); - rc = strlcat(buffer, "=", buflen); - } - - if (values == NULL) - return (PAPI_OK); - - for (i = 0; values[i] != NULL; i++) { - switch (attribute->type) { - case PAPI_STRING: - rc = strlcat(buffer, values[i]->string, buflen); - break; - case PAPI_INTEGER: { - char string[24]; - - snprintf(string, sizeof (string), "%d", - values[i]->integer); - rc = strlcat(buffer, string, buflen); - } - break; - case PAPI_BOOLEAN: - if (values[1] != NULL) - rc = strlcat(buffer, (values[i]->boolean ? - "true" : "false"), buflen); - break; - case PAPI_RANGE: { - char string[24]; - - if (values[i]->range.lower == values[i]->range.upper) - snprintf(string, sizeof (string), "%d", - values[i]->range.lower); - else - snprintf(string, sizeof (string), "%d-%d", - values[i]->range.lower, - values[i]->range.upper); - rc = strlcat(buffer, string, buflen); - } - break; - case PAPI_RESOLUTION: { - char string[24]; - - snprintf(string, sizeof (string), "%dx%ddp%c", - values[i]->resolution.xres, - values[i]->resolution.yres, - (values[i]->resolution.units == PAPI_RES_PER_CM - ? 'c' : 'i')); - rc = strlcat(buffer, string, buflen); - } - break; - case PAPI_DATETIME: { - struct tm *tm = localtime(&values[i]->datetime); - - if (tm != NULL) { - char string[64]; - - strftime(string, sizeof (string), "%C", tm); - rc = strlcat(buffer, string, buflen); - }} - break; - case PAPI_COLLECTION: { - char *string = alloca(buflen); - - papiAttributeListToString(values[i]->collection, - delim, string, buflen); - rc = strlcat(buffer, string, buflen); - } - break; - default: { - char string[32]; - - snprintf(string, sizeof (string), "unknown-type-0x%x", - attribute->type); - rc = strlcat(buffer, string, buflen); - } - } - if (values[i+1] != NULL) - rc = strlcat(buffer, ",", buflen); - - if (rc >= buflen) - return (PAPI_NOT_POSSIBLE); - - } - - return (PAPI_OK); -} - -papi_status_t -papiAttributeListToString(papi_attribute_t **attrs, - char *delim, char *buffer, size_t buflen) -{ - papi_status_t status = PAPI_OK; - int i; - - if ((attrs == NULL) || (buffer == NULL)) - return (PAPI_BAD_ARGUMENT); - - buffer[0] = '\0'; - if (!delim) - delim = " "; - - for (i = 0; ((attrs[i] != NULL) && (status == PAPI_OK)); i++) { - status = papiAttributeToString(attrs[i], delim, buffer, buflen); - if (attrs[i+1] != NULL) - strlcat(buffer, delim, buflen); - } - - return (status); -} - -static int -is_in_list(char *value, char **list) -{ - if ((list != NULL) && (value != NULL)) { - int i; - - for (i = 0; list[i] != NULL; i++) - if (strcasecmp(value, list[i]) == 0) - return (0); - } - - return (1); -} - -static papi_status_t -copy_attribute(papi_attribute_t ***list, papi_attribute_t *attribute) -{ - papi_status_t status; - int i = 0; - - if ((list == NULL) || (attribute == NULL) || - (attribute->values == NULL)) - return (PAPI_BAD_ARGUMENT); - - for (status = papiAttributeListAddValue(list, PAPI_ATTR_EXCL, - attribute->name, attribute->type, - attribute->values[i]); - ((status == PAPI_OK) && (attribute->values[i] != NULL)); - status = papiAttributeListAddValue(list, PAPI_ATTR_APPEND, - attribute->name, attribute->type, - attribute->values[i])) - i++; - - return (status); -} - -void -copy_attributes(papi_attribute_t ***result, papi_attribute_t **attributes) -{ - int i; - - if ((result == NULL) || (attributes == NULL)) - return; - - for (i = 0; attributes[i] != NULL; i++) - copy_attribute(result, attributes[i]); -} - -void -split_and_copy_attributes(char **list, papi_attribute_t **attributes, - papi_attribute_t ***in, papi_attribute_t ***out) -{ - int i; - - if ((list == NULL) || (attributes == NULL)) - return; - - for (i = 0; attributes[i] != NULL; i++) - if (is_in_list(attributes[i]->name, list) == 0) - copy_attribute(in, attributes[i]); - else - copy_attribute(out, attributes[i]); -} - -void -papiAttributeListPrint(FILE *fp, papi_attribute_t **attributes, - char *prefix_fmt, ...) -{ - char *prefix = NULL; - char *buffer = NULL; - char *newfmt = NULL; - void *mem; - ssize_t size = 0; - va_list ap; - - newfmt = malloc(strlen(prefix_fmt) + 2); - sprintf(newfmt, "\n%s", prefix_fmt); - - va_start(ap, prefix_fmt); - while (vsnprintf(prefix, size, newfmt, ap) > size) { - size += 1024; - mem = realloc(prefix, size); - if (!mem) goto error; - prefix = mem; - } - va_end(ap); - - if (attributes) { - size = 0; - while (papiAttributeListToString(attributes, prefix, buffer, - size) != PAPI_OK) { - size += 1024; - mem = realloc(buffer, size); - if (!mem) goto error; - buffer = mem; - } - } - - fprintf(fp, "%s%s\n", prefix, buffer ? buffer : ""); - fflush(fp); - - error: - free(newfmt); - free(prefix); - free(buffer); -} diff --git a/usr/src/lib/print/libpapi-common/common/common.c b/usr/src/lib/print/libpapi-common/common/common.c deleted file mode 100644 index c14515417b..0000000000 --- a/usr/src/lib/print/libpapi-common/common/common.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: common.c 151 2006-04-25 16:55:34Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Shared "unsupported" function implementations that can be overridden - * by libpapi and the various print service modules (psms). - */ - -#include <stdlib.h> -#include <papi.h> - -static papi_status_t -_unsupported() -{ - return (PAPI_OPERATION_NOT_SUPPORTED); -} - -static void * -_unsupported_null_return() -{ - return (NULL); -} - -static void -_unsupported_no_return() -{ -} - -/* - * Service interfaces - */ -#pragma weak papiServiceCreate = _unsupported -#pragma weak papiServiceDestroy = _unsupported_no_return -#pragma weak papiServiceSetPeer = _unsupported -#pragma weak papiServiceSetUserName = _unsupported -#pragma weak papiServiceSetPassword = _unsupported -#pragma weak papiServiceSetEncryption = _unsupported -#pragma weak papiServiceSetAuthCB = _unsupported -#pragma weak papiServiceSetAppData = _unsupported - -#pragma weak papiServiceGetServiceName = _unsupported_null_return -#pragma weak papiServiceGetUserName = _unsupported_null_return -#pragma weak papiServiceGetPassword = _unsupported_null_return -#pragma weak papiServiceGetAppData = _unsupported_null_return - -papi_encryption_t -papiServiceGetEncryption(papi_service_t handle) -{ - return (PAPI_ENCRYPT_NEVER); -} - -#pragma weak papiServiceGetAttributeList = _unsupported_null_return -#pragma weak papiServiceGetStatusMessage = _unsupported_null_return - -/* - * Printer operations - */ -#pragma weak papiPrintersList = _unsupported -#pragma weak papiPrinterQuery = _unsupported -#pragma weak papiPrinterEnable = _unsupported -#pragma weak papiPrinterDisable = _unsupported -#pragma weak papiPrinterPause = _unsupported -#pragma weak papiPrinterResume = _unsupported -#pragma weak papiPrinterAdd = _unsupported -#pragma weak papiPrinterModify = _unsupported -#pragma weak papiPrinterRemove = _unsupported -#pragma weak papiPrinterPurgeJobs = _unsupported -#pragma weak papiPrinterListJobs = _unsupported -#pragma weak papiPrinterGetAttributeList = _unsupported_null_return -#pragma weak papiPrinterFree = _unsupported_no_return -#pragma weak papiPrinterListFree = _unsupported_no_return - -/* - * Job interfaces - */ -#pragma weak papiJobHold = _unsupported -#pragma weak papiJobRelease = _unsupported -#pragma weak papiJobRestart = _unsupported -#pragma weak papiJobPromote = _unsupported -#pragma weak papiJobModify = _unsupported -#pragma weak papiJobSubmit = _unsupported -#pragma weak papiJobSubmitByReference = _unsupported -#pragma weak papiJobValidate = _unsupported -#pragma weak papiJobStreamOpen = _unsupported -#pragma weak papiJobStreamWrite = _unsupported -#pragma weak papiJobStreamClose = _unsupported -#pragma weak papiJobQuery = _unsupported -#pragma weak papiJobMove = _unsupported -#pragma weak papiJobCancel = _unsupported -#pragma weak papiJobGetAttributeList = _unsupported_null_return -#pragma weak papiJobGetPrinterName = _unsupported_null_return -#pragma weak papiJobCreate = _unsupported -#pragma weak papiJobStreamAdd = _unsupported -#pragma weak papiJobCommit = _unsupported - -int -papiJobGetId(papi_job_t job) -{ - return (-1); -} - -#pragma weak papiJobGetJobTicket = _unsupported_null_return -#pragma weak papiJobFree = _unsupported_no_return -#pragma weak papiJobListFree = _unsupported_no_return - -/* private functions */ -#pragma weak getprinterbyname = _unsupported_null_return diff --git a/usr/src/lib/print/libpapi-common/common/config-site.h b/usr/src/lib/print/libpapi-common/common/config-site.h deleted file mode 100644 index 2007f4f669..0000000000 --- a/usr/src/lib/print/libpapi-common/common/config-site.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -#ifndef _CONFIG_SITE_H -#define _CONFIG_SITE_H - -/* $Id: config-site.h.in 171 2006-05-20 06:00:32Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <config.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* the "default" destination for various commands and libraries */ -#define DEFAULT_DEST "_default" - -/* the "default" server uri to fallback to */ -#define DEFAULT_SERVICE_URI "lpsched://localhost/printers" - -/* the "default" IPP service to fallback to in the IPP psm */ -#define DEFAULT_IPP_SERVICE_URI "ipp://localhost/printers" - -/* the name of the SUID lpd-port binary that hands psm-lpd a connected socket */ -#define SUID_LPD_PORT "/usr/lib/print/lpd-port" - -/* enable/disable printer-uri in enumeration results */ -#define NEED_BROKEN_PRINTER_URI_SEMANTIC - -#ifdef __cplusplus -} -#endif - -#endif /* _CONFIG_SITE_H */ diff --git a/usr/src/lib/print/libpapi-common/common/config.h b/usr/src/lib/print/libpapi-common/common/config.h deleted file mode 100644 index 280ac6d6b4..0000000000 --- a/usr/src/lib/print/libpapi-common/common/config.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -#ifndef _CONFIG_H -#define _CONFIG_H - -/* source/libpapi-common/config.h. Generated by configure. */ -/* source/libpapi-common/config.h.in. Generated from configure.in by autoheader. */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Define to 1 if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the `dlopen' function. */ -#define HAVE_DLOPEN 1 - -/* Define to 1 if you have the `dlsym' function. */ -#define HAVE_DLSYM 1 - -/* Define to 1 if you have the `fprintf' function. */ -#define HAVE_FPRINTF 1 - -/* define if you have getipnodbyname */ -#define HAVE_GETIPNODEBYNAME 1 - -/* Define to 1 if you have the `getpassphrase' function. */ -#define HAVE_GETPASSPHRASE 1 - -/* Define to 1 if you have the `gettext' function. */ -#define HAVE_GETTEXT 1 - -/* Define to 1 if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `is_system_labeled' function. */ -#define HAVE_IS_SYSTEM_LABELED 1 - -/* Define to 1 if you have the `localtime' function. */ -#define HAVE_LOCALTIME 1 - -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the <priv.h> header file. */ -#define HAVE_PRIV_H 1 - -/* define if you have rresvport_af */ -#define HAVE_RRESVPORT_AF 1 - -/* Define to 1 if you have the <ruby.h> header file. */ -/* #undef HAVE_RUBY_H */ - -/* Define to 1 if you have the `snprintf' function. */ -#define HAVE_SNPRINTF 1 - -/* Define to 1 if you have the <stdarg.h> header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if you have the <stdint.h> header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strcmp' function. */ -#define HAVE_STRCMP 1 - -/* Define to 1 if you have the `strdup' function. */ -#define HAVE_STRDUP 1 - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the `strftime' function. */ -#define HAVE_STRFTIME 1 - -/* Define to 1 if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the `strlcat' function. */ -#define HAVE_STRLCAT 1 - -/* Define to 1 if you have the `strlcpy' function. */ -#define HAVE_STRLCPY 1 - -/* Define to 1 if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define HAVE_UNISTD_H 1 - -/* Name of package */ -#define PACKAGE "papi" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "1.0_rc1" - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - - -#ifdef __cplusplus -} -#endif - -#endif /* _CONFIG_H */ diff --git a/usr/src/lib/print/libpapi-common/common/library.c b/usr/src/lib/print/libpapi-common/common/library.c deleted file mode 100644 index 12b1ffb449..0000000000 --- a/usr/src/lib/print/libpapi-common/common/library.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: library.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <alloca.h> -#include <libintl.h> -#include <papi.h> - -static char *calls[] = { - /* Attribute Calls */ - "papiAttributeListAddValue", - "papiAttributeListAddBoolean", "papiAttributeListAddCollection", - "papiAttributeListAddDatetime", "papiAttributeListAddInteger", - "papiAttributeListAddMetadata", "papiAttributeListAddRange", - "papiAttributeListAddResolution", "papiAttributeListAddString", - "papiAttributeListDelete", - "papiAttributeListGetValue", "papiAttributeListGetNext", - "papiAttributeListFind", - "papiAttributeListGetBoolean", "papiAttributeListGetCollection", - "papiAttributeListGetDatetime", "papiAttributeListGetInteger", - "papiAttributeListGetMetadata", "papiAttributeListGetRange", - "papiAttributeListGetResolution", "papiAttributeListGetString", - "papiAttributeListFromString", "papiAttributeListToString", - "papiAttributeListFree", - /* Job Calls */ - "papiJobSubmit", "papiJobSubmitByReference", "papiJobValidate", - "papiJobStreamOpen", "papiJobStreamWrite", "papiJobStreamClose", - "papiJobQuery", "papiJobModify", "papiJobCancel", "papiJobPromote", - "papiJobGetAttributeList", "papiJobGetId", "papiJobGetPrinterName", - "papiJobGetJobTicket", - "papiJobFree", "papiJobListFree", - "papiJobHold", "papiJobRelease", "papiJobRestart", - /* Printer Calls */ - "papiPrintersList", "papiPrinterQuery", "papiPrinterModify", - "papiPrinterAdd", "papiPrinterRemove", - "papiPrinterPause", "papiPrinterResume", - "papiPrinterDisable", "papiPrinterEnable", - "papiPrinterPurgeJobs", "papiPrinterListJobs", - "papiPrinterGetAttributeList", - "papiPrinterFree", "papiPrinterListFree", - /* Service Calls */ - "papiServiceCreate", "papiServiceDestroy", - "papiServiceGetAppData", - "papiServiceGetEncryption", "papiServiceGetPassword", - "papiServiceGetServiceName", "papiServiceGetUserName", - "papiServiceSetAppData", "papiServiceSetAuthCB", - "papiServiceSetEncryption", "papiServiceSetPassword", - "papiServiceSetUserName", - "papiServiceGetAttributeList", "papiServiceGetStatusMessage", - /* Misc Calls */ - "papiStatusString", - "papiLibrarySupportedCall", "papiLibrarySupportedCalls", - NULL -}; - -char ** -papiLibrarySupportedCalls() -{ - return (calls); -} - -char -papiLibrarySupportedCall(const char *name) -{ - int i; - - for (i = 0; calls[i] != NULL; i++) - if (strcmp(name, calls[i]) == 0) - return (PAPI_TRUE); - - return (PAPI_FALSE); -} diff --git a/usr/src/lib/print/libpapi-common/common/list.c b/usr/src/lib/print/libpapi-common/common/list.c deleted file mode 100644 index b2560c5059..0000000000 --- a/usr/src/lib/print/libpapi-common/common/list.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: list.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdlib.h> -#include <stdarg.h> -#include <errno.h> - -static int __list_increment = 16; - -#define LIST_SIZE(x) ((((x) / __list_increment) + 1) * __list_increment) - -int -list_append(void ***list, void *item) -{ - int count; - - if ((list == NULL) || (item == NULL)) { - errno = EINVAL; - return (-1); - } - - if (item != NULL) { - if (*list == NULL) - *list = (void **)calloc(__list_increment, - sizeof (void *)); - - for (count = 0; (*list)[count] != NULL; count++) - ; - - if ((count + 1) % __list_increment == 0) { /* expand the list */ - void **new_list = NULL; - int new_size = LIST_SIZE(count + 1); - - new_list = (void **)calloc(new_size, sizeof (void *)); - if (new_list == NULL) - return (-1); - - for (count = 0; (*list)[count] != NULL; count++) - new_list[count] = (*list)[count]; - free(*list); - *list = new_list; - } - - (*list)[count] = item; - } - - return (0); -} - -/* - * list_concatenate() takes in two NULL terminated lists of items (type **) - * and creates a new list with items from list2 appended on the end of - * the list of items from list1. The result is a list (type **). If - * there is a failure, -1 is returned. - */ -int -list_concatenate(void ***result, void **list2) -{ - void **list1; - int size1 = 0; - int size2 = 0; - int new_size = 0; - - if ((result == NULL) || ((*result == NULL) && (list2 == NULL))) { - errno = EINVAL; - return (-1); - } - - list1 = *result; - - if (list1 != NULL) - for (size1 = 0; list1[size1] != NULL; size1++) - ; - if (list2 != NULL) - for (size2 = 0; list2[size2] != NULL; size2++) - ; - - /* list1 + list2 padded to a multiple of _list_increment */ - new_size = LIST_SIZE(size1 + size2); - - if ((*result = (void **)calloc((new_size), sizeof (void *))) != NULL) { - int count = 0; - - if (list1 != NULL) - for (size1 = 0; list1[size1] != NULL; size1++) - (*result)[count++] = list1[size1]; - if (list2 != NULL) - for (size2 = 0; list2[size2] != NULL; size2++) - (*result)[count++] = list2[size2]; - free(list1); - } - - return (0); -} - -/* - * list_locate() iterates through the list passed in and uses the comparison - * routine and element passed in to find an element in the list. It - * returns the first element matched, or NULL if none exists - */ -void * -list_locate(void **list, int (*compare)(void *, void *), void *element) -{ - int current = 0; - - if ((list != NULL) && (element != NULL)) - for (current = 0; list[current] != NULL; current++) - if ((compare)(list[current], element) == 0) - return (list[current]); - return (NULL); -} - -void -list_remove(void ***list, void *item) -{ - int i = 0, count; - - if ((list == NULL) || (*list == NULL) || (item == NULL)) - return; - - /* size the original list */ - for (count = 0; (*list)[count] != NULL; count++) - if ((*list)[count] == item) { /* mark the location of item */ - i = count; - item = NULL; - } - - /* if found, remove it */ - if (item == NULL) { - /* shift the list over the item */ - for (++i; ((*list)[i] != NULL); i++) - (*list)[i-1] = (*list)[i]; - (*list)[i-1] = NULL; - } - - /* if found, removed, and list should shrink, shrink it */ - if ((item == NULL) && (LIST_SIZE(i) < LIST_SIZE(count))) { - void **tmp = (void **)calloc(LIST_SIZE(i), sizeof (void *)); - - if (tmp != NULL) { - for (i = 0; (*list)[i] != NULL; i++) - tmp[i] = (*list)[i]; - free(*list); - *list = tmp; - } - } -} diff --git a/usr/src/lib/print/libpapi-common/common/mapfile b/usr/src/lib/print/libpapi-common/common/mapfile deleted file mode 100644 index c1f9e3f1ab..0000000000 --- a/usr/src/lib/print/libpapi-common/common/mapfile +++ /dev/null @@ -1,168 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# $Id: mapfile.in,v 1.2 2006/03/02 06:31:36 njacobs Exp $ -# - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -$mapfile_version 2 - -# -# Common interfaces that are most likely to be shared amongst the various -# PAPI implementations. -# - -SYMBOL_VERSION SUNW_1.0 { - global: - # PAPI Attribute Calls - papiAttributeListAddValue; - papiAttributeListAddBoolean; - papiAttributeListAddCollection; - papiAttributeListAddDatetime; - papiAttributeListAddInteger; - papiAttributeListAddMetadata; - papiAttributeListAddRange; - papiAttributeListAddResolution; - papiAttributeListAddString; - papiAttributeListDelete; - papiAttributeListGetValue; - papiAttributeListGetNext; - papiAttributeListFind; - papiAttributeListGetBoolean; - papiAttributeListGetCollection; - papiAttributeListGetDatetime; - papiAttributeListGetInteger; - papiAttributeListGetMetadata; - papiAttributeListGetRange; - papiAttributeListGetResolution; - papiAttributeListGetString; - papiAttributeListFromString; - papiAttributeListToString; - papiAttributeListFree; - - # PAPI Service Calls - papiServiceCreate { FLAGS = NODYNSORT }; - papiServiceDestroy { FLAGS = NODYNSORT }; - papiServiceSetUserName { FLAGS = NODYNSORT }; - papiServiceSetPassword { FLAGS = NODYNSORT }; - papiServiceSetEncryption { FLAGS = NODYNSORT }; - papiServiceSetAuthCB { FLAGS = NODYNSORT }; - papiServiceSetAppData { FLAGS = NODYNSORT }; - papiServiceGetUserName { FLAGS = NODYNSORT }; - papiServiceGetPassword { FLAGS = NODYNSORT }; - papiServiceGetEncryption; - papiServiceGetAppData { FLAGS = NODYNSORT }; - papiServiceGetServiceName { FLAGS = NODYNSORT }; - papiServiceGetAttributeList { FLAGS = NODYNSORT }; - papiServiceGetStatusMessage { FLAGS = NODYNSORT }; - - # PAPI Printer Calls - papiPrintersList { FLAGS = NODYNSORT }; - papiPrinterQuery { FLAGS = NODYNSORT }; - papiPrinterAdd { FLAGS = NODYNSORT }; - papiPrinterModify { FLAGS = NODYNSORT }; - papiPrinterRemove { FLAGS = NODYNSORT }; - papiPrinterDisable { FLAGS = NODYNSORT }; - papiPrinterEnable { FLAGS = NODYNSORT }; - papiPrinterPause { FLAGS = NODYNSORT }; - papiPrinterResume { FLAGS = NODYNSORT }; - papiPrinterPurgeJobs { FLAGS = NODYNSORT }; - papiPrinterListJobs { FLAGS = NODYNSORT }; - papiPrinterGetAttributeList { FLAGS = NODYNSORT }; - papiPrinterFree { FLAGS = NODYNSORT }; - papiPrinterListFree { FLAGS = NODYNSORT }; - - # PAPI Job Calls - papiJobSubmit { FLAGS = NODYNSORT }; - papiJobSubmitByReference { FLAGS = NODYNSORT }; - papiJobValidate { FLAGS = NODYNSORT }; - papiJobStreamOpen { FLAGS = NODYNSORT }; - papiJobStreamWrite { FLAGS = NODYNSORT }; - papiJobStreamClose { FLAGS = NODYNSORT }; - papiJobQuery { FLAGS = NODYNSORT }; - papiJobModify { FLAGS = NODYNSORT }; - papiJobMove { FLAGS = NODYNSORT }; - papiJobCancel { FLAGS = NODYNSORT }; - papiJobHold { FLAGS = NODYNSORT }; - papiJobRelease { FLAGS = NODYNSORT }; - papiJobRestart { FLAGS = NODYNSORT }; - papiJobPromote { FLAGS = NODYNSORT }; - papiJobGetAttributeList { FLAGS = NODYNSORT }; - papiJobGetPrinterName { FLAGS = NODYNSORT }; - papiJobGetId; - papiJobGetJobTicket { FLAGS = NODYNSORT }; - papiJobFree { FLAGS = NODYNSORT }; - papiJobListFree { FLAGS = NODYNSORT }; - - # Misc. PAPI Calls - papiStatusString; - papiLibrarySupportedCall; - papiLibrarySupportedCalls; -}; - -SYMBOL_VERSION SUNWprivate_1.0 { # Misc. semi-private supporting calls - global: - papiServiceSetPeer { FLAGS = NODYNSORT }; - papiJobCreate { FLAGS = NODYNSORT }; - papiJobStreamAdd { FLAGS = NODYNSORT }; - papiJobCommit { FLAGS = NODYNSORT }; - - # URI - uri_from_string; - uri_to_string; - uri_free; - - # list - list_remove; - list_append; - list_concatenate; - - # NS - getprinterbyname { FLAGS = NODYNSORT }; - - # extra Attribute Calls - copy_attributes; - split_and_copy_attributes; - papiAttributeListPrint; - - is_localhost; - - local: - *; -}; diff --git a/usr/src/lib/print/libpapi-common/common/misc.c b/usr/src/lib/print/libpapi-common/common/misc.c deleted file mode 100644 index 2688fd0ec0..0000000000 --- a/usr/src/lib/print/libpapi-common/common/misc.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: misc.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <sys/types.h> -#include <papi.h> -#include <uri.h> -#include <config-site.h> - -/* - * The implementations of strlcpy() and strlcat() have been taken directly - * from OpenSolaris. The contents of this file originated from - * usr/src/lib/libc/port/gen/strlcpy.c - * usr/src/lib/libc/port/gen/strcat.c - */ - -#ifndef HAVE_STRLCPY -size_t -strlcpy(char *dst, const char *src, size_t len) -{ - size_t slen = strlen(src); - size_t copied; - - if (len == 0) - return (slen); - - if (slen >= len) - copied = len - 1; - else - copied = slen; - (void) memcpy(dst, src, copied); - dst[copied] = '\0'; - return (slen); -} -#endif - -#ifndef HAVE_STRLCAT -size_t -strlcat(char *dst, const char *src, size_t dstsize) -{ - char *df = dst; - size_t left = dstsize; - size_t l1; - size_t l2 = strlen(src); - size_t copied; - - while (left-- != 0 && *df != '\0') - df++; - l1 = df - dst; - if (dstsize == l1) - return (l1 + l2); - - copied = l1 + l2 >= dstsize ? dstsize - l1 - 1 : l2; - (void) memcpy(dst + l1, src, copied); - dst[l1+copied] = '\0'; - return (l1 + l2); -} -#endif - -#if defined(__sun) && defined(__SVR4) -#include <sys/systeminfo.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/sockio.h> -#include <net/if.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> - -static struct in6_addr ** -local_interfaces() -{ - struct in6_addr **result = NULL; - int s; - struct lifnum n; - struct lifconf c; - struct lifreq *r; - int count; - - /* we need a socket to get the interfaces */ - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - return (0); - - /* get the number of interfaces */ - memset(&n, 0, sizeof (n)); - n.lifn_family = AF_UNSPEC; - if (ioctl(s, SIOCGLIFNUM, (char *)&n) < 0) { - close(s); - return (0); /* no interfaces */ - } - - /* get the interface(s) configuration */ - memset(&c, 0, sizeof (c)); - c.lifc_family = AF_UNSPEC; - c.lifc_buf = calloc(n.lifn_count, sizeof (struct lifreq)); - c.lifc_len = (n.lifn_count * sizeof (struct lifreq)); - if (ioctl(s, SIOCGLIFCONF, (char *)&c) < 0) { - free(c.lifc_buf); - close(s); - return (0); /* can't get interface(s) configuration */ - } - close(s); - - r = c.lifc_req; - for (count = c.lifc_len / sizeof (struct lifreq); - count > 0; count--, r++) { - struct in6_addr v6[1], *addr = NULL; - - switch (r->lifr_addr.ss_family) { - case AF_INET: { - struct sockaddr_in *s = - (struct sockaddr_in *)&r->lifr_addr; - IN6_INADDR_TO_V4MAPPED(&s->sin_addr, v6); - addr = v6; - } - break; - case AF_INET6: { - struct sockaddr_in6 *s = - (struct sockaddr_in6 *)&r->lifr_addr; - addr = &s->sin6_addr; - } - break; - } - - if (addr != NULL) { - struct in6_addr *a = malloc(sizeof (*a)); - - memcpy(a, addr, sizeof (*a)); - list_append(&result, a); - } - } - free(c.lifc_buf); - - return (result); -} - -static int -match_interfaces(char *host) -{ - struct in6_addr **lif = local_interfaces(); - struct hostent *hp; - int rc = 0; - int errnum; - - /* are there any local interfaces */ - if (lif == NULL) - return (0); - - /* cycle through the host db addresses */ - hp = getipnodebyname(host, AF_INET6, AI_ALL|AI_V4MAPPED, &errnum); - if (hp != NULL) { - struct in6_addr **tmp = (struct in6_addr **)hp->h_addr_list; - int i; - - for (i = 0; ((rc == 0) && (tmp[i] != NULL)); i++) { - int j; - - for (j = 0; ((rc == 0) && (lif[j] != NULL)); j++) - if (memcmp(tmp[i], lif[j], - sizeof (struct in6_addr)) == 0) - rc = 1; - } - } - free(lif); - - return (rc); -} -#endif - -int -is_localhost(char *host) -{ - char hostname[BUFSIZ]; - - /* is it "localhost" */ - if (strncasecmp(host, "localhost", 10) == 0) - return (1); - - /* is it the {nodename} */ - sysinfo(SI_HOSTNAME, hostname, sizeof (hostname)); - if (strncasecmp(host, hostname, strlen(hostname)) == 0) - return (1); - -#if defined(__sun) && defined(__SVR4) - /* does it match one of the host's configured interfaces */ - if (match_interfaces(host) != 0) - return (1); -#endif - return (0); -} diff --git a/usr/src/lib/print/libpapi-common/common/papi.h b/usr/src/lib/print/libpapi-common/common/papi.h deleted file mode 100644 index 5fcaccc584..0000000000 --- a/usr/src/lib/print/libpapi-common/common/papi.h +++ /dev/null @@ -1,452 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -#ifndef _PAPI_H -#define _PAPI_H - -/* $Id: papi.h 161 2006-05-03 04:32:59Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <time.h> -#include <stdio.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Types - */ - -/* service related types */ -typedef void *papi_service_t; -typedef void *papi_printer_t; -typedef void *papi_job_t; -typedef void *papi_stream_t; - -typedef enum { - PAPI_ENCRYPT_IF_REQUESTED, /* Encrypt if requested (TLS upgrade) */ - PAPI_ENCRYPT_NEVER, /* Never encrypt */ - PAPI_ENCRYPT_REQUIRED, /* Encryption required (TLS upgrade) */ - PAPI_ENCRYPT_ALWAYS /* Always encrypt (SSL) */ -} papi_encryption_t; - -/* attribute related types */ -typedef enum { - PAPI_STRING, - PAPI_INTEGER, - PAPI_BOOLEAN, - PAPI_RANGE, - PAPI_RESOLUTION, - PAPI_DATETIME, - PAPI_COLLECTION, - PAPI_METADATA -} papi_attribute_value_type_t; - -typedef enum { - PAPI_RES_PER_INCH = 3, - PAPI_RES_PER_CM -} papi_resolution_unit_t; - -enum { /* for boolean values */ - PAPI_FALSE = 0, - PAPI_TRUE = 1 -}; - -typedef enum { - PAPI_UNSUPPORTED = 0x10, - PAPI_DEFAULT = 0x11, - PAPI_UNKNOWN, - PAPI_NO_VALUE, - PAPI_NOT_SETTABLE = 0x15, - PAPI_DELETE = 0x16 -} papi_metadata_t; - -#define PAPI_LIST_JOBS_OTHERS 0x0001 -#define PAPI_LIST_JOBS_COMPLETED 0x0002 -#define PAPI_LIST_JOBS_NOT_COMPLETED 0x0004 -#define PAPI_LIST_JOBS_ALL 0xFFFF - -typedef struct papi_attribute_s papi_attribute_t; - -typedef union { - char *string; /* PAPI_STRING value */ - int integer; /* PAPI_INTEGER value */ - char boolean; /* PAPI_BOOLEAN value */ - struct { /* PAPI_RANGE value */ - int lower; - int upper; - } range; - struct { /* PAPI_RESOLUTION value */ - int xres; - int yres; - papi_resolution_unit_t units; - } resolution; - time_t datetime; /* PAPI_DATETIME value */ - papi_attribute_t **collection; /* PAPI_COLLECTION value */ - papi_metadata_t metadata; /* PAPI_METADATA value */ -} papi_attribute_value_t; - -struct papi_attribute_s { - char *name; /* attribute name */ - papi_attribute_value_type_t type; /* type of values */ - papi_attribute_value_t **values; /* list of values */ -}; - -#define PAPI_ATTR_APPEND 0x0001 /* Add values to attr */ -#define PAPI_ATTR_REPLACE 0x0002 /* Delete existing values, then add */ -#define PAPI_ATTR_EXCL 0x0004 /* Fail if attr exists */ - -/* job related types */ -typedef enum { - PAPI_JT_FORMAT_JDF = 0, - PAPI_JT_FORMAT_PWG = 1 -} papi_jt_format_t; - -typedef struct { - papi_jt_format_t format; - char *ticket_data; - char *file_name; -} papi_job_ticket_t; - -/* status related types */ -typedef enum { - PAPI_OK = 0x0000, - PAPI_OK_SUBST, - PAPI_OK_CONFLICT, - PAPI_OK_IGNORED_SUBSCRIPTIONS, - PAPI_OK_IGNORED_NOTIFICATIONS, - PAPI_OK_TOO_MANY_EVENTS, - PAPI_OK_BUT_CANCEL_SUBSCRIPTION, - PAPI_REDIRECTION_OTHER_SITE = 0x0300, - PAPI_BAD_REQUEST = 0x0400, - PAPI_FORBIDDEN, - PAPI_NOT_AUTHENTICATED, - PAPI_NOT_AUTHORIZED, - PAPI_NOT_POSSIBLE, - PAPI_TIMEOUT, - PAPI_NOT_FOUND, - PAPI_GONE, - PAPI_REQUEST_ENTITY, - PAPI_REQUEST_VALUE, - PAPI_DOCUMENT_FORMAT, - PAPI_ATTRIBUTES, - PAPI_URI_SCHEME, - PAPI_CHARSET, - PAPI_CONFLICT, - PAPI_COMPRESSION_NOT_SUPPORTED, - PAPI_COMPRESSION_ERROR, - PAPI_DOCUMENT_FORMAT_ERROR, - PAPI_DOCUMENT_ACCESS_ERROR, - PAPI_ATTRIBUTES_NOT_SETTABLE, - PAPI_IGNORED_ALL_SUBSCRIPTIONS, - PAPI_TOO_MANY_SUBSCRIPTIONS, - PAPI_IGNORED_ALL_NOTIFICATIONS, - PAPI_PRINT_SUPPORT_FILE_NOT_FOUND, - PAPI_INTERNAL_ERROR = 0x0500, - PAPI_OPERATION_NOT_SUPPORTED, - PAPI_SERVICE_UNAVAILABLE, - PAPI_VERSION_NOT_SUPPORTED, - PAPI_DEVICE_ERROR, - PAPI_TEMPORARY_ERROR, - PAPI_NOT_ACCEPTING, - PAPI_PRINTER_BUSY, - PAPI_ERROR_JOB_CANCELLED, - PAPI_MULTIPLE_JOBS_NOT_SUPPORTED, - PAPI_PRINTER_IS_DEACTIVATED, - PAPI_BAD_ARGUMENT, - PAPI_JOB_TICKET_NOT_SUPPORTED -} papi_status_t; - -/* list filter related */ -typedef enum { - PAPI_FILTER_BITMASK = 0 -} papi_filter_type_t; - -typedef struct { - papi_filter_type_t type; - union { - struct { /* PAPI_FILTER_BITMASK */ - unsigned int mask; - unsigned int value; - } bitmask; - } filter; -} papi_filter_t; - -enum { - PAPI_PRINTER_LOCAL = 0x0000, /* Local destination */ - PAPI_PRINTER_CLASS = 0x0001, /* Printer class */ - PAPI_PRINTER_REMOTE = 0x0002, /* Remote destination */ - PAPI_PRINTER_BW = 0x0004, /* Can do B&W printing */ - PAPI_PRINTER_COLOR = 0x0008, /* Can do color printing */ - PAPI_PRINTER_DUPLEX = 0x0010, /* Can do duplex printing */ - PAPI_PRINTER_STAPLE = 0x0020, /* Can do stapling */ - PAPI_PRINTER_COPIES = 0x0040, /* Can do copies */ - PAPI_PRINTER_COLLATE = 0x0080, /* Can collate copies */ - PAPI_PRINTER_PUNCH = 0x0100, /* Can punch output */ - PAPI_PRINTER_COVER = 0x0200, /* Can cover output */ - PAPI_PRINTER_BIND = 0x0400, /* Can bind output */ - PAPI_PRINTER_SORT = 0x0800, /* Can sort output */ - PAPI_PRINTER_SMALL = 0x1000, /* Can do letter/legal/a4 */ - PAPI_PRINTER_MEDIUM = 0x2000, /* Can do tabloid/B/C/A3/A2 */ - PAPI_PRINTER_LARGE = 0x4000, /* Can do D/E/A1/A0 */ - PAPI_PRINTER_VARIABLE = 0x8000, /* Can do variable sizes */ - PAPI_PRINTER_IMPLICIT = 0x10000, /* implicit class */ - PAPI_PRINTER_DEFAULT = 0x20000, /* Default printer on network */ - PAPI_PRINTER_OPTIONS = 0xfffc /* ~ (CLASS | REMOTE | IMPLICIT) */ -}; - -/* - * Functions - */ - -/* Service related */ -extern papi_status_t papiServiceCreate(papi_service_t *handle, - char *service_name, char *user_name, - char *password, - int (*authCB)(papi_service_t svc, - void *app_data), - papi_encryption_t encryption, - void *app_data); -extern void papiServiceDestroy(papi_service_t handle); -extern papi_status_t papiServiceSetUserName(papi_service_t handle, - char *user_name); -extern papi_status_t papiServiceSetPassword(papi_service_t handle, - char *password); -extern papi_status_t papiServiceSetEncryption(papi_service_t handle, - papi_encryption_t encryption); -extern papi_status_t papiServiceSetAuthCB(papi_service_t handle, - int (*authCB)(papi_service_t s, - void *app_data)); -extern papi_status_t papiServiceSetAppData(papi_service_t handle, - void *app_data); -extern char *papiServiceGetServiceName(papi_service_t handle); -extern char *papiServiceGetUserName(papi_service_t handle); -extern char *papiServiceGetPassword(papi_service_t handle); -extern papi_encryption_t papiServiceGetEncryption(papi_service_t handle); -extern void *papiServiceGetAppData(papi_service_t handle); -extern papi_attribute_t **papiServiceGetAttributeList(papi_service_t handle); -extern char *papiServiceGetStatusMessage(papi_service_t handle); - -/* Attribute related */ -extern papi_status_t papiAttributeListAddValue(papi_attribute_t ***attrs, - int flags, char *name, - papi_attribute_value_type_t type, - papi_attribute_value_t *value); -extern papi_status_t papiAttributeListAddString(papi_attribute_t ***attrs, - int flags, char *name, char *string); -extern papi_status_t papiAttributeListAddInteger(papi_attribute_t ***attrs, - int flags, char *name, int integer); -extern papi_status_t papiAttributeListAddBoolean(papi_attribute_t ***attrs, - int flags, char *name, char boolean); -extern papi_status_t papiAttributeListAddRange(papi_attribute_t ***attrs, - int flags, char *name, - int lower, int upper); -extern papi_status_t papiAttributeListAddResolution(papi_attribute_t ***attrs, - int flags, char *name, - int xres, int yres, - papi_resolution_unit_t units); -extern papi_status_t papiAttributeListAddDatetime(papi_attribute_t ***attrs, - int flags, char *name, time_t datetime); -extern papi_status_t papiAttributeListAddCollection(papi_attribute_t ***attrs, - int flags, char *name, - papi_attribute_t **collection); -extern papi_status_t papiAttributeListAddMetadata(papi_attribute_t ***attrs, - int flags, char *name, - papi_metadata_t metadata); -extern papi_status_t papiAttributeListDelete(papi_attribute_t ***attributes, - char *name); -extern papi_status_t papiAttributeListGetValue(papi_attribute_t **list, - void **iterator, char *name, - papi_attribute_value_type_t type, - papi_attribute_value_t **value); -extern papi_status_t papiAttributeListGetString(papi_attribute_t **list, - void **iterator, char *name, - char **vptr); -extern papi_status_t papiAttributeListGetInteger(papi_attribute_t **list, - void **iterator, char *name, int *vptr); -extern papi_status_t papiAttributeListGetBoolean(papi_attribute_t **list, - void **iterator, char *name, - char *vptr); -extern papi_status_t papiAttributeListGetRange(papi_attribute_t **list, - void **iterator, char *name, - int *min, int *max); -extern papi_status_t papiAttributeListGetResolution(papi_attribute_t **list, - void **iterator, char *name, - int *x, int *y, - papi_resolution_unit_t *units); -extern papi_status_t papiAttributeListGetDatetime(papi_attribute_t **list, - void **iterator, char *name, - time_t *dt); -extern papi_status_t papiAttributeListGetCollection(papi_attribute_t **list, - void **iterator, char *name, - papi_attribute_t ***collection); -extern papi_status_t papiAttributeListGetMetadata(papi_attribute_t **list, - void **iterator, char *name, - papi_metadata_t *vptr); -extern papi_attribute_t *papiAttributeListFind(papi_attribute_t **list, - char *name); -extern papi_attribute_t *papiAttributeListGetNext(papi_attribute_t **list, - void **iterator); -extern void papiAttributeListFree(papi_attribute_t **attributes); - -extern papi_status_t papiAttributeListFromString(papi_attribute_t ***attrs, - int flags, char *string); -extern papi_status_t papiAttributeListToString(papi_attribute_t **attrs, - char *delim, - char *buffer, size_t buflen); -extern void papiAttributeListPrint(FILE *fp, papi_attribute_t **list, - char *prefix_fmt, ...); - -/* Printer related */ -extern papi_status_t papiPrintersList(papi_service_t handle, - char **requested_attrs, - papi_filter_t *filter, - papi_printer_t **printers); -extern papi_status_t papiPrinterQuery(papi_service_t handle, char *name, - char **requested_attrs, - papi_attribute_t **job_attributes, - papi_printer_t *printer); -extern papi_status_t papiPrinterAdd(papi_service_t handle, char *name, - papi_attribute_t **attributes, - papi_printer_t *printer); -extern papi_status_t papiPrinterModify(papi_service_t handle, char *name, - papi_attribute_t **attributes, - papi_printer_t *printer); -extern papi_status_t papiPrinterRemove(papi_service_t handle, char *name); -extern papi_status_t papiPrinterDisable(papi_service_t handle, char *name, - char *message); -extern papi_status_t papiPrinterEnable(papi_service_t handle, char *name); -extern papi_status_t papiPrinterPause(papi_service_t handle, char *name, - char *message); -extern papi_status_t papiPrinterResume(papi_service_t handle, char *name); -extern papi_status_t papiPrinterPurgeJobs(papi_service_t handle, - char *name, papi_job_t **jobs); -extern papi_status_t papiPrinterListJobs(papi_service_t handle, - char *name, char **requested_attrs, - int type_mask, int max_num_jobs, - papi_job_t **jobs); -extern papi_attribute_t **papiPrinterGetAttributeList(papi_printer_t printer); -extern void papiPrinterFree(papi_printer_t printer); -extern void papiPrinterListFree(papi_printer_t *printers); - -/* Job related */ -extern papi_status_t papiJobSubmit(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, - char **files, papi_job_t *job); -extern papi_status_t papiJobSubmitByReference(papi_service_t handle, - char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, - char **files, papi_job_t *job); -extern papi_status_t papiJobValidate(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, - char **files, papi_job_t *job); -extern papi_status_t papiJobStreamOpen(papi_service_t handle, - char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, - papi_stream_t *stream); -extern papi_status_t papiJobStreamWrite(papi_service_t handle, - papi_stream_t stream, - void *buffer, size_t buflen); -extern papi_status_t papiJobStreamClose(papi_service_t handle, - papi_stream_t stream, - papi_job_t *job); -extern papi_status_t papiJobQuery(papi_service_t handle, char *printer, - int32_t job_id, char **requested_attrs, - papi_job_t *job); -extern papi_status_t papiJobModify(papi_service_t handle, char *printer, - int32_t job_id, - papi_attribute_t **attributes, - papi_job_t *job); -extern papi_status_t papiJobMove(papi_service_t handle, char *printer, - int32_t job_id, char *destination); -extern papi_status_t papiJobCancel(papi_service_t handle, char *printer, - int32_t job_id); -extern papi_status_t papiJobHold(papi_service_t handle, char *printer, - int32_t job_id); -extern papi_status_t papiJobRelease(papi_service_t handle, char *printer, - int32_t job_id); -extern papi_status_t papiJobRestart(papi_service_t handle, char *printer, - int32_t job_id); -extern papi_status_t papiJobPromote(papi_service_t handle, char *printer, - int32_t job_id); -extern papi_attribute_t **papiJobGetAttributeList(papi_job_t printer); -extern char *papiJobGetPrinterName(papi_job_t printer); -extern int32_t papiJobGetId(papi_job_t printer); -extern papi_job_ticket_t *papiJobGetJobTicket(papi_job_t printer); -extern void papiJobFree(papi_job_t job); -extern void papiJobListFree(papi_job_t *jobs); - -#ifdef SOLARIS_PRIVATE_POST_0_9 -/* - * These have been added to support IPP create-job/send-document with PAPI v0.9 - * in an IPP listener using PAPI as it's spooler interface. A future version - * of the API is expected to support this type of functionality - */ -extern papi_status_t papiJobCreate(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, - papi_job_t *job); -extern papi_status_t papiJobStreamAdd(papi_service_t handle, char *printer, - int32_t id, papi_stream_t *stream); -extern papi_status_t papiJobCommit(papi_service_t handle, char *printer, - int32_t id); -extern papi_status_t papiServiceSetPeer(papi_service_t handle, int peerfd); -#endif /* SOLARIS_PRIVATE_POST_0_9 */ - -extern char *papiStatusString(papi_status_t status); - -/* - * Internal functions that aren't in the API, but are shared across - * protocol support implementations(psms) and the tightly bound - * listener library. Do not use these in your applications. - */ -extern void list_append(); -extern void list_concatenate(); -extern void list_remove(); -extern void copy_attributes(papi_attribute_t ***result, - papi_attribute_t **list); -extern void split_and_copy_attributes(char **list, - papi_attribute_t **attributes, - papi_attribute_t ***in, - papi_attribute_t ***out); - -extern papi_attribute_t **getprinterbyname(char *name, char *ns); - -extern int is_localhost(char *hostname); - -#ifdef __cplusplus -} -#endif - -#endif /* _PAPI_H */ diff --git a/usr/src/lib/print/libpapi-common/common/status.c b/usr/src/lib/print/libpapi-common/common/status.c deleted file mode 100644 index 897aa1322d..0000000000 --- a/usr/src/lib/print/libpapi-common/common/status.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: status.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdlib.h> -#include <papi.h> -#include <libintl.h> - -char * -papiStatusString(const papi_status_t status) -{ - switch (status) { - case PAPI_OK: - return (gettext("ok")); - case PAPI_OK_SUBST: - return (gettext("ok-substitution")); - case PAPI_OK_CONFLICT: - return (gettext("ok-conflict")); - case PAPI_OK_IGNORED_SUBSCRIPTIONS: - return (gettext("ok-ignored-subscriptions")); - case PAPI_OK_IGNORED_NOTIFICATIONS: - return (gettext("ok-ignored-notifications")); - case PAPI_OK_TOO_MANY_EVENTS: - return (gettext("ok-too-many-events")); - case PAPI_OK_BUT_CANCEL_SUBSCRIPTION: - return (gettext("ok-but-cancel-subscription")); - case PAPI_REDIRECTION_OTHER_SITE: - return (gettext("redirection-to-other-site")); - case PAPI_BAD_REQUEST: - return (gettext("bad-request")); - case PAPI_FORBIDDEN: - return (gettext("forbidden")); - case PAPI_NOT_AUTHENTICATED: - return (gettext("not-authenticated")); - case PAPI_NOT_AUTHORIZED: - return (gettext("not-authorized")); - case PAPI_NOT_POSSIBLE: - return (gettext("not-possible")); - case PAPI_TIMEOUT: - return (gettext("timeout")); - case PAPI_NOT_FOUND: - return (gettext("not-found")); - case PAPI_GONE: - return (gettext("gone")); - case PAPI_REQUEST_ENTITY: - return (gettext("request-entity")); - case PAPI_REQUEST_VALUE: - return (gettext("request-value")); - case PAPI_DOCUMENT_FORMAT: - return (gettext("document-format")); - case PAPI_ATTRIBUTES: - return (gettext("attributes")); - case PAPI_URI_SCHEME: - return (gettext("uri-scheme")); - case PAPI_CHARSET: - return (gettext("charset")); - case PAPI_CONFLICT: - return (gettext("conflict")); - case PAPI_COMPRESSION_NOT_SUPPORTED: - return (gettext("compression-not-supported")); - case PAPI_COMPRESSION_ERROR: - return (gettext("compression-error")); - case PAPI_DOCUMENT_FORMAT_ERROR: - return (gettext("document-format-error")); - case PAPI_DOCUMENT_ACCESS_ERROR: - return (gettext("document-access-error")); - case PAPI_ATTRIBUTES_NOT_SETTABLE: - return (gettext("attributes-not-settable")); - case PAPI_IGNORED_ALL_SUBSCRIPTIONS: - return (gettext("ignored-all-subscriptions")); - case PAPI_TOO_MANY_SUBSCRIPTIONS: - return (gettext("too-many-subscriptions")); - case PAPI_IGNORED_ALL_NOTIFICATIONS: - return (gettext("ignored-all-notifications")); - case PAPI_PRINT_SUPPORT_FILE_NOT_FOUND: - return (gettext("print-support-file-not-found")); - case PAPI_INTERNAL_ERROR: - return (gettext("internal-error")); - case PAPI_OPERATION_NOT_SUPPORTED: - return (gettext("operation-not-supported")); - case PAPI_SERVICE_UNAVAILABLE: - return (gettext("service-unavailable")); - case PAPI_VERSION_NOT_SUPPORTED: - return (gettext("version-not-supported")); - case PAPI_DEVICE_ERROR: - return (gettext("device-error")); - case PAPI_TEMPORARY_ERROR: - return (gettext("temporary-error")); - case PAPI_NOT_ACCEPTING: - return (gettext("not-accepting")); - case PAPI_PRINTER_BUSY: - return (gettext("printer-busy")); - case PAPI_ERROR_JOB_CANCELLED: - return (gettext("error-job-cancelled")); - case PAPI_MULTIPLE_JOBS_NOT_SUPPORTED: - return (gettext("multiple-jobs-not-supported")); - case PAPI_PRINTER_IS_DEACTIVATED: - return (gettext("printer-is-deactivated")); - case PAPI_BAD_ARGUMENT: - return (gettext("bad-argument")); - case PAPI_JOB_TICKET_NOT_SUPPORTED: - return (gettext("job-ticket-not-supported")); - default: - return (gettext("unknown-error")); - } -} diff --git a/usr/src/lib/print/libpapi-common/common/uri.c b/usr/src/lib/print/libpapi-common/common/uri.c deleted file mode 100644 index 31f6ce4eff..0000000000 --- a/usr/src/lib/print/libpapi-common/common/uri.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -/* $Id: uri.c 146 2006-03-24 00:26:54Z njacobs $ */ - -/*LINTLIBRARY*/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <sys/types.h> -#include <errno.h> -#include "uri.h" - -/* - * This will handle the following forms: - * scheme:scheme_data - * scheme://[[user[:password]@]host[:port]]/path[[#fragment]|[?query]] - */ -int -uri_from_string(char *string, uri_t **uri) -{ - char *ptr; - uri_t *u; - - if ((string == NULL) || (uri == NULL)) { - errno = EINVAL; - return (-1); - } - - /* find the scheme:scheme_part split */ - if ((ptr = strchr(string, ':')) == NULL) { - errno = EINVAL; - return (-1); - } - - if ((*uri = u = calloc(1, sizeof (*u))) == NULL) - return (-1); - - u->scheme = strndup(string, ptr - string); - - if ((ptr[1] == '/') && (ptr[2] == '/')) { - /* - * CSTYLED - * scheme://[host_part]/[path_part] - */ - char *end = NULL, *user = NULL, *host = NULL, *path = NULL; - - string = ptr + 3; /* skip the :// */ - - if ((path = end = strchr(string, '/')) == NULL) - for (end = string; *end != '\0'; end++) - continue; - - u->host_part = strndup(string, end - string); - - for (host = string; host < end; host ++) - if (*host == '@') { - /* string to host is the user part */ - u->user_part = strndup(string, host-string); - /* host+1 to end is the host part */ - u->host_part = strndup(host + 1, - end - (host+1)); - user = string; - host++; - break; - } - - if (user != NULL) { - char *password = NULL; - - for (password = user; (password < host - 1); password++) - if (*password == ':') { - u->password = strndup(password + 1, - host - password - 2); - break; - } - u->user = strndup(user, password - user); - } else - host = string; - - if (host != NULL) { - char *port = NULL; - - for (port = host; (port < path); port++) - if ((*port == ':') || (*port == '/')) - break; - - if (port < path) { - u->port = strndup(port + 1, path - port - 1); - } - - u->host = strndup(host, port - host); - } - - if (path != NULL) { - char *name = strrchr(path, '/'); - - u->path_part = strdup(path); - - if (name != NULL) { - char *query, *fragment; - - query = strrchr(name, '?'); - if ((query != NULL) && (*query != '\0')) { - u->query = strdup(query + 1); - end = query; - } else { - for (end = path; *end != '\0'; end++) - continue; - } - - fragment = strrchr(name, '#'); - if ((fragment != NULL) && (*fragment != '\0')) { - u->fragment = strndup(fragment + 1, - end - fragment - 1); - end = fragment; - } - - u->path = strndup(path, end - path); - } - } - } else { /* scheme:scheme_part */ - u->scheme_part = strdup(&ptr[1]); - } - - if ((u->host_part == NULL) && (u->path_part == NULL) && - (u->scheme_part == NULL)) { - errno = EINVAL; - uri_free(u); - *uri = NULL; - return (-1); - } - - return (0); -} - -int -uri_to_string(uri_t *uri, char *buffer, size_t buflen) -{ - char *uri_ppfix; - - if ((uri == NULL) || (buffer == NULL) || (buflen == 0) || - (uri->scheme == NULL) || - ((uri->password != NULL) && (uri->user == NULL)) || - ((uri->user != NULL) && (uri->host == NULL)) || - ((uri->port != NULL) && (uri->host == NULL)) || - ((uri->fragment != NULL) && (uri->path == NULL)) || - ((uri->query != NULL) && (uri->path == NULL))) { - errno = EINVAL; - return (-1); - } - if (uri->path == NULL || uri->path[0] == '/') - uri_ppfix = ""; - else - uri_ppfix = "/"; - - (void) memset(buffer, 0, buflen); - - if (uri->scheme_part == NULL) { - (void) snprintf(buffer, buflen, - "%s://%s%s%s%s%s%s%s%s%s%s%s%s%s", - uri->scheme, - (uri->user ? uri->user : ""), - (uri->password ? ":" : ""), - (uri->password ? uri->password : ""), - (uri->user ? "@": ""), - (uri->host ? uri->host : ""), - (uri->port ? ":" : ""), - (uri->port ? uri->port : ""), - uri_ppfix, - (uri->path ? uri->path : ""), - (uri->fragment ? "#" : ""), - (uri->fragment ? uri->fragment : ""), - (uri->query ? "?" : ""), - (uri->query ? uri->query : "")); - } else { - (void) snprintf(buffer, buflen, "%s:%s", uri->scheme, - uri->scheme_part); - } - - return (0); -} - -void -uri_free(uri_t *uri) -{ - if (uri != NULL) { - if (uri->scheme != NULL) - free(uri->scheme); - if (uri->scheme_part != NULL) - free(uri->scheme_part); - if (uri->user != NULL) - free(uri->user); - if (uri->password != NULL) - free(uri->password); - if (uri->host != NULL) - free(uri->host); - if (uri->port != NULL) - free(uri->port); - if (uri->path != NULL) - free(uri->path); - if (uri->fragment != NULL) - free(uri->fragment); - if (uri->query != NULL) - free(uri->query); - /* help me debug */ - if (uri->user_part != NULL) - free(uri->user_part); - if (uri->host_part != NULL) - free(uri->host_part); - if (uri->path_part != NULL) - free(uri->path_part); - free(uri); - } -} - -#ifdef DEADBEEF -static void -uri_dump(FILE *fp, uri_t *uri) -{ - if (uri != NULL) { - fprintf(fp, "URI:\n"); - if (uri->scheme != NULL) - fprintf(fp, "scheme: %s\n", uri->scheme); - if (uri->scheme_part != NULL) - fprintf(fp, "scheme_part: %s\n", uri->scheme_part); - if (uri->user != NULL) - fprintf(fp, "user: %s\n", uri->user); - if (uri->password != NULL) - fprintf(fp, "password: %s\n", uri->password); - if (uri->host != NULL) - fprintf(fp, "host: %s\n", uri->host); - if (uri->port != NULL) - fprintf(fp, "port: %s\n", uri->port); - if (uri->path != NULL) - fprintf(fp, "path: %s\n", uri->path); - if (uri->fragment != NULL) - fprintf(fp, "fragment: %s\n", uri->fragment); - if (uri->query != NULL) - fprintf(fp, "query: %s\n", uri->query); - /* help me debug */ - if (uri->user_part != NULL) - fprintf(fp, "user_part: %s\n", uri->user_part); - if (uri->host_part != NULL) - fprintf(fp, "host_part: %s\n", uri->host_part); - if (uri->path_part != NULL) - fprintf(fp, "path_part: %s\n", uri->path_part); - fflush(fp); - } -} - -int -main(int argc, char *argv[]) -{ - uri_t *u = NULL; - - if (argc != 2) { - fprintf(stderr, "Usage: %s uri\n", argv[0]); - exit(1); - } - - if (uri_from_string(argv[1], &u) == 0) { - char buf[BUFSIZ]; - - uri_dump(stdout, u); - uri_to_string(u, buf, sizeof (buf)); - fprintf(stdout, "reconstituted: %s\n", buf); - - uri_to_string(u, buf, 12); - fprintf(stdout, "reconstituted(12): %s\n", buf); - } else - printf(" failed for %s (%s)\n", argv[1], strerror(errno)); - - exit(0); -} -#endif /* DEADBEEF */ diff --git a/usr/src/lib/print/libpapi-common/i386/Makefile b/usr/src/lib/print/libpapi-common/i386/Makefile deleted file mode 100644 index 3b985583a4..0000000000 --- a/usr/src/lib/print/libpapi-common/i386/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBS) $(ROOTLINKS) # $(ROOTLINT) diff --git a/usr/src/lib/print/libpapi-common/sparc/Makefile b/usr/src/lib/print/libpapi-common/sparc/Makefile deleted file mode 100644 index 3b985583a4..0000000000 --- a/usr/src/lib/print/libpapi-common/sparc/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBS) $(ROOTLINKS) # $(ROOTLINT) diff --git a/usr/src/lib/print/libpapi-dynamic/Makefile.com b/usr/src/lib/print/libpapi-dynamic/Makefile.com deleted file mode 100644 index 8a51154c48..0000000000 --- a/usr/src/lib/print/libpapi-dynamic/Makefile.com +++ /dev/null @@ -1,57 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY = libpapi.a -VERS = .0 -OBJECTS = job.o nss.o printer.o psm.o service.o - -include ../../../Makefile.lib -include ../../../Makefile.rootfs - -SRCDIR = ../common - -ROOTLIBDIR= $(ROOT)/usr/lib - -LIBS = $(DYNLIB) - -$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) - -MAPFILES = $(SRCDIR)/mapfile - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRCDIR) -CPPFLAGS += -I../../libpapi-common/common -CPPFLAGS += -DNSS_SOLARIS -LDLIBS += -lc - -CERRWARN += -_gcc=-Wno-unused-variable - -.KEEP_STATE: - -all: $(LIBS) - -lint: lintcheck - -include ../../../Makefile.targ diff --git a/usr/src/lib/print/libpapi-dynamic/common/job.c b/usr/src/lib/print/libpapi-dynamic/common/job.c deleted file mode 100644 index e7bca751a0..0000000000 --- a/usr/src/lib/print/libpapi-dynamic/common/job.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: job.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdlib.h> -#include <papi_impl.h> - -void -papiJobFree(papi_job_t job) -{ - job_t *tmp = (job_t *)job; - - if (tmp != NULL) { - void (*f)(); - - f = (void (*)())psm_sym(tmp->svc, "papiJobFree"); - if (f != NULL) - f(tmp->job); - free(tmp); - } -} - -void -papiJobListFree(papi_job_t *jobs) -{ - if (jobs != NULL) { - int i; - - for (i = 0; jobs[i] != NULL; i++) - papiJobFree(jobs[i]); - free(jobs); - } -} - -papi_attribute_t ** -papiJobGetAttributeList(papi_job_t job) -{ - papi_attribute_t **result = NULL; - job_t *j = job; - - if (job != NULL) { - papi_attribute_t **(*f)(); - - f = (papi_attribute_t **(*)())psm_sym(j->svc, - "papiJobGetAttributeList"); - if (f != NULL) - result = f(j->job); - } - - return (result); -} - -char * -papiJobGetPrinterName(papi_job_t job) -{ - char *result = NULL; - job_t *j = job; - - if (job != NULL) { - char *(*f)(); - - f = (char *(*)())psm_sym(j->svc, "papiJobGetPrinterName"); - if (f != NULL) - result = f(j->job); - } - - return (result); -} - -int32_t -papiJobGetId(papi_job_t job) -{ - int32_t result = -1; - job_t *j = job; - - if (job != NULL) { - int32_t (*f)(); - - f = (int32_t (*)())psm_sym(j->svc, "papiJobGetId"); - if (f != NULL) - result = f(j->job); - } - - return (result); -} - -papi_job_ticket_t * -papiJobGetJobTicket(papi_job_t job) -{ - papi_job_ticket_t *result = NULL; - job_t *j = job; - - if (job != NULL) { - papi_job_ticket_t *(*f)(); - - f = (papi_job_ticket_t *(*)())psm_sym(j->svc, - "papiJobGetJobTicket"); - if (f != NULL) - result = f(j->job); - } - - return (result); -} - -/* common support for papiJob{Submit|SubmitByReference|Validate} */ -static papi_status_t -_papi_job_submit_reference_or_validate(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, char **files, papi_job_t *job, - char *function) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - job_t *j = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (printer == NULL) || (files == NULL) || - (job == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - if ((*job = j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - j->svc = svc; - f = (papi_status_t (*)())psm_sym(j->svc, function); - if (f != NULL) - result = f(svc->svc_handle, svc->name, job_attributes, - job_ticket, files, &j->job); - - return (result); -} - -papi_status_t -papiJobSubmit(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) -{ - return (_papi_job_submit_reference_or_validate(handle, printer, - job_attributes, job_ticket, files, job, - "papiJobSubmit")); -} - -papi_status_t -papiJobSubmitByReference(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) -{ - return (_papi_job_submit_reference_or_validate(handle, printer, - job_attributes, job_ticket, files, job, - "papiJobSubmitByReference")); -} - -papi_status_t -papiJobValidate(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) -{ - return (_papi_job_submit_reference_or_validate(handle, printer, - job_attributes, job_ticket, files, job, - "papiJobValidate")); -} - -papi_status_t -papiJobStreamOpen(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, papi_stream_t *stream) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_status_t (*f)(); - - if ((svc == NULL) || (printer == NULL) || (stream == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - f = (papi_status_t (*)())psm_sym(svc, "papiJobStreamOpen"); - if (f != NULL) - result = f(svc->svc_handle, svc->name, job_attributes, - job_ticket, stream); - - return (result); -} - -papi_status_t -papiJobStreamWrite(papi_service_t handle, - papi_stream_t stream, void *buffer, size_t buflen) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_status_t (*f)(); - - if ((svc == NULL) || (stream == NULL) || (buffer == NULL) || - (buflen == 0)) - return (PAPI_BAD_ARGUMENT); - - f = (papi_status_t (*)())psm_sym(svc, "papiJobStreamWrite"); - if (f != NULL) - result = f(svc->svc_handle, stream, buffer, buflen); - - return (result); -} - -papi_status_t -papiJobStreamClose(papi_service_t handle, papi_stream_t stream, papi_job_t *job) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - job_t *j = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (stream == NULL) || (job == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((*job = j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - j->svc = svc; - f = (papi_status_t (*)())psm_sym(j->svc, "papiJobStreamClose"); - if (f != NULL) - result = f(svc->svc_handle, stream, &j->job); - - return (result); -} - -papi_status_t -papiJobQuery(papi_service_t handle, char *printer, int32_t job_id, - char **requested_attrs, papi_job_t *job) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - job_t *j = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (printer == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - if ((*job = j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - j->svc = svc; - f = (papi_status_t (*)())psm_sym(j->svc, "papiJobQuery"); - if (f != NULL) - result = f(svc->svc_handle, svc->name, job_id, - requested_attrs, &j->job); - - return (result); -} - -papi_status_t -papiJobMove(papi_service_t handle, char *printer, int32_t job_id, - char *destination) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_status_t (*f)(); - - if ((svc == NULL) || (printer == NULL) || (job_id < 0)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - f = (papi_status_t (*)())psm_sym(svc, "papiJobMove"); - if (f != NULL) { - papi_attribute_t **attrs = getprinterbyname(destination, NULL); - - papiAttributeListGetString(attrs, NULL, - "printer-uri-supported", &destination); - result = f(svc->svc_handle, svc->name, job_id, destination); - papiAttributeListFree(attrs); - } - - return (result); -} - -/* common support for papiJob{Cancel|Release|Restart|Promote} */ -static papi_status_t -_papi_job_handle_printer_id(papi_service_t handle, - char *printer, int32_t job_id, char *function) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_status_t (*f)(); - - if ((svc == NULL) || (printer == NULL) || (job_id < 0)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - f = (papi_status_t (*)())psm_sym(svc, function); - if (f != NULL) - result = f(svc->svc_handle, svc->name, job_id); - - return (result); -} - -papi_status_t -papiJobCancel(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_papi_job_handle_printer_id(handle, printer, job_id, - "papiJobCancel")); -} - -papi_status_t -papiJobRelease(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_papi_job_handle_printer_id(handle, printer, job_id, - "papiJobRelease")); -} - -papi_status_t -papiJobRestart(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_papi_job_handle_printer_id(handle, printer, job_id, - "papiJobRestart")); -} - -papi_status_t -papiJobPromote(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_papi_job_handle_printer_id(handle, printer, job_id, - "papiJobPromote")); -} - -papi_status_t -papiJobCommit(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_papi_job_handle_printer_id(handle, printer, job_id, - "papiJobCommit")); -} - -papi_status_t -papiJobHold(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_papi_job_handle_printer_id(handle, printer, job_id, - "papiJobHold")); -} - -papi_status_t -papiJobModify(papi_service_t handle, char *printer, int32_t job_id, - papi_attribute_t **attributes, papi_job_t *job) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - job_t *j = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (printer == NULL) || (job_id < 0) || - (attributes == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - if ((*job = j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - j->svc = svc; - f = (papi_status_t (*)())psm_sym(j->svc, "papiJobModify"); - if (f != NULL) - result = f(svc->svc_handle, svc->name, job_id, attributes, - &j->job); - - return (result); -} - -/* - * The functions defined below are private to Solaris. They are here - * temporarily, until equivalent functionality makes it's way into the PAPI - * spec. This is expected in the next minor version after v1.0. - */ -papi_status_t -papiJobCreate(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, papi_job_t *job) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - job_t *j = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (printer == NULL) || (job == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - if ((*job = j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - j->svc = svc; - f = (papi_status_t (*)())psm_sym(j->svc, "papiJobCreate"); - if (f != NULL) - result = f(svc->svc_handle, svc->name, job_attributes, - job_ticket, &j->job); - - return (result); -} - -papi_status_t -papiJobStreamAdd(papi_service_t handle, char *printer, int32_t id, - papi_stream_t *stream) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_status_t (*f)(); - - if ((svc == NULL) || (printer == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - f = (papi_status_t (*)())psm_sym(svc, "papiJobStreamAdd"); - if (f != NULL) - result = f(svc->svc_handle, svc->name, id, stream); - - return (result); -} diff --git a/usr/src/lib/print/libpapi-dynamic/common/mapfile b/usr/src/lib/print/libpapi-dynamic/common/mapfile deleted file mode 100644 index cc8cb45239..0000000000 --- a/usr/src/lib/print/libpapi-dynamic/common/mapfile +++ /dev/null @@ -1,279 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# $Id: mapfile.in,v 1.2 2006/03/02 06:31:36 njacobs Exp $ -# - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -$mapfile_version 2 - -# -# Common interfaces that are most likely to be shared amongst the various -# PAPI implementations. -# - -SYMBOL_VERSION SUNW_1.0 { - global: - # PAPI Attribute Calls - papiAttributeListAddValue { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddBoolean { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddCollection { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddDatetime { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddInteger { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddMetadata { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddRange { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddResolution { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListDelete { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetValue { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetNext { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListFind { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetBoolean { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetCollection { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetDatetime { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetInteger { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetMetadata { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetRange { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetResolution { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListFromString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListToString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListFree { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - # PAPI Service Calls - papiServiceCreate ; - papiServiceDestroy ; - papiServiceSetUserName ; - papiServiceSetPassword ; - papiServiceSetEncryption ; - papiServiceSetAuthCB ; - papiServiceSetAppData ; - papiServiceGetUserName ; - papiServiceGetPassword ; - papiServiceGetEncryption ; - papiServiceGetAppData ; - papiServiceGetServiceName ; - papiServiceGetAttributeList ; - papiServiceGetStatusMessage ; - - # PAPI Printer Calls - papiPrintersList ; - papiPrinterQuery ; - papiPrinterAdd ; - papiPrinterModify ; - papiPrinterRemove ; - papiPrinterDisable ; - papiPrinterEnable ; - papiPrinterPause ; - papiPrinterResume ; - papiPrinterPurgeJobs ; - papiPrinterListJobs ; - papiPrinterGetAttributeList ; - papiPrinterFree ; - papiPrinterListFree ; - - # PAPI Job Calls - papiJobSubmit ; - papiJobSubmitByReference ; - papiJobValidate ; - papiJobStreamOpen ; - papiJobStreamWrite ; - papiJobStreamClose ; - papiJobQuery ; - papiJobModify ; - papiJobMove ; - papiJobCancel ; - papiJobHold ; - papiJobRelease ; - papiJobRestart ; - papiJobPromote ; - papiJobGetAttributeList ; - papiJobGetPrinterName ; - papiJobGetId ; - papiJobGetJobTicket ; - papiJobFree ; - papiJobListFree ; - - # Misc. PAPI Calls - papiStatusString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiLibrarySupportedCall { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiLibrarySupportedCalls { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; -}; - -SYMBOL_VERSION SUNWprivate_1.0 { - global: - papiServiceSetPeer ; # extension - papiJobCreate ; - papiJobStreamAdd ; - papiJobCommit ; - - # Misc. supporting calls - # URI - uri_from_string { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - uri_to_string { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - uri_free { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - # list - list_remove { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - list_append { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - list_concatenate { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - # NS - getprinterbyname ; - is_localhost { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - # extra Attribute Calls - copy_attributes { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - split_and_copy_attributes { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListPrint { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - local: - * ; -} ; - -SYMBOL_VERSION FSG_1.0 {} SUNW_1.0; diff --git a/usr/src/lib/print/libpapi-dynamic/common/nss.c b/usr/src/lib/print/libpapi-dynamic/common/nss.c deleted file mode 100644 index 5ab245e936..0000000000 --- a/usr/src/lib/print/libpapi-dynamic/common/nss.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. - * - */ - -/* Id: nss.c 180 2006-07-20 17:33:02Z njacobs $ */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <sys/types.h> -#include <syslog.h> -#include <papi.h> -#include <uri.h> -#include <papi_impl.h> -#ifdef NSS_EMULATION -#include <nss-emulation.h> -#elif NSS_SOLARIS -#include <nss_dbdefs.h> -#endif -#include <config-site.h> -#if defined(__sun) && defined(__SVR4) -#include <sys/systeminfo.h> -#endif - - -static char * -bsdaddr_to_uri(papi_attribute_t **list, char *bsdaddr) -{ - char *result = NULL; - - if (bsdaddr != NULL) { - char *bsd[3], *tmp, *iter = NULL; - char buf[512]; - - tmp = strdup(bsdaddr); - - bsd[0] = strtok_r(tmp, ":,", &iter); - if ((bsd[1] = strtok_r(NULL, ":,", &iter)) == NULL) - papiAttributeListGetString(list, NULL, - "printer-name", &bsd[1]); - bsd[2] = strtok_r(NULL, ":,", &iter); - - snprintf(buf, sizeof (buf), "lpd://%s/printers/%s%s%s", bsd[0], - (bsd[1] != NULL) ? bsd[1] : "", - (bsd[2] != NULL) ? "#" : "", - (bsd[2] != NULL) ? bsd[2] : ""); - - free(tmp); - - result = strdup(buf); - } - - return (result); -} - -#if defined(__sun) && defined(__SVR4) -/* - * This is an awful HACK to force the dynamic PAPI library to use the - * lpsched support when the destination apears to be a local lpsched - * queue on Solaris. - */ -static void -solaris_lpsched_shortcircuit_hack(papi_attribute_t ***list) -{ - papi_attribute_t *attribute; - uri_t *uri = NULL; - char *printer = NULL; - char buf[128], buf2[128]; - - /* setting this in the calling env can be useful for debugging */ - if (getenv("DISABLE_LPSCHED_SHORTCIRCUIT") != NULL) - return; - - papiAttributeListGetString(*list, NULL, - "printer-uri-supported", &printer); - /* if there is no printer-uri-supported, there is nothing to do */ - if (printer == NULL) { - return; - } - - if (uri_from_string(printer, &uri) < 0) { - papiAttributeListFree(*list); - *list = NULL; - uri_free(uri); - return; - } - - /* already an lpsched URI ? */ - if (strcasecmp(uri->scheme, "lpsched") == 0) { - uri_free(uri); - return; - } - - if (uri->path == NULL) { - printer = ""; - } else { - if ((printer = strrchr(uri->path, '/')) == NULL) - printer = uri->path; - else - printer++; - } - - /* is there an lpsched queue (printer/class) */ - snprintf(buf, sizeof (buf), "/etc/lp/interfaces/%s", printer); - snprintf(buf2, sizeof (buf2), "/etc/lp/classes/%s", printer); - if ((access(buf, F_OK) < 0) && (access(buf2, F_OK) < 0)) { - uri_free(uri); - return; - } - - /* is this the "local" host */ - if ((uri->host != NULL) && (is_localhost(uri->host) == 0)) { - uri_free(uri); - return; - } - - snprintf(buf, sizeof (buf), "lpsched://%s/printers/%s", - (uri->host ? uri->host : "localhost"), printer); - papiAttributeListAddString(list, PAPI_ATTR_REPLACE, - "printer-uri-supported", buf); - uri_free(uri); -} -#endif - -static void -fill_printer_uri_supported(papi_attribute_t ***list) -{ - papi_attribute_t *attribute; - char *string = NULL; - - /* do we have a printer-uri-supported */ - attribute = papiAttributeListFind(*list, "printer-uri-supported"); - if (attribute != NULL) /* we have what we need, return */ - return; - - /* do we have a printer-uri (in URI form) to rename */ - attribute = papiAttributeListFind(*list, "printer-uri"); - if ((attribute != NULL) && - (attribute->type == PAPI_STRING) && - (attribute->values != NULL) && - (attribute->values[0]->string != NULL) && - (strstr(attribute->values[0]->string, "://") != NULL)) { - /* rename it in place and return */ - free(attribute->name); - attribute->name = strdup("printer-uri-supported"); - return; - } - - /* do we have a printers.conf(4) "bsdaddr" to convert */ - papiAttributeListGetString(*list, NULL, "bsdaddr", &string); - if (string != NULL) { /* parse it, convert it, add it */ - char *uri = bsdaddr_to_uri(*list, string); - - if (uri != NULL) { - papiAttributeListAddString(list, PAPI_ATTR_APPEND, - "printer-uri-supported", uri); - papiAttributeListDelete(list, "bsdaddr"); - free(uri); - return; - } - } - - /* do we have a printers.conf(4) "rm" (and "rp") to convert */ - papiAttributeListGetString(*list, NULL, "rm", &string); - if (string != NULL) { - char *rp = NULL; - - /* default to "printer-name", but use "rp" if we have it */ - papiAttributeListGetString(*list, NULL, "printer-name", &rp); - papiAttributeListGetString(*list, NULL, "rp", &rp); - - if (rp != NULL) { /* fill in the uri if we have the data */ - char buf[BUFSIZ]; - - snprintf(buf, sizeof (buf), "lpd://%s/printers/%s", - string, rp); - papiAttributeListAddString(list, PAPI_ATTR_APPEND, - "printer-uri-supported", strdup(buf)); - return; - } - } - - /* if were are here, we don't have a printer-uri-supported */ -} - -#ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC -static void -fill_printer_uri(papi_attribute_t ***list) -{ - papi_attribute_t *attribute; - char *uri = NULL; - - if ((list == NULL) || (*list == NULL)) - return; - - /* do we have a printer-uri */ - attribute = papiAttributeListFind(*list, "printer-uri"); - if (attribute != NULL) /* we have what we need, return */ - return; - - /* - * this is sufficient to fool libgnomeprintpapi, but not promote it's - * use in the future. - */ - papiAttributeListAddString(list, PAPI_ATTR_EXCL, "printer-uri", - "broken printer-uri semantic"); -} -#endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */ - -static void -cvt_all_to_member_names(papi_attribute_t ***list) -{ - papi_status_t status; - void *iter = NULL; - char *string = NULL; - - papiAttributeListGetString(*list, NULL, "member-names", &string); - if (string != NULL) /* already have a member-names */ - return; - - for (status = papiAttributeListGetString(*list, &iter, "all", &string); - status == PAPI_OK; - status = papiAttributeListGetString(*list, &iter, NULL, &string)) { - char *s_iter = NULL, *value, *tmp = strdup(string); - - for (value = strtok_r(tmp, ", \t", &s_iter); - value != NULL; - value = strtok_r(NULL, ", \t", &s_iter)) - papiAttributeListAddString(list, PAPI_ATTR_APPEND, - "member-names", value); - free(tmp); - } -} - -static papi_attribute_t ** -_cvt_nss_entry_to_printer(char *entry) -{ - char *key = NULL; - char *cp; - char buf[BUFSIZ]; - int in_namelist = 1, buf_pos = 0; - papi_attribute_t **list = NULL; - - if (entry == NULL) - return (NULL); - - memset(buf, 0, sizeof (buf)); - for (cp = entry; *cp != '\0'; cp++) { - switch (*cp) { - case ':': /* end of kvp */ - if (in_namelist != 0) { - papiAttributeListAddString(&list, - PAPI_ATTR_APPEND, "printer-name", buf); - in_namelist = 0; - } else if (key != NULL) { - papiAttributeListAddString(&list, - PAPI_ATTR_APPEND, key, buf); - free(key); - } - memset(buf, 0, sizeof (buf)); - buf_pos = 0; - key = NULL; - break; - case '=': /* kvp seperator */ - if (key == NULL) { - key = strdup(buf); - memset(buf, 0, sizeof (buf)); - buf_pos = 0; - } else - buf[buf_pos++] = *cp; - break; - case '|': /* namelist seperator */ - if (in_namelist != 0) { - papiAttributeListAddString(&list, - PAPI_ATTR_APPEND, "printer-name", buf); - memset(buf, 0, sizeof (buf)); - buf_pos = 0; - } else /* add it to the buffer */ - buf[buf_pos++] = *cp; - break; - case '\\': /* escape char */ - buf[buf_pos++] = *(++cp); - break; - default: - buf[buf_pos++] = *cp; - } - - } - - if (key != NULL) { - papiAttributeListAddString(&list, PAPI_ATTR_APPEND, key, buf); - free(key); - } - - /* resolve any "use" references in the configuration DB */ - key = NULL; - papiAttributeListGetString(list, NULL, "use", &key); - if (key != NULL) { - papi_attribute_t **use_attrs = getprinterbyname(key, NULL); - - list_concatenate(&list, use_attrs); - } - - fill_printer_uri_supported(&list); - cvt_all_to_member_names(&list); /* convert "all" to "member-names" */ - - return (list); -} - -#if defined(NSS_SOLARIS) && !defined(NSS_EMULATION) - -#ifndef NSS_DBNAM__PRINTERS /* not in nss_dbdefs.h because it's private */ -#define NSS_DBNAM__PRINTERS "_printers" -#endif - -static DEFINE_NSS_DB_ROOT(db_root); -static DEFINE_NSS_GETENT(context); - -static char *private_ns = NULL; - -static void -_nss_initf_printers(p) - nss_db_params_t *p; -{ - if (private_ns != NULL) { - /* - * because we need to support a legacy interface that allows - * us to select a specific name service, we need to dummy up - * the parameters to use a private nsswitch database and set - * the * default_config entry to the name service we are - * looking into. - */ - p->name = NSS_DBNAM__PRINTERS; /* "_printers" */ - p->default_config = private_ns; - } else { - /* regular behaviour */ - p->name = NSS_DBNAM_PRINTERS; /* "printers" */ - p->default_config = NSS_DEFCONF_PRINTERS; - } - syslog(LOG_DEBUG, "database: %s, default: %s", - (p->name ? p->name : "NULL"), - (p->default_config ? p->default_config : "NULL")); -} - -/* - * Return values: 0 = success, 1 = parse error, 2 = erange ... - * The structure pointer passed in is a structure in the caller's space - * wherein the field pointers would be set to areas in the buffer if - * need be. instring and buffer should be separate areas. - */ -/* ARGSUSED */ -static int -str2printer(const char *instr, int lenstr, void *ent, char *buffer, int buflen) -{ - if (lenstr + 1 > buflen) - return (NSS_STR_PARSE_ERANGE); - - /* skip entries that begin with '#' */ - if (instr[0] == '#') - return (NSS_STR_PARSE_PARSE); - - /* - * We copy the input string into the output buffer - */ - (void) memcpy(buffer, instr, lenstr); - buffer[lenstr] = '\0'; - - return (NSS_STR_PARSE_SUCCESS); -} -#endif /* NSS_SOLARIS */ - -int -setprinterentry(int stayopen, char *ns) -{ -#ifdef NSS_EMULATION - emul_setprinterentry(stayopen); -#elif NSS_SOLARIS - private_ns = ns; - nss_setent(&db_root, _nss_initf_printers, &context); - private_ns = NULL; -#endif - return (0); -} - - -int -endprinterentry(int i) -{ -#ifdef NSS_EMULATION - emul_endprinterentry(); -#elif NSS_SOLARIS - nss_endent(&db_root, _nss_initf_printers, &context); - nss_delete(&db_root); - private_ns = NULL; -#endif - return (0); -} - -/* ARGSUSED2 */ -papi_attribute_t ** -getprinterentry(char *ns) -{ - papi_attribute_t **result = NULL; - -#if defined(NSS_EMULATION) || defined(NSS_SOLARIS) - char buf[10240]; - nss_status_t res = NSS_NOTFOUND; - -#ifdef NSS_EMULATION - res = emul_getprinterentry_r(buf, sizeof (buf)); -#elif NSS_SOLARIS - nss_XbyY_args_t arg; - - private_ns = ns; - buf[0] = '\0'; - NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer); - res = nss_getent(&db_root, _nss_initf_printers, &context, &arg); - (void) NSS_XbyY_FINI(&arg); - private_ns = NULL; -#endif - - if (res != NSS_SUCCESS) - buf[0] = '\0'; - - result = _cvt_nss_entry_to_printer(buf); -#if defined(__sun) && defined(__SVR4) - solaris_lpsched_shortcircuit_hack(&result); -#endif -#ifdef NEED_BROKEN_PRINTER_URI_SEMANTIC - fill_printer_uri(&result); -#endif /* NEED_BROKEN_PRINTER_URI_SEMANTIC */ -#endif - -#ifdef DEBUG - printf("getprinterentry(%s): 0x%8.8x\n", (ns ? ns : "NULL"), result); - if (result != NULL) { - char buf[4096]; - - papiAttributeListToString(result, "\n\t", buf, sizeof (buf)); - printf("\t%s\n", buf); - } -#endif /* DEBUG */ - - return (result); -} - - -papi_attribute_t ** -getprinterbyname(char *name, char *ns) -{ - papi_attribute_t **result = NULL; - - if (strstr(name, "://") != NULL) { /* shortcut for URI form */ - papiAttributeListAddString(&result, PAPI_ATTR_APPEND, - "printer-name", name); - papiAttributeListAddString(&result, PAPI_ATTR_APPEND, - "printer-uri-supported", name); - } else if (strchr(name, ':') != NULL) { /* shortcut for POSIX form */ - char *uri = bsdaddr_to_uri(result, name); - - papiAttributeListAddString(&result, PAPI_ATTR_APPEND, - "printer-name", name); - if (uri != NULL) { - papiAttributeListAddString(&result, PAPI_ATTR_APPEND, - "printer-uri-supported", uri); - free(uri); - } - } else { /* anything else */ -#if defined(NSS_EMULATION) || defined(NSS_SOLARIS) - char buf[10240]; - nss_status_t res = NSS_NOTFOUND; - -#ifdef NSS_EMULATION - res = emul_getprinterbyname_r(name, buf, sizeof (buf)); -#elif NSS_SOLARIS - nss_XbyY_args_t arg; - - private_ns = ns; - NSS_XbyY_INIT(&arg, buf, buf, sizeof (buf), str2printer); - arg.key.name = name; - res = nss_search(&db_root, _nss_initf_printers, - NSS_DBOP_PRINTERS_BYNAME, &arg); - (void) NSS_XbyY_FINI(&arg); - private_ns = NULL; - - if (res != NSS_SUCCESS) - buf[0] = '\0'; -#endif - - result = _cvt_nss_entry_to_printer(buf); -#endif - } -#if defined(__sun) && defined(__SVR4) - solaris_lpsched_shortcircuit_hack(&result); -#endif -#ifdef DEBUG - printf("getprinterbyname(%s): %s = 0x%8.8x\n", (ns ? ns : "NULL"), - name, result); - if (result != NULL) { - char buf[4096]; - - papiAttributeListToString(result, "\n\t", buf, sizeof (buf)); - printf("\t%s\n", buf); - } -#endif /* DEBUG */ - - return (result); -} diff --git a/usr/src/lib/print/libpapi-dynamic/common/papi_impl.h b/usr/src/lib/print/libpapi-dynamic/common/papi_impl.h deleted file mode 100644 index be28a9de0c..0000000000 --- a/usr/src/lib/print/libpapi-dynamic/common/papi_impl.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -#ifndef _PAPI_IMPL_H -#define _PAPI_IMPL_H - -/* $Id: papi_impl.h 161 2006-05-03 04:32:59Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <papi.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#include <time.h> -#include <sys/types.h> -#include <stdarg.h> -#include <uri.h> - -/* - * Implementation specific types/prototypes/definitions follow - * - * - * Ex: - */ - -typedef struct { - papi_attribute_t **attributes; - void *so_handle; - void *svc_handle; - char *name; - char *user; - char *password; - int (*authCB)(papi_service_t svc, void *app_data); - papi_encryption_t encryption; - void *app_data; - uri_t *uri; - int peer_fd; -} service_t; - -typedef struct job { - service_t *svc; - papi_job_t *job; -} job_t; - -typedef struct { - service_t *svc; - papi_printer_t *printer; - papi_attribute_t **attributes; - char svc_is_internal; -} printer_t; - -extern papi_status_t psm_open(service_t *svc, char *name); -extern void *psm_sym(service_t *svc, char *name); -extern void psm_close(void *handle); -extern void detailed_error(service_t *svc, char *fmt, ...); -extern papi_status_t service_connect(service_t *svc, char *uri); -extern papi_attribute_t **getprinterentry(char *ns); -extern papi_attribute_t **getprinterbyname(char *name, char *ns); -extern int setprinterentry(int stayopen, char *ns); -extern int endprinterentry(int stayopen); - - - -extern void list_remove(); - -#ifdef __cplusplus -} -#endif - -#endif /* _PAPI_IMPL_H */ diff --git a/usr/src/lib/print/libpapi-dynamic/common/printer.c b/usr/src/lib/print/libpapi-dynamic/common/printer.c deleted file mode 100644 index e02a325ebd..0000000000 --- a/usr/src/lib/print/libpapi-dynamic/common/printer.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: printer.c 151 2006-04-25 16:55:34Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdlib.h> -#include <papi_impl.h> - -void -papiPrinterFree(papi_printer_t printer) -{ - printer_t *tmp = printer; - - if (tmp != NULL) { - void (*f)(); - - f = (void (*)())psm_sym(tmp->svc, "papiPrinterFree"); - if (f != NULL) - f(tmp->printer); - if (tmp->attributes != NULL) - papiAttributeListFree(tmp->attributes); - if (tmp->svc_is_internal != 0) - papiServiceDestroy(tmp->svc); - free(tmp); - } -} - -void -papiPrinterListFree(papi_printer_t *printers) -{ - if (printers != NULL) { - int i; - - for (i = 0; printers[i] != NULL; i++) - papiPrinterFree(printers[i]); - free(printers); - } -} - -/* Enumerate a list of printers from the loaded print service. */ -static papi_status_t -printers_from_service(service_t *svc, char **requested_attrs, - papi_filter_t *filter, papi_printer_t **printers) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - papi_printer_t *svc_printers = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (printers == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* connect to the service if we are not connected */ - if ((result = service_connect(svc, svc->name)) != PAPI_OK) - return (result); - - f = (papi_status_t (*)())psm_sym(svc, "papiPrintersList"); - if (f != NULL) - result = f(svc->svc_handle, requested_attrs, filter, - &svc_printers); - - /* - * copy the resulting printer object pointers into our own - * representation of a printer object because we need the - * service context to operate against the individual printer - * objects. We free the list now because we no longer need - * it and would have no way of freeing it later. - */ - if ((result == PAPI_OK) && (svc_printers != NULL)) { - int i; - - *printers = NULL; - for (i = 0; svc_printers[i] != NULL; i++) { - printer_t *p = NULL; - - if ((p = calloc(1, sizeof (*p))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - p->svc = svc; - p->printer = svc_printers[i]; - list_append(printers, p); - } - free(svc_printers); - } - - return (result); -} - -/* Get printer attributes from it's print service */ -static papi_status_t -printer_from_service(service_t *svc, printer_t *p, char **requested_attrs) -{ - papi_status_t result; - papi_service_t p_svc = NULL; - papi_printer_t printer = NULL; - char *psm = NULL; - char *uri = NULL; - - /* get the psm and uri from the attributes */ - papiAttributeListGetString(p->attributes, NULL, - "print-service-module", &psm); - papiAttributeListGetString(p->attributes, NULL, "printer-name", &uri); - papiAttributeListGetString(p->attributes, NULL, "printer-uri-supported", - &uri); - - /* contact the service for the printer */ - result = papiServiceCreate((papi_service_t *)&p_svc, psm, svc->user, - svc->password, svc->authCB, svc->encryption, - svc->app_data); - if (result != PAPI_OK) - return (result); - - /* get the printer from the service */ - result = papiPrinterQuery(p_svc, uri, requested_attrs, NULL, &printer); - if (result == PAPI_OK) { - papi_attribute_t **attributes; - - attributes = papiPrinterGetAttributeList(printer); - copy_attributes(&p->attributes, attributes); - } - papiPrinterFree(printer); - papiServiceDestroy(p_svc); - - return (result); -} - -/* are the requested attributes contained in the list */ -static int -contained(char **requested, papi_attribute_t **list) -{ - int i; - - if (requested == NULL) /* we want every possible attribute */ - return (0); - - for (i = 0; requested[i] != NULL; i++) - if (papiAttributeListFind(list, requested[i]) == NULL) - return (0); - - return (1); -} - -/* Enumerate a list of printers from the Name Service */ -static papi_status_t -printers_from_name_service(service_t *svc, char **requested_attrs, - papi_filter_t *filter, papi_printer_t **printers) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - papi_attribute_t **attrs; - - if ((svc == NULL) || (printers == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* retrieve printers from the nameservice */ - setprinterentry(0, NULL); - while ((attrs = getprinterentry(NULL)) != NULL) { - printer_t *p = NULL; - - if ((p = calloc(1, sizeof (*p))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - p->attributes = attrs; - list_append(printers, p); - } - - /* if we have printers, check if our request has been satisfied */ - if ((printers != NULL) && (*printers != NULL)) { - int i; - - /* walk through the list */ - for (i = 0; (*printers)[i] != NULL; i++) { - printer_t *p = (*printers)[i]; - - /* see if the name service satisfied the request */ - if (contained(requested_attrs, p->attributes) == 0) - printer_from_service(svc, p, requested_attrs); - } - } - - return (PAPI_OK); -} - -papi_status_t -papiPrintersList(papi_service_t handle, char **requested_attrs, - papi_filter_t *filter, papi_printer_t **printers) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_printer_t *svc_printers = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (printers == NULL)) - return (PAPI_BAD_ARGUMENT); - - if (svc->so_handle != NULL) /* connected, use the print svc */ - result = printers_from_service(svc, requested_attrs, - filter, printers); - else /* not connected, use the name svc */ - result = printers_from_name_service(svc, requested_attrs, - filter, printers); - - return (result); -} - -papi_status_t -papiPrinterQuery(papi_service_t handle, char *name, char **requested_attrs, - papi_attribute_t **job_attributes, papi_printer_t *printer) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - printer_t *p = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (name == NULL) || (printer == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - if ((*printer = p = calloc(1, sizeof (*p))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - if ((svc->name != NULL) && (svc->svc_handle != NULL) && - (svc->uri != NULL)) { - p->svc = svc; - f = (papi_status_t (*)())psm_sym(p->svc, "papiPrinterQuery"); - if (f != NULL) - result = f(svc->svc_handle, svc->name, requested_attrs, - job_attributes, &p->printer); - } else { - setprinterentry(0, NULL); - p->attributes = getprinterbyname(name, NULL); - if (p->attributes == NULL) - result = PAPI_NOT_FOUND; - else - result = PAPI_OK; - } - - return (result); -} - -static papi_status_t -_papi_printer_disable_or_pause(papi_service_t handle, char *name, char *message, - char *function) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_status_t (*f)(); - - if ((svc == NULL) || (name == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - f = (papi_status_t (*)())psm_sym(svc, function); - if (f != NULL) - result = f(svc->svc_handle, svc->name, message); - - return (result); -} - -static papi_status_t -_papi_printer_enable_or_resume(papi_service_t handle, char *name, - char *function) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_status_t (*f)(); - - if ((svc == NULL) || (name == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - f = (papi_status_t (*)())psm_sym(svc, function); - if (f != NULL) - result = f(svc->svc_handle, svc->name); - - return (result); -} - -papi_status_t -papiPrinterDisable(papi_service_t handle, char *name, char *message) -{ - return (_papi_printer_disable_or_pause(handle, name, message, - "papiPrinterDisable")); -} - -papi_status_t -papiPrinterPause(papi_service_t handle, char *name, char *message) -{ - return (_papi_printer_disable_or_pause(handle, name, message, - "papiPrinterPause")); -} - -papi_status_t -papiPrinterEnable(papi_service_t handle, char *name) -{ - return (_papi_printer_enable_or_resume(handle, name, - "papiPrinterEnable")); -} - -papi_status_t -papiPrinterResume(papi_service_t handle, char *name) -{ - return (_papi_printer_enable_or_resume(handle, name, - "papiPrinterResume")); -} - -static papi_status_t -_papi_printer_add_or_modify(papi_service_t handle, char *name, - papi_attribute_t **attributes, papi_printer_t *printer, - char *function) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - printer_t *p = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (name == NULL) || (attributes == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - if ((*printer = p = calloc(1, sizeof (*p))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - p->svc = svc; - f = (papi_status_t (*)())psm_sym(p->svc, function); - if (f != NULL) - result = f(svc->svc_handle, svc->name, attributes, - &p->printer); - - return (result); -} - -papi_status_t -papiPrinterAdd(papi_service_t handle, char *name, - papi_attribute_t **attributes, papi_printer_t *printer) -{ - return (_papi_printer_add_or_modify(handle, name, attributes, printer, - "papiPrinterAdd")); -} - -papi_status_t -papiPrinterModify(papi_service_t handle, char *name, - papi_attribute_t **attributes, papi_printer_t *printer) -{ - return (_papi_printer_add_or_modify(handle, name, attributes, printer, - "papiPrinterModify")); -} - - -papi_status_t -papiPrinterRemove(papi_service_t handle, char *name) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_status_t (*f)(); - - if ((svc == NULL) || (name == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - f = (papi_status_t (*)())psm_sym(svc, "papiPrinterRemove"); - if (f != NULL) - result = f(svc->svc_handle, svc->name); - - return (result); -} - -papi_status_t -papiPrinterPurgeJobs(papi_service_t handle, char *name, papi_job_t **jobs) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_job_t *svc_jobs = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (name == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - f = (papi_status_t (*)())psm_sym(svc, "papiPrinterPurgeJobs"); - if (f != NULL) - result = f(svc->svc_handle, svc->name, &svc_jobs); - - /* - * copy the resulting job object pointers into our own - * representation of a job object because we need the - * service context to operate against the individual job - * objects. We free the list now because we no longer need - * it and would have no way of freeing it later. - */ - if ((result == PAPI_OK) && (svc_jobs != NULL) && (jobs != NULL)) { - int i; - - *jobs = NULL; - for (i = 0; svc_jobs[i] != NULL; i++) { - job_t *j = NULL; - - if ((j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - j->svc = svc; - j->job = svc_jobs[i]; - list_append(jobs, j); - } - free(svc_jobs); - } - - return (result); -} - -papi_status_t -papiPrinterListJobs(papi_service_t handle, char *name, char **requested_attrs, - int type_mask, int max_num_jobs, papi_job_t **jobs) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_job_t *svc_jobs = NULL; - papi_status_t (*f)(); - - if ((svc == NULL) || (name == NULL) || (jobs == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - f = (papi_status_t (*)())psm_sym(svc, "papiPrinterListJobs"); - if (f != NULL) - result = f(svc->svc_handle, svc->name, requested_attrs, - type_mask, max_num_jobs, &svc_jobs); - - /* - * copy the resulting job object pointers into our own - * representation of a job object because we need the - * service context to operate against the individual job - * objects. We free the list now because we no longer need - * it and would have no way of freeing it later. - */ - if ((result == PAPI_OK) && (svc_jobs != NULL)) { - int i; - - *jobs = NULL; - for (i = 0; svc_jobs[i] != NULL; i++) { - job_t *j = NULL; - - if ((j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - j->svc = svc; - j->job = svc_jobs[i]; - list_append(jobs, j); - } - free(svc_jobs); - } - - return (result); -} - -papi_attribute_t ** -papiPrinterGetAttributeList(papi_printer_t printer) -{ - papi_attribute_t **result = NULL; - printer_t *p = printer; - - if ((p != NULL) && (p->printer != NULL)) { - papi_attribute_t **(*f)(); - - f = (papi_attribute_t **(*)())psm_sym(p->svc, - "papiPrinterGetAttributeList"); - if (f != NULL) - result = f(p->printer); - } else - result = p->attributes; - - return (result); -} diff --git a/usr/src/lib/print/libpapi-dynamic/common/psm.c b/usr/src/lib/print/libpapi-dynamic/common/psm.c deleted file mode 100644 index af31f24b4e..0000000000 --- a/usr/src/lib/print/libpapi-dynamic/common/psm.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: psm.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <dlfcn.h> -#include <papi_impl.h> - -#ifndef RTLD_GROUP -#define RTLD_GROUP 0 -#endif /* RTLD_GROUP */ - -#ifndef PSM_DIR -#define PSM_DIR "/usr/lib/print" -#endif - -papi_status_t -psm_open(service_t *svc, char *scheme) -{ - papi_status_t result = PAPI_OK; - char path[BUFSIZ]; - - if ((scheme == NULL) || (strchr(scheme, '/') != NULL)) - return (PAPI_BAD_ARGUMENT); - - snprintf(path, sizeof (path), PSM_DIR "/psm-%s.so", scheme); - - svc->so_handle = dlopen(path, RTLD_LAZY|RTLD_LOCAL|RTLD_GROUP); - if (svc->so_handle == NULL) { /* failed, set the result/message */ - if ((access(path, F_OK) < 0) && (errno == ENOENT)) - result = PAPI_URI_SCHEME; - else - result = PAPI_NOT_POSSIBLE; -#ifdef DEBUG - detailed_error(svc, "psm_open(%s): %s: %s", scheme, path, - dlerror()); -#endif - } - - return (result); -} - -void -psm_close(void *handle) -{ - dlclose(handle); -} - -void * -psm_sym(service_t *svc, char *name) -{ - char *error = "invalid input"; - void *func = NULL; - - if ((svc != NULL) && (svc->so_handle != NULL) && (name != NULL)) { - if ((func = dlsym(svc->so_handle, name)) == NULL) - error = dlerror(); - } -#ifdef DEBUG - if (func == NULL) - detailed_error(svc, "psm_sym(%s): %s", name, error); -#endif - - return (func); -} diff --git a/usr/src/lib/print/libpapi-dynamic/common/service.c b/usr/src/lib/print/libpapi-dynamic/common/service.c deleted file mode 100644 index 55f1732a65..0000000000 --- a/usr/src/lib/print/libpapi-dynamic/common/service.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: service.c 172 2006-05-24 20:54:00Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <sys/types.h> -#include <unistd.h> -#include <string.h> -#include <alloca.h> -#include <libintl.h> -#include <papi_impl.h> -#include <config-site.h> - -static int -interposed_auth_callback(papi_service_t handle, void *app_data) -{ - int result = -1; - service_t *svc = app_data; - - if (svc != NULL) - result = svc->authCB(svc, svc->app_data); - - return (result); -} - -static char * -default_service_uri(char *fallback) -{ - char *result = NULL; - - if (getuid() == geteuid()) - result = getenv("PAPI_SERVICE_URI"); - - if (result == NULL) { - char *cups; - - if ((cups = getenv("CUPS_SERVER")) != NULL) { - char buf[BUFSIZ]; - - snprintf(buf, sizeof (buf), "ipp://%s/printers/", cups); - result = strdup(buf); - } - } - - if (result == NULL) - result = fallback; - - return (result); -} - -static char * -default_print_service() -{ - static char *result = NULL; - - if (result == NULL) { - char *service_uri = default_service_uri(DEFAULT_SERVICE_URI); - uri_t *uri = NULL; - - if (uri_from_string(service_uri, &uri) != -1) - result = strdup(uri->scheme); - - if (uri != NULL) - uri_free(uri); - } - - return (result); -} - -static papi_status_t -service_load(service_t *svc, char *name) -{ - papi_status_t result; - char *scheme = default_print_service(); - - if (svc->so_handle != NULL) /* already loaded */ - return (PAPI_OK); - - if (name == NULL) /* no info, can't load yet */ - return (PAPI_OK); - - /* Lookup the printer in the configuration DB */ - svc->attributes = getprinterbyname((char *)name, NULL); - - if (svc->attributes != NULL) { - char *tmp = NULL; - - /* Printer found (or was a URI), use the attribute data */ - papiAttributeListGetString(svc->attributes, NULL, - "printer-uri-supported", &tmp); - if (tmp != NULL) - svc->name = strdup(tmp); - - /* parse the URI and set the scheme(print service) */ - if (uri_from_string(svc->name, &svc->uri) != -1) - scheme = (svc->uri)->scheme; - - /* override the scheme if it was in the attributes */ - papiAttributeListGetString(svc->attributes, NULL, - "print-service-module", &scheme); - - } else /* not found, assume it is the actual print service name */ - scheme = name; - - result = psm_open(svc, scheme); - switch (result) { - case PAPI_OK: - break; /* no error */ - case PAPI_URI_SCHEME: - result = PAPI_NOT_FOUND; -#ifdef DEBUG - detailed_error(svc, "Unable to load service for: %s", name); -#endif - break; - default: /* set the detailed message */ - detailed_error(svc, "Unable to load service (%s) for: %s", - scheme, name); - } - - return (result); -} - -static papi_status_t -service_send_peer(service_t *svc) -{ - papi_status_t result = PAPI_OK; - - if ((svc->peer_fd != -1) && (svc->so_handle != NULL) && - (svc->svc_handle != NULL)) { - papi_status_t (*f)(); - - f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetPeer"); - - if (f != NULL) - result = f(svc->svc_handle, svc->peer_fd); - } - - return (result); -} - -papi_status_t -service_connect(service_t *svc, char *name) -{ - papi_status_t result = PAPI_NOT_POSSIBLE; - - /* if there is no print service module loaded, try and load one. */ - if (svc->so_handle == NULL) - result = service_load(svc, name); - else if ((svc->name == NULL) && (name != NULL)) - svc->name = strdup(name); - - /* - * the print service module is loaded, but we don't have a service - * handle. - */ - if (svc->so_handle != NULL) { - papi_status_t (*f)(); - - if (svc->svc_handle != NULL) /* already connected? */ - return (PAPI_OK); - - f = (papi_status_t (*)())psm_sym(svc, "papiServiceCreate"); - - if (f != NULL) { - char *user = svc->user; - char *password = svc->password; - - /* if no API user, try the URI user */ - if ((user == NULL) && (svc->uri != NULL)) - user = (svc->uri)->user; - /* if no API password, try the URI password */ - if ((password == NULL) && (svc->uri != NULL)) - password = (svc->uri)->password; - - result = f(&svc->svc_handle, svc->name, user, password, - (svc->authCB ? interposed_auth_callback - : NULL), - svc->encryption, svc); - (void) service_send_peer(svc); - } - } - - return (result); -} - -papi_status_t -papiServiceCreate(papi_service_t *handle, char *service_name, char *user_name, - char *password, - int (*authCB)(papi_service_t svc, void *app_data), - papi_encryption_t encryption, void *app_data) -{ - papi_status_t result = PAPI_NOT_POSSIBLE; - service_t *svc = NULL; - uri_t *u = NULL; - - if (handle == NULL) - return (PAPI_BAD_ARGUMENT); - - if ((*handle = svc = calloc(1, sizeof (*svc))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - svc->peer_fd = -1; - - if (user_name != NULL) - svc->user = strdup(user_name); - - if (password != NULL) - svc->password = strdup(password); - - svc->encryption = encryption; - - if (authCB != NULL) - svc->authCB = authCB; - - if (app_data != NULL) - svc->app_data = app_data; - - /* If not specified, get a "default" service from the environment */ - if (service_name == NULL) - service_name = default_service_uri(NULL); - - if (service_name != NULL) { - result = service_load(svc, service_name); - /* if the psm loaded and the svc contains a URI, connect */ - if ((result == PAPI_OK) && (svc->uri != NULL)) - result = service_connect(svc, service_name); - } else - result = PAPI_OK; - - return (result); -} - -void -papiServiceDestroy(papi_service_t handle) -{ - if (handle != NULL) { - service_t *svc = handle; - - if (svc->so_handle != NULL) { - if (svc->svc_handle != NULL) { - void (*f)(); - - f = (void (*)())psm_sym(svc, - "papiServiceDestroy"); - f(svc->svc_handle); - } - psm_close(svc->so_handle); - } - if (svc->attributes != NULL) - papiAttributeListFree(svc->attributes); - if (svc->name != NULL) - free(svc->name); - if (svc->user != NULL) - free(svc->user); - if (svc->password != NULL) - free(svc->password); - if (svc->uri != NULL) - uri_free(svc->uri); - - free(handle); - } -} - -papi_status_t -papiServiceSetPeer(papi_service_t handle, int fd) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - - svc->peer_fd = fd; - result = service_send_peer(svc); - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - -papi_status_t -papiServiceSetUserName(papi_service_t handle, char *user_name) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - papi_status_t (*f)(); - - if (svc->user != NULL) - free(svc->user); - if (user_name != NULL) - svc->user = strdup(user_name); - f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetUserName"); - if (f != NULL) - result = f(svc->svc_handle, user_name); - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - -papi_status_t -papiServiceSetPassword(papi_service_t handle, char *password) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - papi_status_t (*f)(); - - if (svc->password != NULL) - free(svc->password); - if (password != NULL) - svc->password = strdup(password); - f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetPassword"); - if (f != NULL) - result = f(svc->svc_handle, password); - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - -papi_status_t -papiServiceSetEncryption(papi_service_t handle, papi_encryption_t encryption) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - papi_status_t (*f)(); - - svc->encryption = encryption; - f = (papi_status_t (*)())psm_sym(svc, - "papiServiceSetEncryption"); - if (f != NULL) - result = f(svc->svc_handle, encryption); - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - -papi_status_t -papiServiceSetAuthCB(papi_service_t handle, - int (*authCB)(papi_service_t svc, void *app_data)) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - papi_status_t (*f)(); - - svc->authCB = authCB; - f = (papi_status_t (*)())psm_sym(svc, "papiServiceSetAuthCB"); - if (f != NULL) - result = f(svc->svc_handle, interposed_auth_callback); - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - - -papi_status_t -papiServiceSetAppData(papi_service_t handle, void *app_data) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - papi_status_t (*f)(); - - svc->app_data = (void *)app_data; - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - -char * -papiServiceGetServiceName(papi_service_t handle) -{ - char *result = NULL; - - if (handle != NULL) { - service_t *svc = handle; - char *(*f)(); - - f = (char *(*)())psm_sym(svc, "papiServiceGetServiceName"); - if (f != NULL) - result = f(svc->svc_handle); - if (result == NULL) - result = svc->name; - } - - return (result); -} - -char * -papiServiceGetUserName(papi_service_t handle) -{ - char *result = NULL; - - if (handle != NULL) { - service_t *svc = handle; - char *(*f)(); - - f = (char *(*)())psm_sym(svc, "papiServiceGetUserName"); - if (f != NULL) - result = f(svc->svc_handle); - if (result == NULL) - result = svc->user; - } - - return (result); -} - -char * -papiServiceGetPassword(papi_service_t handle) -{ - char *result = NULL; - - if (handle != NULL) { - service_t *svc = handle; - char *(*f)(); - - f = (char *(*)())psm_sym(svc, "papiServiceGetPassword"); - if (f != NULL) - result = f(svc->svc_handle); - if (result == NULL) - result = svc->password; - } - - return (result); -} - -papi_encryption_t -papiServiceGetEncryption(papi_service_t handle) -{ - papi_encryption_t result = PAPI_ENCRYPT_NEVER; - - if (handle != NULL) { - service_t *svc = handle; - papi_encryption_t (*f)(); - - f = (papi_encryption_t (*)())psm_sym(svc, - "papiServiceGetEncryption"); - if (f != NULL) - result = f(svc->svc_handle); - if (result == PAPI_ENCRYPT_NEVER) - result = svc->encryption; - } - - return (result); -} - -void * -papiServiceGetAppData(papi_service_t handle) -{ - void *result = NULL; - service_t *svc = handle; - - if (handle != NULL) - result = svc->app_data; - - return (result); -} - -papi_attribute_t ** -papiServiceGetAttributeList(papi_service_t handle) -{ - papi_attribute_t **result = NULL; - service_t *svc = handle; - - if (handle != NULL) { - papi_attribute_t **(*f)(); - - if (svc->so_handle == NULL) { - char *uri = default_service_uri(DEFAULT_SERVICE_URI); - - if (service_connect(svc, uri) != PAPI_OK) - return (NULL); - } - - f = (papi_attribute_t **(*)())psm_sym(svc, - "papiServiceGetAttributeList"); - if (f != NULL) - result = f(svc->svc_handle); - } else - result = svc->attributes; - - return (result); -} - -char * -papiServiceGetStatusMessage(papi_service_t handle) -{ - char *result = NULL; - service_t *svc = handle; - - if (handle != NULL) { - char *(*f)(); - - f = (char *(*)())psm_sym(svc, "papiServiceGetStatusMessage"); - if (f != NULL) - result = f(svc->svc_handle); - } - if (result == NULL) { - papiAttributeListGetString(svc->attributes, NULL, - "detailed-status-message", &result); - } - - return (result); -} - -void -detailed_error(service_t *svc, char *fmt, ...) -{ - if ((svc != NULL) && (fmt != NULL)) { - va_list ap; - size_t size; - char *message = alloca(BUFSIZ); - - va_start(ap, fmt); - /* - * fill in the message. If the buffer is too small, allocate - * one that is large enough and fill it in. - */ - if ((size = vsnprintf(message, BUFSIZ, fmt, ap)) >= BUFSIZ) - if ((message = alloca(size)) != NULL) - vsnprintf(message, size, fmt, ap); - va_end(ap); - - papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND, - "detailed-status-message", message); -#ifdef DEBUG - fprintf(stderr, "detailed_error(%s)\n", message); -#endif - } -} diff --git a/usr/src/lib/print/libpapi-dynamic/i386/Makefile b/usr/src/lib/print/libpapi-dynamic/i386/Makefile deleted file mode 100644 index 3b985583a4..0000000000 --- a/usr/src/lib/print/libpapi-dynamic/i386/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBS) $(ROOTLINKS) # $(ROOTLINT) diff --git a/usr/src/lib/print/libpapi-dynamic/sparc/Makefile b/usr/src/lib/print/libpapi-dynamic/sparc/Makefile deleted file mode 100644 index 3b985583a4..0000000000 --- a/usr/src/lib/print/libpapi-dynamic/sparc/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBS) $(ROOTLINKS) # $(ROOTLINT) diff --git a/usr/src/lib/print/libpapi-ipp/Makefile b/usr/src/lib/print/libpapi-ipp/Makefile deleted file mode 100644 index b92d620b10..0000000000 --- a/usr/src/lib/print/libpapi-ipp/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../../Makefile.lib - -#HDRS = papi.h -#HDRDIR = common -SUBDIRS = $(MACH) -#$(BUILD64)SUBDIRS += $(MACH64) - -all := TARGET = all -clean := TARGET = clean -clobber := TARGET = clobber -install := TARGET = install -lint := TARGET = lint - -.KEEP_STATE: - -all clean clobber install: .WAIT $(SUBDIRS) - -lint: # $(SUBDIRS) - -install_h: # $(ROOTHDRS) - -check: # $(CHECKHDRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: - -include ../../Makefile.targ diff --git a/usr/src/lib/print/libpapi-ipp/Makefile.com b/usr/src/lib/print/libpapi-ipp/Makefile.com deleted file mode 100644 index f5abebce00..0000000000 --- a/usr/src/lib/print/libpapi-ipp/Makefile.com +++ /dev/null @@ -1,71 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY = psm-ipp.a -VERS = .1 -OBJECTS = ipp-support.o job.o printer.o service.o -ROOTLIBDIR = $(ROOT)/usr/lib/print - -include ../../../Makefile.lib -include ../../../Makefile.rootfs - -SRCDIR = ../common - -ROOTLIBDIR= $(ROOT)/usr/lib/print -ROOTLIBDIR64= $(ROOT)/usr/lib/print/$(MACH) - -EXTRALINKS= $(ROOTLIBDIR)/psm-http.so -$(EXTRALINKS): $(ROOTLINKS) - $(RM) $@; $(SYMLINK) $(LIBLINKS) $@ - -LIBS = $(DYNLIB) - -$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRCDIR) -CPPFLAGS += -I../../libpapi-common/common -CPPFLAGS += -I../../libipp-core/common -CPPFLAGS += -I../../libhttp-core/common - -CERRWARN += -_gcc=-Wno-type-limits -CERRWARN += -_gcc=-Wno-unused-variable -CERRWARN += -_gcc=-Wno-uninitialized - -MAPFILES = $(SRCDIR)/mapfile - -LDLIBS += -L$(ROOTLIBDIR) -R/usr/lib/print -lhttp-core -lmd5 -LDLIBS += -lipp-core -lc - -.KEEP_STATE: - -all: $(LIBS) - -lint: lintcheck - -$(ROOTLIBDIR): - $(INS.dir) - -include ../../../Makefile.targ diff --git a/usr/src/lib/print/libpapi-ipp/common/ipp-support.c b/usr/src/lib/print/libpapi-ipp/common/ipp-support.c deleted file mode 100644 index b2caff84ac..0000000000 --- a/usr/src/lib/print/libpapi-ipp/common/ipp-support.c +++ /dev/null @@ -1,631 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: ipp-support.c 148 2006-04-25 16:54:17Z njacobs $ */ - - -#include <papi_impl.h> -#include <stdlib.h> -#include <pwd.h> -#include <locale.h> -#include <errno.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <md5.h> - -#include <config-site.h> - -#include <ipp.h> - -static void ipp_add_printer_uri(service_t *svc, char *name, - papi_attribute_t ***op); - -papi_status_t -http_to_papi_status(http_status_t status) -{ - switch (status) { - case HTTP_OK: - return (PAPI_OK); - case HTTP_BAD_REQUEST: - return (PAPI_BAD_REQUEST); - case HTTP_UNAUTHORIZED: - case HTTP_FORBIDDEN: - return (PAPI_NOT_AUTHORIZED); - case HTTP_NOT_FOUND: - return (PAPI_NOT_FOUND); - case HTTP_GONE: - return (PAPI_GONE); - case HTTP_SERVICE_UNAVAILABLE: - return (PAPI_SERVICE_UNAVAILABLE); - default: - return ((papi_status_t)status); - } -} - -papi_status_t -ipp_to_papi_status(uint16_t status) -{ - switch (status) { - case IPP_OK: - return (PAPI_OK); - case IPP_OK_IGNORED_ATTRIBUTES: - return (PAPI_OK); - case IPP_OK_CONFLICTING_ATTRIBUTES: - return (PAPI_OK); - case IPP_OK_IGNORED_SUBSCRIPTIONS: - return (PAPI_OK_IGNORED_SUBSCRIPTIONS); - case IPP_OK_IGNORED_NOTIFICATIONS: - return (PAPI_OK_IGNORED_NOTIFICATIONS); - case IPP_CERR_BAD_REQUEST: - return (PAPI_BAD_REQUEST); - case IPP_CERR_FORBIDDEN: - return (PAPI_FORBIDDEN); - case IPP_CERR_NOT_AUTHENTICATED: - return (PAPI_NOT_AUTHENTICATED); - case IPP_CERR_NOT_AUTHORIZED: - return (PAPI_NOT_AUTHORIZED); - case IPP_CERR_NOT_POSSIBLE: - return (PAPI_NOT_POSSIBLE); - case IPP_CERR_TIMEOUT: - return (PAPI_TIMEOUT); - case IPP_CERR_NOT_FOUND: - return (PAPI_NOT_FOUND); - case IPP_CERR_GONE: - return (PAPI_GONE); - case IPP_CERR_REQUEST_ENTITY: - return (PAPI_REQUEST_ENTITY); - case IPP_CERR_REQUEST_VALUE: - return (PAPI_REQUEST_VALUE); - case IPP_CERR_DOCUMENT_FORMAT: - return (PAPI_DOCUMENT_FORMAT); - case IPP_CERR_ATTRIBUTES: - return (PAPI_ATTRIBUTES); - case IPP_CERR_URI_SCHEME: - return (PAPI_URI_SCHEME); - case IPP_CERR_CHARSET: - return (PAPI_CHARSET); - case IPP_CERR_CONFLICT: - return (PAPI_CONFLICT); - case IPP_CERR_COMPRESSION_NOT_SUPPORTED: - return (PAPI_COMPRESSION_NOT_SUPPORTED); - case IPP_CERR_COMPRESSION_ERROR: - return (PAPI_COMPRESSION_ERROR); - case IPP_CERR_DOCUMENT_FORMAT_ERROR: - return (PAPI_DOCUMENT_FORMAT_ERROR); - case IPP_CERR_DOCUMENT_ACCESS_ERROR: - return (PAPI_DOCUMENT_ACCESS_ERROR); - case IPP_CERR_ATTRIBUTES_NOT_SETTABLE: - return (PAPI_ATTRIBUTES_NOT_SETTABLE); - case IPP_CERR_IGNORED_ALL_SUBSCRIPTIONS: - return (PAPI_IGNORED_ALL_SUBSCRIPTIONS); - case IPP_CERR_TOO_MANY_SUBSCRIPTIONS: - return (PAPI_TOO_MANY_SUBSCRIPTIONS); - case IPP_CERR_IGNORED_ALL_NOTIFICATIONS: - return (PAPI_IGNORED_ALL_NOTIFICATIONS); - case IPP_CERR_PRINT_SUPPORT_FILE_NOT_FOUND: - return (PAPI_PRINT_SUPPORT_FILE_NOT_FOUND); - case IPP_SERR_INTERNAL: - return (PAPI_INTERNAL_ERROR); - case IPP_SERR_OPERATION_NOT_SUPPORTED: - return (PAPI_OPERATION_NOT_SUPPORTED); - case IPP_SERR_SERVICE_UNAVAILABLE: - return (PAPI_SERVICE_UNAVAILABLE); - case IPP_SERR_VERSION_NOT_SUPPORTED: - return (PAPI_VERSION_NOT_SUPPORTED); - case IPP_SERR_DEVICE_ERROR: - return (PAPI_DEVICE_ERROR); - case IPP_SERR_TEMPORARY_ERROR: - return (PAPI_TEMPORARY_ERROR); - case IPP_SERR_NOT_ACCEPTING: - return (PAPI_NOT_ACCEPTING); - case IPP_SERR_BUSY: - case IPP_SERR_CANCELLED: - default: - return (PAPI_TEMPORARY_ERROR); - } -} - -void -ipp_initialize_request(service_t *svc, papi_attribute_t ***request, - uint16_t operation) -{ - papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, - "version-major", 1); - papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, - "version-minor", 1); - papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, - "request-id", (short)lrand48()); - papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, - "operation-id", operation); -} - -void -ipp_initialize_operational_attributes(service_t *svc, papi_attribute_t ***op, - char *printer, int job_id) -{ - char *charset = "utf-8"; /* default to UTF-8 encoding */ - char *language = setlocale(LC_ALL, ""); - char *user = "nobody"; - struct passwd *pw = NULL; - - /* - * All IPP requests must contain the following: - * attributes-charset (UTF-8) - * attributes-natural-language (our current locale) - * (object identifier) printer-uri/job-id or job-uri - * requesting-user-name (process user or none) - */ - papiAttributeListAddString(op, PAPI_ATTR_EXCL, - "attributes-charset", charset); - - papiAttributeListAddString(op, PAPI_ATTR_EXCL, - "attributes-natural-language", language); - - if (printer != NULL) - ipp_add_printer_uri(svc, printer, op); - - if ((printer != NULL) && (job_id >= 0)) - papiAttributeListAddInteger(op, PAPI_ATTR_EXCL, - "job-id", job_id); - - if ((pw = getpwuid(getuid())) != NULL) - user = pw->pw_name; - /* - * if our euid is 0 "super user", we will allow the system supplied - * user name to be overridden, if the requestor wants to. - */ - if (geteuid() == 0) { - if (svc->user != NULL) - user = svc->user; - } - papiAttributeListAddString(op, PAPI_ATTR_REPLACE, - "requesting-user-name", user); -} - -#ifndef OPID_CUPS_GET_DEFAULT /* for servers that will enumerate */ -#define OPID_CUPS_GET_DEFAULT 0x4001 -#endif /* OPID_CUPS_GET_DEFAULT */ - -static papi_status_t -_default_destination(service_t *svc, char **uri) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - printer_t *p = NULL; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - char *tmp = NULL; - - if ((svc == NULL) || (uri == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* we must be connected to find the default destination */ - if (svc->connection == NULL) - return (PAPI_NOT_POSSIBLE); - - if ((p = calloc(1, sizeof (*p))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - ipp_initialize_request(svc, &request, OPID_CUPS_GET_DEFAULT); - ipp_initialize_operational_attributes(svc, &op, NULL, -1); - papiAttributeListAddString(&op, PAPI_ATTR_APPEND, - "requested-attributes", "printer-uri-supported"); - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - - op = NULL; - papiAttributeListGetCollection(response, NULL, - "printer-attributes-group", &op); - - if (uri != NULL) { - char *tmp = NULL; - - papiAttributeListGetString(op, NULL, "printer-uri", &tmp); - papiAttributeListGetString(op, NULL, - "printer-uri-supported", &tmp); - if (tmp != NULL) - *uri = strdup(tmp); - } - - papiAttributeListFree(response); - - return (result); -} - -static void -ipp_add_printer_uri(service_t *svc, char *name, papi_attribute_t ***op) -{ - char *uri = name; - char buf[BUFSIZ]; - uri_t *tmp = NULL; - - if (strstr(name, "://") == NULL) { /* not in URI form */ - if (strcmp(name, DEFAULT_DEST) != 0) { - /* not the "default" */ - snprintf(buf, sizeof (buf), "%s/%s", svc->name, name); - uri = buf; - } else - _default_destination(svc, &uri); - } - - papiAttributeListAddString(op, PAPI_ATTR_EXCL, "printer-uri", uri); - - /* save the printer-uri's path to be used by http POST request */ - if ((uri_from_string(uri, &tmp) == 0) && (tmp != NULL)) { - if (svc->post != NULL) - free(svc->post); - svc->post = strdup(tmp->path); - uri_free(tmp); - } -} - - -/* - * don't actually write anything, just add to the total size and return the - * size of what would be written, so we can figure out how big the request - * is going to be. - */ -static ssize_t -size_calculate(void *fd, void *buffer, size_t length) -{ - ssize_t *size = (ssize_t *)fd; - - *size += length; - return (length); -} - - -static ssize_t -build_chunk(void *fd, void *buffer, size_t length) -{ - char **s1 = fd; - - memcpy(*s1, buffer, length); - *s1 = *s1 + length; - - return (length); -} - -ssize_t -ipp_request_write(void *fd, void *buffer, size_t length) -{ - service_t *svc = (service_t *)fd; - -#ifdef DEBUG - printf("ipp_request_write(0x%8.8x, 0x%8.8x, %d)\n", fd, buffer, length); - httpDumpData(stdout, "ipp_request_write:", buffer, length); -#endif - return (httpWrite(svc->connection, buffer, length)); -} - -ssize_t -ipp_request_read(void *fd, void *buffer, size_t length) -{ - service_t *svc = (service_t *)fd; - ssize_t rc, i = length; - char *p = buffer; - - while ((rc = httpRead(svc->connection, p, i)) != i) { - if (rc == 0) - return (rc); - if (rc < 0) - return (rc); - i -= rc; - p += rc; - } -#ifdef DEBUG - printf("ipp_request_read(0x%8.8x, 0x%8.8x, %d) = %d\n", - fd, buffer, length, rc); - httpDumpData(stdout, "ipp_request_read:", buffer, length); -#endif - - return (length); -} - -papi_status_t -ipp_send_initial_request_block(service_t *svc, papi_attribute_t **request, - ssize_t file_size) -{ - papi_status_t result = PAPI_OK; - ssize_t chunk_size = 0; - char length[32]; - void *chunk, *ptr; - http_status_t status; - - /* calculate the request size */ - (void) ipp_write_message(&size_calculate, &chunk_size, request); - - /* Fill in the HTTP Header information */ - httpClearFields(svc->connection); - if (svc->transfer_encoding == TRANSFER_ENCODING_CHUNKED) - httpSetField(svc->connection, HTTP_FIELD_TRANSFER_ENCODING, - "chunked"); - else { - sprintf(length, "%lu", (unsigned long)(file_size + chunk_size)); - httpSetField(svc->connection, HTTP_FIELD_CONTENT_LENGTH, - length); - } - httpSetField(svc->connection, HTTP_FIELD_CONTENT_TYPE, - "application/ipp"); - httpSetField(svc->connection, HTTP_FIELD_AUTHORIZATION, - svc->connection->authstring); - - /* flush any state information about this connection */ - httpFlush(svc->connection); - - /* if we have don't have a POST path, use the service uri path */ - if ((svc->post == NULL) && (svc->uri->path)) - svc->post = strdup(svc->uri->path); - /* send the HTTP POST message for the IPP request */ - /* if the POST fails, return the error */ - status = httpPost(svc->connection, svc->post); - if (status != 0) - return (http_to_papi_status(status)); - - if (httpCheck(svc->connection) != 0) { - status = httpUpdate(svc->connection); - if (status != HTTP_OK) - return (http_to_papi_status(status)); - } - - /* build the request chunk */ - chunk = ptr = calloc(1, chunk_size); - result = ipp_write_message(&build_chunk, &ptr, request); -#ifdef DEBUG - printf("request: %d (0x%x) bytes\n", chunk_size, chunk_size); - httpDumpData(stdout, "request:", chunk, chunk_size); -#endif - - /* send the actual IPP request */ - if (ipp_request_write(svc, chunk, chunk_size) != chunk_size) - result = PAPI_TEMPORARY_ERROR; - free(chunk); - - if (httpCheck(svc->connection) != 0) { - status = httpUpdate(svc->connection); - if (status != HTTP_OK) - return (http_to_papi_status(status)); - } - - return (result); -} - -static int -setAuthString(service_t *svc) -{ - http_t *http; - char *user, *passphrase; - char encoded[BUFSIZ]; - - if ((svc == NULL) || (svc->connection == NULL) || (svc->name == NULL)) - return (-1); - - http = svc->connection; - - if (svc->user == NULL) { - struct passwd *p; - - if ((p = getpwuid(getuid())) != NULL) { - user = p->pw_name; - } else if ((user = getenv("LOGNAME")) == NULL) - user = getenv("USER"); - if (user == NULL) - user = "nobody"; - } else - user = svc->user; - - /* if the passphrase is not set, use the Authentication Callback */ - if (((svc->password == NULL) || (svc->password[0] == '\0')) && - (svc->authCB != NULL)) - (svc->authCB)(svc, svc->app_data); - passphrase = svc->password; - - /* if there is still no passphrase, we have to fail */ - if ((passphrase == NULL) || (passphrase[0] == '\0')) - return (-1); - - if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], - "Basic", 5) == 0) { - char plain[BUFSIZ]; - - snprintf(plain, sizeof (plain), "%s:%s", user, passphrase); - httpEncode64(encoded, plain); - snprintf(http->authstring, sizeof (http->authstring), - "Basic %s", encoded); - } else if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], - "Digest", 6) == 0) { - char realm[HTTP_MAX_VALUE]; - char nonce[HTTP_MAX_VALUE]; - char line [BUFSIZ]; - char urp[128]; - char mr[128]; - char *uri = svc->post; - - httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, - "realm", realm); - httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, - "nonce", nonce); - - snprintf(line, sizeof (line), "%s:%s:%s", user, realm, - passphrase); - md5_calc(urp, line, strlen(line)); - - snprintf(line, sizeof (line), "POST:%s", uri); - md5_calc(mr, line, strlen(line)); - - snprintf(line, sizeof (line), "%s:%s:%s", urp, mr, nonce); - md5_calc(encoded, line, strlen(line)); - - snprintf(http->authstring, sizeof (http->authstring), - "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", " - "uri=\"%s\", response=\"%s\"", user, realm, nonce, uri, - encoded); - } - - return (0); -} - -papi_status_t -ipp_status_info(service_t *svc, papi_attribute_t **response) -{ - papi_attribute_t **operational = NULL; - int32_t status = 0; - - papiAttributeListGetCollection(response, NULL, - "operational-attributes-group", &operational); - if (operational != NULL) { - char *message = NULL; - - papiAttributeListGetString(response, NULL, - "status-message", &message); - papiAttributeListAddString(&svc->attributes, PAPI_ATTR_REPLACE, - "detailed-status-message", message); - } - papiAttributeListGetInteger(response, NULL, "status-code", &status); - - return (ipp_to_papi_status(status)); -} - -papi_status_t -ipp_send_request_with_file(service_t *svc, papi_attribute_t **request, - papi_attribute_t ***response, char *file) -{ - papi_status_t result = PAPI_OK; - ssize_t size = 0; - struct stat statbuf; - int fd; - -#ifdef DEBUG - fprintf(stderr, "\nIPP-REQUEST: (%s)", (file ? file : "")); - papiAttributeListPrint(stderr, request, " "); - putc('\n', stderr); - fflush(stderr); -#endif - - /* - * if we are sending a file, open it and include it's size in the - * message size. - */ - if (file != NULL) { - if ((fd = open(file, O_RDONLY)) < 0) { - detailed_error(svc, "%s: %s", file, strerror(errno)); - return (PAPI_DOCUMENT_ACCESS_ERROR); - } else if (strcmp("standard input", file) != 0) { - if (stat(file, &statbuf) < 0) { - detailed_error(svc, - gettext("Cannot access file: %s: %s"), - file, strerror(errno)); - return (PAPI_DOCUMENT_ACCESS_ERROR); - } - if (statbuf.st_size == 0) { - detailed_error(svc, - "Zero byte (empty) file: %s", file); - return (PAPI_BAD_ARGUMENT); - } - } else if (svc->transfer_encoding != - TRANSFER_ENCODING_CHUNKED) { - struct stat st; - - if (fstat(fd, &st) >= 0) - size = st.st_size; - } - } - - *response = NULL; - while (*response == NULL) { - http_status_t status = HTTP_CONTINUE; - - result = ipp_send_initial_request_block(svc, request, size); - - if (result == PAPI_OK) { - if (file != NULL) { - /* send the file contents if we have it */ - int rc; - char buf[BUFSIZ]; - - lseek(fd, 0L, SEEK_SET); - while ((rc = read(fd, buf, sizeof (buf))) > 0) { - if (ipp_request_write(svc, buf, rc) - < rc) { - break; - } - } - } - - (void) ipp_request_write(svc, "", 0); - } - - /* update our connection info */ - while (status == HTTP_CONTINUE) - status = httpUpdate(svc->connection); - - if (status == HTTP_UNAUTHORIZED) { - httpFlush(svc->connection); - if ((svc->connection->authstring[0] == '\0') && - (setAuthString(svc) == 0)) { - httpReconnect(svc->connection); - continue; - } - } else if (status == HTTP_UPGRADE_REQUIRED) { - /* - * If the transport was built with TLS support, we can - * try to use it. - */ - httpFlush(svc->connection); - httpReconnect(svc->connection); - httpEncryption(svc->connection, HTTP_ENCRYPT_REQUIRED); - continue; - } - - if (status != HTTP_OK) - return (http_to_papi_status(status)); - - /* read the IPP response */ - result = ipp_read_message(&ipp_request_read, svc, response, - IPP_TYPE_RESPONSE); - - if (result == PAPI_OK) - result = ipp_status_info(svc, *response); -#ifdef DEBUG - fprintf(stderr, "\nIPP-RESPONSE: (%s) (%s)", (file ? file : ""), - papiStatusString(result)); - papiAttributeListPrint(stderr, *response, " "); - putc('\n', stderr); - fflush(stderr); -#endif - } - - return (result); -} - -papi_status_t -ipp_send_request(service_t *svc, papi_attribute_t **request, - papi_attribute_t ***response) -{ - return (ipp_send_request_with_file(svc, request, response, NULL)); -} diff --git a/usr/src/lib/print/libpapi-ipp/common/job.c b/usr/src/lib/print/libpapi-ipp/common/job.c deleted file mode 100644 index 65575d44db..0000000000 --- a/usr/src/lib/print/libpapi-ipp/common/job.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: job.c 148 2006-04-25 16:54:17Z njacobs $ */ - - -/*LINTLIBRARY*/ - -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <papi_impl.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <libintl.h> - -#ifndef OPID_CUPS_MOVE_JOB -#define OPID_CUPS_MOVE_JOB 0x400D -#endif - -void -papiJobFree(papi_job_t job) -{ - job_t *tmp = (job_t *)job; - - if (tmp != NULL) { - if (tmp->attributes != NULL) - papiAttributeListFree(tmp->attributes); - free(tmp); - } -} - -void -papiJobListFree(papi_job_t *jobs) -{ - if (jobs != NULL) { - int i; - - for (i = 0; jobs[i] != NULL; i++) - papiJobFree(jobs[i]); - free(jobs); - } -} - -papi_attribute_t ** -papiJobGetAttributeList(papi_job_t job) -{ - papi_attribute_t **result = NULL; - job_t *j = job; - - if (j != NULL) - result = j->attributes; - - return (result); -} - -char * -papiJobGetPrinterName(papi_job_t job) -{ - char *result = NULL; - job_t *j = job; - - if (j != NULL) - (void) papiAttributeListGetString(j->attributes, NULL, - "printer-name", &result); - - return (result); -} - -int32_t -papiJobGetId(papi_job_t job) -{ - int32_t result = -1; - job_t *j = job; - - if (j != NULL) - (void) papiAttributeListGetInteger(j->attributes, NULL, - "job-id", &result); - - return (result); -} - -papi_job_ticket_t * -papiJobGetJobTicket(papi_job_t job) -{ - papi_job_ticket_t *result = NULL; - - return (result); -} - -static void -populate_job_request(service_t *svc, papi_attribute_t ***request, - papi_attribute_t **attributes, char *printer, uint16_t type) -{ - papi_attribute_t **operational = NULL, **job = NULL; - static char *operational_names[] = { - "job-name", "ipp-attribute-fidelity", "document-name", - "compression", "document-format", "document-natural-language", - "job-k-octets", "job-impressions", "job-media-sheets", NULL - }; - - /* create the base IPP request */ - ipp_initialize_request(svc, request, type); - - /* create an operational attributes group */ - ipp_initialize_operational_attributes(svc, &operational, printer, -1); - - /* split up the attributes into operational and job attributes */ - split_and_copy_attributes(operational_names, attributes, - &operational, &job); - - /* add the operational attributes group to the request */ - papiAttributeListAddCollection(request, PAPI_ATTR_REPLACE, - "operational-attributes-group", operational); - papiAttributeListFree(operational); - - /* add the job attributes group to the request */ - if (job != NULL) { - /* - * Add job-originating-host-name to attributes - * if not already set. - */ - char *hostname = NULL; - - papiAttributeListGetString(job, NULL, - "job-originating-host-name", &hostname); - - if (hostname == NULL) { - char host[BUFSIZ]; - - if (gethostname(host, sizeof (host)) == 0) - papiAttributeListAddString(&job, PAPI_ATTR_EXCL, - "job-originating-host-name", host); - } - - papiAttributeListAddCollection(request, PAPI_ATTR_REPLACE, - "job-attributes-group", job); - papiAttributeListFree(job); - } -} - -static papi_status_t -send_document_uri(service_t *svc, char *file, papi_attribute_t **attributes, - char *printer, int32_t id, char last, uint16_t type) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - - /* create the base IPP request */ - ipp_initialize_request(svc, &request, type); - - /* create an operational attributes group */ - ipp_initialize_operational_attributes(svc, &op, printer, id); - - papiAttributeListAddString(&op, PAPI_ATTR_REPLACE, "document-name", - file); - papiAttributeListAddBoolean(&op, PAPI_ATTR_REPLACE, "last-document", - (last ? PAPI_TRUE : PAPI_FALSE)); - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - - /* send the IPP request to the server */ - result = ipp_send_request_with_file(svc, request, &response, file); - papiAttributeListFree(request); - papiAttributeListFree(response); - - return (result); -} - -typedef enum {_WITH_DATA, _BY_REFERENCE, _VALIDATE} call_type_t; - -papi_status_t -internal_job_submit(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, - char **files, papi_job_t *job, - call_type_t call_type) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - struct stat statbuf; - job_t *j = NULL; - int i; - uint16_t req_type = OPID_PRINT_JOB; - uint16_t data_type = OPID_SEND_DOCUMENT; - papi_attribute_t **request = NULL, **response = NULL; - - if ((svc == NULL) || (printer == NULL) || (job == NULL)) - return (PAPI_BAD_ARGUMENT); - - switch (call_type) { - case _BY_REFERENCE: -#ifdef SOME_DAY_WE_WILL_BE_ABLE_TO_USE_URIS_FOR_JOB_DATA - /* - * For the time being, this is disabled. There are a number - * of issues to be dealt with before we can send a URI - * across the network to the server. For example, the file - * name(s) passed in are most likely relative to the current - * hosts filesystem. They also most likely will require some - * form of authentication information to be passed with the - * URI. - */ - req_type = OPID_PRINT_URI; - req_type = OPID_SEND_URI; -#endif - /* fall-through */ - case _WITH_DATA: - if ((files == NULL) || (files[0] == NULL)) - return (PAPI_BAD_ARGUMENT); - - if (files[1] != NULL) /* more than 1 file */ - req_type = OPID_CREATE_JOB; - - break; - case _VALIDATE: - req_type = OPID_VALIDATE_JOB; - /* if we have files, validate access to them */ - if (files != NULL) { - for (i = 0; files[i] != NULL; i++) { - if (access(files[i], R_OK) < 0) { - detailed_error(svc, "%s: %s", files[i], - strerror(errno)); - return (PAPI_DOCUMENT_ACCESS_ERROR); - } - - if (strcmp("standard input", files[i]) != 0) { - if (stat(files[i], &statbuf) < 0) { - detailed_error(svc, gettext( - "Cannot access file: %s:" - " %s"), files[i], - strerror(errno)); - return ( - PAPI_DOCUMENT_ACCESS_ERROR); - } - if (statbuf.st_size == 0) { - detailed_error(svc, - "Zero byte (empty) file: " - "%s", - files[i]); - return (PAPI_BAD_ARGUMENT); - } - } - } - files = NULL; - } - break; - } - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - if ((*job = j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - /* - * before creating IPP request - * add the job-name - */ - if ((files != NULL) && (files[0] != NULL)) - papiAttributeListAddString(&job_attributes, PAPI_ATTR_EXCL, - "job-name", files[0]); - - /* create IPP request */ - populate_job_request(svc, &request, job_attributes, printer, req_type); - - switch (req_type) { - case OPID_PRINT_JOB: - result = ipp_send_request_with_file(svc, request, &response, - files[0]); - break; - case OPID_CREATE_JOB: - case OPID_VALIDATE_JOB: - case OPID_PRINT_URI: - result = ipp_send_request(svc, request, &response); - break; - } - papiAttributeListFree(request); - - if (result == PAPI_OK) { - papi_attribute_t **op = NULL; - - /* retrieve the job attributes */ - papiAttributeListGetCollection(response, NULL, - "job-attributes-group", &op); - copy_attributes(&j->attributes, op); - - if (req_type == OPID_CREATE_JOB) { - int32_t id = 0; - - papiAttributeListGetInteger(j->attributes, NULL, - "job-id", &id); - /* send each document */ - for (i = 0; ((result == PAPI_OK) && (files[i] != NULL)); - i++) - result = send_document_uri(svc, files[i], - job_attributes, - printer, id, (files[i+1]?0:1), - data_type); - } - } - papiAttributeListFree(response); - - return (result); -} - -papi_status_t -papiJobSubmit(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) -{ - return (internal_job_submit(handle, printer, job_attributes, - job_ticket, files, job, _WITH_DATA)); -} - -papi_status_t -papiJobSubmitByReference(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) -{ - return (internal_job_submit(handle, printer, job_attributes, - job_ticket, files, job, _BY_REFERENCE)); -} - -papi_status_t -papiJobValidate(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) -{ - return (internal_job_submit(handle, printer, job_attributes, - job_ticket, files, job, _VALIDATE)); -} - -papi_status_t -papiJobStreamOpen(papi_service_t handle, char *printer, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, papi_stream_t *stream) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - papi_attribute_t **request = NULL; - service_t *svc = handle; - - if ((svc == NULL) || (printer == NULL) || (stream == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - papiAttributeListAddString(&job_attributes, PAPI_ATTR_EXCL, - "job-name", "standard input"); - - /* create job request */ - populate_job_request(svc, &request, job_attributes, printer, - OPID_PRINT_JOB); - - *stream = svc->connection; - - result = ipp_send_initial_request_block(svc, request, 0); - papiAttributeListFree(request); - - return (result); -} - -papi_status_t -papiJobStreamWrite(papi_service_t handle, - papi_stream_t stream, void *buffer, size_t buflen) -{ - papi_status_t result = PAPI_OK; - service_t *svc = handle; - size_t rc; - -#ifdef DEBUG - printf("papiJobStreamWrite(0x%8.8x, 0x%8.8x, 0x%8.8x, %d)\n", - handle, stream, buffer, buflen); - httpDumpData(stdout, "papiJobStreamWrite:", buffer, buflen); -#endif - - if ((svc == NULL) || (stream == NULL) || (buffer == NULL) || - (buflen == 0)) - return (PAPI_BAD_ARGUMENT); - - while ((result == PAPI_OK) && (buflen > 0)) { - rc = ipp_request_write(svc, buffer, buflen); - if (rc < 0) - result = PAPI_TEMPORARY_ERROR; - else { - buffer = (char *)buffer + rc; - buflen -= rc; - } - } - -#ifdef DEBUG - printf("papiJobStreamWrite(): %s\n", papiStatusString(result)); -#endif - - return (result); -} - -papi_status_t -papiJobStreamClose(papi_service_t handle, - papi_stream_t stream, papi_job_t *job) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - http_status_t status = HTTP_CONTINUE; - service_t *svc = handle; - papi_attribute_t **response = NULL; - job_t *j = NULL; - - if ((svc == NULL) || (stream == NULL) || (job == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((*job = j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - (void) ipp_request_write(svc, "", 0); - - /* update our connection info */ - while (status == HTTP_CONTINUE) - status = httpUpdate(svc->connection); - - if (status != HTTP_OK) - return (http_to_papi_status(status)); - httpWait(svc->connection, 1000); - - /* read the IPP response */ - result = ipp_read_message(&ipp_request_read, svc, &response, - IPP_TYPE_RESPONSE); - if (result == PAPI_OK) - result = ipp_status_info(svc, response); - - if (result == PAPI_OK) { - papi_attribute_t **op = NULL; - - papiAttributeListGetCollection(response, NULL, - "job-attributes-group", &op); - copy_attributes(&j->attributes, op); - } - papiAttributeListFree(response); - - return (result); -} - -papi_status_t -papiJobQuery(papi_service_t handle, char *printer, int32_t job_id, - char **requested_attrs, - papi_job_t *job) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - job_t *j = NULL; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - - if ((svc == NULL) || (printer == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - if ((*job = j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - ipp_initialize_request(svc, &request, OPID_GET_JOB_ATTRIBUTES); - - ipp_initialize_operational_attributes(svc, &op, printer, job_id); - - if (requested_attrs != NULL) { - int i; - - for (i = 0; requested_attrs[i] != NULL; i++) - papiAttributeListAddString(&op, PAPI_ATTR_APPEND, - "requested-attributes", requested_attrs[i]); - } - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - - op = NULL; - papiAttributeListGetCollection(response, NULL, - "job-attributes-group", &op); - copy_attributes(&j->attributes, op); - papiAttributeListFree(response); - - return (result); -} - -/* papiJob{Cancel|Hold|Release|Restart|Promote} are all the same */ -static papi_status_t -_job_cancel_hold_release_restart_promote(papi_service_t handle, - char *printer, int32_t job_id, uint16_t type) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - - if ((svc == NULL) || (printer == NULL) || (job_id < 0)) - return (PAPI_BAD_ARGUMENT); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - ipp_initialize_request(svc, &request, type); - - ipp_initialize_operational_attributes(svc, &op, printer, job_id); - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - papiAttributeListFree(response); - - return (result); -} - -papi_status_t -papiJobCancel(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_job_cancel_hold_release_restart_promote(handle, printer, - job_id, OPID_CANCEL_JOB)); -} - - -papi_status_t -papiJobHold(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_job_cancel_hold_release_restart_promote(handle, printer, - job_id, OPID_HOLD_JOB)); -} - -papi_status_t -papiJobRelease(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_job_cancel_hold_release_restart_promote(handle, printer, - job_id, OPID_RELEASE_JOB)); -} - -papi_status_t -papiJobRestart(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_job_cancel_hold_release_restart_promote(handle, printer, - job_id, OPID_RESTART_JOB)); -} - -papi_status_t -papiJobPromote(papi_service_t handle, char *printer, int32_t job_id) -{ - return (_job_cancel_hold_release_restart_promote(handle, printer, - job_id, OPID_PROMOTE_JOB)); -} - -papi_status_t -papiJobMove(papi_service_t handle, char *printer, int32_t job_id, - char *destination) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - - if ((svc == NULL) || (printer == NULL) || (job_id < 0) || - (destination == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - ipp_initialize_request(svc, &request, OPID_CUPS_MOVE_JOB); - - ipp_initialize_operational_attributes(svc, &op, printer, job_id); - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - - op = NULL; - papiAttributeListAddString(&op, PAPI_ATTR_EXCL, - "job-printer-uri", destination); - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "job-attributes-group", op); - papiAttributeListFree(op); - - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - papiAttributeListFree(response); - - return (result); -} - -papi_status_t -papiJobModify(papi_service_t handle, char *printer, int32_t job_id, - papi_attribute_t **attributes, papi_job_t *job) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - job_t *j = NULL; - - if ((svc == NULL) || (printer == NULL) || (job_id < 0) || - (attributes == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((*job = j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, printer)) != PAPI_OK) - return (result); - - ipp_initialize_request(svc, &request, OPID_SET_JOB_ATTRIBUTES); - - ipp_initialize_operational_attributes(svc, &op, printer, job_id); - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "job-attributes-group", attributes); - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - - op = NULL; - papiAttributeListGetCollection(response, NULL, - "job-attributes-group", &op); - copy_attributes(&j->attributes, op); - papiAttributeListFree(response); - - return (result); -} diff --git a/usr/src/lib/print/libpapi-ipp/common/mapfile b/usr/src/lib/print/libpapi-ipp/common/mapfile deleted file mode 100644 index 847a5bb76f..0000000000 --- a/usr/src/lib/print/libpapi-ipp/common/mapfile +++ /dev/null @@ -1,292 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# $Id: mapfile.in,v 1.2 2006/03/02 06:31:36 njacobs Exp $ -# - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -$mapfile_version 2 - -# -# Common interfaces that are most likely to be shared amongst the various -# PAPI implementations. -# - -SYMBOL_VERSION SUNW_1.0 { - global: - # PAPI Attribute Calls - papiAttributeListAddValue { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddBoolean { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddCollection { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddDatetime { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddInteger { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddMetadata { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddRange { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddResolution { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListDelete { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetValue { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetNext { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListFind { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetBoolean { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetCollection { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetDatetime { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetInteger { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetMetadata { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetRange { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetResolution { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListFromString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListToString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListFree { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - # PAPI Service Calls - papiServiceCreate ; - papiServiceDestroy ; - papiServiceSetUserName ; - papiServiceSetPassword ; - papiServiceSetEncryption ; - papiServiceSetAuthCB ; - papiServiceSetAppData ; - papiServiceGetUserName ; - papiServiceGetPassword ; - papiServiceGetEncryption ; - papiServiceGetAppData ; - papiServiceGetServiceName ; - papiServiceGetAttributeList ; - papiServiceGetStatusMessage ; - - # PAPI Printer Calls - papiPrintersList ; - papiPrinterQuery ; - papiPrinterAdd ; - papiPrinterModify ; - papiPrinterRemove ; - papiPrinterDisable ; - papiPrinterEnable ; - papiPrinterPause ; - papiPrinterResume ; - papiPrinterPurgeJobs ; - papiPrinterListJobs ; - papiPrinterGetAttributeList ; - papiPrinterFree ; - papiPrinterListFree ; - - # PAPI Job Calls - papiJobSubmit ; - papiJobSubmitByReference ; - papiJobValidate ; - papiJobStreamOpen ; - papiJobStreamWrite ; - papiJobStreamClose ; - papiJobQuery ; - papiJobModify ; - papiJobMove ; - papiJobCancel ; - papiJobHold ; - papiJobRelease ; - papiJobRestart ; - papiJobPromote ; - papiJobGetAttributeList ; - papiJobGetPrinterName ; - papiJobGetId ; - papiJobGetJobTicket ; - papiJobFree ; - papiJobListFree ; - - # Misc. PAPI Calls - papiStatusString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiLibrarySupportedCall { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiLibrarySupportedCalls { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; -} ; - -SYMBOL_VERSION SUNWprivate_1.0 { - global: - papiServiceSetPeer { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobCreate { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobStreamAdd { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobCommit { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - # Misc. supporting calls - # URI - uri_from_string { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - uri_to_string { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - uri_free { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - # list - list_remove { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - list_append { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - list_concatenate { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - # NS - getprinterbyname { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - is_localhost { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - # extra Attribute Calls - copy_attributes { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - split_and_copy_attributes { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListPrint { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - local: - * ; -} ; diff --git a/usr/src/lib/print/libpapi-ipp/common/papi_impl.h b/usr/src/lib/print/libpapi-ipp/common/papi_impl.h deleted file mode 100644 index c7048665a8..0000000000 --- a/usr/src/lib/print/libpapi-ipp/common/papi_impl.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -#ifndef _PAPI_IMPL_H -#define _PAPI_IMPL_H - -/* $Id: papi_impl.h 161 2006-05-03 04:32:59Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <papi.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#include <time.h> -#include <sys/types.h> -#include <stdarg.h> -#include <uri.h> - -#include <http.h> -#include <ipp.h> - -/* - * Implementation specific types/prototypes/definitions follow - * - * - * Ex: - */ -typedef enum { - TRANSFER_ENCODING_CHUNKED, - TRANSFER_ENCODING_LENGTH -} http_transfer_encoding_t; - -typedef struct { - papi_attribute_t **attributes; - char *name; - char *user; - char *password; - int (*authCB)(papi_service_t svc, void *app_data); - papi_encryption_t encryption; - void *app_data; - uri_t *uri; - char *post; - http_t *connection; - http_transfer_encoding_t transfer_encoding; -} service_t; - -typedef struct job { - papi_attribute_t **attributes; -} job_t; - -typedef struct { - papi_attribute_t **attributes; -} printer_t; - -/* IPP glue interfaces */ -extern ssize_t ipp_request_read(void *fd, void *buffer, size_t length); -extern ssize_t ipp_request_write(void *fd, void *buffer, size_t length); -extern papi_status_t ipp_send_request(service_t *svc, - papi_attribute_t **request, - papi_attribute_t ***response); -extern papi_status_t ipp_send_request_with_file(service_t *svc, - papi_attribute_t **request, - papi_attribute_t ***response, char *file); -extern papi_status_t ipp_send_initial_request_block(service_t *svc, - papi_attribute_t **request, ssize_t file_size); -extern papi_status_t ipp_status_info(service_t *svc, - papi_attribute_t **response); -extern void ipp_initialize_request(service_t *svc, - papi_attribute_t ***request, uint16_t type); -extern void ipp_initialize_operational_attributes(service_t *svc, - papi_attribute_t ***op, - char *printer, int job_id); -extern papi_status_t ipp_to_papi_status(uint16_t status); -extern papi_status_t http_to_papi_status(http_status_t status); - -/* service related interfaces */ -extern void detailed_error(service_t *svc, char *fmt, ...); -extern papi_status_t service_connect(service_t *svc, char *service_name); - -#ifdef __cplusplus -} -#endif - -#endif /* _PAPI_IMPL_H */ diff --git a/usr/src/lib/print/libpapi-ipp/common/printer.c b/usr/src/lib/print/libpapi-ipp/common/printer.c deleted file mode 100644 index c49c4adb03..0000000000 --- a/usr/src/lib/print/libpapi-ipp/common/printer.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: printer.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdlib.h> -#include <papi_impl.h> - -#include <config-site.h> - -void -papiPrinterFree(papi_printer_t printer) -{ - printer_t *tmp = printer; - - if (tmp != NULL) { - if (tmp->attributes != NULL) - papiAttributeListFree(tmp->attributes); - free(tmp); - } -} - -void -papiPrinterListFree(papi_printer_t *printers) -{ - if (printers != NULL) { - int i; - - for (i = 0; printers[i] != NULL; i++) - papiPrinterFree(printers[i]); - free(printers); - } -} - -/* - * Enumeration of printers is not part of the IPP specification, so many - * servers will probably not respond back with a list of printers, but - * CUPS has implemented an extension to IPP to enumerate printers and - * classes. the Apache/mod_ipp IPP listener module available in Solaris - * implements this IPP extension, so CUPS and Solaris can provide this - * to IPP clients. - */ -#ifndef OPID_CUPS_GET_PRINTERS /* for servers that will enumerate */ -#define OPID_CUPS_GET_PRINTERS 0x4002 -#endif /* OPID_CUPS_GET_PRINTERS */ -#ifndef OPID_CUPS_DELETE_PRINTER /* for servers that can delete */ -#define OPID_CUPS_DELETE_PRINTER 0x4004 -#endif /* OPID_CUPS_DELETE_PRINTER */ -#ifndef OPID_CUPS_GET_CLASSES /* for servers that will enumerate */ -#define OPID_CUPS_GET_CLASSES 0x4005 -#endif /* OPID_CUPS_GET_CLASSES */ - -papi_status_t -papiPrintersList(papi_service_t handle, char **requested_attrs, - papi_filter_t *filter, papi_printer_t **printers) -{ - papi_status_t status, result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - void *iter = NULL; - - if ((svc == NULL) || (printers == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, DEFAULT_DEST)) != PAPI_OK) - return (result); - ipp_initialize_request(svc, &request, OPID_CUPS_GET_PRINTERS); - - ipp_initialize_operational_attributes(svc, &op, NULL, -1); - - if (requested_attrs != NULL) { - int i; - - for (i = 0; requested_attrs[i] != NULL; i++) - papiAttributeListAddString(&op, PAPI_ATTR_APPEND, - "requested-attributes", requested_attrs[i]); - } - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - - op = NULL; - for (status = papiAttributeListGetCollection(response, &iter, - "printer-attributes-group", &op); - status == PAPI_OK; - status = papiAttributeListGetCollection(response, &iter, - NULL, &op)) { - printer_t *p = NULL; - - if ((p = calloc(1, sizeof (*p))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - copy_attributes(&p->attributes, op); - op = NULL; - list_append(printers, p); - } - papiAttributeListFree(response); - - return (result); -} - -papi_status_t -papiPrinterQuery(papi_service_t handle, char *name, - char **requested_attrs, - papi_attribute_t **job_attributes, - papi_printer_t *printer) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - printer_t *p = NULL; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - - if ((svc == NULL) || (name == NULL) || (printer == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - if ((*printer = p = calloc(1, sizeof (*p))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - ipp_initialize_request(svc, &request, OPID_GET_PRINTER_ATTRIBUTES); - - ipp_initialize_operational_attributes(svc, &op, name, -1); - - if (requested_attrs != NULL) { - int i; - - for (i = 0; requested_attrs[i] != NULL; i++) - papiAttributeListAddString(&op, PAPI_ATTR_APPEND, - "requested-attributes", requested_attrs[i]); - } - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - - op = NULL; - papiAttributeListGetCollection(response, NULL, - "printer-attributes-group", &op); - copy_attributes(&p->attributes, op); - papiAttributeListFree(response); - - return (result); -} - -static papi_status_t -_printer_enable_disable_pause_resume_delete(papi_service_t handle, char *name, - char *message, uint16_t type) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - - if ((svc == NULL) || (name == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - ipp_initialize_request(svc, &request, type); - - ipp_initialize_operational_attributes(svc, &op, name, -1); - - switch (type) { - case OPID_DISABLE_PRINTER: - papiAttributeListAddString(&op, PAPI_ATTR_REPLACE, - "printer-message-from-operator", message); - break; - case OPID_PAUSE_PRINTER: - papiAttributeListAddString(&op, PAPI_ATTR_REPLACE, - "printer-state-message", message); - break; - default: /* a message value is of no use */ - break; - } - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - papiAttributeListFree(response); - - return (result); -} - -papi_status_t -papiPrinterEnable(papi_service_t handle, char *name) -{ - return (_printer_enable_disable_pause_resume_delete(handle, name, - NULL, OPID_ENABLE_PRINTER)); -} - -papi_status_t -papiPrinterResume(papi_service_t handle, char *name) -{ - return (_printer_enable_disable_pause_resume_delete(handle, name, - NULL, OPID_RESUME_PRINTER)); -} - -papi_status_t -papiPrinterPause(papi_service_t handle, char *name, char *message) -{ - return (_printer_enable_disable_pause_resume_delete(handle, name, - message, OPID_PAUSE_PRINTER)); -} - -papi_status_t -papiPrinterDisable(papi_service_t handle, char *name, char *message) -{ - return (_printer_enable_disable_pause_resume_delete(handle, name, - message, OPID_PAUSE_PRINTER)); -} - -/* - * there is no IPP create operation, the set-printer-attibutes operation - * is the closest we have, so we will assume that the server will create - * a printer and set attributes if there is none. - */ -papi_status_t -papiPrinterAdd(papi_service_t handle, char *name, - papi_attribute_t **attributes, papi_printer_t *printer) -{ - return (papiPrinterModify(handle, name, attributes, printer)); -} - -papi_status_t -papiPrinterModify(papi_service_t handle, char *name, - papi_attribute_t **attributes, papi_printer_t *printer) -{ - papi_status_t result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - printer_t *p = NULL; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - - if ((svc == NULL) || (name == NULL) || (printer == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - if ((*printer = p = calloc(1, sizeof (*p))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - ipp_initialize_request(svc, &request, OPID_SET_PRINTER_ATTRIBUTES); - - ipp_initialize_operational_attributes(svc, &op, name, -1); - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "printer-attributes-group", attributes); - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - - op = NULL; - papiAttributeListGetCollection(response, NULL, - "printer-attributes-group", &op); - copy_attributes(&p->attributes, op); - papiAttributeListFree(response); - - return (result); -} - -papi_status_t -papiPrinterRemove(papi_service_t handle, char *name) -{ - return (_printer_enable_disable_pause_resume_delete(handle, name, - NULL, OPID_CUPS_DELETE_PRINTER)); -} - -papi_status_t -papiPrinterPurgeJobs(papi_service_t handle, char *name, - papi_job_t **jobs) -{ - papi_status_t status, result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - void *iter = NULL; - - - if ((svc == NULL) || (name == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - ipp_initialize_request(svc, &request, OPID_PURGE_JOBS); - - ipp_initialize_operational_attributes(svc, &op, name, -1); - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - - op = NULL; - for (status = papiAttributeListGetCollection(response, &iter, - "job-attributes-group", &op); - status == PAPI_OK; - status = papiAttributeListGetCollection(response, &iter, - NULL, &op)) { - job_t *j = NULL; - - if ((j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - copy_attributes(&j->attributes, op); - op = NULL; - list_append(jobs, j); - } - papiAttributeListFree(response); - - return (result); -} - -papi_status_t -papiPrinterListJobs(papi_service_t handle, char *name, - char **requested_attrs, int type_mask, - int max_num_jobs, papi_job_t **jobs) -{ - papi_status_t status, result = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - papi_attribute_t **request = NULL, **op = NULL, **response = NULL; - void *iter = NULL; - - if ((svc == NULL) || (name == NULL)) - return (PAPI_BAD_ARGUMENT); - - /* if we are already connected, use that connection. */ - if (svc->connection == NULL) - if ((result = service_connect(svc, name)) != PAPI_OK) - return (result); - - ipp_initialize_request(svc, &request, OPID_GET_JOBS); - - ipp_initialize_operational_attributes(svc, &op, name, -1); - - if (requested_attrs != NULL) { - int i; - - for (i = 0; requested_attrs[i] != NULL; i++) - papiAttributeListAddString(&op, PAPI_ATTR_APPEND, - "requested-attributes", requested_attrs[i]); - } - - papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, - "operational-attributes-group", op); - papiAttributeListFree(op); - result = ipp_send_request(svc, request, &response); - papiAttributeListFree(request); - - op = NULL; - for (status = papiAttributeListGetCollection(response, &iter, - "job-attributes-group", &op); - status == PAPI_OK; - status = papiAttributeListGetCollection(response, &iter, - NULL, &op)) { - job_t *j = NULL; - - if ((j = calloc(1, sizeof (*j))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - copy_attributes(&j->attributes, op); - op = NULL; - list_append(jobs, j); - } - papiAttributeListFree(response); - - return (result); -} - -papi_attribute_t ** -papiPrinterGetAttributeList(papi_printer_t printer) -{ - papi_attribute_t **result = NULL; - printer_t *p = printer; - - if (p != NULL) - result = p->attributes; - - return (result); -} diff --git a/usr/src/lib/print/libpapi-ipp/common/service.c b/usr/src/lib/print/libpapi-ipp/common/service.c deleted file mode 100644 index e5531f1422..0000000000 --- a/usr/src/lib/print/libpapi-ipp/common/service.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: service.c 171 2006-05-20 06:00:32Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <alloca.h> -#include <libintl.h> -#include <papi_impl.h> - -#include <config-site.h> - -http_encryption_t -http_encryption_type(papi_encryption_t encryption) -{ - switch (encryption) { - case PAPI_ENCRYPT_IF_REQUESTED: - return (HTTP_ENCRYPT_IF_REQUESTED); - case PAPI_ENCRYPT_REQUIRED: - return (HTTP_ENCRYPT_REQUIRED); - case PAPI_ENCRYPT_ALWAYS: - return (HTTP_ENCRYPT_ALWAYS); - case PAPI_ENCRYPT_NEVER: - return (HTTP_ENCRYPT_NEVER); - default: - ; /* this should log an error */ - } - - return (HTTP_ENCRYPT_NEVER); /* should never get here */ -} - -papi_status_t -service_connect(service_t *svc, char *service_name) -{ - papi_status_t result = PAPI_OK; - int port = 631; - - if (svc == NULL) - return (PAPI_BAD_ARGUMENT); - - if (svc->connection != NULL) /* alread connected ? */ - return (PAPI_OK); - - if (svc->uri == NULL) - uri_from_string(service_name, &svc->uri); - - if ((service_name != NULL) && (svc->uri == NULL)) { - /* - * a name was supplied and it's not in URI form, we will - * try to use a "default" IPP service under the assumption - * that this is most likely a short-form printer name from - * from a papiPrinter*() or papiJob*() call and not from a - * papiServiceCreate() call. - */ - if ((service_name = getenv("PAPI_SERVICE_URI")) == NULL) { - char *cups; - - if ((cups = getenv("CUPS_SERVER")) != NULL) { - char buf[BUFSIZ]; - - snprintf(buf, sizeof (buf), - "ipp://%s/printers/", cups); - service_name = strdup(buf); - } - } - if (service_name == NULL) - service_name = DEFAULT_IPP_SERVICE_URI; - - uri_from_string(service_name, &svc->uri); - } - - if (svc->uri == NULL) - return (PAPI_NOT_POSSIBLE); - - if (svc->uri->port != NULL) - port = strtol(svc->uri->port, NULL, 10); - - svc->connection = httpConnectEncrypt(svc->uri->host, port, - http_encryption_type(svc->encryption)); - if (svc->connection == NULL) { - if (svc->uri != NULL) { - uri_free(svc->uri); - svc->uri = NULL; - } - result = PAPI_SERVICE_UNAVAILABLE; - } else if (service_name != NULL) - svc->name = strdup(service_name); - - return (result); -} - -papi_status_t -papiServiceCreate(papi_service_t *handle, char *service_name, - char *user_name, char *password, - int (*authCB)(papi_service_t svc, void *app_data), - papi_encryption_t encryption, void *app_data) -{ - papi_status_t result = PAPI_NOT_POSSIBLE; - service_t *svc = NULL; - char *encoding = getenv("HTTP_TRANSFER_ENCODING"); - - if (handle == NULL) - return (PAPI_BAD_ARGUMENT); - - if ((*handle = svc = calloc(1, sizeof (*svc))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - if (user_name != NULL) - svc->user = strdup(user_name); - - if (password != NULL) - svc->password = strdup(password); - - svc->encryption = encryption; - - if (authCB != NULL) - svc->authCB = authCB; - - if (app_data != NULL) - svc->app_data = app_data; - - if ((encoding != NULL) && (strcasecmp(encoding, "content-length") == 0)) - svc->transfer_encoding = TRANSFER_ENCODING_LENGTH; - else - svc->transfer_encoding = TRANSFER_ENCODING_CHUNKED; - - if (service_name != NULL) { - result = service_connect(svc, service_name); - } else - result = PAPI_OK; - - return (result); -} - -void -papiServiceDestroy(papi_service_t handle) -{ - if (handle != NULL) { - service_t *svc = handle; - - if (svc->attributes != NULL) - papiAttributeListFree(svc->attributes); - if (svc->name != NULL) - free(svc->name); - if (svc->user != NULL) - free(svc->user); - if (svc->password != NULL) - free(svc->password); - if (svc->uri != NULL) - uri_free(svc->uri); - if (svc->post != NULL) - free(svc->post); - if (svc->connection != NULL) - httpClose(svc->connection); - - free(handle); - } -} - -papi_status_t -papiServiceSetUserName(papi_service_t handle, char *user_name) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - - if (svc->user != NULL) - free(svc->user); - svc->user = NULL; - if (user_name != NULL) - svc->user = strdup(user_name); - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - -papi_status_t -papiServiceSetPassword(papi_service_t handle, char *password) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - - if (svc->password != NULL) - free(svc->password); - svc->password = NULL; - if (password != NULL) - svc->password = strdup(password); - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - -papi_status_t -papiServiceSetEncryption(papi_service_t handle, - papi_encryption_t encryption) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - - svc->encryption = encryption; - httpEncryption(svc->connection, - (http_encryption_t)svc->encryption); - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - -papi_status_t -papiServiceSetAuthCB(papi_service_t handle, - int (*authCB)(papi_service_t svc, void *app_data)) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - - svc->authCB = authCB; - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - - -papi_status_t -papiServiceSetAppData(papi_service_t handle, void *app_data) -{ - papi_status_t result = PAPI_OK; - - if (handle != NULL) { - service_t *svc = handle; - - svc->app_data = (void *)app_data; - } else - result = PAPI_BAD_ARGUMENT; - - return (result); -} - -char * -papiServiceGetServiceName(papi_service_t handle) -{ - char *result = NULL; - - if (handle != NULL) { - service_t *svc = handle; - - result = svc->name; - } - - return (result); -} - -char * -papiServiceGetUserName(papi_service_t handle) -{ - char *result = NULL; - - if (handle != NULL) { - service_t *svc = handle; - - result = svc->user; - } - - return (result); -} - -char * -papiServiceGetPassword(papi_service_t handle) -{ - char *result = NULL; - - if (handle != NULL) { - service_t *svc = handle; - - result = svc->password; - } - - return (result); -} - -papi_encryption_t -papiServiceGetEncryption(papi_service_t handle) -{ - papi_encryption_t result = PAPI_ENCRYPT_NEVER; - - if (handle != NULL) { - service_t *svc = handle; - - result = svc->encryption; - } - - return (result); -} - -void * -papiServiceGetAppData(papi_service_t handle) -{ - void *result = NULL; - - if (handle != NULL) { - service_t *svc = handle; - - result = svc->app_data; - } - - return (result); -} - -papi_attribute_t ** -papiServiceGetAttributeList(papi_service_t handle) -{ - papi_attribute_t **result = NULL; - service_t *svc = handle; - - if (handle != NULL) - result = svc->attributes; - - return (result); -} - -char * -papiServiceGetStatusMessage(papi_service_t handle) -{ - char *result = NULL; - service_t *svc = handle; - - papiAttributeListGetString(svc->attributes, NULL, - "detailed-status-message", &result); - - return (result); -} - -void -detailed_error(service_t *svc, char *fmt, ...) -{ - if ((svc != NULL) && (fmt != NULL)) { - va_list ap; - size_t size; - char *message = alloca(BUFSIZ); - - va_start(ap, fmt); - /* - * fill in the message. If the buffer is too small, allocate - * one that is large enough and fill it in. - */ - if ((size = vsnprintf(message, BUFSIZ, fmt, ap)) >= BUFSIZ) - if ((message = alloca(size)) != NULL) - vsnprintf(message, size, fmt, ap); - va_end(ap); - - papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND, - "detailed-status-message", message); - } -} diff --git a/usr/src/lib/print/libpapi-ipp/i386/Makefile b/usr/src/lib/print/libpapi-ipp/i386/Makefile deleted file mode 100644 index 39b4a998ec..0000000000 --- a/usr/src/lib/print/libpapi-ipp/i386/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBDIR) $(ROOTLIBS) $(ROOTLINKS) $(EXTRALINKS) diff --git a/usr/src/lib/print/libpapi-ipp/sparc/Makefile b/usr/src/lib/print/libpapi-ipp/sparc/Makefile deleted file mode 100644 index 39b4a998ec..0000000000 --- a/usr/src/lib/print/libpapi-ipp/sparc/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBDIR) $(ROOTLIBS) $(ROOTLINKS) $(EXTRALINKS) diff --git a/usr/src/lib/print/libpapi-lpd/Makefile b/usr/src/lib/print/libpapi-lpd/Makefile deleted file mode 100644 index b92d620b10..0000000000 --- a/usr/src/lib/print/libpapi-lpd/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../../Makefile.lib - -#HDRS = papi.h -#HDRDIR = common -SUBDIRS = $(MACH) -#$(BUILD64)SUBDIRS += $(MACH64) - -all := TARGET = all -clean := TARGET = clean -clobber := TARGET = clobber -install := TARGET = install -lint := TARGET = lint - -.KEEP_STATE: - -all clean clobber install: .WAIT $(SUBDIRS) - -lint: # $(SUBDIRS) - -install_h: # $(ROOTHDRS) - -check: # $(CHECKHDRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -FRC: - -include ../../Makefile.targ diff --git a/usr/src/lib/print/libpapi-lpd/Makefile.com b/usr/src/lib/print/libpapi-lpd/Makefile.com deleted file mode 100644 index c50fd8b223..0000000000 --- a/usr/src/lib/print/libpapi-lpd/Makefile.com +++ /dev/null @@ -1,92 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY = psm-lpd.a -VERS = .1 -COMMON_OBJS = lpd-misc.o -OBJECTS = job.o library.o lpd-cancel.o lpd-job.o lpd-query.o printer.o \ - service.o $(COMMON_OBJS) - -include ../../../Makefile.lib -include ../../../Makefile.rootfs - -SRCDIR = ../common - -ROOTLIBDIR= $(ROOT)/usr/lib/print -ROOTLIBDIR64= $(ROOT)/usr/lib/print/$(MACH) - -EXTRALINKS= $(ROOTLIBDIR)/psm-rfc-1179.so -$(EXTRALINKS): $(ROOTLINKS) - $(RM) $@; $(SYMLINK) $(LIBLINKS) $@ - -LIBS = $(DYNLIB) - -$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRCDIR) -CPPFLAGS += -I../../libpapi-common/common - -CERRWARN += -_gcc=-Wno-unused-variable - -MAPFILES = $(SRCDIR)/mapfile - -LDLIBS += -lc - -.KEEP_STATE: - -all: $(LIBS) $(PROG) - -lint: lintcheck - -include ../../../Makefile.targ - -# -# NEEDED to build lpd-port -# -PROG = lpd-port -LPD_PORT_OBJS = lpd-port.o $(COMMON_OBJS) - -$(PROG) := LDLIBS += -lsocket -lnsl -lsendfile - -PROG_OBJS = $(LPD_PORT_OBJS:%=pics/%) -OBJS += $(PROG_OBJS) - -LDFLAGS.cmd = \ - $(ENVLDFLAGS1) $(ENVLDFLAGS2) $(ENVLDFLAGS3) $(BDIRECT) \ - $(MAPFILE.NES:%=-M%) $(MAPFILE.PGA:%=-M%) $(MAPFILE.NED:%=-M%) - -$(PROG): $(PROG_OBJS) - $(LINK.c) -o $@ $(PROG_OBJS) $(LDFLAGS.cmd) $(LDLIBS) - $(POST_PROCESS) - -# needed for the 'install' phase -ROOTLIBPRINTPROG = $(PROG:%=$(ROOTLIBDIR)/%) -$(ROOTLIBPRINTPROG) := FILEMODE = 04511 - -$(ROOTLIBDIR)/%: $(ROOTLIBDIR) % - $(INS.file) -$(ROOTLIBDIR): - $(INS.dir) diff --git a/usr/src/lib/print/libpapi-lpd/common/job.c b/usr/src/lib/print/libpapi-lpd/common/job.c deleted file mode 100644 index 8663816337..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/job.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* $Id: job.c 179 2006-07-17 18:24:07Z njacobs $ */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <limits.h> -#include <libintl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <papi_impl.h> -#include <uri.h> - -/* - * must copy files before leaving routine - */ -papi_status_t -papiJobSubmit(papi_service_t handle, char *name, papi_attribute_t **attributes, - papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) -{ - papi_status_t status = PAPI_OK; - service_t *svc = handle; - job_t *j = NULL; - char *metadata = NULL; - - if ((svc == NULL) || (name == NULL) || (files == NULL) || - (job == NULL)) - return (PAPI_BAD_ARGUMENT); - - if (job_ticket != NULL) { - detailed_error(svc, - gettext("papiJobSubmit: job ticket not supported")); - return (PAPI_OPERATION_NOT_SUPPORTED); - } - - if ((status = service_fill_in(svc, name)) != PAPI_OK) - return (status); - - if ((*job = j = (job_t *)calloc(1, sizeof (*j))) == NULL) { - detailed_error(svc, - gettext("calloc() failed")); - return (PAPI_TEMPORARY_ERROR); - } - - /* before creating a control file add the job-name */ - if ((files != NULL) && (files[0] != NULL)) - papiAttributeListAddString(&attributes, PAPI_ATTR_EXCL, - "job-name", files[0]); - - /* create a control file */ - (void) lpd_job_add_attributes(svc, attributes, &metadata, - &j->attributes); - - if ((status = lpd_job_add_files(svc, attributes, files, &metadata, - &j->attributes)) != PAPI_OK) { - return (status); - } - - /* send the job to the server */ - status = lpd_submit_job(svc, metadata, &j->attributes, NULL); - free(metadata); - - return (status); - -} - - -papi_status_t -papiJobSubmitByReference(papi_service_t handle, char *name, - papi_attribute_t **job_attributes, - papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) -{ - return (papiJobSubmit(handle, name, job_attributes, - job_ticket, files, job)); -} - -papi_status_t -papiJobStreamOpen(papi_service_t handle, char *name, - papi_attribute_t **attributes, - papi_job_ticket_t *job_ticket, papi_stream_t *stream) -{ - papi_status_t status = PAPI_OK; - service_t *svc = handle; - char *metadata = NULL; - stream_t *s = NULL; - - if ((svc == NULL) || (name == NULL) || (stream == NULL)) - return (PAPI_BAD_ARGUMENT); - - if (job_ticket != NULL) - return (PAPI_OPERATION_NOT_SUPPORTED); - - if ((status = service_fill_in(svc, name)) != PAPI_OK) - return (status); - - /* create the stream container */ - if ((*stream = s = calloc(1, sizeof (*s))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - /* create the job */ - if ((s->job = calloc(1, sizeof (*(s->job)))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - papiAttributeListAddString(&attributes, PAPI_ATTR_EXCL, - "job-name", "standard input"); - - /* process the attribute list */ - lpd_job_add_attributes(svc, attributes, &metadata, &s->job->attributes); - - /* if we can stream, do it */ - if ((svc->uri->fragment != NULL) && - (strcasecmp(svc->uri->fragment, "streaming") == 0)) { - char *files[] = { "standard input", NULL }; - - lpd_job_add_files(svc, attributes, files, &metadata, - &(s->job->attributes)); - status = lpd_submit_job(svc, metadata, &(s->job->attributes), - &s->fd); - } else { - char dfname[18]; - char buf[256]; - - strcpy(dfname, "/tmp/stdin-XXXXX"); - - if ((s->fd = mkstemp(dfname)) >= 0) - s->dfname = strdup(dfname); - if (s->job->attributes) - papiAttributeListFree(s->job->attributes); - s->job->attributes = NULL; - papiAttributeListToString(attributes, " ", buf, sizeof (buf)); - papiAttributeListFromString(&(s->job->attributes), - PAPI_ATTR_APPEND, buf); - } - s->metadata = metadata; - - return (status); -} - - -papi_status_t -papiJobStreamWrite(papi_service_t handle, papi_stream_t stream, - void *buffer, size_t buflen) -{ - service_t *svc = handle; - stream_t *s = stream; - - if ((svc == NULL) || (stream == NULL) || (buffer == NULL) || - (buflen == 0)) - return (PAPI_BAD_ARGUMENT); - - if (write(s->fd, buffer, buflen) != buflen) - return (PAPI_DEVICE_ERROR); - - return (PAPI_OK); -} - -papi_status_t -papiJobStreamClose(papi_service_t handle, papi_stream_t stream, papi_job_t *job) -{ - papi_status_t status = PAPI_INTERNAL_ERROR; - service_t *svc = handle; - job_t *j = NULL; - stream_t *s = stream; - int ret; - - if ((svc == NULL) || (stream == NULL) || (job == NULL)) - return (PAPI_BAD_ARGUMENT); - - close(s->fd); /* close the stream */ - - if (s->dfname != NULL) { /* if it is a tmpfile, print it */ - char *files[2]; - - files[0] = s->dfname; - files[1] = NULL; - - lpd_job_add_files(svc, s->job->attributes, files, &s->metadata, - &(s->job->attributes)); - status = lpd_submit_job(svc, s->metadata, - &(s->job->attributes), NULL); - unlink(s->dfname); - free(s->dfname); - } else - status = PAPI_OK; - - if (s->metadata != NULL) - free(s->metadata); - - *job = s->job; - - return (status); -} - -papi_status_t -papiJobQuery(papi_service_t handle, char *name, int32_t job_id, - char **job_attributes, papi_job_t *job) -{ - papi_status_t status = PAPI_OK; - service_t *svc = handle; - - if ((svc == NULL) || (name == NULL) || job_id < 0) - return (PAPI_BAD_ARGUMENT); - - if ((status = service_fill_in(svc, name)) == PAPI_OK) - status = lpd_find_job_info(svc, job_id, (job_t **)job); - - return (status); -} - -papi_status_t -papiJobCancel(papi_service_t handle, char *name, int32_t job_id) -{ - papi_status_t status; - service_t *svc = handle; - - if ((svc == NULL) || (name == NULL) || (job_id < 0)) - return (PAPI_BAD_ARGUMENT); - - if ((status = service_fill_in(svc, name)) == PAPI_OK) - status = lpd_cancel_job(svc, job_id); - - return (status); -} - -papi_attribute_t ** -papiJobGetAttributeList(papi_job_t job) -{ - job_t *j = (job_t *)job; - - if (j != NULL) - return ((papi_attribute_t **)j->attributes); - - return (NULL); -} - -char * -papiJobGetPrinterName(papi_job_t job) -{ - char *result = NULL; - job_t *j = (job_t *)job; - - if (j != NULL) - papiAttributeListGetString(j->attributes, NULL, - "printer-name", &result); - - return (result); -} - -int -papiJobGetId(papi_job_t job) -{ - int result = -1; - job_t *j = (job_t *)job; - - if (j != NULL) - papiAttributeListGetInteger(j->attributes, NULL, - "job-id", &result); - - return (result); -} - -void -papiJobFree(papi_job_t job) -{ - job_t *j = (job_t *)job; - - - if (j != NULL) { - papiAttributeListFree(j->attributes); - free(j); - } -} - -void -papiJobListFree(papi_job_t *jobs) -{ - if (jobs != NULL) { - int i; - - for (i = 0; jobs[i] != NULL; i++) - papiJobFree(jobs[i]); - free(jobs); - } -} diff --git a/usr/src/lib/print/libpapi-lpd/common/library.c b/usr/src/lib/print/libpapi-lpd/common/library.c deleted file mode 100644 index de38c2bbfa..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/library.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: library.c 146 2006-03-24 00:26:54Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <alloca.h> -#include <libintl.h> -#include <papi_impl.h> - -static char *calls[] = { - /* Attribute Calls */ - "papiAttributeListAdd", - "papiAttributeListAddBoolean", "papiAttributeListAddCollection", - "papiAttributeListAddDatetime", "papiAttributeListAddInteger", - "papiAttributeListAddMetadata", "papiAttributeListAddRange", - "papiAttributeListAddResolution", "papiAttributeListAddString", - "papiAttributeListDelete", - "papiAttributeListGetValue", "papiAttributeListGetNext", - "papiAttributeListFind", - "papiAttributeListGetBoolean", "papiAttributeListGetCollection", - "papiAttributeListGetDatetime", "papiAttributeListGetInteger", - "papiAttributeListGetMetadata", "papiAttributeListGetRange", - "papiAttributeListGetResolution", "papiAttributeListGetString", - "papiAttributeListFromString", "papiAttributeListToString", - "papiAttributeListFree", - /* Job Calls */ - "papiJobSubmit", "papiJobSubmitByReference", - "papiJobStreamOpen", "papiJobStreamWrite", "papiJobStreamClose", - "papiJobQuery", "papiJobCancel", - "papiJobGetAttributeList", "papiJobGetId", "papiJobGetPrinterName", - "papiJobFree", "papiJobListFree", - /* Printer Calls */ - "papiPrinterQuery", "papiPrinterPurgeJobs", "papiPrinterListJobs", - "papiPrinterGetAttributeList", "papiPrinterFree", - /* Service Calls */ - "papiServiceCreate", "papiServiceDestroy", - "papiServiceGetStatusMessage", - /* Misc Calls */ - "papiStatusString", - "papiLibrarySupportedCall", "papiLibrarySupportedCalls", - NULL -}; - -char ** -papiLibrarySupportedCalls() -{ - return (calls); -} - -char -papiLibrarySupportedCall(char *name) -{ - int i; - - for (i = 0; calls[i] != NULL; i++) - if (strcmp(name, calls[i]) == 0) - return (PAPI_TRUE); - - return (PAPI_FALSE); -} diff --git a/usr/src/lib/print/libpapi-lpd/common/lpd-cancel.c b/usr/src/lib/print/libpapi-lpd/common/lpd-cancel.c deleted file mode 100644 index d5a8fd30fd..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/lpd-cancel.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: lpd-cancel.c 155 2006-04-26 02:34:54Z ktou $ */ - -#define __EXTENSIONS__ /* for strtok_r() */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <papi_impl.h> - -papi_status_t -lpd_cancel_job(service_t *svc, int id) -{ - papi_status_t status = PAPI_INTERNAL_ERROR; - int fd; - char *list[2]; - char buf[128]; /* this should be overkill */ - - if (svc == NULL) - return (PAPI_BAD_ARGUMENT); - - snprintf(buf, sizeof (buf), "%d", id); - list[0] = buf; - list[1] = NULL; - - if ((fd = lpd_open(svc, 'c', list, 15)) < 0) - return (PAPI_INTERNAL_ERROR); - - memset(buf, 0, sizeof (buf)); - if (fdgets(buf, sizeof (buf), fd) != NULL) { - if (buf[0] == '\0') - status = PAPI_NOT_FOUND; - else if ((strstr(buf, "permission denied") != NULL) || - (strstr(buf, "not-authorized") != NULL)) - status = PAPI_NOT_AUTHORIZED; - else if ((strstr(buf, "cancelled") != NULL) || - (strstr(buf, "removed") != NULL)) - status = PAPI_OK; - } else - status = PAPI_NOT_FOUND; - - close(fd); - - return (status); -} - -papi_status_t -lpd_purge_jobs(service_t *svc, job_t ***jobs) -{ - papi_status_t status = PAPI_INTERNAL_ERROR; - int fd; - char *queue; - char buf[256]; - - if (svc == NULL) - return (PAPI_BAD_ARGUMENT); - - if ((fd = lpd_open(svc, 'c', NULL, 15)) < 0) - return (PAPI_INTERNAL_ERROR); - - queue = queue_name_from_uri(svc->uri); - - status = PAPI_OK; - memset(buf, 0, sizeof (buf)); - while (fdgets(buf, sizeof (buf), fd) != NULL) { - /* if we canceled it, add it to the list */ - if ((strstr(buf, "cancelled") != NULL) || - (strstr(buf, "removed") != NULL)) { - job_t *job; - papi_attribute_t **attributes = NULL; - char *ptr, *iter = NULL; - int id; - - ptr = strtok_r(buf, ":", &iter); - papiAttributeListAddString(&attributes, PAPI_ATTR_EXCL, - "job-name", ptr); - id = atoi(ptr); - papiAttributeListAddInteger(&attributes, PAPI_ATTR_EXCL, - "job-id", id); - papiAttributeListAddString(&attributes, PAPI_ATTR_EXCL, - "job-printer", queue); - - if ((job = (job_t *)calloc(1, (sizeof (*job)))) - != NULL) { - job->attributes = attributes; - list_append(jobs, job); - } else - papiAttributeListFree(attributes); - } else if (strstr(buf, "permission denied") != NULL) - status = PAPI_NOT_AUTHORIZED; - } - close(fd); - - return (status); -} diff --git a/usr/src/lib/print/libpapi-lpd/common/lpd-job.c b/usr/src/lib/print/libpapi-lpd/common/lpd-job.c deleted file mode 100644 index c958a51e06..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/lpd-job.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: lpd-job.c 157 2006-04-26 15:07:55Z ktou $ */ - - -#define __EXTENSIONS__ /* for strtok_r() */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <limits.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <string.h> -#include <pwd.h> -#include <libintl.h> -#include <papi_impl.h> - -enum { LPD_RFC, LPD_SVR4 }; - -static char -mime_type_to_rfc1179_type(char *mime) -{ - static struct { char *mime; char rfc; } cvt[] = { - { "text/plain", 'f' }, - { "application/octet-stream", 'l' }, - { "application/postscript", 'f' }, /* rfc incorrectly has 'o' */ - { "application/x-pr", 'p' }, - { "application/x-cif", 'c' }, - { "application/x-dvi", 'd' }, - { "application/x-fortran", 'r' }, - { "application/x-plot", 'g' }, - { "application/x-ditroff", 'n' }, - { "application/x-troff", 't' }, - { "application/x-raster", 'v' }, - { NULL, 0} - }; - char result = '\0'; - - if (mime != NULL) { - int i; - - for (i = 0; cvt[i].mime != NULL; i++) - if (strcasecmp(cvt[i].mime, mime) == 0) { - result = cvt[i].rfc; - break; - } - } - - return (result); -} - -static papi_status_t -add_lpd_control_line(char **metadata, char code, char *value) -{ - size_t size = 0; - char line[BUFSIZ]; - - if ((metadata == NULL) || (value == NULL)) - return (PAPI_BAD_REQUEST); - - if (*metadata != NULL) - size = strlen(*metadata); - size += strlen(value) + 3; - - if (*metadata == NULL) { - *metadata = (char *)calloc(1, size); - } else { - void *tmp; - tmp = calloc(1, size); - if (tmp) { - strlcpy(tmp, *metadata, size); - free(*metadata); - *metadata = (char *)tmp; - } else - return (PAPI_TEMPORARY_ERROR); - } - - snprintf(line, sizeof (line), "%c%s\n", code, value); - strlcat(*metadata, line, size); - - return (PAPI_OK); -} - -static papi_status_t -add_svr4_control_line(char **metadata, char code, char *value) -{ - - char line[BUFSIZ]; - - if ((metadata == NULL) || (value == NULL)) - return (PAPI_BAD_REQUEST); - - snprintf(line, sizeof (line), "%c%s", code, value); - - return (add_lpd_control_line(metadata, '5', line)); -} - -static papi_status_t -add_hpux_control_line(char **metadata, char *value) -{ - - char line[BUFSIZ]; - - if ((metadata == NULL) || (value == NULL)) - return (PAPI_BAD_REQUEST); - - snprintf(line, sizeof (line), " O%s", value); - - return (add_lpd_control_line(metadata, 'N', line)); -} - -static papi_status_t -add_int_control_line(char **metadata, char code, int value, int flag) -{ - char buf[16]; - - snprintf(buf, sizeof (buf), "%d", value); - - if (flag == LPD_SVR4) - return (add_svr4_control_line(metadata, code, buf)); - else - return (add_lpd_control_line(metadata, code, buf)); -} - -static papi_status_t -lpd_add_rfc1179_attributes(service_t *svc, papi_attribute_t **attributes, - char **metadata, papi_attribute_t ***used) -{ - papi_status_t status = PAPI_OK; - char *s; - int integer; - char bool; - char host[BUFSIZ]; - char *user = "nobody"; - uid_t uid = getuid(); - struct passwd *pw; - char *h1; - - if (svc == NULL) - return (PAPI_BAD_REQUEST); - - /* There is nothing to do */ - if (attributes == NULL) - return (PAPI_OK); - - gethostname(host, sizeof (host)); - if (papiAttributeListGetString(attributes, NULL, - "job-originating-host-name", &h1) == PAPI_OK) { - papiAttributeListAddString(&attributes, PAPI_ATTR_APPEND, - "job-host", h1); - } - add_lpd_control_line(metadata, 'H', host); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "job-originating-host-name", host); - - if ((pw = getpwuid(uid)) != NULL) - user = pw->pw_name; - if (uid == 0) - papiAttributeListGetString(svc->attributes, NULL, "username", - &user); - add_lpd_control_line(metadata, 'P', user); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "job-originating-user-name", user); - - /* Class for Banner Page */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "rfc-1179-class", &s); - if (s != NULL) { - add_lpd_control_line(metadata, 'C', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "rfc-1179-class", s); - } - - /* Print Banner Page */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "job-sheets", &s); - if ((s != NULL) && (strcmp(s, "standard") == 0)) { - add_lpd_control_line(metadata, 'L', user); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "job-sheets", s); - } - - /* Jobname */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "job-name", &s); - if (s != NULL) { - add_lpd_control_line(metadata, 'J', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "job-name", s); - } - - /* User to mail when job is done - lpr -m */ - bool = PAPI_FALSE; - papiAttributeListGetBoolean(attributes, NULL, "rfc-1179-mail", &bool); - if (bool == PAPI_TRUE) { - add_lpd_control_line(metadata, 'M', user); - papiAttributeListAddBoolean(used, PAPI_ATTR_EXCL, - "rfc-1179-mail", bool); - } - - /* Title for pr */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "pr-title", &s); - if (s != NULL) { - add_lpd_control_line(metadata, 'T', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "pr-title", s); - } - - /* Indent - used with pr filter */ - integer = 0; - papiAttributeListGetInteger(attributes, NULL, "pr-indent", &integer); - if (integer >= 1) { - add_int_control_line(metadata, 'I', integer, LPD_RFC); - papiAttributeListAddInteger(used, PAPI_ATTR_EXCL, - "pr-indent", integer); - } - - /* Width - used with pr filter */ - integer = 0; - papiAttributeListGetInteger(attributes, NULL, "pr-width", &integer); - if (integer >= 1) { - add_int_control_line(metadata, 'W', integer, LPD_RFC); - papiAttributeListAddInteger(used, PAPI_ATTR_EXCL, - "pr-width", integer); - } - - /* file with Times Roman font lpr -1 */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "rfc-1179-font-r", &s); - if (s != NULL) { - add_lpd_control_line(metadata, '1', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "rfc-1179-font-r", s); - } - - /* file with Times Roman font lpr -2 */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "rfc-1179-font-i", &s); - if (s != NULL) { - add_lpd_control_line(metadata, '2', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "rfc-1179-font-i", s); - } - - /* file with Times Roman font lpr -3 */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "rfc-1179-font-b", &s); - if (s != NULL) { - add_lpd_control_line(metadata, '3', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "rfc-1179-font-b", s); - } - - /* file with Times Roman font lpr -4 */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "rfc-1179-font-s", &s); - if (s != NULL) { - add_lpd_control_line(metadata, '4', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "rfc-1179-font-s", s); - } - - /* - * The document format needs to be added, but the control line - * should be added when the filenames are figured out. - */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "document-format", &s); - if (s != NULL) { - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "document-format", s); - } - - return (status); -} - -static char * -unused_attributes(papi_attribute_t **list, papi_attribute_t **used) -{ - char *result = NULL; - char **names = NULL; - int i; - - if ((list == NULL) || (used == NULL)) - return (NULL); - - for (i = 0; used[i] != NULL; i++) - list_append(&names, used[i]->name); - - if (names != NULL) { - papi_attribute_t **unused = NULL; - - /* add these to the list of things to ignore */ - list_append(&names, "document-format"); - list_append(&names, "copies"); - - split_and_copy_attributes(names, list, NULL, &unused); - if (unused != NULL) { - size_t size = 0; - - do { - size += 1024; - if (result != NULL) - free(result); - result = calloc(1, size); - } while (papiAttributeListToString(unused, " ", - result, size) != PAPI_OK); - papiAttributeListFree(unused); - } - free(names); - } - - return (result); -} - -/* - * lpd_add_svr4_attributes - * Solaris 2.x LP - BSD protocol extensions - */ -static papi_status_t -lpd_add_svr4_attributes(service_t *svc, papi_attribute_t **attributes, - char **metadata, papi_attribute_t ***used) -{ - papi_attribute_t *tmp[2]; - char *s; - int integer; - - if (svc == NULL) - return (PAPI_BAD_REQUEST); - - /* media */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "media", &s); - if (s != NULL) { - add_svr4_control_line(metadata, 'f', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "media", s); - } - - /* Handling */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "job-hold-until", &s); - if ((s != NULL) && (strcmp(s, "indefinite") == 0)) { - add_svr4_control_line(metadata, 'H', "hold"); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "job-hold-until", "indefinite"); - } else if ((s != NULL) && (strcmp(s, "no-hold") == 0)) { - add_svr4_control_line(metadata, 'H', "immediate"); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "job-hold-until", "no-hold"); - } else if (s != NULL) { - add_svr4_control_line(metadata, 'H', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "job-hold-until", s); - } - - /* Pages */ - s = NULL; - memset(tmp, NULL, sizeof (tmp)); - tmp[0] = papiAttributeListFind(attributes, "page-ranges"); - if (tmp[0] != NULL) { - char buf[BUFSIZ]; - - papiAttributeListToString(tmp, " ", buf, sizeof (buf)); - if ((s = strchr(buf, '=')) != NULL) { - add_svr4_control_line(metadata, 'P', ++s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "page-ranges", s); - } - } - - /* Priority : lp -q */ - integer = -1; - papiAttributeListGetInteger(attributes, NULL, "job-priority", &integer); - if (integer != -1) { - integer = 40 - (integer / 2.5); - add_int_control_line(metadata, 'q', integer, LPD_SVR4); - papiAttributeListAddInteger(used, PAPI_ATTR_EXCL, - "job-priority", integer); - } - - /* Charset : lp -S */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "lp-charset", &s); - if (s != NULL) { - add_svr4_control_line(metadata, 'S', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "lp-charset", s); - } - - /* Type : done when adding file */ - - /* Mode : lp -y */ - s = NULL; - papiAttributeListGetString(attributes, NULL, "lp-modes", &s); - if (s != NULL) { - add_svr4_control_line(metadata, 'y', s); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "lp-modes", s); - } - - /* Options lp -o are handled elsewhere */ - if ((s = unused_attributes(attributes, *used)) != NULL) { - add_lpd_control_line(metadata, 'O', s); - free(s); - } - - return (PAPI_OK); -} - -papi_status_t -lpd_add_hpux_attributes(service_t *svc, papi_attribute_t **attributes, - char **metadata, papi_attribute_t ***used) -{ - char *s = NULL; - - /* Options lp -o */ - if ((s = unused_attributes(attributes, *used)) != NULL) { - add_hpux_control_line(metadata, s); - free(s); - } - - return (PAPI_OK); -} - -papi_status_t -lpd_job_add_attributes(service_t *svc, papi_attribute_t **attributes, - char **metadata, papi_attribute_t ***used) -{ - if ((svc == NULL) || (metadata == NULL)) - return (PAPI_BAD_REQUEST); - - lpd_add_rfc1179_attributes(svc, attributes, metadata, used); - - /* add protocol extensions if applicable */ - if (svc->uri->fragment != NULL) { - if ((strcasecmp(svc->uri->fragment, "solaris") == 0) || - (strcasecmp(svc->uri->fragment, "svr4") == 0)) - lpd_add_svr4_attributes(svc, attributes, metadata, - used); - else if (strcasecmp(svc->uri->fragment, "hpux") == 0) - lpd_add_hpux_attributes(svc, attributes, metadata, - used); - /* - * others could be added here: - * lprng, sco, aix, digital unix, xerox, ... - */ - } - - return (PAPI_OK); -} - -papi_status_t -lpd_job_add_files(service_t *svc, papi_attribute_t **attributes, - char **files, char **metadata, papi_attribute_t ***used) -{ - char *format = "text/plain"; - char rfc_fmt = 'l'; - int copies = 1; - char host[BUFSIZ]; - int i; - - if ((svc == NULL) || (attributes == NULL) || (files == NULL) || - (metadata == NULL)) - return (PAPI_BAD_ARGUMENT); - - papiAttributeListGetString(attributes, NULL, "document-format", - &format); - papiAttributeListAddString(used, PAPI_ATTR_EXCL, - "document-format", format); - if ((rfc_fmt = mime_type_to_rfc1179_type(format)) == '\0') { - if ((svc->uri->fragment != NULL) && - ((strcasecmp(svc->uri->fragment, "solaris") == 0) || - (strcasecmp(svc->uri->fragment, "svr4") == 0))) - add_svr4_control_line(metadata, 'T', format); - rfc_fmt = 'l'; - } - - papiAttributeListGetInteger(attributes, NULL, "copies", &copies); - if (copies < 1) - copies = 1; - papiAttributeListAddInteger(used, PAPI_ATTR_EXCL, "copies", copies); - - gethostname(host, sizeof (host)); - - for (i = 0; files[i] != NULL; i++) { - char name[BUFSIZ]; - struct stat statbuf; - char key; - int j; - - if ((strcmp("standard input", files[i]) != 0) && - (access(files[i], R_OK) < 0)) { - detailed_error(svc, gettext("aborting request, %s: %s"), - files[i], strerror(errno)); - return (PAPI_NOT_AUTHORIZED); - } - if (strcmp("standard input", files[i]) != 0) { - if (stat(files[i], &statbuf) < 0) { - detailed_error(svc, - gettext("Cannot access file: %s: %s"), - files[i], strerror(errno)); - return (PAPI_DOCUMENT_ACCESS_ERROR); - } - if (statbuf.st_size == 0) { - detailed_error(svc, - gettext("Zero byte (empty) file: %s"), - files[i]); - return (PAPI_BAD_ARGUMENT); - } - } - - if (i < 26) - key = 'A' + i; - else if (i < 52) - key = 'a' + (i - 26); - else if (i < 62) - key = '0' + (i - 52); - else { - detailed_error(svc, - gettext("too many files, truncated at 62")); - return (PAPI_OK_SUBST); - } - - snprintf(name, sizeof (name), "df%cXXX%s", key, host); - - for (j = 0; j < copies; j++) - add_lpd_control_line(metadata, rfc_fmt, name); - add_lpd_control_line(metadata, 'U', name); - add_lpd_control_line(metadata, 'N', (char *)files[i]); - } - - return (PAPI_OK); -} - -papi_status_t -lpd_submit_job(service_t *svc, char *metadata, papi_attribute_t ***attributes, - int *ofd) -{ - papi_status_t status = PAPI_INTERNAL_ERROR; - int fd; - char path[32]; - char *list[2]; - - if ((svc == NULL) || (metadata == NULL)) - return (PAPI_BAD_ARGUMENT); - - strcpy(path, "/tmp/lpd-job-XXXXXX"); - fd = mkstemp(path); - write(fd, metadata, strlen(metadata)); - close(fd); - - list[0] = path; - list[1] = NULL; - - if (((fd = lpd_open(svc, 's', list, 15)) < 0) && (errno != EBADMSG)) { - switch (errno) { - case ENOSPC: - status = PAPI_TEMPORARY_ERROR; - break; - case EIO: - status = PAPI_TEMPORARY_ERROR; - break; - case ECONNREFUSED: - status = PAPI_SERVICE_UNAVAILABLE; - break; - case ENOENT: - status = PAPI_NOT_ACCEPTING; - break; - case EBADMSG: - case EBADF: - status = PAPI_OK; - break; - default: - status = PAPI_TIMEOUT; - break; - } - } else - status = PAPI_OK; - - if (ofd != NULL) - *ofd = fd; - else - close(fd); - - /* read the ID and add it to to the job */ - if ((fd = open(path, O_RDONLY)) >= 0) { - int job_id = 0; - read(fd, &job_id, sizeof (job_id)); - papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, - "job-id", job_id); - close(fd); - } - - unlink(path); - - return (status); -} diff --git a/usr/src/lib/print/libpapi-lpd/common/lpd-misc.c b/usr/src/lib/print/libpapi-lpd/common/lpd-misc.c deleted file mode 100644 index 1dc9589d25..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/lpd-misc.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: lpd-misc.c 155 2006-04-26 02:34:54Z ktou $ */ - -#define __EXTENSIONS__ /* for strtok_r() */ -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <fcntl.h> -#include <stdarg.h> -#include <string.h> -#include <signal.h> -#include <sys/socket.h> -#include <errno.h> -#include <wait.h> -#include <stropts.h> -#include <papi_impl.h> - -#include <config-site.h> - -char * -fdgets(char *buf, size_t len, int fd) -{ - char tmp; - int count = 0; - - memset(buf, 0, len); - while ((count < len) && (read(fd, &tmp, 1) > 0)) - if ((buf[count++] = tmp) == '\n') break; - - if (count != 0) - return (buf); - return (NULL); -} - -char * -queue_name_from_uri(uri_t *uri) -{ - char *result = NULL; - - if ((uri != NULL) && (uri->path != NULL)) { - char *ptr = strrchr(uri->path, '/'); - - if (ptr == NULL) - result = uri->path; - else - result = ++ptr; - } - - return (result); -} - -static int -recvfd(int sockfd) -{ - int fd = -1; -#if defined(sun) && defined(unix) && defined(I_RECVFD) - struct strrecvfd recv_fd; - - memset(&recv_fd, NULL, sizeof (recv_fd)); - if (ioctl(sockfd, I_RECVFD, &recv_fd) == 0) - fd = recv_fd.fd; -#else - struct iovec iov[1]; - struct msghdr msg; - -#ifdef CMSG_DATA - struct cmsghdr cmp[1]; - char buf[24]; /* send/recv 2 byte protocol */ - - memset(buf, 0, sizeof (buf)); - - iov[0].iov_base = buf; - iov[0].iov_len = sizeof (buf); - - msg.msg_control = cmp; - msg.msg_controllen = sizeof (struct cmsghdr) + sizeof (int); -#else - iov[0].iov_base = NULL; - iov[0].iov_len = 0; - msg.msg_accrights = (caddr_t)&fd; - msg.msg_accrights = sizeof (fd); -#endif - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - - if (recvmsg(sockfd, &msg, 0) < 0) - fd = -1; -#ifdef CMSG_DATA - else - fd = * (int *)CMSG_DATA(cmp); -#endif -#endif - return (fd); -} - -int -lpd_open(service_t *svc, char type, char **args, int timeout) -{ - int ac, rc = -1, fds[2]; - pid_t pid; - char *av[64], *tmp, buf[BUFSIZ]; - - if ((svc == NULL) || (svc->uri == NULL)) - return (-1); - -#ifndef SUID_LPD_PORT -#define SUID_LPD_PORT "/usr/lib/print/lpd-port" -#endif - - av[0] = SUID_LPD_PORT; ac = 1; - - /* server */ - av[ac++] = "-H"; - av[ac++] = svc->uri->host; - - /* timeout */ - if (timeout > 0) { - snprintf(buf, sizeof (buf), "%d", timeout); - av[ac++] = "-t"; - av[ac++] = strdup(buf); - } - - /* operation */ - snprintf(buf, sizeof (buf), "-%c", type); - av[ac++] = buf; - - /* queue */ - if (svc->uri->path == NULL) { - tmp = ""; - } else { - if ((tmp = strrchr(svc->uri->path, '/')) == NULL) - tmp = svc->uri->path; - else - tmp++; - } - av[ac++] = tmp; - - /* args */ - if (args != NULL) - while ((*args != NULL) && (ac < 62)) - av[ac++] = *args++; - - av[ac++] = NULL; - -#if defined(sun) && defined(unix) && defined(I_RECVFD) - pipe(fds); -#else - socketpair(AF_UNIX, SOCK_STREAM, 0, fds); -#endif - - switch (pid = fork()) { - case -1: /* failed */ - break; - case 0: /* child */ - dup2(fds[1], 1); - execv(av[0], &av[0]); - perror("exec"); - exit(1); - break; - default: { /* parent */ - int err, status = 0; - - while ((waitpid(pid, &status, 0) < 0) && (errno == EINTR)); - errno = WEXITSTATUS(status); - - if (errno == 0) - rc = recvfd(fds[0]); - - err = errno; - close(fds[0]); - close(fds[1]); - errno = err; - } - } - - return (rc); -} diff --git a/usr/src/lib/print/libpapi-lpd/common/lpd-port.c b/usr/src/lib/print/libpapi-lpd/common/lpd-port.c deleted file mode 100644 index 5c6c2e3ff8..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/lpd-port.c +++ /dev/null @@ -1,823 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: lpd-port.c 155 2006-04-26 02:34:54Z ktou $ */ - -#include <config-site.h> - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdarg.h> -#include <string.h> -#include <signal.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <errno.h> -#include <syslog.h> -#include <values.h> -#include <stropts.h> /* for sendfd */ -#include <sys/uio.h> /* for sendmsg stuff */ -#include <pwd.h> -#include <sys/sendfile.h> -#include <ctype.h> -#ifdef HAVE_PRIV_H -#include <priv.h> -#endif - -#ifndef JOB_ID_FILE -#define JOB_ID_FILE "/var/run/rfc-1179.seq" -#endif /* JOB_ID_FILE */ - -static int -sendfd(int sockfd, int fd) -{ - syslog(LOG_DEBUG, "sendfd(%d, %d)", sockfd, fd); - -#if defined(sun) && defined(unix) && defined(I_SENDFD) - return (ioctl(sockfd, I_SENDFD, fd)); -#else - struct iovec iov[1]; - struct msghdr msg; -#ifdef CMSG_DATA - struct cmsghdr cmp[1]; - char buf[2]; /* send/recv 2 byte protocol */ - - iov[0].iov_base = buf; - iov[0].iov_len = 2; - - cmp[0].cmsg_level = SOL_SOCKET; - cmp[0].cmsg_type = SCM_RIGHTS; - cmp[0].cmsg_len = sizeof (struct cmsghdr) + sizeof (int); - * (int *)CMSG_DATA(cmp) = fd; - - buf[1] = 0; - buf[0] = 0; - msg.msg_control = cmp; - msg.msg_controllen = sizeof (struct cmsghdr) + sizeof (int); -#else - iov[0].iov_base = NULL; - iov[0].iov_len = 0; - msg.msg_accrights = (caddr_t)&fd; - msg.msg_accrights = sizeof (fd); -#endif - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - - return (sendmsg(sockfd, &msg, 0)); -#endif -} - -static void -null(int i) -{ -} - -static int -sock_connect(int sock, char *host, int timeout) -{ - struct hostent *hp; - struct servent *sp; -#if defined(HAVE_GETIPNODEBYNAME) && defined(HAVE_RRESVPORT_AF) - struct sockaddr_in6 sin; -#else - struct sockaddr_in sin; -#endif - static void (*old_handler)(); - int err, error_num; - unsigned timo = 1; - - /* - * Get the host address and port number to connect to. - */ - if (host == NULL) { - return (-1); - } - - /* linux style NULL usage */ - (void) memset((char *)&sin, (int)NULL, sizeof (sin)); - -#if defined(HAVE_GETIPNODEBYNAME) && defined(HAVE_RRESVPORT_AF) - if ((hp = getipnodebyname(host, AF_INET6, AI_DEFAULT, - &error_num)) == NULL) { - errno = ENOENT; - return (-1); - } - (void) memcpy((caddr_t)&sin.sin6_addr, hp->h_addr, hp->h_length); - sin.sin6_family = hp->h_addrtype; -#else - if ((hp = gethostbyname(host)) == NULL) { - errno = ENOENT; - return (-1); - } - - (void) memcpy((caddr_t)&sin.sin_addr, hp->h_addr, hp->h_length); - sin.sin_family = hp->h_addrtype; -#endif - - if ((sp = getservbyname("printer", "tcp")) == NULL) { - errno = ENOENT; - return (-1); - } - -#if defined(HAVE_GETIPNODEBYNAME) && defined(HAVE_RRESVPORT_AF) - sin.sin6_port = sp->s_port; -#else - sin.sin_port = sp->s_port; -#endif - -retry: - old_handler = signal(SIGALRM, null); - (void) alarm(timeout); - - if (connect(sock, (struct sockaddr *)&sin, sizeof (sin)) < 0) { - (void) alarm(0); - (void) signal(SIGALRM, old_handler); - - if (errno == ECONNREFUSED && timo <= 16) { - (void) sleep(timo); - timo *= 2; - goto retry; - } - - return (-1); - } - - (void) alarm(0); - (void) signal(SIGALRM, old_handler); - return (sock); -} - -static int -next_job_id() -{ - int fd, result = getpid() % 1000; - - /* gain back enough privilege to open the id file */ -#ifdef PRIV_ALLSETS - if ((priv_set(PRIV_ON, PRIV_EFFECTIVE, - PRIV_FILE_DAC_READ, PRIV_FILE_DAC_WRITE, NULL)) < 0) { - syslog(LOG_ERR, "lpd_port:next_job_id:priv_set fails: : %m"); - return (-1); - } -#else - seteuid(0); -#endif - - /* open the sequence file */ - if (((fd = open(JOB_ID_FILE, O_RDWR)) < 0) && (errno == ENOENT)) - fd = open(JOB_ID_FILE, O_CREAT|O_EXCL|O_RDWR, 0644); - - syslog(LOG_DEBUG, "sequence file fd: %d", fd); - - /* drop our privilege again */ -#ifdef PRIV_ALLSETS - /* drop file access privilege */ - priv_set(PRIV_OFF, PRIV_PERMITTED, - PRIV_FILE_DAC_READ, PRIV_FILE_DAC_WRITE, NULL); -#else - seteuid(getuid()); -#endif - - if (fd >= 0) { - /* wait for a lock on the file */ - if (lockf(fd, F_LOCK, 0) == 0) { - char buf[8]; - int next; - - /* get the current id */ - (void) memset(buf, 0, sizeof (buf)); - if (read(fd, buf, sizeof (buf)) > 0) - result = atoi(buf); - - next = ((result < 999) ? (result + 1) : 0); - - /* store the next id in the file */ - snprintf(buf, sizeof (buf), "%.3d", next); - if ((lseek(fd, 0, SEEK_SET) == 0) && - (ftruncate(fd, 0) == 0)) - write(fd, buf, strlen(buf)); - } - close(fd); - } - syslog(LOG_DEBUG, "next_job_id() is %d", result); - - return (result); -} - -static int -reserved_port() -{ - int result = -1; - int port; - - /* gain back enough privilege to open a reserved port */ -#ifdef PRIV_ALLSETS - if ((priv_set( - PRIV_ON, PRIV_EFFECTIVE, PRIV_NET_PRIVADDR, NULL)) != 0) { - syslog(LOG_ERR, "priv_set fails for net_privaddr %m"); - return (-1); - } -#else - seteuid(0); -#endif - -#if defined(HAVE_GETIPNODEBYNAME) && defined(HAVE_RRESVPORT_AF) - port = 0; /* set to 0, rresvport_af() will find us one. */ - result = rresvport_af(&port, AF_INET6); -#else - port = IPPORT_RESERVED - 1; - while (((result = rresvport(&port)) < 0) && (port >= 0)) - port--; -#endif - - /* drop our privilege again */ -#ifdef PRIV_ALLSETS - priv_set(PRIV_OFF, PRIV_PERMITTED, PRIV_NET_PRIVADDR, NULL); -#else - seteuid(getuid()); -#endif - - return (result); -} - -static char * -get_user_name() -{ - static struct passwd *p = NULL; - - if ((p = getpwuid(getuid())) != NULL) - return (p->pw_name); - else - return ("unknown"); -} - -static void -add_args(int ac, char **av, char *buf, size_t len) -{ - while (ac--) { - strlcat(buf, " ", len); - strlcat(buf, *(av++), len); - } -} - -static int -massage_control_data(char *data, int id) -{ - char *line, *iter = NULL; - char *ptr, *mod_ptr, *datacpy; - char host[BUFSIZ]; - int host_present = 0; - - if (gethostname(host, sizeof (host)) != 0) - return (-1); - - if ((datacpy = strdup(data)) == NULL) { - return (-1); - } - - for (ptr = strtok_r(datacpy, "\n", &iter); ptr != NULL; - ptr = strtok_r(NULL, "\n", &iter)) { - - if (ptr[0] == 'H') { - if (strncmp(++ptr, host, strlen(host)) != 0) { - free(datacpy); - return (-1); - } - host_present = 1; - } else if ((ptr[0] == 'P') || (ptr[0] == 'L')) { - /* check the user name */ - uid_t uid = getuid(); - struct passwd *pw; - int len; - - if (uid == 0) { /* let root do what they want */ - continue; - } - if ((pw = getpwuid(uid)) == NULL) { - free(datacpy); - return (-1); /* failed */ - } - len = strlen(pw->pw_name); - if ((strncmp(++ptr, pw->pw_name, len) != 0)) { - free(datacpy); - return (-1); /* failed */ - } - } else if ((islower(ptr[0]) != 0) || (ptr[0] == 'U')) { - /* check/fix df?XXXhostname */ - ptr++; - - if (strlen(ptr) < 6) { - free(datacpy); - return (-1); - } - - /* - * As ptr is a copy of the string (df?XXX...) the code - * needs to work on the original, hence the need for - * mod_ptr. No need to check for a NULL mod_ptr - * because the required string must already exist as - * ptr is a copy of the original data. - */ - - mod_ptr = strstr(data, ptr); - - if ((mod_ptr[0] == 'd') && (mod_ptr[1] == 'f') && - (mod_ptr[3] == 'X') && (mod_ptr[4] == 'X') && - (mod_ptr[5] == 'X')) { - mod_ptr[3] = '0' + (id / 100) % 10; - mod_ptr[4] = '0' + (id / 10) % 10; - mod_ptr[5] = '0' + id % 10; - - if (strncmp(&mod_ptr[6], host, strlen(host)) - != 0) { - free(datacpy); - return (-1); - } - } else { - free(datacpy); - return (-1); - } - } - - } - free(datacpy); - - if (!host_present) { - return (-1); - } - - return (1); -} - -static int -send_lpd_message(int fd, char *fmt, ...) -{ - char buf[BUFSIZ]; - size_t size; - va_list ap; - - va_start(ap, fmt); - size = vsnprintf(buf, sizeof (buf), fmt, ap); - va_end(ap); - if (size == 0) - size = 1; - - syslog(LOG_DEBUG, "lpd_messsage(%d, %s)", fd, buf); - - if (write(fd, buf, size) != size) { - errno = EIO; - return (-1); - } - - if ((read(fd, buf, 1) != 1) || (buf[0] != 0)) - return (-1); - - return (0); -} - -static int -send_data_file(int sock, char *dfname, char *name) -{ - size_t len; - off_t off = 0; - struct stat st; - char buf[32]; - int fd = -1; - - if (strcmp(name, "standard input") != 0) { - if ((fd = open(name, O_RDONLY)) < 0) - return (-1); - - if (fstat(fd, &st) < 0) - return (-1); - } else - st.st_size = MAXINT; /* should be 0 */ - - /* request data file transfer, read ack/nack */ - errno = ENOSPC; - if (send_lpd_message(sock, "\003%d %s\n", st.st_size, dfname) < 0) - return (-1); - - if (fd != -1) { - /* write the data */ - if (sendfile(sock, fd, &off, st.st_size) != st.st_size) - return (-1); - close(fd); - - /* request ack/nack after the data transfer */ - errno = EIO; - if (send_lpd_message(sock, "") < 0) - return (-1); - } - - return (0); -} - -static int -send_control_file(int sock, char *data, int id) -{ - int len; - char buf[BUFSIZ]; - char *ptr, *iter = NULL; - char *datacpy = NULL; - char *host = NULL; - - len = strlen(data); - - if ((datacpy = strdup(data)) == NULL) - return (-1); - - syslog(LOG_DEBUG, "cfA: %s\n", datacpy); - - for (ptr = strtok_r(datacpy, "\n", &iter); ptr != NULL; - ptr = strtok_r(NULL, "\n", &iter)) { - - if (ptr[0] != 'H') - continue; - - ptr++; - host = ptr; - syslog(LOG_DEBUG, "hostname: %s\n", host); - } - - free(datacpy); - - /* request data file transfer, read ack/nack */ - errno = ENOSPC; - if (send_lpd_message(sock, "\002%d cfA%.3d%s\n", len, id, host) < 0) - return (-1); - - /* write the data */ - if (write(sock, data, len) != len) - return (-1); - - /* request ack/nack after the data transfer */ - errno = EIO; - if (send_lpd_message(sock, "") < 0) - return (-1); - - return (0); -} - - -static int -submit_job(int sock, char *printer, int job_id, char *path) -{ - struct stat st; - int current = 0; - off_t off = 0; - char *metadata = NULL; - char *ptr, *iter = NULL; - int fd, err; - int sent_files = 0; - char buf[BUFSIZ]; - size_t len; - - /* open the control file */ - if ((fd = open(path, O_RDONLY)) < 0) { - syslog(LOG_ERR, "submit_job(%d, %s, %d, %s): open(): %m", - sock, printer, job_id, path); - return (-1); - } - - /* get the size of the control file */ - if (fstat(fd, &st) < 0) { - syslog(LOG_ERR, "submit_job(%d, %s, %d, %s): fstat(): %m", - sock, printer, job_id, path); - close(fd); - return (-1); - } - - /* allocate memory for the control file */ - if ((metadata = calloc(1, st.st_size + 1)) == NULL) { - syslog(LOG_ERR, "submit_job(%d, %s, %d, %s): calloc(): %m", - sock, printer, job_id, path); - close(fd); - return (-1); - } - - /* read in the control file */ - if (read(fd, metadata, st.st_size) != st.st_size) { - syslog(LOG_ERR, "submit_job(%d, %s, %d, %s): read(): %m", - sock, printer, job_id, path); - free(metadata); - close(fd); - return (-1); - } - - /* massage the control file */ - if (massage_control_data(metadata, job_id) < 0) { - /* bad control data, dump the job */ - syslog(LOG_ALERT, - "bad control file, possible subversion attempt"); - free(metadata); - errno = EINVAL; - close(fd); - return (-1); - } - - /* request to transfer the job */ - if (send_lpd_message(sock, "\002%s\n", printer) < 0) { - /* no such (or disabled) queue, got to love rfc-1179 */ - errno = ENOENT; - return (-1); - } - - /* send the control data */ - if (send_control_file(sock, metadata, job_id) < 0) { - err = errno; - write(sock, "\001\n", 2); /* abort */ - errno = err; - return (-1); - } - - /* walk the control file sending the data files */ - for (ptr = strtok_r(metadata, "\n", &iter); ptr != NULL; - ptr = strtok_r(NULL, "\n", &iter)) { - char *name = NULL; - - if (ptr[0] != 'U') - continue; - - name = strtok_r(NULL, "\n", &iter); - if (name[0] != 'N') - continue; - - ptr++; - name++; - - if (send_data_file(sock, ptr, name) < 0) { - err = errno; - write(sock, "\001\n", 2); /* abort */ - errno = err; - return (-1); - } - if (strcmp(name, "standard input") != 0) - sent_files++; - } - - /* write back the job-id */ - err = errno; - if ((fd = open(path, O_WRONLY)) >= 0) { - ftruncate(fd, 0); - write(fd, &job_id, sizeof (job_id)); - close(fd); - } - errno = err; - - if (sent_files != 0) { - err = errno; - close(sock); - errno = err; - } - - return (0); -} -static int -query(int fd, char *printer, int ac, char **av) -{ - char buf[BUFSIZ]; - int rc, len; - - /* build the request */ - snprintf(buf, sizeof (buf), "\04%s", printer); - add_args(ac, av, buf, sizeof (buf)); - strlcat(buf, "\n", sizeof (buf)); - len = strlen(buf); - - if (((rc = write(fd, buf, len)) >= 0) && (rc != len)) { - errno = EMSGSIZE; - rc = -1; - } else - rc = 0; - - return (rc); -} - -static int -cancel(int fd, char *printer, int ac, char **av) -{ - char buf[BUFSIZ]; - int rc, len; - - /* build the request */ - snprintf(buf, sizeof (buf), "\05%s %s", printer, get_user_name()); - add_args(ac, av, buf, sizeof (buf)); - strlcat(buf, "\n", sizeof (buf)); - len = strlen(buf); - - if (((rc = write(fd, buf, len)) >= 0) && (rc != len)) { - errno = EMSGSIZE; - rc = -1; - } else - rc = 0; - - return (rc); -} - -static void -usage(char *program) -{ - char *name; - - setreuid(getuid(), getuid()); - - if ((name = strrchr(program, '/')) == NULL) - name = program; - else - name++; - - fprintf(stderr, "usage:\t%s -H host [-t timeout] -s queue control ]\n", - name); - fprintf(stderr, "\t%s -H host [-t timeout] -c queue [user|job ...]\n", - name); - fprintf(stderr, "\t%s -H host [-t timeout] -q queue [user|job ...]\n", - name); - exit(EINVAL); -} - -/* - * The main program temporarily loses privilege while searching the command - * line arguments. It then allocates any resources it need privilege for - * job-id, reserved port. Once it has the resources it needs, it perminently - * drops all elevated privilege. It ghen connects to the remote print service - * based on destination hostname. Doing it this way reduces the potenential - * opportunity for a breakout with elevated privilege, breakout with an - * unconnected reserved port, and exploitation of the remote print service - * by a calling program. - */ -int -main(int ac, char *av[]) -{ - enum { OP_NONE, OP_SUBMIT, OP_QUERY, OP_CANCEL } operation = OP_NONE; - int fd, c, timeout = 0, exit_code = 0; - char *host = NULL, *queue = NULL; - uid_t uid = getuid(); -#ifdef PRIV_ALLSETS - priv_set_t *saveset; -#endif - - openlog("lpd-port", LOG_PID, LOG_LPR); - -#ifdef PRIV_ALLSETS - - /* lose as much as we can perminently and temporarily drop the rest. */ - - if ((saveset = priv_allocset()) == NULL) { - syslog(LOG_ERR, "lpd_port: priv_allocset saveset failed: %m\n"); - return (-1); - } - - priv_basicset(saveset); - (void) priv_addset(saveset, PRIV_NET_PRIVADDR); - (void) priv_addset(saveset, PRIV_FILE_DAC_READ); - (void) priv_addset(saveset, PRIV_FILE_DAC_WRITE); - - if ((setppriv(PRIV_SET, PRIV_PERMITTED, saveset)) < 0) { - syslog(LOG_ERR, "lpd_port:setppriv:priv_set failed: %m"); - return (-1); - } - - priv_freeset(saveset); - - /* - * These privileges permanently dropped in next_job_id() and - * reserved_port() - */ - - if (priv_set(PRIV_OFF, PRIV_EFFECTIVE, PRIV_NET_PRIVADDR, - PRIV_FILE_DAC_READ, PRIV_FILE_DAC_WRITE, (char *)NULL) < 0) { - syslog(LOG_ERR, "lpd_port:priv_set:priv_off failed: %m"); - return (-1); - } - - syslog(LOG_DEBUG, "using privs"); -#else - - syslog(LOG_DEBUG, "no privs"); - seteuid(uid); -#endif - - while ((c = getopt(ac, av, "H:t:c:q:s:")) != EOF) { - switch (c) { - case 'H': - host = optarg; - break; - case 't': - timeout = atoi(optarg); - break; - case 'c': - if (operation != OP_NONE) - usage(av[0]); - operation = OP_CANCEL; - queue = optarg; - break; - case 'q': - if (operation != OP_NONE) - usage(av[0]); - operation = OP_QUERY; - queue = optarg; - break; - case 's': - if (operation != OP_NONE) - usage(av[0]); - operation = OP_SUBMIT; - queue = optarg; - break; - default: - usage(av[0]); - /* does not return */ - } - } - - if ((host == NULL) || (queue == NULL) || (timeout < 0) || - (operation == OP_NONE)) - usage(av[0]); - - if (operation == OP_SUBMIT) /* get a job-id if we need it */ - if ((c = next_job_id()) < 0) { - syslog(LOG_ERR, "lpd_port:main:next_job_id fails"); - return (-1); - } - - if ((fd = reserved_port()) < 0) { - syslog(LOG_ERR, "reserved_port() failed %m"); - return (errno); - } - - /* - * we no longer want or need any elevated privilege, lose it all - * permanently. - */ - - setreuid(uid, uid); - - /* connect to the print service */ - if ((fd = sock_connect(fd, host, timeout)) < 0) - return (errno); - - /* perform the requested operation */ - switch (operation) { - case OP_SUBMIT: /* transfer the job, close the fd */ - if (submit_job(fd, queue, c, av[optind]) < 0) - exit_code = errno; - break; - case OP_QUERY: /* send the query string, return the fd */ - if (query(fd, queue, ac - optind, &av[optind]) < 0) - exit_code = errno; - break; - case OP_CANCEL: /* send the cancel string, return the fd */ - if (cancel(fd, queue, ac - optind, &av[optind]) < 0) - exit_code = errno; - break; - default: /* This should never happen */ - exit_code = EINVAL; - } - - - /* if the operation succeeded, send the fd to our parent */ - if ((exit_code == 0) && (sendfd(1, fd) < 0)) { - char buf[BUFSIZ]; - - exit_code = errno; - - /* sendfd() failed, dump the socket data for the heck of it */ - while ((c = read(fd, buf, sizeof (buf))) > 0) - write(1, buf, c); - } - - syslog(LOG_DEBUG, "exit code: %d", exit_code); - return (exit_code); -} diff --git a/usr/src/lib/print/libpapi-lpd/common/lpd-query.c b/usr/src/lib/print/libpapi-lpd/common/lpd-query.c deleted file mode 100644 index 964023c919..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/lpd-query.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. - */ - -/* $Id: lpd-query.c 155 2006-04-26 02:34:54Z ktou $ */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/fcntl.h> -#include <time.h> -#include <ctype.h> -#include <string.h> -#include <stdarg.h> -#include <regex.h> - -#include <papi_impl.h> - -/* The string is modified by this call */ -static char * -regvalue(regmatch_t match, char *string) -{ - char *result = NULL; - - if (match.rm_so != match.rm_eo) { - result = string + match.rm_so; - *(result + (match.rm_eo - match.rm_so)) = '\0'; - } - - return (result); -} - -/* - * Print job entries start with: - * (user): (rank) [job (number) (...)] - * (user) is the job-owner's user name - * (rank) is the rank in queue. (active, 1st, 2nd, ...) - * (number) is the job number - * (...) is an optional hostname - * some servers will use whitespace a little differently than is displayed - * above. The regular expression below makes whitespace optional in some - * places. - */ -static char *job_expr = "^(.*[[:alnum:]]):[[:space:]]+([[:alnum:]]+)"\ - "[[:space:]]+[[][[:space:]]*job[[:space:]]*([[:digit:]]+)"\ - "[[:space:]]*(.*)]"; -static regex_t job_re; - -/* - * Print job entries for remote windows printer start with: - * Owner Status Jobname Job-Id Size Pages Priority - * e.g: - * Owner Status Jobname Job-Id Size Pages Priority - * ------------------------------------------------------------ - * root (10.3. Waiting /etc/release 2 240 1 4 - * - * Owner is the job-owner's user name - * Status is the job-status (printing, waiting, error) - * Jobname is the name of the job to be printed - * Job-Id is the id of the job queued to be printed - * Size is the size of the job in bytes - * Pages is the number of pages of the job - * Priority is the job-priority - */ -static char *wjob_expr = "^([[:alnum:]]+)[[:space:]]*[(](.*)[)]*[[:space:]]"\ - "+([[:alnum:]]+)[[:space:]]+(.*)([[:alnum:]]+)(.*)[[:space:]]+"\ - "([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([[:digit:]]+)"\ - "[[:space:]]+([[:digit:]]+)"; -static regex_t wjob_re; - -/* - * Windows job header is in the following format - * Owner Status Jobname Job-Id Size Pages Priority - * -------------------------------------------------------------- - */ -static char *whjob_expr = "Owner Status Jobname Job-Id"\ - " Size Pages Priority"; -static regex_t whjob_re; - -static char *wline_expr = "----------"; -static regex_t wline_re; - -/* - * status line(s) for "processing" printers will contain one of the following: - * ready and printing - * Printing - * processing - */ -static char *proc_expr = "(ready and printing|printing|processing)"; -static regex_t proc_re; - -/* - * status line(s) for "idle" printers will contain one of the following: - * no entries - * (printer) is ready - * idle - */ -static char *idle_expr = "(no entries|is ready| idle)"; -static regex_t idle_re; - -/* - * Printer state reason (For Windows remote printers) - * Paused - */ -static char *state_reason_expr = "(Paused)"; -static regex_t state_reason_re; - -/* - * document line(s) - * (copies) copies of (name) (size) bytes - * (name) (size) bytes - * document lines can be in either format above. - * (copies) is the number of copies of the document to print - * (name) is the name of the document: /etc/motd, ... - * (size) is the number of bytes in the document data - */ -static char *doc1_expr = "[[:space:]]+(([[:digit:]]+) copies of )"\ - "([^[:space:]]+)[[:space:]]*([[:digit:]]+) bytes"; -static char *doc2_expr = "[[:space:]]+()([^[:space:]]+)[[:space:]]*"\ - "([[:digit:]]+) bytes"; -static regex_t doc1_re; -static regex_t doc2_re; - -/* Printer-state for Windows */ -static int win_state = 0x03; /* Idle */ - -static void -parse_lpd_job(service_t *svc, job_t **job, int fd, char *line, int len) -{ - papi_attribute_t **attributes = NULL; - regmatch_t matches[10]; - char *s; - int octets = 0; - int flag = 0; - - /* - * job_re and wjob_re were compiled in the calling function - * first check for solaris jobs - * if there is no-match check for windows jobs - */ - - if (regexec(&job_re, line, (size_t)5, matches, 0) == REG_NOMATCH) { - if (regexec(&wjob_re, line, (size_t)10, matches, 0) - == REG_NOMATCH) - return; - else - flag = 1; - } - - if (flag == 1) { - /* Windows job */ - /* first match is job-id */ - - if ((s = regvalue(matches[1], line)) == NULL) - s = "nobody"; - papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE, - "job-originating-user-name", s); - - if ((s = regvalue(matches[4], line)) == NULL) - s = "unknown"; - papiAttributeListAddString(&attributes, PAPI_ATTR_APPEND, - "job-name", s); - papiAttributeListAddString(&attributes, PAPI_ATTR_APPEND, - "job-file-names", s); - - if ((s = regvalue(matches[7], line)) == NULL) - s = "0"; - papiAttributeListAddInteger(&attributes, PAPI_ATTR_REPLACE, - "job-id", atoi(s)); - - if ((s = regvalue(matches[8], line)) == NULL) - s = "0"; - octets = atoi(s); - papiAttributeListAddInteger(&attributes, - PAPI_ATTR_APPEND, "job-file-sizes", atoi(s)); - - /* - * Since a job has been found so the printer state is either - * 'stopped' or 'processing' - * By default it is "processing" - */ - win_state = 0x04; - } else { - /* Solaris job */ - if ((s = regvalue(matches[1], line)) == NULL) - s = "nobody"; - papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE, - "job-originating-user-name", s); - - if ((s = regvalue(matches[2], line)) == NULL) - s = "0"; - papiAttributeListAddInteger(&attributes, PAPI_ATTR_REPLACE, - "number-of-intervening-jobs", atoi(s) - 1); - - if ((s = regvalue(matches[3], line)) == NULL) - s = "0"; - papiAttributeListAddInteger(&attributes, PAPI_ATTR_REPLACE, - "job-id", atoi(s)); - - if ((s = regvalue(matches[4], line)) == NULL) - s = svc->uri->host; - papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE, - "job-originating-host-name", s); - } - - while ((fdgets(line, len, fd) != NULL) && - (regexec(&job_re, line, (size_t)0, NULL, 0) == REG_NOMATCH) && - (regexec(&wjob_re, line, (size_t)0, NULL, 0) == REG_NOMATCH)) { - int size = 0, copies = 1; - /* process copies/documents */ - - /* doc1_re and doc2_re were compiled in the calling function */ - if ((regexec(&doc1_re, line, (size_t)4, matches, 0) != 0) && - (regexec(&doc2_re, line, (size_t)4, matches, 0) != 0)) - continue; - - if ((s = regvalue(matches[1], line)) == NULL) - s = "1"; - if ((copies = atoi(s)) < 1) - copies = 1; - - if ((s = regvalue(matches[2], line)) == NULL) - s = "unknown"; - papiAttributeListAddString(&attributes, - PAPI_ATTR_APPEND, "job-name", s); - papiAttributeListAddString(&attributes, - PAPI_ATTR_APPEND, "job-file-names", s); - - if ((s = regvalue(matches[3], line)) == NULL) - s = "0"; - size = atoi(s); - - papiAttributeListAddInteger(&attributes, - PAPI_ATTR_APPEND, "job-file-sizes", size); - - octets += (size * copies); - } - - papiAttributeListAddInteger(&attributes, PAPI_ATTR_APPEND, - "job-k-octets", octets/1024); - papiAttributeListAddInteger(&attributes, PAPI_ATTR_APPEND, - "job-octets", octets); - papiAttributeListAddString(&attributes, PAPI_ATTR_APPEND, - "printer-name", queue_name_from_uri(svc->uri)); - - if ((*job = (job_t *)calloc(1, sizeof (**job))) != NULL) - (*job)->attributes = attributes; -} - -void -parse_lpd_query(service_t *svc, int fd) -{ - papi_attribute_t **attributes = NULL; - cache_t *cache = NULL; - int state = 0x03; /* idle */ - char line[128]; - char status[1024]; - char *s; - int win_flag = 0; - - papiAttributeListAddString(&attributes, PAPI_ATTR_APPEND, - "printer-name", queue_name_from_uri(svc->uri)); - - if (uri_to_string(svc->uri, status, sizeof (status)) == 0) - papiAttributeListAddString(&attributes, PAPI_ATTR_APPEND, - "printer-uri-supported", status); - - /* - * on most systems, status is a single line, but some appear to - * return multi-line status messages. To get the "best" possible - * printer-state-reason, we accumulate the text until we hit the - * first print job entry. - * - * Print job entries start with: - * user: rank [job number ...] - */ - (void) regcomp(&job_re, job_expr, REG_EXTENDED|REG_ICASE); - - /* - * For remote windows printers - * Print job entries start with: - * Owner Status Jobname Job-Id Size Pages Priority - */ - (void) regcomp(&wjob_re, wjob_expr, REG_EXTENDED|REG_ICASE); - (void) regcomp(&whjob_re, whjob_expr, REG_EXTENDED|REG_ICASE); - (void) regcomp(&wline_re, wline_expr, REG_EXTENDED|REG_ICASE); - - status[0] = '\0'; - - while ((fdgets(line, sizeof (line), fd) != NULL) && - (regexec(&job_re, line, (size_t)0, NULL, 0) == REG_NOMATCH) && - (regexec(&wjob_re, line, (size_t)0, NULL, 0) == REG_NOMATCH)) { - /* - * When windows job queue gets queried following header - * should not get printed - * Owner Status Jobname Job-Id Size Pages Priority - * ----------------------------------------------- - */ - if ((regexec(&whjob_re, line, (size_t)0, NULL, 0) - == REG_NOMATCH) && - (regexec(&wline_re, line, (size_t)0, NULL, 0) - == REG_NOMATCH)) - strlcat(status, line, sizeof (status)); - } - - /* chop off trailing whitespace */ - s = status + strlen(status) - 1; - while ((s > status) && (isspace(*s) != 0)) - *s-- = '\0'; - - papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE, - "printer-state-reasons", status); - - /* Check if this is for Windows remote printers */ - if (strstr(status, "Windows")) { - /* - * It is a remote windows printer - * By default set the status as idle - * Set the printer-state after call to "parse_lpd_job" - */ - win_flag = 1; - (void) regcomp(&state_reason_re, state_reason_expr, - REG_EXTENDED|REG_ICASE); - - if (regexec(&state_reason_re, status, (size_t)0, NULL, 0) == 0) - state = 0x05; /* stopped */ - } else { - (void) regcomp(&proc_re, proc_expr, REG_EXTENDED|REG_ICASE); - (void) regcomp(&idle_re, idle_expr, REG_EXTENDED|REG_ICASE); - - if (regexec(&proc_re, status, (size_t)0, NULL, 0) == 0) - state = 0x04; /* processing */ - else if (regexec(&idle_re, status, (size_t)0, NULL, 0) == 0) - state = 0x03; /* idle */ - else - state = 0x05; /* stopped */ - papiAttributeListAddInteger(&attributes, PAPI_ATTR_REPLACE, - "printer-state", state); - } - - if ((cache = (cache_t *)calloc(1, sizeof (*cache))) == NULL) - return; - - if ((cache->printer = (printer_t *)calloc(1, sizeof (*cache->printer))) - == NULL) - return; - - cache->printer->attributes = attributes; - svc->cache = cache; - - (void) regcomp(&doc1_re, doc1_expr, REG_EXTENDED|REG_ICASE); - (void) regcomp(&doc2_re, doc2_expr, REG_EXTENDED|REG_ICASE); - /* process job related entries */ - while (line[0] != '\0') { - job_t *job = NULL; - - parse_lpd_job(svc, &job, fd, line, sizeof (line)); - if (job == NULL) - break; - list_append(&cache->jobs, job); - } - - /* - * For remote windows printer set the printer-state - * after parse_lpd_job - */ - if (win_flag) { - if (state == 0x05) - win_state = state; - - papiAttributeListAddInteger(&attributes, PAPI_ATTR_REPLACE, - "printer-state", win_state); - } - time(&cache->timestamp); -} - -void -cache_update(service_t *svc) -{ - int fd; - - if (svc == NULL) - return; - - if (svc->cache != NULL) { /* this should be time based */ - if (svc->cache->jobs == NULL) { - free(svc->cache); - svc->cache = NULL; - } else - return; - } - - if ((fd = lpd_open(svc, 'q', NULL, 15)) < 0) - return; - - parse_lpd_query(svc, fd); - - close(fd); -} - -papi_status_t -lpd_find_printer_info(service_t *svc, printer_t **printer) -{ - papi_status_t result = PAPI_BAD_ARGUMENT; - - if ((svc == NULL) || (printer == NULL)) - return (PAPI_BAD_ARGUMENT); - - cache_update(svc); - - if (svc->cache != NULL) { - *printer = svc->cache->printer; - result = PAPI_OK; - } else - result = PAPI_NOT_FOUND; - - return (result); -} - -papi_status_t -lpd_find_jobs_info(service_t *svc, job_t ***jobs) -{ - papi_status_t result = PAPI_BAD_ARGUMENT; - - if (svc != NULL) { - cache_update(svc); - - if (svc->cache != NULL) { - *jobs = svc->cache->jobs; - result = PAPI_OK; - } - } - - /* - * cache jobs is free()-ed in - * libpapi-dynamic/common/printer.c - - * papiPrinterListJobs() cache printer is - * free()-ed by the caller of - * lpd_find_printer_info Invalidate the - * cache by freeing the cache. - */ - free(svc->cache); - svc->cache = NULL; - - return (result); -} - -papi_status_t -lpd_find_job_info(service_t *svc, int job_id, job_t **job) -{ - papi_status_t result = PAPI_BAD_ARGUMENT; - job_t **jobs; - - if ((lpd_find_jobs_info(svc, &jobs) == PAPI_OK) && (jobs != NULL)) { - int i; - - *job = NULL; - for (i = 0; ((*job == NULL) && (jobs[i] != NULL)); i++) { - int id = -1; - - papiAttributeListGetInteger(jobs[i]->attributes, NULL, - "job-id", &id); - if (id == job_id) - *job = jobs[i]; - } - - if (*job != NULL) - result = PAPI_OK; - } - - return (result); -} - -void -cache_free(cache_t *item) -{ - if (item != NULL) { - if (item->printer != NULL) - papiPrinterFree((papi_printer_t *)item->printer); - if (item->jobs != NULL) - papiJobListFree((papi_job_t *)item->jobs); - free(item); - } -} diff --git a/usr/src/lib/print/libpapi-lpd/common/mapfile b/usr/src/lib/print/libpapi-lpd/common/mapfile deleted file mode 100644 index 2ad5020f15..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/mapfile +++ /dev/null @@ -1,322 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# $Id: mapfile.in,v 1.2 2006/03/02 06:31:36 njacobs Exp $ -# - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -$mapfile_version 2 - -# -# Common interfaces that are most likely to be shared amongst the various -# PAPI implementations. -# - -SYMBOL_VERSION SUNW_1.0 { - global: - # PAPI Attribute Calls - papiAttributeListAddValue { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddBoolean { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddCollection { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddDatetime { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddInteger { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddMetadata { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddRange { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddResolution { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListAddString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListDelete { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetValue { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetNext { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListFind { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetBoolean { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetCollection { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetDatetime { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetInteger { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetMetadata { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetRange { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetResolution { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListGetString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListFromString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListToString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListFree { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - # PAPI Service Calls - papiServiceCreate ; - papiServiceDestroy ; - papiServiceSetUserName ; - papiServiceSetPassword ; - papiServiceSetEncryption ; - papiServiceSetAuthCB ; - papiServiceSetAppData ; - papiServiceGetUserName ; - papiServiceGetPassword ; - papiServiceGetEncryption ; - papiServiceGetAppData ; - papiServiceGetServiceName ; - papiServiceGetAttributeList ; - papiServiceGetStatusMessage ; - - # PAPI Printer Calls - papiPrintersList { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiPrinterQuery ; - papiPrinterAdd { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiPrinterModify { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiPrinterRemove { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiPrinterDisable ; - papiPrinterEnable ; - papiPrinterPause ; - papiPrinterResume ; - papiPrinterPurgeJobs ; - papiPrinterListJobs ; - papiPrinterGetAttributeList ; - papiPrinterFree ; - papiPrinterListFree ; - - # PAPI Job Calls - papiJobSubmit ; - papiJobSubmitByReference ; - papiJobValidate { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobStreamOpen ; - papiJobStreamWrite ; - papiJobStreamClose ; - papiJobQuery ; - papiJobModify { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobMove { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobCancel ; - papiJobHold { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobRelease { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobRestart { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobPromote { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobGetAttributeList ; - papiJobGetPrinterName ; - papiJobGetId ; - papiJobGetJobTicket { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobFree ; - papiJobListFree ; - - # Misc. PAPI Calls - papiStatusString { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiLibrarySupportedCall ; - papiLibrarySupportedCalls ; -} ; - -SYMBOL_VERSION SUNWprivate_1.0 { - global: - papiServiceSetPeer { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobCreate { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobStreamAdd { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiJobCommit { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - # Misc. supporting calls - # URI - uri_from_string { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - uri_to_string { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - uri_free { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - # list - list_remove { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - list_append { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - list_concatenate { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - # NS - getprinterbyname { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - is_localhost { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - # extra Attribute Calls - copy_attributes { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - split_and_copy_attributes { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - papiAttributeListPrint { - TYPE = FUNCTION; - FILTER = libpapi-common.so; - } ; - - local: - * ; -} ; diff --git a/usr/src/lib/print/libpapi-lpd/common/papi_impl.h b/usr/src/lib/print/libpapi-lpd/common/papi_impl.h deleted file mode 100644 index 82d955b3cb..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/papi_impl.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -#ifndef _PAPI_IMPL_H -#define _PAPI_IMPL_H - -/* $Id: papi_impl.h 161 2006-05-03 04:32:59Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <papi.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#include <time.h> -#include <sys/types.h> -#include <stdarg.h> -#include <uri.h> - -typedef struct { - papi_attribute_t **attributes; -} printer_t; - -typedef struct job { - papi_attribute_t **attributes; -} job_t; - -typedef struct stream { - job_t *job; /* describes current job */ - int fd; /* the fd to write to */ - char *metadata; /* the converted metadata */ - char *dfname; /* the stream data (if we can't stream) */ - -} stream_t; - -typedef struct { /* used for query operations only */ - time_t timestamp; - printer_t *printer; - job_t **jobs; -} cache_t; - -typedef struct { - papi_attribute_t **attributes; /* extra info */ - uri_t *uri; /* printer uri */ - cache_t *cache; /* printer/job cache */ - int (*authCB)(papi_service_t svc, void *app_data); /* unused */ - void *app_data; /* unused */ -} service_t; - - -extern papi_status_t service_fill_in(service_t *svc, char *name); -extern void detailed_error(service_t *svc, char *fmt, ...); -extern char *queue_name_from_uri(uri_t *uri); -extern char *fdgets(char *buf, size_t len, int fd); - - -/* lpd operations */ - /* open a connection to remote print service */ -extern int lpd_open(service_t *svc, char type, char **args, - int timeout); - /* job cancelation */ -extern papi_status_t lpd_purge_jobs(service_t *svc, job_t ***jobs); -extern papi_status_t lpd_cancel_job(service_t *svc, int job_id); - /* job submission */ -extern papi_status_t lpd_submit_job(service_t *svc, char *metadata, - papi_attribute_t ***attributes, int *fd); -extern papi_status_t lpd_job_add_attributes(service_t *svc, - papi_attribute_t **attributes, - char **metadata, - papi_attribute_t ***used_attributes); -extern papi_status_t lpd_job_add_files(service_t *svc, - papi_attribute_t **attributes, char **files, - char **metadata, - papi_attribute_t ***used_attributes); - /* query cache lookup routines */ -extern papi_status_t lpd_find_printer_info(service_t *svc, printer_t **result); -extern papi_status_t lpd_find_job_info(service_t *svc, int job_id, job_t **job); -extern papi_status_t lpd_find_jobs_info(service_t *svc, job_t ***jobs); - - -#ifdef __cplusplus -} -#endif - -#endif /* _PAPI_IMPL_H */ diff --git a/usr/src/lib/print/libpapi-lpd/common/printer.c b/usr/src/lib/print/libpapi-lpd/common/printer.c deleted file mode 100644 index 308d9c9443..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/printer.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: printer.c 149 2006-04-25 16:55:01Z njacobs $ */ - -#include <stdlib.h> -#include <strings.h> -#include <papi_impl.h> -#include <libintl.h> - -static int -contains(char *value, char **list) -{ - int i; - - if ((value == NULL) || (list == NULL)) - return (1); - - for (i = 0; list[i] != NULL; i++) - if (strcasecmp(value, list[i]) == 0) - return (1); - - return (0); -} - -papi_status_t -papiPrinterQuery(papi_service_t handle, char *name, - char **requested_attrs, - papi_attribute_t **job_attributes, - papi_printer_t *printer) -{ - papi_status_t status; - service_t *svc = handle; - printer_t *p = NULL; - - if ((svc == NULL) || (name == NULL) || (printer == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((status = service_fill_in(svc, name)) == PAPI_OK) { - *printer = NULL; - - if ((contains("printer-state", requested_attrs) == 1) || - (contains("printer-state-reasons", requested_attrs) == 1)) - status = lpd_find_printer_info(svc, - (printer_t **)printer); - - if ((status == PAPI_OK) && (*printer == NULL)) { - char buf[BUFSIZ]; - - *printer = p = calloc(1, sizeof (*p)); - - papiAttributeListAddString(&(p->attributes), - PAPI_ATTR_APPEND, "printer-name", - queue_name_from_uri(svc->uri)); - - if (uri_to_string(svc->uri, buf, sizeof (buf)) == 0) - papiAttributeListAddString(&(p->attributes), - PAPI_ATTR_APPEND, - "printer-uri-supported", buf); - } - /* Set printer accepting: mimic prepapi behavior */ - if ((p = *printer) != NULL) - papiAttributeListAddBoolean(&(p->attributes), - PAPI_ATTR_REPLACE, - "printer-is-accepting-jobs", PAPI_TRUE); - - } - - return (status); -} - -papi_status_t -papiPrinterPurgeJobs(papi_service_t handle, char *name, papi_job_t **jobs) -{ - papi_status_t status; - service_t *svc = handle; - - if ((svc == NULL) || (name == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((status = service_fill_in(svc, name)) == PAPI_OK) - status = lpd_purge_jobs(svc, (job_t ***)jobs); - - return (status); -} - -papi_status_t -papiPrinterListJobs(papi_service_t handle, char *name, - char **requested_attrs, int type_mask, - int max_num_jobs, papi_job_t **jobs) -{ - papi_status_t status; - service_t *svc = handle; - - if ((svc == NULL) || (name == NULL) || (jobs == NULL)) - return (PAPI_BAD_ARGUMENT); - - if ((status = service_fill_in(svc, name)) == PAPI_OK) - status = lpd_find_jobs_info(svc, (job_t ***)jobs); - - return (status); -} - -papi_attribute_t ** -papiPrinterGetAttributeList(papi_printer_t printer) -{ - printer_t *p = printer; - - if (p == NULL) - return (NULL); - - return (p->attributes); -} - -void -papiPrinterFree(papi_printer_t printer) -{ - printer_t *p = printer; - - if (p != NULL) { - if (p->attributes != NULL) - papiAttributeListFree(p->attributes); - free(p); - } -} - -void -papiPrinterListFree(papi_printer_t *printers) -{ - if (printers != NULL) { - int i; - - for (i = 0; printers[i] != NULL; i++) - papiPrinterFree(printers[i]); - free(printers); - } -} - - -papi_status_t -papiPrinterDisable(papi_service_t handle, char *name, char *message) -{ - service_t *svc = handle; - papi_status_t status; - - if ((status = service_fill_in(svc, name)) == PAPI_OK) { - detailed_error(svc, - gettext("Warning: %s is remote, disable has no meaning."), - queue_name_from_uri(svc->uri)); - } - return (PAPI_OPERATION_NOT_SUPPORTED); -} - -papi_status_t -papiPrinterEnable(papi_service_t handle, char *name) -{ - service_t *svc = handle; - papi_status_t status; - - if ((status = service_fill_in(svc, name)) == PAPI_OK) { - detailed_error(svc, - gettext("Warning: %s is remote, enable has no meaning."), - queue_name_from_uri(svc->uri)); - } - return (PAPI_OPERATION_NOT_SUPPORTED); -} - - -papi_status_t -papiPrinterResume(papi_service_t handle, char *name) -{ - service_t *svc = handle; - papi_status_t status; - - if ((status = service_fill_in(svc, name)) == PAPI_OK) { - detailed_error(svc, - gettext("Warning: %s is remote, accept has no meaning."), - queue_name_from_uri(svc->uri)); - } - return (PAPI_OPERATION_NOT_SUPPORTED); -} - - -papi_status_t -papiPrinterPause(papi_service_t handle, char *name, char *message) -{ - service_t *svc = handle; - papi_status_t status; - - if ((status = service_fill_in(svc, name)) == PAPI_OK) { - detailed_error(svc, - gettext("Warning: %s is remote, reject has no meaning."), - queue_name_from_uri(svc->uri)); - } - return (PAPI_OPERATION_NOT_SUPPORTED); -} diff --git a/usr/src/lib/print/libpapi-lpd/common/service.c b/usr/src/lib/print/libpapi-lpd/common/service.c deleted file mode 100644 index c39ea0cbb5..0000000000 --- a/usr/src/lib/print/libpapi-lpd/common/service.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: service.c 163 2006-05-09 15:07:45Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <alloca.h> -#include <uri.h> -#include <papi_impl.h> - -papi_status_t -service_fill_in(service_t *svc, char *name) -{ - papi_status_t status = PAPI_OK; - uri_t *uri = NULL; - - if (svc == NULL) - return (PAPI_BAD_ARGUMENT); - - if (name == NULL) - return (PAPI_OK); - - /* - * valid URIs are in the form: - * lpd://server[:port]/.../queue[#extensions] - * rfc-1179://server[:port]/.../queue[#extensions] - * any authentication information supplied the URI is ignored. - */ - if (uri_from_string((char *)name, &uri) != -1) { - if ((strcasecmp(uri->scheme, "lpd") == 0) || - (strcasecmp(uri->scheme, "rfc-1179") == 0)) { - if (svc->uri != NULL) - uri_free(svc->uri); - svc->uri = uri; - } else { - uri_free(uri); - status = PAPI_URI_SCHEME; - } - } - - return (status); -} - -papi_status_t -papiServiceCreate(papi_service_t *handle, char *service_name, - char *user_name, char *password, - int (*authCB)(papi_service_t svc, void *app_data), - papi_encryption_t encryption, void *app_data) -{ - papi_status_t status; - service_t *svc = NULL; - - if (handle == NULL) - return (PAPI_BAD_ARGUMENT); - - if ((*handle = svc = (service_t *)calloc(1, sizeof (*svc))) == NULL) - return (PAPI_TEMPORARY_ERROR); - - if (service_name != NULL) - papiAttributeListAddString(&svc->attributes, PAPI_ATTR_EXCL, - "service-name", service_name); - - (void) papiServiceSetUserName(svc, user_name); - (void) papiServiceSetPassword(svc, password); - (void) papiServiceSetAuthCB(svc, authCB); - (void) papiServiceSetAppData(svc, app_data); - (void) papiServiceSetEncryption(svc, encryption); - - status = service_fill_in(svc, service_name); - - return (status); -} - -void -papiServiceDestroy(papi_service_t handle) -{ - if (handle != NULL) { - service_t *svc = handle; - -#ifdef DEADBEEF - if (svc->cache != NULL) - cache_free(svc->cache); -#endif - if (svc->uri != NULL) - uri_free(svc->uri); - if (svc->attributes != NULL) - papiAttributeListFree(svc->attributes); - free(svc); - } -} - -papi_status_t -papiServiceSetUserName(papi_service_t handle, char *user_name) -{ - service_t *svc = handle; - - if (svc == NULL) - return (PAPI_BAD_ARGUMENT); - - return (papiAttributeListAddString(&svc->attributes, PAPI_ATTR_REPLACE, - "user-name", user_name)); -} - -papi_status_t -papiServiceSetPassword(papi_service_t handle, char *password) -{ - service_t *svc = handle; - - if (svc == NULL) - return (PAPI_BAD_ARGUMENT); - - return (papiAttributeListAddString(&svc->attributes, - PAPI_ATTR_REPLACE, "password", password)); -} - -papi_status_t -papiServiceSetEncryption(papi_service_t handle, - papi_encryption_t encryption) -{ - service_t *svc = handle; - - if (svc == NULL) - return (PAPI_BAD_ARGUMENT); - - return (papiAttributeListAddInteger(&svc->attributes, PAPI_ATTR_REPLACE, - "encryption", (int)encryption)); -} - -papi_status_t -papiServiceSetAuthCB(papi_service_t handle, - int (*authCB)(papi_service_t svc, void *app_data)) -{ - service_t *svc = handle; - - if (svc == NULL) - return (PAPI_BAD_ARGUMENT); - - svc->authCB = (int (*)(papi_service_t svc, void *))authCB; - - return (PAPI_OK); -} - -papi_status_t -papiServiceSetAppData(papi_service_t handle, void *app_data) -{ - service_t *svc = handle; - - if (svc == NULL) - return (PAPI_BAD_ARGUMENT); - - svc->app_data = (void *)app_data; - - return (PAPI_OK); -} - -char * -papiServiceGetServiceName(papi_service_t handle) -{ - service_t *svc = handle; - char *result = NULL; - - if (svc != NULL) - papiAttributeListGetString(svc->attributes, NULL, - "service-name", &result); - - return (result); -} - -char * -papiServiceGetUserName(papi_service_t handle) -{ - service_t *svc = handle; - char *result = NULL; - - if (svc != NULL) - papiAttributeListGetString(svc->attributes, NULL, - "user-name", &result); - - return (result); - -} - -char * -papiServiceGetPassword(papi_service_t handle) -{ - service_t *svc = handle; - char *result = NULL; - - if (svc != NULL) - papiAttributeListGetString(svc->attributes, NULL, - "password", &result); - - return (result); -} - -papi_encryption_t -papiServiceGetEncryption(papi_service_t handle) -{ - service_t *svc = handle; - papi_encryption_t result = PAPI_ENCRYPT_NEVER; - - if (svc != NULL) - papiAttributeListGetInteger(svc->attributes, NULL, - "encryption", (int *)&result); - - return (result); -} - -void * -papiServiceGetAppData(papi_service_t handle) -{ - service_t *svc = handle; - void *result = NULL; - - if (svc != NULL) { - result = svc->app_data; - } - - return (result); - -} - -papi_attribute_t ** -papiServiceGetAttributeList(papi_service_t handle) -{ - service_t *svc = handle; - papi_attribute_t **result = NULL; - - if (svc != NULL) - result = svc->attributes; - - return (result); -} - -char * -papiServiceGetStatusMessage(papi_service_t handle) -{ - service_t *svc = handle; - char *result = NULL; - - if (svc != NULL) { - papiAttributeListGetString(svc->attributes, NULL, - "detailed-status-message", &result); - } - - return (result); -} - -void -detailed_error(service_t *svc, char *fmt, ...) -{ - if ((svc != NULL) && (fmt != NULL)) { - va_list ap; - size_t size; - char *message = alloca(BUFSIZ); - - va_start(ap, fmt); - /* - * fill in the message. If the buffer is too small, allocate - * one that is large enough and fill it in. - */ - if ((size = vsnprintf(message, BUFSIZ, fmt, ap)) >= BUFSIZ) - if ((message = alloca(size)) != NULL) - vsnprintf(message, size, fmt, ap); - va_end(ap); - - papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND, - "detailed-status-message", message); - } -} diff --git a/usr/src/lib/print/libpapi-lpd/i386/Makefile b/usr/src/lib/print/libpapi-lpd/i386/Makefile deleted file mode 100644 index 362f811e03..0000000000 --- a/usr/src/lib/print/libpapi-lpd/i386/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBDIR) $(ROOTLIBS) $(ROOTLINKS) $(EXTRALINKS) \ - $(ROOTLIBPRINTPROG) diff --git a/usr/src/lib/print/libpapi-lpd/sparc/Makefile b/usr/src/lib/print/libpapi-lpd/sparc/Makefile deleted file mode 100644 index 362f811e03..0000000000 --- a/usr/src/lib/print/libpapi-lpd/sparc/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBDIR) $(ROOTLIBS) $(ROOTLINKS) $(EXTRALINKS) \ - $(ROOTLIBPRINTPROG) diff --git a/usr/src/lib/print/libprint/Makefile.com b/usr/src/lib/print/libprint/Makefile.com deleted file mode 100644 index 88fbb532b0..0000000000 --- a/usr/src/lib/print/libprint/Makefile.com +++ /dev/null @@ -1,58 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -LIBRARY = libprint.a -VERS = .2 -OBJECTS = \ - list.o ns.o ns_bsd_addr.o ns_cmn_kvp.o \ - ns_cmn_printer.o nss_convert.o nss_ldap.o nss_printer.o nss_write.o - -include ../../../Makefile.lib -include ../../../Makefile.rootfs - -SRCDIR = ../common - -ROOTLIBDIR= $(ROOT)/usr/lib - -LIBS = $(DYNLIB) - -$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRCDIR) -CPPFLAGS += -I../../head -D_REENTRANT - -LDLIBS += -lnsl -lsocket -lc -lldap - - -.KEEP_STATE: - -all: $(LIBS) - -lint: lintcheck - -include ../../../Makefile.targ diff --git a/usr/src/lib/print/libprint/common/list.c b/usr/src/lib/print/libprint/common/list.c deleted file mode 100644 index fd90e58130..0000000000 --- a/usr/src/lib/print/libprint/common/list.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <stdarg.h> -#include <syslog.h> -#include <stdlib.h> -#include <strings.h> - -#include <list.h> - - -static int _list_increment = 64; /* just so It can be tuned with adb(1) */ -/* - * list_append() takes in a list (type **) and a pointer to an item to add - * to the list and returns a new list with the new item appended on the - * end. The list is NULL terminated. If there was an error, NULL is - * returned. For reasonable efficiency, the list will be allocated - * in blocks of size _list_increment. - */ -void ** -list_append(void **list, void *item) -{ -#ifdef DEBUG - syslog(LOG_DEBUG, "list_append(0x%x, 0x%x)", list, item); -#endif - if (item == NULL) - return (list); - - if (list == NULL) { - list = (void **)calloc(_list_increment, sizeof (void *)); - (void) memset(list, NULL, (_list_increment * sizeof (void *))); - list[0] = item; - } else { - int count; - - for (count = 0; list[count] != NULL; count++); - - if ((count + 1) % _list_increment == 0) { /* increase size */ - void **new_list = NULL; - int new_size = (((count + 1) / _list_increment) + 1) * - _list_increment; - - new_list = (void **)calloc(new_size, - sizeof (void *)); - (void) memset(new_list, NULL, - (new_size * sizeof (void *))); - for (count = 0; list[count] != NULL; count++) - new_list[count] = list[count]; - free(list); - list = new_list; - } - list[count] = item; - } - return (list); -} - - -void ** -list_append_unique(void **list, void *item, int (*cmp)(void *, void*)) -{ - if (list_locate(list, cmp, item)) - return (list); - - list = list_append(list, item); - return (list); -} - - -/* - * list_locate() iterates through the list passed in and uses the comparison - * routine and element passed in to find an element in the list. It - * returns the first element matched, or NULL if none exists - */ -void * -list_locate(void **list, int (*compair)(void *, void *), void *element) -{ - int current = 0; - -#ifdef DEBUG - syslog(LOG_DEBUG, "list_locate()"); -#endif - if (list != NULL) - for (current = 0; list[current] != NULL; current++) - if ((compair)(list[current], element) == 0) - return (list[current]); - return (NULL); -} - - -/* - * list_concatenate() takes in two NULL terminated lists of items (type **) - * and creates a new list with items from list2 appended on the end of - * the list of items from list1. The result is a list (type **). If - * there is a failure, NULL is returned. - */ -void ** -list_concatenate(void **list1, void **list2) -{ - void **list = NULL; - int size1 = 0, - size2 = 0, - new_size = 0; -#ifdef DEBUG - syslog(LOG_DEBUG, "list_concatenate(0x%x, 0x%x)", list1, list2); -#endif - if ((list1 == NULL) || (list2 == NULL)) - return ((list1 != NULL) ? list1 : list2); - - for (size1 = 0; list1[size1] != NULL; size1++); - for (size2 = 0; list2[size2] != NULL; size2++); - - /* list1 + list2 padded to a multiple of _list_increment */ - new_size = ((size1 + size2)/_list_increment + 2) * _list_increment; - - if ((list = (void **)calloc((new_size), sizeof (void *))) - != NULL) { - int count = 0; - - (void) memset(list, NULL, (new_size * sizeof (void *))); - - for (size1 = 0; list1[size1] != NULL; size1++) - list[count++] = list1[size1]; - for (size2 = 0; list2[size2] != NULL; size2++) - list[count++] = list2[size2]; - free(list1); - } - return (list); -} - - -/* - * list_iterate() take in a list, pointer to a function, and variable number - * of arguements following. list_iterate() will iterate through the list - * calling the functions passed in with the first argument being a pointer - * to the current item in the list and the second argument being a va_list - * containing the rest of arguments used to call list_iterate(). The - * calling fuction should be declared: int func(type *, va_list). The - * return results are all added together and the sum is returned from - * list_iterate(). - */ -int -list_iterate(void **list, int (*vfunc)(void *, va_list), ...) -{ - int current = 0, - rc = 0; - -#ifdef DEBUG - syslog(LOG_DEBUG, "list_iterate(0x%x, 0x%x)", list, vfunc); -#endif - if (list != NULL) - while (list[current] != NULL) { - va_list ap; - - va_start(ap, (vfunc)); - rc += (vfunc)(list[current++], ap); - va_end(ap); - } - return (rc); -} diff --git a/usr/src/lib/print/libprint/common/llib-lprint b/usr/src/lib/print/libprint/common/llib-lprint deleted file mode 100644 index c52143e527..0000000000 --- a/usr/src/lib/print/libprint/common/llib-lprint +++ /dev/null @@ -1,141 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* LINTLIBRARY */ -/* PROTOLIB1 */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <arpa/inet.h> -#include <dirent.h> -#include <dlfcn.h> -#include <errno.h> -#include <fcntl.h> -#include <libintl.h> -#include <netdb.h> -#include <netinet/in.h> -#include <pwd.h> -#include <rpc/rpc.h> -#include <rpcsvc/yp_prot.h> -#include <rpcsvc/ypclnt.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/mman.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/systeminfo.h> -#include <sys/types.h> -#include <syslog.h> -#include <unistd.h> - -void **list_append(void **, void *); -void **list_append_unique(void **, void *, int (*)(void *, void*)); -void **list_concatenate(void **, void **); -void * list_locate(void **, int (*)(void *, void *), void *); -int list_iterate(void **, int (*)(void *, __va_list), ...); - -void *dynamic_function(const char *, const char *); - -struct ns_bsd_addr { - char *server; /* server name */ - char *printer; /* printer name or NULL */ - char *extension; /* RFC-1179 conformance */ - char *pname; /* Local printer name */ -}; -typedef struct ns_bsd_addr ns_bsd_addr_t; - -/* Key/Value pair structure */ -struct ns_kvp { - char *key; /* key */ - char *value; /* value string */ -}; -typedef struct ns_kvp ns_kvp_t; - -/* Printer Object structure */ -struct ns_printer { - char *name; /* primary name of printer */ - char **aliases; /* aliases for printer */ - char *source; /* name service derived from */ - ns_kvp_t **attributes; /* key/value pairs. */ -}; -typedef struct ns_printer ns_printer_t; - -/* functions to get/put printer objects */ -ns_printer_t *ns_printer_create(char *, char **, char *, ns_kvp_t **); -ns_printer_t *ns_printer_get_name(const char *, const char *); -ns_printer_t **ns_printer_get_list(const char *); -int ns_printer_put(const ns_printer_t *); -void ns_printer_destroy(ns_printer_t *); - -/* functions to manipulate key/value pairs */ -void *ns_get_value(const char *, const ns_printer_t *); -char *ns_get_value_string(const char *, const ns_printer_t *); -int ns_set_value(const char *, const void *, ns_printer_t *); -int ns_set_value_from_string(const char *, const char *, - ns_printer_t *); -ns_kvp_t *ns_kvp_create(const char *, const char *); - -/* for BSD bindings only */ -ns_bsd_addr_t *ns_bsd_addr_get_default(void); -ns_bsd_addr_t *ns_bsd_addr_get_name(char *name); -ns_bsd_addr_t **ns_bsd_addr_get_all(int); -ns_bsd_addr_t **ns_bsd_addr_get_list(int); - -/* others */ -ns_printer_t *posix_name(const char *); -int ns_printer_match_name(ns_printer_t *, const char *); -char *ns_printer_name_list(const ns_printer_t *); -char *value_to_string(const char *, void *); -void *string_to_value(const char *, char *); - - -ns_printer_t *_cvt_pconf_entry_to_printer(char *, char *); -char *_cvt_printer_to_pconf_entry(ns_printer_t *); - -ns_printer_t *_cvt_user_string_to_printer(char *, char *); -char *_cvt_printer_to_user_string(ns_printer_t *); - - -ns_printer_t *_file_get_name(const char *, const char *, - ns_printer_t *(*)(char *, char *), char *); - -ns_printer_t **_file_get_list(const char *, - ns_printer_t *(*)(char *, char *), char *); - -int _file_put_printer(const char *, const ns_printer_t *, - ns_printer_t *(*)(char *, char *), char *, char *(*)(ns_printer_t *)); - - -ns_printer_t *_nis_get_name(const char *, const char *, - ns_printer_t *(*)(char *, char *), char *); - -ns_printer_t **_nis_get_list(const char *, - ns_printer_t *(*)(char *, char *), char *); - -int _nis_put_printer(const char *, const ns_printer_t *, - ns_printer_t *(*)(char *, char *), char *, char *(*)(ns_printer_t *)); diff --git a/usr/src/lib/print/libprint/common/mapfile-vers b/usr/src/lib/print/libprint/common/mapfile-vers deleted file mode 100644 index 776e97beca..0000000000 --- a/usr/src/lib/print/libprint/common/mapfile-vers +++ /dev/null @@ -1,86 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -$mapfile_version 2 - -# -# Generic interface definition for usr/src/lib/print. -# - -SYMBOL_VERSION SUNWprivate_2.1 { - global: - getprinterbyname; # NSS support - getprinterentry; - setprinterentry; - endprinterentry; - - ns_printer_create; # Old NS support - ns_printer_get_name; - ns_printer_get_list; - ns_printer_put; - ns_printer_destroy; - ns_get_value; - ns_get_value_string; - ns_set_value; - ns_set_value_from_string; - ns_kvp_create; - ns_bsd_addr_get_default; - ns_bsd_addr_get_name; - ns_bsd_addr_get_all; - ns_bsd_addr_get_list; - string_to_bsd_addr; - bsd_addr_create; - ns_printer_match_name; - ns_printer_name_list; - value_to_string; - string_to_value; - normalize_ns_name; - - list_append; # list support - list_append_unique; - list_concatenate; - list_locate; - list_iterate; - - files_put_printer; # required for ns_put_printer() - nis_put_printer; - ldap_put_printer; - - local: - *; -}; diff --git a/usr/src/lib/print/libprint/common/ns.c b/usr/src/lib/print/libprint/common/ns.c deleted file mode 100644 index 943be31e95..0000000000 --- a/usr/src/lib/print/libprint/common/ns.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/*LINTLIBRARY*/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <string.h> -#include <stdarg.h> -#include <dlfcn.h> -#include <nss_dbdefs.h> -#include <syslog.h> - -#include <ns.h> -#include <list.h> - - -/* - * because legacy code can use a variety of values for various name - * services, this routine is needed to "normalize" them. - */ -char * -normalize_ns_name(char *ns) -{ - if (ns == NULL) - return (NULL); - else if ((strcasecmp(ns, "files") == 0) || - (strcasecmp(ns, "system") == 0) || - (strcasecmp(ns, "etc") == 0)) - return ("files"); - else if (strcasecmp(ns, "nis") == 0) - return ("nis"); - else if (strcasecmp(ns, "ldap") == 0) - return ("ldap"); - else - return (ns); -} - - -/* - * FUNCTION: - * void ns_printer_destroy(ns_printer_t *printer) - * INPUT: - * ns_printer_t *printer - a pointer to the printer "object" to destroy - * DESCRIPTION: - * This function will free all of the memory associated with a printer - * object. It does this by walking the structure ad freeing everything - * underneath it, with the exception of the object source field. This - * field is not filled in with newly allocated space when it is - * generated - */ -void -ns_printer_destroy(ns_printer_t *printer) -{ - if (printer != NULL) { - if (printer->attributes != NULL) { /* attributes */ - extern void ns_kvp_destroy(ns_kvp_t *); - - list_iterate((void **)printer->attributes, - (VFUNC_T)ns_kvp_destroy); - free(printer->attributes); - } - if (printer->aliases != NULL) { /* aliases */ - free(printer->aliases); - } - if (printer->name != NULL) /* primary name */ - free(printer->name); - free(printer); - } -} - - -/* - * FUNCTION: - * ns_printer_t **ns_printer_get_list() - * OUTPUT: - * ns_printer_t ** (return value) - an array of pointers to printer - * objects. - * DESCRIPTION: - * This function will return a list of all printer objects found in every - * configuration interface. - */ -ns_printer_t ** -ns_printer_get_list(const char *ns) -{ - char buf[NSS_LINELEN_PRINTERS]; - ns_printer_t **printer_list = NULL; - - (void) setprinterentry(0, (char *)ns); - - ns = normalize_ns_name((char *)ns); - while (getprinterentry(buf, sizeof (buf), (char *)ns) == 0) { - ns_printer_t *printer = - (ns_printer_t *)_cvt_nss_entry_to_printer(buf, NULL); - - printer_list = (ns_printer_t **)list_append( - (void **)printer_list, - (void *)printer); - } - - (void) endprinterentry(); - - return (printer_list); -} - - -/* - * This function looks for the named printer in the supplied - * name service (ns), or the name services configured under - * the nsswitch. - */ -ns_printer_t * -ns_printer_get_name(const char *name, const char *ns) -{ - ns_printer_t *result = NULL; - char buf[NSS_LINELEN_PRINTERS]; - - /* - * Reset printer entries to the start so we know we will always - * pick up the correct entry - */ - endprinterentry(); - - if ((result = (ns_printer_t *)posix_name(name)) != NULL) - return (result); - - ns = normalize_ns_name((char *)ns); - if (getprinterbyname((char *)name, buf, sizeof (buf), (char *)ns) == 0) - result = (ns_printer_t *)_cvt_nss_entry_to_printer(buf, NULL); - - return (result); -} - - -/* - * FUNCTION: - * int ns_printer_put(const ns_printer_t *printer) - * INPUT: - * const ns_printer_t *printer - a printer object - * DESCRIPTION: - * This function attempts to put the data in the printer object back - * to the "name service" specified in the source field of the object. - */ -int -ns_printer_put(const ns_printer_t *printer) -{ - char func[32]; - int (*fpt)(); - - if ((printer == NULL) || (printer->source == NULL)) - return (-1); - - if (snprintf(func, sizeof (func), "%s_put_printer", - normalize_ns_name(printer->source)) >= sizeof (func)) { - syslog(LOG_ERR, "ns_printer_put: buffer overflow"); - return (-1); - } - - if ((fpt = (int (*)())dlsym(RTLD_DEFAULT, func)) != NULL) - return ((*fpt)(printer)); - - return (-1); -} diff --git a/usr/src/lib/print/libprint/common/ns.h b/usr/src/lib/print/libprint/common/ns.h deleted file mode 100644 index 84d16f7ceb..0000000000 --- a/usr/src/lib/print/libprint/common/ns.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _NS_H -#define _NS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Name Service Common Keys/types for lookup - */ -#define NS_KEY_BSDADDR "bsdaddr" -#define NS_KEY_USE "use" -#define NS_KEY_ALL "all" -#define NS_KEY_GROUP "group" -#define NS_KEY_LIST "list" - -#define NS_KEY_PRINTER_TYPE "printer-type" -#define NS_KEY_DESCRIPTION "description" - -/* - * Name Service reserved names for lookup - */ -#define NS_NAME_DEFAULT "_default" -#define NS_NAME_ALL "_all" - -/* - * Name Services supported - */ -#define NS_SVC_USER "user" -#define NS_SVC_PRINTCAP "printcap" -#define NS_SVC_ETC "etc" -#define NS_SVC_NIS "nis" -#define NS_SVC_LDAP "ldap" - -/* - * Known Protocol Extensions - */ -#define NS_EXT_SOLARIS "solaris" -#define NS_EXT_GENERIC "extensions" /* same as SOLARIS */ -#define NS_EXT_HPUX "hpux" -#define NS_EXT_DEC "dec" - -/* - * get unique or full list of printer bindings - */ -#define NOTUNIQUE 0 -#define UNIQUE 1 -#define LOCAL_UNIQUE 2 /* include alias names */ - -/* BSD binding address structure */ -struct ns_bsd_addr { - char *server; /* server name */ - char *printer; /* printer name or NULL */ - char *extension; /* RFC-1179 conformance */ - char *pname; /* Local printer name */ -}; -typedef struct ns_bsd_addr ns_bsd_addr_t; - -/* Key/Value pair structure */ -struct ns_kvp { - char *key; /* key */ - char *value; /* value string */ -}; -typedef struct ns_kvp ns_kvp_t; - - -/* LDAP specific result codes */ - -typedef enum NSL_RESULT -{ - NSL_OK = 0, /* Operation successful */ - NSL_ERR_INTERNAL = 1, /* Internal coding Error */ - NSL_ERR_ADD_FAILED = 2, /* LDAP add failed */ - NSL_ERR_MOD_FAILED = 3, /* LDAP modify failed */ - NSL_ERR_DEL_FAILED = 4, /* LDAP delete failed */ - NSL_ERR_UNKNOWN_PRINTER = 5, /* Unknown Printer object */ - NSL_ERR_CREDENTIALS = 6, /* LDAP credentials invalid */ - NSL_ERR_CONNECT = 7, /* LDAP server connect failed */ - NSL_ERR_BIND = 8, /* LDAP bind failed */ - NSL_ERR_RENAME = 9, /* Object rename is not allowed */ - NSL_ERR_KVP = 10, /* sun-printer-kvp not allowed */ - NSL_ERR_BSDADDR = 11, /* sun-printer-bsdaddr not allowed */ - NSL_ERR_PNAME = 12, /* printer-name not allowed */ - NSL_ERR_MEMORY = 13, /* memory allocation failed */ - NSL_ERR_MULTIOP = 14, /* Replace and delete operation */ - NSL_ERR_NOTALLOWED = 15, /* KVP attribute not allowed */ - NSL_ERROR = -1 /* General error */ -} NSL_RESULT; - - -/* LDAP bind password security type */ - -typedef enum NS_PASSWD_TYPE { - NS_PW_INSECURE = 0, - NS_PW_SECURE = 1 -} NS_PASSWD_TYPE; - - -/* - * Information needed to update a name service. - * Currently only used for ldap. - */ -struct ns_cred { - char *binddn; - char *passwd; - char *host; - int port; /* LDAP port, 0 = default */ - NS_PASSWD_TYPE passwdType; /* password security type */ - uchar_t *domainDN; /* NS domain DN */ -}; -typedef struct ns_cred ns_cred_t; - -/* LDAP specific NS Data */ - -typedef struct NS_LDAPDATA { - char **attrList; /* list of user defined Key Value Pairs */ -} NS_LDAPDATA; - -/* Printer Object structure */ -struct ns_printer { - char *name; /* primary name of printer */ - char **aliases; /* aliases for printer */ - char *source; /* name service derived from */ - ns_kvp_t **attributes; /* key/value pairs. */ - ns_cred_t *cred; /* info to update name service */ - void *nsdata; /* name service specific data */ -}; -typedef struct ns_printer ns_printer_t; - -/* functions to get/put printer objects */ -extern ns_printer_t *ns_printer_create(char *, char **, char *, ns_kvp_t **); -extern ns_printer_t *ns_printer_get_name(const char *, const char *); -extern ns_printer_t **ns_printer_get_list(const char *); -extern int ns_printer_put(const ns_printer_t *); -extern void ns_printer_destroy(ns_printer_t *); - -extern int setprinterentry(int, char *); -extern int endprinterentry(); -extern int getprinterentry(char *, int, char *); -extern int getprinterbyname(char *, char *, int, char *); - -extern char *_cvt_printer_to_entry(ns_printer_t *, char *, int); - -extern ns_printer_t *_cvt_nss_entry_to_printer(char *, char *); -extern ns_printer_t *posix_name(const char *); - - - -/* functions to manipulate key/value pairs */ -extern void *ns_get_value(const char *, const ns_printer_t *); -extern char *ns_get_value_string(const char *, const ns_printer_t *); -extern int ns_set_value(const char *, const void *, ns_printer_t *); -extern int ns_set_value_from_string(const char *, const char *, - ns_printer_t *); -extern ns_kvp_t *ns_kvp_create(const char *, const char *); - -/* for BSD bindings only */ -extern ns_bsd_addr_t *ns_bsd_addr_get_default(); -extern ns_bsd_addr_t *ns_bsd_addr_get_name(char *name); -extern ns_bsd_addr_t **ns_bsd_addr_get_all(int); -extern ns_bsd_addr_t **ns_bsd_addr_get_list(int); - -/* others */ -extern int ns_printer_match_name(ns_printer_t *, const char *); -extern char *ns_printer_name_list(const ns_printer_t *); -extern char *value_to_string(const char *, void *); -extern void *string_to_value(const char *, char *); -extern char *normalize_ns_name(char *); -extern char *strncat_escaped(char *, char *, int, char *); - - - -#ifdef __cplusplus -} -#endif - -#endif /* _NS_H */ diff --git a/usr/src/lib/print/libprint/common/ns_bsd_addr.c b/usr/src/lib/print/libprint/common/ns_bsd_addr.c deleted file mode 100644 index ba142bb8a1..0000000000 --- a/usr/src/lib/print/libprint/common/ns_bsd_addr.c +++ /dev/null @@ -1,571 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <stdarg.h> -#include <string.h> -#include <syslog.h> - -#include <ns.h> -#include <list.h> - -static char ** -strsplit(char *string, char *seperators) -{ - char **list = NULL; - char *where = NULL; - char *element; - - for (element = strtok_r(string, seperators, &where); element != NULL; - element = strtok_r(NULL, seperators, &where)) - list = (char **)list_append((void **)list, element); - - return (list); -} - -/* - * Manipulate bsd_addr structures - */ -ns_bsd_addr_t * -bsd_addr_create(const char *server, const char *printer, const char *extension) -{ - ns_bsd_addr_t *addr = NULL; - - if ((server != NULL) && - ((addr = calloc(1, sizeof (*addr))) != NULL)) { - addr->printer = (char *)printer; - addr->server = (char *)server; - addr->extension = (char *)extension; - } - - return (addr); -} - -static char * -bsd_addr_to_string(const ns_bsd_addr_t *addr) -{ - char buf[BUFSIZ]; - - if ((addr == NULL) || (addr->server == NULL)) - return (NULL); - - if (snprintf(buf, sizeof (buf), "%s", addr->server) >= sizeof (buf)) { - syslog(LOG_ERR, "bsd_addr_to_string: buffer overflow"); - return (NULL); - } - - if ((addr->printer != NULL) || (addr->extension != NULL)) - (void) strlcat(buf, ",", sizeof (buf)); - if (addr->printer != NULL) - if (strlcat(buf, addr->printer, sizeof (buf)) >= sizeof (buf)) { - syslog(LOG_ERR, "bsd_addr_to_string: buffer overflow"); - return (NULL); - } - if (addr->extension != NULL) { - (void) strlcat(buf, ",", sizeof (buf)); - if (strlcat(buf, addr->extension, sizeof (buf)) - >= sizeof (buf)) { - syslog(LOG_ERR, "bsd_addr_to_string: buffer overflow"); - return (NULL); - } - } - - return (strdup(buf)); -} - -ns_bsd_addr_t * -string_to_bsd_addr(const char *string) -{ - char **list, *tmp, *printer = NULL, *extension = NULL; - - if (string == NULL) - return (NULL); - - tmp = strdup(string); - list = strsplit(tmp, ","); - - if (list[1] != NULL) { - printer = list[1]; - if (list[2] != NULL) - extension = list[2]; - } - - return (bsd_addr_create(list[0], printer, extension)); -} - -static char * -list_to_string(const char **list) -{ - char buf[BUFSIZ]; - - if ((list == NULL) || (*list == NULL)) - return (NULL); - - if (snprintf(buf, sizeof (buf), "%s", *list) >= sizeof (buf)) { - syslog(LOG_ERR, "list_to_string: buffer overflow"); - return (NULL); - } - - while (*++list != NULL) { - (void) strlcat(buf, ",", sizeof (buf)); - if (strlcat(buf, *list, sizeof (buf)) >= sizeof (buf)) { - syslog(LOG_ERR, "list_to_string: buffer overflow"); - return (NULL); - } - } - - return (strdup(buf)); -} - -static char * -internal_list_to_string(const ns_printer_t **list) -{ - char buf[BUFSIZ]; - - if ((list == NULL) || (*list == NULL)) - return (NULL); - - if (snprintf(buf, sizeof (buf), "%s", (*list)->name) >= sizeof (buf)) { - syslog(LOG_ERR, "internal_list_to_string:buffer overflow"); - return (NULL); - } - - while (*++list != NULL) { - (void) strlcat(buf, ",", sizeof (buf)); - if (strlcat(buf, (*list)->name, sizeof (buf)) >= sizeof (buf)) { - syslog(LOG_ERR, - "internal_list_to_string:buffer overflow"); - return (NULL); - } - } - - return (strdup(buf)); -} - - -char * -value_to_string(const char *key, void *value) -{ - char *string = NULL; - - if ((key != NULL) && (value != NULL)) { - if (strcmp(key, NS_KEY_BSDADDR) == 0) { - string = bsd_addr_to_string(value); - } else if ((strcmp(key, NS_KEY_ALL) == 0) || - (strcmp(key, NS_KEY_GROUP) == 0)) { - string = list_to_string(value); - } else if (strcmp(key, NS_KEY_LIST) == 0) { - string = internal_list_to_string(value); - } else { - string = strdup((char *)value); - } - } - - return (string); -} - - -void * -string_to_value(const char *key, char *string) -{ - void *value = NULL; - - if ((key != NULL) && (string != NULL) && (string[0] != NULL)) { - if (strcmp(key, NS_KEY_BSDADDR) == 0) { - value = (void *)string_to_bsd_addr(string); - } else if ((strcmp(key, NS_KEY_ALL) == 0) || - (strcmp(key, NS_KEY_GROUP) == 0)) { - value = (void *)strsplit(string, ","); - } else { - value = (void *)string; - } - } - - return (value); -} - -static void -split_name(char *name, const char *delimiter, char **p1, char **p2, char **p3) -{ - char *tmp, *junk = NULL; - - if (p1 != NULL) - *p1 = NULL; - if (p2 != NULL) - *p2 = NULL; - if (p3 != NULL) - *p3 = NULL; - - if ((name == NULL) || (delimiter == NULL)) { - syslog(LOG_DEBUG, "split_name(): name/delimter invalid\n"); - return; - } - - for (tmp = (char *)strtok_r(name, delimiter, &junk); tmp != NULL; - tmp = (char *)strtok_r(NULL, delimiter, &junk)) - if ((p1 != NULL) && (*p1 == NULL)) - *p1 = tmp; - else if ((p2 != NULL) && (*p2 == NULL)) { - *p2 = tmp; - if (p3 == NULL) - break; - } else if ((p3 != NULL) && (*p3 == NULL)) { - *p3 = tmp; - break; - } -} - -/* - * This implements support for printer names that are fully resolvable - * on their own. These "complete" names are converted into a ns_printer_t - * structure containing an appropriate "bsdaddr" attribute. The supported - * formats are as follows: - * POSIX style (server:printer[:conformance]). - * This format is an adaptation of the format originally - * described in POSIX 1387.4. The POSIX draft has since been - * squashed, but this particular component lives on. The - * conformace field has been added to allow further identification - * of the the server. - */ -ns_printer_t * -posix_name(const char *name) -{ - ns_printer_t *printer = NULL; - char *tmp = NULL; - - if ((name != NULL) && ((tmp = strpbrk(name, ":")) != NULL)) { - char *server = NULL; - char *queue = NULL; - char *extension = NULL; - char *addr = strdup(name); - char buf[BUFSIZ]; - - if (*tmp == ':') - split_name(addr, ": \t", &server, &queue, &extension); - - memset(buf, 0, sizeof (buf)); - if ((server != NULL) && (queue != NULL)) - snprintf(buf, sizeof (buf), "%s,%s%s%s", server, - queue, (extension != NULL ? "," : ""), - (extension != NULL ? extension : "")); - - /* build the structure here */ - if (buf[0] != NULL) { - ns_kvp_t **list, *kvp; - - kvp = ns_kvp_create(NS_KEY_BSDADDR, buf); - list = (ns_kvp_t **)list_append(NULL, kvp); - if (list != NULL) - printer = ns_printer_create(strdup(name), NULL, - "posix", list); - } - } - - return (printer); -} - -/* - * FUNCTION: - * int ns_bsd_addr_cmp(ns_bsd_addr_t *at, ns_bsd_addr_t *a2) - * INPUTS: - * ns_bsd_addr_t *a1 - a bsd addr - * ns_bsd_addr_t *21 - another bsd addr - * DESCRIPTION: - * This functions compare 2 bsd_addr structures to determine if the - * information in them is the same. - */ -static int -ns_bsd_addr_cmp(ns_bsd_addr_t *a1, ns_bsd_addr_t *a2) -{ - int rc; - - if ((a1 == NULL) || (a2 == NULL)) - return (1); - - if ((rc = strcmp(a1->server, a2->server)) != 0) - return (rc); - - if ((a1->printer == NULL) || (a2->printer == NULL)) - return (a1->printer != a2->printer); - - return (strcmp(a1->printer, a2->printer)); -} - - - - -/* - * FUNCTION: ns_bsd_addr_cmp_local() - * - * DESCRIPTION: This function compares 2 bsd_addr structures to determine if - * the information in them is the same. It destinquishes between - * real printer names and alias names while doing the compare. - * - * INPUTS: ns_bsd_addr_t *a1 - a bsd addr - * ns_bsd_addr_t *21 - another bsd addr - */ - -static int -ns_bsd_addr_cmp_local(ns_bsd_addr_t *a1, ns_bsd_addr_t *a2) - -{ - int rc; - - if ((a1 == NULL) || (a2 == NULL)) - { - return (1); - } - - if ((rc = strcmp(a1->server, a2->server)) != 0) - { - return (rc); - } - - if ((a1->printer == NULL) || (a2->printer == NULL)) - { - return (a1->printer != a2->printer); - } - - rc = strcmp(a1->printer, a2->printer); - if (rc == 0) - { - /* - * The printer's real names are the same, but now check if - * their local names (alias) are the same. - */ - rc = strcmp(a1->pname, a2->pname); - } - - return (rc); -} /* ns_bsd_addr_cmp_local */ - - - -/* - * FUNCTION: - * ns_bsd_addr_t *ns_bsd_addr_get_name(char *name) - * INPUTS: - * char *name - name of printer to get address for - * OUTPUTS: - * ns_bsd_addr_t *(return) - the address of the printer - * DESCRIPTION: - * This function will get the BSD address of the printer specified. - * it fills in the printer name if none is specified in the "name service" - * as a convenience to calling functions. - */ -ns_bsd_addr_t * -ns_bsd_addr_get_name(char *name) -{ - ns_printer_t *printer; - ns_bsd_addr_t *addr = NULL; - - endprinterentry(); - if ((printer = ns_printer_get_name(name, NULL)) != NULL) { - addr = ns_get_value(NS_KEY_BSDADDR, printer); - - if (addr != NULL && addr->printer == NULL) - addr->printer = strdup(printer->name); - if (addr != NULL) { - /* - * if the name given is not the same as that in the - * this is an alias/remote name so put that into the - * pname field otherwise duplicate the real printer - * name - */ - if (strcmp(name, printer->name) != 0) { - addr->pname = strdup(name); - } else { - addr->pname = strdup(printer->name); - } - } - } - - return (addr); -} - - -/* - * FUNCTION: - * ns_bsd_addr_t **ns_bsd_addr_get_list() - * OUTPUT: - * ns_bsd_addr_t **(return) - a list of bsd addresses for all printers - * in all "name services" - * DESCRIPTION: - * This function will gather a list of all printer addresses in all - * of the "name services". All redundancy is removed. - */ -ns_bsd_addr_t ** -ns_bsd_addr_get_list(int unique) - -{ - ns_printer_t **printers; - ns_bsd_addr_t **list = NULL; - char **aliases = NULL; - - for (printers = ns_printer_get_list(NULL); - printers != NULL && *printers != NULL; printers++) { - ns_bsd_addr_t *addr; - - if (strcmp(NS_NAME_ALL, (*printers)->name) == 0) - continue; - - if ((addr = ns_get_value(NS_KEY_BSDADDR, *printers)) != NULL) { - if (addr->printer == NULL) - addr->printer = strdup((*printers)->name); - addr->pname = strdup((*printers)->name); - } - - if (unique == UNIQUE) - list = - (ns_bsd_addr_t **)list_append_unique((void **)list, - (void *)addr, (COMP_T)ns_bsd_addr_cmp); - else - if (unique == LOCAL_UNIQUE) - list = - (ns_bsd_addr_t **)list_append_unique((void **)list, - (void *)addr, (COMP_T)ns_bsd_addr_cmp_local); - else - list = (ns_bsd_addr_t **)list_append((void **)list, - (void *)addr); - - for (aliases = (*printers)->aliases; - (aliases != NULL) && (*aliases != NULL); aliases++) - { - /* - * Include any alias names that belong to the printer - */ - - if ((addr = - ns_get_value(NS_KEY_BSDADDR, *printers)) != NULL) - { - if (addr->printer == NULL) - { - addr->printer = strdup(*aliases); - } - addr->pname = strdup(*aliases); - } - - if (unique == UNIQUE) - { - list = (ns_bsd_addr_t **) - list_append_unique((void **)list, - (void *)addr, (COMP_T)ns_bsd_addr_cmp); - } - else - if (unique == LOCAL_UNIQUE) - { - list = (ns_bsd_addr_t **) - list_append_unique((void **)list, - (void *)addr, - (COMP_T)ns_bsd_addr_cmp_local); - } - else - { - list = (ns_bsd_addr_t **) - list_append((void **)list, (void *)addr); - } - } - } - - return (list); -} - - - - -/* - * FUNCTION: - * ns_bsd_addr_t **ns_bsd_addr_get_list() - * OUTPUT: - * ns_bsd_addr_t **(return) - a list of bsd addresses for "_all" printers - * in the "name service" - * DESCRIPTION: - * This function will use the "_all" entry to find a list of printers and - * addresses. The "default" printer is also added to the list. - * All redundancy is removed. - */ -ns_bsd_addr_t ** -ns_bsd_addr_get_all(int unique) -{ - ns_printer_t *printer; - ns_bsd_addr_t **list = NULL; - char **printers; - char *def = NULL; - - if (((def = (char *)getenv("PRINTER")) == NULL) && - ((def = (char *)getenv("LPDEST")) == NULL)) - def = NS_NAME_DEFAULT; - - list = (ns_bsd_addr_t **)list_append((void **)list, - (void *)ns_bsd_addr_get_name(def)); - - endprinterentry(); - if ((printer = ns_printer_get_name(NS_NAME_ALL, NULL)) == NULL) - return (ns_bsd_addr_get_list(unique)); - - for (printers = (char **)ns_get_value(NS_KEY_ALL, printer); - printers != NULL && *printers != NULL; printers++) { - ns_bsd_addr_t *addr; - - addr = ns_bsd_addr_get_name(*printers); - if (addr != NULL) - addr->pname = *printers; - if (unique == UNIQUE) - list = - (ns_bsd_addr_t **)list_append_unique((void **)list, - (void *)addr, (COMP_T)ns_bsd_addr_cmp); - else - list = (ns_bsd_addr_t **)list_append((void **)list, - (void *)addr); - } - - return (list); -} - -ns_bsd_addr_t * -ns_bsd_addr_get_default() -{ - char *def = NULL; - ns_bsd_addr_t *addr; - - if (((def = (char *)getenv("PRINTER")) == NULL) && - ((def = (char *)getenv("LPDEST")) == NULL)) { - def = NS_NAME_DEFAULT; - addr = ns_bsd_addr_get_name(def); - if (addr != NULL) { - addr->pname = def; - return (addr); - } - } - - return (NULL); -} diff --git a/usr/src/lib/print/libprint/common/ns_cmn_kvp.c b/usr/src/lib/print/libprint/common/ns_cmn_kvp.c deleted file mode 100644 index 3fdacd7e5d..0000000000 --- a/usr/src/lib/print/libprint/common/ns_cmn_kvp.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <stdarg.h> -#include <string.h> - -#include <ns.h> -#include <list.h> - -/* - * Commonly Used routines... - */ - -/* - * FUNCTION: - * kvp_create(const char *key, const void *value) - * INPUT(S): - * const char *key - * - key for key/value pair - * const void *value - * - value for key/value pair - * OUTPUT(S): - * ns_kvp_t * (return value) - * - pointer to structure containing the key/value pair - * DESCRIPTION: - */ -ns_kvp_t * -ns_kvp_create(const char *key, const char *value) -{ - ns_kvp_t *kvp; - - if ((kvp = calloc(1, sizeof (*kvp))) != NULL) { - kvp->key = strdup(key); - kvp->value = (char *)value; - } - return (kvp); -} - -void -ns_kvp_destroy(ns_kvp_t *kvp) -{ - if (kvp != NULL) { - if (kvp->key != NULL) - free(kvp->key); - if (kvp->value != NULL) - free(kvp->value); - free(kvp); - } -} - - - - -/* - * FUNCTION: - * ns_kvp_match_key(const ns_kvp_t *kvp, const char *key) - * INPUT(S): - * const ns_kvp_t *kvp - * - key/value pair to check - * const char *key - * - key for matching - * OUTPUT(S): - * int (return value) - * - 0 if matched - * DESCRIPTION: - */ -static int -ns_kvp_match_key(const ns_kvp_t *kvp, char *key) -{ - if ((kvp != NULL) && (kvp->key != NULL) && (key != NULL)) - return (strcmp(kvp->key, key)); - return (-1); -} - - -/* - * FUNCTION: - * ns_r_get_value(const char *key, const ns_printer_t *printer) - * INPUT(S): - * const char *key - * - key for matching - * const ns_printer_t *printer - * - printer to glean this from - * OUTPUT(S): - * char * (return value) - * - NULL, if not matched - * DESCRIPTION: - */ -static void * -ns_r_get_value(const char *key, const ns_printer_t *printer, int level) -{ - ns_kvp_t *kvp, **attrs; - - if ((key == NULL) || (printer == NULL) || - (printer->attributes == NULL)) - return (NULL); - - if (level++ == 16) - return (NULL); - - /* find it right here */ - if ((kvp = list_locate((void **)printer->attributes, - (COMP_T)ns_kvp_match_key, (void *)key)) != NULL) { - void *value = string_to_value(key, kvp->value); - - /* fill in an empty printer for a bsdaddr */ - if (strcmp(key, NS_KEY_BSDADDR) == 0) { - ns_bsd_addr_t *addr = value; - - if (addr->printer == NULL) - addr->printer = strdup(printer->name); - } - return (value); - } - - /* find it in a child */ - for (attrs = printer->attributes; attrs != NULL && *attrs != NULL; - attrs++) { - void *value = NULL; - - if ((strcmp((*attrs)->key, NS_KEY_ALL) == 0) || - (strcmp((*attrs)->key, NS_KEY_GROUP) == 0)) { - char **printers; - - for (printers = string_to_value((*attrs)->key, - (*attrs)->value); - printers != NULL && *printers != NULL; printers++) { - ns_printer_t *printer = - ns_printer_get_name(*printers, NULL); - - if ((value = ns_r_get_value(key, printer, - level)) != NULL) - return (value); - ns_printer_destroy(printer); - } - } else if (strcmp((*attrs)->key, NS_KEY_LIST) == 0) { - ns_printer_t **printers; - - for (printers = string_to_value((*attrs)->key, - (*attrs)->value); - printers != NULL && *printers != NULL; printers++) { - if ((value = ns_r_get_value(key, *printers, - level)) != NULL) - return (value); - } - } else if (strcmp((*attrs)->key, NS_KEY_USE) == 0) { - char *string = NULL; - ns_printer_t *printer = - ns_printer_get_name((*attrs)->value, NULL); - if ((value = ns_r_get_value(key, printer, - level)) != NULL) - string = value_to_string(string, value); - if (string != NULL) - value = string_to_value(key, string); - ns_printer_destroy(printer); - } - - if (value != NULL) - return (value); - } - - return (NULL); -} - - -/* - * ns_get_value() gets the value of the passed in attribute from the passed - * in printer structure. The value is returned in a converted format. - */ -void * -ns_get_value(const char *key, const ns_printer_t *printer) -{ - return (ns_r_get_value(key, printer, 0)); -} - - -/* - * ns_get_value_string() gets the value of the key passed in from the - * printer structure passed in. The results is an ascii string. - */ -char * -ns_get_value_string(const char *key, const ns_printer_t *printer) -{ - return ((char *)value_to_string(key, ns_get_value(key, printer))); -} - - -/* - * ns_set_value() sets the passed in kvp in the passed in printer structure, - * This is done by converting the value to a string first. - */ -int -ns_set_value(const char *key, const void *value, ns_printer_t *printer) -{ - return (ns_set_value_from_string(key, - value_to_string(key, (void *)value), printer)); -} - - -/* - * ns_set_value_from_string() sets the passed in kvp in the passed in printer - * structure. - */ -int -ns_set_value_from_string(const char *key, const char *string, - ns_printer_t *printer) -{ - if (printer == NULL) - return (-1); - - if (key == NULL) - list_iterate((void **)printer->attributes, - (VFUNC_T)ns_kvp_destroy); - else { - ns_kvp_t *kvp; - - if (((kvp = list_locate((void **)printer->attributes, - (COMP_T)ns_kvp_match_key, - (void *)key)) == NULL) && - ((kvp = calloc(1, sizeof (*kvp))) != NULL)) { - kvp->key = strdup(key); - printer->attributes = (ns_kvp_t **) - list_append((void **)printer->attributes, kvp); - } - if (string != NULL) - kvp->value = strdup(string); - else - kvp->value = NULL; - } - - return (0); -} diff --git a/usr/src/lib/print/libprint/common/ns_cmn_printer.c b/usr/src/lib/print/libprint/common/ns_cmn_printer.c deleted file mode 100644 index 25e344b3c4..0000000000 --- a/usr/src/lib/print/libprint/common/ns_cmn_printer.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/*LINTLIBRARY*/ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <stdarg.h> -#include <string.h> -#include <syslog.h> - -#include <ns.h> -#include <list.h> - -extern void ns_kvp_destroy(ns_kvp_t *); - -/* - * Commonly Used routines... - */ - -/* - * FUNCTION: - * printer_create(char *name, char **aliases, char *source, - * ns_kvp_t **attributes) - * INPUT(S): - * char *name - * - primary name of printer - * char **aliases - * - aliases for printer - * char *source - * - name service derived from - * ks_kvp_t **attributes - * - key/value pairs - * OUTPUT(S): - * ns_printer_t * (return value) - * - pointer to printer object structure - * DESCRIPTION: - */ -ns_printer_t * -ns_printer_create(char *name, char **aliases, char *source, - ns_kvp_t **attributes) -{ - ns_printer_t *printer; - - if ((printer = (ns_printer_t *)calloc(1, sizeof (*printer))) != NULL) { - printer->name = (char *)name; - printer->aliases = (char **)aliases; - printer->source = (char *)source; - printer->attributes = (ns_kvp_t **)attributes; - } - return (printer); -} - - -static int -ns_strcmp(char *s1, char *s2) -{ - return (strcmp(s1, s2) != 0); -} - - -/* - * FUNCTION: - * ns_printer_match_name(const ns_printer_t *printer, const char *name) - * INPUT(S): - * const ns_printer_t *printer - * - key/value pair to check - * const char *key - * - key for matching - * OUTPUT(S): - * int (return value) - * - 0 if matched - * DESCRIPTION: - */ -int -ns_printer_match_name(ns_printer_t *printer, const char *name) -{ - if ((printer == NULL) || (printer->name == NULL) || (name == NULL)) - return (-1); - - if ((strcmp(printer->name, name) == 0) || - (list_locate((void **)printer->aliases, - (COMP_T)ns_strcmp, (void *)name) != NULL)) - return (0); - - return (-1); -} - - -static void -_ns_append_printer_name(const char *name, va_list ap) -{ - char *buf = va_arg(ap, char *); - int bufsize = va_arg(ap, int); - - if (name == NULL) - return; - - (void) strlcat(buf, name, bufsize); - (void) strlcat(buf, "|", bufsize); -} - -/* - * FUNCTION: - * char *ns_printer_name_list(const ns_printer_t *printer) - * INPUT: - * const ns_printer_t *printer - printer object to generate list from - * OUTPUT: - * char * (return) - a newly allocated string containing the names of - * the printer - */ -char * -ns_printer_name_list(const ns_printer_t *printer) -{ - char buf[BUFSIZ]; - - if ((printer == NULL) || (printer->name == NULL)) - return (NULL); - - if (snprintf(buf, sizeof (buf), "%s|", printer->name) >= sizeof (buf)) { - syslog(LOG_ERR, "ns_printer_name:buffer overflow"); - return (NULL); - } - - list_iterate((void **)printer->aliases, - (VFUNC_T)_ns_append_printer_name, buf, sizeof (buf)); - - buf[strlen(buf) - 1] = (char)NULL; - - return (strdup(buf)); -} diff --git a/usr/src/lib/print/libprint/common/nss_convert.c b/usr/src/lib/print/libprint/common/nss_convert.c deleted file mode 100644 index eaee6df5b2..0000000000 --- a/usr/src/lib/print/libprint/common/nss_convert.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * This file contains routines necessary to convert a string buffer into - * a printer object. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <string.h> -#include <stdarg.h> -#include <syslog.h> - -#include <ns.h> -#include <list.h> - -#define ESCAPE_CHARS "\\\n=:" /* \, \n, =, : */ - -/* - * Just like strncat(3C), but escapes the supplied characters. - * This allows the escape character '\' and seperators to be part of the - * keys or values. - */ -char * -strncat_escaped(char *d, char *s, int len, char *escape) -{ - char *t = d; - - while ((*t != NULL) && (len > 0)) - len--, t++; - - if (escape == NULL) - escape = "\\"; - - while ((*s != NULL) && (len > 0)) { - if (strchr(escape, *s) != NULL) - len--, *t++ = '\\'; - len--, *t++ = *s++; - } - *t = NULL; - - return (d); -} - - - -char * -_cvt_printer_to_entry(ns_printer_t *printer, char *buf, int buflen) -{ - int i, len; - int bufferok = 1; - - (void) memset(buf, NULL, buflen); - - if ((printer == NULL) || (printer->attributes == NULL)) - return (NULL); - - if (snprintf(buf, buflen, "%s", printer->name) >= buflen) { - (void) memset(buf, NULL, buflen); - syslog(LOG_ERR, "_cvt_printer_to_entry: buffer overflow"); - return (NULL); - } - - if ((printer->aliases != NULL) && (printer->aliases[0] != NULL)) { - char **alias = printer->aliases; - - while (*alias != NULL) { - (void) strlcat(buf, "|", buflen); - (void) strncat_escaped(buf, *alias++, buflen, - ESCAPE_CHARS); - } - } - - if (strlcat(buf, ":", buflen) >= buflen) { - (void) memset(buf, NULL, buflen); - syslog(LOG_ERR, "_cvt_printer_to_entry: buffer overflow"); - return (NULL); - } - - len = strlen(buf); - - for (i = 0; printer->attributes[i] != NULL && bufferok; i++) { - ns_kvp_t *kvp = printer->attributes[i]; - - if (kvp->value == NULL) - continue; - (void) strlcat(buf, "\\\n\t:", buflen); - (void) strncat_escaped(buf, kvp->key, buflen, ESCAPE_CHARS); - (void) strlcat(buf, "=", buflen); - (void) strncat_escaped(buf, kvp->value, buflen, ESCAPE_CHARS); - if (strlcat(buf, ":", buflen) >= buflen) { - bufferok = 0; - } - } - - if (!bufferok) { - (void) memset(buf, NULL, buflen); - syslog(LOG_ERR, "_cvt_printer_to_entry: buffer overflow"); - return (NULL); - } - - if (strlen(buf) == len) { /* there were no attributes */ - (void) memset(buf, NULL, buflen); - buf = NULL; - } - - return (buf); -} - - -ns_printer_t * -_cvt_nss_entry_to_printer(char *entry, char *ns) -{ - char *name = NULL, - *key = NULL, - **aliases = NULL, - *cp, - buf[BUFSIZ]; - int in_namelist = 1, buf_pos = 0; - ns_printer_t *printer = NULL; - - if (entry == NULL) - return (NULL); - - (void) memset(buf, NULL, sizeof (buf)); - for (cp = entry; *cp != NULL; cp++) { - switch (*cp) { - case ':': /* end of kvp */ - if (in_namelist != 0) { - if (name == NULL) - name = strdup(buf); - else - aliases = (char **)list_append( - (void **)aliases, - (void *)strdup(buf)); - printer = (ns_printer_t *)ns_printer_create( - name, aliases, ns, NULL); - in_namelist = 0; - } else if (key != NULL) - (void) ns_set_value_from_string(key, buf, - printer); - (void) memset(buf, NULL, sizeof (buf)); - buf_pos = 0; - key = NULL; - break; - case '=': /* kvp seperator */ - if (key == NULL) { - key = strdup(buf); - (void) memset(buf, NULL, sizeof (buf)); - buf_pos = 0; - } else - buf[buf_pos++] = *cp; - break; - case '|': /* namelist seperator */ - if (in_namelist != 0) { - if (name == NULL) - name = strdup(buf); - else - aliases = (char **)list_append( - (void **)aliases, - (void *)strdup(buf)); - (void) memset(buf, NULL, sizeof (buf)); - buf_pos = 0; - } else /* add it to the buffer */ - buf[buf_pos++] = *cp; - break; - case '\\': /* escape char */ - buf[buf_pos++] = *(++cp); - break; - default: - buf[buf_pos++] = *cp; - } - - } - - if (key != NULL) - (void) ns_set_value_from_string(key, buf, printer); - - return (printer); -} diff --git a/usr/src/lib/print/libprint/common/nss_ldap.c b/usr/src/lib/print/libprint/common/nss_ldap.c deleted file mode 100644 index c2140d5048..0000000000 --- a/usr/src/lib/print/libprint/common/nss_ldap.c +++ /dev/null @@ -1,2477 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <string.h> -#include <stdarg.h> -#include <fcntl.h> -#include <syslog.h> -#include <errno.h> -#include <pwd.h> -#include <libintl.h> -#include <netdb.h> /* for rcmd() */ - -#include <ns.h> -#include <list.h> - -#define LDAP_REFERRALS -#include <lber.h> -#include <ldap.h> -#include <sys/systeminfo.h> - - -/* - * This modules contains the code required to manipulate printer objects in - * a LDAP directory for the Naming Service (NS) switch. - * It can "add", "modify" and "delete" the objects on the given ldap server - * and in the given NS domain DN, eg. "dc=mkg,dc=sun,dc=com". - * Note: printers known to the naming service are contained in the RDN - * "ou=printers" under the NS domain DN - */ - -#define PCONTAINER "ou=printers" - -/* attribute keywords */ -#define ATTR_DN "dn" -#define ATTR_OCLASS "objectClass" -#define ATTR_URI "printer-uri" -#define ATTR_PNAME "printer-name" -#define ATTR_XRISUP "printer-xri-supported" -#define ATTR_BSDADDR "sun-printer-bsdaddr" -#define ATTR_KVP "sun-printer-kvp" - -/* objectClass values */ -#define OCV_TOP "top" -#define OCV_PSERVICE "printerService" -#define OCV_SUNPRT "sunPrinter" -#define OCV_PABSTRACT "printerAbstract" - -/* xri-supported attribute value */ -#define AV_UNKNOWN "unknown" - - -/* - * LDAP objectclass atributes that the user can explicity change - */ - -static const char *nsl_attr_printerService[] = { - "printer-uri", - "printer-xri-supported", - /* Not allowed "printer-name", */ - "printer-natural-language-configured", - "printer-location", - "printer-info", - "printer-more-info", - "printer-make-and-model", - "printer-charset-configured", - "printer-charset-supported", - "printer-generated-natural-language-supported", - "printer-document-format-supported", - "printer-color-supported", - "printer-compression-supported", - "printer-pages-per-minute", - "printer-pages-per-minute-color", - "printer-finishings-supported", - "printer-number-up-supported", - "printer-sides-supported", - "printer-media-supported", - "printer-media-local-supported", - "printer-resolution-supported", - "printer-print-quality-supported", - "printer-job-priority-supported", - "printer-copies-supported", - "printer-job-k-octets-supported", - "printer-current-operator", - "printer-service-person", - "printer-delivery-orientation-supported", - "printer-stacking-order-supported", - "printer-output-features-supported", - (char *)NULL -}; - - -static const char *nsl_attr_printerIPP[] = { - "printer-ipp-versions-supported", - "printer-multiple-document-jobs-supported", - (char *)NULL -}; - -static const char *nsl_attr_sunPrinter[] = { - /* Not allowed "sun-printer-bsdaddr", */ - /* Not allowed "sun-printer-kvp", */ - (char *)NULL -}; - - -/* - * List of LDAP attributes that user is not allowed to explicitly change - */ -static const char *nsl_attr_notAllowed[] = { - ATTR_DN, - ATTR_OCLASS, /* objectclass */ - ATTR_PNAME, /* printer-name */ - ATTR_BSDADDR, - ATTR_KVP, - (char *)NULL -}; - - -static NSL_RESULT _connectToLDAP(ns_cred_t *cred, LDAP **ld); -static uchar_t *_constructPrinterDN(uchar_t *printerName, - uchar_t *domainDN, char **attrList); -static NSL_RESULT _checkPrinterExists(LDAP *ld, uchar_t *printerName, - uchar_t *domainDN, uchar_t **printerDN); -static NSL_RESULT _checkPrinterDNExists(LDAP *ld, uchar_t *objectDN); -static NSL_RESULT _checkSunPrinter(LDAP *ld, uchar_t *printerDN); -static NSL_RESULT _addNewPrinterObject(LDAP *ld, uchar_t *printerName, - uchar_t *domainDN, char **attrList); -static NSL_RESULT _modifyPrinterObject(LDAP *ld, uchar_t *printerDN, - uchar_t *printerName, uchar_t *domainDN, char **attrList); -static NSL_RESULT _checkAttributes(char **list); -static NSL_RESULT _addLDAPmodValue(LDAPMod ***attrs, char *type, char *value); -static NSL_RESULT _modLDAPmodValue(LDAPMod ***attrs, char *type, char *value); -static NSL_RESULT _constructAddLDAPMod(uchar_t *printerName, - char **attrList, LDAPMod ***attrs); -static NSL_RESULT _constructModLDAPMod(uchar_t *printerName, int sunPrinter, - char **attrList, char ***oldKVPList, LDAPMod ***attrs); -static NSL_RESULT _compareURIinDNs(uchar_t *dn1, uchar_t *dn2); -static uchar_t *_getThisNSDomainDN(void); -static int _popen(char *cmd, char *results, int size); -static int _attrInList(char *attr, const char **list); -static int _attrInLDAPList(char *attr); -static NSL_RESULT _getCurrentKVPValues(LDAP *ld, - uchar_t *objectDN, char ***list); -static void _freeList(char ***list); -static NSL_RESULT _modAttrKVP(char *value, char ***kvpList); -static NSL_RESULT _attrAddKVP(LDAPMod ***attrs, char **kvpList, int kvpExists); -static int _manageReferralCredentials(LDAP *ld, char **dn, char **credp, - int *methodp, int freeit); - -/* - * ***************************************************************************** - * - * Function: ldap_put_printer() - * - * Description: Action the request to change a printer object in the LDAP - * directory DIT. The object is either added, modified or deleted - * depending on the request's attribute list. A null list indicates - * the request is a delete. - * The object's DN is constructed from the supplied domain DN and - * a check is done to see if the object exists already, if it - * doesn't exist then this is a request to add a new object - * If a URI is given in the attribute list and it is different to - * the existing printing object's DN then the request will be - * rejected. - * - * - * Parameters: - * Input: const ns_printer_t *printer - * - this structure contains the following : - * char *printerName - name of the printer - * ns_cred_t *cred - structure containing the ldap host and - * port, user, password and NS domain DN for the - * directory server to be updated. - * char **attrList - pointer to a list of attribute key values - * for the printer object. If the object does - * not already exist then this list contains the - * values for the new object, otherwise this list - * is a list of attributes to modify. For modify - * a null attribute value is a attribute delete - * request. A NULL ptr = delete the object. - * Output: None - * - * Returns: int - 0 = request actioned okay - * !0 = error - see NSL_RESULT codes - * - * ***************************************************************************** - */ - -int -ldap_put_printer(const ns_printer_t *printer) - -{ - NSL_RESULT result = NSL_OK; - NSL_RESULT printerExists = NSL_ERR_UNKNOWN_PRINTER; - LDAP *ld = NULL; - uchar_t *printerDN = NULL; - uchar_t *domainDN = NULL; - char *printerName = NULL; - ns_cred_t *cred = NULL; - char **attrList = NULL; - - /* -------- */ - - /* - * Note: the "attributes" list should be null for ldap as the attribute - * values are passed in the nsdata field - */ - - if ((printer != NULL) && - (printer->attributes == NULL) && (printer->name != NULL)) - { - /* extract required pointer values from structure */ - - printerName = printer->name; - cred = printer->cred; - if (printer->nsdata != NULL) - { - attrList = ((NS_LDAPDATA *)(printer->nsdata))->attrList; - } - - /* connect and bind to the ldap directory server */ - - result = _connectToLDAP(cred, &ld); - if ((result == NSL_OK) && (ld != NULL)) - { - /* - * check if the NS domain DN was given, if not use the - * current NS domain - */ - - if (cred->domainDN != NULL) - { - domainDN = (uchar_t *) - strdup((char *)cred->domainDN); - } - else - { - /* get DN of current domain */ - domainDN = _getThisNSDomainDN(); - } - - printerExists = - _checkPrinterExists(ld, (uchar_t *)printerName, - domainDN, &printerDN); - if (printerExists != LDAP_SUCCESS) - { - /* - * could not find the printer by printer-name, - * but there could be a non sunPrinter object - * so if the printer-uri was given check if - * an object for that exists - */ - printerDN = - _constructPrinterDN(NULL, - domainDN, attrList); - if (printerDN != NULL) - { - printerExists = _checkPrinterDNExists( - ld, printerDN); - } - } -#ifdef DEBUG -if (printerExists == NSL_OK) -{ -printf("DN found = '%s' for '%s'\n", printerDN, printerName); -} -#endif - - if (attrList == NULL) - { - /* - * a null list indicates that this is a DELETE - * object request, so if object exists delete - * it, otherwise report an error. - */ - if (printerExists == LDAP_SUCCESS) - { - result = ldap_delete_s(ld, - (char *)printerDN); - if (result != LDAP_SUCCESS) - { - result = NSL_ERR_DEL_FAILED; -#ifdef DEBUG -ldap_perror(ld, "ldap_delete_s failed"); -#endif - } - } - else - { - result = NSL_ERR_UNKNOWN_PRINTER; - } - } - else - { - /* - * if object exists then this is a - * modify request otherwise is is an add request - */ - - if (printerExists == LDAP_SUCCESS) - { - /* - * Modify the printer object to - * give it the new attribute values - * specified by the user - */ - result = - _modifyPrinterObject(ld, printerDN, - (uchar_t *)printerName, - domainDN, attrList); - } - else - { - /* - * add new printer object into the - * ldap directory with the user - * specified attribute values - */ - result = - _addNewPrinterObject(ld, - (uchar_t *)printerName, - domainDN, attrList); - } - } - - if (printerDN != NULL) - { - free(printerDN); - } - if (domainDN != NULL) - { - free(domainDN); - } - - /* disconnect from LDAP server */ - - (void) ldap_unbind(ld); - } - } - - else - { - /* no printerName given */ - result = NSL_ERR_INTERNAL; - } - - return ((int)result); -} /* ldap_put_printer */ - - - - -/* - * ***************************************************************************** - * - * Function: _connectToLDAP() - * - * Description: Setup the connection and bind to the LDAP directory server. - * The function returns the ldap connection descriptor - * - * Note: Currently the native ldap functions do not support secure - * passwords, when this is supported this function will require - * updating to allow the type passed in cred->passwdType to - * be used with the ldap_simple_bind() - * - * Parameters: - * Input: ns_cred_t *cred - structure containing the credentials (host, - * port, user and password) required to bind - * to the directory server to be updated. - * char *printerName - printer name used only for error messages - * Output: LDAP** - ldap connection descriptor pointer. NULL = failed - * - * Returns: NSL_RESULT - NSL_OK = connected okay - * - * ***************************************************************************** - */ - -static NSL_RESULT -_connectToLDAP(ns_cred_t *cred, LDAP **ld) - -{ - NSL_RESULT result = NSL_OK; - int lresult = 0; - int ldapPort = LDAP_PORT; /* default LDAP port number */ - int protoVersion = LDAP_VERSION3; - int derefOption = LDAP_DEREF_NEVER; - int referrals = 1; - char hostname[MAXHOSTNAMELEN]; - int tmpMethod = LDAP_AUTH_SIMPLE; /* temp - until its passed in */ - - /* -------- */ - - if ((ld == NULL) || (cred == NULL) || - ((cred->passwd == NULL) || (cred->binddn == NULL))) - { - result = NSL_ERR_CREDENTIALS; - } - - else - { - *ld = NULL; - - /* if host was not given then bind to local host */ - - if (cred->host != NULL) - { - (void) strlcpy(hostname, cred->host, sizeof (hostname)); - } - else - { - (void) sysinfo(SI_HOSTNAME, - hostname, sizeof (hostname)); - } - - /* initialise the connection to the ldap server */ - - if (cred->port != 0) - { - ldapPort = cred->port; - } - *ld = ldap_init(hostname, ldapPort); - if (*ld == NULL) - { - /* connection setup failed */ - result = NSL_ERR_CONNECT; -#ifdef DEBUG -(void) perror("ldap_init"); -#endif - } - else - { - /* set ldap options */ - - (void) ldap_set_option(*ld, LDAP_OPT_DEREF, - &derefOption); - (void) ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION, - &protoVersion); - (void) ldap_set_option(*ld, LDAP_OPT_REFERRALS, - &referrals); - - /* bind to the user DN in the directory */ - - /* cred->passwdType is currently not supported */ - - lresult = ldap_simple_bind_s(*ld, - cred->binddn, cred->passwd); - - /* - * before doing anything else, set up the function to - * call to get authentication details if the - * ldap update function calls (eg. ldap_add_s()) get a - * "referral" (to another ldap server) from the - * original ldap server, eg. if we are trying to do - * a update on a LDAP replica server. - */ - (void) _manageReferralCredentials(*ld, - &(cred->binddn), &(cred->passwd), - &tmpMethod, -1); - ldap_set_rebind_proc(*ld, - (LDAP_REBINDPROC_CALLBACK *) - _manageReferralCredentials, NULL); - - if (lresult != LDAP_SUCCESS) - { - result = NSL_ERR_BIND; - *ld = NULL; -#ifdef DEBUG -(void) ldap_perror(*ld, "ldap_simple_bind_s"); -#endif - } - } - } - - return (result); -} /* _connectToLDAP */ - - - - - -/* - * ***************************************************************************** - * - * Function: _constructPrinterDN() - * - * Description: Construct the DN for the printer object from its name and NS - * domain DN. If the printer-uri is given in the attrList then - * that is used instead of the printerName. - * - * Parameters: - * Input: uchar_t *printerName - * uchar_t *domainDN - * char **attrList - this list is searched for printer-uri - * Output: None - * - * Returns: uchar_t* - pointer to the DN, this memory is malloced so - * must be freed using free() when finished with. - * - * ***************************************************************************** - */ - -static uchar_t * -_constructPrinterDN(uchar_t *printerName, uchar_t *domainDN, char **attrList) - -{ - uchar_t *dn = NULL; - uchar_t *uri = NULL; - char **p = NULL; - int len = 0; - - /* ------- */ - - /* first search for printer-uri in the attribute list */ - - for (p = attrList; (p != NULL) && (*p != NULL) && (uri == NULL); p++) - { - /* get length of this key word */ - - for (len = 0; ((*p)[len] != '=') && ((*p)[len] != '\0'); len++); - - if ((strncasecmp(*p, ATTR_URI, len) == 0) && - (strlen(*p) > len+1)) - { - uri = (uchar_t *)&((*p)[len+1]); - } - } - - - if (domainDN != NULL) { - size_t size; - - /* malloc memory for the DN and then construct it */ - - if ((uri == NULL) && (printerName != NULL)) - { - /* use the printerName for the RDN */ - - size = strlen(ATTR_URI) + - strlen((char *)printerName) + - strlen((char *)domainDN) + - strlen(PCONTAINER) + - 10; /* plus a few extra */ - - if ((dn = malloc(size)) != NULL) - (void) snprintf((char *)dn, size, "%s=%s,%s,%s", - ATTR_URI, printerName, PCONTAINER, domainDN); - } - else - if (uri != NULL) - { - /* use the URI for the RDN */ - - size = strlen(ATTR_URI) + - strlen((char *)uri) + - strlen((char *)domainDN) + - strlen(PCONTAINER) + - 10; /* plus a few extra */ - - if ((dn = malloc(size)) != NULL) - (void) snprintf((char *)dn, size, "%s=%s,%s,%s", - ATTR_URI, uri, PCONTAINER, domainDN); - } - - /* - * else - * { - * printName not given so return null - * } - */ - - } - - return (dn); /* caller must free this memory */ -} /* _constructPrinterDN */ - - - -/* - * ***************************************************************************** - * - * Function: _checkPrinterExists() - * - * Description: Check that the printer object for the printerName exists in the - * directory DIT and then extract the object's DN - * The function uses an exiting ldap connection and does a - * search for the printerName in the supplied domain DN. - * - * Parameters: - * Input: LDAP *ld - existing ldap connection descriptor - * uchar_t *printerName - printer name - * uchar_t *domainDN - DN of domain to search in - * Output: uchar_t **printerDN - DN of the printer - the caller should - * free this memory using free() - * - * Result: NSL_RESULT - NSL_OK = object exists - * - * ***************************************************************************** - */ - -static NSL_RESULT -_checkPrinterExists(LDAP *ld, uchar_t *printerName, uchar_t *domainDN, - uchar_t **printerDN) - -{ - NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER; - int sresult = LDAP_NO_SUCH_OBJECT; - LDAPMessage *ldapMsg = NULL; - char *requiredAttrs[2] = { ATTR_PNAME, NULL }; - LDAPMessage *ldapEntry = NULL; - uchar_t *filter = NULL; - uchar_t *baseDN = NULL; - - /* ---------- */ - - if ((printerName != NULL) && (domainDN != NULL) && (printerDN != NULL)) - { - size_t size; - - if (printerDN != NULL) - { - *printerDN = NULL; - } - - /* search for this Printer in the directory */ - - size = (3 + strlen((char *)printerName) + strlen(ATTR_PNAME) + - 2); - - if ((filter = malloc(size)) != NULL) - (void) snprintf((char *)filter, size, "(%s=%s)", - ATTR_PNAME, (char *)printerName); - - size = (strlen((char *)domainDN) + strlen(PCONTAINER) + 5); - - if ((baseDN = malloc(size)) != NULL) - (void) snprintf((char *)baseDN, size, "%s,%s", - PCONTAINER, (char *)domainDN); - - sresult = ldap_search_s(ld, (char *)baseDN, LDAP_SCOPE_SUBTREE, - (char *)filter, requiredAttrs, 0, &ldapMsg); - if (sresult == LDAP_SUCCESS) - { - /* check that the object exists and extract its DN */ - - ldapEntry = ldap_first_entry(ld, ldapMsg); - if (ldapEntry != NULL) - { - /* object found - there should only be one */ - result = NSL_OK; - - if (printerDN != NULL) - { - *printerDN = (uchar_t *) - ldap_get_dn(ld, ldapEntry); - } - } - - (void) ldap_msgfree(ldapMsg); - } - } - - else - { - result = NSL_ERR_INTERNAL; - } - - return (result); -} /* _checkPrinterExists */ - - - - -/* - * ***************************************************************************** - * - * Function: _checkPrinterDNExists() - * - * Description: Check that the printer object for the DN exists in the - * directory DIT. - * The function uses an exiting ldap connection and does a - * search for the DN supplied. - * - * Parameters: LDAP *ld - existing ldap connection descriptor - * char *objectDN - DN to search for - * - * Result: NSL_RESULT - NSL_OK = object exists - * - * ***************************************************************************** - */ - -static NSL_RESULT -_checkPrinterDNExists(LDAP *ld, uchar_t *objectDN) - -{ - NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER; - int sresult = LDAP_NO_SUCH_OBJECT; - LDAPMessage *ldapMsg; - char *requiredAttrs[2] = { ATTR_PNAME, NULL }; - LDAPMessage *ldapEntry; - - /* ---------- */ - - if ((ld != NULL) && (objectDN != NULL)) - { - /* search for this Printer in the directory */ - - sresult = ldap_search_s(ld, (char *)objectDN, LDAP_SCOPE_BASE, - "(objectclass=*)", requiredAttrs, 0, &ldapMsg); - if (sresult == LDAP_SUCCESS) - { - /* check that the object exists */ - ldapEntry = ldap_first_entry(ld, ldapMsg); - if (ldapEntry != NULL) - { - /* object found */ - result = NSL_OK; - } - - (void) ldap_msgfree(ldapMsg); - } - } - - else - { - result = NSL_ERR_INTERNAL; - } - - return (result); -} /* _checkPrinterDNExists */ - - - - - -/* - * ***************************************************************************** - * - * Function: _checkSunPrinter() - * - * Description: Check that the printer object for the printerDN is a sunPrinter - * ie. it has the required objectclass attribute value. - * - * Parameters: - * Input: LDAP *ld - existing ldap connection descriptor - * Output: uchar_t *printerDN - DN of the printer - * - * Result: NSL_RESULT - NSL_OK = object exists and is a sunPrinter - * - * ***************************************************************************** - */ - -static NSL_RESULT -_checkSunPrinter(LDAP *ld, uchar_t *printerDN) - -{ - NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER; - int sresult = LDAP_NO_SUCH_OBJECT; - char *requiredAttrs[2] = { ATTR_PNAME, NULL }; - LDAPMessage *ldapMsg = NULL; - LDAPMessage *ldapEntry = NULL; - char *filter = NULL; - - /* ---------- */ - - if ((ld != NULL) && (printerDN != NULL)) - { - size_t size; - - /* search for this Printer in the directory */ - - size = (3 + strlen(OCV_SUNPRT) + strlen(ATTR_OCLASS) + 2); - if ((filter = malloc(size)) != NULL) - (void) snprintf(filter, size, "(%s=%s)", - ATTR_OCLASS, OCV_SUNPRT); - - sresult = ldap_search_s(ld, (char *)printerDN, - LDAP_SCOPE_SUBTREE, filter, - requiredAttrs, 0, &ldapMsg); - if (sresult == LDAP_SUCCESS) - { - /* check that the printer object exists */ - - ldapEntry = ldap_first_entry(ld, ldapMsg); - if (ldapEntry != NULL) - { - /* object is a sunPrinter */ - result = NSL_OK; - } - - (void) ldap_msgfree(ldapMsg); - } - } - - else - { - result = NSL_ERR_INTERNAL; - } - - return (result); -} /* _checkSunPrinter */ - - - - - -/* - * ***************************************************************************** - * - * Function: _addNewPrinterObject() - * - * Description: For the given printerName add a printer object into the - * LDAP directory NS domain. The object is created with the - * supplied attribute values. Note: if the printer's uri is - * given that is used as the RDN otherwise the printer's - * name is used as the RDN - * - * Parameters: - * Input: LDAP *ld - existing ldap connection descriptor - * uchar_t *printerName - Name of printer to be added - * uchar_t *domainDN - DN of the domain to add the printer - * char **attrList - user specified attribute values list - * Output: None - * - * Returns: NSL_RESULT - NSL_OK = request actioned okay - * !NSL_OK = error - * - * ***************************************************************************** - */ - -static NSL_RESULT -_addNewPrinterObject(LDAP *ld, uchar_t *printerName, - uchar_t *domainDN, char **attrList) - -{ - NSL_RESULT result = NSL_ERR_ADD_FAILED; - int lresult = 0; - uchar_t *printerDN = NULL; - LDAPMod **attrs = NULL; - - /* ---------- */ - - if ((ld != NULL) && (printerName != NULL) && (domainDN != NULL) && - (attrList != NULL) && (attrList[0] != NULL)) - { - result = _checkAttributes(attrList); - - if (result == NSL_OK) - { - /* - * construct a DN for the printer from the - * printerName and printer-uri if given. - */ - printerDN = _constructPrinterDN(printerName, - domainDN, attrList); - if (printerDN != NULL) - { - /* - * setup attribute values in an LDAPMod - * structure and then add the object - */ - result = _constructAddLDAPMod(printerName, - attrList, &attrs); - if (result == NSL_OK) - { - lresult = ldap_add_s(ld, - (char *)printerDN, attrs); - if (lresult == LDAP_SUCCESS) - { - result = NSL_OK; - } - else - { - result = NSL_ERR_ADD_FAILED; -#ifdef DEBUG -(void) ldap_perror(ld, "ldap_add_s"); -#endif - } - - (void) ldap_mods_free(attrs, 1); - } - free(printerDN); - } - - else - { - result = NSL_ERR_INTERNAL; - } - } - } - - else - { - result = NSL_ERR_INTERNAL; - } - - return (result); -} /* _addNewPrinterObject */ - - - - - - -/* - * ***************************************************************************** - * - * Function: _modifyPrinterObject() - * - * Description: Modify the given LDAP printer object to set the new attributes - * in the attribute list. If the printer's URI (specified in the - * attrList) changes the URI of the object the request is rejected. - * - * Parameters: - * Input: LDAP *ld - existing ldap connection descriptor - * uchar_t *printerDN - DN of printer object to modify - * uchar_t *printerName - Name of printer to be modified - * uchar_t *domainDN - DN of the domain the printer is in - * char **attrList - user specified attribute values list - * Output: None - * - * Returns: NSL_RESULT - NSL_OK = object modified okay - * - * ***************************************************************************** - */ - -static NSL_RESULT -_modifyPrinterObject(LDAP *ld, uchar_t *printerDN, - uchar_t *printerName, uchar_t *domainDN, char **attrList) - -{ - NSL_RESULT result = NSL_ERR_INTERNAL; - int lresult = 0; - int sunPrinter = 0; - uchar_t *uriDN = NULL; - LDAPMod **attrs = NULL; - char **kvpList = NULL; - - /* ---------- */ - - if ((ld != NULL) && (printerDN != NULL) && (printerName != NULL) && - (domainDN != NULL) && (attrList != NULL) && (attrList[0] != NULL)) - { - result = _checkAttributes(attrList); - - if (result == NSL_OK) - { - /* - * The user may have requested that the printer object - * be given a new URI RDN, so construct a DN for the - * printer from the printerName or the printer-uri (if - * given). - */ - uriDN = _constructPrinterDN(NULL, domainDN, attrList); - - /* - * compare the 2 DNs to see if the URI has changed, - * if uriDN is null then the DN hasn't changed - */ - if ((uriDN == NULL) || ((uriDN != NULL) && - (_compareURIinDNs(printerDN, uriDN) == NSL_OK))) - { - /* - * setup the modify object LDAPMod - * structure and then do the modify - */ - - if (_checkSunPrinter(ld, printerDN) == NSL_OK) - { - sunPrinter = 1; - } - - (void) _getCurrentKVPValues(ld, - printerDN, &kvpList); - - result = _constructModLDAPMod(printerName, - sunPrinter, attrList, - &kvpList, &attrs); - _freeList(&kvpList); - - if ((result == NSL_OK) && (attrs != NULL)) - { - lresult = ldap_modify_s( - ld, (char *)printerDN, attrs); - if (lresult == LDAP_SUCCESS) - { - result = NSL_OK; - } - else - { - result = NSL_ERR_MOD_FAILED; -#ifdef DEBUG -(void) ldap_perror(ld, "ldap_modify_s"); -#endif - } - - (void) ldap_mods_free(attrs, 1); - } - } - else - { - /* - * printer-uri name change has been requested - * this is NOT allowed as it requires that - * a new printer object is created - */ - result = NSL_ERR_RENAME; /* NOT ALLOWED */ - } - - if (uriDN != NULL) - { - free(uriDN); - } - } - } - - return (result); -} /* _modifyPrinterObject */ - - - - -/* - * ***************************************************************************** - * - * Function: _checkAttributes() - * - * Description: Check that the given attribute lists does not contain any - * key words that are not allowed. - * - * Parameters: - * Input: char **list - attribute list to check - * Output: None - * - * Returns: NSL_RESULT - NSL_OK = checked okay - * - * ***************************************************************************** - */ - -static NSL_RESULT -_checkAttributes(char **list) - -{ - NSL_RESULT result = NSL_OK; - int len = 0; - char *attr = NULL; - char **p = NULL; - - /* ------ */ - - for (p = list; (p != NULL) && (*p != NULL) && (result == NSL_OK); p++) - { - /* get length of this key word */ - - for (len = 0; ((*p)[len] != '=') && ((*p)[len] != '\0'); len++); - - /* check if the key word is allowed */ - - if (strncasecmp(*p, ATTR_KVP, len) == 0) - { - /* not supported through this interface */ - result = NSL_ERR_KVP; - } - else - if (strncasecmp(*p, ATTR_BSDADDR, len) == 0) - { - /* not supported through this interface */ - result = NSL_ERR_BSDADDR; - } - else - if (strncasecmp(*p, ATTR_PNAME, len) == 0) - { - /* not supported through this interface */ - result = NSL_ERR_PNAME; - } - else - { - /* check for any others */ - - attr = strdup(*p); - attr[len] = '\0'; /* terminate the key */ - - if (_attrInList(attr, nsl_attr_notAllowed)) - { - result = NSL_ERR_NOTALLOWED; - } - } - - } - - return (result); -} /* _checkAttributes */ - - - - -/* - * ***************************************************************************** - * - * Function: _addLDAPmodValue() - * - * Description: Add the given attribute and its value to the LDAPMod array. - * If this is the first entry in the array then create it. - * - * Parameters: - * Input: LDAPMod ***attrs - array to update - * char *type - attribute to add into array - * char *value - attribute value - * Output: None - * - * Returns: NSL_RESULT - NSL_OK = added okay - * - * ***************************************************************************** - */ - -static NSL_RESULT -_addLDAPmodValue(LDAPMod ***attrs, char *type, char *value) - -{ - int i = 0; - int j = 0; - NSL_RESULT result = NSL_OK; - - /* ---------- */ - - if ((attrs != NULL) && (type != NULL) && (value != NULL)) - { -#ifdef DEBUG -printf("_addLDAPmodValue() type='%s', value='%s'\n", type, value); -#endif - /* search the existing LDAPMod array for the attribute */ - - for (i = 0; *attrs != NULL && (*attrs)[i] != NULL; i++) - { - if (strcasecmp((*attrs)[i]->mod_type, type) == 0) - { - break; - } - } - - if (*attrs == NULL) - { - /* array empty so create it */ - - *attrs = (LDAPMod **)calloc(1, 2 * sizeof (LDAPMod *)); - if (*attrs != NULL) - { - i = 0; - } - else - { - result = NSL_ERR_MEMORY; - } - - } - else - if ((*attrs)[i] == NULL) - { - *attrs = (LDAPMod **) - realloc(*attrs, (i+2) * sizeof (LDAPMod *)); - if (*attrs == NULL) - { - result = NSL_ERR_MEMORY; - } - } - } - else - { - result = NSL_ERR_INTERNAL; - } - - if (result == NSL_OK) - { - if ((*attrs)[i] == NULL) - { - /* We've got a new slot. Create the new mod. */ - - (*attrs)[i] = (LDAPMod *) malloc(sizeof (LDAPMod)); - if ((*attrs)[i] != NULL) - { - (*attrs)[i]->mod_op = LDAP_MOD_ADD; - (*attrs)[i]->mod_type = strdup(type); - (*attrs)[i]->mod_values = (char **) - malloc(2 * sizeof (char *)); - if ((*attrs)[i]->mod_values != NULL) - { - (*attrs)[i]->mod_values[0] = - strdup(value); - (*attrs)[i]->mod_values[1] = NULL; - (*attrs)[i+1] = NULL; - } - else - { - result = NSL_ERR_MEMORY; - } - } - else - { - result = NSL_ERR_MEMORY; - } - } - - else - { - /* Found an existing entry so add value to it */ - - for (j = 0; (*attrs)[i]->mod_values[j] != NULL; j++); - - (*attrs)[i]->mod_values = - (char **)realloc((*attrs)[i]->mod_values, - (j + 2) * sizeof (char *)); - if ((*attrs)[i]->mod_values != NULL) - { - (*attrs)[i]->mod_values[j] = strdup(value); - (*attrs)[i]->mod_values[j+1] = NULL; - } - else - { - result = NSL_ERR_MEMORY; - } - } - } - - return (result); -} /* _addLDAPmodValue */ - - - - -/* - * ***************************************************************************** - * - * Function: _modLDAPmodValue() - * - * Description: Add the given attribute modify operation and its value into - * the LDAPMod array. This will either be a "replace" or a - * "delete"; value = null implies a "delete". - * If this is the first entry in the array then create it. - * - * Parameters: - * Input: LDAPMod ***attrs - array to update - * char *type - attribute to modify - * char *value - attribute value, null implies "delete" - * Output: None - * - * Returns: NSL_RESULT - NSL_OK = added okay - * - * ***************************************************************************** - */ - -static NSL_RESULT -_modLDAPmodValue(LDAPMod ***attrs, char *type, char *value) - -{ - int i = 0; - int j = 0; - NSL_RESULT result = NSL_OK; - - /* ---------- */ - - if ((attrs != NULL) && (type != NULL)) - { -#ifdef DEBUG -if (value != NULL) -printf("_modLDAPmodValue() REPLACE type='%s', value='%s'\n", type, value); -else -printf("_modLDAPmodValue() DELETE type='%s'\n", type); -#endif - /* search the existing LDAPMod array for the attribute */ - - for (i = 0; *attrs != NULL && (*attrs)[i] != NULL; i++) - { - if (strcasecmp((*attrs)[i]->mod_type, type) == 0) - { - break; - } - } - - if (*attrs == NULL) - { - /* array empty so create it */ - - *attrs = (LDAPMod **)calloc(1, 2 * sizeof (LDAPMod *)); - if (*attrs != NULL) - { - i = 0; - } - else - { - result = NSL_ERR_MEMORY; - } - - } - else - if ((*attrs)[i] == NULL) - { - /* attribute not found in array so add slot for it */ - - *attrs = (LDAPMod **) - realloc(*attrs, (i+2) * sizeof (LDAPMod *)); - if (*attrs == NULL) - { - result = NSL_ERR_MEMORY; - } - } - } - else - { - result = NSL_ERR_INTERNAL; - } - - if (result == NSL_OK) - { - if ((*attrs)[i] == NULL) - { - /* We've got a new slot. Create the new mod entry */ - - (*attrs)[i] = (LDAPMod *) malloc(sizeof (LDAPMod)); - if (((*attrs)[i] != NULL) && (value != NULL)) - { - /* Do an attribute replace */ - - (*attrs)[i]->mod_op = LDAP_MOD_REPLACE; - (*attrs)[i]->mod_type = strdup(type); - (*attrs)[i]->mod_values = (char **) - malloc(2 * sizeof (char *)); - if ((*attrs)[i]->mod_values != NULL) - { - (*attrs)[i]->mod_values[0] = - strdup(value); - (*attrs)[i]->mod_values[1] = NULL; - (*attrs)[i+1] = NULL; - } - else - { - result = NSL_ERR_MEMORY; - } - } - else - if ((*attrs)[i] != NULL) - { - /* value is null so do an attribute delete */ - - (*attrs)[i]->mod_op = LDAP_MOD_DELETE; - (*attrs)[i]->mod_type = strdup(type); - (*attrs)[i]->mod_values = NULL; - (*attrs)[i+1] = NULL; - } - else - { - result = NSL_ERR_MEMORY; /* malloc failed */ - } - } - - else - { - /* Found an existing entry so add value to it */ - - if (value != NULL) - { - /* add value to attribute's replace list */ - - if ((*attrs)[i]->mod_op == LDAP_MOD_REPLACE) - { - for (j = 0; - (*attrs)[i]->mod_values[j] != NULL; j++); - - (*attrs)[i]->mod_values = - (char **)realloc((*attrs)[i]->mod_values, - (j + 2) * sizeof (char *)); - if ((*attrs)[i]->mod_values != NULL) - { - (*attrs)[i]->mod_values[j] = - strdup(value); - (*attrs)[i]->mod_values[j+1] = NULL; - } - else - { - result = NSL_ERR_MEMORY; - } - } - else - { - /* Delete and replace not allowed */ - result = NSL_ERR_MULTIOP; - } - } - - else - { - /* - * attribute delete - so free any existing - * entries in the value array - */ - - (*attrs)[i]->mod_op = LDAP_MOD_DELETE; - - if ((*attrs)[i]->mod_values != NULL) - { - for (j = 0; - (*attrs)[i]->mod_values[j] != NULL; - j++) - { - free((*attrs)[i]->mod_values[j]); - } - - free((*attrs)[i]->mod_values); - (*attrs)[i]->mod_values = NULL; - } - } - } - } - - return (result); -} /* _modLDAPmodValue */ - - - - - -/* - * ***************************************************************************** - * - * Function: _constructAddLDAPMod() - * - * Description: For the given attribute list construct an - * LDAPMod array for the printer object to be added. Default - * attribute values are included. - * - * Parameters: - * Input: - * uchar_t *printerName - Name of printer to be added - * char **attrList - user specified attribute values list - * Output: LDAPMod ***attrs - pointer to the constructed array - * - * Returns: NSL_RESULT - NSL_OK = constructed okay - * - * ***************************************************************************** - */ - -static NSL_RESULT -_constructAddLDAPMod(uchar_t *printerName, char **attrList, LDAPMod ***attrs) - -{ - NSL_RESULT result = NSL_ERROR; - int len = 0; - char **p = NULL; - char *value = NULL; - char *attr = NULL; - - /* ---------- */ - - if ((printerName != NULL) && - ((attrList != NULL) && (attrList[0] != NULL)) && (attrs != NULL)) - { - *attrs = NULL; - - /* - * setup printer object attribute values in an LDAPMod structure - */ - result = _addLDAPmodValue(attrs, ATTR_OCLASS, OCV_TOP); - if (result == NSL_OK) - { - /* Structural Objectclass */ - result = - _addLDAPmodValue(attrs, ATTR_OCLASS, OCV_PSERVICE); - } - if (result == NSL_OK) - { - result = _addLDAPmodValue(attrs, - ATTR_OCLASS, OCV_PABSTRACT); - } - if (result == NSL_OK) - { - result = _addLDAPmodValue(attrs, - ATTR_OCLASS, OCV_SUNPRT); - } - if (result == NSL_OK) - { - result = _addLDAPmodValue(attrs, - ATTR_PNAME, (char *)printerName); - } - - /* - * Now work through the user supplied attribute - * values list and add them into the LDAPMod array - */ - - for (p = attrList; - (p != NULL) && (*p != NULL) && (result == NSL_OK); p++) - { - /* get length of this key word */ - - for (len = 0; - ((*p)[len] != '=') && ((*p)[len] != '\0'); len++); - - if ((strlen(*p) > len+1)) - { - attr = strdup(*p); - attr[len] = '\0'; - value = strdup(&attr[len+1]); - - /* handle specific Key Value Pairs (KVP) */ - - if (strcasecmp(attr, NS_KEY_BSDADDR) == 0) - { - /* use LDAP attribute name */ - free(attr); - attr = strdup(ATTR_BSDADDR); - } - else - if (_attrInLDAPList(attr) == 0) - { - /* - * Non-LDAP attribute so use LDAP - * KVP attribute and the given KVP - * as the value, ie. - * sun-printer-kvp=description=printer - */ - free(attr); - attr = strdup(ATTR_KVP); - value = strdup(*p); - } - - /* add it into the LDAPMod array */ - - result = _addLDAPmodValue(attrs, attr, value); - - free(attr); - free(value); - } - } /* for */ - - if ((result != NSL_OK) && (*attrs != NULL)) - { - (void) ldap_mods_free(*attrs, 1); - attrs = NULL; - } - } - else - { - result = NSL_ERR_INTERNAL; - } - - return (result); -} /* _constructAddLDAPMod */ - - - - - - - -/* - * ***************************************************************************** - * - * Function: _constructModLDAPMod() - * - * Description: For the given modify attribute list, construct an - * LDAPMod array for the printer object to be modified - * - * Parameters: - * Input: uchar_t *printerName - name of printer to be modified - * int sunPrinter - Boolean; object is a sunPrinter - * char **attrList - user specified attribute values list - * char ***oldKVPList - current list of KVP values on object - * Output: LDAPMod ***attrs - pointer to the constructed array - * - * Returns: NSL_RESULT - NSL_OK = constructed okay - * - * ***************************************************************************** - */ - -static NSL_RESULT -_constructModLDAPMod(uchar_t *printerName, int sunPrinter, char **attrList, - char ***oldKVPList, LDAPMod ***attrs) - -{ - NSL_RESULT result = NSL_OK; - int len = 0; - int kvpUpdated = 0; - int kvpExists = 0; - char **p = NULL; - char *value = NULL; - char *attr = NULL; - - /* ---------- */ - - if ((printerName != NULL) && - ((attrList != NULL) && (attrList[0] != NULL)) && (attrs != NULL)) - { - *attrs = NULL; - - if ((oldKVPList != NULL) && (*oldKVPList != NULL)) - { - kvpExists = 1; - } - - if (!sunPrinter) - { - /* - * The object was previously not a sunPrinter, so - * add the required objectclass attribute value, and - * ensure it has the printername attribute. - */ - result = _addLDAPmodValue(attrs, - ATTR_OCLASS, OCV_SUNPRT); - if (result == NSL_OK) - { - result = _modLDAPmodValue(attrs, - ATTR_PNAME, (char *)printerName); - } - } - - /* - * work through the user supplied attribute - * values list and add them into the LDAPMod array depending - * on if they are a replace or delete attribute operation, - * a "null value" means delete. - */ - - for (p = attrList; - (p != NULL) && (*p != NULL) && (result == NSL_OK); p++) - { - /* get length of this key word */ - - for (len = 0; - ((*p)[len] != '=') && ((*p)[len] != '\0'); len++); - - if ((strlen(*p) > len+1)) - { - attr = strdup(*p); - attr[len] = '\0'; - value = strdup(&attr[len+1]); - - /* handle specific Key Value Pairs (KVP) */ - - if ((_attrInLDAPList(attr) == 0) && - (strcasecmp(attr, NS_KEY_BSDADDR) != 0)) - { - /* - * Non-LDAP attribute so use LDAP - * KVP attribute and the given KVP as - * the value, ie. - * sun-printer-kvp=description=printer - */ - result = _modAttrKVP(*p, oldKVPList); - kvpUpdated = 1; - } - - else - { - if (strcasecmp(attr, NS_KEY_BSDADDR) == - 0) - { - /* - * use LDAP bsdaddr attribute - * name - */ - free(attr); - attr = strdup(ATTR_BSDADDR); - } - - /* - * else - * use the supplied attribute name - */ - - /* add it into the LDAPMod array */ - - result = _modLDAPmodValue(attrs, - attr, value); - } - - free(attr); - free(value); - } - - else - if (strlen(*p) >= 1) - { - /* handle attribute DELETE request */ - - attr = strdup(*p); - if (attr[len] == '=') - { - /* terminate "attribute=" */ - attr[len] = '\0'; - } - - /* handle specific Key Value Pairs (KVP) */ - - if (strcasecmp(attr, NS_KEY_BSDADDR) == 0) - { - /* use LDAP bsdaddr attribute name */ - result = _modLDAPmodValue(attrs, - ATTR_BSDADDR, NULL); - } - else - if (_attrInLDAPList(attr) == 0) - { - /* - * Non-LDAP kvp, so sort items - * in the kvp list - */ - result = _modAttrKVP(*p, oldKVPList); - kvpUpdated = 1; - } - else - { - result = _modLDAPmodValue(attrs, - attr, NULL); - } - - free(attr); - } - } /* for */ - - if ((result == NSL_OK) && (kvpUpdated)) - { - result = _attrAddKVP(attrs, *oldKVPList, kvpExists); - } - - if ((result != NSL_OK) && (*attrs != NULL)) - { - (void) ldap_mods_free(*attrs, 1); - *attrs = NULL; - } - } - else - { - result = NSL_ERR_INTERNAL; - } - - return (result); -} /* _constructModLDAPMod */ - - - - - - -/* - * ***************************************************************************** - * - * Function: _compareURIinDNs() - * - * Description: For the 2 given printer object DNs compare the naming part - * part of the DN (printer-uri) to see if they are the same. - * - * Note: This function only returns "compare failed" if their URI don't - * compare. Problems with the dn etc., return a good compare - * because I don't want us to create a new object for these - * - * Parameters: - * Input: uchar_t *dn1 - * uchar_t *dn2 - * Output: None - * - * Returns: NSL_RESULT - NSL_OK = URIs are the same - * - * ***************************************************************************** - */ - -static NSL_RESULT -_compareURIinDNs(uchar_t *dn1, uchar_t *dn2) - -{ - NSL_RESULT result = NSL_OK; - uchar_t *DN1 = NULL; - uchar_t *DN2 = NULL; - char *p1 = NULL; - char *p2 = NULL; - - /* --------- */ - - if ((dn1 != NULL) && (dn2 != NULL)) - { - DN1 = (uchar_t *)strdup((char *)dn1); - DN2 = (uchar_t *)strdup((char *)dn2); - - /* terminate each string after the printer-uri */ - - p1 = strstr((char *)DN1, PCONTAINER); - /* move back to the comma */ - while ((p1 != NULL) && (*p1 != ',') && (p1 >= (char *)DN1)) - { - p1--; - } - - p2 = strstr((char *)DN2, PCONTAINER); - /* move back to the comma */ - while ((p2 != NULL) && (*p2 != ',') && (p2 >= (char *)DN2)) - { - p2--; - } - - if ((*p1 == ',') && (*p2 == ',')) - { - *p1 = '\0'; /* re-terminate it */ - *p2 = '\0'; /* re-terminate it */ - - /* do the compare */ - - /* - * Note: SHOULD really normalise the 2 DNs before - * doing the compare - */ -#ifdef DEBUG -printf("_compareURIinDNs() @1 (%s) (%s)\n", DN1, DN2); -#endif - if (strcasecmp((char *)DN1, (char *)DN2) != 0) - { - result = NSL_ERROR; - } - - } - - free(DN1); - free(DN2); - } - - return (result); -} /* _compareURIinDNs */ - - - - - - - -/* - * ***************************************************************************** - * - * Function: _getThisNSDomainDN() - * - * Description: Get the current Name Service Domain DN - * This is extracted from the result of executing ldaplist. - * - * Note: Do it this way until the NS LDAP library interface is - * made public. - * - * Parameters: - * Input: None - * Output: None - * - * Returns: uchar_t* - pointer to NS Domain DN (The caller should free this - * returned memory). - * - * ***************************************************************************** - */ - -#define LDAPLIST_D "/usr/bin/ldaplist -d 2>&1" -#define DNID "dn: " - -static uchar_t * -_getThisNSDomainDN(void) - -{ - uchar_t *domainDN = NULL; - char *cp = NULL; - char buf[BUFSIZ] = ""; - - /* --------- */ - - if (_popen(LDAPLIST_D, buf, sizeof (buf)) == 0) - { - if ((cp = strstr(buf, DNID)) != NULL) - { - cp += strlen(DNID); /* increment past "dn: " label */ - domainDN = (uchar_t *)strdup(cp); - - if ((cp = strchr((char *)domainDN, '\n')) != NULL) - { - *cp = '\0'; /* terminate it */ - } - } - } - - return (domainDN); -} /* _getThisNSDomainDN */ - - - - - -/* - * ***************************************************************************** - * - * Function: _popen() - * - * Description: General popen function. The caller should always use a full - * path cmd. - * - * Parameters: - * Input: char *cmd - command line to execute - * char *buffer - ptr to buffer to put result in - * int size - size of result buffer - * Output: None - * - * Returns: int - 0 = opened okay - * - * ***************************************************************************** - */ - -static int -_popen(char *cmd, char *buffer, int size) - -{ - int result = -1; - int rsize = 0; - FILE *fptr; - char safe_cmd[BUFSIZ]; - char linebuf[BUFSIZ]; - - /* -------- */ - - if ((cmd != NULL) && (buffer != NULL) && (size != 0)) - { - (void) strcpy(buffer, ""); - (void) strcpy(linebuf, ""); - (void) snprintf(safe_cmd, BUFSIZ, "IFS=' \t'; %s", cmd); - - if ((fptr = popen(safe_cmd, "r")) != NULL) - { - while ((fgets(linebuf, BUFSIZ, fptr) != NULL) && - (rsize < size)) - { - rsize = strlcat(buffer, linebuf, size); - if (rsize >= size) - { - /* result is too long */ - (void) memset(buffer, '\0', size); - } - } - - if (strlen(buffer) > 0) - { - result = 0; - } - - (void) pclose(fptr); - } - } - - return (result); -} /* popen */ - - -/* - * ***************************************************************************** - * - * Function: _attrInList() - * - * Description: For the given list check if the attribute is it - * - * Parameters: - * Input: char *attr - attribute to check - * char **list - list of attributes to check against - * Output: None - * - * Returns: int - TRUE = attr found in list - * - * ***************************************************************************** - */ - -static int -_attrInList(char *attr, const char **list) - -{ - int result = 0; - int j; - - /* ------- */ - - if ((attr != NULL) && (list != NULL)) - { - for (j = 0; (list[j] != NULL) && (result != 1); j++) - { - if (strcasecmp(list[j], attr) == 0) - { - result = 1; /* found */ - } - } - } - - return (result); -} /* _attrInList */ - - - - -/* - * ***************************************************************************** - * - * Function: _attrInLDAPList() - * - * Description: Checks to see if the given attribute is an LDAP printing - * attribute, ie. is either in an IPP objectclass or the - * sun printer objectclass. Note: some attributes are handled - * specifically outside this function, so are excluded from - * the lists that are checked. - * - * Parameters: - * Input: char *attr - attribute to check - * Output: None - * - * Returns: int - TRUE = attr found in list - * - * ***************************************************************************** - */ - -static int -_attrInLDAPList(char *attr) - -{ - int result = 0; - - /* ------- */ - - if (_attrInList(attr, nsl_attr_printerService)) - { - result = 1; /* in list */ - } - else - if (_attrInList(attr, nsl_attr_printerIPP)) - { - result = 1; /* in list */ - } - else - if (_attrInList(attr, nsl_attr_sunPrinter)) - { - result = 1; /* in list */ - } - - return (result); -} /* _attrInLDAPList */ - - - - -/* - * ***************************************************************************** - * - * Function: _getCurrentKVPValues() - * - * Description: For the given printer object read the current set of values - * the object has for the sun-printer-kvp (Key Value pair) - * - * Parameters: - * Input: LDAP *ld - existing ldap connection descriptor - * char *objectDN - DN to search for - * Output: char ***list - returned set of kvp values - * - * Result: NSL_RESULT - NSL_OK = object exists - * - * ***************************************************************************** - */ - -static NSL_RESULT -_getCurrentKVPValues(LDAP *ld, uchar_t *objectDN, char ***list) - -{ - NSL_RESULT result = NSL_ERR_UNKNOWN_PRINTER; - int sresult = LDAP_NO_SUCH_OBJECT; - int i = 0; - LDAPMessage *ldapMsg; - char *requiredAttrs[2] = { ATTR_KVP, NULL }; - LDAPMessage *ldapEntry = NULL; - char *entryAttrib = NULL; - char **attribValues = NULL; - BerElement *berElement = NULL; - - /* ---------- */ - - if ((list != NULL) && (ld != NULL) && (objectDN != NULL)) - { - /* search for this Printer in the directory */ - - sresult = ldap_search_s(ld, (char *)objectDN, LDAP_SCOPE_BASE, - "(objectclass=*)", requiredAttrs, 0, &ldapMsg); - if (sresult == LDAP_SUCCESS) - { - /* - * check that the object exists and extract its - * KVP attribute values - */ - ldapEntry = ldap_first_entry(ld, ldapMsg); - if (ldapEntry != NULL) - { - entryAttrib = ldap_first_attribute(ld, - ldapEntry, &berElement); - if ((entryAttrib != NULL) && - (strcasecmp(entryAttrib, ATTR_KVP) == 0)) - - { -#ifdef DEBUG -printf("Attribute: %s, its values are:\n", entryAttrib); -#endif - /* - * add each KVP value to the list - * that we will return - */ - attribValues = ldap_get_values( - ld, ldapEntry, entryAttrib); - for (i = 0; - attribValues[i] != NULL; i++) - { - *list = (char **) - list_append((void **)*list, - strdup(attribValues[i])); -#ifdef DEBUG -printf("\t%s\n", attribValues[i]); -#endif - } - (void) ldap_value_free(attribValues); - } - - if ((entryAttrib != NULL) && - (berElement != NULL)) - { - ber_free(berElement, 0); - } - - - /* object found */ - result = NSL_OK; - } - - (void) ldap_msgfree(ldapMsg); - } - } - - else - { - result = NSL_ERR_INTERNAL; - } - - return (result); -} /* _getCurrentKVPValues */ - - - -/* - * ***************************************************************************** - * - * Function: _freeList() - * - * Description: Free the list created by list_append() where the items in - * the list have been strdup'ed. - * - * Parameters: - * Input: char ***list - returned set of kvp values - * - * Result: void - * - * ***************************************************************************** - */ - -static void -_freeList(char ***list) - -{ - int i = 0; - - /* ------ */ - - if (list != NULL) - { - if (*list != NULL) - { - for (i = 0; (*list)[i] != NULL; i++) - { - free((*list)[i]); - } - free(*list); - } - - *list = NULL; - } -} /* _freeList */ - - - -/* - * ***************************************************************************** - * - * Function: _modAttrKVP() - * - * Description: Sort out the KVP attribute value list, such that this new - * value takes precidence over any existing value in the list. - * The current list is updated to remove this key, and the new - * key "value" is added to the list, eg. for - * value: bbb=ddddd - * and kvpList: - * aaa=yyyy - * bbb=zzzz - * ccc=xxxx - * the resulting kvpList is: - * aaa=yyyy - * ccc=xxxx - * bbb=ddddd - * - * Note: When all new values have been handled the function _attrAddKVP() - * must be called to add the "new list" values into the - * LDAPMod array. - * - * Parameters: - * Input: char *value - Key Value Pair to process, - * eg. aaaaa=hhhhh, where aaaaa is the key - * char ***kvpList - list of current KVP values - * Output: char ***kvpList - updated list of KVP values - * - * Returns: NSL_RESULT - NSL_OK = done okay - * - * ***************************************************************************** - */ - -static NSL_RESULT -_modAttrKVP(char *value, char ***kvpList) - -{ - NSL_RESULT result = NSL_ERR_INTERNAL; - int i = 0; - int inList = 0; - int keyDelete = 0; - char *key = NULL; - char **p = NULL; - char **newList = NULL; - - /* ------- */ - - if ((value != NULL) && (kvpList != NULL)) - { - result = NSL_OK; - - /* extract "key" from value */ - - key = strdup(value); - - for (i = 0; ((key)[i] != '=') && ((key)[i] != '\0'); i++); - key[i] = '\0'; /* terminate the key */ - - /* Is this a request to delete a "key" value */ - - if ((value[i] == '\0') || (value[i+1] == '\0')) - { - /* this is a request to delete the key */ - keyDelete = 1; - } - - if ((*kvpList != NULL) && (**kvpList != NULL)) - { - /* - * for each item in the list remove it if the keys match - */ - for (p = *kvpList; *p != NULL; p++) - { - for (i = 0; - ((*p)[i] != '=') && ((*p)[i] != '\0'); i++); - - if ((strlen(key) == i) && - (strncasecmp(*p, key, i) == 0)) - { - inList = 1; - } - else - { - /* no match so add value to new list */ - newList = (char **)list_append( - (void **)newList, - strdup(*p)); - } - } - } - - /* - * if it was not a DELETE request add the new key value into - * the newList, otherwise we have already removed the key - */ - - if (!keyDelete) - { - newList = (char **)list_append((void **)newList, - strdup(value)); - } - - if ((newList != NULL) || (inList)) - { - /* replace old list with the newList */ - _freeList(kvpList); - *kvpList = newList; - } - - free(key); - } - - return (result); -} /* modAttrKVP */ - - - - -/* - * ***************************************************************************** - * - * Function: _attrAddKVP() - * - * Description: Process KVP items in the kvpList adding them to the - * LDAPMod modify array. If the list is empty but there were - * previously LDAP KVP values delete them. - * - * Note: This function should only be called when all the new KVP - * items have been processed by _modAttrKVP() - * - * Parameters: - * Input: LDAPMod ***attrs - array to update - * char **kvpList - list KVP values - * int kvpExists - object currently has LDAP KVP values - * Output: None - * - * Returns: NSL_RESULT - NSL_OK = done okay - * - * ***************************************************************************** - */ - -static NSL_RESULT -_attrAddKVP(LDAPMod ***attrs, char **kvpList, int kvpExists) - -{ - NSL_RESULT result = NSL_OK; - - /* ------- */ - - if (attrs != NULL) - { - if (kvpList != NULL) - { - while ((kvpList != NULL) && (*kvpList != NULL)) - { - /* add item to LDAPMod array */ - - result = - _modLDAPmodValue(attrs, ATTR_KVP, *kvpList); - - kvpList++; - } - } - else - if (kvpExists) - { - /* - * We now have no LDAP KVP values but there were - * some previously, so delete them - */ - result = _modLDAPmodValue(attrs, ATTR_KVP, NULL); - } - } - - else - { - result = NSL_ERR_INTERNAL; - } - - return (result); -} /* _attrAddKVP */ - - - - -/* - * ***************************************************************************** - * - * Function: _manageReferralCredentials() - * - * Description: This function is called if a referral request is returned by - * the origonal LDAP server during the ldap update request call, - * eg. ldap_add_s(), ldap_modify_s() or ldap_delete_s(). - * Parameters: - * Input: LDAP *ld - LDAP descriptor - * int freeit - 0 = first call to get details - * - 1 = second call to free details - * - -1 = initial store of authentication details - * Input/Output: char **dn - returns DN to bind to on master - * char **credp - returns password for DN - * int *methodp - returns authentication type, eg. simple - * - * Returns: int - 0 = okay - * - * ***************************************************************************** - */ -static int _manageReferralCredentials(LDAP *ld, char **dn, char **credp, - int *methodp, int freeit) - -{ - int result = 0; - static char *sDN = NULL; - static char *sPasswd = NULL; - static int sMethod = LDAP_AUTH_SIMPLE; - - /* -------- */ - - if (freeit == 1) - { - /* second call - free memory */ - - if ((dn != NULL) && (*dn != NULL)) - { - free(*dn); - } - - if ((credp != NULL) && (*credp != NULL)) - { - free(*credp); - } - } - - else - if ((ld != NULL) && - (dn != NULL) && (credp != NULL) && (methodp != NULL)) - { - if ((freeit == 0) && (sDN != NULL) && (sPasswd != NULL)) - { - /* first call - get the saved bind credentials */ - - *dn = strdup(sDN); - *credp = strdup(sPasswd); - *methodp = sMethod; - } - else - if (freeit == -1) - { - /* initial call - save the saved bind credentials */ - - sDN = *dn; - sPasswd = *credp; - sMethod = *methodp; - } - else - { - result = 1; /* error */ - } - } - else - { - result = 1; /* error */ - } - - return (result); -} /* _manageReferralCredentials */ diff --git a/usr/src/lib/print/libprint/common/nss_printer.c b/usr/src/lib/print/libprint/common/nss_printer.c deleted file mode 100644 index 149ddadd5c..0000000000 --- a/usr/src/lib/print/libprint/common/nss_printer.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <stdio.h> -#include <string.h> -#include <ctype.h> -#include <sys/types.h> -#include <nss_dbdefs.h> -#include <syslog.h> -#include <ns.h> - -#ifndef NSS_DBNAM__PRINTERS /* not in nss_dbdefs.h because it's private */ -#define NSS_DBNAM__PRINTERS "_printers" -#endif - -static DEFINE_NSS_DB_ROOT(db_root); -static DEFINE_NSS_GETENT(context); - -static int printers_stayopen; -static char *private_ns = NULL; - -static void -_nss_initf_printers(p) - nss_db_params_t *p; -{ - if (private_ns != NULL) { - /* - * because we need to support a legacy interface that allows - * us to select a specific name service, we need to dummy up - * the parameters to use a private nsswitch database and set - * the * default_config entry to the name service we are - * looking into. - */ - p->name = NSS_DBNAM__PRINTERS; /* "_printers" */ - p->default_config = normalize_ns_name(private_ns); - } else { - /* regular behaviour */ - p->name = NSS_DBNAM_PRINTERS; /* "printers" */ - p->default_config = NSS_DEFCONF_PRINTERS; - } - syslog(LOG_DEBUG, "database: %s, default: %s", - (p->name ? p->name : "NULL"), - (p->default_config ? p->default_config : "NULL")); -} - -/* - * Return values: 0 = success, 1 = parse error, 2 = erange ... - * The structure pointer passed in is a structure in the caller's space - * wherein the field pointers would be set to areas in the buffer if - * need be. instring and buffer should be separate areas. - */ -/* ARGSUSED */ -static int -str2printer(const char *instr, int lenstr, void *ent, char *buffer, int buflen) -{ - if (lenstr + 1 > buflen) - return (NSS_STR_PARSE_ERANGE); - - /* skip entries that begin with '#' */ - if (instr[0] == '#') - return (NSS_STR_PARSE_PARSE); - - /* - * We copy the input string into the output buffer - */ - (void) memcpy(buffer, instr, lenstr); - buffer[lenstr] = '\0'; - - return (NSS_STR_PARSE_SUCCESS); -} - - -int -setprinterentry(int stayopen, char *ns) -{ - printers_stayopen |= stayopen; - private_ns = ns; - nss_setent(&db_root, _nss_initf_printers, &context); - private_ns = NULL; - return (0); -} - - -int -endprinterentry() -{ - printers_stayopen = 0; - nss_endent(&db_root, _nss_initf_printers, &context); - nss_delete(&db_root); - private_ns = NULL; - return (0); -} - - -/* ARGSUSED2 */ -int -getprinterentry(char *linebuf, int linelen, char *ns) -{ - nss_XbyY_args_t arg; - nss_status_t res; - - private_ns = ns; - NSS_XbyY_INIT(&arg, linebuf, linebuf, linelen, str2printer); - res = nss_getent(&db_root, _nss_initf_printers, &context, &arg); - (void) NSS_XbyY_FINI(&arg); - private_ns = NULL; - - return (arg.status = res); -} - - -int -getprinterbyname(char *name, char *linebuf, int linelen, char *ns) -{ - nss_XbyY_args_t arg; - nss_status_t res; - - private_ns = ns; - NSS_XbyY_INIT(&arg, linebuf, linebuf, linelen, str2printer); - arg.key.name = name; - res = nss_search(&db_root, _nss_initf_printers, - NSS_DBOP_PRINTERS_BYNAME, &arg); - (void) NSS_XbyY_FINI(&arg); - private_ns = NULL; - - return (arg.status = res); -} diff --git a/usr/src/lib/print/libprint/common/nss_write.c b/usr/src/lib/print/libprint/common/nss_write.c deleted file mode 100644 index c617f0d0a5..0000000000 --- a/usr/src/lib/print/libprint/common/nss_write.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <string.h> -#include <stdarg.h> -#include <fcntl.h> -#include <syslog.h> -#include <errno.h> -#include <pwd.h> -#include <libintl.h> -#include <netdb.h> /* for rcmd() */ - -#include <ns.h> -#include <list.h> - -/* escaped chars include delimiters and shell meta characters */ -#define ESCAPE_CHARS "\\\n=: `&;|>^$()<*?[" - -/* - * This modules contains all of the code nedessary to write back to each - * printing configuration data repository. The support is intended to - * introduce the least number of dependencies in the library, so it doesn't - * always perform it's operations in the cleanest fashion. - */ - - -/* - * Generic Files support begins here. - */ -static char * -freadline(FILE *fp, char *buf, int buflen) -{ - char *s = buf; - - while (fgets(s, buflen, fp)) { - if ((s == buf) && ((*s == '#') || (*s == '\n'))) { - continue; - } else { - if ((*s == '#') || (*s == '\n')) { - *s = NULL; - break; - } - - buflen -= strlen(s); - s += strlen(s); - - if (*(s - 2) != '\\') - break; -#ifdef STRIP_CONTINUATION - buflen -= 2; - s -= 2; -#endif - } - } - - if (s == buf) - return (NULL); - else - return (buf); -} - - -static int -_file_put_printer(const char *file, const ns_printer_t *printer) -{ - FILE *ifp, - *ofp; - char *tmpfile; - int fd; - int exit_status = 0; - int size; - - size = strlen(file) + 1 + 20; - if ((tmpfile = malloc(size)) == NULL) - return (-1); - - if (snprintf(tmpfile, size, "%sXXXXXX", file) >= size) { - syslog(LOG_ERR, "_file_put_printer:buffer overflow:tmpfile"); - return (-1); - } - - /* LINTED */ - while (1) { /* syncronize writes */ - fd = open(file, O_RDWR|O_CREAT|O_EXCL, 0644); - if ((fd < 0) && (errno == EEXIST)) - fd = open(file, O_RDWR); - if (fd < 0) { - if (errno == EAGAIN) - continue; - free(tmpfile); - return (-1); - } - if (lockf(fd, F_TLOCK, 0) == 0) - break; - (void) close(fd); - } - - if ((ifp = fdopen(fd, "r")) == NULL) { - (void) close(fd); - free(tmpfile); - return (-1); - } - - if ((fd = mkstemp(tmpfile)) < 0) { - (void) fclose(ifp); - free(tmpfile); - return (-1); - } - - (void) fchmod(fd, 0644); - if ((ofp = fdopen(fd, "wb+")) != NULL) { - char buf[4096]; - - (void) fprintf(ofp, - "#\n#\tIf you hand edit this file, comments and structure may change.\n" - "#\tThe preferred method of modifying this file is through the use of\n" - "#\tlpset(1M)\n#\n"); - - /* - * Handle the special case of lpset -x all - * This deletes all entries in the file - * In this case, just don't write any entries to the tmpfile - */ - - if (!((strcmp(printer->name, "all") == 0) && - (printer->attributes == NULL))) { - char *t, *entry, *pentry; - - (void) _cvt_printer_to_entry((ns_printer_t *)printer, - buf, sizeof (buf)); - t = pentry = strdup(buf); - - while (freadline(ifp, buf, sizeof (buf)) != NULL) { - ns_printer_t *tmp = (ns_printer_t *) - _cvt_nss_entry_to_printer(buf, ""); - - if (ns_printer_match_name(tmp, printer->name) - == 0) { - entry = pentry; - pentry = NULL; - } else - entry = buf; - - (void) fprintf(ofp, "%s\n", entry); - } - - if (pentry != NULL) - (void) fprintf(ofp, "%s\n", pentry); - free(t); - } - - (void) fclose(ofp); - (void) rename(tmpfile, file); - } else { - (void) close(fd); - (void) unlink(tmpfile); - exit_status = -1; - } - - (void) fclose(ifp); /* releases the lock, after rename on purpose */ - (void) free(tmpfile); - return (exit_status); -} - - -/* - * Support for writing a printer into the FILES /etc/printers.conf - * file. - */ -int -files_put_printer(const ns_printer_t *printer) -{ - static char *file = "/etc/printers.conf"; - - return (_file_put_printer(file, printer)); -} - -/* - * Support for writing a printer into the NIS printers.conf.byname - * map. - */ - -#include <rpc/rpc.h> -#include <rpcsvc/ypclnt.h> -#include <rpcsvc/yp_prot.h> - -/* - * Run the remote command. We aren't interested in any io, Only the - * return code. - */ -static int -remote_command(char *command, char *host) -{ - struct passwd *pw; - - if ((pw = getpwuid(getuid())) != NULL) { - int fd; - - if ((fd = rcmd_af(&host, htons(514), pw->pw_name, "root", - command, NULL, AF_INET6)) < 0) - return (-1); - (void) close(fd); - return (0); - } else - return (-1); -} - - -/* - * This isn't all that pretty, but you can update NIS if the machine this - * runs on is in the /.rhosts or /etc/hosts.equiv on the NIS master. - * copy it local, update it, copy it remote - */ -#define TMP_PRINTERS_FILE "/tmp/printers.NIS" -#define NIS_MAKEFILE "/var/yp/Makefile" -#define MAKE_EXCERPT "/usr/lib/print/Makefile.yp" -/*ARGSUSED*/ -int -nis_put_printer(const ns_printer_t *printer) -{ - static char *domain = NULL; - char *map = "printers.conf.byname"; - char *tmp = NULL; - char *host = NULL; - char lfile[BUFSIZ]; - char rfile[BUFSIZ]; - char cmd[BUFSIZ]; - - if (domain == NULL) - (void) yp_get_default_domain(&domain); - - if ((yp_master(domain, (char *)map, &host) != 0) && - (yp_master(domain, "passwd.byname", &host) != 0)) - return (-1); - - if (snprintf(lfile, sizeof (lfile), "/tmp/%s", map) >= - sizeof (lfile)) { - syslog(LOG_ERR, "nis_put_printer:lfile buffer overflow"); - return (-1); - } - if (snprintf(rfile, sizeof (rfile), "root@%s:/etc/%s", host, map) >= - sizeof (rfile)) { - syslog(LOG_ERR, "nis_put_printer:rfile buffer overflow"); - return (-1); - } - - if (((tmp = strrchr(rfile, '.')) != NULL) && - (strcmp(tmp, ".byname") == 0)) - *tmp = NULL; /* strip the .byname */ - - /* copy it local */ - if (snprintf(cmd, sizeof (cmd), "rcp %s %s >/dev/null 2>&1", - rfile, lfile) >= sizeof (cmd)) { - syslog(LOG_ERR, - "nis_put_printer:buffer overflow building cmd"); - return (-1); - } - (void) system(cmd); /* could fail because it doesn't exist */ - - - /* update it */ - if (_file_put_printer(lfile, printer) != 0) - return (-1); - - /* copy it back */ - if (snprintf(cmd, sizeof (cmd), "rcp %s %s >/dev/null 2>&1", - lfile, rfile) >= sizeof (cmd)) { - syslog(LOG_ERR, - "nis_put_printer:buffer overflow building cmd"); - return (-1); - } - if (system(cmd) != 0) - return (-1); - - /* copy the Makefile excerpt */ - if (snprintf(cmd, sizeof (cmd), - "rcp %s root@%s:%s.print >/dev/null 2>&1", - MAKE_EXCERPT, host, NIS_MAKEFILE) >= sizeof (cmd)) { - syslog(LOG_ERR, - "nis_put_printer:buffer overflow building cmd"); - return (-1); - } - - if (system(cmd) != 0) - return (-1); - - /* run the make */ - if (snprintf(cmd, sizeof (cmd), - "/bin/sh -c 'PATH=/usr/ccs/bin:/bin:/usr/bin:$PATH " - "make -f %s -f %s.print printers.conf >/dev/null 2>&1'", - NIS_MAKEFILE, NIS_MAKEFILE) >= sizeof (cmd)) { - syslog(LOG_ERR, - "nis_put_printer:buffer overflow on make"); - return (-1); - } - - return (remote_command(cmd, host)); -} diff --git a/usr/src/lib/print/libprint/common/sunPrinter.at.conf.txt b/usr/src/lib/print/libprint/common/sunPrinter.at.conf.txt deleted file mode 100644 index 0cac14ae95..0000000000 --- a/usr/src/lib/print/libprint/common/sunPrinter.at.conf.txt +++ /dev/null @@ -1,64 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# Copyright 2001 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" - -# IPP Draft 4 schema and Sun Printer Schema - -attribute printer-uri 1.3.18.0.2.4.1140 cis single -attribute printer-xri-supported 1.3.18.0.2.4.1107 cis -attribute printer-name 1.3.18.0.2.4.1135 cis single -attribute printer-natural-language-configured 1.3.18.0.2.4.1119 cis single -attribute printer-location 1.3.18.0.2.4.1136 cis single -attribute printer-info 1.3.18.0.2.4.1139 cis single -attribute printer-more-info 1.3.18.0.2.4.1134 cis single -attribute printer-make-and-model 1.3.18.0.2.4.1138 cis single -attribute printer-ipp-versions-supported 1.3.18.0.2.4.1133 cis -attribute printer-multiple-document-jobs-supported 1.3.18.0.2.4.1132 bin single -attribute printer-charset-configured 1.3.18.0.2.4.1109 cis single -attribute printer-charset-supported 1.3.18.0.2.4.1131 cis -attribute printer-generated-natural-language-supported 1.3.18.0.2.4.1137 cis -attribute printer-document-format-supported 1.3.18.0.2.4.1130 cis -attribute printer-color-supported 1.3.18.0.2.4.1129 bin single -attribute printer-compression-supported 1.3.18.0.2.4.1128 cis -attribute printer-pages-per-minute 1.3.18.0.2.4.1127 bin single -attribute printer-pages-per-minute-color 1.3.18.0.2.4.1126 bin single -attribute printer-finishings-supported 1.3.18.0.2.4.1125 cis -attribute printer-number-up-supported 1.3.18.0.2.4.1124 bin -attribute printer-sides-supported 1.3.18.0.2.4.1123 cis -attribute printer-media-supported 1.3.18.0.2.4.1122 cis -attribute printer-media-local-supported 1.3.18.0.2.4.1117 cis -attribute printer-resolution-supported 1.3.18.0.2.4.1121 cis -attribute printer-print-quality-supported 1.3.18.0.2.4.1120 cis -attribute printer-job-priority-supported 1.3.18.0.2.4.1110 bin single -attribute printer-copies-supported 1.3.18.0.2.4.1118 bin single -attribute printer-job-k-octets-supported 1.3.18.0.2.4.1111 bin single -attribute printer-current-operator 1.3.18.0.2.4.1112 cis single -attribute printer-service-person 1.3.18.0.2.4.1113 cis single -attribute printer-delivery-orientation-supported 1.3.18.0.2.4.1114 cis -attribute printer-stacking-order-supported 1.3.18.0.2.4.1115 cis -attribute printer-output-features-supported 1.3.18.0.2.4.1116 cis -attribute printer-aliases 1.3.18.0.2.4.1108 cis -attribute sun-printer-bsdaddr 1.3.6.1.4.1.42.2.27.5.1.63 cis single -attribute sun-printer-kvp 1.3.6.1.4.1.42.2.27.5.1.64 cis diff --git a/usr/src/lib/print/libprint/common/sunPrinter.oc.conf.txt b/usr/src/lib/print/libprint/common/sunPrinter.oc.conf.txt deleted file mode 100644 index 77f365819d..0000000000 --- a/usr/src/lib/print/libprint/common/sunPrinter.oc.conf.txt +++ /dev/null @@ -1,116 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# Copyright 2001 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" - -# IPP Schema Draft 4 and Sun Printer Schema - -objectclass slpService - oid 1.3.18.0.2.6.2549 - superior - top - -objectclass slpServicePrinter - oid 1.3.18.0.2.6.254 - superior - slpService - -objectclass printerAbstract - oid 1.3.18.0.2.6.258 - superior - top - allows - printer-charset-configured, - printer-charset-supported, - printer-color-supported, - printer-compression-supported, - printer-copies-supported, - printer-current-operator, - printer-delivery-orientation-supported, - printer-document-format-supported, - printer-finishings-supported, - printer-generated-natural-language-supported, - printer-info, - printer-job-k-octets-supported, - printer-job-priority-supported, - printer-location, - printer-make-and-model, - printer-media-local-supported, - printer-media-supported, - printer-more-info, - printer-multiple-document-jobs-supported, - printer-name, - printer-natural-language-configured, - printer-number-up-supported, - printer-output-features-supported, - printer-pages-per-minute, - printer-pages-per-minute-color, - printer-print-quality-supported, - printer-resolution-supported, - printer-service-person, - printer-sides-supported, - printer-stacking-order-supported - -objectclass printerService - oid 1.3.18.0.2.6.255 - superior - printerAbstract - allows - printer-uri, - printer-xri-supported - -objectclass printerServiceAuxClass - oid 1.3.18.0.2.6.257 - superior - printerAbstract - allows - printer-uri, - printer-xri-supported - -objectclass printerIPP - oid 1.3.18.0.2.6.256 - superior - top - allows - printer-ipp-versions-supported, - printer-multiple-document-jobs-supported - -objectclass printerLPR - oid 1.3.18.0.2.6.253 - superior - top - requires - printer-name - allows - printer-aliases - -objectclass sunPrinter - oid 1.3.6.1.4.1.42.2.27.5.2.14 - superior - top - requires - printer-name - allows - sun-printer-bsdaddr, - sun-printer-kvp diff --git a/usr/src/lib/print/libprint/i386/Makefile b/usr/src/lib/print/libprint/i386/Makefile deleted file mode 100644 index 3b985583a4..0000000000 --- a/usr/src/lib/print/libprint/i386/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBS) $(ROOTLINKS) # $(ROOTLINT) diff --git a/usr/src/lib/print/libprint/sparc/Makefile b/usr/src/lib/print/libprint/sparc/Makefile deleted file mode 100644 index 3b985583a4..0000000000 --- a/usr/src/lib/print/libprint/sparc/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "%Z%%M% %I% %E% SMI" -# - -include ../Makefile.com - -install: all $(ROOTLIBS) $(ROOTLINKS) # $(ROOTLINT) diff --git a/usr/src/lib/print/mod_ipp/Makefile b/usr/src/lib/print/mod_ipp/Makefile deleted file mode 100644 index 8d6500fb41..0000000000 --- a/usr/src/lib/print/mod_ipp/Makefile +++ /dev/null @@ -1,95 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2010 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY = mod_ipp.a -VERS = -OBJECTS = mod_ipp.o - -include ../../Makefile.lib -include ../../Makefile.rootfs - -APACHEMODDIR = $(ROOT)/usr/apache/libexec -APACHECONFDIR = $(ROOT)/etc/apache -LISTENERDIR = $(ROOT)/var/lp/ipp-listener - -ROOTDIRS = $(ROOT)/usr/apache $(APACHEMODDIR) $(APACHECONFDIR) \ - $(ROOT)/var/lp $(LISTENERDIR) - -$(ROOT)/var/lp:= DIRMODE = 775 -$(ROOT)/var/lp:= FILEMODE = 775 - -LIBS = $(DYNLIB) - -SRCS = $(OBJECTS:%.o = %.c) - - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I../libipp-listener/common -CPPFLAGS += -I../libipp-core/common -CPPFLAGS += -I/usr/apache/include -CPPFLAGS += -DEAPI -ZDEFS = $(ZNODEFS) - -MAPFILES = mapfile - -LDLIBS += -lipp-listener -lipp-core -lpapi -lc - -# SMF manifest -MANIFEST= ipp-listener.xml -ROOTMANIFESTDIR= $(ROOT)/lib/svc/manifest/application/print -ROOTMANIFEST= $(MANIFEST:%=$(ROOTMANIFESTDIR)/%) -$(ROOTMANIFEST) := FILEMODE= 444 - -# Apache module -$(APACHEMODDIR)/$(LIBLINKS): $(ROOTDIRS) - -# Apache config -APACHECONFFILE= $(APACHECONFDIR)/httpd-standalone-ipp.conf -$(APACHECONFFILE) := FILEMODE= 644 -LISTENERFILE= $(LISTENERDIR)/index.html -$(LISTENERFILE) := FILEMODE= 444 - -$(ROOT)/var/lp:= FILEMODE = 0775 - -$(APACHEMODDIR)/$(LIBLINKS):= FILEMODE = 0555 - -$(ROOTMANIFESTDIR)/% $(APACHEMODDIR)/% $(APACHECONFDIR)/% $(LISTENERDIR)/%: % - $(INS.file) - -$(ROOTDIRS): - $(INS.dir) - -.KEEP_STATE: - -all: $(LIBS) - -install: all $(APACHEMODDIR)/$(LIBLINKS) $(APACHECONFFILE) \ - $(LISTENERFILE) $(ROOTMANIFEST) - -install_h: - -lint: - -include ../../Makefile.targ diff --git a/usr/src/lib/print/mod_ipp/httpd-standalone-ipp.conf b/usr/src/lib/print/mod_ipp/httpd-standalone-ipp.conf deleted file mode 100644 index 07a4b8dc11..0000000000 --- a/usr/src/lib/print/mod_ipp/httpd-standalone-ipp.conf +++ /dev/null @@ -1,341 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# "$Id: httpd-standalone-ipp.conf,v 1.4 2006/03/24 00:26:54 njacobs Exp $" -# - -# ident "%Z%%M% %I% %E% SMI" - -## -## httpd-standalone-ipp.conf -- Apache HTTP server configuration file for -## an Internet Print Protocol (IPP) listener -## - -# -# Based upon the NCSA server configuration files originally by Rob McCool. -# -# This is the main Apache server configuration file. It contains the -# configuration directives that give the server its instructions. -# See <URL:http://www.apache.org/docs/> for detailed information about -# the directives. mod_ipp specific directives are described in the -# mod_ipp(4) man page. -# - -### Section 1: Global Environment -# -# The directives in this section affect the overall operation of Apache, -# such as the number of concurrent requests it can handle or where it -# can find its configuration files. -# - -# -# ServerType is either inetd, or standalone. Inetd mode is only supported on -# Unix platforms. -# -ServerType standalone - -# -# ServerRoot: The top of the directory tree under which the server's -# configuration, error, and log files are kept. -# -# NOTE! If you intend to place this on an NFS (or otherwise network) -# mounted filesystem then please read the LockFile documentation -# (available at <URL:http://www.apache.org/docs/mod/core.html#lockfile>); -# you will save yourself a lot of trouble. -# -ServerRoot "/usr/apache" - -# -# The LockFile directive sets the path to the lockfile used when Apache -# is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or -# USE_FLOCK_SERIALIZED_ACCEPT. This directive should normally be left at -# its default value. The main reason for changing it is if the logs -# directory is NFS mounted, since the lockfile MUST BE STORED ON A LOCAL -# DISK. The PID of the main server process is automatically appended to -# the filename. -# -#LockFile /var/run/httpd.lock -LockFile /var/run/httpd-standalone-ipp.lock - -# -# PidFile: The file in which the server should record its process -# identification number when it starts. -# -PidFile /var/run/httpd-standalone-ipp.pid - -# -# ScoreBoardFile: File used to store internal server process information. -# Not all architectures require this. But if yours does (you'll know because -# this file will be created when you run Apache) then you *must* ensure that -# no two invocations of Apache share the same scoreboard file. -# -ScoreBoardFile /var/run/httpd-standalone-ipp.scoreboard - -# -# In the standard configuration, the server will process httpd.conf (this -# file, specified by the -f command line option), srm.conf, and access.conf -# in that order. The latter two files are now distributed empty, as it is -# recommended that all directives be kept in a single file for simplicity. -# The commented-out values below are the built-in defaults. You can have the -# server ignore these files altogether by using "/dev/null" (for Unix) or -# "nul" (for Win32) for the arguments to the directives. -# -#ResourceConfig conf/srm.conf -#AccessConfig conf/access.conf - -# -# Timeout: The number of seconds before receives and sends time out. -# -Timeout 300 - -# -# KeepAlive: Whether or not to allow persistent connections (more than -# one request per connection). Set to "Off" to deactivate. -# -KeepAlive On - -# -# MaxKeepAliveRequests: The maximum number of requests to allow -# during a persistent connection. Set to 0 to allow an unlimited amount. -# We recommend you leave this number high, for maximum performance. -# -MaxKeepAliveRequests 100 - -# -# KeepAliveTimeout: Number of seconds to wait for the next request from the -# same client on the same connection. -# -KeepAliveTimeout 15 - -# -# Server-pool size regulation. Rather than making you guess how many -# server processes you need, Apache dynamically adapts to the load it -# sees --- that is, it tries to maintain enough server processes to -# handle the current load, plus a few spare servers to handle transient -# load spikes (e.g., multiple simultaneous requests from a single -# Netscape browser). -# -# It does this by periodically checking how many servers are waiting -# for a request. If there are fewer than MinSpareServers, it creates -# a new spare. If there are more than MaxSpareServers, some of the -# spares die off. The default values are probably OK for most sites. -# -MinSpareServers 1 -MaxSpareServers 2 - -# -# Number of servers to start initially --- should be a reasonable ballpark -# figure. -# -StartServers 1 - -# -# Limit on total number of servers running, i.e., limit on the number -# of clients who can simultaneously connect --- if this limit is ever -# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW. -# It is intended mainly as a brake to keep a runaway server from taking -# the system with it as it spirals down... -# -MaxClients 150 - -# -# MaxRequestsPerChild: the number of requests each child process is -# allowed to process before the child dies. The child will exit so -# as to avoid problems after prolonged use when Apache (and maybe the -# libraries it uses) leak memory or other resources. On most systems, this -# isn't really needed, but a few (such as Solaris) do have notable leaks -# in the libraries. For these platforms, set to something like 10000 -# or so; a setting of 0 means unlimited. -# -# NOTE: This value does not include keepalive requests after the initial -# request per connection. For example, if a child process handles -# an initial request and 10 subsequent "keptalive" requests, it -# would only count as 1 request towards this limit. -# -MaxRequestsPerChild 10 - -# -# Dynamic Shared Object (DSO) Support -# -# To be able to use the functionality of a module which was built as a DSO you -# have to place corresponding `LoadModule' lines at this location so the -# directives contained in it are actually available _before_ they are used. -# Please read the file http://httpd.apache.org/docs/dso.html for more -# details about the DSO mechanism and run `httpd -l' for the list of already -# built-in (statically linked and thus always available) modules in your httpd -# binary. -# -# Note: The order in which modules are loaded is important. Don't change -# the order below without expert advice. -# -LoadModule access_module libexec/mod_access.so -LoadModule alias_module libexec/mod_alias.so -LoadModule auth_module libexec/mod_auth.so -LoadModule mime_module libexec/mod_mime.so -LoadModule mime_magic_module libexec/mod_mime_magic.so -LoadModule ipp_module libexec/mod_ipp.so - -# Reconstruction of the complete module list from all available modules -# (static and shared ones) to achieve correct module execution order. -# [WHENEVER YOU CHANGE THE LOADMODULE SECTION ABOVE UPDATE THIS, TOO] -ClearModuleList -AddModule mod_access.c -AddModule mod_alias.c -AddModule mod_auth.c -AddModule mod_mime.c -AddModule mod_mime_magic.c -AddModule mod_ipp.c -AddModule mod_so.c - -### Section 2: 'Main' server configuration -# -# The directives in this section set up the values used by the 'main' -# server, which responds to any requests that aren't handled by a -# <VirtualHost> definition. These values also provide defaults for -# any <VirtualHost> containers you may define later in the file. -# -# All of these directives may appear inside <VirtualHost> containers, -# in which case these default settings will be overridden for the -# virtual host being defined. -# - -# -# If your ServerType directive (set earlier in the 'Global Environment' -# section) is set to "inetd", the next few directives don't have any -# effect since their settings are defined by the inetd configuration. -# Skip ahead to the ServerAdmin directive. -# - -# -# Port: The port to which the standalone server listens. For -# ports < 1023, you will need httpd to be run as root initially. -# -Port 631 - -# -# If you wish httpd to run as a different user or group, you must run -# httpd as root initially and it will switch. -# -# User/Group: The name (or #number) of the user/group to run httpd as. -# . On SCO (ODT 3) use "User nouser" and "Group nogroup". -# . On HPUX you may not be able to use shared memory as nobody, and the -# suggested workaround is to create a user www and use that user. -# NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET) -# when the value of (unsigned)Group is above 60000; -# don't use Group nobody on these systems! -# -User lp -Group lp - -# -# ServerAdmin: Your address, where problems with the server should be -# e-mailed. This address appears on some server-generated pages, such -# as error documents. -# -ServerAdmin lp@localhost - -# -# ServerName allows you to set a host name which is sent back to clients for -# your server if it's different than the one the program would get (i.e., use -# "www" instead of the host's real name). -# -# Note: You cannot just invent host names and hope they work. The name you -# define here must be a valid DNS name for your host. If you don't understand -# this, ask your network administrator. -# If your host doesn't have a registered DNS name, enter its IP address here. -# You will have to access it by its address (e.g., http://123.45.67.89/) -# anyway, and this will make redirections work in a sensible way. -# -# 127.0.0.1 is the TCP/IP local loop-back address, often named localhost. Your -# machine always knows itself by this address. If you use Apache strictly for -# local testing and development, you may use 127.0.0.1 as the server name. -# -#Servername printserver.some_company.com - -DefaultType application/ipp - -ErrorLog /var/lp/logs/ipp-errors -LogLevel warn - -DocumentRoot /var/lp/ipp-listener - -# Allow passing PPD files from this service as well -Alias /etc/lp/ppd/ /etc/lp/ppd/ -<Directory /etc/lp/ppd> - SetHandler send-as-is - <LimitExcept GET> - Deny from all - </LimitExcept> -</Directory> - -# mod_ipp specific configuration -<IfModule mod_ipp.c> - - <Location /> - # ipp-conformance automatic # default - # ipp-default-user nobody - ipp-default-service lpsched - # - # By default, only turn on operations that are not - # likely to cause real problems when the user can't - # be trusted. - # - ipp-operation all off - ipp-operation print-job on - ipp-operation validate-job on - ipp-operation create-job on - ipp-operation get-jobs on - ipp-operation get-printer-attributes on - ipp-operation send-document on - ipp-operation cancel-job on - ipp-operation get-job-attributes on - ipp-operation cups-get-default on - ipp-operation cups-get-printers on - ipp-operation cups-get-classes on - ipp-operation cups-move-job on - - # redirect non-IPP requests - ErrorDocument 404 /index.html - </Location> - - <Location /admin> - # ipp-conformance automatic # default - # ipp-default-user nobody - ipp-default-service lpsched - - ipp-operation all on - - AuthType Basic - AuthName "IPP Server" - AuthUserFile /etc/ipp-users - Require valid-user - - # redirect non-IPP requests - ErrorDocument 404 /index.html - </Location> -</IfModule> - diff --git a/usr/src/lib/print/mod_ipp/index.html b/usr/src/lib/print/mod_ipp/index.html deleted file mode 100644 index 15f680c666..0000000000 --- a/usr/src/lib/print/mod_ipp/index.html +++ /dev/null @@ -1,44 +0,0 @@ -<!-- - - CDDL HEADER START - - The contents of this file are subject to the terms of the - Common Development and Distribution License (the "License"). - You may not use this file except in compliance with the License. - - You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - or http://www.opensolaris.org/os/licensing. - See the License for the specific language governing permissions - and limitations under the License. - - When distributing Covered Code, include this CDDL HEADER in each - file and include the License file at usr/src/OPENSOLARIS.LICENSE. - If applicable, add the following below this CDDL HEADER, with the - fields enclosed by brackets "[]" replaced with your own identifying - information: Portions Copyright [yyyy] [name of copyright owner] - - CDDL HEADER END - - - Copyright 2006 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. - - ident "%Z%%M% %I% %E% SMI" ---> -<html> -<body> -The Internet Print Protocol (IPP) requires that all protocol requests be -encapsulated in HTTP and that all HTTP protocol requests be POST requests with -a Content-Type of "application/ipp". Since your request did not meet this -criteria, it has been ignored by the IPP listener. You will be redirected to -the -<a href=http://docs.sun.com/db?q=%22Internet+Print+Protocol%22&p=prod%2Fsolaris> -<b>Solaris®</b> AnswerBook -</a> -so that you can learn more about the Internet Print Protocol Listener. -<p> -If you would like more information about the Internet Print Protocol itself, -please visit <a href=http://www.pwg.org/ipp>http://www.pwg.org/ipp/</a>. -</body> -</html> -<meta HTTP-EQUIV=REFRESH CONTENT=10;URL=http://docs.sun.com/db?q=%22Internet+Print+Protocol%22&p=prod%2Fsolaris> diff --git a/usr/src/lib/print/mod_ipp/ipp-listener.xml b/usr/src/lib/print/mod_ipp/ipp-listener.xml deleted file mode 100644 index 686646a78c..0000000000 --- a/usr/src/lib/print/mod_ipp/ipp-listener.xml +++ /dev/null @@ -1,84 +0,0 @@ -<?xml version="1.0"?> -<!-- -CDDL HEADER START - -The contents of this file are subject to the terms of the -Common Development and Distribution License (the "License"). -You may not use this file except in compliance with the License. - -You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -or http://www.opensolaris.org/os/licensing. -See the License for the specific language governing permissions -and limitations under the License. - -When distributing Covered Code, include this CDDL HEADER in each -file and include the License file at usr/src/OPENSOLARIS.LICENSE. -If applicable, add the following below this CDDL HEADER, with the -fields enclosed by brackets "[]" replaced with your own identifying -information: Portions Copyright [yyyy] [name of copyright owner] - -CDDL HEADER END ---> -<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> -<!-- - Copyright 2009 Sun Microsystems, Inc. All rights reserved. - Use is subject to license terms. ---> - -<service_bundle type='manifest' name='SUNWipplr:ipp-listener'> - -<service - name='application/print/ipp-listener' - type='service' - version='1'> - - <create_default_instance enabled='false' /> - - <dependency name='print-service' - grouping='require_any' - restart_on='refresh' - type='service'> - <service_fmri value='svc:/application/print/server' /> - </dependency> - - <exec_method - type='method' - name='start' - exec='/usr/apache/bin/httpd -f /etc/apache/httpd-standalone-ipp.conf' - timeout_seconds='10' /> - - <exec_method - type='method' - name='stop' - exec='/bin/pkill -f httpd-standalone-ipp.conf' - timeout_seconds='5' /> - - <property_group name='general' type='framework'> - <!-- to start/stop IPP listening service--> - <propval name='action_authorization' type='astring' - value='solaris.print.admin' /> - <propval name='value_authorization' type='astring' - value='solaris.print.admin' /> - </property_group> - - <property_group name='firewall_context' type='com.sun,fw_definition'> - <propval name='ipf_method' type='astring' - value='/lib/svc/method/print-svc ipfilter svc:/application/print/server:default' /> - </property_group> - - <stability value='Unstable' /> - - <template> - <common_name> - <loctext xml:lang='C'> - Internet Print Protocol Listening Service - </loctext> - </common_name> - <documentation> - <manpage title='mod_ipp' section='4' - manpath='/usr/share/man' /> - </documentation> - </template> -</service> - -</service_bundle> diff --git a/usr/src/lib/print/mod_ipp/mod_ipp.c b/usr/src/lib/print/mod_ipp/mod_ipp.c deleted file mode 100644 index 2d9ece2287..0000000000 --- a/usr/src/lib/print/mod_ipp/mod_ipp.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - * - */ - -/* $Id: mod_ipp.c 149 2006-04-25 16:55:01Z njacobs $ */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Internet Printing Protocol (IPP) module for Apache. - */ - -#include "ap_config.h" - -#include <stdio.h> -#include <time.h> -#include <sys/time.h> -#include <values.h> -#include <libintl.h> -#include <alloca.h> - -#include "httpd.h" -#include "http_config.h" -#include "http_core.h" -#include "http_protocol.h" -#include "http_log.h" -#include "http_main.h" -#include "papi.h" -#ifndef APACHE_RELEASE /* appears to only exist in Apache 1.X */ -#define APACHE2 -#include "apr_compat.h" -#endif - -#include <papi.h> -#include <ipp-listener.h> - -#ifndef APACHE2 -module MODULE_VAR_EXPORT ipp_module; -#else -module AP_MODULE_DECLARE_DATA ipp_module; -#endif - -#ifndef AP_INIT_TAKE1 /* Apache 2.X has this, but 1.3.X does not */ -#define AP_INIT_NO_ARGS(directive, action, arg, where, mesg) \ - { directive, action, arg, where, NO_ARGS, mesg } -#define AP_INIT_TAKE1(directive, action, arg, where, mesg) \ - { directive, action, arg, where, TAKE1, mesg } -#define AP_INIT_TAKE2(directive, action, arg, where, mesg) \ - { directive, action, arg, where, TAKE2, mesg } -#endif - -typedef struct { - int conformance; - char *default_user; - char *default_svc; - papi_attribute_t **operations; -} IPPListenerConfig; - -#ifdef DEBUG -void -dump_buffer(FILE *fp, char *tag, char *buffer, int bytes) -{ - int i, j, ch; - - fprintf(fp, "%s %d(0x%x) bytes\n", (tag ? tag : ""), bytes, bytes); - for (i = 0; i < bytes; i += 16) { - fprintf(fp, "%s ", (tag ? tag : "")); - - for (j = 0; j < 16 && (i + j) < bytes; j ++) - fprintf(fp, " %02X", buffer[i + j] & 255); - - while (j < 16) { - fprintf(fp, " "); - j++; - } - - fprintf(fp, " "); - for (j = 0; j < 16 && (i + j) < bytes; j ++) { - ch = buffer[i + j] & 255; - if (ch < ' ' || ch == 127) - ch = '.'; - putc(ch, fp); - } - putc('\n', fp); - } - fflush(fp); -} -#endif - -static ssize_t -read_data(void *fd, void *buf, size_t siz) -{ - ssize_t len_read; - request_rec *ap_r = (request_rec *)fd; - - len_read = ap_get_client_block(ap_r, buf, siz); -#ifndef APACHE2 - ap_reset_timeout(ap_r); -#endif - -#ifdef DEBUG - fprintf(stderr, "read_data(0x%8.8x, 0x%8.8x, %d): %d", - fd, buf, siz, len_read); - if (len_read < 0) - fprintf(stderr, ": %s", strerror(errno)); - putc('\n', stderr); - dump_buffer(stderr, "read_data:", buf, len_read); -#endif - - return (len_read); -} - -static ssize_t -write_data(void *fd, void *buf, size_t siz) -{ - ssize_t len_written; - request_rec *ap_r = (request_rec *)fd; - -#ifndef APACHE2 - ap_reset_timeout(ap_r); -#endif -#ifdef DEBUG - dump_buffer(stderr, "write_data:", buf, siz); -#endif - len_written = ap_rwrite(buf, siz, ap_r); - - return (len_written); -} - -static void -discard_data(request_rec *r) -{ -#ifdef APACHE2 - (void) ap_discard_request_body(r); -#else - /* - * This is taken from ap_discard_request_body(). The reason we can't - * just use it in Apache 1.3 is that it does various timeout things we - * don't want it to do. Apache 2.0 doesn't do that, so we can safely - * use the normal function. - */ - if (r->read_chunked || r->remaining > 0) { - char dumpbuf[HUGE_STRING_LEN]; - int i; - - do { - i = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN); -#ifdef DEBUG - dump_buffer(stderr, "discarded", dumpbuf, i); -#endif - } while (i > 0); - } -#endif -} - -void _log_rerror(const char *file, int line, int level, request_rec *r, - const char *fmt, ...) -{ - va_list args; - size_t size; - char *message = alloca(BUFSIZ); - - va_start(args, fmt); - /* - * fill in the message. If the buffer is too small, allocate - * one that is large enough and fill it in. - */ - if ((size = vsnprintf(message, BUFSIZ, fmt, args)) >= BUFSIZ) - if ((message = alloca(size)) != NULL) - vsnprintf(message, size, fmt, args); - va_end(args); - -#ifdef APACHE2 - ap_log_rerror(file, line, level, NULL, r, message); -#else - ap_log_rerror(file, line, level, r, message); -#endif -} - -static int -ipp_handler(request_rec *r) -{ - papi_attribute_t **request = NULL, **response = NULL; - IPPListenerConfig *config; - papi_status_t status; - int ret; - - /* Really, IPP is all POST requests */ - if (r->method_number != M_POST) - return (DECLINED); - -#ifndef APACHE2 - /* - * An IPP request must have a MIME type of "application/ipp" - * (RFC-2910, Section 4, page 19). If it doesn't match this - * MIME type, we should decline the request and let someone else - * try and handle it. - */ - if (r->headers_in != NULL) { - char *mime_type = (char *)ap_table_get(r->headers_in, - "Content-Type"); - - if ((mime_type == NULL) || - (strcasecmp(mime_type, "application/ipp") != 0)) - return (DECLINED); - } -#endif - /* CHUNKED_DECHUNK might not work right for IPP? */ - if ((ret = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK) - return (ret); - - if (!ap_should_client_block(r)) - return (HTTP_INTERNAL_SERVER_ERROR); - -#ifndef APACHE2 - ap_soft_timeout("ipp_module: read/reply request ", r); -#endif - /* read the IPP request off the network */ - status = ipp_read_message(read_data, r, &request, IPP_TYPE_REQUEST); - - if (status != PAPI_OK) - _log_rerror(APLOG_MARK, APLOG_ERR, r, - "read failed: %s\n", papiStatusString(status)); -#ifdef DEBUG - papiAttributeListPrint(stderr, request, "request (%d) ", getpid()); -#endif - - (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, - "originating-host", (char *) -#ifdef APACHE2 - ap_get_remote_host - (r->connection, r->per_dir_config, REMOTE_NAME, NULL)); -#else - ap_get_remote_host - (r->connection, r->per_dir_config, REMOTE_NAME)); -#endif - - (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL, - "uri-port", ap_get_server_port(r)); - if (r->headers_in != NULL) { - char *host = (char *)ap_table_get(r->headers_in, "Host"); - - if ((host == NULL) || (host[0] == '\0')) - host = (char *)ap_get_server_name(r); - - (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, - "uri-host", host); - } - (void) papiAttributeListAddString(&request, PAPI_ATTR_EXCL, - "uri-path", r->uri); - - config = ap_get_module_config(r->per_dir_config, &ipp_module); - if (config != NULL) { - (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL, - "conformance", config->conformance); - (void) papiAttributeListAddCollection(&request, PAPI_ATTR_EXCL, - "operations", config->operations); - if (config->default_user != NULL) - (void) papiAttributeListAddString(&request, - PAPI_ATTR_EXCL, "default-user", - config->default_user); - if (config->default_svc != NULL) - (void) papiAttributeListAddString(&request, - PAPI_ATTR_EXCL, "default-service", - config->default_svc); - } - - /* - * For Trusted Solaris, pass the fd number of the socket connection - * to the backend so the it can be forwarded to the backend print - * service to retrieve the sensativity label off of a multi-level - * port. - */ - (void) papiAttributeListAddInteger(&request, PAPI_ATTR_EXCL, - "peer-socket", ap_bfileno(r->connection->client, B_RD)); - - /* process the request */ - status = ipp_process_request(request, &response, read_data, r); - if (status != PAPI_OK) { - errno = 0; - _log_rerror(APLOG_MARK, APLOG_ERR, r, - "request failed: %s\n", papiStatusString(status)); - discard_data(r); - } -#ifdef DEBUG - fprintf(stderr, "processing result: %s\n", papiStatusString(status)); - papiAttributeListPrint(stderr, response, "response (%d) ", getpid()); -#endif - - /* - * If the client is using chunking and we have not yet received the - * final "0" sized chunk, we need to discard any data that may - * remain in the post request. - */ - if ((r->read_chunked != 0) && - (ap_table_get(r->headers_in, "Content-Length") == NULL)) - discard_data(r); - - /* write an IPP response back to the network */ - r->content_type = "application/ipp"; - -#ifndef APACHE2 - ap_send_http_header(r); -#endif - - status = ipp_write_message(write_data, r, response); - if (status != PAPI_OK) - _log_rerror(APLOG_MARK, APLOG_ERR, r, - "write failed: %s\n", papiStatusString(status)); -#ifdef DEBUG - fprintf(stderr, "write result: %s\n", papiStatusString(status)); - fflush(stderr); -#endif - - papiAttributeListFree(request); - papiAttributeListFree(response); - -#ifndef APACHE2 - ap_kill_timeout(r); - if (ap_rflush(r) < 0) - _log_rerror(APLOG_MARK, APLOG_ERR, r, - "flush failed, response may not have been sent"); -#endif - - return (OK); -} - - -/*ARGSUSED1*/ -static void * -create_ipp_dir_config( -#ifndef APACHE2 - pool *p, -#else - apr_pool_t *p, -#endif - char *dirspec) -{ - IPPListenerConfig *config = -#ifndef APACHE2 - ap_pcalloc(p, sizeof (*config)); -#else - apr_pcalloc(p, sizeof (*config)); -#endif - - if (config != NULL) { - (void) memset(config, 0, sizeof (*config)); - config->conformance = IPP_PARSE_CONFORMANCE_RASH; - config->default_user = NULL; - config->default_svc = NULL; - (void) ipp_configure_operation(&config->operations, "required", - "enable"); - } - - return (config); -} - -/*ARGSUSED0*/ -static const char * -ipp_conformance(cmd_parms *cmd, void *cfg, const char *arg) -{ - IPPListenerConfig *config = (IPPListenerConfig *)cfg; - - if (strncasecmp(arg, "automatic", 4) == 0) { - config->conformance = IPP_PARSE_CONFORMANCE_RASH; - } else if (strcasecmp(arg, "1.0") == 0) { - config->conformance = IPP_PARSE_CONFORMANCE_LOOSE; - } else if (strcasecmp(arg, "1.1") == 0) { - config->conformance = IPP_PARSE_CONFORMANCE_STRICT; - } else { - return ("unknown conformance, try (automatic/1.0/1.1)"); - } - - return (NULL); -} - -/*ARGSUSED0*/ -static const char * -ipp_operation(cmd_parms *cmd, void *cfg, char *op, char *toggle) -{ - IPPListenerConfig *config = (IPPListenerConfig *)cfg; - papi_status_t status; - - status = ipp_configure_operation(&config->operations, op, toggle); - switch (status) { - case PAPI_OK: - return (NULL); - case PAPI_BAD_ARGUMENT: - return (gettext("internal error (invalid argument)")); - default: - return (papiStatusString(status)); - } - - /* NOTREACHED */ - /* return (gettext("contact your software vendor")); */ -} - -static const char * -ipp_default_user(cmd_parms *cmd, void *cfg, const char *arg) -{ - IPPListenerConfig *config = (IPPListenerConfig *)cfg; - - config->default_user = (char *)arg; - - return (NULL); -} - -static const char * -ipp_default_svc(cmd_parms *cmd, void *cfg, const char *arg) -{ - IPPListenerConfig *config = (IPPListenerConfig *)cfg; - - config->default_svc = (char *)arg; - - return (NULL); -} - -#ifdef DEBUG -/*ARGSUSED0*/ -static const char * -ipp_module_hang(cmd_parms *cmd, void *cfg) -{ - static int i = 1; - - /* wait so we can attach a debugger, assign i = 0, and step through */ - while (i); - - return (NULL); -} -#endif /* DEBUG */ - -static const command_rec ipp_cmds[] = -{ - AP_INIT_TAKE1("ipp-conformance", ipp_conformance, NULL, ACCESS_CONF, - "IPP protocol conformance (loose/strict)"), - AP_INIT_TAKE2("ipp-operation", ipp_operation, NULL, ACCESS_CONF, - "IPP protocol operations to enable/disable)"), - AP_INIT_TAKE1("ipp-default-user", ipp_default_user, NULL, ACCESS_CONF, - "default user for various operations"), - AP_INIT_TAKE1("ipp-default-service", ipp_default_svc, NULL, ACCESS_CONF, - "default service for various operations"), -#ifdef DEBUG - AP_INIT_NO_ARGS("ipp-module-hang", ipp_module_hang, NULL, ACCESS_CONF, - "hang the module until we can attach a debugger (no args)"), -#endif - { NULL } -}; - -#ifdef APACHE2 -/*ARGSUSED0*/ -static const char * -ipp_method(const request_rec *r) -{ - return ("ipp"); -} - -/*ARGSUSED0*/ -static unsigned short -ipp_port(const request_rec *r) -{ - return (631); -} - -/* Dispatch list for API hooks */ -/*ARGSUSED0*/ -static void -ipp_register_hooks(apr_pool_t *p) -{ - static const char * const modules[] = { "mod_dir.c", NULL }; - - /* Need to make sure we don't get directory listings by accident */ - ap_hook_handler(ipp_handler, NULL, modules, APR_HOOK_MIDDLE); - ap_hook_default_port(ipp_port, NULL, NULL, APR_HOOK_MIDDLE); - ap_hook_http_method(ipp_method, NULL, NULL, APR_HOOK_MIDDLE); -} - -module AP_MODULE_DECLARE_DATA ipp_module = { - STANDARD20_MODULE_STUFF, - create_ipp_dir_config, /* create per-dir config */ - NULL, /* merge per-dir config */ - NULL, /* create per-server config */ - NULL, /* merge per-server config */ - ipp_cmds, /* table of config commands */ - ipp_register_hooks /* register hooks */ -}; - -#else /* Apache 1.X */ - -/* Dispatch list of content handlers */ -static const handler_rec ipp_handlers[] = { - /* - * This handler association causes all IPP request with the - * correct MIME type to call the protocol handler. - */ - { "application/ipp", ipp_handler }, - /* - * This hander association is causes everything to go through the IPP - * protocol request handler. This is necessary because client POST - * request may be for something outside of the normal printer-uri - * space. - */ - { "*/*", ipp_handler }, - - { NULL, NULL } -}; - - -module MODULE_VAR_EXPORT ipp_module = { - STANDARD_MODULE_STUFF, - NULL, /* module initializer */ - create_ipp_dir_config, /* create per-dir config structures */ - NULL, /* merge per-dir config structures */ - NULL, /* create per-server config structures */ - NULL, /* merge per-server config structures */ - ipp_cmds, /* table of config file commands */ - ipp_handlers, /* [#8] MIME-typed-dispatched handlers */ - NULL, /* [#1] URI to filename translation */ - NULL, /* [#4] validate user id from request */ - NULL, /* [#5] check if the user is ok _here_ */ - NULL, /* [#3] check access by host address */ - NULL, /* [#6] determine MIME type */ - NULL, /* [#7] pre-run fixups */ - NULL, /* [#9] log a transaction */ - NULL, /* [#2] header parser */ - NULL, /* child_init */ - NULL, /* child_exit */ - NULL /* [#0] post read-request */ -}; -#endif diff --git a/usr/src/lib/pylibbe/Makefile.com b/usr/src/lib/pylibbe/Makefile.com index aa26dec043..9f964ce417 100644 --- a/usr/src/lib/pylibbe/Makefile.com +++ b/usr/src/lib/pylibbe/Makefile.com @@ -44,7 +44,8 @@ C99MODE= $(C99_ENABLE) LIBS = $(DYNLIB) LDLIBS += -lbe -lnvpair -lc CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I/usr/include/python2.6 -D_FILE_OFFSET_BITS=64 -I../../libbe/common +CPPFLAGS += -I$(ADJUNCT_PROTO)/usr/include/python2.6 \ + -D_FILE_OFFSET_BITS=64 -I../../libbe/common .KEEP_STATE: diff --git a/usr/src/lib/pysolaris/Makefile.com b/usr/src/lib/pysolaris/Makefile.com index a27492771a..0e5b385bd8 100644 --- a/usr/src/lib/pysolaris/Makefile.com +++ b/usr/src/lib/pysolaris/Makefile.com @@ -44,6 +44,7 @@ C99LMODE= -Xc99=%all LIBS = $(DYNLIB) LDLIBS += -lc -lsec -lidmap -lpython2.6 CFLAGS += $(CCVERBOSE) +CPPFLAGS += -I$(ADJUNCT_PROTO)/usr/include/python2.6 CERRWARN += -_gcc=-Wno-unused-variable CPPFLAGS += -I/usr/include/python2.6 diff --git a/usr/src/lib/pyzfs/Makefile.com b/usr/src/lib/pyzfs/Makefile.com index 29d0407cae..a565ed8059 100644 --- a/usr/src/lib/pyzfs/Makefile.com +++ b/usr/src/lib/pyzfs/Makefile.com @@ -47,6 +47,7 @@ C99LMODE= -Xc99=%all LIBS = $(DYNLIB) LDLIBS += -lc -lnvpair -lpython2.6 -lzfs CFLAGS += $(CCVERBOSE) +CPPFLAGS += -I$(ADJUNCT_PROTO)/usr/include/python2.6 CERRWARN += -_gcc=-Wno-unused-variable CPPFLAGS += -I/usr/include/python2.6 CPPFLAGS += -I../../../uts/common/fs/zfs |