summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2015-11-18 23:45:09 +0000
committerngie <ngie@FreeBSD.org>2015-11-18 23:45:09 +0000
commitb923a91e2c985b47c61617b8287f43bce6c02e29 (patch)
treed6ee7d819b417a1d2f90dc1c053d1bcba4b359f7
parent02e252b417a4084cc0dff45952250e8825107b57 (diff)
parenta4cd1c7d39390fde357dda05b99473229331d9fc (diff)
downloadFreeBSD-src-b923a91e2c985b47c61617b8287f43bce6c02e29.zip
FreeBSD-src-b923a91e2c985b47c61617b8287f43bce6c02e29.tar.gz
MFhead @ r291038
-rw-r--r--MAINTAINERS8
-rw-r--r--Makefile.inc14
-rw-r--r--ObsoleteFiles.inc35
-rw-r--r--UPDATING9
-rw-r--r--bin/sh/expand.c3
-rw-r--r--bin/sh/tests/parameters/positional8.031
-rw-r--r--crypto/openssl/doc/crypto/EVP_EncryptInit.pod4
-rw-r--r--crypto/openssl/doc/crypto/EVP_PKEY_CTX_ctrl.pod4
-rw-r--r--etc/Makefile2
-rw-r--r--etc/mtree/BSD.usr.dist14
-rw-r--r--include/Makefile2
-rw-r--r--lib/libcrypt/tests/Makefile14
-rw-r--r--lib/libpmc/pmc.h17
-rw-r--r--sbin/Makefile80
-rw-r--r--secure/lib/libcrypto/Makefile.inc6
-rw-r--r--secure/lib/libcrypto/Makefile.man3
-rw-r--r--secure/lib/libcrypto/man/EVP_EncryptInit.36
-rw-r--r--secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.34
-rw-r--r--secure/lib/libcrypto/man/SSLeay_version.3192
-rw-r--r--share/colldef/Makefile7
-rw-r--r--share/ctypedef/Makefile63
-rw-r--r--share/ctypedef/en_US.ISO8859-1.src (renamed from share/ctypedef/en_GB.ISO8859-15.src)0
-rw-r--r--share/locale-links/Makefile1
-rw-r--r--share/mk/dirdeps.mk17
-rw-r--r--share/mk/local.gendirdeps.mk1
-rw-r--r--share/mk/sys.mk5
-rw-r--r--share/monetdef/Makefile13
-rw-r--r--share/monetdef/en_ZA.ISO8859-15.src (renamed from share/monetdef/en_ZA.ISO8859-1.src)0
-rw-r--r--share/monetdef/fr_CA.ISO8859-15.src (renamed from share/monetdef/fr_CA.ISO8859-1.src)0
-rw-r--r--share/msgdef/Makefile7
-rw-r--r--share/numericdef/Makefile7
-rw-r--r--share/timedef/Makefile9
-rw-r--r--share/timedef/fr_CA.ISO8859-15.src (renamed from share/timedef/fr_CA.ISO8859-1.src)0
-rw-r--r--sys/arm/arm/busdma_machdep-v6.c35
-rw-r--r--sys/arm/arm/pl310.c2
-rw-r--r--sys/arm/include/pcb.h13
-rw-r--r--sys/arm/include/pl310.h1
-rw-r--r--sys/arm/samsung/exynos/exynos5_ehci.c2
-rw-r--r--sys/boot/common/loader.810
-rw-r--r--sys/conf/files.powerpc14
-rw-r--r--sys/conf/kern.pre.mk6
-rw-r--r--sys/conf/options1
-rw-r--r--sys/conf/options.powerpc1
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c50
-rw-r--r--sys/dev/isp/isp.c631
-rw-r--r--sys/dev/isp/isp_freebsd.c38
-rw-r--r--sys/dev/isp/isp_library.c72
-rw-r--r--sys/dev/isp/isp_library.h3
-rw-r--r--sys/dev/isp/isp_stds.h14
-rw-r--r--sys/dev/isp/isp_target.c48
-rw-r--r--sys/dev/isp/ispmbox.h24
-rw-r--r--sys/dev/isp/ispvar.h15
-rw-r--r--sys/dev/ntb/if_ntb/if_ntb.c91
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_hw.c109
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_hw.h6
-rw-r--r--sys/dev/re/if_re.c8
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c15
-rw-r--r--sys/dev/vmware/vmxnet3/if_vmx.c11
-rw-r--r--sys/dev/wpi/if_wpi.c8
-rw-r--r--sys/dev/xen/control/control.c4
-rw-r--r--sys/fs/nfsclient/nfs_clvfsops.c4
-rw-r--r--sys/geom/geom_dev.c27
-rw-r--r--sys/kern/imgact_elf.c7
-rw-r--r--sys/kern/kern_dump.c10
-rw-r--r--sys/mips/conf/AP14351
-rw-r--r--sys/mips/conf/AP143.hints105
-rw-r--r--sys/mips/conf/ONIONOMEGA53
-rw-r--r--sys/mips/conf/ONIONOMEGA.hints94
-rw-r--r--sys/mips/conf/QCA953X_BASE138
-rw-r--r--sys/mips/conf/QCA953X_BASE.hints75
-rw-r--r--sys/modules/tests/framework/Makefile1
-rw-r--r--sys/net/pfkeyv2.h2
-rw-r--r--sys/netipsec/ipsec.h1
-rw-r--r--sys/netipsec/key.c39
-rw-r--r--sys/netipsec/xform_esp.c8
-rw-r--r--sys/netpfil/ipfw/ip_fw_dynamic.c3
-rw-r--r--sys/netsmb/smb_conn.c4
-rw-r--r--sys/netsmb/smb_iod.c11
-rw-r--r--sys/opencrypto/xform.c2
-rw-r--r--sys/powerpc/aim/mmu_oea64.c6
-rw-r--r--sys/powerpc/aim/moea64_native.c24
-rw-r--r--sys/powerpc/include/bus.h5
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.c121
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.h39
-rw-r--r--sys/powerpc/ofw/ofw_machdep.c14
-rw-r--r--sys/powerpc/ofw/ofw_pci.c19
-rw-r--r--sys/powerpc/ofw/ofw_pcibus.c12
-rw-r--r--sys/powerpc/ofw/openpic_ofw.c6
-rw-r--r--sys/powerpc/powermac/cpcht.c4
-rw-r--r--sys/powerpc/powermac/kiic.c4
-rw-r--r--sys/powerpc/powermac/macgpio.c6
-rw-r--r--sys/powerpc/pseries/mmu_phyp.c4
-rw-r--r--sys/powerpc/pseries/phyp_console.c4
-rw-r--r--sys/powerpc/pseries/phyp_llan.c2
-rw-r--r--sys/powerpc/pseries/phyp_vscsi.c3
-rw-r--r--sys/powerpc/pseries/platform_chrp.c37
-rw-r--r--sys/powerpc/pseries/plpar_iommu.c13
-rw-r--r--sys/powerpc/pseries/rtas_pci.c2
-rw-r--r--sys/sparc64/include/dump.h8
-rw-r--r--sys/sparc64/sparc64/dump_machdep.c24
-rw-r--r--sys/sys/pmc.h17
-rw-r--r--sys/x86/x86/intr_machdep.c15
-rw-r--r--sys/x86/xen/hvm.c26
-rw-r--r--sys/x86/xen/xen_intr.c3
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc30
-rw-r--r--tools/install.sh2
-rw-r--r--tools/sched/schedgraph.py4
-rw-r--r--tools/tools/locale/etc/charmaps.xml6
-rwxr-xr-xtools/tools/shlib-compat/shlib-compat.py26
-rw-r--r--usr.bin/netstat/if.c2
-rw-r--r--usr.bin/xinstall/Makefile2
-rw-r--r--usr.sbin/Makefile349
-rw-r--r--usr.sbin/mpsutil/Makefile2
-rw-r--r--usr.sbin/mpsutil/mps_cmd.c58
-rw-r--r--usr.sbin/mpsutil/mps_flash.c237
-rw-r--r--usr.sbin/mpsutil/mpsutil.842
-rw-r--r--usr.sbin/mpsutil/mpsutil.h3
-rw-r--r--usr.sbin/pmcstat/pmcpl_gprof.c54
-rw-r--r--usr.sbin/pmcstat/pmcstat.89
-rw-r--r--usr.sbin/pmcstat/pmcstat.c32
-rw-r--r--usr.sbin/pmcstat/pmcstat.h1
-rw-r--r--usr.sbin/ypldap/Makefile20
-rw-r--r--usr.sbin/ypldap/aldap.c1273
-rw-r--r--usr.sbin/ypldap/aldap.h221
-rw-r--r--usr.sbin/ypldap/ber.c1270
-rw-r--r--usr.sbin/ypldap/ber.h129
-rw-r--r--usr.sbin/ypldap/entries.c149
-rw-r--r--usr.sbin/ypldap/ldapclient.c705
-rw-r--r--usr.sbin/ypldap/log.c162
-rw-r--r--usr.sbin/ypldap/parse.y838
-rw-r--r--usr.sbin/ypldap/yp.c652
-rw-r--r--usr.sbin/ypldap/ypldap.882
-rw-r--r--usr.sbin/ypldap/ypldap.c651
-rw-r--r--usr.sbin/ypldap/ypldap.conf.5167
-rw-r--r--usr.sbin/ypldap/ypldap.h222
-rw-r--r--usr.sbin/ypldap/ypldap_dns.c254
136 files changed, 9123 insertions, 1384 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 16cc5f1..b22accb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -59,7 +59,6 @@ contrib/llvm dim Pre-commit review preferred.
contrib/llvm/tools/lldb emaste Pre-commit review preferred.
atf freebsd-testing,jmmv,ngie Pre-commit review requested.
contrib/netbsd-tests freebsd-testing,ngie Pre-commit review requested.
-contrib/pf kp,glebius Pre-commit review recommended.
contrib/pjdfstest freebsd-testing,ngie,pjd Pre-commit review requested.
share/mk/*.test.mk freebsd-testing,ngie (same list as share/mk too) Pre-commit review requested.
tests freebsd-testing,ngie Pre-commit review requested.
@@ -69,7 +68,12 @@ sys/compat/linuxkpi hselasky If in doubt, ask.
sys/dev/e1000 erj Pre-commit phabricator review requested.
sys/dev/ixgbe erj Pre-commit phabricator review requested.
sys/dev/ixl erj Pre-commit phabricator review requested.
+sys/netinet/ip_carp.c glebius Pre-commit review recommended.
+sys/netpfil/pf kp,glebius Pre-commit review recommended.
usr.sbin/pkg pkg@ Please coordinate behavior or flag changes with pkg team.
+lpr gad Pre-commit review requested, particularly for
+ lpd/recvjob.c and lpd/printjob.c.
+nis(8), yp(8) araujo Pre-commit review requested.
---- OLD ----
libc/posix1e rwatson Pre-commit review requested.
POSIX.1e ACLs rwatson Pre-commit review requested.
@@ -100,8 +104,6 @@ etc/mail gshapiro Pre-commit review requested.
Keep in sync with -STABLE.
etc/sendmail gshapiro Pre-commit review requested.
Keep in sync with -STABLE.
-lpr gad Pre-commit review requested, particularly for
- lpd/recvjob.c and lpd/printjob.c.
nvi peter Try not to break it.
libz peter Try not to break it.
groff ru Recommends pre-commit review.
diff --git a/Makefile.inc1 b/Makefile.inc1
index d9f01be..cc48d20 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -1458,9 +1458,6 @@ ${_bt}-usr.bin/mandoc: ${_bt}-lib/libopenbsd ${_bt}-lib/libsqlite3
_makewhatis=usr.bin/makewhatis
.endif
-# Rebuild up-to-date libmd for xinstall
-${_bt}-usr.bin/xinstall: ${_bt}-lib/libmd
-
bootstrap-tools: .PHONY
# Please document (add comment) why something is in 'bootstrap-tools'.
@@ -1483,7 +1480,6 @@ bootstrap-tools: .PHONY
${_yacc} \
${_m4} \
${_lex} \
- lib/libmd \
usr.bin/xinstall \
${_gensnmptree} \
usr.sbin/config \
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index be5e9c7..4e69783 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -49,41 +49,6 @@ OLD_FILES+=usr/share/locale/zh_TW.UTF-8/zh_Hant_TW.UTF-8
# 20151107: String collation improvements
OLD_FILES+=usr/share/locale/UTF-8/LC_CTYPE
OLD_DIRS+=usr/share/locale/UTF-8
-OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_NUMERIC
-OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_MESSAGES
-OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_TIME
-OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_CTYPE
-OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_COLLATE
-OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_MONETARY
-OLD_DIRS+=usr/share/locale/en_CA.ISO8859-15
-OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_COLLATE
-OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_CTYPE
-OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_MESSAGES
-OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_TIME
-OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_NUMERIC
-OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_MONETARY
-OLD_DIRS+=usr/share/locale/en_AU.ISO8859-15
-OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_CTYPE
-OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_MESSAGES
-OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_COLLATE
-OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_TIME
-OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_MONETARY
-OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_NUMERIC
-OLD_DIRS+=usr/share/locale/en_US.ISO8859-15
-OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_MESSAGES
-OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_COLLATE
-OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_TIME
-OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_MONETARY
-OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_NUMERIC
-OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_CTYPE
-OLD_DIRS+=usr/share/locale/en_NZ.ISO8859-15
-OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_COLLATE
-OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_MESSAGES
-OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_CTYPE
-OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_TIME
-OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_NUMERIC
-OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_MONETARY
-OLD_DIRS+=usr/share/locale/fr_CA.ISO8859-15
OLD_FILES+=usr/share/locale/kk_KZ.PT154/LC_COLLATE
OLD_FILES+=usr/share/locale/kk_KZ.PT154/LC_CTYPE
OLD_FILES+=usr/share/locale/kk_KZ.PT154/LC_MESSAGES
diff --git a/UPDATING b/UPDATING
index 18ed81b..8c4ca72 100644
--- a/UPDATING
+++ b/UPDATING
@@ -39,6 +39,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
Databases administrators will need to reindex their databases given
collation results will be different.
+ Due to a bug in install(1) it is recommended to remove the ancient
+ locales before running make installworld.
+
+ rm -rf /usr/share/locale/*
+
20151030:
The OpenSSL has been upgraded to 1.0.2d. Any binaries requiring
libcrypto.so.7 or libssl.so.7 must be recompiled.
@@ -191,12 +196,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
like it always used to, and the difference will be irrelevant.
If you remove 'device random', you get *NO* kernel-processed
- entopy at all. This may be acceptable to folks building
+ entropy at all. This may be acceptable to folks building
embedded systems, but has complications. Carry on reading,
and it is assumed you know what you need.
*PLEASE* read random(4) and random(9) if you are in the
- habit of tweeking kernel configs, and/or if you are a member
+ habit of tweaking kernel configs, and/or if you are a member
of the embedded community, wanting specific and not-usual
behaviour from your security subsystems.
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index f7c6735..6217982 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -249,7 +249,8 @@ argstr(char *p, int flag)
case CTLQUOTEMARK:
lit_quoted = 1;
/* "$@" syntax adherence hack */
- if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
+ if (p[0] == CTLVAR && (p[1] & VSQUOTE) != 0 &&
+ p[2] == '@' && p[3] == '=')
break;
if ((flag & EXP_FULL) != 0)
USTPUTC(c, expdest);
diff --git a/bin/sh/tests/parameters/positional8.0 b/bin/sh/tests/parameters/positional8.0
new file mode 100644
index 0000000..4c4dbd5
--- /dev/null
+++ b/bin/sh/tests/parameters/positional8.0
@@ -0,0 +1,31 @@
+# $FreeBSD$
+
+failures=''
+ok=''
+
+testcase() {
+ code="$1"
+ expected="$2"
+ oIFS="$IFS"
+ eval "$code"
+ IFS='|'
+ result="$#|$*"
+ IFS="$oIFS"
+ if [ "x$result" = "x$expected" ]; then
+ ok=x$ok
+ else
+ failures=x$failures
+ echo "For $code, expected $expected actual $result"
+ fi
+}
+
+testcase 'shift $#; set -- ""$*' '1|'
+testcase 'shift $#; set -- $*""' '1|'
+testcase 'shift $#; set -- ""$@' '1|'
+testcase 'shift $#; set -- $@""' '1|'
+testcase 'shift $#; set -- """$*"' '1|'
+testcase 'shift $#; set -- "$*"""' '1|'
+testcase 'shift $#; set -- """$@"' '1|'
+testcase 'shift $#; set -- "$@"""' '1|'
+
+test "x$failures" = x
diff --git a/crypto/openssl/doc/crypto/EVP_EncryptInit.pod b/crypto/openssl/doc/crypto/EVP_EncryptInit.pod
index fb6036f..f02895c 100644
--- a/crypto/openssl/doc/crypto/EVP_EncryptInit.pod
+++ b/crypto/openssl/doc/crypto/EVP_EncryptInit.pod
@@ -20,7 +20,7 @@ EVP_CIPHER_CTX_set_padding, EVP_enc_null, EVP_des_cbc, EVP_des_ecb,
EVP_des_cfb, EVP_des_ofb, EVP_des_ede_cbc, EVP_des_ede, EVP_des_ede_ofb,
EVP_des_ede_cfb, EVP_des_ede3_cbc, EVP_des_ede3, EVP_des_ede3_ofb,
EVP_des_ede3_cfb, EVP_desx_cbc, EVP_rc4, EVP_rc4_40, EVP_idea_cbc,
-EVP_idea_ecb, EVP_idea_cfb, EVP_idea_ofb, EVP_idea_cbc, EVP_rc2_cbc,
+EVP_idea_ecb, EVP_idea_cfb, EVP_idea_ofb, EVP_rc2_cbc,
EVP_rc2_ecb, EVP_rc2_cfb, EVP_rc2_ofb, EVP_rc2_40_cbc, EVP_rc2_64_cbc,
EVP_bf_cbc, EVP_bf_ecb, EVP_bf_cfb, EVP_bf_ofb, EVP_cast5_cbc,
EVP_cast5_ecb, EVP_cast5_cfb, EVP_cast5_ofb, EVP_rc5_32_12_16_cbc,
@@ -315,7 +315,7 @@ RC4 stream cipher. This is a variable key length cipher with default key length
RC4 stream cipher with 40 bit key length. This is obsolete and new code should use EVP_rc4()
and the EVP_CIPHER_CTX_set_key_length() function.
-=item EVP_idea_cbc() EVP_idea_ecb(void), EVP_idea_cfb(void), EVP_idea_ofb(void), EVP_idea_cbc(void)
+=item EVP_idea_cbc() EVP_idea_ecb(void), EVP_idea_cfb(void), EVP_idea_ofb(void)
IDEA encryption algorithm in CBC, ECB, CFB and OFB modes respectively.
diff --git a/crypto/openssl/doc/crypto/EVP_PKEY_CTX_ctrl.pod b/crypto/openssl/doc/crypto/EVP_PKEY_CTX_ctrl.pod
index 44b5fdb..2367ae6 100644
--- a/crypto/openssl/doc/crypto/EVP_PKEY_CTX_ctrl.pod
+++ b/crypto/openssl/doc/crypto/EVP_PKEY_CTX_ctrl.pod
@@ -2,7 +2,7 @@
=head1 NAME
-EVP_PKEY_CTX_ctrl, EVP_PKEY_CTX_ctrl_str, EVP_PKEY_get_default_digest_nid,
+EVP_PKEY_CTX_ctrl, EVP_PKEY_CTX_ctrl_str,
EVP_PKEY_CTX_set_signature_md, EVP_PKEY_CTX_set_rsa_padding,
EVP_PKEY_CTX_set_rsa_pss_saltlen, EVP_PKEY_CTX_set_rsa_rsa_keygen_bits,
EVP_PKEY_CTX_set_rsa_keygen_pubexp, EVP_PKEY_CTX_set_dsa_paramgen_bits,
@@ -19,8 +19,6 @@ EVP_PKEY_CTX_set_ec_paramgen_curve_nid - algorithm specific control operations
int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value);
- int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid);
-
#include <openssl/rsa.h>
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
diff --git a/etc/Makefile b/etc/Makefile
index 4a4422d..ddb7769 100644
--- a/etc/Makefile
+++ b/etc/Makefile
@@ -337,10 +337,10 @@ MTREE_FILTER= sed -e 's,\([gu]\)name=,\1id=,g' \
-e 's,\(gid=\)[^ ]*$$,\1${_gid},'
.else
MTREE_FILTER= cat
-.endif
.if !defined(NO_FSCHG)
MTREE_FSCHG= -i
.endif
+.endif
MTREES= mtree/BSD.root.dist / \
mtree/BSD.var.dist /var \
diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist
index eb68221..3fced30 100644
--- a/etc/mtree/BSD.usr.dist
+++ b/etc/mtree/BSD.usr.dist
@@ -515,6 +515,8 @@
locale
af_ZA.ISO8859-1
..
+ af_ZA.ISO8859-15
+ ..
af_ZA.UTF-8
..
ar_AE.UTF-8
@@ -601,12 +603,16 @@
..
en_AU.ISO8859-1
..
+ en_AU.ISO8859-15
+ ..
en_AU.US-ASCII
..
en_AU.UTF-8
..
en_CA.ISO8859-1
..
+ en_CA.ISO8859-15
+ ..
en_CA.US-ASCII
..
en_CA.UTF-8
@@ -631,6 +637,8 @@
..
en_NZ.ISO8859-1
..
+ en_NZ.ISO8859-15
+ ..
en_NZ.US-ASCII
..
en_NZ.UTF-8
@@ -643,12 +651,16 @@
..
en_US.ISO8859-1
..
+ en_US.ISO8859-15
+ ..
en_US.US-ASCII
..
en_US.UTF-8
..
en_ZA.ISO8859-1
..
+ en_ZA.ISO8859-15
+ ..
en_ZA.US-ASCII
..
en_ZA.UTF-8
@@ -695,6 +707,8 @@
..
fr_CA.ISO8859-1
..
+ fr_CA.ISO8859-15
+ ..
fr_CA.UTF-8
..
fr_CH.ISO8859-1
diff --git a/include/Makefile b/include/Makefile
index 61bfbc6..d59900f 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -376,7 +376,7 @@ symlinks:
@touch ${.OBJDIR}/${.TARGET}
.endif
-.if ${MACHINE} == "host"
+.if ${MACHINE} == "host" && !defined(_SKIP_BUILD)
# we're here because we are building a sysroot...
# we need MACHINE et al set correctly
HOST_MACHINE!= uname -m
diff --git a/lib/libcrypt/tests/Makefile b/lib/libcrypt/tests/Makefile
index 15798b2..7be335f 100644
--- a/lib/libcrypt/tests/Makefile
+++ b/lib/libcrypt/tests/Makefile
@@ -1,12 +1,12 @@
# $FreeBSD$
-ATF_TESTS_C+= crypt_tests
-
-NETBSD_ATF_TESTS_C+= crypt_test
-
-CFLAGS+= -I${.CURDIR:H}
-LIBADD= crypt
-
+#ATF_TESTS_C+= crypt_tests
+#
+#NETBSD_ATF_TESTS_C+= crypt_test
+#
+#CFLAGS+= -I${.CURDIR:H}
+#LIBADD= crypt
+#
.include <netbsd-tests.test.mk>
.include <bsd.test.mk>
diff --git a/lib/libpmc/pmc.h b/lib/libpmc/pmc.h
index 81672d2..f237285 100644
--- a/lib/libpmc/pmc.h
+++ b/lib/libpmc/pmc.h
@@ -37,14 +37,15 @@
* Driver statistics.
*/
struct pmc_driverstats {
- int pm_intr_ignored; /* #interrupts ignored */
- int pm_intr_processed; /* #interrupts processed */
- int pm_intr_bufferfull; /* #interrupts with ENOSPC */
- int pm_syscalls; /* #syscalls */
- int pm_syscall_errors; /* #syscalls with errors */
- int pm_buffer_requests; /* #buffer requests */
- int pm_buffer_requests_failed; /* #failed buffer requests */
- int pm_log_sweeps; /* #sample buffer processing passes */
+ unsigned int pm_intr_ignored; /* #interrupts ignored */
+ unsigned int pm_intr_processed; /* #interrupts processed */
+ unsigned int pm_intr_bufferfull; /* #interrupts with ENOSPC */
+ unsigned int pm_syscalls; /* #syscalls */
+ unsigned int pm_syscall_errors; /* #syscalls with errors */
+ unsigned int pm_buffer_requests; /* #buffer requests */
+ unsigned int pm_buffer_requests_failed; /* #failed buffer requests */
+ unsigned int pm_log_sweeps; /* #sample buffer processing
+ passes */
};
/*
diff --git a/sbin/Makefile b/sbin/Makefile
index c828b21..3b17e10 100644
--- a/sbin/Makefile
+++ b/sbin/Makefile
@@ -70,66 +70,26 @@ SUBDIR=adjkerntz \
tunefs \
umount
-.if ${MK_ATM} != "no"
-SUBDIR+= atm
-.endif
-
-.if ${MK_CASPER} != "no"
-SUBDIR+= casperd
-.endif
-
-.if ${MK_CCD} != "no"
-SUBDIR+= ccdconfig
-.endif
-
-.if ${MK_CXX} != "no"
-SUBDIR+= devd
-.endif
-
-.if ${MK_HAST} != "no"
-SUBDIR+= hastctl
-SUBDIR+= hastd
-.endif
-
-.if ${MK_INET6} != "no"
-SUBDIR+= ping6
-SUBDIR+= rtsol
-.endif
-
-.if ${MK_IPFILTER} != "no"
-SUBDIR+= ipf
-.endif
-
-.if ${MK_IPFW} != "no"
-SUBDIR+= ipfw
-SUBDIR+= natd
-.endif
-
-.if ${MK_ISCSI} != "no"
-SUBDIR+= iscontrol
-.endif
-
-.if ${MK_NAND} != "no"
-SUBDIR+= nandfs
-SUBDIR+= newfs_nandfs
-.endif
-
-.if ${MK_PF} != "no"
-SUBDIR+= pfctl
-SUBDIR+= pflogd
-.endif
-
-.if ${MK_QUOTAS} != "no"
-SUBDIR+= quotacheck
-.endif
-
-.if ${MK_ROUTED} != "no"
-SUBDIR+= routed
-.endif
-
-.if ${MK_TESTS} != "no"
-SUBDIR+= tests
-.endif
+SUBDIR.${MK_ATM}+= atm
+SUBDIR.${MK_CASPER}+= casperd
+SUBDIR.${MK_CCD}+= ccdconfig
+SUBDIR.${MK_CXX}+= devd
+SUBDIR.${MK_HAST}+= hastctl
+SUBDIR.${MK_HAST}+= hastd
+SUBDIR.${MK_INET6}+= ping6
+SUBDIR.${MK_INET6}+= rtsol
+SUBDIR.${MK_IPFILTER}+= ipf
+SUBDIR.${MK_IPFW}+= ipfw
+SUBDIR.${MK_IPFW}+= natd
+SUBDIR.${MK_ISCSI}+= iscontrol
+SUBDIR.${MK_NAND}+= nandfs
+SUBDIR.${MK_NAND}+= newfs_nandfs
+SUBDIR.${MK_PF}+= pfctl
+SUBDIR.${MK_PF}+= pflogd
+SUBDIR.${MK_QUOTAS}+= quotacheck
+SUBDIR.${MK_ROUTED}+= routed
+
+SUBDIR.${MK_TESTS}+= tests
.include <bsd.arch.inc.mk>
diff --git a/secure/lib/libcrypto/Makefile.inc b/secure/lib/libcrypto/Makefile.inc
index c791d79..8f41603 100644
--- a/secure/lib/libcrypto/Makefile.inc
+++ b/secure/lib/libcrypto/Makefile.inc
@@ -45,7 +45,7 @@ MANDIR= ${SHAREDIR}/openssl/man/man
.if defined(LIB)
_docs= ${LIB}
-_skip= des_modes
+_skip= SSLeay_version des_modes
_sec= 3
.else
_docs= apps
@@ -72,13 +72,13 @@ man-makefile-update:
${.CURDIR}/Makefile.man
for i in ${LCRYPTO_DOC}/${_docs}/*.pod; do \
fn=`basename $$i .pod`; \
- if [ "$$fn" != "${_skip}" ]; then \
+ if ! echo '${_skip}' | grep -qw "$$fn"; then \
${ECHO} "MAN+= $$fn.${_sec}" >> ${.CURDIR}/Makefile.man; \
fi; \
done
for i in ${LCRYPTO_DOC}/${_docs}/*.pod; do \
fn=`basename $$i .pod`; \
- if [ "$$fn" != "${_skip}" ]; then \
+ if ! echo '${_skip}' | grep -qw "$$fn"; then \
perl ${LCRYPTO_SRC}/util/extract-names.pl < $$i | \
awk "/^$$fn\$$/ { next; } \
{ print \"MLINKS+= $$fn.${_sec} \" \$$1 \".${_sec}\" }" >> \
diff --git a/secure/lib/libcrypto/Makefile.man b/secure/lib/libcrypto/Makefile.man
index 239d1e1..8a55ce5 100644
--- a/secure/lib/libcrypto/Makefile.man
+++ b/secure/lib/libcrypto/Makefile.man
@@ -160,7 +160,6 @@ MAN+= SMIME_read_CMS.3
MAN+= SMIME_read_PKCS7.3
MAN+= SMIME_write_CMS.3
MAN+= SMIME_write_PKCS7.3
-MAN+= SSLeay_version.3
MAN+= X509_NAME_ENTRY_get_object.3
MAN+= X509_NAME_add_entry_by_txt.3
MAN+= X509_NAME_get_index_by_NID.3
@@ -695,7 +694,6 @@ MLINKS+= EVP_EncryptInit.3 EVP_idea_cbc.3
MLINKS+= EVP_EncryptInit.3 EVP_idea_ecb.3
MLINKS+= EVP_EncryptInit.3 EVP_idea_cfb.3
MLINKS+= EVP_EncryptInit.3 EVP_idea_ofb.3
-MLINKS+= EVP_EncryptInit.3 EVP_idea_cbc.3
MLINKS+= EVP_EncryptInit.3 EVP_rc2_cbc.3
MLINKS+= EVP_EncryptInit.3 EVP_rc2_ecb.3
MLINKS+= EVP_EncryptInit.3 EVP_rc2_cfb.3
@@ -723,7 +721,6 @@ MLINKS+= EVP_EncryptInit.3 EVP_aes_256_ccm.3
MLINKS+= EVP_OpenInit.3 EVP_OpenUpdate.3
MLINKS+= EVP_OpenInit.3 EVP_OpenFinal.3
MLINKS+= EVP_PKEY_CTX_ctrl.3 EVP_PKEY_CTX_ctrl_str.3
-MLINKS+= EVP_PKEY_CTX_ctrl.3 EVP_PKEY_get_default_digest_nid.3
MLINKS+= EVP_PKEY_CTX_ctrl.3 EVP_PKEY_CTX_set_signature_md.3
MLINKS+= EVP_PKEY_CTX_ctrl.3 EVP_PKEY_CTX_set_rsa_padding.3
MLINKS+= EVP_PKEY_CTX_ctrl.3 EVP_PKEY_CTX_set_rsa_pss_saltlen.3
diff --git a/secure/lib/libcrypto/man/EVP_EncryptInit.3 b/secure/lib/libcrypto/man/EVP_EncryptInit.3
index 87ad242..e850ff1 100644
--- a/secure/lib/libcrypto/man/EVP_EncryptInit.3
+++ b/secure/lib/libcrypto/man/EVP_EncryptInit.3
@@ -157,7 +157,7 @@ EVP_CIPHER_CTX_set_padding, EVP_enc_null, EVP_des_cbc, EVP_des_ecb,
EVP_des_cfb, EVP_des_ofb, EVP_des_ede_cbc, EVP_des_ede, EVP_des_ede_ofb,
EVP_des_ede_cfb, EVP_des_ede3_cbc, EVP_des_ede3, EVP_des_ede3_ofb,
EVP_des_ede3_cfb, EVP_desx_cbc, EVP_rc4, EVP_rc4_40, EVP_idea_cbc,
-EVP_idea_ecb, EVP_idea_cfb, EVP_idea_ofb, EVP_idea_cbc, EVP_rc2_cbc,
+EVP_idea_ecb, EVP_idea_cfb, EVP_idea_ofb, EVP_rc2_cbc,
EVP_rc2_ecb, EVP_rc2_cfb, EVP_rc2_ofb, EVP_rc2_40_cbc, EVP_rc2_64_cbc,
EVP_bf_cbc, EVP_bf_ecb, EVP_bf_cfb, EVP_bf_ofb, EVP_cast5_cbc,
EVP_cast5_ecb, EVP_cast5_cfb, EVP_cast5_ofb, EVP_rc5_32_12_16_cbc,
@@ -440,8 +440,8 @@ Three key triple \s-1DES\s0 in \s-1CBC, ECB, CFB\s0 and \s-1OFB\s0 modes respect
.IX Item "EVP_rc4_40(void)"
\&\s-1RC4\s0 stream cipher with 40 bit key length. This is obsolete and new code should use \fIEVP_rc4()\fR
and the \fIEVP_CIPHER_CTX_set_key_length()\fR function.
-.IP "\fIEVP_idea_cbc()\fR EVP_idea_ecb(void), EVP_idea_cfb(void), EVP_idea_ofb(void), EVP_idea_cbc(void)" 4
-.IX Item "EVP_idea_cbc() EVP_idea_ecb(void), EVP_idea_cfb(void), EVP_idea_ofb(void), EVP_idea_cbc(void)"
+.IP "\fIEVP_idea_cbc()\fR EVP_idea_ecb(void), EVP_idea_cfb(void), EVP_idea_ofb(void)" 4
+.IX Item "EVP_idea_cbc() EVP_idea_ecb(void), EVP_idea_cfb(void), EVP_idea_ofb(void)"
\&\s-1IDEA\s0 encryption algorithm in \s-1CBC, ECB, CFB\s0 and \s-1OFB\s0 modes respectively.
.IP "EVP_rc2_cbc(void), EVP_rc2_ecb(void), EVP_rc2_cfb(void), EVP_rc2_ofb(void)" 4
.IX Item "EVP_rc2_cbc(void), EVP_rc2_ecb(void), EVP_rc2_cfb(void), EVP_rc2_ofb(void)"
diff --git a/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3 b/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3
index 47ee71f..bce645d 100644
--- a/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3
+++ b/secure/lib/libcrypto/man/EVP_PKEY_CTX_ctrl.3
@@ -139,7 +139,7 @@
.if n .ad l
.nh
.SH "NAME"
-EVP_PKEY_CTX_ctrl, EVP_PKEY_CTX_ctrl_str, EVP_PKEY_get_default_digest_nid,
+EVP_PKEY_CTX_ctrl, EVP_PKEY_CTX_ctrl_str,
EVP_PKEY_CTX_set_signature_md, EVP_PKEY_CTX_set_rsa_padding,
EVP_PKEY_CTX_set_rsa_pss_saltlen, EVP_PKEY_CTX_set_rsa_rsa_keygen_bits,
EVP_PKEY_CTX_set_rsa_keygen_pubexp, EVP_PKEY_CTX_set_dsa_paramgen_bits,
@@ -156,8 +156,6 @@ EVP_PKEY_CTX_set_ec_paramgen_curve_nid \- algorithm specific control operations
\& int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
\& const char *value);
\&
-\& int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid);
-\&
\& #include <openssl/rsa.h>
\&
\& int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md);
diff --git a/secure/lib/libcrypto/man/SSLeay_version.3 b/secure/lib/libcrypto/man/SSLeay_version.3
deleted file mode 100644
index 677cc4b..0000000
--- a/secure/lib/libcrypto/man/SSLeay_version.3
+++ /dev/null
@@ -1,192 +0,0 @@
-.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.30)
-.\"
-.\" Standard preamble:
-.\" ========================================================================
-.de Sp \" Vertical space (when we can't use .PP)
-.if t .sp .5v
-.if n .sp
-..
-.de Vb \" Begin verbatim text
-.ft CW
-.nf
-.ne \\$1
-..
-.de Ve \" End verbatim text
-.ft R
-.fi
-..
-.\" Set up some character translations and predefined strings. \*(-- will
-.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
-.\" double quote, and \*(R" will give a right double quote. \*(C+ will
-.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
-.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
-.\" nothing in troff, for use with C<>.
-.tr \(*W-
-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
-.ie n \{\
-. ds -- \(*W-
-. ds PI pi
-. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
-. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
-. ds L" ""
-. ds R" ""
-. ds C` ""
-. ds C' ""
-'br\}
-.el\{\
-. ds -- \|\(em\|
-. ds PI \(*p
-. ds L" ``
-. ds R" ''
-. ds C`
-. ds C'
-'br\}
-.\"
-.\" Escape single quotes in literal strings from groff's Unicode transform.
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\"
-.\" If the F register is turned on, we'll generate index entries on stderr for
-.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
-.\" entries marked with X<> in POD. Of course, you'll have to process the
-.\" output yourself in some meaningful fashion.
-.\"
-.\" Avoid warning from groff about undefined register 'F'.
-.de IX
-..
-.nr rF 0
-.if \n(.g .if rF .nr rF 1
-.if (\n(rF:(\n(.g==0)) \{
-. if \nF \{
-. de IX
-. tm Index:\\$1\t\\n%\t"\\$2"
-..
-. if !\nF==2 \{
-. nr % 0
-. nr F 2
-. \}
-. \}
-.\}
-.rr rF
-.\"
-.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
-.\" Fear. Run. Save yourself. No user-serviceable parts.
-. \" fudge factors for nroff and troff
-.if n \{\
-. ds #H 0
-. ds #V .8m
-. ds #F .3m
-. ds #[ \f1
-. ds #] \fP
-.\}
-.if t \{\
-. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
-. ds #V .6m
-. ds #F 0
-. ds #[ \&
-. ds #] \&
-.\}
-. \" simple accents for nroff and troff
-.if n \{\
-. ds ' \&
-. ds ` \&
-. ds ^ \&
-. ds , \&
-. ds ~ ~
-. ds /
-.\}
-.if t \{\
-. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
-. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
-. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
-. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
-. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
-. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
-.\}
-. \" troff and (daisy-wheel) nroff accents
-.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
-.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
-.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
-.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
-.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
-.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
-.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
-.ds ae a\h'-(\w'a'u*4/10)'e
-.ds Ae A\h'-(\w'A'u*4/10)'E
-. \" corrections for vroff
-.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
-.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
-. \" for low resolution devices (crt and lpr)
-.if \n(.H>23 .if \n(.V>19 \
-\{\
-. ds : e
-. ds 8 ss
-. ds o a
-. ds d- d\h'-1'\(ga
-. ds D- D\h'-1'\(hy
-. ds th \o'bp'
-. ds Th \o'LP'
-. ds ae ae
-. ds Ae AE
-.\}
-.rm #[ #] #H #V #F C
-.\" ========================================================================
-.\"
-.IX Title "SSLeay_version 3"
-.TH SSLeay_version 3 "2015-07-09" "1.0.2d" "OpenSSL"
-.\" For nroff, turn off justification. Always turn off hyphenation; it makes
-.\" way too many mistakes in technical documents.
-.if n .ad l
-.nh
-.SH "NAME"
-SSLeay_version \- retrieve version/build information about OpenSSL library
-.SH "SYNOPSIS"
-.IX Header "SYNOPSIS"
-.Vb 1
-\& #include <openssl/crypto.h>
-\&
-\& const char *SSLeay_version(int type);
-.Ve
-.SH "DESCRIPTION"
-.IX Header "DESCRIPTION"
-\&\fISSLeay_version()\fR returns a pointer to a constant string describing the
-version of the OpenSSL library or giving information about the library
-build.
-.PP
-The following \fBtype\fR values are supported:
-.IP "\s-1SSLEAY_VERSION\s0" 4
-.IX Item "SSLEAY_VERSION"
-The version of the OpenSSL library including the release date.
-.IP "\s-1SSLEAY_CFLAGS\s0" 4
-.IX Item "SSLEAY_CFLAGS"
-The compiler flags set for the compilation process in the form
-\&\*(L"compiler: ...\*(R" if available or \*(L"compiler: information not available\*(R"
-otherwise.
-.IP "\s-1SSLEAY_BUILT_ON\s0" 4
-.IX Item "SSLEAY_BUILT_ON"
-The date of the build process in the form \*(L"built on: ...\*(R" if available
-or \*(L"built on: date not available\*(R" otherwise.
-.IP "\s-1SSLEAY_PLATFORM\s0" 4
-.IX Item "SSLEAY_PLATFORM"
-The \*(L"Configure\*(R" target of the library build in the form \*(L"platform: ...\*(R"
-if available or \*(L"platform: information not available\*(R" otherwise.
-.IP "\s-1SSLEAY_DIR\s0" 4
-.IX Item "SSLEAY_DIR"
-The \*(L"\s-1OPENSSLDIR\*(R"\s0 setting of the library build in the form \*(L"\s-1OPENSSLDIR: \*(R"..."\*(L"\s0
-if available or \*(R"\s-1OPENSSLDIR: N/A"\s0 otherwise.
-.SH "RETURN VALUES"
-.IX Header "RETURN VALUES"
-The following return values can occur:
-.ie n .IP """not available""" 4
-.el .IP "``not available''" 4
-.IX Item "not available"
-An invalid value for \fBtype\fR was given.
-.IP "Pointer to constant string" 4
-.IX Item "Pointer to constant string"
-Textual description.
-.SH "SEE ALSO"
-.IX Header "SEE ALSO"
-\&\fIcrypto\fR\|(3)
-.SH "HISTORY"
-.IX Header "HISTORY"
-\&\fB\s-1SSLEAY_DIR\s0\fR was added in OpenSSL 0.9.7.
diff --git a/share/colldef/Makefile b/share/colldef/Makefile
index 47074f9..6f48c01 100644
--- a/share/colldef/Makefile
+++ b/share/colldef/Makefile
@@ -47,6 +47,7 @@ LOCALES+= uk_UA.UTF-8
LOCALES+= zh_Hans_CN.UTF-8
LOCALES+= zh_Hant_TW.UTF-8
+SAME+= af_ZA.UTF-8:af_ZA.ISO8859-15
SAME+= af_ZA.UTF-8:af_ZA.ISO8859-1
SAME+= ar_SA.UTF-8:ar_QA.UTF-8
SAME+= ar_SA.UTF-8:ar_MA.UTF-8
@@ -108,6 +109,7 @@ SAME+= en_US.UTF-8:fr_CH.UTF-8
SAME+= en_US.UTF-8:fr_CH.ISO8859-15
SAME+= en_US.UTF-8:fr_CH.ISO8859-1
SAME+= en_US.UTF-8:fr_CA.UTF-8
+SAME+= en_US.UTF-8:fr_CA.ISO8859-15
SAME+= en_US.UTF-8:fr_CA.ISO8859-1
SAME+= en_US.UTF-8:fr_BE.UTF-8
SAME+= en_US.UTF-8:fr_BE.ISO8859-15
@@ -117,14 +119,17 @@ SAME+= en_US.UTF-8:eu_ES.ISO8859-15
SAME+= en_US.UTF-8:eu_ES.ISO8859-1
SAME+= en_US.UTF-8:en_ZA.UTF-8
SAME+= en_US.UTF-8:en_ZA.US-ASCII
+SAME+= en_US.UTF-8:en_ZA.ISO8859-15
SAME+= en_US.UTF-8:en_ZA.ISO8859-1
SAME+= en_US.UTF-8:en_US.US-ASCII
+SAME+= en_US.UTF-8:en_US.ISO8859-15
SAME+= en_US.UTF-8:en_US.ISO8859-1
SAME+= en_US.UTF-8:en_SG.UTF-8
SAME+= en_US.UTF-8:en_SG.ISO8859-1
SAME+= en_US.UTF-8:en_PH.UTF-8
SAME+= en_US.UTF-8:en_NZ.UTF-8
SAME+= en_US.UTF-8:en_NZ.US-ASCII
+SAME+= en_US.UTF-8:en_NZ.ISO8859-15
SAME+= en_US.UTF-8:en_NZ.ISO8859-1
SAME+= en_US.UTF-8:en_IE.UTF-8
SAME+= en_US.UTF-8:en_IE.ISO8859-15
@@ -137,9 +142,11 @@ SAME+= en_US.UTF-8:en_GB.ISO8859-15
SAME+= en_US.UTF-8:en_GB.ISO8859-1
SAME+= en_US.UTF-8:en_CA.UTF-8
SAME+= en_US.UTF-8:en_CA.US-ASCII
+SAME+= en_US.UTF-8:en_CA.ISO8859-15
SAME+= en_US.UTF-8:en_CA.ISO8859-1
SAME+= en_US.UTF-8:en_AU.UTF-8
SAME+= en_US.UTF-8:en_AU.US-ASCII
+SAME+= en_US.UTF-8:en_AU.ISO8859-15
SAME+= en_US.UTF-8:en_AU.ISO8859-1
SAME+= en_US.UTF-8:de_DE.UTF-8
SAME+= en_US.UTF-8:de_DE.ISO8859-15
diff --git a/share/ctypedef/Makefile b/share/ctypedef/Makefile
index 56a5607..4a75970 100644
--- a/share/ctypedef/Makefile
+++ b/share/ctypedef/Makefile
@@ -16,8 +16,8 @@ LOCALES+= be_BY.CP1131
LOCALES+= ca_IT.ISO8859-1
LOCALES+= ca_IT.ISO8859-15
LOCALES+= el_GR.ISO8859-7
-LOCALES+= en_GB.ISO8859-15
LOCALES+= en_US.ISO8859-1
+LOCALES+= en_US.ISO8859-15
LOCALES+= en_US.US-ASCII
LOCALES+= en_US.UTF-8
LOCALES+= hi_IN.ISCII-DEV
@@ -152,6 +152,35 @@ SAME+= en_US.ISO8859-1:de_CH.ISO8859-1
SAME+= en_US.ISO8859-1:de_AT.ISO8859-1
SAME+= en_US.ISO8859-1:da_DK.ISO8859-1
SAME+= en_US.ISO8859-1:af_ZA.ISO8859-1
+SAME+= en_US.ISO8859-15:en_GB.ISO8859-15
+SAME+= en_US.ISO8859-15:sv_SE.ISO8859-15
+SAME+= en_US.ISO8859-15:sv_FI.ISO8859-15
+SAME+= en_US.ISO8859-15:pt_PT.ISO8859-15
+SAME+= en_US.ISO8859-15:nn_NO.ISO8859-15
+SAME+= en_US.ISO8859-15:nl_NL.ISO8859-15
+SAME+= en_US.ISO8859-15:nl_BE.ISO8859-15
+SAME+= en_US.ISO8859-15:nb_NO.ISO8859-15
+SAME+= en_US.ISO8859-15:it_IT.ISO8859-15
+SAME+= en_US.ISO8859-15:it_CH.ISO8859-15
+SAME+= en_US.ISO8859-15:is_IS.ISO8859-15
+SAME+= en_US.ISO8859-15:fr_FR.ISO8859-15
+SAME+= en_US.ISO8859-15:fr_CH.ISO8859-15
+SAME+= en_US.ISO8859-15:fr_CA.ISO8859-15
+SAME+= en_US.ISO8859-15:fr_BE.ISO8859-15
+SAME+= en_US.ISO8859-15:fi_FI.ISO8859-15
+SAME+= en_US.ISO8859-15:eu_ES.ISO8859-15
+SAME+= en_US.ISO8859-15:et_EE.ISO8859-15
+SAME+= en_US.ISO8859-15:es_ES.ISO8859-15
+SAME+= en_US.ISO8859-15:en_ZA.ISO8859-15
+SAME+= en_US.ISO8859-15:en_NZ.ISO8859-15
+SAME+= en_US.ISO8859-15:en_IE.ISO8859-15
+SAME+= en_US.ISO8859-15:en_CA.ISO8859-15
+SAME+= en_US.ISO8859-15:en_AU.ISO8859-15
+SAME+= en_US.ISO8859-15:de_DE.ISO8859-15
+SAME+= en_US.ISO8859-15:de_CH.ISO8859-15
+SAME+= en_US.ISO8859-15:de_AT.ISO8859-15
+SAME+= en_US.ISO8859-15:da_DK.ISO8859-15
+SAME+= en_US.ISO8859-15:af_ZA.ISO8859-15
SAME+= ru_RU.CP1251:bg_BG.CP1251
SAME+= ru_RU.CP1251:be_BY.CP1251
SAME+= ru_RU.ISO8859-5:sr_Cyrl_RS.ISO8859-5
@@ -169,28 +198,6 @@ SAME+= sr_Latn_RS.ISO8859-2:pl_PL.ISO8859-2
SAME+= sr_Latn_RS.ISO8859-2:hu_HU.ISO8859-2
SAME+= sr_Latn_RS.ISO8859-2:hr_HR.ISO8859-2
SAME+= sr_Latn_RS.ISO8859-2:cs_CZ.ISO8859-2
-SAME+= en_GB.ISO8859-15:sv_SE.ISO8859-15
-SAME+= en_GB.ISO8859-15:sv_FI.ISO8859-15
-SAME+= en_GB.ISO8859-15:pt_PT.ISO8859-15
-SAME+= en_GB.ISO8859-15:nn_NO.ISO8859-15
-SAME+= en_GB.ISO8859-15:nl_NL.ISO8859-15
-SAME+= en_GB.ISO8859-15:nl_BE.ISO8859-15
-SAME+= en_GB.ISO8859-15:nb_NO.ISO8859-15
-SAME+= en_GB.ISO8859-15:it_IT.ISO8859-15
-SAME+= en_GB.ISO8859-15:it_CH.ISO8859-15
-SAME+= en_GB.ISO8859-15:is_IS.ISO8859-15
-SAME+= en_GB.ISO8859-15:fr_FR.ISO8859-15
-SAME+= en_GB.ISO8859-15:fr_CH.ISO8859-15
-SAME+= en_GB.ISO8859-15:fr_BE.ISO8859-15
-SAME+= en_GB.ISO8859-15:fi_FI.ISO8859-15
-SAME+= en_GB.ISO8859-15:eu_ES.ISO8859-15
-SAME+= en_GB.ISO8859-15:et_EE.ISO8859-15
-SAME+= en_GB.ISO8859-15:es_ES.ISO8859-15
-SAME+= en_GB.ISO8859-15:en_IE.ISO8859-15
-SAME+= en_GB.ISO8859-15:de_DE.ISO8859-15
-SAME+= en_GB.ISO8859-15:de_CH.ISO8859-15
-SAME+= en_GB.ISO8859-15:de_AT.ISO8859-15
-SAME+= en_GB.ISO8859-15:da_DK.ISO8859-15
SAME+= en_US.US-ASCII:en_ZA.US-ASCII
SAME+= en_US.US-ASCII:en_NZ.US-ASCII
SAME+= en_US.US-ASCII:en_GB.US-ASCII
@@ -222,11 +229,11 @@ SYMPAIRS+= zh_Hans_CN.eucCN.src:zh_Hans_CN.GB18030.src
SYMPAIRS+= zh_Hans_CN.eucCN.src:zh_Hans_CN.GB2312.src
SYMPAIRS+= zh_Hans_CN.eucCN.src:zh_Hans_CN.GBK.src
SYMPAIRS+= zh_Hant_HK.Big5HKSCS.src:zh_Hant_TW.Big5.src
-SYMPAIRS+= en_GB.ISO8859-15.src:en_US.ISO8859-1.src
-SYMPAIRS+= en_GB.ISO8859-15.src:en_US.US-ASCII.src
-SYMPAIRS+= en_GB.ISO8859-15.src:lv_LV.ISO8859-13.src
-SYMPAIRS+= en_GB.ISO8859-15.src:sr_Latn_RS.ISO8859-2.src
-SYMPAIRS+= en_GB.ISO8859-15.src:tr_TR.ISO8859-9.src
+SYMPAIRS+= en_US.ISO8859-1.src:en_US.ISO8859-15.src
+SYMPAIRS+= en_US.ISO8859-1.src:en_US.US-ASCII.src
+SYMPAIRS+= en_US.ISO8859-1.src:lv_LV.ISO8859-13.src
+SYMPAIRS+= en_US.ISO8859-1.src:sr_Latn_RS.ISO8859-2.src
+SYMPAIRS+= en_US.ISO8859-1.src:tr_TR.ISO8859-9.src
SYMPAIRS+= ja_JP.eucJP.src:ja_JP.SJIS.src
.for PAIR in ${SYMPAIRS}
diff --git a/share/ctypedef/en_GB.ISO8859-15.src b/share/ctypedef/en_US.ISO8859-1.src
index 135c6d9..135c6d9 100644
--- a/share/ctypedef/en_GB.ISO8859-15.src
+++ b/share/ctypedef/en_US.ISO8859-1.src
diff --git a/share/locale-links/Makefile b/share/locale-links/Makefile
index 20080eb..d59cedf 100644
--- a/share/locale-links/Makefile
+++ b/share/locale-links/Makefile
@@ -8,6 +8,7 @@ ALIASES= zh_Hans_CN.GB18030 zh_CN.GB18030 \
zh_Hans_CN.GB2312 zh_CN.GB2312 \
zh_Hans_CN.GBK zh_CN.GBK \
zh_Hans_CN.eucCN zh_CN.eucCN \
+ zh_Hans_CN.UTF-8 zh_CN.UTF-8 \
zh_Hant_HK.Big5HKSCS zh_HK.Big5HKSCS \
zh_Hant_HK.UTF-8 zh_HK.UTF-8 \
zh_Hant_TW.Big5 zh_TW.Big5 \
diff --git a/share/mk/dirdeps.mk b/share/mk/dirdeps.mk
index c3c19d2..a989f95 100644
--- a/share/mk/dirdeps.mk
+++ b/share/mk/dirdeps.mk
@@ -1,5 +1,5 @@
# $FreeBSD$
-# $Id: dirdeps.mk,v 1.54 2015/06/08 20:55:11 sjg Exp $
+# $Id: dirdeps.mk,v 1.55 2015/10/20 22:04:53 sjg Exp $
# Copyright (c) 2010-2013, Juniper Networks, Inc.
# All rights reserved.
@@ -243,6 +243,21 @@ DEP_${TARGET_SPEC_VARS:[$i]} := ${_tspec:[$i]}
DEP_MACHINE := ${_DEP_TARGET_SPEC}
.endif
+.if ${MAKEFILE:T} == ${.PARSEFILE} && empty(DIRDEPS) && ${.TARGETS:Uall:M*/*} != ""
+# This little trick let's us do
+#
+# mk -f dirdeps.mk some/dir.${TARGET_SPEC}
+#
+all:
+${.TARGETS:Nall}: all
+DIRDEPS := ${.TARGETS:M*/*}
+# so that -DNO_DIRDEPS works
+DEP_RELDIR := ${DIRDEPS:R:[1]}
+# disable DIRDEPS_CACHE as it does not like this trick
+MK_DIRDEPS_CACHE = no
+.endif
+
+
# pickup customizations
# as below you can use !target(_DIRDEP_USE) to protect things
# which should only be done once.
diff --git a/share/mk/local.gendirdeps.mk b/share/mk/local.gendirdeps.mk
index 833ac80..a790cbc 100644
--- a/share/mk/local.gendirdeps.mk
+++ b/share/mk/local.gendirdeps.mk
@@ -6,6 +6,7 @@ GENDIRDEPS_HEADER= echo '\# ${FreeBSD:L:@v@$$$v$$ @:M*F*}';
# supress optional/auto dependecies
# local.dirdeps.mk will put them in if necessary
GENDIRDEPS_FILTER+= \
+ Nbin/cat.host \
Ngnu/lib/libssp/libssp_nonshared \
Ncddl/usr.bin/ctf* \
Nlib/clang/include \
diff --git a/share/mk/sys.mk b/share/mk/sys.mk
index 4ec1a6b..6b6f847 100644
--- a/share/mk/sys.mk
+++ b/share/mk/sys.mk
@@ -19,13 +19,12 @@ MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb|hf)?/arm
# Some options we need now
__DEFAULT_NO_OPTIONS= \
- DIRDEPS_CACHE \
DIRDEPS_BUILD \
- META_MODE \
-
+ DIRDEPS_CACHE
__DEFAULT_DEPENDENT_OPTIONS= \
AUTO_OBJ/DIRDEPS_BUILD \
+ META_MODE/DIRDEPS_BUILD \
STAGING/DIRDEPS_BUILD \
SYSROOT/DIRDEPS_BUILD
diff --git a/share/monetdef/Makefile b/share/monetdef/Makefile
index 12397a3..2fb532c 100644
--- a/share/monetdef/Makefile
+++ b/share/monetdef/Makefile
@@ -40,13 +40,13 @@ LOCALES+= en_NZ.UTF-8
LOCALES+= en_PH.UTF-8
LOCALES+= en_SG.UTF-8
LOCALES+= en_US.UTF-8
-LOCALES+= en_ZA.ISO8859-1
+LOCALES+= en_ZA.ISO8859-15
LOCALES+= en_ZA.US-ASCII
LOCALES+= en_ZA.UTF-8
LOCALES+= es_AR.UTF-8
LOCALES+= es_CR.UTF-8
LOCALES+= es_MX.UTF-8
-LOCALES+= fr_CA.ISO8859-1
+LOCALES+= fr_CA.ISO8859-15
LOCALES+= fr_CA.UTF-8
LOCALES+= fr_CH.ISO8859-15
LOCALES+= fr_CH.UTF-8
@@ -109,7 +109,9 @@ LOCALES+= zh_Hant_HK.UTF-8
LOCALES+= zh_Hant_TW.Big5
LOCALES+= zh_Hant_TW.UTF-8
-SAME+= en_ZA.ISO8859-1:af_ZA.ISO8859-1
+SAME+= en_ZA.ISO8859-15:en_ZA.ISO8859-1
+SAME+= en_ZA.ISO8859-15:af_ZA.ISO8859-15
+SAME+= en_ZA.ISO8859-15:af_ZA.ISO8859-1
SAME+= en_ZA.UTF-8:af_ZA.UTF-8
SAME+= sl_SI.ISO8859-2:nl_BE.ISO8859-1
SAME+= sl_SI.ISO8859-2:it_IT.ISO8859-1
@@ -150,17 +152,21 @@ SAME+= it_CH.UTF-8:de_CH.UTF-8
SAME+= it_CH.UTF-8:de_CH.ISO8859-15
SAME+= it_CH.UTF-8:de_CH.ISO8859-1
SAME+= en_AU.UTF-8:en_AU.US-ASCII
+SAME+= en_AU.UTF-8:en_AU.ISO8859-15
SAME+= en_AU.UTF-8:en_AU.ISO8859-1
SAME+= en_CA.UTF-8:en_CA.US-ASCII
+SAME+= en_CA.UTF-8:en_CA.ISO8859-15
SAME+= en_CA.UTF-8:en_CA.ISO8859-1
SAME+= en_GB.ISO8859-15:en_GB.ISO8859-1
SAME+= zh_Hant_HK.UTF-8:zh_Hant_HK.Big5HKSCS
SAME+= zh_Hant_HK.UTF-8:en_HK.UTF-8
SAME+= zh_Hant_HK.UTF-8:en_HK.ISO8859-1
SAME+= en_NZ.UTF-8:en_NZ.US-ASCII
+SAME+= en_NZ.UTF-8:en_NZ.ISO8859-15
SAME+= en_NZ.UTF-8:en_NZ.ISO8859-1
SAME+= en_SG.UTF-8:en_SG.ISO8859-1
SAME+= en_US.UTF-8:en_US.US-ASCII
+SAME+= en_US.UTF-8:en_US.ISO8859-15
SAME+= en_US.UTF-8:en_US.ISO8859-1
SAME+= es_AR.UTF-8:es_AR.ISO8859-1
SAME+= es_MX.UTF-8:es_MX.ISO8859-1
@@ -180,6 +186,7 @@ SAME+= sk_SK.UTF-8:et_EE.UTF-8
SAME+= sv_FI.UTF-8:se_FI.UTF-8
SAME+= sv_FI.UTF-8:lt_LT.UTF-8
SAME+= sv_FI.UTF-8:fi_FI.UTF-8
+SAME+= fr_CA.ISO8859-15:fr_CA.ISO8859-1
SAME+= fr_CH.ISO8859-15:fr_CH.ISO8859-1
SAME+= hr_HR.UTF-8:hr_HR.ISO8859-2
SAME+= is_IS.UTF-8:is_IS.ISO8859-15
diff --git a/share/monetdef/en_ZA.ISO8859-1.src b/share/monetdef/en_ZA.ISO8859-15.src
index 9f2ba68..9f2ba68 100644
--- a/share/monetdef/en_ZA.ISO8859-1.src
+++ b/share/monetdef/en_ZA.ISO8859-15.src
diff --git a/share/monetdef/fr_CA.ISO8859-1.src b/share/monetdef/fr_CA.ISO8859-15.src
index 65c6b07..65c6b07 100644
--- a/share/monetdef/fr_CA.ISO8859-1.src
+++ b/share/monetdef/fr_CA.ISO8859-15.src
diff --git a/share/msgdef/Makefile b/share/msgdef/Makefile
index a303dcc..d6425da 100644
--- a/share/msgdef/Makefile
+++ b/share/msgdef/Makefile
@@ -89,6 +89,7 @@ SAME+= nl_NL.UTF-8:nl_BE.UTF-8
SAME+= nl_NL.UTF-8:nl_BE.ISO8859-15
SAME+= nl_NL.UTF-8:nl_BE.ISO8859-1
SAME+= nl_NL.UTF-8:af_ZA.UTF-8
+SAME+= nl_NL.UTF-8:af_ZA.ISO8859-15
SAME+= nl_NL.UTF-8:af_ZA.ISO8859-1
SAME+= ar_SA.UTF-8:ar_QA.UTF-8
SAME+= ar_SA.UTF-8:ar_MA.UTF-8
@@ -132,14 +133,17 @@ SAME+= de_DE.UTF-8:de_AT.ISO8859-15
SAME+= de_DE.UTF-8:de_AT.ISO8859-1
SAME+= en_US.UTF-8:en_ZA.UTF-8
SAME+= en_US.UTF-8:en_ZA.US-ASCII
+SAME+= en_US.UTF-8:en_ZA.ISO8859-15
SAME+= en_US.UTF-8:en_ZA.ISO8859-1
SAME+= en_US.UTF-8:en_US.US-ASCII
+SAME+= en_US.UTF-8:en_US.ISO8859-15
SAME+= en_US.UTF-8:en_US.ISO8859-1
SAME+= en_US.UTF-8:en_SG.UTF-8
SAME+= en_US.UTF-8:en_SG.ISO8859-1
SAME+= en_US.UTF-8:en_PH.UTF-8
SAME+= en_US.UTF-8:en_NZ.UTF-8
SAME+= en_US.UTF-8:en_NZ.US-ASCII
+SAME+= en_US.UTF-8:en_NZ.ISO8859-15
SAME+= en_US.UTF-8:en_NZ.ISO8859-1
SAME+= en_US.UTF-8:en_IE.UTF-8
SAME+= en_US.UTF-8:en_IE.ISO8859-15
@@ -152,9 +156,11 @@ SAME+= en_US.UTF-8:en_GB.ISO8859-15
SAME+= en_US.UTF-8:en_GB.ISO8859-1
SAME+= en_US.UTF-8:en_CA.UTF-8
SAME+= en_US.UTF-8:en_CA.US-ASCII
+SAME+= en_US.UTF-8:en_CA.ISO8859-15
SAME+= en_US.UTF-8:en_CA.ISO8859-1
SAME+= en_US.UTF-8:en_AU.UTF-8
SAME+= en_US.UTF-8:en_AU.US-ASCII
+SAME+= en_US.UTF-8:en_AU.ISO8859-15
SAME+= en_US.UTF-8:en_AU.ISO8859-1
SAME+= et_EE.UTF-8:et_EE.ISO8859-15
SAME+= et_EE.UTF-8:et_EE.ISO8859-1
@@ -167,6 +173,7 @@ SAME+= fr_FR.UTF-8:fr_CH.UTF-8
SAME+= fr_FR.UTF-8:fr_CH.ISO8859-15
SAME+= fr_FR.UTF-8:fr_CH.ISO8859-1
SAME+= fr_FR.UTF-8:fr_CA.UTF-8
+SAME+= fr_FR.UTF-8:fr_CA.ISO8859-15
SAME+= fr_FR.UTF-8:fr_CA.ISO8859-1
SAME+= fr_FR.UTF-8:fr_BE.UTF-8
SAME+= fr_FR.UTF-8:fr_BE.ISO8859-15
diff --git a/share/numericdef/Makefile b/share/numericdef/Makefile
index 727fe33..2220216 100644
--- a/share/numericdef/Makefile
+++ b/share/numericdef/Makefile
@@ -47,16 +47,19 @@ SAME+= uk_UA.ISO8859-5:lt_LT.ISO8859-13
SAME+= uk_UA.ISO8859-5:hu_HU.ISO8859-2
SAME+= uk_UA.ISO8859-5:fr_FR.ISO8859-15
SAME+= uk_UA.ISO8859-5:fr_FR.ISO8859-1
+SAME+= uk_UA.ISO8859-5:fr_CA.ISO8859-15
SAME+= uk_UA.ISO8859-5:fr_CA.ISO8859-1
SAME+= uk_UA.ISO8859-5:fi_FI.ISO8859-15
SAME+= uk_UA.ISO8859-5:fi_FI.ISO8859-1
SAME+= uk_UA.ISO8859-5:et_EE.ISO8859-15
SAME+= uk_UA.ISO8859-5:et_EE.ISO8859-1
+SAME+= uk_UA.ISO8859-5:en_ZA.ISO8859-15
SAME+= uk_UA.ISO8859-5:en_ZA.ISO8859-1
SAME+= uk_UA.ISO8859-5:cs_CZ.ISO8859-2
SAME+= uk_UA.ISO8859-5:bg_BG.CP1251
SAME+= uk_UA.ISO8859-5:be_BY.ISO8859-5
SAME+= uk_UA.ISO8859-5:be_BY.CP1251
+SAME+= uk_UA.ISO8859-5:af_ZA.ISO8859-15
SAME+= uk_UA.ISO8859-5:af_ZA.ISO8859-1
SAME+= uk_UA.UTF-8:sv_SE.UTF-8
SAME+= uk_UA.UTF-8:sv_FI.UTF-8
@@ -97,12 +100,14 @@ SAME+= en_US.UTF-8:he_IL.UTF-8
SAME+= en_US.UTF-8:es_MX.UTF-8
SAME+= en_US.UTF-8:es_MX.ISO8859-1
SAME+= en_US.UTF-8:en_US.US-ASCII
+SAME+= en_US.UTF-8:en_US.ISO8859-15
SAME+= en_US.UTF-8:en_US.ISO8859-1
SAME+= en_US.UTF-8:en_SG.UTF-8
SAME+= en_US.UTF-8:en_SG.ISO8859-1
SAME+= en_US.UTF-8:en_PH.UTF-8
SAME+= en_US.UTF-8:en_NZ.UTF-8
SAME+= en_US.UTF-8:en_NZ.US-ASCII
+SAME+= en_US.UTF-8:en_NZ.ISO8859-15
SAME+= en_US.UTF-8:en_NZ.ISO8859-1
SAME+= en_US.UTF-8:en_IE.UTF-8
SAME+= en_US.UTF-8:en_IE.ISO8859-15
@@ -115,9 +120,11 @@ SAME+= en_US.UTF-8:en_GB.ISO8859-15
SAME+= en_US.UTF-8:en_GB.ISO8859-1
SAME+= en_US.UTF-8:en_CA.UTF-8
SAME+= en_US.UTF-8:en_CA.US-ASCII
+SAME+= en_US.UTF-8:en_CA.ISO8859-15
SAME+= en_US.UTF-8:en_CA.ISO8859-1
SAME+= en_US.UTF-8:en_AU.UTF-8
SAME+= en_US.UTF-8:en_AU.US-ASCII
+SAME+= en_US.UTF-8:en_AU.ISO8859-15
SAME+= en_US.UTF-8:en_AU.ISO8859-1
SAME+= en_US.UTF-8:am_ET.UTF-8
SAME+= ar_SA.UTF-8:ar_QA.UTF-8
diff --git a/share/timedef/Makefile b/share/timedef/Makefile
index fbbe7e1..dde32a2 100644
--- a/share/timedef/Makefile
+++ b/share/timedef/Makefile
@@ -53,7 +53,7 @@ LOCALES+= fi_FI.ISO8859-15
LOCALES+= fi_FI.UTF-8
LOCALES+= fr_BE.ISO8859-15
LOCALES+= fr_BE.UTF-8
-LOCALES+= fr_CA.ISO8859-1
+LOCALES+= fr_CA.ISO8859-15
LOCALES+= fr_CA.UTF-8
LOCALES+= fr_CH.ISO8859-15
LOCALES+= fr_CH.UTF-8
@@ -132,6 +132,7 @@ LOCALES+= zh_Hant_HK.UTF-8
LOCALES+= zh_Hant_TW.Big5
LOCALES+= zh_Hant_TW.UTF-8
+SAME+= af_ZA.UTF-8:af_ZA.ISO8859-15
SAME+= af_ZA.UTF-8:af_ZA.ISO8859-1
SAME+= ar_SA.UTF-8:ar_QA.UTF-8
SAME+= ar_SA.UTF-8:ar_EG.UTF-8
@@ -155,8 +156,10 @@ SAME+= de_DE.UTF-8:de_CH.UTF-8
SAME+= en_HK.UTF-8:en_HK.ISO8859-1
SAME+= en_HK.UTF-8:en_AU.UTF-8
SAME+= en_HK.UTF-8:en_AU.US-ASCII
+SAME+= en_HK.UTF-8:en_AU.ISO8859-15
SAME+= en_HK.UTF-8:en_AU.ISO8859-1
SAME+= en_CA.UTF-8:en_CA.US-ASCII
+SAME+= en_CA.UTF-8:en_CA.ISO8859-15
SAME+= en_CA.UTF-8:en_CA.ISO8859-1
SAME+= en_GB.UTF-8:en_GB.US-ASCII
SAME+= en_GB.UTF-8:en_GB.ISO8859-15
@@ -166,10 +169,13 @@ SAME+= en_IE.UTF-8:en_IE.ISO8859-1
SAME+= en_SG.UTF-8:en_SG.ISO8859-1
SAME+= en_SG.UTF-8:en_NZ.UTF-8
SAME+= en_SG.UTF-8:en_NZ.US-ASCII
+SAME+= en_SG.UTF-8:en_NZ.ISO8859-15
SAME+= en_SG.UTF-8:en_NZ.ISO8859-1
SAME+= en_US.UTF-8:en_US.US-ASCII
+SAME+= en_US.UTF-8:en_US.ISO8859-15
SAME+= en_US.UTF-8:en_US.ISO8859-1
SAME+= en_ZA.UTF-8:en_ZA.US-ASCII
+SAME+= en_ZA.UTF-8:en_ZA.ISO8859-15
SAME+= en_ZA.UTF-8:en_ZA.ISO8859-1
SAME+= es_CR.UTF-8:es_AR.UTF-8
SAME+= es_ES.ISO8859-15:es_ES.ISO8859-1
@@ -178,6 +184,7 @@ SAME+= eu_ES.UTF-8:eu_ES.ISO8859-15
SAME+= eu_ES.UTF-8:eu_ES.ISO8859-1
SAME+= fi_FI.ISO8859-15:fi_FI.ISO8859-1
SAME+= fr_BE.ISO8859-15:fr_BE.ISO8859-1
+SAME+= fr_CA.ISO8859-15:fr_CA.ISO8859-1
SAME+= fr_CH.ISO8859-15:fr_CH.ISO8859-1
SAME+= fr_FR.ISO8859-15:fr_FR.ISO8859-1
SAME+= is_IS.ISO8859-15:is_IS.ISO8859-1
diff --git a/share/timedef/fr_CA.ISO8859-1.src b/share/timedef/fr_CA.ISO8859-15.src
index 1fb71de..1fb71de 100644
--- a/share/timedef/fr_CA.ISO8859-1.src
+++ b/share/timedef/fr_CA.ISO8859-15.src
diff --git a/sys/arm/arm/busdma_machdep-v6.c b/sys/arm/arm/busdma_machdep-v6.c
index a755740..fe446b9 100644
--- a/sys/arm/arm/busdma_machdep-v6.c
+++ b/sys/arm/arm/busdma_machdep-v6.c
@@ -117,8 +117,8 @@ struct bounce_page {
struct sync_list {
vm_offset_t vaddr; /* kva of client data */
+ bus_addr_t paddr; /* physical address */
vm_page_t pages; /* starting page of client data */
- vm_offset_t dataoffs; /* page offset of client data */
bus_size_t datacount; /* client data count */
};
@@ -1076,17 +1076,19 @@ _bus_dmamap_load_phys(bus_dma_tag_t dmat, bus_dmamap_t map, vm_paddr_t buf,
sgsize);
} else {
if (map->sync_count > 0)
- sl_end = VM_PAGE_TO_PHYS(sl->pages) +
- sl->dataoffs + sl->datacount;
+ sl_end = sl->paddr + sl->datacount;
if (map->sync_count == 0 || curaddr != sl_end) {
if (++map->sync_count > dmat->nsegments)
break;
sl++;
sl->vaddr = 0;
+ sl->paddr = curaddr;
sl->datacount = sgsize;
sl->pages = PHYS_TO_VM_PAGE(curaddr);
- sl->dataoffs = curaddr & PAGE_MASK;
+ KASSERT(sl->pages != NULL,
+ ("%s: page at PA:0x%08lx is not in "
+ "vm_page_array", __func__, curaddr));
} else
sl->datacount += sgsize;
}
@@ -1188,8 +1190,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
sgsize);
} else {
if (map->sync_count > 0) {
- sl_pend = VM_PAGE_TO_PHYS(sl->pages) +
- sl->dataoffs + sl->datacount;
+ sl_pend = sl->paddr + sl->datacount;
sl_vend = sl->vaddr + sl->datacount;
}
@@ -1201,9 +1202,17 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
goto cleanup;
sl++;
sl->vaddr = kvaddr;
+ sl->paddr = curaddr;
+ if (kvaddr != 0) {
+ sl->pages = NULL;
+ } else {
+ sl->pages = PHYS_TO_VM_PAGE(curaddr);
+ KASSERT(sl->pages != NULL,
+ ("%s: page at PA:0x%08lx is not "
+ "in vm_page_array", __func__,
+ curaddr));
+ }
sl->datacount = sgsize;
- sl->pages = PHYS_TO_VM_PAGE(curaddr);
- sl->dataoffs = curaddr & PAGE_MASK;
} else
sl->datacount += sgsize;
}
@@ -1299,10 +1308,10 @@ dma_dcache_sync(struct sync_list *sl, bus_dmasync_op_t op)
vm_offset_t va, tempva;
bus_size_t size;
- offset = sl->dataoffs;
+ offset = sl->paddr & PAGE_MASK;
m = sl->pages;
size = sl->datacount;
- pa = VM_PAGE_TO_PHYS(m) | offset;
+ pa = sl->paddr;
for ( ; size != 0; size -= len, pa += len, offset = 0, ++m) {
tempva = 0;
@@ -1310,13 +1319,13 @@ dma_dcache_sync(struct sync_list *sl, bus_dmasync_op_t op)
len = min(PAGE_SIZE - offset, size);
tempva = pmap_quick_enter_page(m);
va = tempva | offset;
+ KASSERT(pa == (VM_PAGE_TO_PHYS(m) | offset),
+ ("unexpected vm_page_t phys: 0x%08x != 0x%08x",
+ VM_PAGE_TO_PHYS(m) | offset, pa));
} else {
len = sl->datacount;
va = sl->vaddr;
}
- KASSERT(pa == (VM_PAGE_TO_PHYS(m) | offset),
- ("unexpected vm_page_t phys: 0x%08x != 0x%08x",
- VM_PAGE_TO_PHYS(m) | offset, pa));
switch (op) {
case BUS_DMASYNC_PREWRITE:
diff --git a/sys/arm/arm/pl310.c b/sys/arm/arm/pl310.c
index 2fba6a8..c269b47 100644
--- a/sys/arm/arm/pl310.c
+++ b/sys/arm/arm/pl310.c
@@ -90,7 +90,7 @@ static struct ofw_compat_data compat_data[] = {
{NULL, false}
};
-void
+static void
pl310_print_config(struct pl310_softc *sc)
{
uint32_t aux, prefetch;
diff --git a/sys/arm/include/pcb.h b/sys/arm/include/pcb.h
index 29078e9..390758b 100644
--- a/sys/arm/include/pcb.h
+++ b/sys/arm/include/pcb.h
@@ -52,14 +52,17 @@ struct pcb {
#define PCB_OWNFPU 0x00000001
#define PCB_NOALIGNFLT 0x00000002
caddr_t pcb_onfault; /* On fault handler */
-#ifdef ARM_NEW_PMAP
- uint32_t pcb_pagedir; /* TTB0 value */
-#else
- vm_offset_t pcb_pagedir; /* PT hooks */
+ vm_offset_t pcb_pagedir; /* TTB0 value */
+ /*
+ * XXX:
+ * Variables pcb_pl1vec, pcb_l1vec, pcb_dacr are used solely
+ * by old PMAP. Keep them here for PCB binary compatibility
+ * between old and new PMAP.
+ */
uint32_t *pcb_pl1vec; /* PTR to vector_base L1 entry*/
uint32_t pcb_l1vec; /* Value to stuff on ctx sw */
u_int pcb_dacr; /* Domain Access Control Reg */
-#endif
+
struct vfp_state pcb_vfpstate; /* VP/NEON state */
u_int pcb_vfpcpu; /* VP/NEON last cpu */
} __aligned(8); /*
diff --git a/sys/arm/include/pl310.h b/sys/arm/include/pl310.h
index b1b7cd5..5fcb7af 100644
--- a/sys/arm/include/pl310.h
+++ b/sys/arm/include/pl310.h
@@ -177,7 +177,6 @@ pl310_write4(struct pl310_softc *sc, bus_size_t off, uint32_t val)
bus_write_4(sc->sc_mem_res, off, val);
}
-void pl310_print_config(struct pl310_softc *sc);
void pl310_set_ram_latency(struct pl310_softc *sc, uint32_t which_reg,
uint32_t read, uint32_t write, uint32_t setup);
diff --git a/sys/arm/samsung/exynos/exynos5_ehci.c b/sys/arm/samsung/exynos/exynos5_ehci.c
index 9234a64..6683937 100644
--- a/sys/arm/samsung/exynos/exynos5_ehci.c
+++ b/sys/arm/samsung/exynos/exynos5_ehci.c
@@ -122,7 +122,7 @@ static device_method_t ehci_methods[] = {
static driver_t ehci_driver = {
"ehci",
ehci_methods,
- sizeof(ehci_softc_t)
+ sizeof(struct exynos_ehci_softc)
};
static devclass_t ehci_devclass;
diff --git a/sys/boot/common/loader.8 b/sys/boot/common/loader.8
index 7d5a561..7dff914 100644
--- a/sys/boot/common/loader.8
+++ b/sys/boot/common/loader.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 25, 2015
+.Dd November 18, 2015
.Dt LOADER 8
.Os
.Sh NAME
@@ -471,6 +471,14 @@ userland output (e.g.\& from
.It Va currdev
Selects the default device.
Syntax for devices is odd.
+.It Va dumpdev
+Sets the device for kernel dumps.
+This can be used to ensure that a device is configured before the corresponding
+.Va dumpdev
+directive from
+.Xr rc.conf 5
+has been processed, allowing kernel panics that happen during the early stages
+of boot to be captured.
.It Va init_chroot
If set to a valid directory in the root file system, it causes
.Xr init 8
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 7aa9840..912f015 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -74,7 +74,7 @@ dev/syscons/scvtb.c optional sc
dev/tsec/if_tsec.c optional tsec
dev/tsec/if_tsec_fdt.c optional tsec fdt
dev/uart/uart_cpu_powerpc.c optional uart
-dev/usb/controller/ehci_fsl.c optional ehci mpc85xx
+dev/usb/controller/ehci_fsl.c optional ehci mpc85xx | ehci qoriq_dpaa
dev/vt/hw/ofwfb/ofwfb.c optional vt aim
kern/kern_clocksource.c standard
kern/subr_dummy_vdso_tc.c standard
@@ -133,15 +133,15 @@ powerpc/mikrotik/platform_rb.c optional mikrotik
powerpc/mpc85xx/atpic.c optional mpc85xx isa
powerpc/mpc85xx/ds1553_bus_fdt.c optional ds1553 fdt
powerpc/mpc85xx/ds1553_core.c optional ds1553
-powerpc/mpc85xx/fsl_sdhc.c optional mpc85xx sdhc
+powerpc/mpc85xx/fsl_sdhc.c optional mpc85xx sdhc | qoriq_dpaa sdhc
powerpc/mpc85xx/i2c.c optional iicbus fdt
powerpc/mpc85xx/isa.c optional mpc85xx isa
-powerpc/mpc85xx/lbc.c optional mpc85xx
-powerpc/mpc85xx/mpc85xx.c optional mpc85xx
+powerpc/mpc85xx/lbc.c optional mpc85xx | qoriq_dpaa
+powerpc/mpc85xx/mpc85xx.c optional mpc85xx | qoriq_dpaa
powerpc/mpc85xx/mpc85xx_gpio.c optional mpc85xx gpio
-powerpc/mpc85xx/platform_mpc85xx.c optional mpc85xx
-powerpc/mpc85xx/pci_mpc85xx.c optional pci mpc85xx
-powerpc/mpc85xx/pci_mpc85xx_pcib.c optional pci mpc85xx
+powerpc/mpc85xx/platform_mpc85xx.c optional mpc85xx | qoriq_dpaa
+powerpc/mpc85xx/pci_mpc85xx.c optional pci mpc85xx | pci qoriq_dpaa
+powerpc/mpc85xx/pci_mpc85xx_pcib.c optional pci mpc85xx | pci qoriq_dpaa
powerpc/ofw/ofw_machdep.c standard
powerpc/ofw/ofw_pci.c optional pci
powerpc/ofw/ofw_pcibus.c optional pci
diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
index 1dbd5a9..100f7aa 100644
--- a/sys/conf/kern.pre.mk
+++ b/sys/conf/kern.pre.mk
@@ -157,15 +157,15 @@ DTRACE_CFLAGS+= -I$S/cddl/contrib/opensolaris/uts/intel -I$S/cddl/dev/dtrace/x86
.endif
DTRACE_CFLAGS+= -I$S/cddl/contrib/opensolaris/common/util -I$S -DDIS_MEM -DSMP
DTRACE_ASM_CFLAGS= -x assembler-with-cpp -DLOCORE ${DTRACE_CFLAGS}
-DTRACE_C= ${CC} -c ${DTRACE_CFLAGS} ${CDDL_CFLAGS} ${WERROR} ${PROF} ${.IMPSRC}
-DTRACE_S= ${CC} -c ${DTRACE_ASM_CFLAGS} ${CDDL_CFLAGS} ${WERROR} ${.IMPSRC}
+DTRACE_C= ${CC} -c ${DTRACE_CFLAGS} ${WERROR} ${PROF} ${.IMPSRC}
+DTRACE_S= ${CC} -c ${DTRACE_ASM_CFLAGS} ${WERROR} ${.IMPSRC}
# Special flags for managing the compat compiles for DTrace/FBT
FBT_CFLAGS= -DBUILDING_DTRACE -nostdinc -I$S/cddl/dev/fbt/${MACHINE_CPUARCH} -I$S/cddl/dev/fbt -I$S/cddl/compat/opensolaris -I$S/cddl/contrib/opensolaris/uts/common -I$S ${CDDL_CFLAGS}
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
FBT_CFLAGS+= -I$S/cddl/dev/fbt/x86
.endif
-FBT_C= ${CC} -c ${FBT_CFLAGS} ${CDDL_CFLAGS} ${WERROR} ${PROF} ${.IMPSRC}
+FBT_C= ${CC} -c ${FBT_CFLAGS} ${WERROR} ${PROF} ${.IMPSRC}
.if ${MK_CTF} != "no"
NORMAL_CTFCONVERT= ${CTFCONVERT} ${CTFFLAGS} ${.TARGET}
diff --git a/sys/conf/options b/sys/conf/options
index 346e22e..4938dda 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -650,6 +650,7 @@ BKTR_NEW_MSP34XX_DRIVER opt_bktr.h
# Options for uart(4)
UART_PPS_ON_CTS opt_uart.h
UART_POLL_FREQ opt_uart.h
+UART_DEV_TOLERANCE_PCT opt_uart.h
# options for bus/device framework
BUS_DEBUG opt_bus.h
diff --git a/sys/conf/options.powerpc b/sys/conf/options.powerpc
index 4926947..27f2952 100644
--- a/sys/conf/options.powerpc
+++ b/sys/conf/options.powerpc
@@ -21,6 +21,7 @@ GFB_NO_MODE_CHANGE opt_gfb.h
MPC85XX opt_platform.h
POWERMAC opt_platform.h
PS3 opt_platform.h
+QORIQ_DPAA opt_platform.h
MAMBO
PSERIES
PSIM
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 024a54f..7f46573 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -1282,8 +1282,16 @@ pmc_process_csw_in(struct thread *td)
*/
if (PMC_TO_MODE(pm) == PMC_MODE_TS) {
mtx_pool_lock_spin(pmc_mtxpool, pm);
+
+ /*
+ * Use the saved value calculated after the most recent
+ * thread switch out to start this counter. Reset
+ * the saved count in case another thread from this
+ * process switches in before any threads switch out.
+ */
newvalue = PMC_PCPU_SAVED(cpu,ri) =
pp->pp_pmcs[ri].pp_pmcval;
+ pp->pp_pmcs[ri].pp_pmcval = pm->pm_sc.pm_reloadcount;
mtx_pool_unlock_spin(pmc_mtxpool, pm);
} else {
KASSERT(PMC_TO_MODE(pm) == PMC_MODE_TC,
@@ -1431,31 +1439,43 @@ pmc_process_csw_out(struct thread *td)
pcd->pcd_read_pmc(cpu, adjri, &newvalue);
- tmp = newvalue - PMC_PCPU_SAVED(cpu,ri);
-
- PMCDBG3(CSW,SWO,1,"cpu=%d ri=%d tmp=%jd", cpu, ri,
- tmp);
-
if (mode == PMC_MODE_TS) {
+ PMCDBG3(CSW,SWO,1,"cpu=%d ri=%d tmp=%jd (samp)",
+ cpu, ri, PMC_PCPU_SAVED(cpu,ri) - newvalue);
/*
* For sampling process-virtual PMCs,
- * we expect the count to be
- * decreasing as the 'value'
- * programmed into the PMC is the
- * number of events to be seen till
- * the next sampling interrupt.
+ * newvalue is the number of events to be seen
+ * until the next sampling interrupt.
+ * We can just add the events left from this
+ * invocation to the counter, then adjust
+ * in case we overflow our range.
+ *
+ * (Recall that we reload the counter every
+ * time we use it.)
*/
- if (tmp < 0)
- tmp += pm->pm_sc.pm_reloadcount;
mtx_pool_lock_spin(pmc_mtxpool, pm);
- pp->pp_pmcs[ri].pp_pmcval -= tmp;
- if ((int64_t) pp->pp_pmcs[ri].pp_pmcval <= 0)
- pp->pp_pmcs[ri].pp_pmcval +=
+
+ pp->pp_pmcs[ri].pp_pmcval += newvalue;
+ if (pp->pp_pmcs[ri].pp_pmcval >
+ pm->pm_sc.pm_reloadcount)
+ pp->pp_pmcs[ri].pp_pmcval -=
pm->pm_sc.pm_reloadcount;
+ KASSERT(pp->pp_pmcs[ri].pp_pmcval > 0 &&
+ pp->pp_pmcs[ri].pp_pmcval <=
+ pm->pm_sc.pm_reloadcount,
+ ("[pmc,%d] pp_pmcval outside of expected "
+ "range cpu=%d ri=%d pp_pmcval=%jx "
+ "pm_reloadcount=%jx", __LINE__, cpu, ri,
+ pp->pp_pmcs[ri].pp_pmcval,
+ pm->pm_sc.pm_reloadcount));
mtx_pool_unlock_spin(pmc_mtxpool, pm);
} else {
+ tmp = newvalue - PMC_PCPU_SAVED(cpu,ri);
+
+ PMCDBG3(CSW,SWO,1,"cpu=%d ri=%d tmp=%jd (count)",
+ cpu, ri, tmp);
/*
* For counting process-virtual PMCs,
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 9b8ce72..fed5a6e 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -64,19 +64,13 @@ __FBSDID("$FreeBSD$");
* General defines
*/
#define MBOX_DELAY_COUNT 1000000 / 100
-#define ISP_MARK_PORTDB(a, b, c) \
- do { \
- isp_prt(isp, ISP_LOG_SANCFG, \
- "Chan %d ISP_MARK_PORTDB@LINE %d", (b), __LINE__); \
- isp_mark_portdb((a), (b), (c)); \
- } while (0)
/*
* Local static data
*/
static const char fconf[] = "Chan %d PortDB[%d] changed:\n current =(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)\n database=(0x%x@0x%06x 0x%08x%08x 0x%08x%08x)";
static const char notresp[] = "Not RESPONSE in RESPONSE Queue (type 0x%x) @ idx %d (next %d) nlooked %d";
-static const char topology[] = "Chan %d WWPN 0x%08x%08x PortID 0x%06x handle 0x%x, Connection '%s'";
+static const char topology[] = "Chan %d WWPN 0x%08x%08x PortID 0x%06x LoopID 0x%x Connection '%s'";
static const char bun[] = "bad underrun (count %d, resid %d, status %s)";
static const char lipd[] = "Chan %d LIP destroyed %d active commands";
static const char sacq[] = "unable to acquire scratch area";
@@ -131,8 +125,9 @@ static int isp_scan_fabric(ispsoftc_t *, int);
static int isp_login_device(ispsoftc_t *, int, uint32_t, isp_pdb_t *, uint16_t *);
static int isp_register_fc4_type(ispsoftc_t *, int);
static int isp_register_fc4_type_24xx(ispsoftc_t *, int);
+static int isp_register_fc4_features_24xx(ispsoftc_t *, int);
static uint16_t isp_next_handle(ispsoftc_t *, uint16_t *);
-static void isp_fw_state(ispsoftc_t *, int);
+static int isp_fw_state(ispsoftc_t *, int);
static void isp_mboxcmd_qnw(ispsoftc_t *, mbreg_t *, int);
static void isp_mboxcmd(ispsoftc_t *, mbreg_t *);
@@ -149,6 +144,19 @@ static void isp_parse_nvram_12160(ispsoftc_t *, int, uint8_t *);
static void isp_parse_nvram_2100(ispsoftc_t *, uint8_t *);
static void isp_parse_nvram_2400(ispsoftc_t *, uint8_t *);
+static void
+isp_change_fw_state(ispsoftc_t *isp, int chan, int state)
+{
+ fcparam *fcp = FCPARAM(isp, chan);
+
+ if (fcp->isp_fwstate == state)
+ return;
+ isp_prt(isp, ISP_LOGCONFIG|ISP_LOG_SANCFG,
+ "Chan %d Firmware state <%s->%s>", chan,
+ isp_fc_fw_statename(fcp->isp_fwstate), isp_fc_fw_statename(state));
+ fcp->isp_fwstate = state;
+}
+
/*
* Reset Hardware.
*
@@ -1267,8 +1275,9 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults)
isp->isp_nchan = 1;
}
}
- for (i = 0; i < isp->isp_nchan; i++) {
- isp_fw_state(isp, i);
+ if (IS_FC(isp)) {
+ for (i = 0; i < isp->isp_nchan; i++)
+ isp_change_fw_state(isp, i, FW_CONFIG_WAIT);
}
if (isp->isp_dead) {
isp_shutdown(isp);
@@ -2187,7 +2196,7 @@ isp_fibre_init_2400(ispsoftc_t *isp)
size_t amt = 0;
uint8_t *off;
- vpinfo.vp_global_options = 0;
+ vpinfo.vp_global_options = ICB2400_VPGOPT_GEN_RIDA;
if (ISP_CAP_VP0(isp)) {
vpinfo.vp_global_options |= ICB2400_VPGOPT_VP0_DECOUPLE;
vpinfo.vp_count = isp->isp_nchan;
@@ -2207,7 +2216,8 @@ isp_fibre_init_2400(ispsoftc_t *isp)
ISP_MEMZERO(&pi, sizeof (pi));
fcp2 = FCPARAM(isp, chan);
if (fcp2->role != ISP_ROLE_NONE) {
- pi.vp_port_options = ICB2400_VPOPT_ENABLED;
+ pi.vp_port_options = ICB2400_VPOPT_ENABLED |
+ ICB2400_VPOPT_ENA_SNSLOGIN;
if (fcp2->role & ISP_ROLE_INITIATOR)
pi.vp_port_options |= ICB2400_VPOPT_INI_ENABLE;
if ((fcp2->role & ISP_ROLE_TARGET) == 0)
@@ -2576,7 +2586,10 @@ isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb, int dolock)
pdb->portid = BITS2WORD_24XX(un.bill.pdb_portid_bits);
ISP_MEMCPY(pdb->portname, un.bill.pdb_portname, 8);
ISP_MEMCPY(pdb->nodename, un.bill.pdb_nodename, 8);
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x", chan, id, pdb->portid, un.bill.pdb_flags, un.bill.pdb_curstate);
+ isp_prt(isp, ISP_LOGDEBUG1,
+ "Chan %d handle 0x%x Port 0x%06x flags 0x%x curstate %x",
+ chan, id, pdb->portid, un.bill.pdb_flags,
+ un.bill.pdb_curstate);
if (un.bill.pdb_curstate < PDB2400_STATE_PLOGI_DONE || un.bill.pdb_curstate > PDB2400_STATE_LOGGED_IN) {
mbs.param[0] = MBOX_NOT_LOGGED_IN;
if (dolock) {
@@ -2591,6 +2604,8 @@ isp_getpdb(ispsoftc_t *isp, int chan, uint16_t id, isp_pdb_t *pdb, int dolock)
pdb->portid = BITS2WORD(un.fred.pdb_portid_bits);
ISP_MEMCPY(pdb->portname, un.fred.pdb_portname, 8);
ISP_MEMCPY(pdb->nodename, un.fred.pdb_nodename, 8);
+ isp_prt(isp, ISP_LOGDEBUG1,
+ "Chan %d handle 0x%x Port 0x%06x", chan, id, pdb->portid);
}
if (dolock) {
FC_SCRATCH_RELEASE(isp, chan);
@@ -2674,7 +2689,7 @@ static void
isp_dump_chip_portdb(ispsoftc_t *isp, int chan, int dolock)
{
isp_pdb_t pdb;
- int lim, loopid;
+ uint16_t lim, nphdl;
isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d chip port dump", chan);
if (ISP_CAP_2KLOGIN(isp)) {
@@ -2682,40 +2697,35 @@ isp_dump_chip_portdb(ispsoftc_t *isp, int chan, int dolock)
} else {
lim = NPH_MAX;
}
- for (loopid = 0; loopid != lim; loopid++) {
- if (isp_getpdb(isp, chan, loopid, &pdb, dolock)) {
+ for (nphdl = 0; nphdl != lim; nphdl++) {
+ if (isp_getpdb(isp, chan, nphdl, &pdb, dolock)) {
continue;
}
- isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Loopid 0x%04x "
+ isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGINFO, "Chan %d Handle 0x%04x "
"PortID 0x%06x WWPN 0x%02x%02x%02x%02x%02x%02x%02x%02x",
- chan, loopid, pdb.portid, pdb.portname[0], pdb.portname[1],
+ chan, nphdl, pdb.portid, pdb.portname[0], pdb.portname[1],
pdb.portname[2], pdb.portname[3], pdb.portname[4],
pdb.portname[5], pdb.portname[6], pdb.portname[7]);
}
}
static uint64_t
-isp_get_wwn(ispsoftc_t *isp, int chan, int loopid, int nodename)
+isp_get_wwn(ispsoftc_t *isp, int chan, int nphdl, int nodename)
{
uint64_t wwn = INI_NONE;
- fcparam *fcp = FCPARAM(isp, chan);
mbreg_t mbs;
- if (fcp->isp_fwstate < FW_READY ||
- fcp->isp_loopstate < LOOP_PDB_RCVD) {
- return (wwn);
- }
MBSINIT(&mbs, MBOX_GET_PORT_NAME,
MBLOGALL & ~MBLOGMASK(MBOX_COMMAND_PARAM_ERROR), 500000);
if (ISP_CAP_2KLOGIN(isp)) {
- mbs.param[1] = loopid;
+ mbs.param[1] = nphdl;
if (nodename) {
mbs.param[10] = 1;
}
mbs.param[9] = chan;
} else {
mbs.ibitm = 3;
- mbs.param[1] = loopid << 8;
+ mbs.param[1] = nphdl << 8;
if (nodename) {
mbs.param[1] |= 1;
}
@@ -2756,30 +2766,29 @@ static int
isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
{
mbreg_t mbs;
- int check_for_fabric, r;
- uint8_t lwfs;
- int loopid;
+ int r;
+ uint16_t nphdl;
fcparam *fcp;
- fcportdb_t *lp;
isp_pdb_t pdb;
NANOTIME_T hra, hrb;
fcp = FCPARAM(isp, chan);
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC Link Test Entry", chan);
- ISP_MARK_PORTDB(isp, chan, 1);
+ /* Mark port database entries for following scan. */
+ isp_mark_portdb(isp, chan, 1);
+
+ if (fcp->isp_loopstate >= LOOP_LTEST_DONE)
+ return (0);
+
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test", chan);
+ fcp->isp_loopstate = LOOP_TESTING_LINK;
/*
* Wait up to N microseconds for F/W to go to a ready state.
*/
- lwfs = FW_CONFIG_WAIT;
GET_NANOTIME(&hra);
while (1) {
- isp_fw_state(isp, chan);
- if (lwfs != fcp->isp_fwstate) {
- isp_prt(isp, ISP_LOGCONFIG|ISP_LOG_SANCFG, "Chan %d Firmware State <%s->%s>", chan, isp_fc_fw_statename((int)lwfs), isp_fc_fw_statename((int)fcp->isp_fwstate));
- lwfs = fcp->isp_fwstate;
- }
+ isp_change_fw_state(isp, chan, isp_fw_state(isp, chan));
if (fcp->isp_fwstate == FW_READY) {
break;
}
@@ -2793,7 +2802,9 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
* If we haven't gone to 'ready' state, return.
*/
if (fcp->isp_fwstate != FW_READY) {
- isp_prt(isp, ISP_LOG_SANCFG, "%s: chan %d not at FW_READY state", __func__, chan);
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d Firmware is not ready (%s)",
+ chan, isp_fc_fw_statename(fcp->isp_fwstate));
return (-1);
}
@@ -2814,7 +2825,14 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
}
if (IS_2100(isp)) {
- fcp->isp_topo = TOPO_NL_PORT;
+ /*
+ * Don't bother with fabric if we are using really old
+ * 2100 firmware. It's just not worth it.
+ */
+ if (ISP_FW_NEWER_THAN(isp, 1, 15, 37))
+ fcp->isp_topo = TOPO_FL_PORT;
+ else
+ fcp->isp_topo = TOPO_NL_PORT;
} else {
int topo = (int) mbs.param[6];
if (topo < TOPO_NL_PORT || topo > TOPO_PTP_STUB) {
@@ -2824,22 +2842,6 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
}
fcp->isp_portid = mbs.param[2] | (mbs.param[3] << 16);
- if (IS_2100(isp)) {
- /*
- * Don't bother with fabric if we are using really old
- * 2100 firmware. It's just not worth it.
- */
- if (ISP_FW_NEWER_THAN(isp, 1, 15, 37)) {
- check_for_fabric = 1;
- } else {
- check_for_fabric = 0;
- }
- } else if (fcp->isp_topo == TOPO_FL_PORT || fcp->isp_topo == TOPO_F_PORT) {
- check_for_fabric = 1;
- } else {
- check_for_fabric = 0;
- }
-
/*
* Check to make sure we got a valid loopid
* The 24XX seems to mess this up for multiple channels.
@@ -2859,72 +2861,33 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
}
if (alpa_map[i] && fcp->isp_loopid != i) {
isp_prt(isp, ISP_LOG_SANCFG,
- "Chan %d deriving loopid %d from AL_PA map (AL_PA 0x%x) and ignoring returned value %d (AL_PA 0x%x)",
+ "Chan %d Deriving loopid %d from AL_PA map (AL_PA 0x%x) and ignoring returned value %d (AL_PA 0x%x)",
chan, i, alpa_map[i], fcp->isp_loopid, alpa);
fcp->isp_loopid = i;
}
}
}
-
- if (IS_24XX(isp)) { /* XXX SHOULDN'T THIS BE FOR 2K F/W? XXX */
- loopid = NPH_FL_ID;
- } else {
- loopid = FL_ID;
- }
- if (check_for_fabric) {
- r = isp_getpdb(isp, chan, loopid, &pdb, 1);
- if (r && (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT)) {
- isp_prt(isp, ISP_LOGWARN, "fabric topology but cannot get info about fabric controller (0x%x)", r);
- fcp->isp_topo = TOPO_PTP_STUB;
- }
- } else {
- r = -1;
- }
- if (r == 0) {
- if (IS_2100(isp)) {
- fcp->isp_topo = TOPO_FL_PORT;
- }
- if (pdb.portid == 0) {
- /*
- * Crock.
- */
- fcp->isp_topo = TOPO_NL_PORT;
+ if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
+ nphdl = IS_24XX(isp) ? NPH_FL_ID : FL_ID;
+ r = isp_getpdb(isp, chan, nphdl, &pdb, 1);
+ if (r != 0 || pdb.portid == 0) {
+ if (IS_2100(isp)) {
+ fcp->isp_topo = TOPO_NL_PORT;
+ } else {
+ isp_prt(isp, ISP_LOGWARN,
+ "fabric topology, but cannot get info about fabric controller (0x%x)", r);
+ fcp->isp_topo = TOPO_PTP_STUB;
+ }
goto not_on_fabric;
}
- /*
- * Save the Fabric controller's port database entry.
- */
- lp = &fcp->portdb[FL_ID];
- lp->state = FC_PORTDB_STATE_PENDING_VALID;
- MAKE_WWN_FROM_NODE_NAME(lp->node_wwn, pdb.nodename);
- MAKE_WWN_FROM_NODE_NAME(lp->port_wwn, pdb.portname);
- lp->prli_word3 = pdb.prli_word3;
- lp->portid = pdb.portid;
- lp->handle = pdb.handle;
- lp->new_portid = lp->portid;
- lp->new_prli_word3 = lp->prli_word3;
if (IS_24XX(isp)) {
- if (check_for_fabric) {
- /*
- * The mbs is still hanging out from the MBOX_GET_LOOP_ID above.
- */
- fcp->isp_fabric_params = mbs.param[7];
- } else {
- fcp->isp_fabric_params = 0;
- }
- if (chan) {
- fcp->isp_sns_hdl = NPH_RESERVED - chan;
- r = isp_plogx(isp, chan, fcp->isp_sns_hdl, SNS_PORT_ID, PLOGX_FLG_CMD_PLOGI | PLOGX_FLG_COND_PLOGI | PLOGX_FLG_SKIP_PRLI, 0);
- if (r) {
- isp_prt(isp, ISP_LOGWARN, "%s: Chan %d cannot log into SNS", __func__, chan);
- return (-1);
- }
- } else {
- fcp->isp_sns_hdl = NPH_SNS_ID;
- }
+ fcp->isp_fabric_params = mbs.param[7];
+ fcp->isp_sns_hdl = NPH_SNS_ID;
r = isp_register_fc4_type_24xx(isp, chan);
+ if (r == 0)
+ isp_register_fc4_features_24xx(isp, chan);
} else {
fcp->isp_sns_hdl = SNS_ID;
r = isp_register_fc4_type(isp, chan);
@@ -2933,11 +2896,9 @@ isp_fclink_test(ispsoftc_t *isp, int chan, int usdelay)
isp_prt(isp, ISP_LOGWARN|ISP_LOG_SANCFG, "%s: register fc4 type failed", __func__);
return (-1);
}
- } else {
-not_on_fabric:
- fcp->portdb[FL_ID].state = FC_PORTDB_STATE_NIL;
}
+not_on_fabric:
fcp->isp_gbspeed = 1;
if (IS_23XX(isp) || IS_24XX(isp)) {
MBSINIT(&mbs, MBOX_GET_SET_DATA_RATE, MBLOGALL, 3000000);
@@ -2961,11 +2922,12 @@ not_on_fabric:
}
}
+ fcp->isp_loopstate = LOOP_LTEST_DONE;
/*
* Announce ourselves, too.
*/
isp_prt(isp, ISP_LOG_SANCFG|ISP_LOGCONFIG, topology, chan, (uint32_t) (fcp->isp_wwpn >> 32), (uint32_t) fcp->isp_wwpn, fcp->isp_portid, fcp->isp_loopid, isp_fc_toponame(fcp));
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC Link Test Complete", chan);
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC link test done", chan);
return (0);
}
@@ -2975,19 +2937,10 @@ not_on_fabric:
* At this point, we've scanned the local loop (if any) and the fabric
* and performed fabric logins on all new devices.
*
- * Our task here is to go through our port database and remove any entities
+ * Our task here is to go through our port database removing any entities
* that are still marked probational (issuing PLOGO for ones which we had
- * PLOGI'd into) or are dead.
- *
- * Our task here is to also check policy to decide whether devices which
- * have *changed* in some way should still be kept active. For example,
- * if a device has just changed PortID, we can either elect to treat it
- * as an old device or as a newly arrived device (and notify the outer
- * layer appropriately).
- *
- * We also do initiator map target id assignment here for new initiator
- * devices and refresh old ones ot make sure that they point to the correct
- * entities.
+ * PLOGI'd into) or are dead, and notifying upper layers about new/changed
+ * devices.
*/
static int
isp_pdb_sync(ispsoftc_t *isp, int chan)
@@ -2996,44 +2949,14 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
fcportdb_t *lp;
uint16_t dbidx;
- if (fcp->isp_loopstate == LOOP_READY) {
- return (0);
- }
-
- /*
- * Make sure we're okay for doing this right now.
- */
- if (fcp->isp_loopstate != LOOP_PDB_RCVD &&
- fcp->isp_loopstate != LOOP_FSCAN_DONE &&
- fcp->isp_loopstate != LOOP_LSCAN_DONE) {
- isp_prt(isp, ISP_LOGWARN, "isp_pdb_sync: bad loopstate %d",
- fcp->isp_loopstate);
+ if (fcp->isp_loopstate < LOOP_FSCAN_DONE) {
return (-1);
}
-
- if (fcp->isp_topo == TOPO_FL_PORT ||
- fcp->isp_topo == TOPO_NL_PORT ||
- fcp->isp_topo == TOPO_N_PORT) {
- if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
- if (isp_scan_loop(isp, chan) != 0) {
- isp_prt(isp, ISP_LOGWARN,
- "isp_pdb_sync: isp_scan_loop failed");
- return (-1);
- }
- }
- }
-
- if (fcp->isp_topo == TOPO_F_PORT || fcp->isp_topo == TOPO_FL_PORT) {
- if (fcp->isp_loopstate < LOOP_FSCAN_DONE) {
- if (isp_scan_fabric(isp, chan) != 0) {
- isp_prt(isp, ISP_LOGWARN,
- "isp_pdb_sync: isp_scan_fabric failed");
- return (-1);
- }
- }
+ if (fcp->isp_loopstate > LOOP_SYNCING_PDB) {
+ return (0);
}
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Synchronizing PDBs", chan);
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync", chan);
fcp->isp_loopstate = LOOP_SYNCING_PDB;
@@ -3087,10 +3010,6 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
lp->prli_word3 = lp->new_prli_word3;
lp->state = FC_PORTDB_STATE_VALID;
isp_async(isp, ISPASYNC_DEV_STAYED, chan, lp);
- if (dbidx != FL_ID) {
- lp->new_prli_word3 = 0;
- lp->new_portid = 0;
- }
break;
case FC_PORTDB_STATE_ZOMBIE:
break;
@@ -3109,6 +3028,7 @@ isp_pdb_sync(ispsoftc_t *isp, int chan)
*/
fcp->loop_seen_once = 1;
fcp->isp_loopstate = LOOP_READY;
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC PDB sync done", chan);
return (0);
}
@@ -3125,36 +3045,34 @@ isp_scan_loop(ispsoftc_t *isp, int chan)
uint16_t handles[LOCAL_LOOP_LIM];
uint16_t handle;
- if (fcp->isp_fwstate < FW_READY ||
- fcp->isp_loopstate < LOOP_PDB_RCVD) {
+ if (fcp->isp_loopstate < LOOP_LTEST_DONE) {
return (-1);
}
if (fcp->isp_loopstate > LOOP_SCANNING_LOOP) {
return (0);
}
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan", chan);
if (fcp->isp_topo != TOPO_NL_PORT && fcp->isp_topo != TOPO_FL_PORT &&
fcp->isp_topo != TOPO_N_PORT) {
isp_prt(isp, ISP_LOG_SANCFG,
- "Chan %d no loop topology to scan", chan);
+ "Chan %d FC loop scan done (no loop)", chan);
fcp->isp_loopstate = LOOP_LSCAN_DONE;
return (0);
}
-
fcp->isp_loopstate = LOOP_SCANNING_LOOP;
lim = LOCAL_LOOP_LIM;
r = isp_gethandles(isp, chan, handles, &lim, 1, 1);
if (r != 0) {
isp_prt(isp, ISP_LOG_SANCFG,
- "Chan %d getting list of handles failed with %x", chan, r);
+ "Chan %d Getting list of handles failed with %x", chan, r);
fail:
- ISP_MARK_PORTDB(isp, chan, 1);
isp_prt(isp, ISP_LOG_SANCFG,
- "Chan %d FC scan loop DONE (bad)", chan);
+ "Chan %d FC loop scan done (bad)", chan);
return (-1);
}
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop -- %d ports",
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Got %d handles",
chan, lim);
/*
@@ -3167,7 +3085,7 @@ fail:
* Don't scan "special" ids.
*/
if (ISP_CAP_2KLOGIN(isp)) {
- if (handle >= NPH_RESERVED - isp->isp_nchan)
+ if (handle >= NPH_RESERVED)
continue;
} else {
if (handle >= FL_ID && handle <= SNS_ID)
@@ -3180,8 +3098,12 @@ fail:
*/
if (IS_2100(isp) || IS_2200(isp)) {
uint64_t node_wwn = isp_get_wwn(isp, chan, handle, 1);
- if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
- goto fail;
+ if (fcp->isp_loopstate < LOOP_SCANNING_LOOP) {
+abort:
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d FC loop scan done (abort)", chan);
+ return (-1);
+ }
if (node_wwn == INI_NONE) {
continue;
}
@@ -3193,15 +3115,15 @@ fail:
r = isp_getpdb(isp, chan, handle, &pdb, 1);
if (r != 0) {
isp_prt(isp, ISP_LOGDEBUG1,
- "Chan %d FC scan loop handle %d returned %x",
+ "Chan %d FC Scan Loop handle %d returned %x",
chan, handle, r);
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
- goto fail;
+ goto abort;
continue;
}
if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
- goto fail;
+ goto abort;
/*
* On *very* old 2100 firmware we would end up sometimes
@@ -3287,7 +3209,9 @@ fail:
lp->new_portid = tmp.portid;
lp->new_prli_word3 = tmp.prli_word3;
lp->state = FC_PORTDB_STATE_PENDING_VALID;
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Loop Port 0x%06x@0x%04x Pending Valid", chan, tmp.portid, tmp.handle);
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d Loop port 0x%06x@0x%04x now pending valid",
+ chan, tmp.portid, tmp.handle);
continue;
}
@@ -3301,7 +3225,9 @@ fail:
* Claim that this has changed and let somebody else
* decide what to do.
*/
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Loop Port 0x%06x@0x%04x changed", chan, tmp.portid, tmp.handle);
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d Loop port 0x%06x@0x%04x changed",
+ chan, tmp.portid, tmp.handle);
lp->state = FC_PORTDB_STATE_CHANGED;
lp->new_portid = tmp.portid;
lp->new_prli_word3 = tmp.prli_word3;
@@ -3332,10 +3258,14 @@ fail:
lp->handle = tmp.handle;
lp->port_wwn = tmp.port_wwn;
lp->node_wwn = tmp.node_wwn;
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Loop Port 0x%06x@0x%04x is New Entry", chan, tmp.portid, tmp.handle);
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d Loop port 0x%06x@0x%04x is a new entry",
+ chan, tmp.portid, tmp.handle);
}
+ if (fcp->isp_loopstate < LOOP_SCANNING_LOOP)
+ goto abort;
fcp->isp_loopstate = LOOP_LSCAN_DONE;
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC scan loop DONE", chan);
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC loop scan done", chan);
return (0);
}
@@ -3516,53 +3446,53 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
{
fcparam *fcp = FCPARAM(isp, chan);
uint32_t portid;
- uint16_t handle, loopid;
+ uint16_t nphdl;
isp_pdb_t pdb;
int portidx, portlim, r;
sns_gid_ft_rsp_t *rs0, *rs1;
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC Scan Fabric", chan);
- if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_LSCAN_DONE) {
+ if (fcp->isp_loopstate < LOOP_LSCAN_DONE) {
return (-1);
}
if (fcp->isp_loopstate > LOOP_SCANNING_FABRIC) {
return (0);
}
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan", chan);
if (fcp->isp_topo != TOPO_FL_PORT && fcp->isp_topo != TOPO_F_PORT) {
fcp->isp_loopstate = LOOP_FSCAN_DONE;
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC Scan Fabric Done (no fabric)", chan);
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d FC fabric scan done (no fabric)", chan);
return (0);
}
-
fcp->isp_loopstate = LOOP_SCANNING_FABRIC;
+
if (FC_SCRATCH_ACQUIRE(isp, chan)) {
isp_prt(isp, ISP_LOGERR, sacq);
- ISP_MARK_PORTDB(isp, chan, 1);
+fail:
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d FC fabric scan done (bad)", chan);
return (-1);
}
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+abort:
FC_SCRATCH_RELEASE(isp, chan);
- ISP_MARK_PORTDB(isp, chan, 1);
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d FC fabric scan done (abort)", chan);
return (-1);
}
/*
* Make sure we still are logged into the fabric controller.
*/
- if (IS_24XX(isp)) { /* XXX SHOULDN'T THIS BE TRUE FOR 2K F/W? XXX */
- loopid = NPH_FL_ID;
- } else {
- loopid = FL_ID;
- }
- r = isp_getpdb(isp, chan, loopid, &pdb, 0);
+ nphdl = IS_24XX(isp) ? NPH_FL_ID : FL_ID;
+ r = isp_getpdb(isp, chan, nphdl, &pdb, 0);
if ((r & 0xffff) == MBOX_NOT_LOGGED_IN) {
isp_dump_chip_portdb(isp, chan, 0);
}
if (r) {
- fcp->isp_loopstate = LOOP_PDB_RCVD;
+ fcp->isp_loopstate = LOOP_LTEST_DONE;
FC_SCRATCH_RELEASE(isp, chan);
- ISP_MARK_PORTDB(isp, chan, 1);
- return (-1);
+ goto fail;
}
if (IS_24XX(isp)) {
@@ -3572,9 +3502,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
}
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp, chan);
- ISP_MARK_PORTDB(isp, chan, 1);
- return (-1);
+ goto abort;
}
if (r > 0) {
@@ -3582,7 +3510,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
FC_SCRATCH_RELEASE(isp, chan);
return (0);
} else if (r < 0) {
- fcp->isp_loopstate = LOOP_PDB_RCVD; /* try again */
+ fcp->isp_loopstate = LOOP_LTEST_DONE; /* try again */
FC_SCRATCH_RELEASE(isp, chan);
return (0);
}
@@ -3592,9 +3520,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
rs1 = (sns_gid_ft_rsp_t *) ((uint8_t *)fcp->isp_scratch+OGPOFF);
isp_get_gid_ft_response(isp, rs0, rs1, NGENT);
if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp, chan);
- ISP_MARK_PORTDB(isp, chan, 1);
- return (-1);
+ goto abort;
}
if (rs1->snscb_cthdr.ct_cmd_resp != LS_ACC) {
int level;
@@ -3612,12 +3538,6 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
return (0);
}
-
- /*
- * If we get this far, we certainly still have the fabric controller.
- */
- fcp->portdb[FL_ID].state = FC_PORTDB_STATE_PENDING_VALID;
-
/*
* Go through the list and remove duplicate port ids.
*/
@@ -3639,7 +3559,7 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
}
portlim = portidx + 1;
isp_prt(isp, ISP_LOG_SANCFG,
- "Chan %d got %d ports back from name server", chan, portlim);
+ "Chan %d Got %d ports back from name server", chan, portlim);
for (portidx = 0; portidx < portlim; portidx++) {
int npidx;
@@ -3694,35 +3614,19 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
if (portid == 0) {
isp_prt(isp, ISP_LOG_SANCFG,
- "Chan %d skipping null PortID at idx %d",
+ "Chan %d Skipping null PortID at idx %d",
chan, portidx);
continue;
}
- /*
- * Skip ourselves here and on other channels. If we're
- * multi-id, we can't check the portids in other FCPARAM
- * arenas because the resolutions here aren't synchronized.
- * The best way to do this is to exclude looking at portids
- * that have the same domain and area code as our own
- * portid.
- */
- if (ISP_CAP_MULTI_ID(isp) && isp->isp_nchan > 1) {
- if ((portid >> 8) == (fcp->isp_portid >> 8)) {
- isp_prt(isp, ISP_LOG_SANCFG,
- "Chan %d skip PortID 0x%06x",
- chan, portid);
- continue;
- }
- } else if (portid == fcp->isp_portid) {
+ if (portid == fcp->isp_portid) {
isp_prt(isp, ISP_LOG_SANCFG,
- "Chan %d skip ourselves on @ PortID 0x%06x",
- chan, portid);
+ "Chan %d Skipping our PortID 0x%06x", chan, portid);
continue;
}
isp_prt(isp, ISP_LOG_SANCFG,
- "Chan %d Checking Fabric Port 0x%06x", chan, portid);
+ "Chan %d Checking fabric port 0x%06x", chan, portid);
/*
* We now search our Port Database for any
@@ -3767,10 +3671,8 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
*/
r = isp_getpdb(isp, chan, lp->handle, &pdb, 0);
- if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp, chan);
- ISP_MARK_PORTDB(isp, chan, 1);
- return (-1);
+ if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ goto abort;
}
if (r != 0) {
lp->new_portid = portid;
@@ -3814,19 +3716,14 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
&FCPARAM(isp, 0)->isp_lasthdl)) {
lp->new_portid = portid;
lp->state = FC_PORTDB_STATE_DEAD;
- if (fcp->isp_loopstate !=
+ if (fcp->isp_loopstate <
LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp, chan);
- ISP_MARK_PORTDB(isp, chan, 1);
- return (-1);
+ goto abort;
}
continue;
}
- if (fcp->isp_loopstate !=
- LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp, chan);
- ISP_MARK_PORTDB(isp, chan, 1);
- return (-1);
+ if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ goto abort;
}
MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
@@ -3860,10 +3757,14 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
lp->new_portid = portid;
lp->new_prli_word3 = nr;
if (pdb.portid != lp->portid || nr != lp->prli_word3 || handle_changed) {
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric Port 0x%06x changed", chan, portid);
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d Fabric port 0x%06x changed",
+ chan, portid);
lp->state = FC_PORTDB_STATE_CHANGED;
} else {
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric Port 0x%06x Now Pending Valid", chan, portid);
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d Fabric port 0x%06x now pending valid",
+ chan, portid);
lp->state = FC_PORTDB_STATE_PENDING_VALID;
}
continue;
@@ -3881,10 +3782,6 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
dbidx = MAX_FC_TARG;
for (lp = fcp->portdb; lp < &fcp->portdb[MAX_FC_TARG]; lp++) {
- if (lp >= &fcp->portdb[FL_ID] &&
- lp <= &fcp->portdb[SNS_ID]) {
- continue;
- }
if (lp->state == FC_PORTDB_STATE_NIL) {
if (dbidx == MAX_FC_TARG) {
dbidx = lp - fcp->portdb;
@@ -3930,20 +3827,16 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
*/
if (isp_login_device(isp, chan, portid, &pdb,
&FCPARAM(isp, 0)->isp_lasthdl)) {
- if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp, chan);
- ISP_MARK_PORTDB(isp, chan, 1);
- return (-1);
+ if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ goto abort;
}
continue;
}
- if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
- FC_SCRATCH_RELEASE(isp, chan);
- ISP_MARK_PORTDB(isp, chan, 1);
- return (-1);
+ if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ goto abort;
}
- handle = pdb.handle;
+ nphdl = pdb.handle;
MAKE_WWN_FROM_NODE_NAME(wwnn, pdb.nodename);
MAKE_WWN_FROM_NODE_NAME(wwpn, pdb.portname);
nr = pdb.prli_word3;
@@ -3954,9 +3847,6 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
* WWNN/WWPN duple
*/
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
- if (dbidx >= FL_ID && dbidx <= SNS_ID) {
- continue;
- }
if ((fcp->portdb[dbidx].node_wwn == wwnn ||
fcp->portdb[dbidx].node_wwn == 0) &&
fcp->portdb[dbidx].port_wwn == wwpn) {
@@ -3966,13 +3856,13 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
if (dbidx == MAX_FC_TARG) {
ISP_MEMZERO(lp, sizeof (fcportdb_t));
- lp->handle = handle;
+ lp->handle = nphdl;
lp->node_wwn = wwnn;
lp->port_wwn = wwpn;
lp->new_portid = portid;
lp->new_prli_word3 = nr;
lp->state = FC_PORTDB_STATE_NEW;
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric Port 0x%06x is a New Entry", chan, portid);
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Fabric port 0x%06x is a new entry", chan, portid);
continue;
}
@@ -3996,26 +3886,25 @@ isp_scan_fabric(ispsoftc_t *isp, int chan)
* are different, it maybe a changed device.
*/
lp = &fcp->portdb[dbidx];
- lp->handle = handle;
+ lp->handle = nphdl;
lp->node_wwn = wwnn;
lp->new_portid = portid;
lp->new_prli_word3 = nr;
if (lp->portid != portid || lp->prli_word3 != nr) {
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie Fabric Port 0x%06x Now Changed", chan, portid);
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie fabric port 0x%06x now changed", chan, portid);
lp->state = FC_PORTDB_STATE_CHANGED;
} else {
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie Fabric Port 0x%06x Now Pending Valid", chan, portid);
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d Zombie fabric port 0x%06x now pending valid", chan, portid);
lp->state = FC_PORTDB_STATE_PENDING_VALID;
}
}
- FC_SCRATCH_RELEASE(isp, chan);
- if (fcp->isp_loopstate != LOOP_SCANNING_FABRIC) {
- ISP_MARK_PORTDB(isp, chan, 1);
- return (-1);
+ if (fcp->isp_loopstate < LOOP_SCANNING_FABRIC) {
+ goto abort;
}
+ FC_SCRATCH_RELEASE(isp, chan);
fcp->isp_loopstate = LOOP_FSCAN_DONE;
- isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC Scan Fabric Done", chan);
+ isp_prt(isp, ISP_LOG_SANCFG, "Chan %d FC fabric scan done", chan);
return (0);
}
@@ -4079,7 +3968,7 @@ isp_login_device(ispsoftc_t *isp, int chan, uint32_t portid, isp_pdb_t *p, uint1
i = lim;
break;
} else if ((r & 0xffff) == MBOX_LOOP_ID_USED) {
- /* Try the next loop id. */
+ /* Try the next handle. */
handle = isp_next_handle(isp, ohp);
} else {
/* Give up. */
@@ -4266,6 +4155,125 @@ isp_register_fc4_type_24xx(ispsoftc_t *isp, int chan)
}
}
+static int
+isp_register_fc4_features_24xx(ispsoftc_t *isp, int chan)
+{
+ mbreg_t mbs;
+ fcparam *fcp = FCPARAM(isp, chan);
+ union {
+ isp_ct_pt_t plocal;
+ rff_id_t clocal;
+ uint8_t q[QENTRY_LEN];
+ } un;
+ isp_ct_pt_t *pt;
+ ct_hdr_t *ct;
+ rff_id_t *rp;
+ uint8_t *scp = fcp->isp_scratch;
+
+ if (FC_SCRATCH_ACQUIRE(isp, chan)) {
+ isp_prt(isp, ISP_LOGERR, sacq);
+ return (-1);
+ }
+
+ /*
+ * Build a Passthrough IOCB in memory.
+ */
+ ISP_MEMZERO(un.q, QENTRY_LEN);
+ pt = &un.plocal;
+ pt->ctp_header.rqs_entry_count = 1;
+ pt->ctp_header.rqs_entry_type = RQSTYPE_CT_PASSTHRU;
+ pt->ctp_handle = 0xffffffff;
+ pt->ctp_nphdl = fcp->isp_sns_hdl;
+ pt->ctp_cmd_cnt = 1;
+ pt->ctp_vpidx = ISP_GET_VPIDX(isp, chan);
+ pt->ctp_time = 1;
+ pt->ctp_rsp_cnt = 1;
+ pt->ctp_rsp_bcnt = sizeof (ct_hdr_t);
+ pt->ctp_cmd_bcnt = sizeof (rff_id_t);
+ pt->ctp_dataseg[0].ds_base = DMA_LO32(fcp->isp_scdma+XTXOFF);
+ pt->ctp_dataseg[0].ds_basehi = DMA_HI32(fcp->isp_scdma+XTXOFF);
+ pt->ctp_dataseg[0].ds_count = sizeof (rff_id_t);
+ pt->ctp_dataseg[1].ds_base = DMA_LO32(fcp->isp_scdma+IGPOFF);
+ pt->ctp_dataseg[1].ds_basehi = DMA_HI32(fcp->isp_scdma+IGPOFF);
+ pt->ctp_dataseg[1].ds_count = sizeof (ct_hdr_t);
+ isp_put_ct_pt(isp, pt, (isp_ct_pt_t *) &scp[CTXOFF]);
+ if (isp->isp_dblev & ISP_LOGDEBUG1) {
+ isp_print_bytes(isp, "IOCB CT Request", QENTRY_LEN, pt);
+ }
+
+ /*
+ * Build the CT header and command in memory.
+ *
+ * Note that the CT header has to end up as Big Endian format in memory.
+ */
+ ISP_MEMZERO(&un.clocal, sizeof (un.clocal));
+ ct = &un.clocal.rffid_hdr;
+ ct->ct_revision = CT_REVISION;
+ ct->ct_fcs_type = CT_FC_TYPE_FC;
+ ct->ct_fcs_subtype = CT_FC_SUBTYPE_NS;
+ ct->ct_cmd_resp = SNS_RFF_ID;
+ ct->ct_bcnt_resid = (sizeof (rff_id_t) - sizeof (ct_hdr_t)) >> 2;
+ rp = &un.clocal;
+ rp->rffid_portid[0] = fcp->isp_portid >> 16;
+ rp->rffid_portid[1] = fcp->isp_portid >> 8;
+ rp->rffid_portid[2] = fcp->isp_portid;
+ rp->rffid_fc4features = 0;
+ if (fcp->role & ISP_ROLE_TARGET)
+ rp->rffid_fc4features |= 1;
+ if (fcp->role & ISP_ROLE_INITIATOR)
+ rp->rffid_fc4features |= 2;
+ rp->rffid_fc4type = FC4_SCSI;
+ isp_put_rff_id(isp, rp, (rff_id_t *) &scp[XTXOFF]);
+ if (isp->isp_dblev & ISP_LOGDEBUG1) {
+ isp_print_bytes(isp, "CT Header", QENTRY_LEN, &scp[XTXOFF]);
+ }
+
+ ISP_MEMZERO(&scp[ZTXOFF], sizeof (ct_hdr_t));
+
+ MBSINIT(&mbs, MBOX_EXEC_COMMAND_IOCB_A64, MBLOGALL, 1000000);
+ mbs.param[1] = QENTRY_LEN;
+ mbs.param[2] = DMA_WD1(fcp->isp_scdma + CTXOFF);
+ mbs.param[3] = DMA_WD0(fcp->isp_scdma + CTXOFF);
+ mbs.param[6] = DMA_WD3(fcp->isp_scdma + CTXOFF);
+ mbs.param[7] = DMA_WD2(fcp->isp_scdma + CTXOFF);
+ MEMORYBARRIER(isp, SYNC_SFORDEV, XTXOFF, 2 * QENTRY_LEN, chan);
+ isp_mboxcmd(isp, &mbs);
+ if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ return (-1);
+ }
+ MEMORYBARRIER(isp, SYNC_SFORCPU, ZTXOFF, QENTRY_LEN, chan);
+ pt = &un.plocal;
+ isp_get_ct_pt(isp, (isp_ct_pt_t *) &scp[ZTXOFF], pt);
+ if (isp->isp_dblev & ISP_LOGDEBUG1) {
+ isp_print_bytes(isp, "IOCB response", QENTRY_LEN, pt);
+ }
+ if (pt->ctp_status) {
+ FC_SCRATCH_RELEASE(isp, chan);
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d Register FC4 Features CT Passthrough returned 0x%x",
+ chan, pt->ctp_status);
+ return (1);
+ }
+
+ isp_get_ct_hdr(isp, (ct_hdr_t *) &scp[IGPOFF], ct);
+ FC_SCRATCH_RELEASE(isp, chan);
+
+ if (ct->ct_cmd_resp == LS_RJT) {
+ isp_prt(isp, ISP_LOG_SANCFG|ISP_LOG_WARN1,
+ "Chan %d Register FC4 Features rejected", chan);
+ return (-1);
+ } else if (ct->ct_cmd_resp == LS_ACC) {
+ isp_prt(isp, ISP_LOG_SANCFG,
+ "Chan %d Register FC4 Features accepted", chan);
+ return (0);
+ } else {
+ isp_prt(isp, ISP_LOGWARN,
+ "Chan %d Register FC4 Features: 0x%x", chan, ct->ct_cmd_resp);
+ return (-1);
+ }
+}
+
static uint16_t
isp_next_handle(ispsoftc_t *isp, uint16_t *ohp)
{
@@ -4276,7 +4284,7 @@ isp_next_handle(ispsoftc_t *isp, uint16_t *ohp)
handle = *ohp;
if (ISP_CAP_2KLOGIN(isp)) {
minh = 0;
- maxh = NPH_RESERVED - isp->isp_nchan; /* Reserve for SNS */
+ maxh = NPH_RESERVED - 1;
} else {
minh = SNS_ID + 1;
maxh = NPH_MAX - 1;
@@ -4367,7 +4375,7 @@ isp_start(XS_T *xs)
/*
* Try again later.
*/
- if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) {
+ if (fcp->isp_loopstate != LOOP_READY) {
return (CMD_RQLATER);
}
@@ -5858,7 +5866,7 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
isp->isp_dead = 1;
isp->isp_state = ISP_CRASHED;
FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
- FCPARAM(isp, chan)->isp_fwstate = FW_CONFIG_WAIT;
+ isp_change_fw_state(isp, chan, FW_CONFIG_WAIT);
/*
* Were we waiting for a mailbox command to complete?
* If so, it's dead, so wake up the waiter.
@@ -5931,10 +5939,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
continue;
}
- fcp->isp_fwstate = FW_CONFIG_WAIT;
- fcp->isp_loopstate = LOOP_LIP_RCVD;
+ fcp->isp_loopstate = LOOP_NIL;
ISP_SET_SENDMARKER(isp, chan, 1);
- ISP_MARK_PORTDB(isp, chan, 1);
isp_async(isp, ISPASYNC_LIP, chan);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, chan, mbox)) {
@@ -5990,10 +5996,6 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
}
ISP_SET_SENDMARKER(isp, chan, 1);
-
- fcp->isp_fwstate = FW_CONFIG_WAIT;
- fcp->isp_loopstate = LOOP_LIP_RCVD;
- ISP_MARK_PORTDB(isp, chan, 1);
isp_async(isp, ISPASYNC_LOOP_UP, chan);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, chan, mbox)) {
@@ -6016,10 +6018,9 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
}
ISP_SET_SENDMARKER(isp, chan, 1);
- fcp->isp_fwstate = FW_CONFIG_WAIT;
fcp->isp_loopstate = LOOP_NIL;
- ISP_MARK_PORTDB(isp, chan, 1);
isp_async(isp, ISPASYNC_LOOP_DOWN, chan);
+
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, chan, mbox)) {
acked = 1;
@@ -6041,9 +6042,7 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
}
ISP_SET_SENDMARKER(isp, chan, 1);
- fcp->isp_fwstate = FW_CONFIG_WAIT;
fcp->isp_loopstate = LOOP_NIL;
- ISP_MARK_PORTDB(isp, chan, 1);
isp_async(isp, ISPASYNC_LOOP_RESET, chan);
#ifdef ISP_TARGET_MODE
if (isp_target_async(isp, chan, mbox)) {
@@ -6075,9 +6074,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
if (fcp->role == ISP_ROLE_NONE) {
continue;
}
- ISP_SET_SENDMARKER(isp, chan, 1);
- fcp->isp_loopstate = LOOP_PDB_RCVD;
- ISP_MARK_PORTDB(isp, chan, 1);
+ if (fcp->isp_loopstate > LOOP_LTEST_DONE)
+ fcp->isp_loopstate = LOOP_LTEST_DONE;
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_PDB, nphdl, nlstate, reason);
}
break;
@@ -6101,12 +6099,8 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
continue;
}
- if (fcp->isp_topo == TOPO_F_PORT) {
+ if (fcp->isp_loopstate > LOOP_LSCAN_DONE)
fcp->isp_loopstate = LOOP_LSCAN_DONE;
- } else {
- fcp->isp_loopstate = LOOP_PDB_RCVD;
- }
- ISP_MARK_PORTDB(isp, chan, 1);
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_SNS);
}
break;
@@ -6122,7 +6116,6 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
}
chan = 0;
mbox = ISP_READ(isp, OUTMAILBOX1);
- ISP_MARK_PORTDB(isp, chan, 1);
switch (mbox) {
case ISP_CONN_LOOP:
isp_prt(isp, ISP_LOGINFO,
@@ -6151,10 +6144,9 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
"Unknown connection mode (0x%x)", mbox);
break;
}
+ ISP_SET_SENDMARKER(isp, chan, 1);
+ FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL;
isp_async(isp, ISPASYNC_CHANGE_NOTIFY, chan, ISPASYNC_CHANGE_OTHER);
- FCPARAM(isp, chan)->sendmarker = 1;
- FCPARAM(isp, chan)->isp_fwstate = FW_CONFIG_WAIT;
- FCPARAM(isp, chan)->isp_loopstate = LOOP_LIP_RCVD;
break;
case ASYNC_RCV_ERR:
@@ -6192,6 +6184,9 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox)
static int
isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *optrp)
{
+ isp_ridacq_t rid;
+ int chan, c;
+
switch (type) {
case RQSTYPE_STATUS_CONT:
isp_prt(isp, ISP_LOG_WARN1, "Ignored Continuation Response");
@@ -6199,6 +6194,23 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt
case RQSTYPE_MARKER:
isp_prt(isp, ISP_LOG_WARN1, "Marker Response");
return (1);
+ case RQSTYPE_RPT_ID_ACQ:
+ isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
+ if (rid.ridacq_format == 0) {
+ for (chan = 0; chan < isp->isp_nchan; chan++) {
+ fcparam *fcp = FCPARAM(isp, chan);
+ if (fcp->role == ISP_ROLE_NONE)
+ continue;
+ c = (chan == 0) ? 127 : (chan - 1);
+ if (rid.ridacq_map[c / 16] & (1 << (c % 16)))
+ isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
+ chan, ISPASYNC_CHANGE_OTHER);
+ }
+ } else {
+ isp_async(isp, ISPASYNC_CHANGE_NOTIFY,
+ rid.ridacq_vp_index, ISPASYNC_CHANGE_OTHER);
+ }
+ return (1);
case RQSTYPE_ATIO:
case RQSTYPE_CTIO:
case RQSTYPE_ENABLE_LUN:
@@ -6219,15 +6231,6 @@ isp_handle_other_response(ispsoftc_t *isp, int type, isphdr_t *hp, uint32_t *opt
}
#endif
/* FALLTHROUGH */
- case RQSTYPE_RPT_ID_ACQ:
- if (IS_24XX(isp)) {
- isp_ridacq_t rid;
- isp_get_ridacq(isp, (isp_ridacq_t *)hp, &rid);
- if (rid.ridacq_format == 0) {
- }
- return (1);
- }
- /* FALLTHROUGH */
case RQSTYPE_REQUEST:
default:
ISP_DELAY(100);
@@ -7554,19 +7557,19 @@ out:
}
}
-static void
+static int
isp_fw_state(ispsoftc_t *isp, int chan)
{
if (IS_FC(isp)) {
mbreg_t mbs;
- fcparam *fcp = FCPARAM(isp, chan);
MBSINIT(&mbs, MBOX_GET_FW_STATE, MBLOGALL, 0);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
- fcp->isp_fwstate = mbs.param[1];
+ return (mbs.param[1]);
}
}
+ return (FW_ERROR);
}
static void
@@ -7936,7 +7939,7 @@ isp_reinit(ispsoftc_t *isp, int do_load_defaults)
isp_clear_commands(isp);
if (IS_FC(isp)) {
for (i = 0; i < isp->isp_nchan; i++)
- ISP_MARK_PORTDB(isp, i, -1);
+ isp_mark_portdb(isp, i, -1);
}
return (res);
}
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 0b9294f..cb356fe 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -604,7 +604,7 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td)
{
int needmarker;
struct isp_fc_tsk_mgmt *fct = (struct isp_fc_tsk_mgmt *) addr;
- uint16_t loopid;
+ uint16_t nphdl;
mbreg_t mbs;
if (IS_SCSI(isp)) {
@@ -618,7 +618,7 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td)
}
needmarker = retval = 0;
- loopid = fct->loopid;
+ nphdl = fct->loopid;
ISP_LOCK(isp);
if (IS_24XX(isp)) {
uint8_t local[QENTRY_LEN];
@@ -630,7 +630,7 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td)
for (i = 0; i < MAX_FC_TARG; i++) {
lp = &fcp->portdb[i];
- if (lp->handle == loopid) {
+ if (lp->handle == nphdl) {
break;
}
}
@@ -714,34 +714,34 @@ ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td)
} else {
MBSINIT(&mbs, 0, MBLOGALL, 0);
if (ISP_CAP_2KLOGIN(isp) == 0) {
- loopid <<= 8;
+ nphdl <<= 8;
}
switch (fct->action) {
case IPT_CLEAR_ACA:
mbs.param[0] = MBOX_CLEAR_ACA;
- mbs.param[1] = loopid;
+ mbs.param[1] = nphdl;
mbs.param[2] = fct->lun;
break;
case IPT_TARGET_RESET:
mbs.param[0] = MBOX_TARGET_RESET;
- mbs.param[1] = loopid;
+ mbs.param[1] = nphdl;
needmarker = 1;
break;
case IPT_LUN_RESET:
mbs.param[0] = MBOX_LUN_RESET;
- mbs.param[1] = loopid;
+ mbs.param[1] = nphdl;
mbs.param[2] = fct->lun;
needmarker = 1;
break;
case IPT_CLEAR_TASK_SET:
mbs.param[0] = MBOX_CLEAR_TASK_SET;
- mbs.param[1] = loopid;
+ mbs.param[1] = nphdl;
mbs.param[2] = fct->lun;
needmarker = 1;
break;
case IPT_ABORT_TASK_SET:
mbs.param[0] = MBOX_ABORT_TASK_SET;
- mbs.param[1] = loopid;
+ mbs.param[1] = nphdl;
mbs.param[2] = fct->lun;
needmarker = 1;
break;
@@ -1107,7 +1107,7 @@ isp_dump_atpd(ispsoftc_t *isp, tstate_t *tptr)
const char *states[8] = { "Free", "ATIO", "CAM", "CTIO", "LAST_CTIO", "PDON", "?6", "7" };
for (atp = tptr->atpool; atp < &tptr->atpool[ATPDPSIZE]; atp++) {
- xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u lun %u nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n",
+ xpt_print(tptr->owner, "ATP: [0x%x] origdlen %u bytes_xfrd %u lun %x nphdl 0x%04x s_id 0x%06x d_id 0x%06x oxid 0x%04x state %s\n",
atp->tag, atp->orig_datalen, atp->bytes_xfered, atp->lun, atp->nphdl, atp->sid, atp->portid, atp->oxid, states[atp->state & 0x7]);
}
}
@@ -2295,7 +2295,7 @@ isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
* should, in fact, get this, is in the case that we've
* run out of ATIOS.
*/
- xpt_print(tptr->owner, "no %s for lun %d from initiator %d\n", (atp == NULL && atiop == NULL)? "ATIOs *or* ATPS" :
+ xpt_print(tptr->owner, "no %s for lun %x from initiator %d\n", (atp == NULL && atiop == NULL)? "ATIOs *or* ATPS" :
((atp == NULL)? "ATPs" : "ATIOs"), aep->at_lun, aep->at_iid);
isp_endcmd(isp, aep, SCSI_STATUS_BUSY, 0);
if (atp) {
@@ -2347,7 +2347,7 @@ isp_handle_platform_atio(ispsoftc_t *isp, at_entry_t *aep)
atp->cdb0 = atiop->cdb_io.cdb_bytes[0];
atp->tattr = aep->at_tag_type;
atp->state = ATPD_STATE_CAM;
- isp_prt(isp, ISP_LOGTDEBUG0, "ATIO[0x%x] CDB=0x%x lun %d", aep->at_tag_val, atp->cdb0, atp->lun);
+ isp_prt(isp, ISP_LOGTDEBUG0, "ATIO[0x%x] CDB=0x%x lun %x", aep->at_tag_val, atp->cdb0, atp->lun);
rls_lun_statep(isp, tptr);
}
@@ -3103,8 +3103,8 @@ isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp)
case IN_ABORT_TASK:
{
tstate_t *tptr;
- uint16_t lun;
- uint32_t loopid, sid;
+ uint16_t nphdl, lun;
+ uint32_t sid;
uint64_t wwn;
atio_private_data_t *atp;
fcportdb_t *lp;
@@ -3119,11 +3119,11 @@ isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp)
lun = inp->in_lun;
}
if (ISP_CAP_2KLOGIN(isp)) {
- loopid = ((in_fcentry_e_t *)inp)->in_iid;
+ nphdl = ((in_fcentry_e_t *)inp)->in_iid;
} else {
- loopid = inp->in_iid;
+ nphdl = inp->in_iid;
}
- if (isp_find_pdb_by_handle(isp, 0, loopid, &lp)) {
+ if (isp_find_pdb_by_handle(isp, 0, nphdl, &lp)) {
wwn = lp->port_wwn;
sid = lp->portid;
} else {
@@ -3134,7 +3134,7 @@ isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp)
if (tptr == NULL) {
tptr = get_lun_statep(isp, 0, CAM_LUN_WILDCARD);
if (tptr == NULL) {
- isp_prt(isp, ISP_LOGWARN, "ABORT TASK for lun %u- but no tstate", lun);
+ isp_prt(isp, ISP_LOGWARN, "ABORT TASK for lun %x, but no tstate", lun);
return;
}
}
@@ -3159,7 +3159,7 @@ isp_handle_platform_notify_fc(ispsoftc_t *isp, in_fcentry_t *inp)
nt->nt_hba = isp;
nt->nt_tgt = FCPARAM(isp, 0)->isp_wwpn;
nt->nt_wwn = wwn;
- nt->nt_nphdl = loopid;
+ nt->nt_nphdl = nphdl;
nt->nt_sid = sid;
nt->nt_did = PORT_ANY;
nt->nt_lun = lun;
diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c
index fa1fa8f..43e3510 100644
--- a/sys/dev/isp/isp_library.c
+++ b/sys/dev/isp/isp_library.c
@@ -400,31 +400,24 @@ isp_fc_runstate(ispsoftc_t *isp, int chan, int tval)
if (fcp->role == ISP_ROLE_NONE) {
return (0);
}
- if (fcp->isp_fwstate < FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) {
- if (isp_control(isp, ISPCTL_FCLINK_TEST, chan, tval) != 0) {
- isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: linktest failed for channel %d", chan);
- return (-1);
- }
- if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) {
- isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: f/w not ready for channel %d", chan);
- return (-1);
- }
+ if (isp_control(isp, ISPCTL_FCLINK_TEST, chan, tval) != 0) {
+ isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: linktest failed for channel %d", chan);
+ return (-1);
}
-
if (isp_control(isp, ISPCTL_SCAN_LOOP, chan) != 0) {
- isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan loop fails on channel %d", chan);
- return (LOOP_PDB_RCVD);
+ isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan loop failed on channel %d", chan);
+ return (LOOP_LTEST_DONE);
}
if (isp_control(isp, ISPCTL_SCAN_FABRIC, chan) != 0) {
- isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan fabric fails on channel %d", chan);
+ isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: scan fabric failed on channel %d", chan);
return (LOOP_LSCAN_DONE);
}
if (isp_control(isp, ISPCTL_PDB_SYNC, chan) != 0) {
- isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: pdb_sync fails on channel %d", chan);
+ isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: pdb_sync failed on channel %d", chan);
return (LOOP_FSCAN_DONE);
}
- if (fcp->isp_fwstate != FW_READY || fcp->isp_loopstate != LOOP_READY) {
- isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: f/w not ready again on channel %d", chan);
+ if (fcp->isp_loopstate != LOOP_READY) {
+ isp_prt(isp, ISP_LOG_SANCFG, "isp_fc_runstate: not ready again on channel %d", chan);
return (-1);
}
return (0);
@@ -536,7 +529,7 @@ isp_fc_fw_statename(int state)
{
switch (state) {
case FW_CONFIG_WAIT: return "Config Wait";
- case FW_WAIT_AL_PA: return "Waiting for AL_PA";
+ case FW_WAIT_LINK: return "Wait Link";
case FW_WAIT_LOGIN: return "Wait Login";
case FW_READY: return "Ready";
case FW_LOSS_OF_SYNC: return "Loss Of Sync";
@@ -552,9 +545,9 @@ isp_fc_loop_statename(int state)
{
switch (state) {
case LOOP_NIL: return "NIL";
- case LOOP_LIP_RCVD: return "LIP Received";
- case LOOP_PDB_RCVD: return "PDB Received";
- case LOOP_SCANNING_LOOP: return "Scanning";
+ case LOOP_TESTING_LINK: return "Testing Link";
+ case LOOP_LTEST_DONE: return "Link Test Done";
+ case LOOP_SCANNING_LOOP: return "Scanning Loop";
case LOOP_LSCAN_DONE: return "Loop Scan Done";
case LOOP_SCANNING_FABRIC: return "Scanning Fabric";
case LOOP_FSCAN_DONE: return "Fabric Scan Done";
@@ -568,7 +561,7 @@ const char *
isp_fc_toponame(fcparam *fcp)
{
- if (fcp->isp_fwstate != FW_READY) {
+ if (fcp->isp_loopstate < LOOP_LTEST_DONE) {
return "Unavailable";
}
switch (fcp->isp_topo) {
@@ -604,7 +597,8 @@ isp_fc_enable_vp(ispsoftc_t *isp, int chan)
vp->vp_mod_cnt = 1;
vp->vp_mod_idx0 = chan;
vp->vp_mod_cmd = VP_MODIFY_ENA;
- vp->vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED;
+ vp->vp_mod_ports[0].options = ICB2400_VPOPT_ENABLED |
+ ICB2400_VPOPT_ENA_SNSLOGIN;
if (fcp->role & ISP_ROLE_INITIATOR) {
vp->vp_mod_ports[0].options |= ICB2400_VPOPT_INI_ENABLE;
}
@@ -1733,6 +1727,10 @@ isp_get_ridacq(ispsoftc_t *isp, isp_ridacq_t *src, isp_ridacq_t *dst)
int i;
isp_get_hdr(isp, &src->ridacq_hdr, &dst->ridacq_hdr);
ISP_IOXGET_32(isp, &src->ridacq_handle, dst->ridacq_handle);
+ ISP_IOXGET_8(isp, &src->ridacq_vp_acquired, dst->ridacq_vp_acquired);
+ ISP_IOXGET_8(isp, &src->ridacq_vp_setup, dst->ridacq_vp_setup);
+ ISP_IOXGET_8(isp, &src->ridacq_vp_index, dst->ridacq_vp_index);
+ ISP_IOXGET_8(isp, &src->ridacq_vp_status, dst->ridacq_vp_status);
ISP_IOXGET_16(isp, &src->ridacq_vp_port_lo, dst->ridacq_vp_port_lo);
ISP_IOXGET_8(isp, &src->ridacq_vp_port_hi, dst->ridacq_vp_port_hi);
ISP_IOXGET_8(isp, &src->ridacq_format, dst->ridacq_format);
@@ -1742,17 +1740,6 @@ isp_get_ridacq(ispsoftc_t *isp, isp_ridacq_t *src, isp_ridacq_t *dst)
for (i = 0; i < sizeof (src->ridacq_reserved1) / sizeof (src->ridacq_reserved1[0]); i++) {
ISP_IOXGET_16(isp, &src->ridacq_reserved1[i], dst->ridacq_reserved1[i]);
}
- if (dst->ridacq_format == 0) {
- ISP_IOXGET_8(isp, &src->un.type0.ridacq_vp_acquired, dst->un.type0.ridacq_vp_acquired);
- ISP_IOXGET_8(isp, &src->un.type0.ridacq_vp_setup, dst->un.type0.ridacq_vp_setup);
- ISP_IOXGET_16(isp, &src->un.type0.ridacq_reserved0, dst->un.type0.ridacq_reserved0);
- } else if (dst->ridacq_format == 1) {
- ISP_IOXGET_16(isp, &src->un.type1.ridacq_vp_count, dst->un.type1.ridacq_vp_count);
- ISP_IOXGET_8(isp, &src->un.type1.ridacq_vp_index, dst->un.type1.ridacq_vp_index);
- ISP_IOXGET_8(isp, &src->un.type1.ridacq_vp_status, dst->un.type1.ridacq_vp_status);
- } else {
- ISP_MEMZERO(&dst->un, sizeof (dst->un));
- }
}
@@ -2170,6 +2157,20 @@ isp_put_rft_id(ispsoftc_t *isp, rft_id_t *src, rft_id_t *dst)
}
void
+isp_put_rff_id(ispsoftc_t *isp, rff_id_t *src, rff_id_t *dst)
+{
+ int i;
+
+ isp_put_ct_hdr(isp, &src->rffid_hdr, &dst->rffid_hdr);
+ ISP_IOZPUT_8(isp, src->rffid_reserved, &dst->rffid_reserved);
+ for (i = 0; i < 3; i++)
+ ISP_IOZPUT_8(isp, src->rffid_portid[i], &dst->rffid_portid[i]);
+ ISP_IOZPUT_16(isp, src->rffid_reserved2, &dst->rffid_reserved2);
+ ISP_IOZPUT_8(isp, src->rffid_fc4features, &dst->rffid_fc4features);
+ ISP_IOZPUT_8(isp, src->rffid_fc4type, &dst->rffid_fc4type);
+}
+
+void
isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *src, ct_hdr_t *dst)
{
ISP_IOZGET_8(isp, &src->ct_revision, dst->ct_revision);
@@ -2482,7 +2483,7 @@ isp_find_pdb_by_wwn(ispsoftc_t *isp, int chan, uint64_t wwn, fcportdb_t **lptr)
#ifdef ISP_TARGET_MODE
int
-isp_find_pdb_by_handle(ispsoftc_t *isp, int chan, uint32_t handle, fcportdb_t **lptr)
+isp_find_pdb_by_handle(ispsoftc_t *isp, int chan, uint16_t handle, fcportdb_t **lptr)
{
fcparam *fcp;
int i;
@@ -2533,7 +2534,8 @@ isp_find_chan_by_did(ispsoftc_t *isp, uint32_t did, uint16_t *cp)
*cp = ISP_NOCHAN;
for (chan = 0; chan < isp->isp_nchan; chan++) {
fcparam *fcp = FCPARAM(isp, chan);
- if ((fcp->role & ISP_ROLE_TARGET) == 0 || fcp->isp_fwstate != FW_READY || fcp->isp_loopstate < LOOP_PDB_RCVD) {
+ if ((fcp->role & ISP_ROLE_TARGET) == 0 ||
+ fcp->isp_loopstate < LOOP_LTEST_DONE) {
continue;
}
if (fcp->isp_portid == did) {
diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h
index 2e575b2..1e5feef 100644
--- a/sys/dev/isp/isp_library.h
+++ b/sys/dev/isp/isp_library.h
@@ -148,6 +148,7 @@ void isp_get_fc_hdr(ispsoftc_t *, fc_hdr_t *, fc_hdr_t *);
void isp_put_fc_hdr(ispsoftc_t *, fc_hdr_t *, fc_hdr_t *);
void isp_get_fcp_cmnd_iu(ispsoftc_t *, fcp_cmnd_iu_t *, fcp_cmnd_iu_t *);
void isp_put_rft_id(ispsoftc_t *, rft_id_t *, rft_id_t *);
+void isp_put_rff_id(ispsoftc_t *, rff_id_t *, rff_id_t *);
void isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
void isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
void isp_put_fcp_rsp_iu(ispsoftc_t *isp, fcp_rsp_iu_t *, fcp_rsp_iu_t *);
@@ -172,7 +173,7 @@ void isp_destroy_tgt_handle(ispsoftc_t *, uint32_t);
#endif
int isp_find_pdb_by_wwn(ispsoftc_t *, int, uint64_t, fcportdb_t **);
#ifdef ISP_TARGET_MODE
-int isp_find_pdb_by_handle(ispsoftc_t *, int, uint32_t, fcportdb_t **);
+int isp_find_pdb_by_handle(ispsoftc_t *, int, uint16_t, fcportdb_t **);
int isp_find_pdb_by_sid(ispsoftc_t *, int, uint32_t, fcportdb_t **);
void isp_find_chan_by_did(ispsoftc_t *, uint32_t, uint16_t *);
void isp_add_wwn_entry(ispsoftc_t *, int, uint64_t, uint64_t, uint16_t, uint32_t, uint16_t);
diff --git a/sys/dev/isp/isp_stds.h b/sys/dev/isp/isp_stds.h
index daa199c..315870e 100644
--- a/sys/dev/isp/isp_stds.h
+++ b/sys/dev/isp/isp_stds.h
@@ -139,6 +139,20 @@ typedef struct {
} rft_id_t;
/*
+ * RFF_ID Requet CT_IU
+ *
+ * Source: INCITS 463-2010 Generic Services 6 Section 5.2.5.34
+ */
+typedef struct {
+ ct_hdr_t rffid_hdr;
+ uint8_t rffid_reserved;
+ uint8_t rffid_portid[3];
+ uint16_t rffid_reserved2;
+ uint8_t rffid_fc4features;
+ uint8_t rffid_fc4type;
+} rff_id_t;
+
+/*
* FCP Response IU and bits of interest
* Source: NCITS T10, Project 1828D, Revision 02b (aka FCP4r02b)
*/
diff --git a/sys/dev/isp/isp_target.c b/sys/dev/isp/isp_target.c
index cf35501..f8b1930 100644
--- a/sys/dev/isp/isp_target.c
+++ b/sys/dev/isp/isp_target.c
@@ -52,8 +52,8 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef ISP_TARGET_MODE
-static const char atiocope[] = "ATIO returned for lun %d because it was in the middle of Bus Device Reset on bus %d";
-static const char atior[] = "ATIO returned on for lun %d on from loopid %d because a Bus Reset occurred on bus %d";
+static const char atiocope[] = "ATIO returned for LUN %x because it was in the middle of Bus Device Reset on bus %d";
+static const char atior[] = "ATIO returned for LUN %x from handle 0x%x because a Bus Reset occurred on bus %d";
static const char rqo[] = "%s: Request Queue Overflow";
static void isp_got_msg(ispsoftc_t *, in_entry_t *);
@@ -931,20 +931,20 @@ static void
isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
{
isp_notify_t notify;
- static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x";
- static const char f2[] = "unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n";
- uint16_t seqid, loopid;
+ static const char f1[] = "%s from N-port handle 0x%x lun %x seq 0x%x";
+ static const char f2[] = "unknown %s 0x%x lun %x N-Port handle 0x%x task flags 0x%x seq 0x%x\n";
+ uint16_t seqid, nphdl;
ISP_MEMZERO(&notify, sizeof (isp_notify_t));
notify.nt_hba = isp;
notify.nt_wwn = INI_ANY;
if (ISP_CAP_2KLOGIN(isp)) {
notify.nt_nphdl = ((in_fcentry_e_t *)inp)->in_iid;
- loopid = ((in_fcentry_e_t *)inp)->in_iid;
+ nphdl = ((in_fcentry_e_t *)inp)->in_iid;
seqid = ((in_fcentry_e_t *)inp)->in_seqid;
} else {
notify.nt_nphdl = inp->in_iid;
- loopid = inp->in_iid;
+ nphdl = inp->in_iid;
seqid = inp->in_seqid;
}
notify.nt_sid = PORT_ANY;
@@ -965,28 +965,28 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
notify.nt_lreserved = inp;
if (inp->in_status != IN_MSG_RECEIVED) {
- isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", inp->in_status, notify.nt_lun, loopid, inp->in_task_flags, inp->in_seqid);
+ isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", inp->in_status, notify.nt_lun, nphdl, inp->in_task_flags, inp->in_seqid);
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp);
return;
}
if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) {
- isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", loopid, notify.nt_lun, inp->in_seqid);
+ isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", nphdl, notify.nt_lun, inp->in_seqid);
notify.nt_ncode = NT_ABORT_TASK_SET;
} else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) {
- isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", loopid, notify.nt_lun, inp->in_seqid);
+ isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", nphdl, notify.nt_lun, inp->in_seqid);
notify.nt_ncode = NT_CLEAR_TASK_SET;
} else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) {
- isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", loopid, notify.nt_lun, inp->in_seqid);
+ isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", nphdl, notify.nt_lun, inp->in_seqid);
notify.nt_ncode = NT_LUN_RESET;
} else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) {
- isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", loopid, notify.nt_lun, inp->in_seqid);
+ isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", nphdl, notify.nt_lun, inp->in_seqid);
notify.nt_ncode = NT_TARGET_RESET;
} else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) {
- isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", loopid, notify.nt_lun, inp->in_seqid);
+ isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", nphdl, notify.nt_lun, inp->in_seqid);
notify.nt_ncode = NT_CLEAR_ACA;
} else {
- isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status, notify.nt_lun, loopid, inp->in_task_flags, inp->in_seqid);
+ isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status, notify.nt_lun, nphdl, inp->in_task_flags, inp->in_seqid);
isp_async(isp, ISPASYNC_TARGET_NOTIFY_ACK, inp);
return;
}
@@ -997,8 +997,8 @@ static void
isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep)
{
isp_notify_t notify;
- static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%08x";
- static const char f2[] = "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%08x";
+ static const char f1[] = "%s from PortID 0x%06x lun %x seq 0x%08x";
+ static const char f2[] = "unknown Task Flag 0x%x lun %x PortID 0x%x tag 0x%08x";
uint16_t chan;
uint32_t sid, did;
@@ -1146,7 +1146,7 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
} else {
isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp);
}
- isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u seqid %x flags %x tflags %x response %x", iid, na->na_seqid,
+ isp_prt(isp, ISP_LOGTDEBUG0, "notify ack handle %x seqid %x flags %x tflags %x response %x", iid, na->na_seqid,
na->na_flags, na->na_task_flags, na->na_response);
} else {
na_entry_t *na = (na_entry_t *) storage;
@@ -1166,7 +1166,7 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
na->na_header.rqs_entry_count = 1;
isp_put_notify_ack(isp, na, (na_entry_t *)outp);
- isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt %u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, na->na_seqid, na->na_event);
+ isp_prt(isp, ISP_LOGTDEBUG0, "notify ack handle %x lun %x tgt %u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, na->na_seqid, na->na_event);
}
ISP_TDQE(isp, "isp_notify_ack", isp->isp_reqidx, storage);
ISP_SYNC_REQUEST(isp);
@@ -1274,7 +1274,7 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
/*
* ATIO rejected by the firmware due to disabled lun.
*/
- isp_prt(isp, ISP_LOGERR, "rejected ATIO for disabled lun %d", lun);
+ isp_prt(isp, ISP_LOGERR, "rejected ATIO for disabled lun %x", lun);
break;
case AT_NOCAP:
/*
@@ -1282,7 +1282,7 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
* We sent an ATIO that overflowed the firmware's
* command resource count.
*/
- isp_prt(isp, ISP_LOGERR, "rejected ATIO for lun %d because of command count overflow", lun);
+ isp_prt(isp, ISP_LOGERR, "rejected ATIO for lun %x because of command count overflow", lun);
break;
case AT_BDR_MSG:
@@ -1320,7 +1320,7 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
default:
- isp_prt(isp, ISP_LOGERR, "Unknown ATIO status 0x%x from loopid %d for lun %d", aep->at_status, aep->at_iid, lun);
+ isp_prt(isp, ISP_LOGERR, "Unknown ATIO status 0x%x from handle %x for lun %x", aep->at_status, aep->at_iid, lun);
(void) isp_target_put_atio(isp, aep);
break;
}
@@ -1408,7 +1408,7 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
default:
- isp_prt(isp, ISP_LOGERR, "Unknown ATIO2 status 0x%x from loopid %d for lun %x", aep->at_status, iid, lun);
+ isp_prt(isp, ISP_LOGERR, "Unknown ATIO2 status 0x%x from handle %d for lun %x", aep->at_status, iid, lun);
(void) isp_target_put_atio(isp, aep);
break;
}
@@ -1483,7 +1483,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
* CTIO rejected by the firmware due to disabled lun.
* "Cannot Happen".
*/
- isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for disabled lun %d", ct->ct_lun);
+ isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for disabled lun %x", ct->ct_lun);
break;
case CT_NOPATH:
@@ -1493,7 +1493,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
* we tried to access the bus while a non-disconnecting
* command is in process.
*/
- isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for bad nexus %d/%d/%d", ct->ct_iid, ct->ct_tgt, ct->ct_lun);
+ isp_prt(isp, ISP_LOGERR, "Firmware rejected CTIO for bad nexus %d/%d/%x", ct->ct_iid, ct->ct_tgt, ct->ct_lun);
break;
case CT_RSELTMO:
diff --git a/sys/dev/isp/ispmbox.h b/sys/dev/isp/ispmbox.h
index 25b57d5..b0d74a6 100644
--- a/sys/dev/isp/ispmbox.h
+++ b/sys/dev/isp/ispmbox.h
@@ -1485,18 +1485,10 @@ typedef struct {
typedef struct {
isphdr_t ridacq_hdr;
uint32_t ridacq_handle;
- union {
- struct {
- uint8_t ridacq_vp_acquired;
- uint8_t ridacq_vp_setup;
- uint16_t ridacq_reserved0;
- } type0; /* type 0 */
- struct {
- uint16_t ridacq_vp_count;
- uint8_t ridacq_vp_index;
- uint8_t ridacq_vp_status;
- } type1; /* type 1 */
- } un;
+ uint8_t ridacq_vp_acquired;
+ uint8_t ridacq_vp_setup;
+ uint8_t ridacq_vp_index;
+ uint8_t ridacq_vp_status;
uint16_t ridacq_vp_port_lo;
uint8_t ridacq_vp_port_hi;
uint8_t ridacq_format; /* 0 or 1 */
@@ -1506,8 +1498,11 @@ typedef struct {
#define RIDACQ_STS_COMPLETE 0
#define RIDACQ_STS_UNACQUIRED 1
-#define RIDACQ_STS_CHANGED 20
-
+#define RIDACQ_STS_CHANGED 2
+#define RIDACQ_STS_SNS_TIMEOUT 3
+#define RIDACQ_STS_SNS_REJECTED 4
+#define RIDACQ_STS_SCR_TIMEOUT 5
+#define RIDACQ_STS_SCR_REJECTED 6
/*
* Simple Name Server Data Structures
@@ -1518,6 +1513,7 @@ typedef struct {
#define SNS_GFF_ID 0x11F
#define SNS_GID_FT 0x171
#define SNS_RFT_ID 0x217
+#define SNS_RFF_ID 0x21F
typedef struct {
uint16_t snscb_rblen; /* response buffer length (words) */
uint16_t snscb_reserved0;
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index 233c88c..0bf592f 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -482,7 +482,7 @@ typedef struct {
} fcparam;
#define FW_CONFIG_WAIT 0
-#define FW_WAIT_AL_PA 1
+#define FW_WAIT_LINK 1
#define FW_WAIT_LOGIN 2
#define FW_READY 3
#define FW_LOSS_OF_SYNC 4
@@ -491,8 +491,8 @@ typedef struct {
#define FW_NON_PART 7
#define LOOP_NIL 0
-#define LOOP_LIP_RCVD 1
-#define LOOP_PDB_RCVD 2
+#define LOOP_TESTING_LINK 1
+#define LOOP_LTEST_DONE 2
#define LOOP_SCANNING_LOOP 3
#define LOOP_LSCAN_DONE 4
#define LOOP_SCANNING_FABRIC 5
@@ -861,10 +861,10 @@ void isp_done(XS_T *);
* Update any operating parameters (speed, etc.)
* ... ISPCTL_FCLINK_TEST, int channel);
* Test FC link status on this channel
- * ... ISPCTL_SCAN_FABRIC, int channel);
- * Scan fabric on this channel
* ... ISPCTL_SCAN_LOOP, int channel);
* Scan local loop on this channel
+ * ... ISPCTL_SCAN_FABRIC, int channel);
+ * Scan fabric on this channel
* ... ISPCTL_PDB_SYNC, int channel);
* Synchronize port database on this channel
* ... ISPCTL_SEND_LIP, int channel);
@@ -881,12 +881,11 @@ void isp_done(XS_T *);
* Change role of specified channel
*
* ISPCTL_PDB_SYNC is somewhat misnamed. It actually is the final step, in
- * order, of ISPCTL_FCLINK_TEST, ISPCTL_SCAN_FABRIC, and ISPCTL_SCAN_LOOP.
+ * order, of ISPCTL_FCLINK_TEST, ISPCTL_SCAN_LOOP, and ISPCTL_SCAN_FABRIC.
* The main purpose of ISPCTL_PDB_SYNC is to complete management of logging
* and logging out of fabric devices (if one is on a fabric) and then marking
* the 'loop state' as being ready to now be used for sending commands to
- * devices. Originally fabric name server and local loop scanning were
- * part of this function. It's now been separated to allow for finer control.
+ * devices.
*/
typedef enum {
ISPCTL_RESET_BUS,
diff --git a/sys/dev/ntb/if_ntb/if_ntb.c b/sys/dev/ntb/if_ntb/if_ntb.c
index 28f6305..8b392e9 100644
--- a/sys/dev/ntb/if_ntb/if_ntb.c
+++ b/sys/dev/ntb/if_ntb/if_ntb.c
@@ -116,7 +116,7 @@ SYSCTL_UINT(_hw_if_ntb, OID_AUTO, max_num_clients, CTLFLAG_RDTUN,
STAILQ_HEAD(ntb_queue_list, ntb_queue_entry);
-typedef unsigned ntb_q_idx_t;
+typedef uint32_t ntb_q_idx_t;
struct ntb_queue_entry {
/* ntb_queue list reference */
@@ -125,8 +125,8 @@ struct ntb_queue_entry {
/* info on data to be transferred */
void *cb_data;
void *buf;
- unsigned len;
- unsigned flags;
+ uint32_t len;
+ uint32_t flags;
struct ntb_transport_qp *qp;
struct ntb_payload_header *x_hdr;
@@ -164,7 +164,6 @@ struct ntb_transport_qp {
void *data, int len);
struct ntb_queue_list rx_post_q;
struct ntb_queue_list rx_pend_q;
- struct ntb_queue_list rx_free_q;
/* ntb_rx_q_lock: synchronize access to rx_XXXX_q */
struct mtx ntb_rx_q_lock;
struct task rx_completion_task;
@@ -207,6 +206,7 @@ struct ntb_transport_mw {
size_t phys_size;
size_t xlat_align;
size_t xlat_align_size;
+ bus_addr_t addr_limit;
/* Tx buff is off vbase / phys_addr */
caddr_t vbase;
size_t xlat_size;
@@ -245,9 +245,9 @@ enum {
};
struct ntb_payload_header {
- uint64_t ver;
- uint64_t len;
- uint64_t flags;
+ ntb_q_idx_t ver;
+ uint32_t len;
+ uint32_t flags;
};
enum {
@@ -338,6 +338,14 @@ static const struct ntb_ctx_ops ntb_transport_ops = {
MALLOC_DEFINE(M_NTB_IF, "if_ntb", "ntb network driver");
+static inline void
+iowrite32(uint32_t val, void *addr)
+{
+
+ bus_space_write_4(X86_BUS_SPACE_MEM, 0/* HACK */, (uintptr_t)addr,
+ val);
+}
+
/* Module setup and teardown */
static int
ntb_handle_module_events(struct module *m, int what, void *arg)
@@ -568,7 +576,8 @@ ntb_transport_probe(struct ntb_softc *ntb)
mw = &nt->mw_vec[i];
rc = ntb_mw_get_range(ntb, i, &mw->phys_addr, &mw->vbase,
- &mw->phys_size, &mw->xlat_align, &mw->xlat_align_size);
+ &mw->phys_size, &mw->xlat_align, &mw->xlat_align_size,
+ &mw->addr_limit);
if (rc != 0)
goto err;
@@ -708,7 +717,6 @@ ntb_transport_init_queue(struct ntb_transport_ctx *nt, unsigned int qp_num)
STAILQ_INIT(&qp->rx_post_q);
STAILQ_INIT(&qp->rx_pend_q);
- STAILQ_INIT(&qp->rx_free_q);
STAILQ_INIT(&qp->tx_free_q);
callout_reset(&qp->link_work, 0, ntb_qp_link_work, qp);
@@ -733,9 +741,6 @@ ntb_transport_free_queue(struct ntb_transport_qp *qp)
qp->tx_handler = NULL;
qp->event_handler = NULL;
- while ((entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_free_q)))
- free(entry, M_NTB_IF);
-
while ((entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_pend_q)))
free(entry, M_NTB_IF);
@@ -887,9 +892,9 @@ ntb_process_tx(struct ntb_transport_qp *qp, struct ntb_queue_entry *entry)
{
void *offset;
- offset = (char *)qp->tx_mw + qp->tx_max_frame * qp->tx_index;
+ offset = qp->tx_mw + qp->tx_max_frame * qp->tx_index;
CTR3(KTR_NTB,
- "TX: process_tx: tx_pkts=%u, tx_index=%u, remote entry=%u",
+ "TX: process_tx: tx_pkts=%lu, tx_index=%u, remote entry=%u",
qp->tx_pkts, qp->tx_index, qp->remote_rx_info->entry);
if (qp->tx_index == qp->remote_rx_info->entry) {
CTR0(KTR_NTB, "TX: ring full");
@@ -900,8 +905,11 @@ ntb_process_tx(struct ntb_transport_qp *qp, struct ntb_queue_entry *entry)
if (entry->len > qp->tx_max_frame - sizeof(struct ntb_payload_header)) {
if (qp->tx_handler != NULL)
qp->tx_handler(qp, qp->cb_data, entry->buf,
- EIO);
+ EIO);
+ else
+ m_freem(entry->buf);
+ entry->buf = NULL;
ntb_list_add(&qp->ntb_tx_free_q_lock, entry, &qp->tx_free_q);
CTR1(KTR_NTB,
"TX: frame too big. returning entry %p to tx_free_q",
@@ -929,8 +937,8 @@ ntb_memcpy_tx(struct ntb_transport_qp *qp, struct ntb_queue_entry *entry,
hdr = (struct ntb_payload_header *)((char *)offset + qp->tx_max_frame -
sizeof(struct ntb_payload_header));
entry->x_hdr = hdr;
- hdr->len = entry->len; /* TODO: replace with bus_space_write */
- hdr->ver = qp->tx_pkts; /* TODO: replace with bus_space_write */
+ iowrite32(entry->len, &hdr->len);
+ iowrite32(qp->tx_pkts, &hdr->ver);
/* This piece is ntb_memcpy_tx() */
CTR2(KTR_NTB, "TX: copying %d bytes to offset %p", entry->len, offset);
@@ -945,8 +953,8 @@ ntb_memcpy_tx(struct ntb_transport_qp *qp, struct ntb_queue_entry *entry,
}
/* The rest is ntb_tx_copy_callback() */
- /* TODO: replace with bus_space_write */
- hdr->flags = entry->flags | IF_NTB_DESC_DONE_FLAG;
+ iowrite32(entry->flags | IF_NTB_DESC_DONE_FLAG, &hdr->flags);
+ CTR1(KTR_NTB, "TX: hdr %p set DESC_DONE", hdr);
ntb_peer_db_set(qp->ntb, 1ull << qp->qp_num);
@@ -959,13 +967,16 @@ ntb_memcpy_tx(struct ntb_transport_qp *qp, struct ntb_queue_entry *entry,
qp->tx_bytes += entry->len;
if (qp->tx_handler)
- qp->tx_handler(qp, qp->cb_data, entry->cb_data,
- entry->len);
+ qp->tx_handler(qp, qp->cb_data, entry->buf,
+ entry->len);
+ else
+ m_freem(entry->buf);
+ entry->buf = NULL;
}
- CTR2(KTR_NTB,
- "TX: entry %p sent. hdr->ver = %d, Returning to tx_free_q", entry,
- hdr->ver);
+ CTR3(KTR_NTB,
+ "TX: entry %p sent. hdr->ver = %u, hdr->flags = 0x%x, Returning "
+ "to tx_free_q", entry, hdr->ver, hdr->flags);
ntb_list_add(&qp->ntb_tx_free_q_lock, entry, &qp->tx_free_q);
}
@@ -1021,13 +1032,11 @@ ntb_process_rxc(struct ntb_transport_qp *qp)
{
struct ntb_payload_header *hdr;
struct ntb_queue_entry *entry;
- void *offset;
+ caddr_t offset;
- offset = (void *)
- ((char *)qp->rx_buff + qp->rx_max_frame * qp->rx_index);
- hdr = (void *)
- ((char *)offset + qp->rx_max_frame -
- sizeof(struct ntb_payload_header));
+ offset = qp->rx_buff + qp->rx_max_frame * qp->rx_index;
+ hdr = (void *)(offset + qp->rx_max_frame -
+ sizeof(struct ntb_payload_header));
CTR1(KTR_NTB, "RX: process_rxc rx_index = %u", qp->rx_index);
if ((hdr->flags & IF_NTB_DESC_DONE_FLAG) == 0) {
@@ -1045,7 +1054,7 @@ ntb_process_rxc(struct ntb_transport_qp *qp)
if (hdr->ver != (uint32_t)qp->rx_pkts) {
CTR2(KTR_NTB,"RX: ver != rx_pkts (%x != %lx). "
- "Returning entry %p to rx_pend_q", hdr->ver, qp->rx_pkts);
+ "Returning entry to rx_pend_q", hdr->ver, qp->rx_pkts);
qp->rx_err_ver++;
return (EIO);
}
@@ -1136,20 +1145,30 @@ ntb_complete_rxc(void *arg, int pending)
break;
entry->x_hdr->flags = 0;
- /* XXX bus_space_write */
- qp->rx_info->entry = entry->index;
+ iowrite32(entry->index, &qp->rx_info->entry);
+
+ STAILQ_REMOVE_HEAD(&qp->rx_post_q, entry);
len = entry->len;
m = entry->buf;
- STAILQ_REMOVE_HEAD(&qp->rx_post_q, entry);
- STAILQ_INSERT_TAIL(&qp->rx_free_q, entry, entry);
+ /*
+ * Re-initialize queue_entry for reuse; rx_handler takes
+ * ownership of the mbuf.
+ */
+ entry->buf = NULL;
+ entry->len = transport_mtu;
+ entry->cb_data = qp->transport->ifp;
+
+ STAILQ_INSERT_TAIL(&qp->rx_pend_q, entry, entry);
mtx_unlock_spin(&qp->ntb_rx_q_lock);
CTR2(KTR_NTB, "RX: completing entry %p, mbuf %p", entry, m);
if (qp->rx_handler != NULL && qp->client_ready)
qp->rx_handler(qp, qp->cb_data, m, len);
+ else
+ m_freem(m);
mtx_lock_spin(&qp->ntb_rx_q_lock);
}
@@ -1301,7 +1320,7 @@ ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw, size_t size)
mw->buff_size = buff_size;
mw->virt_addr = contigmalloc(mw->buff_size, M_NTB_IF, M_ZERO, 0,
- BUS_SPACE_MAXADDR, mw->xlat_align, 0);
+ mw->addr_limit, mw->xlat_align, 0);
if (mw->virt_addr == NULL) {
mw->xlat_size = 0;
mw->buff_size = 0;
diff --git a/sys/dev/ntb/ntb_hw/ntb_hw.c b/sys/dev/ntb/ntb_hw/ntb_hw.c
index 24f3912..220d635 100644
--- a/sys/dev/ntb/ntb_hw/ntb_hw.c
+++ b/sys/dev/ntb/ntb_hw/ntb_hw.c
@@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
#define NTB_HB_TIMEOUT 1 /* second */
#define ATOM_LINK_RECOVERY_TIME 500 /* ms */
+#define BAR_HIGH_MASK (~((1ull << 12) - 1))
#define DEVICE2SOFTC(dev) ((struct ntb_softc *) device_get_softc(dev))
@@ -113,6 +114,7 @@ struct ntb_pci_bar_info {
vm_paddr_t pbase;
caddr_t vbase;
vm_size_t size;
+ bool mapped_wc : 1;
/* Configuration register offsets */
uint32_t psz_off;
@@ -326,6 +328,10 @@ SYSCTL_UINT(_hw_ntb, OID_AUTO, debug_level, CTLFLAG_RWTUN,
} \
} while (0)
+static unsigned g_ntb_enable_wc = 1;
+SYSCTL_UINT(_hw_ntb, OID_AUTO, enable_writecombine, CTLFLAG_RDTUN,
+ &g_ntb_enable_wc, 0, "Set to 1 to map memory windows write combining");
+
static struct ntb_hw_info pci_ids[] = {
/* XXX: PS/SS IDs left out until they are supported. */
{ 0x0C4E8086, "BWD Atom Processor S1200 Non-Transparent Bridge B2B",
@@ -766,18 +772,22 @@ map_memory_window_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar)
save_bar_parameters(bar);
}
+ print_map_success(ntb, bar, "mw");
+ if (g_ntb_enable_wc == 0)
+ return (0);
+
/* Mark bar region as write combining to improve performance. */
rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size,
VM_MEMATTR_WRITE_COMBINING);
- print_map_success(ntb, bar, "mw");
- if (rc == 0)
+ if (rc == 0) {
+ bar->mapped_wc = true;
device_printf(ntb->device,
"Marked BAR%d v:[%p-%p] p:[%p-%p] as "
"WRITE_COMBINING.\n",
PCI_RID2BAR(bar->pci_resource_id), bar->vbase,
(char *)bar->vbase + bar->size - 1,
(void *)bar->pbase, (void *)(bar->pbase + bar->size - 1));
- else
+ } else
device_printf(ntb->device,
"Unable to mark BAR%d v:[%p-%p] p:[%p-%p] as "
"WRITE_COMBINING: %d\n",
@@ -2475,15 +2485,19 @@ ntb_peer_spad_read(struct ntb_softc *ntb, unsigned int idx, uint32_t *val)
*/
int
ntb_mw_get_range(struct ntb_softc *ntb, unsigned mw_idx, vm_paddr_t *base,
- caddr_t *vbase, size_t *size, size_t *align, size_t *align_size)
+ caddr_t *vbase, size_t *size, size_t *align, size_t *align_size,
+ bus_addr_t *plimit)
{
struct ntb_pci_bar_info *bar;
+ bus_addr_t limit;
size_t bar_b2b_off;
+ enum ntb_bar bar_num;
if (mw_idx >= ntb_mw_count(ntb))
return (EINVAL);
- bar = &ntb->bar_info[ntb_mw_to_bar(ntb, mw_idx)];
+ bar_num = ntb_mw_to_bar(ntb, mw_idx);
+ bar = &ntb->bar_info[bar_num];
bar_b2b_off = 0;
if (mw_idx == ntb->b2b_mw_idx) {
KASSERT(ntb->b2b_off != 0,
@@ -2491,6 +2505,11 @@ ntb_mw_get_range(struct ntb_softc *ntb, unsigned mw_idx, vm_paddr_t *base,
bar_b2b_off = ntb->b2b_off;
}
+ if (bar_is_64bit(ntb, bar_num))
+ limit = BUS_SPACE_MAXADDR;
+ else
+ limit = BUS_SPACE_MAXADDR_32BIT;
+
if (base != NULL)
*base = bar->pbase + bar_b2b_off;
if (vbase != NULL)
@@ -2501,6 +2520,8 @@ ntb_mw_get_range(struct ntb_softc *ntb, unsigned mw_idx, vm_paddr_t *base,
*align = bar->size;
if (align_size != NULL)
*align_size = 1;
+ if (plimit != NULL)
+ *plimit = limit;
return (0);
}
@@ -2514,7 +2535,9 @@ ntb_mw_get_range(struct ntb_softc *ntb, unsigned mw_idx, vm_paddr_t *base,
* Set the translation of a memory window. The peer may access local memory
* through the window starting at the address, up to the size. The address
* must be aligned to the alignment specified by ntb_mw_get_range(). The size
- * must be aligned to the size alignment specified by ntb_mw_get_range().
+ * must be aligned to the size alignment specified by ntb_mw_get_range(). The
+ * address must be below the plimit specified by ntb_mw_get_range() (i.e. for
+ * 32-bit BARs).
*
* Return: Zero on success, otherwise an error number.
*/
@@ -2551,14 +2574,14 @@ ntb_mw_set_trans(struct ntb_softc *ntb, unsigned idx, bus_addr_t addr,
limit = 0;
if (bar_is_64bit(ntb, bar_num)) {
- base = ntb_reg_read(8, base_reg);
+ base = ntb_reg_read(8, base_reg) & BAR_HIGH_MASK;
if (limit_reg != 0 && size != mw_size)
limit = base + size;
/* Set and verify translation address */
ntb_reg_write(8, xlat_reg, addr);
- reg_val = ntb_reg_read(8, xlat_reg);
+ reg_val = ntb_reg_read(8, xlat_reg) & BAR_HIGH_MASK;
if (reg_val != addr) {
ntb_reg_write(8, xlat_reg, 0);
return (EIO);
@@ -2566,7 +2589,7 @@ ntb_mw_set_trans(struct ntb_softc *ntb, unsigned idx, bus_addr_t addr,
/* Set and verify the limit */
ntb_reg_write(8, limit_reg, limit);
- reg_val = ntb_reg_read(8, limit_reg);
+ reg_val = ntb_reg_read(8, limit_reg) & BAR_HIGH_MASK;
if (reg_val != limit) {
ntb_reg_write(8, limit_reg, base);
ntb_reg_write(8, xlat_reg, 0);
@@ -2575,19 +2598,19 @@ ntb_mw_set_trans(struct ntb_softc *ntb, unsigned idx, bus_addr_t addr,
} else {
/* Configure 32-bit (split) BAR MW */
- if ((addr & ~UINT32_MAX) != 0)
- return (EINVAL);
- if (((addr + size) & ~UINT32_MAX) != 0)
- return (EINVAL);
+ if ((addr & UINT32_MAX) != addr)
+ return (ERANGE);
+ if (((addr + size) & UINT32_MAX) != (addr + size))
+ return (ERANGE);
- base = ntb_reg_read(4, base_reg);
+ base = ntb_reg_read(4, base_reg) & BAR_HIGH_MASK;
if (limit_reg != 0 && size != mw_size)
limit = base + size;
/* Set and verify translation address */
ntb_reg_write(4, xlat_reg, addr);
- reg_val = ntb_reg_read(4, xlat_reg);
+ reg_val = ntb_reg_read(4, xlat_reg) & BAR_HIGH_MASK;
if (reg_val != addr) {
ntb_reg_write(4, xlat_reg, 0);
return (EIO);
@@ -2595,7 +2618,7 @@ ntb_mw_set_trans(struct ntb_softc *ntb, unsigned idx, bus_addr_t addr,
/* Set and verify the limit */
ntb_reg_write(4, limit_reg, limit);
- reg_val = ntb_reg_read(4, limit_reg);
+ reg_val = ntb_reg_read(4, limit_reg) & BAR_HIGH_MASK;
if (reg_val != limit) {
ntb_reg_write(4, limit_reg, base);
ntb_reg_write(4, xlat_reg, 0);
@@ -2622,6 +2645,60 @@ ntb_mw_clear_trans(struct ntb_softc *ntb, unsigned mw_idx)
return (ntb_mw_set_trans(ntb, mw_idx, 0, 0));
}
+/*
+ * ntb_mw_get_wc - Get the write-combine status of a memory window
+ *
+ * Returns: Zero on success, setting *wc; otherwise an error number (e.g. if
+ * idx is an invalid memory window).
+ */
+int
+ntb_mw_get_wc(struct ntb_softc *ntb, unsigned idx, bool *wc)
+{
+ struct ntb_pci_bar_info *bar;
+
+ if (idx >= ntb_mw_count(ntb))
+ return (EINVAL);
+
+ bar = &ntb->bar_info[ntb_mw_to_bar(ntb, idx)];
+ *wc = bar->mapped_wc;
+ return (0);
+}
+
+/*
+ * ntb_mw_set_wc - Set the write-combine status of a memory window
+ *
+ * If 'wc' matches the current status, this does nothing and succeeds.
+ *
+ * Returns: Zero on success, setting the caching attribute on the virtual
+ * mapping of the BAR; otherwise an error number (e.g. if idx is an invalid
+ * memory window, or if changing the caching attribute fails).
+ */
+int
+ntb_mw_set_wc(struct ntb_softc *ntb, unsigned idx, bool wc)
+{
+ struct ntb_pci_bar_info *bar;
+ vm_memattr_t attr;
+ int rc;
+
+ if (idx >= ntb_mw_count(ntb))
+ return (EINVAL);
+
+ bar = &ntb->bar_info[ntb_mw_to_bar(ntb, idx)];
+ if (bar->mapped_wc == wc)
+ return (0);
+
+ if (wc)
+ attr = VM_MEMATTR_WRITE_COMBINING;
+ else
+ attr = VM_MEMATTR_DEFAULT;
+
+ rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size, attr);
+ if (rc == 0)
+ bar->mapped_wc = wc;
+
+ return (rc);
+}
+
/**
* ntb_peer_db_set() - Set the doorbell on the secondary/external side
* @ntb: pointer to ntb_softc instance
diff --git a/sys/dev/ntb/ntb_hw/ntb_hw.h b/sys/dev/ntb/ntb_hw/ntb_hw.h
index 7ed7e4c..d4f4930 100644
--- a/sys/dev/ntb/ntb_hw/ntb_hw.h
+++ b/sys/dev/ntb/ntb_hw/ntb_hw.h
@@ -77,10 +77,14 @@ void ntb_clear_ctx(struct ntb_softc *);
uint8_t ntb_mw_count(struct ntb_softc *);
int ntb_mw_get_range(struct ntb_softc *, unsigned mw_idx, vm_paddr_t *base,
- caddr_t *vbase, size_t *size, size_t *align, size_t *align_size);
+ caddr_t *vbase, size_t *size, size_t *align, size_t *align_size,
+ bus_addr_t *plimit);
int ntb_mw_set_trans(struct ntb_softc *, unsigned mw_idx, bus_addr_t, size_t);
int ntb_mw_clear_trans(struct ntb_softc *, unsigned mw_idx);
+int ntb_mw_get_wc(struct ntb_softc *, unsigned mw_idx, bool *wc);
+int ntb_mw_set_wc(struct ntb_softc *, unsigned mw_idx, bool wc);
+
uint8_t ntb_get_max_spads(struct ntb_softc *ntb);
int ntb_spad_write(struct ntb_softc *ntb, unsigned int idx, uint32_t val);
int ntb_spad_read(struct ntb_softc *ntb, unsigned int idx, uint32_t *val);
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index 22f91f5..246b3d4 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -1696,13 +1696,13 @@ re_attach(device_t dev)
#ifdef DEV_NETMAP
re_netmap_attach(sc);
#endif /* DEV_NETMAP */
+
#ifdef RE_DIAG
/*
* Perform hardware diagnostic on the original RTL8169.
* Some 32-bit cards were incorrectly wired and would
* malfunction if plugged into a 64-bit slot.
*/
-
if (hwrev == RL_HWREV_8169) {
error = re_diag(sc);
if (error) {
@@ -2939,6 +2939,7 @@ re_start_locked(struct ifnet *ifp)
return;
}
#endif /* DEV_NETMAP */
+
if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING || (sc->rl_flags & RL_FLAG_LINK) == 0)
return;
@@ -3851,6 +3852,11 @@ re_setwol(struct rl_softc *sc)
CSR_READ_1(sc, RL_GPIO) & ~0x01);
}
if ((ifp->if_capenable & IFCAP_WOL) != 0) {
+ if ((sc->rl_flags & RL_FLAG_8168G_PLUS) != 0) {
+ /* Disable RXDV gate. */
+ CSR_WRITE_4(sc, RL_MISC, CSR_READ_4(sc, RL_MISC) &
+ ~0x00080000);
+ }
re_set_rxmode(sc);
if ((sc->rl_flags & RL_FLAG_WOL_MANLINK) != 0)
re_set_linkspeed(sc);
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index b2810a0..ee0b37b 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -25,6 +25,7 @@
*/
#include "opt_platform.h"
+#include "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -57,6 +58,16 @@ __FBSDID("$FreeBSD$");
#define DEFAULT_RCLK 1843200
+/*
+ * Set the default baudrate tolerance to 3.0%.
+ *
+ * Some embedded boards have odd reference clocks (eg 25MHz)
+ * and we need to handle higher variances in the target baud rate.
+ */
+#ifndef UART_DEV_TOLERANCE_PCT
+#define UART_DEV_TOLERANCE_PCT 30
+#endif /* UART_DEV_TOLERANCE_PCT */
+
static int broken_txfifo = 0;
SYSCTL_INT(_hw, OID_AUTO, broken_txfifo, CTLFLAG_RWTUN,
&broken_txfifo, 0, "UART FIFO has QEMU emulation bug");
@@ -123,8 +134,8 @@ ns8250_divisor(int rclk, int baudrate)
/* 10 times error in percent: */
error = ((actual_baud - baudrate) * 2000 / baudrate + 1) >> 1;
- /* 3.0% maximum error tolerance: */
- if (error < -30 || error > 30)
+ /* enforce maximum error tolerance: */
+ if (error < -UART_DEV_TOLERANCE_PCT || error > UART_DEV_TOLERANCE_PCT)
return (0);
return (divisor);
diff --git a/sys/dev/vmware/vmxnet3/if_vmx.c b/sys/dev/vmware/vmxnet3/if_vmx.c
index 5faf716..be249c9 100644
--- a/sys/dev/vmware/vmxnet3/if_vmx.c
+++ b/sys/dev/vmware/vmxnet3/if_vmx.c
@@ -510,6 +510,13 @@ vmxnet3_check_version(struct vmxnet3_softc *sc)
return (0);
}
+static int
+trunc_powerof2(int val)
+{
+
+ return (1U << (fls(val) - 1));
+}
+
static void
vmxnet3_initial_config(struct vmxnet3_softc *sc)
{
@@ -520,14 +527,14 @@ vmxnet3_initial_config(struct vmxnet3_softc *sc)
nqueue = VMXNET3_DEF_TX_QUEUES;
if (nqueue > mp_ncpus)
nqueue = mp_ncpus;
- sc->vmx_max_ntxqueues = nqueue;
+ sc->vmx_max_ntxqueues = trunc_powerof2(nqueue);
nqueue = vmxnet3_tunable_int(sc, "rxnqueue", vmxnet3_default_rxnqueue);
if (nqueue > VMXNET3_MAX_RX_QUEUES || nqueue < 1)
nqueue = VMXNET3_DEF_RX_QUEUES;
if (nqueue > mp_ncpus)
nqueue = mp_ncpus;
- sc->vmx_max_nrxqueues = nqueue;
+ sc->vmx_max_nrxqueues = trunc_powerof2(nqueue);
if (vmxnet3_tunable_int(sc, "mq_disable", vmxnet3_mq_disable)) {
sc->vmx_max_nrxqueues = 1;
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
index ddf4a7d..04e75f8 100644
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -3791,8 +3791,8 @@ wpi_set_pslevel(struct wpi_softc *sc, uint8_t dtim, int level, int async)
if (level != 0) /* not CAM */
cmd.flags |= htole16(WPI_PS_ALLOW_SLEEP);
/* Retrieve PCIe Active State Power Management (ASPM). */
- reg = pci_read_config(sc->sc_dev, sc->sc_cap_off + 0x10, 1);
- if (!(reg & 0x1)) /* L0s Entry disabled. */
+ reg = pci_read_config(sc->sc_dev, sc->sc_cap_off + PCIER_LINK_CTL, 1);
+ if (!(reg & PCIEM_LINK_CTL_ASPMC_L0S)) /* L0s Entry disabled. */
cmd.flags |= htole16(WPI_PS_PCI_PMGT);
cmd.rxtimeout = htole32(pmgt->rxtimeout * IEEE80211_DUR_TU);
@@ -5126,9 +5126,9 @@ wpi_apm_init(struct wpi_softc *sc)
WPI_SETBITS(sc, WPI_DBG_HPET_MEM, 0xffff0000);
/* Retrieve PCIe Active State Power Management (ASPM). */
- reg = pci_read_config(sc->sc_dev, sc->sc_cap_off + 0x10, 1);
+ reg = pci_read_config(sc->sc_dev, sc->sc_cap_off + PCIER_LINK_CTL, 1);
/* Workaround for HW instability in PCIe L0->L0s->L1 transition. */
- if (reg & 0x02) /* L1 Entry enabled. */
+ if (reg & PCIEM_LINK_CTL_ASPMC_L1) /* L1 Entry enabled. */
WPI_SETBITS(sc, WPI_GIO, WPI_GIO_L0S_ENA);
else
WPI_CLRBITS(sc, WPI_GIO, WPI_GIO_L0S_ENA);
diff --git a/sys/dev/xen/control/control.c b/sys/dev/xen/control/control.c
index f2851ee..6a351d8 100644
--- a/sys/dev/xen/control/control.c
+++ b/sys/dev/xen/control/control.c
@@ -128,6 +128,8 @@ __FBSDID("$FreeBSD$");
#include <machine/_inttypes.h>
#include <machine/intr_machdep.h>
+#include <x86/apicvar.h>
+
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/vm_kern.h>
@@ -256,6 +258,8 @@ xctrl_suspend()
gnttab_resume(NULL);
#ifdef SMP
+ /* Send an IPI_BITMAP in case there are pending bitmap IPIs. */
+ lapic_ipi_vectored(IPI_BITMAP_VECTOR, APIC_IPI_DEST_ALL);
if (smp_started && !CPU_EMPTY(&cpu_suspend_map)) {
/*
* Now that event channels have been initialized,
diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c
index b165b96..14a4d18 100644
--- a/sys/fs/nfsclient/nfs_clvfsops.c
+++ b/sys/fs/nfsclient/nfs_clvfsops.c
@@ -216,10 +216,12 @@ newnfs_iosize(struct nfsmount *nmp)
* Calculate the size used for io buffers. Use the larger
* of the two sizes to minimise nfs requests but make sure
* that it is at least one VM page to avoid wasting buffer
- * space.
+ * space. It must also be at least NFS_DIRBLKSIZ, since
+ * that is the buffer size used for directories.
*/
iosize = imax(nmp->nm_rsize, nmp->nm_wsize);
iosize = imax(iosize, PAGE_SIZE);
+ iosize = imax(iosize, NFS_DIRBLKSIZ);
nmp->nm_mountp->mnt_stat.f_iosize = iosize;
return (iosize);
}
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index 6aecd78..3e3ae8f 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -150,24 +150,38 @@ g_dev_setdumpdev(struct cdev *dev, struct thread *td)
return (error);
}
-static void
+static int
init_dumpdev(struct cdev *dev)
{
+ struct g_consumer *cp;
const char *devprefix = "/dev/", *devname;
+ int error;
size_t len;
if (dumpdev == NULL)
- return;
+ return (0);
+
len = strlen(devprefix);
devname = devtoname(dev);
if (strcmp(devname, dumpdev) != 0 &&
(strncmp(dumpdev, devprefix, len) != 0 ||
strcmp(devname, dumpdev + len) != 0))
- return;
- if (g_dev_setdumpdev(dev, curthread) == 0) {
+ return (0);
+
+ cp = (struct g_consumer *)dev->si_drv2;
+ error = g_access(cp, 1, 0, 0);
+ if (error != 0)
+ return (error);
+
+ error = g_dev_setdumpdev(dev, curthread);
+ if (error == 0) {
freeenv(dumpdev);
dumpdev = NULL;
}
+
+ (void)g_access(cp, -1, 0, 0);
+
+ return (error);
}
static void
@@ -312,7 +326,10 @@ g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
dev->si_iosize_max = MAXPHYS;
dev->si_drv2 = cp;
- init_dumpdev(dev);
+ error = init_dumpdev(dev);
+ if (error != 0)
+ printf("%s: init_dumpdev() failed (gp->name=%s, error=%d)\n",
+ __func__, gp->name, error);
g_dev_attrchanged(cp, "GEOM::physpath");
snprintf(buf, sizeof(buf), "cdev=%s", gp->name);
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 62c7941..90b7895 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -286,8 +286,11 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp,
if (hdr->e_machine == bi->machine &&
(hdr->e_ident[EI_OSABI] == bi->brand ||
strncmp((const char *)&hdr->e_ident[OLD_EI_BRAND],
- bi->compat_3_brand, strlen(bi->compat_3_brand)) == 0))
- return (bi);
+ bi->compat_3_brand, strlen(bi->compat_3_brand)) == 0)) {
+ /* Looks good, but give brand a chance to veto */
+ if (!bi->header_supported || bi->header_supported(imgp))
+ return (bi);
+ }
}
/* No known brand, see if the header is recognized by any brand */
diff --git a/sys/kern/kern_dump.c b/sys/kern/kern_dump.c
index b33247c..1fd2fdd 100644
--- a/sys/kern/kern_dump.c
+++ b/sys/kern/kern_dump.c
@@ -66,10 +66,10 @@ static size_t fragsz;
struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS];
+#if !defined(__powerpc__) && !defined(__sparc__)
void
dumpsys_gen_pa_init(void)
{
-#if !defined(__sparc__) && !defined(__powerpc__)
int n, idx;
bzero(dump_map, sizeof(dump_map));
@@ -80,8 +80,8 @@ dumpsys_gen_pa_init(void)
dump_map[n].pa_start = dump_avail[idx];
dump_map[n].pa_size = dump_avail[idx + 1] - dump_avail[idx];
}
-#endif
}
+#endif
struct dump_pa *
dumpsys_gen_pa_next(struct dump_pa *mdp)
@@ -99,20 +99,24 @@ dumpsys_gen_pa_next(struct dump_pa *mdp)
void
dumpsys_gen_wbinv_all(void)
{
+
}
void
dumpsys_gen_unmap_chunk(vm_paddr_t pa __unused, size_t chunk __unused,
void *va __unused)
{
+
}
+#if !defined(__sparc__)
int
dumpsys_gen_write_aux_headers(struct dumperinfo *di)
{
return (0);
}
+#endif
int
dumpsys_buf_write(struct dumperinfo *di, char *ptr, size_t sz)
@@ -233,6 +237,7 @@ dumpsys_foreach_chunk(dumpsys_callback_t cb, void *arg)
return (seqnr);
}
+#if !defined(__sparc__)
static off_t fileofs;
static int
@@ -391,3 +396,4 @@ dumpsys_generic(struct dumperinfo *di)
printf("\n** DUMP FAILED (ERROR %d) **\n", error);
return (error);
}
+#endif
diff --git a/sys/mips/conf/AP143 b/sys/mips/conf/AP143
new file mode 100644
index 0000000..296f0c8
--- /dev/null
+++ b/sys/mips/conf/AP143
@@ -0,0 +1,51 @@
+#
+# AP143 - the AP143 reference board from Qualcomm Atheros includes:
+#
+# * AR9330 SoC
+# * 32MB RAM
+# * 4MB flash
+# * Integrated 1x1 2GHz wifi and 10/100 bridge
+#
+# $FreeBSD$
+#
+
+# Include the default QCA953x parameters
+include "QCA953X_BASE"
+
+ident AP143
+
+# Override hints with board values
+hints "AP143.hints"
+
+# Force the board memory - the base AP121 only has 16MB RAM
+options AR71XX_REALMEM=(32*1024*1024)
+
+# i2c GPIO bus
+#device gpioiic
+#device iicbb
+#device iicbus
+#device iic
+
+# Options required for miiproxy and mdiobus
+options ARGE_MDIO # Export an MDIO bus separate from arge
+device miiproxy # MDIO bus <-> MII PHY rendezvous
+
+device etherswitch
+device arswitch
+
+# read MSDOS formatted disks - USB
+#options MSDOSFS
+
+# Enable the uboot environment stuff rather then the
+# redboot stuff.
+options AR71XX_ENV_UBOOT
+
+# uzip - to boot natively from flash
+device geom_uncompress
+options GEOM_UNCOMPRESS
+
+# Used for the static uboot partition map
+device geom_map
+
+# Boot off of the rootfs, as defined in the geom_map setup.
+options ROOTDEVNAME=\"ufs:map/rootfs.uncompress\"
diff --git a/sys/mips/conf/AP143.hints b/sys/mips/conf/AP143.hints
new file mode 100644
index 0000000..eb95d00
--- /dev/null
+++ b/sys/mips/conf/AP143.hints
@@ -0,0 +1,105 @@
+#
+# This file adds to the values in QCA953X_BASE.hints.
+#
+# $FreeBSD$
+
+# Embedded Atheros Switch
+hint.arswitch.0.at="mdio1"
+hint.arswitch.0.is_7240=0
+hint.arswitch.0.is_9340=1
+hint.arswitch.0.numphys=4
+hint.arswitch.0.phy4cpu=1 # phy 4 is a "CPU" separate PHY
+hint.arswitch.0.is_rgmii=0
+hint.arswitch.0.is_gmii=1 # arge1 <-> switch PHY is GMII
+
+# arge0 - MII, autoneg, phy(4)
+# MAC for arge0 is the first 6 bytes of the ART
+hint.arge.0.eeprommac=0x1fff0000
+hint.arge.0.phymask=0x10 # PHY4
+hint.arge.0.mdio=mdioproxy2 # .. off of the switch mdiobus
+
+# arge1 - GMII, 1000/full
+hint.arge.1.eeprommac=0x1fff0006
+hint.arge.1.phymask=0x0 # No directly mapped PHYs
+hint.arge.1.media=1000
+hint.arge.1.fduplex=1
+
+# The AP121 4MB flash layout:
+#
+# bootargs=console=ttyS0,115200 root=31:02 rootfstype=squashfs
+# init=/sbin/init mtdparts=ar7240-nor0:256k(u-boot),64k(u-boot-env),
+# 2752k(rootfs),896k(uImage),64k(NVRAM),64k(ART)
+#
+# So:
+# 256k: uboot
+# 64: uboot-env
+# 2752k: rootfs
+# 896k: kernel
+# 64k: config
+# 64k: ART
+
+hint.map.0.at="flash/spi0"
+hint.map.0.start=0x00000000
+hint.map.0.end=0x000040000
+hint.map.0.name="uboot"
+hint.map.0.readonly=1
+
+hint.map.1.at="flash/spi0"
+hint.map.1.start=0x00040000
+hint.map.1.end=0x00050000
+hint.map.1.name="uboot-env"
+hint.map.1.readonly=0
+
+hint.map.2.at="flash/spi0"
+hint.map.2.start=0x00050000
+hint.map.2.end=0x00300000
+hint.map.2.name="rootfs"
+hint.map.2.readonly=0
+
+hint.map.3.at="flash/spi0"
+hint.map.3.start=0x00300000
+hint.map.3.end=0x003e0000
+hint.map.3.name="kernel"
+hint.map.3.readonly=0
+
+hint.map.4.at="flash/spi0"
+hint.map.4.start=0x003e0000
+hint.map.4.end=0x003f0000
+hint.map.4.name="cfg"
+hint.map.4.readonly=0
+
+# This is radio calibration section. It is (or should be!) unique
+# for each board, to take into account thermal and electrical differences
+# as well as the regulatory compliance data.
+#
+hint.map.5.at="flash/spi0"
+hint.map.5.start=0x003f0000
+hint.map.5.end=0x00400000
+hint.map.5.name="art"
+hint.map.5.readonly=1
+
+# GPIO specific configuration block
+
+# Don't flip on anything that isn't already enabled.
+# This includes leaving the SPI CS1/CS2 pins as GPIO pins as they're
+# not used here.
+hint.gpio.0.function_set=0x00000000
+hint.gpio.0.function_clear=0x00000000
+
+# These are the GPIO LEDs and buttons which can be software controlled.
+#hint.gpio.0.pinmask=0x001c02ae
+# hint.gpio.0.pinmask=0x00001803
+
+# gpio0 - WLAN LED
+# gpio1 - USB LED
+# gpio11 - Jumpstart button
+# gpio12 - Reset button
+
+# LEDs are configured separately and driven by the LED device
+#hint.gpioled.0.at="gpiobus0"
+#hint.gpioled.0.name="wlan"
+#hint.gpioled.0.pins=0x0001
+
+#hint.gpioled.1.at="gpiobus0"
+#hint.gpioled.1.name="usb"
+#hint.gpioled.1.pins=0x0002
diff --git a/sys/mips/conf/ONIONOMEGA b/sys/mips/conf/ONIONOMEGA
new file mode 100644
index 0000000..94c8a33
--- /dev/null
+++ b/sys/mips/conf/ONIONOMEGA
@@ -0,0 +1,53 @@
+#
+# Onion Omega - an AR9330 based SoC
+#
+# https://onion.io/omega/
+#
+# * AR9330 SoC
+# * 64MB RAM
+# * 16MB flash
+# * Integrated 1x1 2GHz wifi and optional 10/100 ethernet
+#
+# $FreeBSD$
+#
+
+# Include the default AR933x parameters
+include "AR933X_BASE"
+
+ident ONIONOMEGA
+
+# Override hints with board values
+hints "ONIONOMEGA.hints"
+
+# Board memory - 64MB
+options AR71XX_REALMEM=(64*1024*1024)
+
+# i2c GPIO bus
+#device gpioiic
+#device iicbb
+#device iicbus
+#device iic
+
+# Options required for miiproxy and mdiobus
+options ARGE_MDIO # Export an MDIO bus separate from arge
+device miiproxy # MDIO bus <-> MII PHY rendezvous
+
+device etherswitch
+device arswitch
+
+# read MSDOS formatted disks - USB
+#options MSDOSFS
+
+# Enable the uboot environment stuff rather then the
+# redboot stuff.
+options AR71XX_ENV_UBOOT
+
+# uzip - to boot natively from flash
+device geom_uncompress
+options GEOM_UNCOMPRESS
+
+# Used for the static uboot partition map
+device geom_map
+
+# Boot off of the rootfs, as defined in the geom_map setup.
+options ROOTDEVNAME=\"ufs:map/rootfs.uncompress\"
diff --git a/sys/mips/conf/ONIONOMEGA.hints b/sys/mips/conf/ONIONOMEGA.hints
new file mode 100644
index 0000000..d3a6869
--- /dev/null
+++ b/sys/mips/conf/ONIONOMEGA.hints
@@ -0,0 +1,94 @@
+#
+# This file adds to the values in AR933X_BASE.hints.
+#
+# $FreeBSD$
+
+# mdiobus on arge1
+hint.argemdio.0.at="nexus0"
+hint.argemdio.0.maddr=0x1a000000
+hint.argemdio.0.msize=0x1000
+hint.argemdio.0.order=0
+
+# Embedded Atheros Switch
+hint.arswitch.0.at="mdio0"
+
+# XXX this should really say it's an AR933x switch, as there
+# are some vlan specific differences here!
+hint.arswitch.0.is_7240=1
+hint.arswitch.0.numphys=4
+hint.arswitch.0.phy4cpu=1 # phy 4 is a "CPU" separate PHY
+hint.arswitch.0.is_rgmii=0
+hint.arswitch.0.is_gmii=1 # arge1 <-> switch PHY is GMII
+
+# arge0 - MII, autoneg, phy(4)
+hint.arge.0.phymask=0x10 # PHY4
+hint.arge.0.mdio=mdioproxy1 # .. off of the switch mdiobus
+hint.arge.0.eeprommac=0x1fff0000
+
+# arge1 - GMII, 1000/full
+hint.arge.1.phymask=0x0 # No directly mapped PHYs
+hint.arge.1.media=1000
+hint.arge.1.fduplex=1
+hint.arge.1.eeprommac=0x1fff0006
+
+# 16MB flash layout:
+# [ 0.510000] 5 tp-link partitions found on MTD device spi0.0
+# [ 0.510000] Creating 5 MTD partitions on "spi0.0":
+# [ 0.520000] 0x000000000000-0x000000020000 : "u-boot"
+# [ 0.520000] 0x000000020000-0x000000136468 : "kernel"
+# [ 0.530000] 0x000000136468-0x000000ff0000 : "rootfs"
+# [ 0.530000] mtd: device 2 (rootfs) set to be root filesystem
+# [ 0.540000] 1 squashfs-split partitions found on MTD device rootfs
+# [ 0.540000] 0x000000730000-0x000000fe0000 : "rootfs_data"
+# [ 0.540000] 0x000000fe0000-0x000000ff0000 : "nvram"
+# [ 0.550000] 0x000000ff0000-0x000001000000 : "art"
+# [ 0.560000] 0x000000020000-0x000000fe0000 : "firmware"
+
+# 64KiB uboot
+hint.map.0.at="flash/spi0"
+hint.map.0.start=0x00000000
+hint.map.0.end=0x00010000
+hint.map.0.name="u-boot"
+hint.map.0.readonly=1
+
+# 64KiB uboot
+hint.map.1.at="flash/spi0"
+hint.map.1.start=0x00010000
+hint.map.1.end=0x00020000
+hint.map.1.name="uboot-env"
+hint.map.1.readonly=1
+
+# kernel
+hint.map.2.at="flash/spi0"
+hint.map.2.start=0x00020000
+hint.map.2.end="search:0x00020000:0x10000:.!/bin/sh"
+hint.map.2.name="kernel"
+hint.map.2.readonly=1
+
+# rootfs ulzma
+hint.map.3.at="flash/spi0"
+hint.map.3.start="search:0x00020000:0x10000:.!/bin/sh"
+hint.map.3.end=0x00fe0000
+hint.map.3.name="rootfs"
+hint.map.3.readonly=1
+
+# 64KiB cfg
+hint.map.4.at="flash/spi0"
+hint.map.4.start=0x00fe0000
+hint.map.4.end=0x00ff0000
+hint.map.4.name="cfg"
+hint.map.4.readonly=0
+
+# all firmware 16000KiB
+hint.map.5.at="flash/spi0"
+hint.map.5.start=0x00020000
+hint.map.5.end=0x00ff0000
+hint.map.5.name="firmware"
+hint.map.5.readonly=0
+
+# 64KiB ART
+hint.map.6.at="flash/spi0"
+hint.map.6.start=0x00ff0000
+hint.map.6.end=0x01000000
+hint.map.6.name="ART"
+hint.map.6.readonly=1
diff --git a/sys/mips/conf/QCA953X_BASE b/sys/mips/conf/QCA953X_BASE
new file mode 100644
index 0000000..ec2a464
--- /dev/null
+++ b/sys/mips/conf/QCA953X_BASE
@@ -0,0 +1,138 @@
+#
+# QCA953x -- Kernel configuration base file for the Qualcomm Atheros QCA953x SoC.
+#
+# This file (and the hints file accompanying it) are not designed to be
+# used by themselves. Instead, users of this file should create a kernel
+# config file which includes this file (which gets the basic hints), then
+# override the default options (adding devices as needed) and adding
+# hints as needed (for example, the GPIO and LAN PHY.)
+#
+# $FreeBSD$
+#
+
+machine mips mips
+ident QCA953X_BASE
+cpu CPU_MIPS4KC
+makeoptions KERNLOADADDR=0x80050000
+options HZ=1000
+
+files "../atheros/files.ar71xx"
+hints "QCA953X_BASE.hints"
+
+makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
+makeoptions MODULES_OVERRIDE="gpio ar71xx if_gif if_vlan if_gre if_bridge bridgestp usb wlan wlan_xauth wlan_acl wlan_wep wlan_tkip wlan_ccmp wlan_rssadapt wlan_amrr hwpmc ipfw"
+
+options DDB
+options KDB
+options ALQ
+options BREAK_TO_DEBUGGER
+options ALT_BREAK_TO_DEBUGGER
+
+options SCHED_4BSD #4BSD scheduler
+options INET #InterNETworking
+#options INET6 #InterNETworking
+#options NFSCL #Network Filesystem Client
+options PSEUDOFS #Pseudo-filesystem framework
+options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
+
+# Don't include the SCSI/CAM strings in the default build
+options SCSI_NO_SENSE_STRINGS
+options SCSI_NO_OP_STRINGS
+
+# .. And no sysctl strings
+options NO_SYSCTL_DESCR
+
+# For small memory footprints
+options VM_KMEM_SIZE_SCALE=1
+
+# Limit IO size
+options NBUF=128
+
+# Limit UMTX hash size
+# options UMTX_NUM_CHAINS=64
+
+#options UMA_DEBUG_ALLOC
+
+# PMC
+options HWPMC_HOOKS
+#options HWPMC_MIPS_BACKTRACE
+device hwpmc
+device hwpmc_mips24k
+
+options ARGE_DEBUG
+
+# options NFS_LEGACYRPC
+# Debugging for use in -current
+options INVARIANTS
+options INVARIANT_SUPPORT
+options WITNESS
+options WITNESS_SKIPSPIN
+options FFS #Berkeley Fast Filesystem
+#options SOFTUPDATES #Enable FFS soft updates support
+#options UFS_ACL #Support for access control lists
+#options UFS_DIRHASH #Improve performance on big directories
+options NO_FFS_SNAPSHOT # We don't require snapshot support
+
+options IPFIREWALL_DEFAULT_TO_ACCEPT
+
+# Wireless NIC cards
+options IEEE80211_DEBUG
+options IEEE80211_SUPPORT_MESH
+options IEEE80211_SUPPORT_TDMA
+options IEEE80211_SUPPORT_SUPERG
+options IEEE80211_ALQ # 802.11 ALQ logging support
+device wlan # 802.11 support
+device wlan_wep # 802.11 WEP support
+device wlan_ccmp # 802.11 CCMP support
+device wlan_tkip # 802.11 TKIP support
+device wlan_xauth # 802.11 hostap support
+
+# ath(4)
+device ath # Atheros network device
+device ath_rate_sample
+device ath_ahb # Atheros host bus glue
+options ATH_DEBUG
+options ATH_DIAGAPI
+option ATH_ENABLE_11N
+option AH_DEBUG_ALQ
+
+#device ath_hal
+device ath_ar9300 # AR9330 HAL; no need for the others
+option AH_DEBUG
+option AH_SUPPORT_AR5416 # 11n HAL support
+option AH_SUPPORT_AR9330 # Chipset support
+option AH_AR5416_INTERRUPT_MITIGATION
+
+device mii
+device arge
+
+device usb
+options USB_EHCI_BIG_ENDIAN_DESC # handle big-endian byte order
+options USB_DEBUG
+options USB_HOST_ALIGN=32 # AR71XX (MIPS in general?) requires this
+device ehci
+
+device scbus
+device umass
+device da
+
+device spibus
+device ar71xx_spi
+device mx25l
+device ar71xx_wdog
+
+# Handle 25MHz refclock by allowing a higher baudrate error tolerance.
+device uart
+device uart_ar71xx
+options UART_DEV_TOLERANCE_PCT=50
+
+device ar71xx_apb
+
+device loop
+device ether
+device md
+device bpf
+device random
+device if_bridge
+device gpio
+device gpioled
diff --git a/sys/mips/conf/QCA953X_BASE.hints b/sys/mips/conf/QCA953X_BASE.hints
new file mode 100644
index 0000000..4bbb083
--- /dev/null
+++ b/sys/mips/conf/QCA953X_BASE.hints
@@ -0,0 +1,75 @@
+# This file (and the kernel config file accompanying it) are not designed
+# to be used by themselves. Instead, users of this file should create a
+# kernel # config file which includes this file (which gets the basic hints),
+# then override the default options (adding devices as needed) and adding
+# hints as needed (for example, the GPIO and LAN PHY.)
+
+# $FreeBSD$
+
+hint.apb.0.at="nexus0"
+hint.apb.0.irq=4
+
+# mdiobus on arge0 - required to bring up arge0
+hint.argemdio.0.at="nexus0"
+hint.argemdio.0.maddr=0x19000000
+hint.argemdio.0.msize=0x1000
+hint.argemdio.0.order=0
+
+# mdiobus on arge1 - this is what the internal switch is hooked into.
+hint.argemdio.1.at="nexus0"
+hint.argemdio.1.maddr=0x1a000000
+hint.argemdio.1.msize=0x1000
+hint.argemdio.1.order=0
+
+# uart0
+hint.uart.0.at="apb0"
+# see atheros/uart_cpu_ar71xx.c why +3
+hint.uart.0.maddr=0x18020003
+hint.uart.0.msize=0x18
+hint.uart.0.irq=3
+
+# ehci - on IP3
+hint.ehci.0.at="nexus0"
+hint.ehci.0.maddr=0x1b000100
+hint.ehci.0.msize=0x00ffff00
+hint.ehci.0.irq=1
+
+hint.arge.0.at="nexus0"
+hint.arge.0.maddr=0x19000000
+hint.arge.0.msize=0x1000
+hint.arge.0.irq=2
+
+hint.arge.1.at="nexus0"
+hint.arge.1.maddr=0x1a000000
+hint.arge.1.msize=0x1000
+hint.arge.1.irq=3
+
+# XXX The ath device hangs off of the AHB, rather than the Nexus.
+hint.ath.0.at="nexus0"
+hint.ath.0.maddr=0x18100000
+hint.ath.0.msize=0x20000
+hint.ath.0.irq=0
+hint.ath.0.vendor_id=0x168c
+# XXX for now this is 0x00ff because there's no HAL support
+# yet for honeybee.
+hint.ath.0.device_id=0x00ff
+# Set this to define where the ath calibration data
+# should be fetched from in physical memory.
+# hint.ath.0.eepromaddr=0x1fff1000
+
+# SPI flash
+hint.spi.0.at="nexus0"
+hint.spi.0.maddr=0x1f000000
+hint.spi.0.msize=0x10
+
+hint.mx25l.0.at="spibus0"
+hint.mx25l.0.cs=0
+
+# Watchdog
+hint.ar71xx_wdog.0.at="nexus0"
+
+# The GPIO function and pin mask is configured per-board
+hint.gpio.0.at="apb0"
+hint.gpio.0.maddr=0x18040000
+hint.gpio.0.msize=0x1000
+hint.gpio.0.irq=2
diff --git a/sys/modules/tests/framework/Makefile b/sys/modules/tests/framework/Makefile
index 7b64cd1..f5f608f 100644
--- a/sys/modules/tests/framework/Makefile
+++ b/sys/modules/tests/framework/Makefile
@@ -6,6 +6,7 @@
KMOD= kern_testfrwk
SRCS= kern_testfrwk.c
+SRCS+= bus_if.h device_if.h
#
# Enable full debugging
diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h
index bab26fe..c9b2769 100644
--- a/sys/net/pfkeyv2.h
+++ b/sys/net/pfkeyv2.h
@@ -225,7 +225,7 @@ struct sadb_x_policy {
u_int8_t sadb_x_policy_dir; /* direction, see ipsec.h */
u_int8_t sadb_x_policy_reserved;
u_int32_t sadb_x_policy_id;
- u_int32_t sadb_x_policy_reserved2;
+ u_int32_t sadb_x_policy_priority;
};
_Static_assert(sizeof(struct sadb_x_policy) == 16, "struct size mismatch");
diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h
index 328e8a3..c01e54f 100644
--- a/sys/netipsec/ipsec.h
+++ b/sys/netipsec/ipsec.h
@@ -92,6 +92,7 @@ struct secpolicy {
u_int state;
#define IPSEC_SPSTATE_DEAD 0
#define IPSEC_SPSTATE_ALIVE 1
+ u_int32_t priority; /* priority of this policy */
u_int32_t id; /* It's unique number on the system. */
/*
* lifetime handler.
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index 9927509..01c589e 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -473,7 +473,7 @@ static void key_porttosaddr(struct sockaddr *, u_int16_t);
key_porttosaddr((struct sockaddr *)(saddr), (port))
static struct mbuf *key_setsadbxsa2(u_int8_t, u_int32_t, u_int32_t);
static struct mbuf *key_setsadbxpolicy(u_int16_t, u_int8_t,
- u_int32_t);
+ u_int32_t, u_int32_t);
static struct seckey *key_dup_keymsg(const struct sadb_key *, u_int,
struct malloc_type *);
static struct seclifetime *key_dup_lifemsg(const struct sadb_lifetime *src,
@@ -1209,6 +1209,29 @@ key_unlink(struct secpolicy *sp)
}
/*
+ * insert a secpolicy into the SP database. Lower priorities first
+ */
+static void
+key_insertsp(struct secpolicy *newsp)
+{
+ struct secpolicy *sp;
+
+ SPTREE_WLOCK();
+ TAILQ_FOREACH(sp, &V_sptree[newsp->spidx.dir], chain) {
+ if (newsp->priority < sp->priority) {
+ TAILQ_INSERT_BEFORE(sp, newsp, chain);
+ goto done;
+ }
+ }
+
+ TAILQ_INSERT_TAIL(&V_sptree[newsp->spidx.dir], newsp, chain);
+
+done:
+ newsp->state = IPSEC_SPSTATE_ALIVE;
+ SPTREE_WUNLOCK();
+}
+
+/*
* Must be called after calling key_allocsp().
* For the packet with socket.
*/
@@ -1391,6 +1414,7 @@ key_msg2sp(struct sadb_x_policy *xpl0, size_t len, int *error)
newsp->spidx.dir = xpl0->sadb_x_policy_dir;
newsp->policy = xpl0->sadb_x_policy_type;
+ newsp->priority = xpl0->sadb_x_policy_priority;
/* check policy */
switch (xpl0->sadb_x_policy_type) {
@@ -1627,6 +1651,7 @@ key_sp2msg(struct secpolicy *sp)
xpl->sadb_x_policy_type = sp->policy;
xpl->sadb_x_policy_dir = sp->spidx.dir;
xpl->sadb_x_policy_id = sp->id;
+ xpl->sadb_x_policy_priority = sp->priority;
p = (caddr_t)xpl + sizeof(*xpl);
/* if is the policy for ipsec ? */
@@ -1904,10 +1929,7 @@ key_spdadd(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
newsp->lifetime = lft ? lft->sadb_lifetime_addtime : 0;
newsp->validtime = lft ? lft->sadb_lifetime_usetime : 0;
- SPTREE_WLOCK();
- TAILQ_INSERT_TAIL(&V_sptree[newsp->spidx.dir], newsp, chain);
- newsp->state = IPSEC_SPSTATE_ALIVE;
- SPTREE_WUNLOCK();
+ key_insertsp(newsp);
/* delete the entry in spacqtree */
if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {
@@ -3744,7 +3766,7 @@ key_porttosaddr(struct sockaddr *sa, u_int16_t port)
* set data into sadb_x_policy
*/
static struct mbuf *
-key_setsadbxpolicy(u_int16_t type, u_int8_t dir, u_int32_t id)
+key_setsadbxpolicy(u_int16_t type, u_int8_t dir, u_int32_t id, u_int32_t priority)
{
struct mbuf *m;
struct sadb_x_policy *p;
@@ -3764,6 +3786,7 @@ key_setsadbxpolicy(u_int16_t type, u_int8_t dir, u_int32_t id)
p->sadb_x_policy_type = type;
p->sadb_x_policy_dir = dir;
p->sadb_x_policy_id = id;
+ p->sadb_x_policy_priority = priority;
return m;
}
@@ -6205,7 +6228,7 @@ key_acquire(const struct secasindex *saidx, struct secpolicy *sp)
/* set sadb_x_policy */
if (sp) {
- m = key_setsadbxpolicy(sp->policy, sp->spidx.dir, sp->id);
+ m = key_setsadbxpolicy(sp->policy, sp->spidx.dir, sp->id, sp->priority);
if (!m) {
error = ENOBUFS;
goto fail;
@@ -6706,7 +6729,7 @@ key_register(struct socket *so, struct mbuf *m, const struct sadb_msghdr *mhp)
continue;
alg = (struct sadb_alg *)(mtod(n, caddr_t) + off);
alg->sadb_alg_id = i;
- alg->sadb_alg_ivlen = ealgo->blocksize;
+ alg->sadb_alg_ivlen = ealgo->ivsize;
alg->sadb_alg_minbits = _BITS(ealgo->minkey);
alg->sadb_alg_maxbits = _BITS(ealgo->maxkey);
off += PFKEY_ALIGN8(sizeof(struct sadb_alg));
diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c
index 9f645c0..c8b5f16 100644
--- a/sys/netipsec/xform_esp.c
+++ b/sys/netipsec/xform_esp.c
@@ -200,16 +200,10 @@ esp_init(struct secasvar *sav, struct xformsw *xsp)
return EINVAL;
}
- /*
- * NB: The null xform needs a non-zero blocksize to keep the
- * crypto code happy but if we use it to set ivlen then
- * the ESP header will be processed incorrectly. The
- * compromise is to force it to zero here.
- */
if (SAV_ISCTRORGCM(sav))
sav->ivlen = 8; /* RFC4106 3.1 and RFC3686 3.1 */
else
- sav->ivlen = (txform == &enc_xform_null ? 0 : txform->ivsize);
+ sav->ivlen = txform->ivsize;
/*
* Setup AH-related state.
diff --git a/sys/netpfil/ipfw/ip_fw_dynamic.c b/sys/netpfil/ipfw/ip_fw_dynamic.c
index 083244d..9db59a2 100644
--- a/sys/netpfil/ipfw/ip_fw_dynamic.c
+++ b/sys/netpfil/ipfw/ip_fw_dynamic.c
@@ -735,6 +735,9 @@ ipfw_install_state(struct ip_fw_chain *chain, struct ip_fw *rule,
id.fib = M_GETFIB(args->m);
if (IS_IP6_FLOW_ID (&(args->f_id))) {
+ bzero(&id.src_ip6, sizeof(id.src_ip6));
+ bzero(&id.dst_ip6, sizeof(id.dst_ip6));
+
if (limit_mask & DYN_SRC_ADDR)
id.src_ip6 = args->f_id.src_ip6;
if (limit_mask & DYN_DST_ADDR)
diff --git a/sys/netsmb/smb_conn.c b/sys/netsmb/smb_conn.c
index d58bc72..adc171c 100644
--- a/sys/netsmb/smb_conn.c
+++ b/sys/netsmb/smb_conn.c
@@ -683,7 +683,9 @@ int
smb_vc_disconnect(struct smb_vc *vcp)
{
- smb_iod_request(vcp->vc_iod, SMBIOD_EV_DISCONNECT | SMBIOD_EV_SYNC, NULL);
+ if (vcp->vc_iod != NULL)
+ smb_iod_request(vcp->vc_iod, SMBIOD_EV_DISCONNECT |
+ SMBIOD_EV_SYNC, NULL);
return 0;
}
diff --git a/sys/netsmb/smb_iod.c b/sys/netsmb/smb_iod.c
index dfdd6f2..412f816 100644
--- a/sys/netsmb/smb_iod.c
+++ b/sys/netsmb/smb_iod.c
@@ -659,6 +659,11 @@ smb_iod_thread(void *arg)
break;
tsleep(&iod->iod_flags, PWAIT, "90idle", iod->iod_sleeptimo);
}
+
+ /* We can now safely destroy the mutexes and free the iod structure. */
+ smb_sl_destroy(&iod->iod_rqlock);
+ smb_sl_destroy(&iod->iod_evlock);
+ free(iod, M_SMBIOD);
mtx_unlock(&Giant);
kproc_exit(0);
}
@@ -685,6 +690,9 @@ smb_iod_create(struct smb_vc *vcp)
RFNOWAIT, 0, "smbiod%d", iod->iod_id);
if (error) {
SMBERROR("can't start smbiod: %d", error);
+ vcp->vc_iod = NULL;
+ smb_sl_destroy(&iod->iod_rqlock);
+ smb_sl_destroy(&iod->iod_evlock);
free(iod, M_SMBIOD);
return error;
}
@@ -695,9 +703,6 @@ int
smb_iod_destroy(struct smbiod *iod)
{
smb_iod_request(iod, SMBIOD_EV_SHUTDOWN | SMBIOD_EV_SYNC, NULL);
- smb_sl_destroy(&iod->iod_rqlock);
- smb_sl_destroy(&iod->iod_evlock);
- free(iod, M_SMBIOD);
return 0;
}
diff --git a/sys/opencrypto/xform.c b/sys/opencrypto/xform.c
index cb44bfa..3dee366 100644
--- a/sys/opencrypto/xform.c
+++ b/sys/opencrypto/xform.c
@@ -154,7 +154,7 @@ MALLOC_DEFINE(M_XDATA, "xform", "xform data buffers");
struct enc_xform enc_xform_null = {
CRYPTO_NULL_CBC, "NULL",
/* NB: blocksize of 4 is to generate a properly aligned ESP header */
- NULL_BLOCK_LEN, NULL_BLOCK_LEN, NULL_MIN_KEY, NULL_MAX_KEY,
+ NULL_BLOCK_LEN, 0, NULL_MIN_KEY, NULL_MAX_KEY,
null_encrypt,
null_decrypt,
null_setkey,
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
index 3766d86..90cb4a3 100644
--- a/sys/powerpc/aim/mmu_oea64.c
+++ b/sys/powerpc/aim/mmu_oea64.c
@@ -493,9 +493,9 @@ moea64_add_ofw_mappings(mmu_t mmup, phandle_t mmu, size_t sz)
int i, j;
bzero(translations, sz);
- OF_getprop(OF_finddevice("/"), "#address-cells", &acells,
+ OF_getencprop(OF_finddevice("/"), "#address-cells", &acells,
sizeof(acells));
- if (OF_getprop(mmu, "translations", trans_cells, sz) == -1)
+ if (OF_getencprop(mmu, "translations", trans_cells, sz) == -1)
panic("moea64_bootstrap: can't get ofw translations");
CTR0(KTR_PMAP, "moea64_add_ofw_mappings: translations");
@@ -856,7 +856,7 @@ moea64_late_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend
*/
chosen = OF_finddevice("/chosen");
- if (chosen != -1 && OF_getprop(chosen, "mmu", &mmui, 4) != -1) {
+ if (chosen != -1 && OF_getencprop(chosen, "mmu", &mmui, 4) != -1) {
mmu = OF_instance_to_package(mmui);
if (mmu == -1 ||
(sz = OF_getproplen(mmu, "translations")) == -1)
diff --git a/sys/powerpc/aim/moea64_native.c b/sys/powerpc/aim/moea64_native.c
index a601fcb..b2ca5ae 100644
--- a/sys/powerpc/aim/moea64_native.c
+++ b/sys/powerpc/aim/moea64_native.c
@@ -230,7 +230,7 @@ moea64_pte_synch_native(mmu_t mmu, struct pvo_entry *pvo)
moea64_pte_from_pvo(pvo, &properpt);
rw_rlock(&moea64_eviction_lock);
- if ((pt->pte_hi & LPTE_AVPN_MASK) !=
+ if ((be64toh(pt->pte_hi) & LPTE_AVPN_MASK) !=
(properpt.pte_hi & LPTE_AVPN_MASK)) {
/* Evicted */
rw_runlock(&moea64_eviction_lock);
@@ -257,7 +257,7 @@ moea64_pte_clear_native(mmu_t mmu, struct pvo_entry *pvo, uint64_t ptebit)
moea64_pte_from_pvo(pvo, &properpt);
rw_rlock(&moea64_eviction_lock);
- if ((pt->pte_hi & LPTE_AVPN_MASK) !=
+ if ((be64toh(pt->pte_hi) & LPTE_AVPN_MASK) !=
(properpt.pte_hi & LPTE_AVPN_MASK)) {
/* Evicted */
rw_runlock(&moea64_eviction_lock);
@@ -268,11 +268,15 @@ moea64_pte_clear_native(mmu_t mmu, struct pvo_entry *pvo, uint64_t ptebit)
/* See "Resetting the Reference Bit" in arch manual */
PTESYNC();
/* 2-step here safe: precision is not guaranteed */
- ptelo = pt->pte_lo;
+ ptelo = be64toh(pt->pte_lo);
/* One-byte store to avoid touching the C bit */
((volatile uint8_t *)(&pt->pte_lo))[6] =
+#if BYTE_ORDER == BIG_ENDIAN
((uint8_t *)(&properpt.pte_lo))[6];
+#else
+ ((uint8_t *)(&properpt.pte_lo))[1];
+#endif
rw_runlock(&moea64_eviction_lock);
critical_enter();
@@ -297,7 +301,7 @@ moea64_pte_unset_native(mmu_t mmu, struct pvo_entry *pvo)
moea64_pte_from_pvo(pvo, &properpt);
rw_rlock(&moea64_eviction_lock);
- if ((pt->pte_hi & LPTE_AVPN_MASK) !=
+ if ((be64toh(pt->pte_hi & LPTE_AVPN_MASK)) !=
(properpt.pte_hi & LPTE_AVPN_MASK)) {
/* Evicted */
moea64_pte_overflow--;
@@ -311,7 +315,7 @@ moea64_pte_unset_native(mmu_t mmu, struct pvo_entry *pvo)
*/
isync();
critical_enter();
- pt->pte_hi = (pt->pte_hi & ~LPTE_VALID) | LPTE_LOCKED;
+ pt->pte_hi = be64toh((pt->pte_hi & ~LPTE_VALID) | LPTE_LOCKED);
PTESYNC();
TLBIE(pvo->pvo_vpn);
ptelo = be64toh(pt->pte_lo);
@@ -337,13 +341,13 @@ moea64_pte_replace_native(mmu_t mmu, struct pvo_entry *pvo, int flags)
moea64_pte_from_pvo(pvo, &properpt);
rw_rlock(&moea64_eviction_lock);
- if ((pt->pte_hi & LPTE_AVPN_MASK) !=
+ if ((be64toh(pt->pte_hi) & LPTE_AVPN_MASK) !=
(properpt.pte_hi & LPTE_AVPN_MASK)) {
rw_runlock(&moea64_eviction_lock);
return (-1);
}
- pt->pte_hi = properpt.pte_hi;
- ptelo = pt->pte_lo;
+ pt->pte_hi = htobe64(properpt.pte_hi);
+ ptelo = be64toh(pt->pte_lo);
rw_runlock(&moea64_eviction_lock);
} else {
/* Otherwise, need reinsertion and deletion */
@@ -571,9 +575,9 @@ moea64_insert_to_pteg_native(struct lpte *pvo_pt, uintptr_t slotbase,
* Update the PTE as per "Adding a Page Table Entry". Lock is released
* by setting the high doubleworld.
*/
- pt->pte_lo = pvo_pt->pte_lo;
+ pt->pte_lo = htobe64(pvo_pt->pte_lo);
EIEIO();
- pt->pte_hi = pvo_pt->pte_hi;
+ pt->pte_hi = htobe64(pvo_pt->pte_hi);
PTESYNC();
/* Keep statistics */
diff --git a/sys/powerpc/include/bus.h b/sys/powerpc/include/bus.h
index 658c4eb..0b47a63 100644
--- a/sys/powerpc/include/bus.h
+++ b/sys/powerpc/include/bus.h
@@ -79,9 +79,14 @@
#define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFUL
#define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFFUL
#else
+#ifdef BOOKE
+#define BUS_SPACE_MAXADDR 0xFFFFFFFFFFULL
+#define BUS_SPACE_MAXSIZE 0xFFFFFFFFUL
+#else
#define BUS_SPACE_MAXADDR 0xFFFFFFFFUL
#define BUS_SPACE_MAXSIZE 0xFFFFFFFFUL
#endif
+#endif
#define BUS_SPACE_MAP_CACHEABLE 0x01
#define BUS_SPACE_MAP_LINEAR 0x02
diff --git a/sys/powerpc/mpc85xx/mpc85xx.c b/sys/powerpc/mpc85xx/mpc85xx.c
index e94a1d8..6608b4d 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.c
+++ b/sys/powerpc/mpc85xx/mpc85xx.c
@@ -27,6 +27,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_platform.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
@@ -45,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <powerpc/mpc85xx/mpc85xx.h>
+
/*
* MPC85xx system specific routines
*/
@@ -70,70 +72,133 @@ int
law_getmax(void)
{
uint32_t ver;
+ int law_max;
ver = SVR_VER(mfspr(SPR_SVR));
- if (ver == SVR_MPC8555E || ver == SVR_MPC8555)
- return (8);
- if (ver == SVR_MPC8548E || ver == SVR_MPC8548 ||
- ver == SVR_MPC8533E || ver == SVR_MPC8533)
- return (10);
+ switch (ver) {
+ case SVR_MPC8555:
+ case SVR_MPC8555E:
+ law_max = 8;
+ break;
+ case SVR_MPC8533:
+ case SVR_MPC8533E:
+ case SVR_MPC8548:
+ case SVR_MPC8548E:
+ law_max = 10;
+ break;
+ case SVR_P5020:
+ case SVR_P5020E:
+ law_max = 32;
+ break;
+ default:
+ law_max = 8;
+ }
- return (12);
+ return (law_max);
+}
+
+static inline void
+law_write(uint32_t n, uint64_t bar, uint32_t sr)
+{
+#if defined(QORIQ_DPAA)
+ ccsr_write4(OCP85XX_LAWBARH(n), bar >> 32);
+ ccsr_write4(OCP85XX_LAWBARL(n), bar);
+#else
+ ccsr_write4(OCP85XX_LAWBAR(n), bar >> 12);
+#endif
+ ccsr_write4(OCP85XX_LAWSR(n), sr);
+
+ /*
+ * The last write to LAWAR should be followed by a read
+ * of LAWAR before any device try to use any of windows.
+ * What more the read of LAWAR should be followed by isync
+ * instruction.
+ */
+
+ ccsr_read4(OCP85XX_LAWSR(n));
+ isync();
+}
+
+static inline void
+law_read(uint32_t n, uint64_t *bar, uint32_t *sr)
+{
+#if defined(QORIQ_DPAA)
+ *bar = (uint64_t)ccsr_read4(OCP85XX_LAWBARH(n)) << 32 |
+ ccsr_read4(OCP85XX_LAWBARL(n));
+#else
+ *bar = (uint64_t)ccsr_read4(OCP85XX_LAWBAR(n)) << 12;
+#endif
+ *sr = ccsr_read4(OCP85XX_LAWSR(n));
+}
+
+static int
+law_find_free(void)
+{
+ uint32_t i,sr;
+ uint64_t bar;
+ int law_max;
+
+ law_max = law_getmax();
+ /* Find free LAW */
+ for (i = 0; i < law_max; i++) {
+ law_read(i, &bar, &sr);
+ if ((sr & 0x80000000) == 0)
+ break;
+ }
+
+ return (i);
}
#define _LAW_SR(trgt,size) (0x80000000 | (trgt << 20) | (ffsl(size) - 2))
-#define _LAW_BAR(addr) (addr >> 12)
int
-law_enable(int trgt, u_long addr, u_long size)
+law_enable(int trgt, uint64_t bar, uint32_t size)
{
- uint32_t bar, sr;
+ uint64_t bar_tmp;
+ uint32_t sr, sr_tmp;
int i, law_max;
if (size == 0)
return (0);
law_max = law_getmax();
- bar = _LAW_BAR(addr);
sr = _LAW_SR(trgt, size);
/* Bail if already programmed. */
- for (i = 0; i < law_max; i++)
- if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
- bar == ccsr_read4(OCP85XX_LAWBAR(i)))
+ for (i = 0; i < law_max; i++) {
+ law_read(i, &bar_tmp, &sr_tmp);
+ if (sr == sr_tmp && bar == bar_tmp)
return (0);
+ }
/* Find an unused access window. */
- for (i = 0; i < law_max; i++)
- if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0)
- break;
+ i = law_find_free();
if (i == law_max)
return (ENOSPC);
- ccsr_write4(OCP85XX_LAWBAR(i), bar);
- ccsr_write4(OCP85XX_LAWSR(i), sr);
+ law_write(i, bar, sr);
return (0);
}
int
-law_disable(int trgt, u_long addr, u_long size)
+law_disable(int trgt, uint64_t bar, uint32_t size)
{
- uint32_t bar, sr;
+ uint64_t bar_tmp;
+ uint32_t sr, sr_tmp;
int i, law_max;
law_max = law_getmax();
- bar = _LAW_BAR(addr);
sr = _LAW_SR(trgt, size);
/* Find and disable requested LAW. */
- for (i = 0; i < law_max; i++)
- if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
- bar == ccsr_read4(OCP85XX_LAWBAR(i))) {
- ccsr_write4(OCP85XX_LAWBAR(i), 0);
- ccsr_write4(OCP85XX_LAWSR(i), 0);
+ for (i = 0; i < law_max; i++) {
+ law_read(i, &bar_tmp, &sr_tmp);
+ if (sr == sr_tmp && bar == bar_tmp) {
+ law_write(i, 0, 0);
return (0);
}
+ }
return (ENOENT);
}
@@ -152,18 +217,22 @@ law_pci_target(struct resource *res, int *trgt_mem, int *trgt_io)
rv = 0;
trgt = -1;
switch (start) {
+ case 0x0000:
case 0x8000:
trgt = 0;
break;
+ case 0x1000:
case 0x9000:
trgt = 1;
break;
+ case 0x2000:
case 0xa000:
if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
trgt = 3;
else
trgt = 2;
break;
+ case 0x3000:
case 0xb000:
if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
rv = EINVAL;
diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h
index 66e7ace..31adc58 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.h
+++ b/sys/powerpc/mpc85xx/mpc85xx.h
@@ -48,14 +48,35 @@ extern vm_offset_t ccsrbar_va;
/*
* Local access registers
*/
-#define OCP85XX_LAWBAR(n) (CCSRBAR_VA + 0xc08 + 0x20 * (n))
-#define OCP85XX_LAWSR(n) (CCSRBAR_VA + 0xc10 + 0x20 * (n))
+#if defined(QORIQ_DPAA)
+/* Write order: OCP_LAWBARH -> OCP_LAWBARL -> OCP_LAWSR */
+#define OCP85XX_LAWBARH(n) (CCSRBAR_VA + 0xc00 + 0x10 * (n))
+#define OCP85XX_LAWBARL(n) (CCSRBAR_VA + 0xc04 + 0x10 * (n))
+#define OCP85XX_LAWSR(n) (CCSRBAR_VA + 0xc08 + 0x10 * (n))
+#else
+#define OCP85XX_LAWBAR(n) (CCSRBAR_VA + 0xc08 + 0x10 * (n))
+#define OCP85XX_LAWSR(n) (CCSRBAR_VA + 0xc10 + 0x10 * (n))
+#endif
-#define OCP85XX_TGTIF_LBC 4
-#define OCP85XX_TGTIF_RAM_INTL 11
-#define OCP85XX_TGTIF_RIO 12
-#define OCP85XX_TGTIF_RAM1 15
-#define OCP85XX_TGTIF_RAM2 22
+/* Attribute register */
+#define OCP85XX_ENA_MASK 0x80000000
+#define OCP85XX_DIS_MASK 0x7fffffff
+
+#if defined(QORIQ_DPAA)
+#define OCP85XX_TGTIF_LBC 0x1f
+#define OCP85XX_TGTIF_RAM_INTL 0x14
+#define OCP85XX_TGTIF_RAM1 0x10
+#define OCP85XX_TGTIF_RAM2 0x11
+#define OCP85XX_TGTIF_BMAN 0x18
+#define OCP85XX_TGTIF_QMAN 0x3C
+#define OCP85XX_TRGT_SHIFT 20
+#else
+#define OCP85XX_TGTIF_LBC 0x04
+#define OCP85XX_TGTIF_RAM_INTL 0x0b
+#define OCP85XX_TGTIF_RIO 0x0c
+#define OCP85XX_TGTIF_RAM1 0x0f
+#define OCP85XX_TGTIF_RAM2 0x16
+#endif
/*
* L2 cache registers
@@ -81,8 +102,8 @@ extern vm_offset_t ccsrbar_va;
*/
uint32_t ccsr_read4(uintptr_t addr);
void ccsr_write4(uintptr_t addr, uint32_t val);
-int law_enable(int trgt, u_long addr, u_long size);
-int law_disable(int trgt, u_long addr, u_long size);
+int law_enable(int trgt, uint64_t bar, uint32_t size);
+int law_disable(int trgt, uint64_t bar, uint32_t size);
int law_getmax(void);
int law_pci_target(struct resource *, int *, int *);
diff --git a/sys/powerpc/ofw/ofw_machdep.c b/sys/powerpc/ofw/ofw_machdep.c
index d7ec7fc..d085af9 100644
--- a/sys/powerpc/ofw/ofw_machdep.c
+++ b/sys/powerpc/ofw/ofw_machdep.c
@@ -154,17 +154,17 @@ parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
* be found.
*/
phandle = OF_finddevice("/");
- if (OF_getprop(phandle, "#address-cells", &address_cells,
+ if (OF_getencprop(phandle, "#address-cells", &address_cells,
sizeof(address_cells)) < (ssize_t)sizeof(address_cells))
address_cells = 1;
- if (OF_getprop(phandle, "#size-cells", &size_cells,
+ if (OF_getencprop(phandle, "#size-cells", &size_cells,
sizeof(size_cells)) < (ssize_t)sizeof(size_cells))
size_cells = 1;
/*
* Get memory.
*/
- if (node == -1 || (sz = OF_getprop(node, prop,
+ if (node == -1 || (sz = OF_getencprop(node, prop,
OFmem, sizeof(OFmem))) <= 0)
panic("Physical memory map not found");
@@ -572,10 +572,10 @@ OF_get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep, int *pcip)
uint32_t addr, size;
int pci, res;
- res = OF_getprop(node, "#address-cells", &addr, sizeof(addr));
+ res = OF_getencprop(node, "#address-cells", &addr, sizeof(addr));
if (res == -1)
addr = 2;
- res = OF_getprop(node, "#size-cells", &size, sizeof(size));
+ res = OF_getencprop(node, "#size-cells", &size, sizeof(size));
if (res == -1)
size = 1;
pci = 0;
@@ -624,7 +624,7 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
OF_get_addr_props(bridge, &naddr, &nsize, &pci);
if (pci)
*tag = &bs_le_tag;
- res = OF_getprop(dev, (pci) ? "assigned-addresses" : "reg",
+ res = OF_getencprop(dev, (pci) ? "assigned-addresses" : "reg",
cell, sizeof(cell));
if (res == -1)
return (ENXIO);
@@ -653,7 +653,7 @@ OF_decode_addr(phandle_t dev, int regno, bus_space_tag_t *tag,
OF_get_addr_props(parent, &nbridge, NULL, &pcib);
if (pcib)
*tag = &bs_le_tag;
- res = OF_getprop(bridge, "ranges", cell, sizeof(cell));
+ res = OF_getencprop(bridge, "ranges", cell, sizeof(cell));
if (res == -1)
goto next;
if (res % sizeof(cell[0]))
diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c
index d9ea5c0..3a92acf 100644
--- a/sys/powerpc/ofw/ofw_pci.c
+++ b/sys/powerpc/ofw/ofw_pci.c
@@ -136,10 +136,11 @@ ofw_pci_init(device_t dev)
sc = device_get_softc(dev);
sc->sc_initialized = 1;
- if (OF_getprop(node, "reg", &sc->sc_pcir, sizeof(sc->sc_pcir)) == -1)
+ if (OF_getencprop(node, "reg", (pcell_t *)&sc->sc_pcir,
+ sizeof(sc->sc_pcir)) == -1)
return (ENXIO);
- if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
+ if (OF_getencprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
busrange[0] = 0;
sc->sc_dev = dev;
@@ -498,11 +499,11 @@ ofw_pci_nranges(phandle_t node)
int host_address_cells = 1, pci_address_cells = 3, size_cells = 2;
ssize_t nbase_ranges;
- OF_getprop(OF_parent(node), "#address-cells", &host_address_cells,
+ OF_getencprop(OF_parent(node), "#address-cells", &host_address_cells,
sizeof(host_address_cells));
- OF_getprop(node, "#address-cells", &pci_address_cells,
+ OF_getencprop(node, "#address-cells", &pci_address_cells,
sizeof(pci_address_cells));
- OF_getprop(node, "#size-cells", &size_cells, sizeof(size_cells));
+ OF_getencprop(node, "#size-cells", &size_cells, sizeof(size_cells));
nbase_ranges = OF_getproplen(node, "ranges");
if (nbase_ranges <= 0)
@@ -521,11 +522,11 @@ ofw_pci_fill_ranges(phandle_t node, struct ofw_pci_range *ranges)
int nranges;
int i, j, k;
- OF_getprop(OF_parent(node), "#address-cells", &host_address_cells,
+ OF_getencprop(OF_parent(node), "#address-cells", &host_address_cells,
sizeof(host_address_cells));
- OF_getprop(node, "#address-cells", &pci_address_cells,
+ OF_getencprop(node, "#address-cells", &pci_address_cells,
sizeof(pci_address_cells));
- OF_getprop(node, "#size-cells", &size_cells, sizeof(size_cells));
+ OF_getencprop(node, "#size-cells", &size_cells, sizeof(size_cells));
nbase_ranges = OF_getproplen(node, "ranges");
if (nbase_ranges <= 0)
@@ -534,7 +535,7 @@ ofw_pci_fill_ranges(phandle_t node, struct ofw_pci_range *ranges)
(pci_address_cells + host_address_cells + size_cells);
base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
- OF_getprop(node, "ranges", base_ranges, nbase_ranges);
+ OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
for (i = 0, j = 0; i < nranges; i++) {
ranges[i].pci_hi = base_ranges[j++];
diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c
index 246b886..cde3c74 100644
--- a/sys/powerpc/ofw/ofw_pcibus.c
+++ b/sys/powerpc/ofw/ofw_pcibus.c
@@ -156,7 +156,8 @@ ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno)
node = ofw_bus_get_node(dev);
for (child = OF_child(node); child != 0; child = OF_peer(child)) {
- if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1)
+ if (OF_getencprop(child, "reg", (pcell_t *)&pcir,
+ sizeof(pcir)) == -1)
continue;
slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);
@@ -305,11 +306,12 @@ ofw_pcibus_assign_interrupt(device_t dev, device_t child)
*/
iparent = -1;
- if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) < 0)
+ if (OF_getencprop(node, "interrupt-parent", &iparent,
+ sizeof(iparent)) < 0)
iparent = -1;
icells = 1;
if (iparent != -1)
- OF_getprop(OF_node_from_xref(iparent), "#interrupt-cells",
+ OF_getencprop(OF_node_from_xref(iparent), "#interrupt-cells",
&icells, sizeof(icells));
/*
@@ -317,12 +319,12 @@ ofw_pcibus_assign_interrupt(device_t dev, device_t child)
* fully specified (i.e. does not need routing)
*/
- isz = OF_getprop(node, "AAPL,interrupts", intr, sizeof(intr));
+ isz = OF_getencprop(node, "AAPL,interrupts", intr, sizeof(intr));
if (isz == sizeof(intr[0])*icells)
return ((iparent == -1) ? intr[0] : ofw_bus_map_intr(dev,
iparent, icells, intr));
- isz = OF_getprop(node, "interrupts", intr, sizeof(intr));
+ isz = OF_getencprop(node, "interrupts", intr, sizeof(intr));
if (isz == sizeof(intr[0])*icells) {
if (iparent != -1)
intr[0] = ofw_bus_map_intr(dev, iparent, icells, intr);
diff --git a/sys/powerpc/ofw/openpic_ofw.c b/sys/powerpc/ofw/openpic_ofw.c
index 16b7575..b0cf020 100644
--- a/sys/powerpc/ofw/openpic_ofw.c
+++ b/sys/powerpc/ofw/openpic_ofw.c
@@ -127,9 +127,9 @@ openpic_ofw_attach(device_t dev)
node = ofw_bus_get_node(dev);
- if (OF_getprop(node, "phandle", &xref, sizeof(xref)) == -1 &&
- OF_getprop(node, "ibm,phandle", &xref, sizeof(xref)) == -1 &&
- OF_getprop(node, "linux,phandle", &xref, sizeof(xref)) == -1)
+ if (OF_getencprop(node, "phandle", &xref, sizeof(xref)) == -1 &&
+ OF_getencprop(node, "ibm,phandle", &xref, sizeof(xref)) == -1 &&
+ OF_getencprop(node, "linux,phandle", &xref, sizeof(xref)) == -1)
xref = node;
return (openpic_common_attach(dev, xref));
diff --git a/sys/powerpc/powermac/cpcht.c b/sys/powerpc/powermac/cpcht.c
index 004f8f0..765d946 100644
--- a/sys/powerpc/powermac/cpcht.c
+++ b/sys/powerpc/powermac/cpcht.c
@@ -176,7 +176,7 @@ cpcht_attach(device_t dev)
node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
- if (OF_getprop(node, "reg", reg, sizeof(reg)) < 12)
+ if (OF_getencprop(node, "reg", reg, sizeof(reg)) < 12)
return (ENXIO);
if (OF_getproplen(node, "ranges") <= 0)
@@ -219,7 +219,7 @@ cpcht_configure_htbridge(device_t dev, phandle_t child)
u_int b, f, s;
sc = device_get_softc(dev);
- if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1)
+ if (OF_getencprop(child, "reg", (pcell_t *)&pcir, sizeof(pcir)) == -1)
return;
b = OFW_PCI_PHYS_HI_BUS(pcir.phys_hi);
diff --git a/sys/powerpc/powermac/kiic.c b/sys/powerpc/powermac/kiic.c
index 7a60ba2..58da0b3 100644
--- a/sys/powerpc/powermac/kiic.c
+++ b/sys/powerpc/powermac/kiic.c
@@ -186,11 +186,11 @@ kiic_attach(device_t self)
return (ENOMEM);
}
- if (OF_getprop(node, "AAPL,i2c-rate", &rate, 4) != 4) {
+ if (OF_getencprop(node, "AAPL,i2c-rate", &rate, 4) != 4) {
device_printf(self, "cannot get i2c-rate\n");
return (ENXIO);
}
- if (OF_getprop(node, "AAPL,address-step", &sc->sc_regstep, 4) != 4) {
+ if (OF_getencprop(node, "AAPL,address-step", &sc->sc_regstep, 4) != 4) {
device_printf(self, "unable to find i2c address step\n");
return (ENXIO);
}
diff --git a/sys/powerpc/powermac/macgpio.c b/sys/powerpc/powermac/macgpio.c
index 9fc4541..4544fef 100644
--- a/sys/powerpc/powermac/macgpio.c
+++ b/sys/powerpc/powermac/macgpio.c
@@ -177,7 +177,7 @@ macgpio_attach(device_t dev)
continue;
}
- if (OF_getprop(child,"reg",&dinfo->gpio_num,
+ if (OF_getencprop(child, "reg", &dinfo->gpio_num,
sizeof(dinfo->gpio_num)) != sizeof(dinfo->gpio_num)) {
/*
* Some early GPIO controllers don't provide GPIO
@@ -191,9 +191,9 @@ macgpio_attach(device_t dev)
resource_list_init(&dinfo->mdi_resources);
- if (OF_getprop(child, "interrupts", &irq, sizeof(irq)) ==
+ if (OF_getencprop(child, "interrupts", &irq, sizeof(irq)) ==
sizeof(irq)) {
- OF_searchprop(child, "interrupt-parent", &iparent,
+ OF_searchencprop(child, "interrupt-parent", &iparent,
sizeof(iparent));
resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
0, MAP_IRQ(iparent, irq), MAP_IRQ(iparent, irq),
diff --git a/sys/powerpc/pseries/mmu_phyp.c b/sys/powerpc/pseries/mmu_phyp.c
index da9ea22..513dc8e 100644
--- a/sys/powerpc/pseries/mmu_phyp.c
+++ b/sys/powerpc/pseries/mmu_phyp.c
@@ -142,11 +142,11 @@ mphyp_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
node = OF_peer(node);
}
- res = OF_getprop(node, "ibm,pft-size", prop, sizeof(prop));
+ res = OF_getencprop(node, "ibm,pft-size", prop, sizeof(prop));
if (res <= 0)
panic("mmu_phyp: unknown PFT size");
final_pteg_count = 1 << prop[1];
- res = OF_getprop(node, "ibm,slb-size", prop, sizeof(prop[0]));
+ res = OF_getencprop(node, "ibm,slb-size", prop, sizeof(prop[0]));
if (res > 0)
n_slbs = prop[0];
diff --git a/sys/powerpc/pseries/phyp_console.c b/sys/powerpc/pseries/phyp_console.c
index 261f92b..ede2387 100644
--- a/sys/powerpc/pseries/phyp_console.c
+++ b/sys/powerpc/pseries/phyp_console.c
@@ -147,7 +147,7 @@ uart_phyp_probe_node(struct uart_phyp_softc *sc)
return (ENXIO);
reg = -1;
- OF_getprop(node, "reg", &reg, sizeof(reg));
+ OF_getencprop(node, "reg", &reg, sizeof(reg));
if (reg == -1)
return (ENXIO);
sc->vtermid = reg;
@@ -200,7 +200,7 @@ uart_phyp_cnprobe(struct consdev *cp)
/* Check if OF has an active stdin/stdout */
input = -1;
- if (OF_getprop(chosen, "stdout", &stdout,
+ if (OF_getencprop(chosen, "stdout", &stdout,
sizeof(stdout)) == sizeof(stdout) && stdout != 0)
input = OF_instance_to_package(stdout);
if (input == -1)
diff --git a/sys/powerpc/pseries/phyp_llan.c b/sys/powerpc/pseries/phyp_llan.c
index 26dbcc0..04e359d 100644
--- a/sys/powerpc/pseries/phyp_llan.c
+++ b/sys/powerpc/pseries/phyp_llan.c
@@ -159,7 +159,7 @@ llan_attach(device_t dev)
node = ofw_bus_get_node(dev);
OF_getprop(node, "local-mac-address", sc->mac_address,
sizeof(sc->mac_address));
- OF_getprop(node, "reg", &sc->unit, sizeof(sc->unit));
+ OF_getencprop(node, "reg", &sc->unit, sizeof(sc->unit));
mtx_init(&sc->io_lock, "llan", NULL, MTX_DEF);
diff --git a/sys/powerpc/pseries/phyp_vscsi.c b/sys/powerpc/pseries/phyp_vscsi.c
index 9b638ef..0623aef 100644
--- a/sys/powerpc/pseries/phyp_vscsi.c
+++ b/sys/powerpc/pseries/phyp_vscsi.c
@@ -290,7 +290,8 @@ vscsi_attach(device_t dev)
mtx_init(&sc->io_lock, "vscsi", NULL, MTX_DEF);
/* Get properties */
- OF_getprop(ofw_bus_get_node(dev), "reg", &sc->unit, sizeof(sc->unit));
+ OF_getencprop(ofw_bus_get_node(dev), "reg", &sc->unit,
+ sizeof(sc->unit));
/* Setup interrupt */
sc->irqid = 0;
diff --git a/sys/powerpc/pseries/platform_chrp.c b/sys/powerpc/pseries/platform_chrp.c
index b1fc948..ba43783 100644
--- a/sys/powerpc/pseries/platform_chrp.c
+++ b/sys/powerpc/pseries/platform_chrp.c
@@ -172,7 +172,7 @@ parse_drconf_memory(struct mem_region *ofmem, int *msz,
vm_offset_t base;
int i, idx, len, lasz, lmsz, res;
uint32_t flags, lmb_size[2];
- uint64_t *dmem;
+ uint32_t *dmem;
lmsz = *msz;
lasz = *asz;
@@ -182,7 +182,8 @@ parse_drconf_memory(struct mem_region *ofmem, int *msz,
/* No drconf node, return. */
return (0);
- res = OF_getprop(phandle, "ibm,lmb-size", lmb_size, sizeof(lmb_size));
+ res = OF_getencprop(phandle, "ibm,lmb-size", lmb_size,
+ sizeof(lmb_size));
if (res == -1)
return (0);
printf("Logical Memory Block size: %d MB\n", lmb_size[1] >> 20);
@@ -207,8 +208,8 @@ parse_drconf_memory(struct mem_region *ofmem, int *msz,
*/
cell_t arr[len/sizeof(cell_t)];
- res = OF_getprop(phandle, "ibm,dynamic-memory", &arr,
- sizeof(arr));
+ res = OF_getencprop(phandle, "ibm,dynamic-memory", arr,
+ sizeof(arr));
if (res == -1)
return (0);
@@ -216,12 +217,12 @@ parse_drconf_memory(struct mem_region *ofmem, int *msz,
idx = arr[0];
/* First address, in arr[1], arr[2]*/
- dmem = (uint64_t*)&arr[1];
+ dmem = &arr[1];
for (i = 0; i < idx; i++) {
- base = *dmem;
- dmem += 2;
- flags = *dmem;
+ base = ((uint64_t)dmem[0] << 32) + dmem[1];
+ dmem += 4;
+ flags = dmem[1];
/* Use region only if available and not reserved. */
if ((flags & 0x8) && !(flags & 0x80)) {
ofmem[lmsz].mr_start = base;
@@ -231,7 +232,7 @@ parse_drconf_memory(struct mem_region *ofmem, int *msz,
lmsz++;
lasz++;
}
- dmem++;
+ dmem += 2;
}
}
@@ -281,7 +282,7 @@ chrp_timebase_freq(platform_t plat, struct cpuref *cpuref)
phandle = cpuref->cr_hwref;
- OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks));
+ OF_getencprop(phandle, "timebase-frequency", &ticks, sizeof(ticks));
if (ticks <= 0)
panic("Unable to determine timebase frequency!");
@@ -327,10 +328,10 @@ chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
return (ENOENT);
cpuref->cr_hwref = cpu;
- res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
+ res = OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
sizeof(cpuid));
if (res <= 0)
- res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid));
+ res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
if (res <= 0)
cpuid = 0;
cpuref->cr_cpuid = cpuid;
@@ -349,7 +350,7 @@ chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s");
if (res > 0) {
cell_t interrupt_servers[res/sizeof(cell_t)];
- OF_getprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s",
+ OF_getencprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s",
interrupt_servers, res);
for (i = 0; i < res/sizeof(cell_t) - 1; i++) {
if (interrupt_servers[i] == cpuref->cr_cpuid) {
@@ -371,10 +372,10 @@ chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
return (ENOENT);
cpuref->cr_hwref = cpu;
- res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
+ res = OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
sizeof(cpuid));
if (res <= 0)
- res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid));
+ res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
if (res <= 0)
cpuid = 0;
cpuref->cr_cpuid = cpuid;
@@ -393,7 +394,7 @@ chrp_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
if (chosen == 0)
return (ENXIO);
- res = OF_getprop(chosen, "cpu", &inst, sizeof(inst));
+ res = OF_getencprop(chosen, "cpu", &inst, sizeof(inst));
if (res < 0)
return (ENXIO);
@@ -401,10 +402,10 @@ chrp_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
/* Pick the primary thread. Can it be any other? */
cpuref->cr_hwref = bsp;
- res = OF_getprop(bsp, "ibm,ppc-interrupt-server#s", &cpuid,
+ res = OF_getencprop(bsp, "ibm,ppc-interrupt-server#s", &cpuid,
sizeof(cpuid));
if (res <= 0)
- res = OF_getprop(bsp, "reg", &cpuid, sizeof(cpuid));
+ res = OF_getencprop(bsp, "reg", &cpuid, sizeof(cpuid));
if (res <= 0)
cpuid = 0;
cpuref->cr_cpuid = cpuid;
diff --git a/sys/powerpc/pseries/plpar_iommu.c b/sys/powerpc/pseries/plpar_iommu.c
index 5edbf6d..eab2ce2 100644
--- a/sys/powerpc/pseries/plpar_iommu.c
+++ b/sys/powerpc/pseries/plpar_iommu.c
@@ -88,19 +88,20 @@ phyp_iommu_set_dma_tag(device_t bus, device_t dev, bus_dma_tag_t tag)
return (ENXIO);
node = ofw_bus_get_node(p);
- if (OF_getprop(node, "ibm,#dma-size-cells", &dma_scells,
+ if (OF_getencprop(node, "ibm,#dma-size-cells", &dma_scells,
sizeof(cell_t)) <= 0)
- OF_searchprop(node, "#size-cells", &dma_scells, sizeof(cell_t));
- if (OF_getprop(node, "ibm,#dma-address-cells", &dma_acells,
+ OF_searchencprop(node, "#size-cells", &dma_scells,
+ sizeof(cell_t));
+ if (OF_getencprop(node, "ibm,#dma-address-cells", &dma_acells,
sizeof(cell_t)) <= 0)
- OF_searchprop(node, "#address-cells", &dma_acells,
+ OF_searchencprop(node, "#address-cells", &dma_acells,
sizeof(cell_t));
if (ofw_bus_has_prop(p, "ibm,my-dma-window"))
- OF_getprop(node, "ibm,my-dma-window", dmawindow,
+ OF_getencprop(node, "ibm,my-dma-window", dmawindow,
sizeof(cell_t)*(dma_scells + dma_acells + 1));
else
- OF_getprop(node, "ibm,dma-window", dmawindow,
+ OF_getencprop(node, "ibm,dma-window", dmawindow,
sizeof(cell_t)*(dma_scells + dma_acells + 1));
struct dma_window *window = malloc(sizeof(struct dma_window),
diff --git a/sys/powerpc/pseries/rtas_pci.c b/sys/powerpc/pseries/rtas_pci.c
index 90a7e6b..9d8460c 100644
--- a/sys/powerpc/pseries/rtas_pci.c
+++ b/sys/powerpc/pseries/rtas_pci.c
@@ -133,7 +133,7 @@ rtaspci_attach(device_t dev)
sc->ex_write_pci_config = rtas_token_lookup("ibm,write-pci-config");
sc->sc_extended_config = 0;
- OF_getprop(ofw_bus_get_node(dev), "ibm,pci-config-space-type",
+ OF_getencprop(ofw_bus_get_node(dev), "ibm,pci-config-space-type",
&sc->sc_extended_config, sizeof(sc->sc_extended_config));
return (ofw_pci_attach(dev));
diff --git a/sys/sparc64/include/dump.h b/sys/sparc64/include/dump.h
index aee0f58..f154660 100644
--- a/sys/sparc64/include/dump.h
+++ b/sys/sparc64/include/dump.h
@@ -35,7 +35,6 @@
#define KERNELDUMP_ARCH_VERSION KERNELDUMP_SPARC64_VERSION
#define EM_VALUE EM_SPARCV9
-void dumpsys_pa_init(void);
int dumpsys(struct dumperinfo *);
static inline struct dump_pa *
@@ -60,13 +59,6 @@ dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va)
}
static inline int
-dumpsys_write_aux_headers(struct dumperinfo *di)
-{
-
- return (dumpsys_gen_write_aux_headers(di));
-}
-
-static inline int
minidumpsys(struct dumperinfo *di)
{
diff --git a/sys/sparc64/sparc64/dump_machdep.c b/sys/sparc64/sparc64/dump_machdep.c
index 1f28b6d..9cb1aab 100644
--- a/sys/sparc64/sparc64/dump_machdep.c
+++ b/sys/sparc64/sparc64/dump_machdep.c
@@ -55,18 +55,6 @@ extern struct dump_pa dump_map[DUMPSYS_MD_PA_NPAIRS];
int do_minidump = 0;
void
-dumpsys_pa_init(void)
-{
- int i;
-
- memset(dump_map, 0, sizeof(dump_map));
- for (i = 0; i < sparc64_nmemreg; i++) {
- dump_map[i].pa_start = sparc64_memreg[i].mr_start;
- dump_map[i].pa_size = sparc64_memreg[i].mr_size;
- }
-}
-
-void
dumpsys_map_chunk(vm_paddr_t pa, size_t chunk __unused, void **va)
{
@@ -89,16 +77,18 @@ int
dumpsys(struct dumperinfo *di)
{
static struct kerneldumpheader kdh;
-
struct sparc64_dump_hdr hdr;
vm_size_t size, totsize, hdrsize;
int error, i, nreg;
- /* Calculate dump size. */
+ /* Set up dump_map and calculate dump size. */
size = 0;
nreg = sparc64_nmemreg;
- for (i = 0; i < sparc64_nmemreg; i++)
- size += sparc64_memreg[i].mr_size;
+ memset(dump_map, 0, sizeof(dump_map));
+ for (i = 0; i < nreg; i++) {
+ dump_map[i].pa_start = sparc64_memreg[i].mr_start;
+ size += dump_map[i].pa_size = sparc64_memreg[i].mr_size;
+ }
/* Account for the header size. */
hdrsize = roundup2(sizeof(hdr) + sizeof(struct sparc64_dump_reg) * nreg,
DEV_BSIZE);
@@ -139,7 +129,7 @@ dumpsys(struct dumperinfo *di)
fileofs = hdrsize;
/* Now, write out the region descriptors. */
- for (i = 0; i < sparc64_nmemreg; i++) {
+ for (i = 0; i < nreg; i++) {
error = reg_write(di, sparc64_memreg[i].mr_start,
sparc64_memreg[i].mr_size);
if (error != 0)
diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h
index 6ed909b..47662fa 100644
--- a/sys/sys/pmc.h
+++ b/sys/sys/pmc.h
@@ -550,14 +550,15 @@ struct pmc_op_configurelog {
*/
struct pmc_op_getdriverstats {
- int pm_intr_ignored; /* #interrupts ignored */
- int pm_intr_processed; /* #interrupts processed */
- int pm_intr_bufferfull; /* #interrupts with ENOSPC */
- int pm_syscalls; /* #syscalls */
- int pm_syscall_errors; /* #syscalls with errors */
- int pm_buffer_requests; /* #buffer requests */
- int pm_buffer_requests_failed; /* #failed buffer requests */
- int pm_log_sweeps; /* #sample buffer processing passes */
+ unsigned int pm_intr_ignored; /* #interrupts ignored */
+ unsigned int pm_intr_processed; /* #interrupts processed */
+ unsigned int pm_intr_bufferfull; /* #interrupts with ENOSPC */
+ unsigned int pm_syscalls; /* #syscalls */
+ unsigned int pm_syscall_errors; /* #syscalls with errors */
+ unsigned int pm_buffer_requests; /* #buffer requests */
+ unsigned int pm_buffer_requests_failed; /* #failed buffer requests */
+ unsigned int pm_log_sweeps; /* #sample buffer processing
+ passes */
};
/*
diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c
index d81c913..35ec992 100644
--- a/sys/x86/x86/intr_machdep.c
+++ b/sys/x86/x86/intr_machdep.c
@@ -197,19 +197,28 @@ int
intr_remove_handler(void *cookie)
{
struct intsrc *isrc;
- int error;
+ int error, mtx_owned;
isrc = intr_handler_source(cookie);
error = intr_event_remove_handler(cookie);
if (error == 0) {
- mtx_lock(&intr_table_lock);
+ /*
+ * Recursion is needed here so PICs can remove interrupts
+ * while resuming. It was previously not possible due to
+ * intr_resume holding the intr_table_lock and
+ * intr_remove_handler recursing on it.
+ */
+ mtx_owned = mtx_owned(&intr_table_lock);
+ if (mtx_owned == 0)
+ mtx_lock(&intr_table_lock);
isrc->is_handlers--;
if (isrc->is_handlers == 0) {
isrc->is_pic->pic_disable_source(isrc, PIC_NO_EOI);
isrc->is_pic->pic_disable_intr(isrc);
}
intrcnt_updatename(isrc);
- mtx_unlock(&intr_table_lock);
+ if (mtx_owned == 0)
+ mtx_unlock(&intr_table_lock);
}
return (error);
}
diff --git a/sys/x86/xen/hvm.c b/sys/x86/xen/hvm.c
index c969e26..a8b14fd 100644
--- a/sys/x86/xen/hvm.c
+++ b/sys/x86/xen/hvm.c
@@ -58,15 +58,8 @@ __FBSDID("$FreeBSD$");
#include <xen/interface/vcpu.h>
/*--------------------------- Forward Declarations ---------------------------*/
-#ifdef SMP
-static void xen_hvm_cpu_resume(void);
-#endif
static void xen_hvm_cpu_init(void);
-/*---------------------------- Extern Declarations ---------------------------*/
-/* Variables used by mp_machdep to perform the bitmap IPI */
-extern volatile u_int cpu_ipi_pending[MAXCPU];
-
/*-------------------------------- Local Types -------------------------------*/
enum xen_hvm_init_type {
XEN_HVM_INIT_COLD,
@@ -80,7 +73,7 @@ enum xen_domain_type xen_domain_type = XEN_NATIVE;
#ifdef SMP
struct cpu_ops xen_hvm_cpu_ops = {
.cpu_init = xen_hvm_cpu_init,
- .cpu_resume = xen_hvm_cpu_resume
+ .cpu_resume = xen_hvm_cpu_init
};
#endif
@@ -107,23 +100,6 @@ int xen_disable_pv_nics = 0;
TUNABLE_INT("hw.xen.disable_pv_disks", &xen_disable_pv_disks);
TUNABLE_INT("hw.xen.disable_pv_nics", &xen_disable_pv_nics);
-#ifdef SMP
-/*---------------------- XEN diverged cpu operations -------------------------*/
-static void
-xen_hvm_cpu_resume(void)
-{
- u_int cpuid = PCPU_GET(cpuid);
-
- /*
- * Reset pending bitmap IPIs, because Xen doesn't preserve pending
- * event channels on migration.
- */
- cpu_ipi_pending[cpuid] = 0;
-
- /* register vcpu_info area */
- xen_hvm_cpu_init();
-}
-#endif
/*---------------------- XEN Hypervisor Probe and Setup ----------------------*/
static uint32_t
xen_hvm_cpuid_base(void)
diff --git a/sys/x86/xen/xen_intr.c b/sys/x86/xen/xen_intr.c
index 1c0ae3a..a7b89fc 100644
--- a/sys/x86/xen/xen_intr.c
+++ b/sys/x86/xen/xen_intr.c
@@ -780,7 +780,10 @@ xen_intr_resume(struct pic *unused, bool suspend_cancelled)
xen_rebind_virq(isrc);
break;
default:
+ intr_remove_handler(isrc->xi_cookie);
isrc->xi_cpu = 0;
+ isrc->xi_type = EVTCHN_TYPE_UNBOUND;
+ isrc->xi_cookie = NULL;
break;
}
}
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 694a774..1ef88ff 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -4505,6 +4505,12 @@ OLD_FILES+=usr/share/locale/en_AU.ISO8859-1/LC_MESSAGES
OLD_FILES+=usr/share/locale/en_AU.ISO8859-1/LC_MONETARY
OLD_FILES+=usr/share/locale/en_AU.ISO8859-1/LC_NUMERIC
OLD_FILES+=usr/share/locale/en_AU.ISO8859-1/LC_TIME
+OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_COLLATE
+OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_CTYPE
+OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_MESSAGES
+OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_MONETARY
+OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_NUMERIC
+OLD_FILES+=usr/share/locale/en_AU.ISO8859-15/LC_TIME
OLD_FILES+=usr/share/locale/en_AU.US-ASCII/LC_COLLATE
OLD_FILES+=usr/share/locale/en_AU.US-ASCII/LC_CTYPE
OLD_FILES+=usr/share/locale/en_AU.US-ASCII/LC_MESSAGES
@@ -4523,6 +4529,12 @@ OLD_FILES+=usr/share/locale/en_CA.ISO8859-1/LC_MESSAGES
OLD_FILES+=usr/share/locale/en_CA.ISO8859-1/LC_MONETARY
OLD_FILES+=usr/share/locale/en_CA.ISO8859-1/LC_NUMERIC
OLD_FILES+=usr/share/locale/en_CA.ISO8859-1/LC_TIME
+OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_COLLATE
+OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_CTYPE
+OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_MESSAGES
+OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_MONETARY
+OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_NUMERIC
+OLD_FILES+=usr/share/locale/en_CA.ISO8859-15/LC_TIME
OLD_FILES+=usr/share/locale/en_CA.US-ASCII/LC_COLLATE
OLD_FILES+=usr/share/locale/en_CA.US-ASCII/LC_CTYPE
OLD_FILES+=usr/share/locale/en_CA.US-ASCII/LC_MESSAGES
@@ -4595,6 +4607,12 @@ OLD_FILES+=usr/share/locale/en_NZ.ISO8859-1/LC_MESSAGES
OLD_FILES+=usr/share/locale/en_NZ.ISO8859-1/LC_MONETARY
OLD_FILES+=usr/share/locale/en_NZ.ISO8859-1/LC_NUMERIC
OLD_FILES+=usr/share/locale/en_NZ.ISO8859-1/LC_TIME
+OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_COLLATE
+OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_CTYPE
+OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_MESSAGES
+OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_MONETARY
+OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_NUMERIC
+OLD_FILES+=usr/share/locale/en_NZ.ISO8859-15/LC_TIME
OLD_FILES+=usr/share/locale/en_NZ.US-ASCII/LC_COLLATE
OLD_FILES+=usr/share/locale/en_NZ.US-ASCII/LC_CTYPE
OLD_FILES+=usr/share/locale/en_NZ.US-ASCII/LC_MESSAGES
@@ -4631,6 +4649,12 @@ OLD_FILES+=usr/share/locale/en_US.ISO8859-1/LC_MESSAGES
OLD_FILES+=usr/share/locale/en_US.ISO8859-1/LC_MONETARY
OLD_FILES+=usr/share/locale/en_US.ISO8859-1/LC_NUMERIC
OLD_FILES+=usr/share/locale/en_US.ISO8859-1/LC_TIME
+OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_COLLATE
+OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_CTYPE
+OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_MESSAGES
+OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_MONETARY
+OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_NUMERIC
+OLD_FILES+=usr/share/locale/en_US.ISO8859-15/LC_TIME
OLD_FILES+=usr/share/locale/en_US.US-ASCII/LC_COLLATE
OLD_FILES+=usr/share/locale/en_US.US-ASCII/LC_CTYPE
OLD_FILES+=usr/share/locale/en_US.US-ASCII/LC_MESSAGES
@@ -4787,6 +4811,12 @@ OLD_FILES+=usr/share/locale/fr_CA.ISO8859-1/LC_MESSAGES
OLD_FILES+=usr/share/locale/fr_CA.ISO8859-1/LC_MONETARY
OLD_FILES+=usr/share/locale/fr_CA.ISO8859-1/LC_NUMERIC
OLD_FILES+=usr/share/locale/fr_CA.ISO8859-1/LC_TIME
+OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_COLLATE
+OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_CTYPE
+OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_MESSAGES
+OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_MONETARY
+OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_NUMERIC
+OLD_FILES+=usr/share/locale/fr_CA.ISO8859-15/LC_TIME
OLD_FILES+=usr/share/locale/fr_CA.UTF-8/LC_COLLATE
OLD_FILES+=usr/share/locale/fr_CA.UTF-8/LC_CTYPE
OLD_FILES+=usr/share/locale/fr_CA.UTF-8/LC_MESSAGES
diff --git a/tools/install.sh b/tools/install.sh
index c28bd89..e39f6ce 100644
--- a/tools/install.sh
+++ b/tools/install.sh
@@ -63,7 +63,7 @@ fi
# the remaining arguments are assumed to be files/dirs only.
if [ -n "${linkmode}" ]; then
if [ "${linkmode}" = "symbolic" ]; then
- ln -fsh "$@"
+ ln -fsn "$@"
else
ln -f "$@"
fi
diff --git a/tools/sched/schedgraph.py b/tools/sched/schedgraph.py
index f0552ca..0723dc3 100644
--- a/tools/sched/schedgraph.py
+++ b/tools/sched/schedgraph.py
@@ -461,7 +461,7 @@ class SourceStats(Toplevel):
if (event.type == "pad"):
continue
duration = event.duration
- if (eventtypes.has_key(event.name)):
+ if (event.name in eventtypes):
(c, d) = eventtypes[event.name]
c += 1
d += duration
@@ -1069,7 +1069,7 @@ class KTRFile:
def makeid(self, group, id, type):
tag = group + id
- if (self.taghash.has_key(tag)):
+ if (tag in self.taghash):
return self.taghash[tag]
if (type == "counter"):
source = Counter(group, id)
diff --git a/tools/tools/locale/etc/charmaps.xml b/tools/tools/locale/etc/charmaps.xml
index 3d74b8d..0b6551a 100644
--- a/tools/tools/locale/etc/charmaps.xml
+++ b/tools/tools/locale/etc/charmaps.xml
@@ -28,7 +28,7 @@
-->
<language name="af"
- encoding="ISO8859-1"
+ encoding="ISO8859-1 ISO8859-15"
countries="ZA" />
<language name="am"
countries="ET" /> <!-- UTF-8 only -->
@@ -60,7 +60,7 @@
encoding="ISO8859-1 ISO8859-15 US-ASCII"
countries="GB" />
<language name="en"
- encoding="ISO8859-1 US-ASCII"
+ encoding="ISO8859-1 ISO8859-15 US-ASCII"
countries="AU CA NZ US ZA" />
<language name="en"
encoding="ISO8859-1 ISO8859-15"
@@ -91,7 +91,7 @@
encoding="ISO8859-1 ISO8859-15"
countries="BE CH FR" />
<language name="fr"
- encoding="ISO8859-1"
+ encoding="ISO8859-1 ISO8859-15"
countries="CA" />
<language name="he"
countries="IL" />
diff --git a/tools/tools/shlib-compat/shlib-compat.py b/tools/tools/shlib-compat/shlib-compat.py
index ca6f036..c0fb2d2 100755
--- a/tools/tools/shlib-compat/shlib-compat.py
+++ b/tools/tools/shlib-compat/shlib-compat.py
@@ -130,7 +130,7 @@ class Cache(object):
self.stats = stats
def get(self, id):
- if self.enabled and self.items.has_key(id):
+ if self.enabled and id in self.items:
self.stats.hit += 1
return self.items[id]
else:
@@ -139,7 +139,7 @@ class Cache(object):
def put(self, id, obj):
if self.enabled:
- if self.items.has_key(id) and obj is not self.items[id]:
+ if id in self.items and obj is not self.items[id]:
#raise ValueError("Item is already cached: %d (%s, %s)" %
# (id, self.items[id], obj))
warn(Config.w_cached, "Item is already cached: %d (%s, %s)" % \
@@ -148,7 +148,7 @@ class Cache(object):
def replace(self, id, obj):
if self.enabled:
- assert self.items.has_key(id)
+ assert id in self.items
self.items[id] = obj
class ListDiff(object):
@@ -226,7 +226,7 @@ class VersionMap(object):
self.symbols = {}
def append(self, symbol):
- if (self.symbols.has_key(symbol.name)):
+ if (symbol.name in self.symbols):
raise ValueError("Symbol is already defined %s@%s" %
(symbol.name, self.name))
self.symbols[symbol.name] = symbol
@@ -250,7 +250,7 @@ class Def(object):
self.attrs = kwargs
def __getattr__(self, attr):
- if not self.attrs.has_key(attr):
+ if attr not in self.attrs:
raise AttributeError('%s in %s' % (attr, str(self)))
return self.attrs[attr]
@@ -645,7 +645,7 @@ class Shlib(object):
if not Config.symbol_filter.match(p['symbol']):
continue
sym = Symbol(p['symbol'], p['offset'], vername, self)
- if not self.versions.has_key(vername):
+ if vername not in self.versions:
self.versions[vername] = VersionMap(vername)
self.versions[vername].append(sym)
if Config.alias_prefixes:
@@ -655,7 +655,7 @@ class Shlib(object):
if not p['symbol'].startswith(prefix):
continue
alias = SymbolAlias(p['symbol'], prefix, p['offset'])
- if self.alias_syms.has_key(alias.name):
+ if alias.name in self.alias_syms:
prevalias = self.alias_syms[alias.name]
if alias.name != prevalias.name or \
alias.offset != prevalias.offset:
@@ -676,7 +676,7 @@ class Shlib(object):
localnames = self.local_offsetmap[sym.offset]
localnames.sort(key=lambda x: -len(x))
for localname in localnames:
- if not self.alias_syms.has_key(localname):
+ if localname not in self.alias_syms:
continue
alias = self.alias_syms[localname]
raw = dwarfdump.offsetmap[alias.offset]
@@ -753,7 +753,7 @@ class ObjdumpParser(Parser):
return
table.append(symbol)
if offsetmap != None:
- if not offsetmap.has_key(offset):
+ if offset not in offsetmap:
offsetmap[offset] = [symbol['symbol']]
else:
offsetmap[offset].append(symbol['symbol'])
@@ -921,9 +921,9 @@ class DwarfdumpParser(Parser):
args = self.parse_arg(tag, args)
tag.unit.tags[tag.id] = tag
def parse_offset(tag):
- if tag.args.has_key('DW_AT_low_pc'):
+ if 'DW_AT_low_pc' in tag.args:
return int(tag.args['DW_AT_low_pc'], 16)
- elif tag.args.has_key('DW_AT_location'):
+ elif 'DW_AT_location' in tag.args:
location = tag.args['DW_AT_location']
if location.startswith('DW_OP_addr'):
return int(location.replace('DW_OP_addr', ''), 16)
@@ -931,9 +931,9 @@ class DwarfdumpParser(Parser):
offset = parse_offset(tag)
if offset is not None and \
(tag.tag not in DwarfdumpParser.skip_tags or \
- (tag.args.has_key('DW_AT_external') and \
+ ('DW_AT_external' in tag.args and \
tag.tag in DwarfdumpParser.external_tags)):
- if self.offsetmap.has_key(offset):
+ if offset in self.offsetmap:
raise ValueError("Dwarf dump parse error: " +
"symbol is aleady defined at offset 0x%x" % offset)
self.offsetmap[offset] = tag
diff --git a/usr.bin/netstat/if.c b/usr.bin/netstat/if.c
index f2f689d..9b8ff70 100644
--- a/usr.bin/netstat/if.c
+++ b/usr.bin/netstat/if.c
@@ -358,7 +358,7 @@ intpr(void (*pfunc)(char *), int af)
} else
xname = name;
- xo_emit("{etk:name/%s}{e:flags/0x%x}{d:/%-*.*s}",
+ xo_emit("{etk:name/%s}{eq:flags/0x%x}{d:/%-*.*s}",
name, ifa->ifa_flags, ifn_len_max, ifn_len_max, xname);
#define IFA_MTU(ifa) (((struct if_data *)(ifa)->ifa_data)->ifi_mtu)
diff --git a/usr.bin/xinstall/Makefile b/usr.bin/xinstall/Makefile
index 1d39273..c1056b5 100644
--- a/usr.bin/xinstall/Makefile
+++ b/usr.bin/xinstall/Makefile
@@ -7,10 +7,8 @@ SRCS= xinstall.c getid.c
MAN= install.1
.PATH: ${.CURDIR}/../../contrib/mtree
-.PATH: ${.CURDIR}/../../lib/libmd
CFLAGS+= -I${.CURDIR}/../../contrib/mtree
CFLAGS+= -I${.CURDIR}/../../lib/libnetbsd
-CFLAGS+= -I${.CURDIR}/../../lib/libmd
LIBADD= md
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index 4f00302..bda14c3 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -48,7 +48,6 @@ SUBDIR= adduser \
mpsutil \
mptutil \
mtest \
- ${_mtree} \
newsyslog \
nfscbd \
nfsd \
@@ -57,7 +56,6 @@ SUBDIR= adduser \
nfsuserd \
nmtree \
nologin \
- ${_pc_sysinstall} \
pciconf \
periodic \
powerd \
@@ -100,254 +98,111 @@ SUBDIR= adduser \
# NB: keep these sorted by MK_* knobs
-.if ${MK_ACCT} != "no"
-SUBDIR+= accton
-SUBDIR+= sa
-.endif
-
-.if ${MK_AMD} != "no"
-SUBDIR+= amd
-.endif
-
-.if ${MK_AUDIT} != "no"
-SUBDIR+= audit
-SUBDIR+= auditd
+SUBDIR.${MK_ACCT}+= accton
+SUBDIR.${MK_ACCT}+= sa
+SUBDIR.${MK_AMD}+= amd
+SUBDIR.${MK_AUDIT}+= audit
+SUBDIR.${MK_AUDIT}+= auditd
.if ${MK_OPENSSL} != "no"
-SUBDIR+= auditdistd
-.endif
-SUBDIR+= auditreduce
-SUBDIR+= praudit
-.endif
-
-.if ${MK_AUTHPF} != "no"
-SUBDIR+= authpf
-.endif
-
-.if ${MK_AUTOFS} != "no"
-SUBDIR+= autofs
-.endif
-
-.if ${MK_BLUETOOTH} != "no"
-SUBDIR+= bluetooth
-.endif
-
-.if ${MK_BOOTPARAMD} != "no"
-SUBDIR+= bootparamd
-.endif
-
-.if ${MK_BSDINSTALL} != "no"
-SUBDIR+= bsdinstall
-.endif
-
-.if ${MK_BSNMP} != "no"
-SUBDIR+= bsnmpd
-.endif
-
-.if ${MK_CTM} != "no"
-SUBDIR+= ctm
-.endif
-
-.if ${MK_FLOPPY} != "no"
-SUBDIR+= fdcontrol
-SUBDIR+= fdformat
-SUBDIR+= fdread
-SUBDIR+= fdwrite
-.endif
-
-.if ${MK_FMTREE} != "no"
-SUBDIR+= fmtree
-.endif
-
-.if ${MK_FREEBSD_UPDATE} != "no"
-SUBDIR+= freebsd-update
-.endif
-
-.if ${MK_GSSAPI} != "no"
-SUBDIR+= gssd
-.endif
-
-.if ${MK_GPIO} != "no"
-SUBDIR+= gpioctl
-.endif
-
-.if ${MK_INET6} != "no"
-SUBDIR+= ip6addrctl
-SUBDIR+= mld6query
-SUBDIR+= ndp
-SUBDIR+= rip6query
-SUBDIR+= route6d
-SUBDIR+= rrenumd
-SUBDIR+= rtadvctl
-SUBDIR+= rtadvd
-SUBDIR+= rtsold
-SUBDIR+= traceroute6
-.endif
-
-.if ${MK_INETD} != "no"
-SUBDIR+= inetd
-.endif
-
-.if ${MK_IPFW} != "no"
-SUBDIR+= ipfwpcap
-.endif
-
-.if ${MK_ISCSI} != "no"
-SUBDIR+= iscsid
-.endif
-
-.if ${MK_JAIL} != "no"
-SUBDIR+= jail
-SUBDIR+= jexec
-SUBDIR+= jls
-.endif
-
+SUBDIR.${MK_AUDIT}+= auditdistd
+.endif
+SUBDIR.${MK_AUDIT}+= auditreduce
+SUBDIR.${MK_AUDIT}+= praudit
+SUBDIR.${MK_AUTHPF}+= authpf
+SUBDIR.${MK_AUTOFS}+= autofs
+SUBDIR.${MK_BLUETOOTH}+= bluetooth
+SUBDIR.${MK_BOOTPARAMD}+= bootparamd
+SUBDIR.${MK_BSDINSTALL}+= bsdinstall
+SUBDIR.${MK_BSNMP}+= bsnmpd
+SUBDIR.${MK_CTM}+= ctm
+SUBDIR.${MK_FLOPPY}+= fdcontrol
+SUBDIR.${MK_FLOPPY}+= fdformat
+SUBDIR.${MK_FLOPPY}+= fdread
+SUBDIR.${MK_FLOPPY}+= fdwrite
+SUBDIR.${MK_FMTREE}+= fmtree
+SUBDIR.${MK_FREEBSD_UPDATE}+= freebsd-update
+SUBDIR.${MK_GSSAPI}+= gssd
+SUBDIR.${MK_GPIO}+= gpioctl
+SUBDIR.${MK_INET6}+= ip6addrctl
+SUBDIR.${MK_INET6}+= mld6query
+SUBDIR.${MK_INET6}+= ndp
+SUBDIR.${MK_INET6}+= rip6query
+SUBDIR.${MK_INET6}+= route6d
+SUBDIR.${MK_INET6}+= rrenumd
+SUBDIR.${MK_INET6}+= rtadvctl
+SUBDIR.${MK_INET6}+= rtadvd
+SUBDIR.${MK_INET6}+= rtsold
+SUBDIR.${MK_INET6}+= traceroute6
+SUBDIR.${MK_INETD}+= inetd
+SUBDIR.${MK_IPFW}+= ipfwpcap
+SUBDIR.${MK_ISCSI}+= iscsid
+SUBDIR.${MK_JAIL}+= jail
+SUBDIR.${MK_JAIL}+= jexec
+SUBDIR.${MK_JAIL}+= jls
# XXX MK_SYSCONS
-.if ${MK_LEGACY_CONSOLE} != "no"
-SUBDIR+= kbdcontrol
-SUBDIR+= kbdmap
-SUBDIR+= moused
-SUBDIR+= vidcontrol
-.endif
-
+SUBDIR.${MK_LEGACY_CONSOLE}+= kbdcontrol
+SUBDIR.${MK_LEGACY_CONSOLE}+= kbdmap
+SUBDIR.${MK_LEGACY_CONSOLE}+= moused
+SUBDIR.${MK_LEGACY_CONSOLE}+= vidcontrol
.if ${MK_LIBTHR} != "no" || ${MK_LIBPTHREAD} != "no"
-.if ${MK_PPP} != "no"
-SUBDIR+= pppctl
-.endif
-.if ${MK_NS_CACHING} != "no"
-SUBDIR+= nscd
-.endif
-.endif
-
-.if ${MK_LPR} != "no"
-SUBDIR+= lpr
-.endif
-
-.if ${MK_MAN_UTILS} != "no"
-SUBDIR+= manctl
-.endif
-
-.if ${MK_NAND} != "no"
-SUBDIR+= nandsim
-SUBDIR+= nandtool
-.endif
-
-.if ${MK_NETGRAPH} != "no"
-SUBDIR+= flowctl
-SUBDIR+= lmcconfig
-SUBDIR+= ngctl
-SUBDIR+= nghook
-.endif
-
-.if ${MK_NIS} != "no"
-SUBDIR+= rpc.yppasswdd
-SUBDIR+= rpc.ypupdated
-SUBDIR+= rpc.ypxfrd
-SUBDIR+= ypbind
-SUBDIR+= yp_mkdb
-SUBDIR+= yppoll
-SUBDIR+= yppush
-SUBDIR+= ypserv
-SUBDIR+= ypset
-.endif
-
-.if ${MK_NTP} != "no"
-SUBDIR+= ntp
-.endif
-
-.if ${MK_OPENSSL} != "no"
-SUBDIR+= keyserv
-.endif
-
-.if ${MK_PC_SYSINSTALL} != "no"
-_pc_sysinstall= pc-sysinstall
-.endif
-
-.if ${MK_PF} != "no"
-SUBDIR+= ftp-proxy
-.endif
-
-.if ${MK_PKGBOOTSTRAP} != "no"
-SUBDIR+= pkg
-.endif
-
-# XXX MK_TOOLCHAIN?
-.if ${MK_PMC} != "no"
-SUBDIR+= pmcannotate
-SUBDIR+= pmccontrol
-SUBDIR+= pmcstat
-SUBDIR+= pmcstudy
-.endif
-
-.if ${MK_PORTSNAP} != "no"
-SUBDIR+= portsnap
-.endif
-
-.if ${MK_PPP} != "no"
-SUBDIR+= ppp
-.endif
-
-.if ${MK_QUOTAS} != "no"
-SUBDIR+= edquota
-SUBDIR+= quotaon
-SUBDIR+= repquota
-.endif
-
-.if ${MK_RCMDS} != "no"
-SUBDIR+= rwhod
-.endif
-
-.if ${MK_RCS} != "no"
-SUBDIR+= etcupdate
-.endif
-
-.if ${MK_SENDMAIL} != "no"
-SUBDIR+= editmap
-SUBDIR+= mailstats
-SUBDIR+= makemap
-SUBDIR+= praliases
-SUBDIR+= sendmail
-.endif
-
-.if ${MK_TCP_WRAPPERS} != "no"
-SUBDIR+= tcpdchk
-SUBDIR+= tcpdmatch
-.endif
-
-.if ${MK_TESTS} != "no"
-SUBDIR+= tests
-.endif
-
-.if ${MK_TIMED} != "no"
-SUBDIR+= timed
-.endif
-
-.if ${MK_TOOLCHAIN} != "no"
-SUBDIR+= config
-SUBDIR+= crunch
-.endif
-
-.if ${MK_UNBOUND} != "no"
-SUBDIR+= unbound
-.endif
-
-.if ${MK_USB} != "no"
-SUBDIR+= uathload
-SUBDIR+= uhsoctl
-SUBDIR+= usbconfig
-SUBDIR+= usbdump
-.endif
-
-.if ${MK_UTMPX} != "no"
-SUBDIR+= ac
-SUBDIR+= lastlogin
-SUBDIR+= utx
-.endif
-
-.if ${MK_WIRELESS} != "no"
-SUBDIR+= ancontrol
-SUBDIR+= wlandebug
-SUBDIR+= wpa
-.endif
+SUBDIR.${MK_PPP}+= pppctl
+SUBDIR.${MK_NS_CACHING}+= nscd
+.endif
+SUBDIR.${MK_LPR}+= lpr
+SUBDIR.${MK_MAN_UTILS}+= manctl
+SUBDIR.${MK_NAND}+= nandsim
+SUBDIR.${MK_NAND}+= nandtool
+SUBDIR.${MK_NETGRAPH}+= flowctl
+SUBDIR.${MK_NETGRAPH}+= lmcconfig
+SUBDIR.${MK_NETGRAPH}+= ngctl
+SUBDIR.${MK_NETGRAPH}+= nghook
+SUBDIR.${MK_NIS}+= rpc.yppasswdd
+SUBDIR.${MK_NIS}+= rpc.ypupdated
+SUBDIR.${MK_NIS}+= rpc.ypxfrd
+SUBDIR.${MK_NIS}+= ypbind
+SUBDIR.${MK_NIS}+= yp_mkdb
+SUBDIR.${MK_NIS}+= yppoll
+SUBDIR.${MK_NIS}+= yppush
+SUBDIR.${MK_NIS}+= ypserv
+SUBDIR.${MK_NIS}+= ypset
+SUBDIR.${MK_NTP}+= ntp
+SUBDIR.${MK_OPENSSL}+= keyserv
+SUBDIR.${MK_PC_SYSINSTALL}+= pc-sysinstall
+SUBDIR.${MK_PF}+= ftp-proxy
+SUBDIR.${MK_PKGBOOTSTRAP}+= pkg
+SUBDIR.${MK_PMC}+= pmcannotate
+SUBDIR.${MK_PMC}+= pmccontrol
+SUBDIR.${MK_PMC}+= pmcstat
+SUBDIR.${MK_PORTSNAP}+= portsnap
+SUBDIR.${MK_PPP}+= ppp
+SUBDIR.${MK_QUOTAS}+= edquota
+SUBDIR.${MK_QUOTAS}+= quotaon
+SUBDIR.${MK_QUOTAS}+= repquota
+SUBDIR.${MK_RCMDS}+= rwhod
+SUBDIR.${MK_RCS}+= etcupdate
+SUBDIR.${MK_SENDMAIL}+= editmap
+SUBDIR.${MK_SENDMAIL}+= mailstats
+SUBDIR.${MK_SENDMAIL}+= makemap
+SUBDIR.${MK_SENDMAIL}+= praliases
+SUBDIR.${MK_SENDMAIL}+= sendmail
+SUBDIR.${MK_TCP_WRAPPERS}+= tcpdchk
+SUBDIR.${MK_TCP_WRAPPERS}+= tcpdmatch
+SUBDIR.${MK_TIMED}+= timed
+SUBDIR.${MK_TOOLCHAIN}+= config
+SUBDIR.${MK_TOOLCHAIN}+= crunch
+SUBDIR.${MK_UNBOUND}+= unbound
+SUBDIR.${MK_USB}+= uathload
+SUBDIR.${MK_USB}+= uhsoctl
+SUBDIR.${MK_USB}+= usbconfig
+SUBDIR.${MK_USB}+= usbdump
+SUBDIR.${MK_UTMPX}+= ac
+SUBDIR.${MK_UTMPX}+= lastlogin
+SUBDIR.${MK_UTMPX}+= utx
+SUBDIR.${MK_WIRELESS}+= ancontrol
+SUBDIR.${MK_WIRELESS}+= wlandebug
+SUBDIR.${MK_WIRELESS}+= wpa
+
+SUBDIR.${MK_TESTS}+= tests
.include <bsd.arch.inc.mk>
diff --git a/usr.sbin/mpsutil/Makefile b/usr.sbin/mpsutil/Makefile
index b559b7f..8ee4ec5 100644
--- a/usr.sbin/mpsutil/Makefile
+++ b/usr.sbin/mpsutil/Makefile
@@ -1,7 +1,7 @@
# $FreeBSD$
PROG= mpsutil
-SRCS= mpsutil.c mps_cmd.c mps_show.c
+SRCS= mps_cmd.c mps_flash.c mps_show.c mpsutil.c
MAN= mpsutil.8
WARNS?= 3
diff --git a/usr.sbin/mpsutil/mps_cmd.c b/usr.sbin/mpsutil/mps_cmd.c
index 2701773..876243f 100644
--- a/usr.sbin/mpsutil/mps_cmd.c
+++ b/usr.sbin/mpsutil/mps_cmd.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org>
+ *
* Copyright (c) 2015 Netflix, Inc.
* All rights reserved.
* Written by: Scott Long <scottl@freebsd.org>
@@ -442,6 +444,62 @@ mps_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion,
return (buf);
}
+int
+mps_firmware_send(int fd, unsigned char *fw, uint32_t len, bool bios)
+{
+ MPI2_FW_DOWNLOAD_REQUEST req;
+ MPI2_FW_DOWNLOAD_REPLY reply;
+
+ bzero(&req, sizeof(req));
+ bzero(&reply, sizeof(reply));
+ req.Function = MPI2_FUNCTION_FW_DOWNLOAD;
+ req.ImageType = bios ? MPI2_FW_DOWNLOAD_ITYPE_BIOS : MPI2_FW_DOWNLOAD_ITYPE_FW;
+ req.TotalImageSize = len;
+ req.MsgFlags = MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT;
+
+ if (mps_user_command(fd, &req, sizeof(req), &reply, sizeof(reply),
+ fw, len, 0)) {
+ return (-1);
+ }
+ return (0);
+}
+
+int
+mps_firmware_get(int fd, unsigned char **firmware, bool bios)
+{
+ MPI2_FW_UPLOAD_REQUEST req;
+ MPI2_FW_UPLOAD_REPLY reply;
+ int size;
+
+ *firmware = NULL;
+ bzero(&req, sizeof(req));
+ bzero(&reply, sizeof(reply));
+ req.Function = MPI2_FUNCTION_FW_UPLOAD;
+ req.ImageType = bios ? MPI2_FW_DOWNLOAD_ITYPE_BIOS : MPI2_FW_DOWNLOAD_ITYPE_FW;
+
+ if (mps_user_command(fd, &req, sizeof(req), &reply, sizeof(reply),
+ NULL, 0, 0)) {
+ return (-1);
+ }
+ if (reply.ActualImageSize == 0) {
+ return (-1);
+ }
+
+ size = reply.ActualImageSize;
+ *firmware = calloc(1, sizeof(char) * size);
+ if (*firmware == NULL) {
+ warn("calloc");
+ return (-1);
+ }
+ if (mps_user_command(fd, &req, sizeof(req), &reply, sizeof(reply),
+ *firmware, size, 0)) {
+ free(*firmware);
+ return (-1);
+ }
+
+ return (size);
+}
+
#else
int
diff --git a/usr.sbin/mpsutil/mps_flash.c b/usr.sbin/mpsutil/mps_flash.c
new file mode 100644
index 0000000..e22f29c
--- /dev/null
+++ b/usr.sbin/mpsutil/mps_flash.c
@@ -0,0 +1,237 @@
+/*-
+ * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$FreeBSD$");
+
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mpsutil.h"
+
+MPS_TABLE(top, flash);
+
+static int
+flash_save(int argc, char **argv)
+{
+ const char *firmware_file;
+ unsigned char *firmware_buffer = NULL;
+ int error, fd, size;
+ bool bios = false;
+ ssize_t written = 0, ret = 0;
+
+ if (argc < 2) {
+ warnx("missing argument: expecting 'firmware' or bios'");
+ return (EINVAL);
+ }
+
+ if (strcmp(argv[1], "bios") == 0) {
+ bios = true;
+ } else if (strcmp(argv[1], "firmware") != 0) {
+ warnx("Invalid argument '%s', expecting 'firmware' or 'bios'",
+ argv[1]);
+ }
+
+ if (argc > 4) {
+ warnx("save %s: extra arguments", argv[1]);
+ return (EINVAL);
+ }
+
+ firmware_file = argv[1];
+ if (argc == 3) {
+ firmware_file = argv[2];
+ }
+
+ fd = mps_open(mps_unit);
+ if (fd < 0) {
+ error = errno;
+ warn("mps_open");
+ return (error);
+ }
+
+ if ((size = mps_firmware_get(fd, &firmware_buffer, bios)) < 0) {
+ warnx("Fail to save %s", argv[1]);
+ return (1);
+ }
+
+ close(fd);
+ if (size > 0) {
+ fd = open(firmware_file, O_CREAT | O_TRUNC | O_RDWR, 0644);
+ if (fd <0) {
+ error = errno;
+ warn("open");
+ free(firmware_buffer);
+ return (error);
+ }
+ while (written != size) {
+ if ((ret = write(fd, firmware_buffer + written, size - written)) <0) {
+ error = errno;
+ warn("write");
+ free(firmware_buffer);
+ return (error);
+ }
+ written += ret;
+ }
+ close(fd);
+ }
+ free(firmware_buffer);
+ printf("%s successfully saved as %s\n", argv[1], firmware_file);
+ return (0);
+}
+
+MPS_COMMAND(flash, save, flash_save, "[firmware|bios] [file]",
+ "Save firmware/bios into a file");
+
+static int
+flash_update(int argc, char **argv)
+{
+ int error, fd;
+ unsigned char *mem = NULL;
+ struct stat st;
+ bool bios = false;
+ MPI2_FW_IMAGE_HEADER *fwheader;
+ MPI2_IOC_FACTS_REPLY *facts;
+
+ if (argc < 2) {
+ warnx("missing argument: expecting 'firmware' or bios'");
+ return (EINVAL);
+ }
+
+ if (strcmp(argv[1], "bios") == 0) {
+ bios = true;
+ } else if (strcmp(argv[1], "firmware") != 0) {
+ warnx("Invalid argument '%s', expecting 'firmware' or 'bios'",
+ argv[1]);
+ }
+
+ if (argc > 4) {
+ warnx("update firmware: extra arguments");
+ return (EINVAL);
+ }
+
+ if (argc != 3) {
+ warnx("no firmware specified");
+ return (EINVAL);
+ }
+
+ if (stat(argv[2], &st) == -1) {
+ error = errno;
+ warn("stat");
+ return (error);
+ }
+
+ fd = open(argv[2], O_RDONLY);
+ if (fd < 0) {
+ error = errno;
+ warn("open");
+ return (error);
+ }
+
+ mem = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (mem == MAP_FAILED) {
+ error = errno;
+ warn("mmap");
+ close(fd);
+ return (error);
+ }
+ close(fd);
+
+ fd = mps_open(mps_unit);
+ if (fd < 0) {
+ error = errno;
+ warn("mps_open");
+ munmap(mem, st.st_size);
+ return (error);
+ }
+
+ if ((facts = mps_get_iocfacts(fd)) == NULL) {
+ warnx("could not get controller IOCFacts\n");
+ munmap(mem, st.st_size);
+ close(fd);
+ return (EINVAL);
+ }
+
+ if (bios) {
+ /* Check boot record magic number */
+ if (((mem[0x01]<<8) + mem[0x00]) != 0xaa55) {
+ warnx("Invalid bios: no boot record magic number");
+ munmap(mem, st.st_size);
+ close(fd);
+ return (1);
+ }
+ if ((st.st_size % 512) != 0) {
+ warnx("Invalid bios: size not a multiple of 512");
+ munmap(mem, st.st_size);
+ close(fd);
+ return (1);
+ }
+ } else {
+ fwheader = (MPI2_FW_IMAGE_HEADER *)mem;
+ if (fwheader->VendorID != MPI2_MFGPAGE_VENDORID_LSI) {
+ warnx("Invalid firmware:");
+ warnx(" Expected Vendor ID: %04x",
+ MPI2_MFGPAGE_VENDORID_LSI);
+ warnx(" Image Vendor ID: %04x", fwheader->VendorID);
+ munmap(mem, st.st_size);
+ close(fd);
+ return (1);
+ }
+
+ if (fwheader->ProductID != facts->ProductID) {
+ warnx("Invalid image:");
+ warnx(" Expected Product ID: %04x", facts->ProductID);
+ warnx(" Image Product ID: %04x", fwheader->ProductID);
+ munmap(mem, st.st_size);
+ close(fd);
+ return (1);
+ }
+ }
+
+ printf("Updating %s...\n", argv[1]);
+ if (mps_firmware_send(fd, mem, st.st_size, bios) < 0) {
+ warnx("Fail to update %s", argv[1]);
+ munmap(mem, st.st_size);
+ close(fd);
+ return (1);
+ }
+
+ munmap(mem, st.st_size);
+ close(fd);
+ printf("%s successfully updated\n", argv[1]);
+ return (0);
+}
+
+MPS_COMMAND(flash, update, flash_update, "[firmware|bios] file",
+ "Update firmware/bios");
diff --git a/usr.sbin/mpsutil/mpsutil.8 b/usr.sbin/mpsutil/mpsutil.8
index 7b6dae4..6634b37 100644
--- a/usr.sbin/mpsutil/mpsutil.8
+++ b/usr.sbin/mpsutil/mpsutil.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 28, 2015
+.Dd November 17, 2015
.Dt MPSUTIL 8
.Os
.Sh NAME
@@ -60,6 +60,16 @@
.Nm
.Op Fl u Ar unit
.Cm show iocfacts
+.Nm
+.Op Fl u Ar unit
+.Cm flash save
+.Op Ar firmware Ns | Ns Ar bios
+.Op Ar file
+.Nm
+.Op Fl u Ar unit
+.Cm flash update
+.Op Ar firmware Ns | Ns Ar bios
+.Ar file
.Sh DESCRIPTION
The
.Nm
@@ -94,7 +104,9 @@ then unit 0 is used.
.Pp
The
.Nm
-utility currently only supports informational commands.
+utility supports several different groups of commands.
+The first group of commands provide information about the controller.
+The second group of commands are used to manager controller-wide operations.
.Pp
The informational commands include:
.Bl -tag -width indent
@@ -119,8 +131,32 @@ Displays IOC Facts messages.
.It Cm show cfgpage page Oo Ar num Oc Op Ar addr
Show IOC Facts Message
.El
+.Pp
+Controller management commands include:
+.Bl -tag -width indent
+.It Cm flash save Oo Ar firmware Ns | Ns Ar bios Oc Op Ar file
+Save the
+.Ar firmware
+or
+.Ar bios
+from the controller into a local
+.Ar file .
+If no
+.Ar file
+is specified then the file will be named
+.Pa firmware
+or
+.Pa bios .
+.It Cm flash update Oo Ar firmware Ns | Ns Ar bios Oc Ar file
+Replace the
+.Ar firmware
+or
+.Ar bios
+from the controller with the one specified via
+.Ar file .
+.El
.Sh SEE ALSO
-.Xr mpr 4
+.Xr mpr 4 ,
.Xr mps 4
.Sh HISTORY
The
diff --git a/usr.sbin/mpsutil/mpsutil.h b/usr.sbin/mpsutil/mpsutil.h
index dd6fc0b..46c7d44 100644
--- a/usr.sbin/mpsutil/mpsutil.h
+++ b/usr.sbin/mpsutil/mpsutil.h
@@ -35,6 +35,7 @@
#include <sys/cdefs.h>
#include <sys/linker_set.h>
+#include <stdbool.h>
#include <dev/mps/mpi/mpi2_type.h>
#include <dev/mps/mpi/mpi2.h>
@@ -122,6 +123,8 @@ void *mps_read_extended_config_page(int fd, U8 ExtPageType, U8 PageVersion,
int mps_map_btdh(int fd, uint16_t *devhandle, uint16_t *bus,
uint16_t *target);
const char *mps_ioc_status(U16 IOCStatus);
+int mps_firmware_send(int fd, unsigned char *buf, uint32_t len, bool bios);
+int mps_firmware_get(int fd, unsigned char **buf, bool bios);
static __inline void *
mps_read_man_page(int fd, U8 PageNumber, U16 *IOCStatus)
diff --git a/usr.sbin/pmcstat/pmcpl_gprof.c b/usr.sbin/pmcstat/pmcpl_gprof.c
index 9ff78e8..5fc9b41 100644
--- a/usr.sbin/pmcstat/pmcpl_gprof.c
+++ b/usr.sbin/pmcstat/pmcpl_gprof.c
@@ -74,6 +74,14 @@ __FBSDID("$FreeBSD$");
#include "pmcpl_callgraph.h"
#include "pmcpl_gprof.h"
+typedef uint64_t WIDEHISTCOUNTER;
+
+#define WIDEHISTCOUNTER_MAX UINT64_MAX
+#define HISTCOUNTER_MAX USHRT_MAX
+#define WIDEHISTCOUNTER_GMONTYPE ((int) 64)
+#define HISTCOUNTER_GMONTYPE ((int) 0)
+static int hc_sz=0;
+
/*
* struct pmcstat_gmonfile tracks a given 'gmon.out' file. These
* files are mmap()'ed in as needed.
@@ -126,11 +134,13 @@ pmcstat_gmon_create_file(struct pmcstat_gmonfile *pgf,
gm.lpc = image->pi_start;
gm.hpc = image->pi_end;
- gm.ncnt = (pgf->pgf_nbuckets * sizeof(HISTCOUNTER)) +
- sizeof(struct gmonhdr);
+ gm.ncnt = (pgf->pgf_nbuckets * hc_sz) + sizeof(struct gmonhdr);
gm.version = GMONVERSION;
gm.profrate = 0; /* use ticks */
- gm.histcounter_type = 0; /* compatibility with moncontrol() */
+ if (args.pa_flags & FLAG_DO_WIDE_GPROF_HC)
+ gm.histcounter_type = WIDEHISTCOUNTER_GMONTYPE;
+ else
+ gm.histcounter_type = HISTCOUNTER_GMONTYPE;
gm.spare[0] = gm.spare[1] = 0;
/* Write out the gmon header */
@@ -400,6 +410,7 @@ pmcpl_gmon_process(struct pmcstat_process *pp, struct pmcstat_pmcrecord *pmcr,
struct pmcstat_gmonfile *pgf;
uintfptr_t bucket;
HISTCOUNTER *hc;
+ WIDEHISTCOUNTER *whc;
pmc_id_t pmcid;
(void) nsamples; (void) usermode; (void) cpu;
@@ -437,6 +448,14 @@ pmcpl_gmon_process(struct pmcstat_process *pp, struct pmcstat_pmcrecord *pmcr,
*/
pgf = pmcstat_image_find_gmonfile(image, pmcid);
if (pgf == NULL) {
+ if (hc_sz == 0) {
+ /* Determine the correct histcounter size. */
+ if (args.pa_flags & FLAG_DO_WIDE_GPROF_HC)
+ hc_sz = sizeof(WIDEHISTCOUNTER);
+ else
+ hc_sz = sizeof(HISTCOUNTER);
+ }
+
if ((pgf = calloc(1, sizeof(*pgf))) == NULL)
err(EX_OSERR, "ERROR:");
@@ -448,7 +467,7 @@ pmcpl_gmon_process(struct pmcstat_process *pp, struct pmcstat_pmcrecord *pmcr,
pgf->pgf_nbuckets = (image->pi_end - image->pi_start) /
FUNCTION_ALIGNMENT; /* see <machine/profile.h> */
pgf->pgf_ndatabytes = sizeof(struct gmonhdr) +
- pgf->pgf_nbuckets * sizeof(HISTCOUNTER);
+ pgf->pgf_nbuckets * hc_sz;
pgf->pgf_nsamples = 0;
pgf->pgf_file = NULL;
@@ -474,14 +493,25 @@ pmcpl_gmon_process(struct pmcstat_process *pp, struct pmcstat_pmcrecord *pmcr,
assert(bucket < pgf->pgf_nbuckets);
- hc = (HISTCOUNTER *) ((uintptr_t) pgf->pgf_gmondata +
- sizeof(struct gmonhdr));
-
- /* saturating add */
- if (hc[bucket] < 0xFFFFU) /* XXX tie this to sizeof(HISTCOUNTER) */
- hc[bucket]++;
- else /* mark that an overflow occurred */
- pgf->pgf_overflow = 1;
+ if (args.pa_flags & FLAG_DO_WIDE_GPROF_HC) {
+ whc = (WIDEHISTCOUNTER *) ((uintptr_t) pgf->pgf_gmondata +
+ sizeof(struct gmonhdr));
+
+ /* saturating add */
+ if (whc[bucket] < WIDEHISTCOUNTER_MAX)
+ whc[bucket]++;
+ else /* mark that an overflow occurred */
+ pgf->pgf_overflow = 1;
+ } else {
+ hc = (HISTCOUNTER *) ((uintptr_t) pgf->pgf_gmondata +
+ sizeof(struct gmonhdr));
+
+ /* saturating add */
+ if (hc[bucket] < HISTCOUNTER_MAX)
+ hc[bucket]++;
+ else /* mark that an overflow occurred */
+ pgf->pgf_overflow = 1;
+ }
pgf->pgf_nsamples++;
}
diff --git a/usr.sbin/pmcstat/pmcstat.8 b/usr.sbin/pmcstat/pmcstat.8
index 25ff7a6..bc4bb74 100644
--- a/usr.sbin/pmcstat/pmcstat.8
+++ b/usr.sbin/pmcstat/pmcstat.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 27, 2015
+.Dd November 18, 2015
.Dt PMCSTAT 8
.Os
.Sh NAME
@@ -49,6 +49,7 @@
.Op Fl a Ar pathname
.Op Fl c Ar cpu-spec
.Op Fl d
+.Op Fl e
.Op Fl f Ar pluginopt
.Op Fl g
.Op Fl k Ar kerneldir
@@ -260,6 +261,12 @@ The default is to measure events for the target process alone.
.Fl P ,
or
.Fl S ) .
+.It Fl e
+Specify that the gprof profile files will use a wide history counter.
+These files are produced in a format compatible with
+.Xr gprof 1 .
+However, other tools that cannot fully parse a BSD-style
+gmon header might be unable to correctly parse these files.
.It Fl f Ar pluginopt
Pass option string to the active plugin.
.br
diff --git a/usr.sbin/pmcstat/pmcstat.c b/usr.sbin/pmcstat/pmcstat.c
index 914fc17..81b0cd0 100644
--- a/usr.sbin/pmcstat/pmcstat.c
+++ b/usr.sbin/pmcstat/pmcstat.c
@@ -506,6 +506,7 @@ pmcstat_show_usage(void)
"\t -a file\t print sampled PCs and callgraph to \"file\"\n"
"\t -c cpu-list\t set cpus for subsequent system-wide PMCs\n"
"\t -d\t\t (toggle) track descendants\n"
+ "\t -e\t\t use wide history counter for gprof(1) output\n"
"\t -f spec\t pass \"spec\" to as plugin option\n"
"\t -g\t\t produce gprof(1) compatible profiles\n"
"\t -k dir\t\t set the path to the kernel\n"
@@ -627,7 +628,7 @@ main(int argc, char **argv)
CPU_COPY(&rootmask, &cpumask);
while ((option = getopt(argc, argv,
- "CD:EF:G:M:NO:P:R:S:TWa:c:df:gk:l:m:n:o:p:qr:s:t:vw:z:")) != -1)
+ "CD:EF:G:M:NO:P:R:S:TWa:c:def:gk:l:m:n:o:p:qr:s:t:vw:z:")) != -1)
switch (option) {
case 'a': /* Annotate + callgraph */
args.pa_flags |= FLAG_DO_ANNOTATE;
@@ -668,6 +669,10 @@ main(int argc, char **argv)
args.pa_required |= FLAG_HAS_PROCESS_PMCS;
break;
+ case 'e': /* wide gprof metrics */
+ args.pa_flags |= FLAG_DO_WIDE_GPROF_HC;
+ break;
+
case 'F': /* produce a system-wide calltree */
args.pa_flags |= FLAG_DO_CALLGRAPHS;
args.pa_plugin = PMCSTAT_PL_CALLTREE;
@@ -1022,6 +1027,13 @@ main(int argc, char **argv)
"ERROR: options -g/-G/-m/-T require sampling PMCs or -R to be specified."
);
+ /* check if -e was specified without -g */
+ if ((args.pa_flags & FLAG_DO_WIDE_GPROF_HC) &&
+ !(args.pa_flags & FLAG_DO_GPROF))
+ errx(EX_USAGE,
+"ERROR: option -e requires gprof mode to be specified."
+ );
+
/* check if -O was spuriously specified */
if ((args.pa_flags & FLAG_HAS_OUTPUT_LOGFILE) &&
(args.pa_required & FLAG_HAS_OUTPUT_LOGFILE) == 0)
@@ -1500,14 +1512,24 @@ main(int argc, char **argv)
"ERROR: Cannot retrieve driver statistics");
if (ds_start.pm_intr_bufferfull != ds_end.pm_intr_bufferfull &&
args.pa_verbosity > 0)
- warnx("WARNING: some samples were dropped.\n"
-"Please consider tuning the \"kern.hwpmc.nsamples\" tunable."
+ warnx(
+"WARNING: sampling was paused at least %u time%s.\n"
+"Please consider tuning the \"kern.hwpmc.nsamples\" tunable.",
+ ds_end.pm_intr_bufferfull -
+ ds_start.pm_intr_bufferfull,
+ ((ds_end.pm_intr_bufferfull -
+ ds_start.pm_intr_bufferfull) != 1) ? "s" : ""
);
if (ds_start.pm_buffer_requests_failed !=
ds_end.pm_buffer_requests_failed &&
args.pa_verbosity > 0)
- warnx("WARNING: some events were discarded.\n"
-"Please consider tuning the \"kern.hwpmc.nbuffers\" tunable."
+ warnx(
+"WARNING: at least %u event%s were discarded while running.\n"
+"Please consider tuning the \"kern.hwpmc.nbuffers\" tunable.",
+ ds_end.pm_buffer_requests_failed -
+ ds_start.pm_buffer_requests_failed,
+ ((ds_end.pm_buffer_requests_failed -
+ ds_start.pm_buffer_requests_failed) != 1) ? "s" : ""
);
}
diff --git a/usr.sbin/pmcstat/pmcstat.h b/usr.sbin/pmcstat/pmcstat.h
index 29dfeb7..5b1d3d9 100644
--- a/usr.sbin/pmcstat/pmcstat.h
+++ b/usr.sbin/pmcstat/pmcstat.h
@@ -55,6 +55,7 @@
#define FLAG_DO_ANALYSIS 0x00020000 /* -g or -G or -m or -T */
#define FLAGS_HAS_CPUMASK 0x00040000 /* -c */
#define FLAG_HAS_DURATION 0x00080000 /* -l secs */
+#define FLAG_DO_WIDE_GPROF_HC 0x00100000 /* -e */
#define DEFAULT_SAMPLE_COUNT 65536
#define DEFAULT_WAIT_INTERVAL 5.0
diff --git a/usr.sbin/ypldap/Makefile b/usr.sbin/ypldap/Makefile
new file mode 100644
index 0000000..1d3cabc
--- /dev/null
+++ b/usr.sbin/ypldap/Makefile
@@ -0,0 +1,20 @@
+# $OpenBSD: Makefile,v 1.8 2015/09/09 15:33:18 deraadt Exp $
+# $FreeBSD$
+
+PROG= ypldap
+SRCS= parse.y ypldap.c log.c \
+ ldapclient.c entries.c yp.c \
+ aldap.c ber.c \
+ ypldap_dns.c
+
+MAN= ypldap.8 ypldap.conf.5
+
+LIBADD= openbsd event util rpcsvc
+
+CFLAGS+=-I${.CURDIR}
+CFLAGS+=-I${.CURDIR}/../../contrib/pf/libevent
+CFLAGS+=-I${.CURDIR}/../../lib/libopenbsd
+
+WARNS= 2
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/ypldap/aldap.c b/usr.sbin/ypldap/aldap.c
new file mode 100644
index 0000000..03e5224
--- /dev/null
+++ b/usr.sbin/ypldap/aldap.c
@@ -0,0 +1,1273 @@
+/* $Id: aldap.c,v 1.30 2012/04/30 21:40:03 jmatthew Exp $ */
+/* $OpenBSD: aldap.c,v 1.30 2012/04/30 21:40:03 jmatthew Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org>
+ * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <errno.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "aldap.h"
+
+#if 0
+#define DEBUG
+#endif
+#define VERSION 3
+
+static struct ber_element *ldap_parse_search_filter(struct ber_element *,
+ char *);
+static struct ber_element *ldap_do_parse_search_filter(
+ struct ber_element *, char **);
+char **aldap_get_stringset(struct ber_element *);
+char *utoa(char *);
+char *parseval(char *, size_t);
+int aldap_create_page_control(struct ber_element *,
+ int, struct aldap_page_control *);
+
+#ifdef DEBUG
+void ldap_debug_elements(struct ber_element *);
+#endif
+
+#ifdef DEBUG
+#define DPRINTF(x...) printf(x)
+#define LDAP_DEBUG(x, y) do { fprintf(stderr, "*** " x "\n"); ldap_debug_elements(y); } while (0)
+#else
+#define DPRINTF(x...) do { } while (0)
+#define LDAP_DEBUG(x, y) do { } while (0)
+#endif
+
+int
+aldap_close(struct aldap *al)
+{
+ if (close(al->ber.fd) == -1)
+ return (-1);
+
+ ber_free(&al->ber);
+ free(al);
+
+ return (0);
+}
+
+struct aldap *
+aldap_init(int fd)
+{
+ struct aldap *a;
+
+ if ((a = calloc(1, sizeof(*a))) == NULL)
+ return NULL;
+ a->ber.fd = fd;
+
+ return a;
+}
+
+int
+aldap_bind(struct aldap *ldap, char *binddn, char *bindcred)
+{
+ struct ber_element *root = NULL, *elm;
+ int error;
+
+ if (binddn == NULL)
+ binddn = "";
+ if (bindcred == NULL)
+ bindcred = "";
+
+ if ((root = ber_add_sequence(NULL)) == NULL)
+ goto fail;
+
+ elm = ber_printf_elements(root, "d{tdsst", ++ldap->msgid, BER_CLASS_APP,
+ (unsigned long)LDAP_REQ_BIND, VERSION, binddn, bindcred,
+ BER_CLASS_CONTEXT, (unsigned long)LDAP_AUTH_SIMPLE);
+ if (elm == NULL)
+ goto fail;
+
+ LDAP_DEBUG("aldap_bind", root);
+
+ error = ber_write_elements(&ldap->ber, root);
+ ber_free_elements(root);
+ root = NULL;
+ if (error == -1)
+ goto fail;
+
+ return (ldap->msgid);
+fail:
+ if (root != NULL)
+ ber_free_elements(root);
+
+ ldap->err = ALDAP_ERR_OPERATION_FAILED;
+ return (-1);
+}
+
+int
+aldap_unbind(struct aldap *ldap)
+{
+ struct ber_element *root = NULL, *elm;
+ int error;
+
+ if ((root = ber_add_sequence(NULL)) == NULL)
+ goto fail;
+ elm = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
+ LDAP_REQ_UNBIND_30);
+ if (elm == NULL)
+ goto fail;
+
+ LDAP_DEBUG("aldap_unbind", root);
+
+ error = ber_write_elements(&ldap->ber, root);
+ ber_free_elements(root);
+ root = NULL;
+ if (error == -1)
+ goto fail;
+
+ return (ldap->msgid);
+fail:
+ if (root != NULL)
+ ber_free_elements(root);
+
+ ldap->err = ALDAP_ERR_OPERATION_FAILED;
+
+ return (-1);
+}
+
+int
+aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter,
+ char **attrs, int typesonly, int sizelimit, int timelimit,
+ struct aldap_page_control *page)
+{
+ struct ber_element *root = NULL, *ber, *c;
+ int i, error;
+
+ if ((root = ber_add_sequence(NULL)) == NULL)
+ goto fail;
+
+ ber = ber_printf_elements(root, "d{t", ++ldap->msgid, BER_CLASS_APP,
+ (unsigned long) LDAP_REQ_SEARCH);
+ if (ber == NULL) {
+ ldap->err = ALDAP_ERR_OPERATION_FAILED;
+ goto fail;
+ }
+
+ c = ber;
+ ber = ber_printf_elements(ber, "sEEddb", basedn, (long long)scope,
+ (long long)LDAP_DEREF_NEVER, sizelimit,
+ timelimit, typesonly);
+ if (ber == NULL) {
+ ldap->err = ALDAP_ERR_OPERATION_FAILED;
+ goto fail;
+ }
+
+ if ((ber = ldap_parse_search_filter(ber, filter)) == NULL) {
+ ldap->err = ALDAP_ERR_PARSER_ERROR;
+ goto fail;
+ }
+
+ if ((ber = ber_add_sequence(ber)) == NULL)
+ goto fail;
+ if (attrs != NULL)
+ for (i = 0; attrs[i] != NULL; i++) {
+ if ((ber = ber_add_string(ber, attrs[i])) == NULL)
+ goto fail;
+ }
+
+ aldap_create_page_control(c, 100, page);
+
+ LDAP_DEBUG("aldap_search", root);
+
+ error = ber_write_elements(&ldap->ber, root);
+ ber_free_elements(root);
+ root = NULL;
+ if (error == -1) {
+ ldap->err = ALDAP_ERR_OPERATION_FAILED;
+ goto fail;
+ }
+
+ return (ldap->msgid);
+
+fail:
+ if (root != NULL)
+ ber_free_elements(root);
+
+ return (-1);
+}
+
+int
+aldap_create_page_control(struct ber_element *elm, int size,
+ struct aldap_page_control *page)
+{
+ int len;
+ struct ber c;
+ struct ber_element *ber = NULL;
+
+ c.br_wbuf = NULL;
+ c.fd = -1;
+
+ ber = ber_add_sequence(NULL);
+
+ if (page == NULL) {
+ if (ber_printf_elements(ber, "ds", 50, "") == NULL)
+ goto fail;
+ } else {
+ if (ber_printf_elements(ber, "dx", 50, page->cookie,
+ page->cookie_len) == NULL)
+ goto fail;
+ }
+
+ if ((len = ber_write_elements(&c, ber)) < 1)
+ goto fail;
+ if (ber_printf_elements(elm, "{t{sx", 2, 0, LDAP_PAGED_OID,
+ c.br_wbuf, (size_t)len) == NULL)
+ goto fail;
+
+ ber_free_elements(ber);
+ ber_free(&c);
+ return len;
+fail:
+ if (ber != NULL)
+ ber_free_elements(ber);
+ ber_free(&c);
+
+ return (-1);
+}
+
+struct aldap_message *
+aldap_parse(struct aldap *ldap)
+{
+ int class;
+ unsigned long type;
+ long long msgid = 0;
+ struct aldap_message *m;
+ struct ber_element *a = NULL, *ep;
+
+ if ((m = calloc(1, sizeof(struct aldap_message))) == NULL)
+ return NULL;
+
+ if ((m->msg = ber_read_elements(&ldap->ber, NULL)) == NULL)
+ goto parsefail;
+
+ LDAP_DEBUG("message", m->msg);
+
+ if (ber_scanf_elements(m->msg, "{ite", &msgid, &class, &type, &a) != 0)
+ goto parsefail;
+ m->msgid = msgid;
+ m->message_type = type;
+ m->protocol_op = a;
+
+ switch (m->message_type) {
+ case LDAP_RES_BIND:
+ case LDAP_RES_MODIFY:
+ case LDAP_RES_ADD:
+ case LDAP_RES_DELETE:
+ case LDAP_RES_MODRDN:
+ case LDAP_RES_COMPARE:
+ case LDAP_RES_SEARCH_RESULT:
+ if (ber_scanf_elements(m->protocol_op, "{EeSeSe",
+ &m->body.res.rescode, &m->dn, &m->body.res.diagmsg, &a) != 0)
+ goto parsefail;
+ if (m->body.res.rescode == LDAP_REFERRAL)
+ if (ber_scanf_elements(a, "{e", &m->references) != 0)
+ goto parsefail;
+ if (m->msg->be_sub) {
+ for (ep = m->msg->be_sub; ep != NULL; ep = ep->be_next) {
+ ber_scanf_elements(ep, "t", &class, &type);
+ if (class == 2 && type == 0)
+ m->page = aldap_parse_page_control(ep->be_sub->be_sub,
+ ep->be_sub->be_sub->be_len);
+ }
+ } else
+ m->page = NULL;
+ break;
+ case LDAP_RES_SEARCH_ENTRY:
+ if (ber_scanf_elements(m->protocol_op, "{eS{e", &m->dn,
+ &m->body.search.attrs) != 0)
+ goto parsefail;
+ break;
+ case LDAP_RES_SEARCH_REFERENCE:
+ if (ber_scanf_elements(m->protocol_op, "{e", &m->references) != 0)
+ goto parsefail;
+ break;
+ }
+
+ return m;
+parsefail:
+ ldap->err = ALDAP_ERR_PARSER_ERROR;
+ aldap_freemsg(m);
+ return NULL;
+}
+
+struct aldap_page_control *
+aldap_parse_page_control(struct ber_element *control, size_t len)
+{
+ char *oid, *s;
+ char *encoded;
+ struct ber b;
+ struct ber_element *elm;
+ struct aldap_page_control *page;
+
+ b.br_wbuf = NULL;
+ b.fd = -1;
+ ber_scanf_elements(control, "ss", &oid, &encoded);
+ ber_set_readbuf(&b, encoded, control->be_next->be_len);
+ elm = ber_read_elements(&b, NULL);
+
+ if ((page = malloc(sizeof(struct aldap_page_control))) == NULL) {
+ if (elm != NULL)
+ ber_free_elements(elm);
+ ber_free(&b);
+ return NULL;
+ }
+
+ ber_scanf_elements(elm->be_sub, "is", &page->size, &s);
+ page->cookie_len = elm->be_sub->be_next->be_len;
+
+ if ((page->cookie = malloc(page->cookie_len)) == NULL) {
+ if (elm != NULL)
+ ber_free_elements(elm);
+ ber_free(&b);
+ free(page);
+ return NULL;
+ }
+ memcpy(page->cookie, s, page->cookie_len);
+
+ ber_free_elements(elm);
+ ber_free(&b);
+ return page;
+}
+
+void
+aldap_freepage(struct aldap_page_control *page)
+{
+ if (page->cookie)
+ free(page->cookie);
+ free(page);
+}
+
+void
+aldap_freemsg(struct aldap_message *msg)
+{
+ if (msg->msg)
+ ber_free_elements(msg->msg);
+ free(msg);
+}
+
+int
+aldap_get_resultcode(struct aldap_message *msg)
+{
+ return msg->body.res.rescode;
+}
+
+char *
+aldap_get_dn(struct aldap_message *msg)
+{
+ char *dn;
+
+ if (msg->dn == NULL)
+ return NULL;
+
+ if (ber_get_string(msg->dn, &dn) == -1)
+ return NULL;
+
+ return utoa(dn);
+}
+
+char **
+aldap_get_references(struct aldap_message *msg)
+{
+ if (msg->references == NULL)
+ return NULL;
+ return aldap_get_stringset(msg->references);
+}
+
+void
+aldap_free_references(char **values)
+{
+ int i;
+
+ if (values == NULL)
+ return;
+
+ for (i = 0; values[i] != NULL; i++)
+ free(values[i]);
+
+ free(values);
+}
+
+char *
+aldap_get_diagmsg(struct aldap_message *msg)
+{
+ char *s;
+
+ if (msg->body.res.diagmsg == NULL)
+ return NULL;
+
+ if (ber_get_string(msg->body.res.diagmsg, &s) == -1)
+ return NULL;
+
+ return utoa(s);
+}
+
+int
+aldap_count_attrs(struct aldap_message *msg)
+{
+ int i;
+ struct ber_element *a;
+
+ if (msg->body.search.attrs == NULL)
+ return (-1);
+
+ for (i = 0, a = msg->body.search.attrs;
+ a != NULL && ber_get_eoc(a) != 0;
+ i++, a = a->be_next)
+ ;
+
+ return i;
+}
+
+int
+aldap_first_attr(struct aldap_message *msg, char **outkey, char ***outvalues)
+{
+ struct ber_element *b, *c;
+ char *key;
+ char **ret;
+
+ if (msg->body.search.attrs == NULL)
+ goto fail;
+
+ if (ber_scanf_elements(msg->body.search.attrs, "{s(e)}e",
+ &key, &b, &c) != 0)
+ goto fail;
+
+ msg->body.search.iter = msg->body.search.attrs->be_next;
+
+ if ((ret = aldap_get_stringset(b)) == NULL)
+ goto fail;
+
+ (*outvalues) = ret;
+ (*outkey) = utoa(key);
+
+ return (1);
+fail:
+ (*outkey) = NULL;
+ (*outvalues) = NULL;
+ return (-1);
+}
+
+int
+aldap_next_attr(struct aldap_message *msg, char **outkey, char ***outvalues)
+{
+ struct ber_element *a, *b;
+ char *key;
+ char **ret;
+
+ if (msg->body.search.iter == NULL)
+ goto notfound;
+
+ LDAP_DEBUG("attr", msg->body.search.iter);
+
+ if (ber_get_eoc(msg->body.search.iter) == 0)
+ goto notfound;
+
+ if (ber_scanf_elements(msg->body.search.iter, "{s(e)}e", &key, &a, &b)
+ != 0)
+ goto fail;
+
+ msg->body.search.iter = msg->body.search.iter->be_next;
+
+ if ((ret = aldap_get_stringset(a)) == NULL)
+ goto fail;
+
+ (*outvalues) = ret;
+ (*outkey) = utoa(key);
+
+ return (1);
+fail:
+notfound:
+ (*outkey) = NULL;
+ (*outvalues) = NULL;
+ return (-1);
+}
+
+int
+aldap_match_attr(struct aldap_message *msg, char *inkey, char ***outvalues)
+{
+ struct ber_element *a, *b;
+ char *descr = NULL;
+ char **ret;
+
+ if (msg->body.search.attrs == NULL)
+ goto fail;
+
+ LDAP_DEBUG("attr", msg->body.search.attrs);
+
+ for (a = msg->body.search.attrs;;) {
+ if (a == NULL)
+ goto notfound;
+ if (ber_get_eoc(a) == 0)
+ goto notfound;
+ if (ber_scanf_elements(a, "{s(e", &descr, &b) != 0)
+ goto fail;
+ if (strcasecmp(descr, inkey) == 0)
+ goto attrfound;
+ a = a->be_next;
+ }
+
+attrfound:
+ if ((ret = aldap_get_stringset(b)) == NULL)
+ goto fail;
+
+ (*outvalues) = ret;
+
+ return (1);
+fail:
+notfound:
+ (*outvalues) = NULL;
+ return (-1);
+}
+
+int
+aldap_free_attr(char **values)
+{
+ int i;
+
+ if (values == NULL)
+ return -1;
+
+ for (i = 0; values[i] != NULL; i++)
+ free(values[i]);
+
+ free(values);
+
+ return (1);
+}
+
+#if 0
+void
+aldap_free_url(struct aldap_url *lu)
+{
+ free(lu->buffer);
+ free(lu->filter);
+}
+
+int
+aldap_parse_url(char *url, struct aldap_url *lu)
+{
+ char *p, *forward, *forward2;
+ const char *errstr = NULL;
+ int i;
+
+ if ((lu->buffer = p = strdup(url)) == NULL)
+ return (-1);
+
+ /* protocol */
+ if (strncasecmp(LDAP_URL, p, strlen(LDAP_URL)) != 0)
+ goto fail;
+ lu->protocol = LDAP;
+ p += strlen(LDAP_URL);
+
+ /* host and optional port */
+ if ((forward = strchr(p, '/')) != NULL)
+ *forward = '\0';
+ /* find the optional port */
+ if ((forward2 = strchr(p, ':')) != NULL) {
+ *forward2 = '\0';
+ /* if a port is given */
+ if (*(forward2+1) != '\0') {
+#define PORT_MAX UINT16_MAX
+ lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr);
+ if (errstr)
+ goto fail;
+ }
+ }
+ /* fail if no host is given */
+ if (strlen(p) == 0)
+ goto fail;
+ lu->host = p;
+ if (forward == NULL)
+ goto done;
+ /* p is assigned either a pointer to a character or to '\0' */
+ p = ++forward;
+ if (strlen(p) == 0)
+ goto done;
+
+ /* dn */
+ if ((forward = strchr(p, '?')) != NULL)
+ *forward = '\0';
+ lu->dn = p;
+ if (forward == NULL)
+ goto done;
+ /* p is assigned either a pointer to a character or to '\0' */
+ p = ++forward;
+ if (strlen(p) == 0)
+ goto done;
+
+ /* attributes */
+ if ((forward = strchr(p, '?')) != NULL)
+ *forward = '\0';
+ for (i = 0; i < MAXATTR; i++) {
+ if ((forward2 = strchr(p, ',')) == NULL) {
+ if (strlen(p) == 0)
+ break;
+ lu->attributes[i] = p;
+ break;
+ }
+ *forward2 = '\0';
+ lu->attributes[i] = p;
+ p = ++forward2;
+ }
+ if (forward == NULL)
+ goto done;
+ /* p is assigned either a pointer to a character or to '\0' */
+ p = ++forward;
+ if (strlen(p) == 0)
+ goto done;
+
+ /* scope */
+ if ((forward = strchr(p, '?')) != NULL)
+ *forward = '\0';
+ if (strcmp(p, "base") == 0)
+ lu->scope = LDAP_SCOPE_BASE;
+ else if (strcmp(p, "one") == 0)
+ lu->scope = LDAP_SCOPE_ONELEVEL;
+ else if (strcmp(p, "sub") == 0)
+ lu->scope = LDAP_SCOPE_SUBTREE;
+ else
+ goto fail;
+ if (forward == NULL)
+ goto done;
+ p = ++forward;
+ if (strlen(p) == 0)
+ goto done;
+
+ /* filter */
+ if (p)
+ lu->filter = p;
+done:
+ free(url);
+ return (1);
+fail:
+ free(lu->buffer);
+ lu->buffer = NULL;
+ return (-1);
+}
+
+int
+aldap_search_url(struct aldap *ldap, char *url, int typesonly, int sizelimit,
+ int timelimit)
+{
+ struct aldap_url *lu;
+
+ if ((lu = calloc(1, sizeof(*lu))) == NULL)
+ return (-1);
+
+ if (aldap_parse_url(url, lu))
+ goto fail;
+
+ if (aldap_search(ldap, lu->dn, lu->scope, lu->filter, lu->attributes,
+ typesonly, sizelimit, timelimit) == -1)
+ goto fail;
+
+ aldap_free_url(lu);
+ return (ldap->msgid);
+fail:
+ aldap_free_url(lu);
+ return (-1);
+}
+#endif /* 0 */
+
+/*
+ * internal functions
+ */
+
+char **
+aldap_get_stringset(struct ber_element *elm)
+{
+ struct ber_element *a;
+ int i;
+ char **ret;
+ char *s;
+
+ if (elm->be_type != BER_TYPE_OCTETSTRING)
+ return NULL;
+
+ for (a = elm, i = 1; i > 0 && a != NULL && a->be_type ==
+ BER_TYPE_OCTETSTRING; a = a->be_next, i++)
+ ;
+ if (i == 1)
+ return NULL;
+
+ if ((ret = calloc(i + 1, sizeof(char *))) == NULL)
+ return NULL;
+
+ for (a = elm, i = 0; a != NULL && a->be_type == BER_TYPE_OCTETSTRING;
+ a = a->be_next, i++) {
+
+ ber_get_string(a, &s);
+ ret[i] = utoa(s);
+ }
+ ret[i + 1] = NULL;
+
+ return ret;
+}
+
+/*
+ * Base case for ldap_do_parse_search_filter
+ *
+ * returns:
+ * struct ber_element *, ber_element tree
+ * NULL, parse failed
+ */
+static struct ber_element *
+ldap_parse_search_filter(struct ber_element *ber, char *filter)
+{
+ struct ber_element *elm;
+ char *cp;
+
+ cp = filter;
+
+ if (cp == NULL || *cp == '\0') {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if ((elm = ldap_do_parse_search_filter(ber, &cp)) == NULL)
+ return (NULL);
+
+ if (*cp != '\0') {
+ ber_free_elements(elm);
+ ber_link_elements(ber, NULL);
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ return (elm);
+}
+
+/*
+ * Translate RFC4515 search filter string into ber_element tree
+ *
+ * returns:
+ * struct ber_element *, ber_element tree
+ * NULL, parse failed
+ *
+ * notes:
+ * when cp is passed to a recursive invocation, it is updated
+ * to point one character beyond the filter that was passed
+ * i.e., cp jumps to "(filter)" upon return
+ * ^
+ * goto's used to discriminate error-handling based on error type
+ * doesn't handle extended filters (yet)
+ *
+ */
+static struct ber_element *
+ldap_do_parse_search_filter(struct ber_element *prev, char **cpp)
+{
+ struct ber_element *elm, *root = NULL;
+ char *attr_desc, *attr_val, *parsed_val, *cp;
+ size_t len;
+ unsigned long type;
+
+ root = NULL;
+
+ /* cpp should pass in pointer to opening parenthesis of "(filter)" */
+ cp = *cpp;
+ if (*cp != '(')
+ goto syntaxfail;
+
+ switch (*++cp) {
+ case '&': /* AND */
+ case '|': /* OR */
+ if (*cp == '&')
+ type = LDAP_FILT_AND;
+ else
+ type = LDAP_FILT_OR;
+
+ if ((elm = ber_add_set(prev)) == NULL)
+ goto callfail;
+ root = elm;
+ ber_set_header(elm, BER_CLASS_CONTEXT, type);
+
+ if (*++cp != '(') /* opening `(` of filter */
+ goto syntaxfail;
+
+ while (*cp == '(') {
+ if ((elm =
+ ldap_do_parse_search_filter(elm, &cp)) == NULL)
+ goto bad;
+ }
+
+ if (*cp != ')') /* trailing `)` of filter */
+ goto syntaxfail;
+ break;
+
+ case '!': /* NOT */
+ if ((root = ber_add_sequence(prev)) == NULL)
+ goto callfail;
+ ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_NOT);
+
+ cp++; /* now points to sub-filter */
+ if ((elm = ldap_do_parse_search_filter(root, &cp)) == NULL)
+ goto bad;
+
+ if (*cp != ')') /* trailing `)` of filter */
+ goto syntaxfail;
+ break;
+
+ default: /* SIMPLE || PRESENCE */
+ attr_desc = cp;
+
+ len = strcspn(cp, "()<>~=");
+ cp += len;
+ switch (*cp) {
+ case '~':
+ type = LDAP_FILT_APPR;
+ cp++;
+ break;
+ case '<':
+ type = LDAP_FILT_LE;
+ cp++;
+ break;
+ case '>':
+ type = LDAP_FILT_GE;
+ cp++;
+ break;
+ case '=':
+ type = LDAP_FILT_EQ; /* assume EQ until disproven */
+ break;
+ case '(':
+ case ')':
+ default:
+ goto syntaxfail;
+ }
+ attr_val = ++cp;
+
+ /* presence filter */
+ if (strncmp(attr_val, "*)", 2) == 0) {
+ cp++; /* point to trailing `)` */
+ if ((root =
+ ber_add_nstring(prev, attr_desc, len)) == NULL)
+ goto bad;
+
+ ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_PRES);
+ break;
+ }
+
+ if ((root = ber_add_sequence(prev)) == NULL)
+ goto callfail;
+ ber_set_header(root, BER_CLASS_CONTEXT, type);
+
+ if ((elm = ber_add_nstring(root, attr_desc, len)) == NULL)
+ goto callfail;
+
+ len = strcspn(attr_val, "*)");
+ if (len == 0 && *cp != '*')
+ goto syntaxfail;
+ cp += len;
+ if (*cp == '\0')
+ goto syntaxfail;
+
+ if (*cp == '*') { /* substring filter */
+ int initial;
+
+ cp = attr_val;
+
+ ber_set_header(root, BER_CLASS_CONTEXT, LDAP_FILT_SUBS);
+
+ if ((elm = ber_add_sequence(elm)) == NULL)
+ goto callfail;
+
+ for (initial = 1;; cp++, initial = 0) {
+ attr_val = cp;
+
+ len = strcspn(attr_val, "*)");
+ if (len == 0) {
+ if (*cp == ')')
+ break;
+ else
+ continue;
+ }
+ cp += len;
+ if (*cp == '\0')
+ goto syntaxfail;
+
+ if (initial)
+ type = LDAP_FILT_SUBS_INIT;
+ else if (*cp == ')')
+ type = LDAP_FILT_SUBS_FIN;
+ else
+ type = LDAP_FILT_SUBS_ANY;
+
+ if ((parsed_val = parseval(attr_val, len)) ==
+ NULL)
+ goto callfail;
+ elm = ber_add_nstring(elm, parsed_val,
+ strlen(parsed_val));
+ free(parsed_val);
+ if (elm == NULL)
+ goto callfail;
+ ber_set_header(elm, BER_CLASS_CONTEXT, type);
+ if (type == LDAP_FILT_SUBS_FIN)
+ break;
+ }
+ break;
+ }
+
+ if ((parsed_val = parseval(attr_val, len)) == NULL)
+ goto callfail;
+ elm = ber_add_nstring(elm, parsed_val, strlen(parsed_val));
+ free(parsed_val);
+ if (elm == NULL)
+ goto callfail;
+ break;
+ }
+
+ cp++; /* now points one char beyond the trailing `)` */
+
+ *cpp = cp;
+ return (root);
+
+syntaxfail: /* XXX -- error reporting */
+callfail:
+bad:
+ if (root != NULL)
+ ber_free_elements(root);
+ ber_link_elements(prev, NULL);
+ return (NULL);
+}
+
+#ifdef DEBUG
+/*
+ * Display a list of ber elements.
+ *
+ */
+void
+ldap_debug_elements(struct ber_element *root)
+{
+ static int indent = 0;
+ long long v;
+ int d;
+ char *buf;
+ size_t len;
+ u_int i;
+ int constructed;
+ struct ber_oid o;
+
+ /* calculate lengths */
+ ber_calc_len(root);
+
+ switch (root->be_encoding) {
+ case BER_TYPE_SEQUENCE:
+ case BER_TYPE_SET:
+ constructed = root->be_encoding;
+ break;
+ default:
+ constructed = 0;
+ break;
+ }
+
+ fprintf(stderr, "%*slen %lu ", indent, "", root->be_len);
+ switch (root->be_class) {
+ case BER_CLASS_UNIVERSAL:
+ fprintf(stderr, "class: universal(%u) type: ", root->be_class);
+ switch (root->be_type) {
+ case BER_TYPE_EOC:
+ fprintf(stderr, "end-of-content");
+ break;
+ case BER_TYPE_BOOLEAN:
+ fprintf(stderr, "boolean");
+ break;
+ case BER_TYPE_INTEGER:
+ fprintf(stderr, "integer");
+ break;
+ case BER_TYPE_BITSTRING:
+ fprintf(stderr, "bit-string");
+ break;
+ case BER_TYPE_OCTETSTRING:
+ fprintf(stderr, "octet-string");
+ break;
+ case BER_TYPE_NULL:
+ fprintf(stderr, "null");
+ break;
+ case BER_TYPE_OBJECT:
+ fprintf(stderr, "object");
+ break;
+ case BER_TYPE_ENUMERATED:
+ fprintf(stderr, "enumerated");
+ break;
+ case BER_TYPE_SEQUENCE:
+ fprintf(stderr, "sequence");
+ break;
+ case BER_TYPE_SET:
+ fprintf(stderr, "set");
+ break;
+ }
+ break;
+ case BER_CLASS_APPLICATION:
+ fprintf(stderr, "class: application(%u) type: ",
+ root->be_class);
+ switch (root->be_type) {
+ case LDAP_REQ_BIND:
+ fprintf(stderr, "bind");
+ break;
+ case LDAP_RES_BIND:
+ fprintf(stderr, "bind");
+ break;
+ case LDAP_REQ_UNBIND_30:
+ break;
+ case LDAP_REQ_SEARCH:
+ fprintf(stderr, "search");
+ break;
+ case LDAP_RES_SEARCH_ENTRY:
+ fprintf(stderr, "search_entry");
+ break;
+ case LDAP_RES_SEARCH_RESULT:
+ fprintf(stderr, "search_result");
+ break;
+ case LDAP_REQ_MODIFY:
+ fprintf(stderr, "modify");
+ break;
+ case LDAP_RES_MODIFY:
+ fprintf(stderr, "modify");
+ break;
+ case LDAP_REQ_ADD:
+ fprintf(stderr, "add");
+ break;
+ case LDAP_RES_ADD:
+ fprintf(stderr, "add");
+ break;
+ case LDAP_REQ_DELETE_30:
+ fprintf(stderr, "delete");
+ break;
+ case LDAP_RES_DELETE:
+ fprintf(stderr, "delete");
+ break;
+ case LDAP_REQ_MODRDN:
+ fprintf(stderr, "modrdn");
+ break;
+ case LDAP_RES_MODRDN:
+ fprintf(stderr, "modrdn");
+ break;
+ case LDAP_REQ_COMPARE:
+ fprintf(stderr, "compare");
+ break;
+ case LDAP_RES_COMPARE:
+ fprintf(stderr, "compare");
+ break;
+ case LDAP_REQ_ABANDON_30:
+ fprintf(stderr, "abandon");
+ break;
+ }
+ break;
+ case BER_CLASS_PRIVATE:
+ fprintf(stderr, "class: private(%u) type: ", root->be_class);
+ fprintf(stderr, "encoding (%lu) type: ", root->be_encoding);
+ break;
+ case BER_CLASS_CONTEXT:
+ /* XXX: this is not correct */
+ fprintf(stderr, "class: context(%u) type: ", root->be_class);
+ switch(root->be_type) {
+ case LDAP_AUTH_SIMPLE:
+ fprintf(stderr, "auth simple");
+ break;
+ }
+ break;
+ default:
+ fprintf(stderr, "class: <INVALID>(%u) type: ", root->be_class);
+ break;
+ }
+ fprintf(stderr, "(%lu) encoding %lu ",
+ root->be_type, root->be_encoding);
+
+ if (constructed)
+ root->be_encoding = constructed;
+
+ switch (root->be_encoding) {
+ case BER_TYPE_BOOLEAN:
+ if (ber_get_boolean(root, &d) == -1) {
+ fprintf(stderr, "<INVALID>\n");
+ break;
+ }
+ fprintf(stderr, "%s(%d)\n", d ? "true" : "false", d);
+ break;
+ case BER_TYPE_INTEGER:
+ if (ber_get_integer(root, &v) == -1) {
+ fprintf(stderr, "<INVALID>\n");
+ break;
+ }
+ fprintf(stderr, "value %lld\n", v);
+ break;
+ case BER_TYPE_ENUMERATED:
+ if (ber_get_enumerated(root, &v) == -1) {
+ fprintf(stderr, "<INVALID>\n");
+ break;
+ }
+ fprintf(stderr, "value %lld\n", v);
+ break;
+ case BER_TYPE_BITSTRING:
+ if (ber_get_bitstring(root, (void *)&buf, &len) == -1) {
+ fprintf(stderr, "<INVALID>\n");
+ break;
+ }
+ fprintf(stderr, "hexdump ");
+ for (i = 0; i < len; i++)
+ fprintf(stderr, "%02x", buf[i]);
+ fprintf(stderr, "\n");
+ break;
+ case BER_TYPE_OBJECT:
+ if (ber_get_oid(root, &o) == -1) {
+ fprintf(stderr, "<INVALID>\n");
+ break;
+ }
+ fprintf(stderr, "\n");
+ break;
+ case BER_TYPE_OCTETSTRING:
+ if (ber_get_nstring(root, (void *)&buf, &len) == -1) {
+ fprintf(stderr, "<INVALID>\n");
+ break;
+ }
+ fprintf(stderr, "string \"%.*s\"\n", len, buf);
+ break;
+ case BER_TYPE_NULL: /* no payload */
+ case BER_TYPE_EOC:
+ case BER_TYPE_SEQUENCE:
+ case BER_TYPE_SET:
+ default:
+ fprintf(stderr, "\n");
+ break;
+ }
+
+ if (constructed && root->be_sub) {
+ indent += 2;
+ ldap_debug_elements(root->be_sub);
+ indent -= 2;
+ }
+ if (root->be_next)
+ ldap_debug_elements(root->be_next);
+}
+#endif
+
+/*
+ * Convert UTF-8 to ASCII.
+ * notes:
+ * non-ASCII characters are displayed as '?'
+ * the argument u should be a NULL terminated sequence of UTF-8 bytes.
+ */
+char *
+utoa(char *u)
+{
+ int len, i, j;
+ char *str;
+
+ /* calculate the length to allocate */
+ for (len = 0, i = 0; u[i] != '\0'; ) {
+ if ((u[i] & 0xF0) == 0xF0)
+ i += 4;
+ else if ((u[i] & 0xE0) == 0xE0)
+ i += 3;
+ else if ((u[i] & 0xC0) == 0xC0)
+ i += 2;
+ else
+ i += 1;
+ len++;
+ }
+
+ if ((str = calloc(len + 1, sizeof(char))) == NULL)
+ return NULL;
+
+ /* copy the ASCII characters to the newly allocated string */
+ for (i = 0, j = 0; u[i] != '\0'; j++) {
+ if ((u[i] & 0xF0) == 0xF0) {
+ str[j] = '?';
+ i += 4;
+ } else if ((u[i] & 0xE0) == 0xE0) {
+ str[j] = '?';
+ i += 3;
+ } else if ((u[i] & 0xC0) == 0xC0) {
+ str[j] = '?';
+ i += 2;
+ } else {
+ str[j] = u[i];
+ i += 1;
+ }
+ }
+
+ return str;
+}
+
+/*
+ * Parse a LDAP value
+ * notes:
+ * the argument u should be a NULL terminated sequence of ASCII bytes.
+ */
+char *
+parseval(char *p, size_t len)
+{
+ char hex[3];
+ char *cp = p, *buffer, *newbuffer;
+ size_t size, newsize, i, j;
+
+ size = 50;
+ if ((buffer = calloc(1, size)) == NULL)
+ return NULL;
+
+ for (i = j = 0; j < len; i++) {
+ if (i >= size) {
+ newsize = size + 1024;
+ if ((newbuffer = realloc(buffer, newsize)) == NULL) {
+ free(buffer);
+ return (NULL);
+ }
+ buffer = newbuffer;
+ size = newsize;
+ }
+
+ if (cp[j] == '\\') {
+ strlcpy(hex, cp + j + 1, sizeof(hex));
+ buffer[i] = (char)strtoumax(hex, NULL, 16);
+ j += 3;
+ } else {
+ buffer[i] = cp[j];
+ j++;
+ }
+ }
+
+ return buffer;
+}
+
+int
+aldap_get_errno(struct aldap *a, const char **estr)
+{
+ switch (a->err) {
+ case ALDAP_ERR_SUCCESS:
+ *estr = "success";
+ break;
+ case ALDAP_ERR_PARSER_ERROR:
+ *estr = "parser failed";
+ break;
+ case ALDAP_ERR_INVALID_FILTER:
+ *estr = "invalid filter";
+ break;
+ case ALDAP_ERR_OPERATION_FAILED:
+ *estr = "operation failed";
+ break;
+ default:
+ *estr = "unknown";
+ break;
+ }
+ return (a->err);
+}
diff --git a/usr.sbin/ypldap/aldap.h b/usr.sbin/ypldap/aldap.h
new file mode 100644
index 0000000..cdf5316
--- /dev/null
+++ b/usr.sbin/ypldap/aldap.h
@@ -0,0 +1,221 @@
+/* $Id: aldap.h,v 1.9 2012/04/30 21:40:03 jmatthew Exp $ */
+/* $OpenBSD: aldap.h,v 1.9 2012/04/30 21:40:03 jmatthew Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org>
+ * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <stdio.h>
+#include "ber.h"
+
+#define LDAP_URL "ldap://"
+#define LDAP_PORT 389
+#define LDAP_PAGED_OID "1.2.840.113556.1.4.319"
+
+struct aldap {
+#define ALDAP_ERR_SUCCESS 0
+#define ALDAP_ERR_PARSER_ERROR 1
+#define ALDAP_ERR_INVALID_FILTER 2
+#define ALDAP_ERR_OPERATION_FAILED 3
+ u_int8_t err;
+ int msgid;
+ struct ber ber;
+};
+
+struct aldap_page_control {
+ int size;
+ char *cookie;
+ unsigned int cookie_len;
+};
+
+struct aldap_message {
+ int msgid;
+ int message_type;
+
+ struct ber_element *msg;
+
+ struct ber_element *header;
+ struct ber_element *protocol_op;
+
+ struct ber_element *dn;
+
+ union {
+ struct {
+ long long rescode;
+ struct ber_element *diagmsg;
+ } res;
+ struct {
+ struct ber_element *iter;
+ struct ber_element *attrs;
+ } search;
+ } body;
+ struct ber_element *references;
+ struct aldap_page_control *page;
+};
+
+enum aldap_protocol {
+ LDAP,
+ LDAPS
+};
+
+struct aldap_url {
+ int protocol;
+ char *host;
+ in_port_t port;
+ char *dn;
+#define MAXATTR 1024
+ char *attributes[MAXATTR];
+ int scope;
+ char *filter;
+ char *buffer;
+};
+
+enum protocol_op {
+ LDAP_REQ_BIND = 0,
+ LDAP_RES_BIND = 1,
+ LDAP_REQ_UNBIND_30 = 2,
+ LDAP_REQ_SEARCH = 3,
+ LDAP_RES_SEARCH_ENTRY = 4,
+ LDAP_RES_SEARCH_RESULT = 5,
+ LDAP_REQ_MODIFY = 6,
+ LDAP_RES_MODIFY = 7,
+ LDAP_REQ_ADD = 8,
+ LDAP_RES_ADD = 9,
+ LDAP_REQ_DELETE_30 = 10,
+ LDAP_RES_DELETE = 11,
+ LDAP_REQ_MODRDN = 12,
+ LDAP_RES_MODRDN = 13,
+ LDAP_REQ_COMPARE = 14,
+ LDAP_RES_COMPARE = 15,
+ LDAP_REQ_ABANDON_30 = 16,
+
+ LDAP_RES_SEARCH_REFERENCE = 19,
+};
+
+enum deref_aliases {
+ LDAP_DEREF_NEVER = 0,
+ LDAP_DEREF_SEARCHING = 1,
+ LDAP_DEREF_FINDING = 2,
+ LDAP_DEREF_ALWAYS = 3,
+};
+
+enum authentication_choice {
+ LDAP_AUTH_SIMPLE = 0,
+};
+
+enum scope {
+ LDAP_SCOPE_BASE = 0,
+ LDAP_SCOPE_ONELEVEL = 1,
+ LDAP_SCOPE_SUBTREE = 2,
+};
+
+enum result_code {
+ LDAP_SUCCESS = 0,
+ LDAP_OPERATIONS_ERROR = 1,
+ LDAP_PROTOCOL_ERROR = 2,
+ LDAP_TIMELIMIT_EXCEEDED = 3,
+ LDAP_SIZELIMIT_EXCEEDED = 4,
+ LDAP_COMPARE_FALSE = 5,
+ LDAP_COMPARE_TRUE = 6,
+ LDAP_STRONG_AUTH_NOT_SUPPORTED = 7,
+ LDAP_STRONG_AUTH_REQUIRED = 8,
+
+ LDAP_REFERRAL = 10,
+ LDAP_ADMINLIMIT_EXCEEDED = 11,
+ LDAP_UNAVAILABLE_CRITICAL_EXTENSION = 12,
+ LDAP_CONFIDENTIALITY_REQUIRED = 13,
+ LDAP_SASL_BIND_IN_PROGRESS = 14,
+ LDAP_NO_SUCH_ATTRIBUTE = 16,
+ LDAP_UNDEFINED_TYPE = 17,
+ LDAP_INAPPROPRIATE_MATCHING = 18,
+ LDAP_CONSTRAINT_VIOLATION = 19,
+ LDAP_TYPE_OR_VALUE_EXISTS = 20,
+ LDAP_INVALID_SYNTAX = 21,
+
+ LDAP_NO_SUCH_OBJECT = 32,
+ LDAP_ALIAS_PROBLEM = 33,
+ LDAP_INVALID_DN_SYNTAX = 34,
+
+ LDAP_ALIAS_DEREF_PROBLEM = 36,
+
+ LDAP_INAPPROPRIATE_AUTH = 48,
+ LDAP_INVALID_CREDENTIALS = 49,
+ LDAP_INSUFFICIENT_ACCESS = 50,
+ LDAP_BUSY = 51,
+ LDAP_UNAVAILABLE = 52,
+ LDAP_UNWILLING_TO_PERFORM = 53,
+ LDAP_LOOP_DETECT = 54,
+
+ LDAP_NAMING_VIOLATION = 64,
+ LDAP_OBJECT_CLASS_VIOLATION = 65,
+ LDAP_NOT_ALLOWED_ON_NONLEAF = 66,
+ LDAP_NOT_ALLOWED_ON_RDN = 67,
+ LDAP_ALREADY_EXISTS = 68,
+ LDAP_NO_OBJECT_CLASS_MODS = 69,
+
+ LDAP_AFFECTS_MULTIPLE_DSAS = 71,
+
+ LDAP_OTHER = 80,
+};
+
+enum filter {
+ LDAP_FILT_AND = 0,
+ LDAP_FILT_OR = 1,
+ LDAP_FILT_NOT = 2,
+ LDAP_FILT_EQ = 3,
+ LDAP_FILT_SUBS = 4,
+ LDAP_FILT_GE = 5,
+ LDAP_FILT_LE = 6,
+ LDAP_FILT_PRES = 7,
+ LDAP_FILT_APPR = 8,
+};
+
+enum subfilter {
+ LDAP_FILT_SUBS_INIT = 0,
+ LDAP_FILT_SUBS_ANY = 1,
+ LDAP_FILT_SUBS_FIN = 2,
+};
+
+struct aldap *aldap_init(int fd);
+int aldap_close(struct aldap *);
+struct aldap_message *aldap_parse(struct aldap *);
+void aldap_freemsg(struct aldap_message *);
+
+int aldap_bind(struct aldap *, char *, char *);
+int aldap_unbind(struct aldap *);
+int aldap_search(struct aldap *, char *, enum scope, char *, char **, int, int, int, struct aldap_page_control *);
+int aldap_get_errno(struct aldap *, const char **);
+
+int aldap_get_resultcode(struct aldap_message *);
+char *aldap_get_dn(struct aldap_message *);
+char *aldap_get_diagmsg(struct aldap_message *);
+char **aldap_get_references(struct aldap_message *);
+void aldap_free_references(char **values);
+#if 0
+int aldap_parse_url(char *, struct aldap_url *);
+void aldap_free_url(struct aldap_url *);
+int aldap_search_url(struct aldap *, char *, int, int, int);
+#endif
+
+int aldap_count_attrs(struct aldap_message *);
+int aldap_match_attr(struct aldap_message *, char *, char ***);
+int aldap_first_attr(struct aldap_message *, char **, char ***);
+int aldap_next_attr(struct aldap_message *, char **, char ***);
+int aldap_free_attr(char **);
+
+struct aldap_page_control *aldap_parse_page_control(struct ber_element *, size_t len);
+void aldap_freepage(struct aldap_page_control *);
diff --git a/usr.sbin/ypldap/ber.c b/usr.sbin/ypldap/ber.c
new file mode 100644
index 0000000..a2950dc
--- /dev/null
+++ b/usr.sbin/ypldap/ber.c
@@ -0,0 +1,1270 @@
+/* $OpenBSD: ber.c,v 1.9 2015/02/12 00:30:38 pelikan Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
+ * Copyright (c) 2006, 2007 Claudio Jeker <claudio@openbsd.org>
+ * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <sys/types.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <err.h> /* XXX for debug output */
+#include <stdio.h> /* XXX for debug output */
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "ber.h"
+
+#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
+
+#define BER_TYPE_CONSTRUCTED 0x20 /* otherwise primitive */
+#define BER_TYPE_SINGLE_MAX 30
+#define BER_TAG_MASK 0x1f
+#define BER_TAG_MORE 0x80 /* more subsequent octets */
+#define BER_TAG_TYPE_MASK 0x7f
+#define BER_CLASS_SHIFT 6
+
+static int ber_dump_element(struct ber *ber, struct ber_element *root);
+static void ber_dump_header(struct ber *ber, struct ber_element *root);
+static void ber_putc(struct ber *ber, u_char c);
+static void ber_write(struct ber *ber, void *buf, size_t len);
+static ssize_t get_id(struct ber *b, unsigned long *tag, int *class,
+ int *cstruct);
+static ssize_t get_len(struct ber *b, ssize_t *len);
+static ssize_t ber_read_element(struct ber *ber, struct ber_element *elm);
+static ssize_t ber_readbuf(struct ber *b, void *buf, size_t nbytes);
+static ssize_t ber_getc(struct ber *b, u_char *c);
+static ssize_t ber_read(struct ber *ber, void *buf, size_t len);
+
+#ifdef DEBUG
+#define DPRINTF(...) printf(__VA_ARGS__)
+#else
+#define DPRINTF(...) do { } while (0)
+#endif
+
+struct ber_element *
+ber_get_element(unsigned long encoding)
+{
+ struct ber_element *elm;
+
+ if ((elm = calloc(1, sizeof(*elm))) == NULL)
+ return NULL;
+
+ elm->be_encoding = encoding;
+ ber_set_header(elm, BER_CLASS_UNIVERSAL, BER_TYPE_DEFAULT);
+
+ return elm;
+}
+
+void
+ber_set_header(struct ber_element *elm, int class, unsigned long type)
+{
+ elm->be_class = class & BER_CLASS_MASK;
+ if (type == BER_TYPE_DEFAULT)
+ type = elm->be_encoding;
+ elm->be_type = type;
+}
+
+void
+ber_link_elements(struct ber_element *prev, struct ber_element *elm)
+{
+ if (prev != NULL) {
+ if ((prev->be_encoding == BER_TYPE_SEQUENCE ||
+ prev->be_encoding == BER_TYPE_SET) &&
+ prev->be_sub == NULL)
+ prev->be_sub = elm;
+ else
+ prev->be_next = elm;
+ }
+}
+
+struct ber_element *
+ber_unlink_elements(struct ber_element *prev)
+{
+ struct ber_element *elm;
+
+ if ((prev->be_encoding == BER_TYPE_SEQUENCE ||
+ prev->be_encoding == BER_TYPE_SET) &&
+ prev->be_sub != NULL) {
+ elm = prev->be_sub;
+ prev->be_sub = NULL;
+ } else {
+ elm = prev->be_next;
+ prev->be_next = NULL;
+ }
+
+ return (elm);
+}
+
+void
+ber_replace_elements(struct ber_element *prev, struct ber_element *new)
+{
+ struct ber_element *ber, *next;
+
+ ber = ber_unlink_elements(prev);
+ next = ber_unlink_elements(ber);
+ ber_link_elements(new, next);
+ ber_link_elements(prev, new);
+
+ /* cleanup old element */
+ ber_free_elements(ber);
+}
+
+struct ber_element *
+ber_add_sequence(struct ber_element *prev)
+{
+ struct ber_element *elm;
+
+ if ((elm = ber_get_element(BER_TYPE_SEQUENCE)) == NULL)
+ return NULL;
+
+ ber_link_elements(prev, elm);
+
+ return elm;
+}
+
+struct ber_element *
+ber_add_set(struct ber_element *prev)
+{
+ struct ber_element *elm;
+
+ if ((elm = ber_get_element(BER_TYPE_SET)) == NULL)
+ return NULL;
+
+ ber_link_elements(prev, elm);
+
+ return elm;
+}
+
+struct ber_element *
+ber_add_enumerated(struct ber_element *prev, long long val)
+{
+ struct ber_element *elm;
+ u_int i, len = 0;
+ u_char cur, last = 0;
+
+ if ((elm = ber_get_element(BER_TYPE_ENUMERATED)) == NULL)
+ return NULL;
+
+ elm->be_numeric = val;
+
+ for (i = 0; i < sizeof(long long); i++) {
+ cur = val & 0xff;
+ if (cur != 0 && cur != 0xff)
+ len = i;
+ if ((cur == 0 && last & 0x80) ||
+ (cur == 0xff && (last & 0x80) == 0))
+ len = i;
+ val >>= 8;
+ last = cur;
+ }
+ elm->be_len = len + 1;
+
+ ber_link_elements(prev, elm);
+
+ return elm;
+}
+
+struct ber_element *
+ber_add_integer(struct ber_element *prev, long long val)
+{
+ struct ber_element *elm;
+ u_int i, len = 0;
+ u_char cur, last = 0;
+
+ if ((elm = ber_get_element(BER_TYPE_INTEGER)) == NULL)
+ return NULL;
+
+ elm->be_numeric = val;
+
+ for (i = 0; i < sizeof(long long); i++) {
+ cur = val & 0xff;
+ if (cur != 0 && cur != 0xff)
+ len = i;
+ if ((cur == 0 && last & 0x80) ||
+ (cur == 0xff && (last & 0x80) == 0))
+ len = i;
+ val >>= 8;
+ last = cur;
+ }
+ elm->be_len = len + 1;
+
+ ber_link_elements(prev, elm);
+
+ return elm;
+}
+
+int
+ber_get_integer(struct ber_element *elm, long long *n)
+{
+ if (elm->be_encoding != BER_TYPE_INTEGER)
+ return -1;
+
+ *n = elm->be_numeric;
+ return 0;
+}
+
+int
+ber_get_enumerated(struct ber_element *elm, long long *n)
+{
+ if (elm->be_encoding != BER_TYPE_ENUMERATED)
+ return -1;
+
+ *n = elm->be_numeric;
+ return 0;
+}
+
+
+struct ber_element *
+ber_add_boolean(struct ber_element *prev, int bool)
+{
+ struct ber_element *elm;
+
+ if ((elm = ber_get_element(BER_TYPE_BOOLEAN)) == NULL)
+ return NULL;
+
+ elm->be_numeric = bool ? 0xff : 0;
+ elm->be_len = 1;
+
+ ber_link_elements(prev, elm);
+
+ return elm;
+}
+
+int
+ber_get_boolean(struct ber_element *elm, int *b)
+{
+ if (elm->be_encoding != BER_TYPE_BOOLEAN)
+ return -1;
+
+ *b = !(elm->be_numeric == 0);
+ return 0;
+}
+
+struct ber_element *
+ber_add_string(struct ber_element *prev, const char *string)
+{
+ return ber_add_nstring(prev, string, strlen(string));
+}
+
+struct ber_element *
+ber_add_nstring(struct ber_element *prev, const char *string0, size_t len)
+{
+ struct ber_element *elm;
+ char *string;
+
+ if ((string = calloc(1, len)) == NULL)
+ return NULL;
+ if ((elm = ber_get_element(BER_TYPE_OCTETSTRING)) == NULL) {
+ free(string);
+ return NULL;
+ }
+
+ bcopy(string0, string, len);
+ elm->be_val = string;
+ elm->be_len = len;
+ elm->be_free = 1; /* free string on cleanup */
+
+ ber_link_elements(prev, elm);
+
+ return elm;
+}
+
+int
+ber_get_string(struct ber_element *elm, char **s)
+{
+ if (elm->be_encoding != BER_TYPE_OCTETSTRING)
+ return -1;
+
+ *s = elm->be_val;
+ return 0;
+}
+
+int
+ber_get_nstring(struct ber_element *elm, void **p, size_t *len)
+{
+ if (elm->be_encoding != BER_TYPE_OCTETSTRING)
+ return -1;
+
+ *p = elm->be_val;
+ *len = elm->be_len;
+ return 0;
+}
+
+struct ber_element *
+ber_add_bitstring(struct ber_element *prev, const void *v0, size_t len)
+{
+ struct ber_element *elm;
+ void *v;
+
+ if ((v = calloc(1, len)) == NULL)
+ return NULL;
+ if ((elm = ber_get_element(BER_TYPE_BITSTRING)) == NULL) {
+ free(v);
+ return NULL;
+ }
+
+ bcopy(v0, v, len);
+ elm->be_val = v;
+ elm->be_len = len;
+ elm->be_free = 1; /* free string on cleanup */
+
+ ber_link_elements(prev, elm);
+
+ return elm;
+}
+
+int
+ber_get_bitstring(struct ber_element *elm, void **v, size_t *len)
+{
+ if (elm->be_encoding != BER_TYPE_BITSTRING)
+ return -1;
+
+ *v = elm->be_val;
+ *len = elm->be_len;
+ return 0;
+}
+
+struct ber_element *
+ber_add_null(struct ber_element *prev)
+{
+ struct ber_element *elm;
+
+ if ((elm = ber_get_element(BER_TYPE_NULL)) == NULL)
+ return NULL;
+
+ ber_link_elements(prev, elm);
+
+ return elm;
+}
+
+int
+ber_get_null(struct ber_element *elm)
+{
+ if (elm->be_encoding != BER_TYPE_NULL)
+ return -1;
+
+ return 0;
+}
+
+struct ber_element *
+ber_add_eoc(struct ber_element *prev)
+{
+ struct ber_element *elm;
+
+ if ((elm = ber_get_element(BER_TYPE_EOC)) == NULL)
+ return NULL;
+
+ ber_link_elements(prev, elm);
+
+ return elm;
+}
+
+int
+ber_get_eoc(struct ber_element *elm)
+{
+ if (elm->be_encoding != BER_TYPE_EOC)
+ return -1;
+
+ return 0;
+}
+
+size_t
+ber_oid2ber(struct ber_oid *o, u_int8_t *buf, size_t len)
+{
+ u_int32_t v;
+ u_int i, j = 0, k;
+
+ if (o->bo_n < BER_MIN_OID_LEN || o->bo_n > BER_MAX_OID_LEN ||
+ o->bo_id[0] > 2 || o->bo_id[1] > 40)
+ return (0);
+
+ v = (o->bo_id[0] * 40) + o->bo_id[1];
+ for (i = 2, j = 0; i <= o->bo_n; v = o->bo_id[i], i++) {
+ for (k = 28; k >= 7; k -= 7) {
+ if (v >= (u_int)(1 << k)) {
+ if (len)
+ buf[j] = v >> k | BER_TAG_MORE;
+ j++;
+ }
+ }
+ if (len)
+ buf[j] = v & BER_TAG_TYPE_MASK;
+ j++;
+ }
+
+ return (j);
+}
+
+int
+ber_string2oid(const char *oidstr, struct ber_oid *o)
+{
+ char *sp, *p, str[BUFSIZ];
+ const char *errstr;
+
+ if (strlcpy(str, oidstr, sizeof(str)) >= sizeof(str))
+ return (-1);
+ bzero(o, sizeof(*o));
+
+ /* Parse OID strings in the common forms n.n.n, n_n_n_n, or n-n-n */
+ for (p = sp = str; p != NULL; sp = p) {
+ if ((p = strpbrk(p, "._-")) != NULL)
+ *p++ = '\0';
+ o->bo_id[o->bo_n++] = strtonum(sp, 0, UINT_MAX, &errstr);
+ if (errstr || o->bo_n > BER_MAX_OID_LEN)
+ return (-1);
+ }
+
+ return (0);
+}
+
+struct ber_element *
+ber_add_oid(struct ber_element *prev, struct ber_oid *o)
+{
+ struct ber_element *elm;
+ u_int8_t *buf;
+ size_t len;
+
+ if ((elm = ber_get_element(BER_TYPE_OBJECT)) == NULL)
+ return (NULL);
+
+ if ((len = ber_oid2ber(o, NULL, 0)) == 0)
+ goto fail;
+
+ if ((buf = calloc(1, len)) == NULL)
+ goto fail;
+
+ elm->be_val = buf;
+ elm->be_len = len;
+ elm->be_free = 1;
+
+ if (ber_oid2ber(o, buf, len) != len)
+ goto fail;
+
+ ber_link_elements(prev, elm);
+
+ return (elm);
+
+ fail:
+ ber_free_elements(elm);
+ return (NULL);
+}
+
+struct ber_element *
+ber_add_noid(struct ber_element *prev, struct ber_oid *o, int n)
+{
+ struct ber_oid no;
+
+ if (n > BER_MAX_OID_LEN)
+ return (NULL);
+ no.bo_n = n;
+ bcopy(&o->bo_id, &no.bo_id, sizeof(no.bo_id));
+
+ return (ber_add_oid(prev, &no));
+}
+
+struct ber_element *
+ber_add_oidstring(struct ber_element *prev, const char *oidstr)
+{
+ struct ber_oid o;
+
+ if (ber_string2oid(oidstr, &o) == -1)
+ return (NULL);
+
+ return (ber_add_oid(prev, &o));
+}
+
+int
+ber_get_oid(struct ber_element *elm, struct ber_oid *o)
+{
+ u_int8_t *buf;
+ size_t len, i = 0, j = 0;
+
+ if (elm->be_encoding != BER_TYPE_OBJECT)
+ return (-1);
+
+ buf = elm->be_val;
+ len = elm->be_len;
+
+ if (!buf[i])
+ return (-1);
+
+ bzero(o, sizeof(*o));
+ o->bo_id[j++] = buf[i] / 40;
+ o->bo_id[j++] = buf[i++] % 40;
+ for (; i < len && j < BER_MAX_OID_LEN; i++) {
+ o->bo_id[j] = (o->bo_id[j] << 7) + (buf[i] & ~0x80);
+ if (buf[i] & 0x80)
+ continue;
+ j++;
+ }
+ o->bo_n = j;
+
+ return (0);
+}
+
+struct ber_element *
+ber_printf_elements(struct ber_element *ber, char *fmt, ...)
+{
+ va_list ap;
+ int d, class;
+ size_t len;
+ unsigned long type;
+ long long i;
+ char *s;
+ void *p;
+ struct ber_oid *o;
+ struct ber_element *sub = ber, *e;
+
+ va_start(ap, fmt);
+ while (*fmt) {
+ switch (*fmt++) {
+ case 'B':
+ p = va_arg(ap, void *);
+ len = va_arg(ap, size_t);
+ if ((ber = ber_add_bitstring(ber, p, len)) == NULL)
+ goto fail;
+ break;
+ case 'b':
+ d = va_arg(ap, int);
+ if ((ber = ber_add_boolean(ber, d)) == NULL)
+ goto fail;
+ break;
+ case 'd':
+ d = va_arg(ap, int);
+ if ((ber = ber_add_integer(ber, d)) == NULL)
+ goto fail;
+ break;
+ case 'e':
+ e = va_arg(ap, struct ber_element *);
+ ber_link_elements(ber, e);
+ break;
+ case 'E':
+ i = va_arg(ap, long long);
+ if ((ber = ber_add_enumerated(ber, i)) == NULL)
+ goto fail;
+ break;
+ case 'i':
+ i = va_arg(ap, long long);
+ if ((ber = ber_add_integer(ber, i)) == NULL)
+ goto fail;
+ break;
+ case 'O':
+ o = va_arg(ap, struct ber_oid *);
+ if ((ber = ber_add_oid(ber, o)) == NULL)
+ goto fail;
+ break;
+ case 'o':
+ s = va_arg(ap, char *);
+ if ((ber = ber_add_oidstring(ber, s)) == NULL)
+ goto fail;
+ break;
+ case 's':
+ s = va_arg(ap, char *);
+ if ((ber = ber_add_string(ber, s)) == NULL)
+ goto fail;
+ break;
+ case 't':
+ class = va_arg(ap, int);
+ type = va_arg(ap, unsigned long);
+ ber_set_header(ber, class, type);
+ break;
+ case 'x':
+ s = va_arg(ap, char *);
+ len = va_arg(ap, size_t);
+ if ((ber = ber_add_nstring(ber, s, len)) == NULL)
+ goto fail;
+ break;
+ case '0':
+ if ((ber = ber_add_null(ber)) == NULL)
+ goto fail;
+ break;
+ case '{':
+ if ((ber = sub = ber_add_sequence(ber)) == NULL)
+ goto fail;
+ break;
+ case '(':
+ if ((ber = sub = ber_add_set(ber)) == NULL)
+ goto fail;
+ break;
+ case '}':
+ case ')':
+ ber = sub;
+ break;
+ case '.':
+ if ((e = ber_add_eoc(ber)) == NULL)
+ goto fail;
+ ber = e;
+ break;
+ default:
+ break;
+ }
+ }
+ va_end(ap);
+
+ return (ber);
+ fail:
+ ber_free_elements(ber);
+ return (NULL);
+}
+
+int
+ber_scanf_elements(struct ber_element *ber, char *fmt, ...)
+{
+#define _MAX_SEQ 128
+ va_list ap;
+ int *d, level = -1;
+ unsigned long *t;
+ long long *i;
+ void **ptr;
+ size_t *len, ret = 0, n = strlen(fmt);
+ char **s;
+ struct ber_oid *o;
+ struct ber_element *parent[_MAX_SEQ], **e;
+
+ bzero(parent, sizeof(struct ber_element *) * _MAX_SEQ);
+
+ va_start(ap, fmt);
+ while (*fmt) {
+ switch (*fmt++) {
+ case 'B':
+ ptr = va_arg(ap, void **);
+ len = va_arg(ap, size_t *);
+ if (ber_get_bitstring(ber, ptr, len) == -1)
+ goto fail;
+ ret++;
+ break;
+ case 'b':
+ d = va_arg(ap, int *);
+ if (ber_get_boolean(ber, d) == -1)
+ goto fail;
+ ret++;
+ break;
+ case 'e':
+ e = va_arg(ap, struct ber_element **);
+ *e = ber;
+ ret++;
+ continue;
+ case 'E':
+ i = va_arg(ap, long long *);
+ if (ber_get_enumerated(ber, i) == -1)
+ goto fail;
+ ret++;
+ break;
+ case 'i':
+ i = va_arg(ap, long long *);
+ if (ber_get_integer(ber, i) == -1)
+ goto fail;
+ ret++;
+ break;
+ case 'o':
+ o = va_arg(ap, struct ber_oid *);
+ if (ber_get_oid(ber, o) == -1)
+ goto fail;
+ ret++;
+ break;
+ case 'S':
+ ret++;
+ break;
+ case 's':
+ s = va_arg(ap, char **);
+ if (ber_get_string(ber, s) == -1)
+ goto fail;
+ ret++;
+ break;
+ case 't':
+ d = va_arg(ap, int *);
+ t = va_arg(ap, unsigned long *);
+ *d = ber->be_class;
+ *t = ber->be_type;
+ ret++;
+ continue;
+ case 'x':
+ ptr = va_arg(ap, void **);
+ len = va_arg(ap, size_t *);
+ if (ber_get_nstring(ber, ptr, len) == -1)
+ goto fail;
+ ret++;
+ break;
+ case '0':
+ if (ber->be_encoding != BER_TYPE_NULL)
+ goto fail;
+ ret++;
+ break;
+ case '.':
+ if (ber->be_encoding != BER_TYPE_EOC)
+ goto fail;
+ ret++;
+ break;
+ case '{':
+ case '(':
+ if (ber->be_encoding != BER_TYPE_SEQUENCE &&
+ ber->be_encoding != BER_TYPE_SET)
+ goto fail;
+ if (ber->be_sub == NULL || level >= _MAX_SEQ-1)
+ goto fail;
+ parent[++level] = ber;
+ ber = ber->be_sub;
+ ret++;
+ continue;
+ case '}':
+ case ')':
+ if (parent[level] == NULL)
+ goto fail;
+ ber = parent[level--];
+ ret++;
+ continue;
+ default:
+ goto fail;
+ }
+
+ if (ber->be_next == NULL)
+ continue;
+ ber = ber->be_next;
+ }
+ va_end(ap);
+ return (ret == n ? 0 : -1);
+
+ fail:
+ va_end(ap);
+ return (-1);
+
+}
+
+/*
+ * write ber elements to the socket
+ *
+ * params:
+ * ber holds the socket
+ * root fully populated element tree
+ *
+ * returns:
+ * >=0 number of bytes written
+ * -1 on failure and sets errno
+ */
+int
+ber_write_elements(struct ber *ber, struct ber_element *root)
+{
+ size_t len;
+
+ /* calculate length because only the definite form is required */
+ len = ber_calc_len(root);
+ DPRINTF("write ber element of %zd bytes length\n", len);
+
+ if (ber->br_wbuf != NULL && ber->br_wbuf + len > ber->br_wend) {
+ free(ber->br_wbuf);
+ ber->br_wbuf = NULL;
+ }
+ if (ber->br_wbuf == NULL) {
+ if ((ber->br_wbuf = malloc(len)) == NULL)
+ return -1;
+ ber->br_wend = ber->br_wbuf + len;
+ }
+
+ /* reset write pointer */
+ ber->br_wptr = ber->br_wbuf;
+
+ if (ber_dump_element(ber, root) == -1)
+ return -1;
+
+ /* XXX this should be moved to a different function */
+ if (ber->fd != -1)
+ return write(ber->fd, ber->br_wbuf, len);
+
+ return (len);
+}
+
+/*
+ * read ber elements from the socket
+ *
+ * params:
+ * ber holds the socket and lot more
+ * root if NULL, build up an element tree from what we receive on
+ * the wire. If not null, use the specified encoding for the
+ * elements received.
+ *
+ * returns:
+ * !=NULL, elements read and store in the ber_element tree
+ * NULL, type mismatch or read error
+ */
+struct ber_element *
+ber_read_elements(struct ber *ber, struct ber_element *elm)
+{
+ struct ber_element *root = elm;
+
+ if (root == NULL) {
+ if ((root = ber_get_element(0)) == NULL)
+ return NULL;
+ }
+
+ DPRINTF("read ber elements, root %p\n", root);
+
+ if (ber_read_element(ber, root) == -1) {
+ /* Cleanup if root was allocated by us */
+ if (elm == NULL)
+ ber_free_elements(root);
+ return NULL;
+ }
+
+ return root;
+}
+
+void
+ber_free_elements(struct ber_element *root)
+{
+ if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
+ root->be_encoding == BER_TYPE_SET))
+ ber_free_elements(root->be_sub);
+ if (root->be_next)
+ ber_free_elements(root->be_next);
+ if (root->be_free && (root->be_encoding == BER_TYPE_OCTETSTRING ||
+ root->be_encoding == BER_TYPE_BITSTRING ||
+ root->be_encoding == BER_TYPE_OBJECT))
+ free(root->be_val);
+ free(root);
+}
+
+size_t
+ber_calc_len(struct ber_element *root)
+{
+ unsigned long t;
+ size_t s;
+ size_t size = 2; /* minimum 1 byte head and 1 byte size */
+
+ /* calculate the real length of a sequence or set */
+ if (root->be_sub && (root->be_encoding == BER_TYPE_SEQUENCE ||
+ root->be_encoding == BER_TYPE_SET))
+ root->be_len = ber_calc_len(root->be_sub);
+
+ /* fix header length for extended types */
+ if (root->be_type > BER_TYPE_SINGLE_MAX)
+ for (t = root->be_type; t > 0; t >>= 7)
+ size++;
+ if (root->be_len >= BER_TAG_MORE)
+ for (s = root->be_len; s > 0; s >>= 8)
+ size++;
+
+ /* calculate the length of the following elements */
+ if (root->be_next)
+ size += ber_calc_len(root->be_next);
+
+ /* This is an empty element, do not use a minimal size */
+ if (root->be_type == BER_TYPE_EOC && root->be_len == 0)
+ return (0);
+
+ return (root->be_len + size);
+}
+
+/*
+ * internal functions
+ */
+
+static int
+ber_dump_element(struct ber *ber, struct ber_element *root)
+{
+ unsigned long long l;
+ int i;
+ uint8_t u;
+
+ ber_dump_header(ber, root);
+
+ switch (root->be_encoding) {
+ case BER_TYPE_BOOLEAN:
+ case BER_TYPE_INTEGER:
+ case BER_TYPE_ENUMERATED:
+ l = (unsigned long long)root->be_numeric;
+ for (i = root->be_len; i > 0; i--) {
+ u = (l >> ((i - 1) * 8)) & 0xff;
+ ber_putc(ber, u);
+ }
+ break;
+ case BER_TYPE_BITSTRING:
+ return -1;
+ case BER_TYPE_OCTETSTRING:
+ case BER_TYPE_OBJECT:
+ ber_write(ber, root->be_val, root->be_len);
+ break;
+ case BER_TYPE_NULL: /* no payload */
+ case BER_TYPE_EOC:
+ break;
+ case BER_TYPE_SEQUENCE:
+ case BER_TYPE_SET:
+ if (root->be_sub && ber_dump_element(ber, root->be_sub) == -1)
+ return -1;
+ break;
+ }
+
+ if (root->be_next == NULL)
+ return 0;
+ return ber_dump_element(ber, root->be_next);
+}
+
+static void
+ber_dump_header(struct ber *ber, struct ber_element *root)
+{
+ u_char id = 0, t, buf[8];
+ unsigned long type;
+ size_t size;
+
+ /* class universal, type encoding depending on type value */
+ /* length encoding */
+ if (root->be_type <= BER_TYPE_SINGLE_MAX) {
+ id = root->be_type | (root->be_class << BER_CLASS_SHIFT);
+ if (root->be_encoding == BER_TYPE_SEQUENCE ||
+ root->be_encoding == BER_TYPE_SET)
+ id |= BER_TYPE_CONSTRUCTED;
+
+ ber_putc(ber, id);
+ } else {
+ id = BER_TAG_MASK | (root->be_class << BER_CLASS_SHIFT);
+ if (root->be_encoding == BER_TYPE_SEQUENCE ||
+ root->be_encoding == BER_TYPE_SET)
+ id |= BER_TYPE_CONSTRUCTED;
+
+ ber_putc(ber, id);
+
+ for (t = 0, type = root->be_type; type > 0; type >>= 7)
+ buf[t++] = type & ~BER_TAG_MORE;
+
+ while (t-- > 0) {
+ if (t > 0)
+ buf[t] |= BER_TAG_MORE;
+ ber_putc(ber, buf[t]);
+ }
+ }
+
+ if (root->be_len < BER_TAG_MORE) {
+ /* short form */
+ ber_putc(ber, root->be_len);
+ } else {
+ for (t = 0, size = root->be_len; size > 0; size >>= 8)
+ buf[t++] = size & 0xff;
+
+ ber_putc(ber, t | BER_TAG_MORE);
+
+ while (t > 0)
+ ber_putc(ber, buf[--t]);
+ }
+}
+
+static void
+ber_putc(struct ber *ber, u_char c)
+{
+ if (ber->br_wptr + 1 <= ber->br_wend)
+ *ber->br_wptr = c;
+ ber->br_wptr++;
+}
+
+static void
+ber_write(struct ber *ber, void *buf, size_t len)
+{
+ if (ber->br_wptr + len <= ber->br_wend)
+ bcopy(buf, ber->br_wptr, len);
+ ber->br_wptr += len;
+}
+
+/*
+ * extract a BER encoded tag. There are two types, a short and long form.
+ */
+static ssize_t
+get_id(struct ber *b, unsigned long *tag, int *class, int *cstruct)
+{
+ u_char u;
+ size_t i = 0;
+ unsigned long t = 0;
+
+ if (ber_getc(b, &u) == -1)
+ return -1;
+
+ *class = (u >> BER_CLASS_SHIFT) & BER_CLASS_MASK;
+ *cstruct = (u & BER_TYPE_CONSTRUCTED) == BER_TYPE_CONSTRUCTED;
+
+ if ((u & BER_TAG_MASK) != BER_TAG_MASK) {
+ *tag = u & BER_TAG_MASK;
+ return 1;
+ }
+
+ do {
+ if (ber_getc(b, &u) == -1)
+ return -1;
+ t = (t << 7) | (u & ~BER_TAG_MORE);
+ i++;
+ } while (u & BER_TAG_MORE);
+
+ if (i > sizeof(unsigned long)) {
+ errno = ERANGE;
+ return -1;
+ }
+
+ *tag = t;
+ return i + 1;
+}
+
+/*
+ * extract length of a ber object -- if length is unknown an error is returned.
+ */
+static ssize_t
+get_len(struct ber *b, ssize_t *len)
+{
+ u_char u, n;
+ ssize_t s, r;
+
+ if (ber_getc(b, &u) == -1)
+ return -1;
+ if ((u & BER_TAG_MORE) == 0) {
+ /* short form */
+ *len = u;
+ return 1;
+ }
+
+ n = u & ~BER_TAG_MORE;
+ if (sizeof(ssize_t) < n) {
+ errno = ERANGE;
+ return -1;
+ }
+ r = n + 1;
+
+ for (s = 0; n > 0; n--) {
+ if (ber_getc(b, &u) == -1)
+ return -1;
+ s = (s << 8) | u;
+ }
+
+ if (s < 0) {
+ /* overflow */
+ errno = ERANGE;
+ return -1;
+ }
+
+ if (s == 0) {
+ /* invalid encoding */
+ errno = EINVAL;
+ return -1;
+ }
+
+ *len = s;
+ return r;
+}
+
+static ssize_t
+ber_read_element(struct ber *ber, struct ber_element *elm)
+{
+ long long val = 0;
+ struct ber_element *next;
+ unsigned long type;
+ int i, class, cstruct;
+ ssize_t len, r, totlen = 0;
+ u_char c;
+
+ if ((r = get_id(ber, &type, &class, &cstruct)) == -1)
+ return -1;
+ DPRINTF("ber read got class %d type %lu, %s\n",
+ class, type, cstruct ? "constructive" : "primitive");
+ totlen += r;
+ if ((r = get_len(ber, &len)) == -1)
+ return -1;
+ DPRINTF("ber read element size %zd\n", len);
+ totlen += r + len;
+
+ elm->be_type = type;
+ elm->be_len = len;
+ elm->be_class = class;
+
+ if (elm->be_encoding == 0) {
+ /* try to figure out the encoding via class, type and cstruct */
+ if (cstruct)
+ elm->be_encoding = BER_TYPE_SEQUENCE;
+ else if (class == BER_CLASS_UNIVERSAL)
+ elm->be_encoding = type;
+ else if (ber->br_application != NULL) {
+ /*
+ * Ask the application to map the encoding to a
+ * universal type. For example, a SMI IpAddress
+ * type is defined as 4 byte OCTET STRING.
+ */
+ elm->be_encoding = (*ber->br_application)(elm);
+ } else
+ /* last resort option */
+ elm->be_encoding = BER_TYPE_NULL;
+ }
+
+ switch (elm->be_encoding) {
+ case BER_TYPE_EOC: /* End-Of-Content */
+ break;
+ case BER_TYPE_BOOLEAN:
+ case BER_TYPE_INTEGER:
+ case BER_TYPE_ENUMERATED:
+ if (len > (ssize_t)sizeof(long long))
+ return -1;
+ for (i = 0; i < len; i++) {
+ if (ber_getc(ber, &c) != 1)
+ return -1;
+ val <<= 8;
+ val |= c;
+ }
+
+ /* sign extend if MSB is set */
+ if (val >> ((i - 1) * 8) & 0x80)
+ val |= ULLONG_MAX << (i * 8);
+ elm->be_numeric = val;
+ break;
+ case BER_TYPE_BITSTRING:
+ elm->be_val = malloc(len);
+ if (elm->be_val == NULL)
+ return -1;
+ elm->be_free = 1;
+ elm->be_len = len;
+ ber_read(ber, elm->be_val, len);
+ break;
+ case BER_TYPE_OCTETSTRING:
+ case BER_TYPE_OBJECT:
+ elm->be_val = malloc(len + 1);
+ if (elm->be_val == NULL)
+ return -1;
+ elm->be_free = 1;
+ elm->be_len = len;
+ ber_read(ber, elm->be_val, len);
+ ((u_char *)elm->be_val)[len] = '\0';
+ break;
+ case BER_TYPE_NULL: /* no payload */
+ if (len != 0)
+ return -1;
+ break;
+ case BER_TYPE_SEQUENCE:
+ case BER_TYPE_SET:
+ if (elm->be_sub == NULL) {
+ if ((elm->be_sub = ber_get_element(0)) == NULL)
+ return -1;
+ }
+ next = elm->be_sub;
+ while (len > 0) {
+ r = ber_read_element(ber, next);
+ if (r == -1)
+ return -1;
+ len -= r;
+ if (len > 0 && next->be_next == NULL) {
+ if ((next->be_next = ber_get_element(0)) ==
+ NULL)
+ return -1;
+ }
+ next = next->be_next;
+ }
+ break;
+ }
+ return totlen;
+}
+
+static ssize_t
+ber_readbuf(struct ber *b, void *buf, size_t nbytes)
+{
+ size_t sz;
+ size_t len;
+
+ if (b->br_rbuf == NULL)
+ return -1;
+
+ sz = b->br_rend - b->br_rptr;
+ len = MINIMUM(nbytes, sz);
+ if (len == 0) {
+ errno = ECANCELED;
+ return (-1); /* end of buffer and parser wants more data */
+ }
+
+ bcopy(b->br_rptr, buf, len);
+ b->br_rptr += len;
+
+ return (len);
+}
+
+void
+ber_set_readbuf(struct ber *b, void *buf, size_t len)
+{
+ b->br_rbuf = b->br_rptr = buf;
+ b->br_rend = (u_int8_t *)buf + len;
+}
+
+ssize_t
+ber_get_writebuf(struct ber *b, void **buf)
+{
+ if (b->br_wbuf == NULL)
+ return -1;
+ *buf = b->br_wbuf;
+ return (b->br_wend - b->br_wbuf);
+}
+
+void
+ber_set_application(struct ber *b, unsigned long (*cb)(struct ber_element *))
+{
+ b->br_application = cb;
+}
+
+void
+ber_free(struct ber *b)
+{
+ if (b->br_wbuf != NULL)
+ free (b->br_wbuf);
+}
+
+static ssize_t
+ber_getc(struct ber *b, u_char *c)
+{
+ ssize_t r;
+ /*
+ * XXX calling read here is wrong in many ways. The most obvious one
+ * being that we will block till data arrives.
+ * But for now it is _good enough_ *gulp*
+ */
+ if (b->fd == -1)
+ r = ber_readbuf(b, c, 1);
+ else
+ r = read(b->fd, c, 1);
+ return r;
+}
+
+static ssize_t
+ber_read(struct ber *ber, void *buf, size_t len)
+{
+ u_char *b = buf;
+ ssize_t r, remain = len;
+
+ /*
+ * XXX calling read here is wrong in many ways. The most obvious one
+ * being that we will block till data arrives.
+ * But for now it is _good enough_ *gulp*
+ */
+
+ while (remain > 0) {
+ if (ber->fd == -1)
+ r = ber_readbuf(ber, b, remain);
+ else
+ r = read(ber->fd, b, remain);
+ if (r == -1) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return -1;
+ }
+ if (r == 0)
+ return (b - (u_char *)buf);
+ b += r;
+ remain -= r;
+ }
+ return (b - (u_char *)buf);
+}
diff --git a/usr.sbin/ypldap/ber.h b/usr.sbin/ypldap/ber.h
new file mode 100644
index 0000000..eec02d4
--- /dev/null
+++ b/usr.sbin/ypldap/ber.h
@@ -0,0 +1,129 @@
+/* $OpenBSD: ber.h,v 1.2 2008/12/29 15:48:13 aschrijver Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
+ * Copyright (c) 2006, 2007 Claudio Jeker <claudio@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
+struct ber_element {
+ struct ber_element *be_next;
+ unsigned long be_type;
+ unsigned long be_encoding;
+ size_t be_len;
+ int be_free;
+ u_int8_t be_class;
+ union {
+ struct ber_element *bv_sub;
+ void *bv_val;
+ long long bv_numeric;
+ } be_union;
+#define be_sub be_union.bv_sub
+#define be_val be_union.bv_val
+#define be_numeric be_union.bv_numeric
+};
+
+struct ber {
+ int fd;
+ u_char *br_wbuf;
+ u_char *br_wptr;
+ u_char *br_wend;
+ u_char *br_rbuf;
+ u_char *br_rptr;
+ u_char *br_rend;
+
+ unsigned long (*br_application)(struct ber_element *);
+};
+
+/* well-known ber_element types */
+#define BER_TYPE_DEFAULT ((unsigned long)-1)
+#define BER_TYPE_EOC 0
+#define BER_TYPE_BOOLEAN 1
+#define BER_TYPE_INTEGER 2
+#define BER_TYPE_BITSTRING 3
+#define BER_TYPE_OCTETSTRING 4
+#define BER_TYPE_NULL 5
+#define BER_TYPE_OBJECT 6
+#define BER_TYPE_ENUMERATED 10
+#define BER_TYPE_SEQUENCE 16
+#define BER_TYPE_SET 17
+
+/* ber classes */
+#define BER_CLASS_UNIVERSAL 0x0
+#define BER_CLASS_UNIV BER_CLASS_UNIVERSAL
+#define BER_CLASS_APPLICATION 0x1
+#define BER_CLASS_APP BER_CLASS_APPLICATION
+#define BER_CLASS_CONTEXT 0x2
+#define BER_CLASS_PRIVATE 0x3
+#define BER_CLASS_MASK 0x3
+
+/* common definitions */
+#define BER_MIN_OID_LEN 2 /* OBJECT */
+#define BER_MAX_OID_LEN 32 /* OBJECT */
+
+struct ber_oid {
+ u_int32_t bo_id[BER_MAX_OID_LEN + 1];
+ size_t bo_n;
+};
+
+__BEGIN_DECLS
+struct ber_element *ber_get_element(unsigned long);
+void ber_set_header(struct ber_element *, int,
+ unsigned long);
+void ber_link_elements(struct ber_element *,
+ struct ber_element *);
+struct ber_element *ber_unlink_elements(struct ber_element *);
+void ber_replace_elements(struct ber_element *,
+ struct ber_element *);
+struct ber_element *ber_add_sequence(struct ber_element *);
+struct ber_element *ber_add_set(struct ber_element *);
+struct ber_element *ber_add_integer(struct ber_element *, long long);
+int ber_get_integer(struct ber_element *, long long *);
+struct ber_element *ber_add_enumerated(struct ber_element *, long long);
+int ber_get_enumerated(struct ber_element *, long long *);
+struct ber_element *ber_add_boolean(struct ber_element *, int);
+int ber_get_boolean(struct ber_element *, int *);
+struct ber_element *ber_add_string(struct ber_element *, const char *);
+struct ber_element *ber_add_nstring(struct ber_element *, const char *,
+ size_t);
+int ber_get_string(struct ber_element *, char **);
+int ber_get_nstring(struct ber_element *, void **,
+ size_t *);
+struct ber_element *ber_add_bitstring(struct ber_element *, const void *,
+ size_t);
+int ber_get_bitstring(struct ber_element *, void **,
+ size_t *);
+struct ber_element *ber_add_null(struct ber_element *);
+int ber_get_null(struct ber_element *);
+struct ber_element *ber_add_eoc(struct ber_element *);
+int ber_get_eoc(struct ber_element *);
+struct ber_element *ber_add_oid(struct ber_element *, struct ber_oid *);
+struct ber_element *ber_add_noid(struct ber_element *, struct ber_oid *, int);
+struct ber_element *ber_add_oidstring(struct ber_element *, const char *);
+int ber_get_oid(struct ber_element *, struct ber_oid *);
+size_t ber_oid2ber(struct ber_oid *, u_int8_t *, size_t);
+int ber_string2oid(const char *, struct ber_oid *);
+struct ber_element *ber_printf_elements(struct ber_element *, char *, ...);
+int ber_scanf_elements(struct ber_element *, char *, ...);
+ssize_t ber_get_writebuf(struct ber *, void **);
+int ber_write_elements(struct ber *, struct ber_element *);
+void ber_set_readbuf(struct ber *, void *, size_t);
+struct ber_element *ber_read_elements(struct ber *, struct ber_element *);
+void ber_free_elements(struct ber_element *);
+size_t ber_calc_len(struct ber_element *);
+void ber_set_application(struct ber *,
+ unsigned long (*)(struct ber_element *));
+void ber_free(struct ber *);
+__END_DECLS
diff --git a/usr.sbin/ypldap/entries.c b/usr.sbin/ypldap/entries.c
new file mode 100644
index 0000000..1adce5a
--- /dev/null
+++ b/usr.sbin/ypldap/entries.c
@@ -0,0 +1,149 @@
+/* $OpenBSD: entries.c,v 1.3 2015/01/16 06:40:22 deraadt Exp $ */
+/* $FreeBSD$ */
+/*
+ * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/tree.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <event.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "ypldap.h"
+
+void
+flatten_entries(struct env *env)
+{
+ size_t wrlen;
+ size_t len;
+ char *linep;
+ char *endp;
+ char *tmp;
+ struct userent *ue;
+ struct groupent *ge;
+
+ log_debug("flattening trees");
+ /*
+ * This takes all the line pointers in RB elements and
+ * concatenates them in a single string, to be able to
+ * implement next element lookup without tree traversal.
+ *
+ * An extra octet is alloced to make space for an additional NUL.
+ */
+ wrlen = env->sc_user_line_len;
+ if ((linep = calloc(1, env->sc_user_line_len + 1)) == NULL) {
+ /*
+ * XXX: try allocating a smaller chunk of memory
+ */
+ fatal("out of memory");
+ }
+ endp = linep;
+
+ RB_FOREACH(ue, user_name_tree, env->sc_user_names) {
+ /*
+ * we convert the first nul back to a column,
+ * copy the string and then convert it back to a nul.
+ */
+ ue->ue_line[strlen(ue->ue_line)] = ':';
+ log_debug("pushing line: %s", ue->ue_line);
+ len = strlen(ue->ue_line) + 1;
+ memcpy(endp, ue->ue_line, len);
+ endp[strcspn(endp, ":")] = '\0';
+ free(ue->ue_line);
+ ue->ue_line = endp;
+ endp += len;
+ wrlen -= len;
+
+ /*
+ * To save memory strdup(3) the netid_line which originally used
+ * LINE_WIDTH bytes
+ */
+ tmp = ue->ue_netid_line;
+ ue->ue_netid_line = strdup(tmp);
+ if (ue->ue_netid_line == NULL) {
+ fatal("out of memory");
+ }
+ free(tmp);
+ }
+ env->sc_user_lines = linep;
+
+ wrlen = env->sc_group_line_len;
+ if ((linep = calloc(1, env->sc_group_line_len + 1)) == NULL) {
+ /*
+ * XXX: try allocating a smaller chunk of memory
+ */
+ fatal("out of memory");
+ }
+ endp = linep;
+ RB_FOREACH(ge, group_name_tree, env->sc_group_names) {
+ /*
+ * we convert the first nul back to a column,
+ * copy the string and then convert it back to a nul.
+ */
+ ge->ge_line[strlen(ge->ge_line)] = ':';
+ log_debug("pushing line: %s", ge->ge_line);
+ len = strlen(ge->ge_line) + 1;
+ memcpy(endp, ge->ge_line, len);
+ endp[strcspn(endp, ":")] = '\0';
+ free(ge->ge_line);
+ ge->ge_line = endp;
+ endp += len;
+ wrlen -= len;
+ }
+ env->sc_group_lines = linep;
+}
+
+int
+userent_name_cmp(struct userent *ue1, struct userent *ue2)
+{
+ return (strcmp(ue1->ue_line, ue2->ue_line));
+}
+
+int
+userent_uid_cmp(struct userent *ue1, struct userent *ue2)
+{
+ return (ue1->ue_uid - ue2->ue_uid);
+}
+
+int
+groupent_name_cmp(struct groupent *ge1, struct groupent *ge2)
+{
+ return (strcmp(ge1->ge_line, ge2->ge_line));
+}
+
+int
+groupent_gid_cmp(struct groupent *ge1, struct groupent *ge2)
+{
+ return (ge1->ge_gid - ge2->ge_gid);
+}
+
+RB_GENERATE(user_name_tree, userent, ue_name_node, userent_name_cmp);
+RB_GENERATE(user_uid_tree, userent, ue_uid_node, userent_uid_cmp);
+RB_GENERATE(group_name_tree, groupent, ge_name_node, groupent_name_cmp);
+RB_GENERATE(group_gid_tree, groupent, ge_gid_node, groupent_gid_cmp);
diff --git a/usr.sbin/ypldap/ldapclient.c b/usr.sbin/ypldap/ldapclient.c
new file mode 100644
index 0000000..897ceb2
--- /dev/null
+++ b/usr.sbin/ypldap/ldapclient.c
@@ -0,0 +1,705 @@
+/* $OpenBSD: ldapclient.c,v 1.31 2014/11/16 23:24:44 tedu Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org>
+ * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/tree.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <netdb.h>
+#include <errno.h>
+#include <err.h>
+#include <event.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "aldap.h"
+#include "ypldap.h"
+
+void client_sig_handler(int, short, void *);
+void client_dispatch_dns(int, short, void *);
+void client_dispatch_parent(int, short, void *);
+void client_shutdown(void);
+void client_connect(int, short, void *);
+void client_configure(struct env *);
+void client_periodic_update(int, short, void *);
+int client_build_req(struct idm *, struct idm_req *, struct aldap_message *,
+ int, int);
+int client_search_idm(struct env *, struct idm *, struct aldap *,
+ char **, char *, int, int, enum imsg_type);
+int client_try_idm(struct env *, struct idm *);
+int client_addr_init(struct idm *);
+int client_addr_free(struct idm *);
+
+struct aldap *client_aldap_open(struct ypldap_addr *);
+
+/*
+ * dummy wrapper to provide aldap_init with its fd's.
+ */
+struct aldap *
+client_aldap_open(struct ypldap_addr *addr)
+{
+ int fd = -1;
+ struct ypldap_addr *p;
+
+ for (p = addr; p != NULL; p = p->next) {
+ char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+ struct sockaddr *sa = (struct sockaddr *)&p->ss;
+
+ if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
+ sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV))
+ errx(1, "could not get numeric hostname");
+
+ if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
+ return NULL;
+
+ if (connect(fd, sa, sa->sa_len) == 0)
+ break;
+
+ warn("connect to %s port %s (%s) failed", hbuf, sbuf, "tcp");
+ close(fd);
+ }
+
+ if (fd == -1)
+ return NULL;
+
+ return aldap_init(fd);
+}
+
+int
+client_addr_init(struct idm *idm)
+{
+ struct sockaddr_in *sa_in;
+ struct sockaddr_in6 *sa_in6;
+ struct ypldap_addr *h;
+
+ for (h = idm->idm_addr; h != NULL; h = h->next) {
+ switch (h->ss.ss_family) {
+ case AF_INET:
+ sa_in = (struct sockaddr_in *)&h->ss;
+ if (ntohs(sa_in->sin_port) == 0)
+ sa_in->sin_port = htons(LDAP_PORT);
+ idm->idm_state = STATE_DNS_DONE;
+ break;
+ case AF_INET6:
+ sa_in6 = (struct sockaddr_in6 *)&h->ss;
+ if (ntohs(sa_in6->sin6_port) == 0)
+ sa_in6->sin6_port = htons(LDAP_PORT);
+ idm->idm_state = STATE_DNS_DONE;
+ break;
+ default:
+ fatalx("king bula sez: wrong AF in client_addr_init");
+ /* not reached */
+ }
+ }
+
+ return (0);
+}
+
+int
+client_addr_free(struct idm *idm)
+{
+ struct ypldap_addr *h, *p;
+
+ if (idm->idm_addr == NULL)
+ return (-1);
+
+ for (h = idm->idm_addr; h != NULL; h = p) {
+ p = h->next;
+ free(h);
+ }
+
+ idm->idm_addr = NULL;
+
+ return (0);
+}
+
+void
+client_sig_handler(int sig, short event, void *p)
+{
+ switch (sig) {
+ case SIGINT:
+ case SIGTERM:
+ client_shutdown();
+ break;
+ default:
+ fatalx("unexpected signal");
+ }
+}
+
+void
+client_dispatch_dns(int fd, short events, void *p)
+{
+ struct imsg imsg;
+ u_int16_t dlen;
+ u_char *data;
+ struct ypldap_addr *h;
+ int n, wait_cnt = 0;
+ struct idm *idm;
+ int shut = 0;
+
+ struct env *env = p;
+ struct imsgev *iev = env->sc_iev_dns;
+ struct imsgbuf *ibuf = &iev->ibuf;
+
+ if ((events & (EV_READ | EV_WRITE)) == 0)
+ fatalx("unknown event");
+
+ if (events & EV_READ) {
+ if ((n = imsg_read(ibuf)) == -1)
+ fatal("imsg_read error");
+ if (n == 0)
+ shut = 1;
+ }
+ if (events & EV_WRITE) {
+ if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
+ fatal("msgbuf_write");
+ if (n == 0)
+ shut = 1;
+ goto done;
+ }
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ fatal("client_dispatch_dns: imsg_get error");
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ case IMSG_HOST_DNS:
+ TAILQ_FOREACH(idm, &env->sc_idms, idm_entry)
+ if (idm->idm_id == imsg.hdr.peerid)
+ break;
+ if (idm == NULL) {
+ log_warnx("IMSG_HOST_DNS with invalid peerID");
+ break;
+ }
+ if (idm->idm_addr != NULL) {
+ log_warnx("IMSG_HOST_DNS but addr != NULL!");
+ break;
+ }
+
+ dlen = imsg.hdr.len - IMSG_HEADER_SIZE;
+ if (dlen == 0) { /* no data -> temp error */
+ idm->idm_state = STATE_DNS_TEMPFAIL;
+ break;
+ }
+
+ data = (u_char *)imsg.data;
+ while (dlen >= sizeof(struct sockaddr_storage)) {
+ if ((h = calloc(1, sizeof(struct ypldap_addr))) ==
+ NULL)
+ fatal(NULL);
+ memcpy(&h->ss, data, sizeof(h->ss));
+
+ if (idm->idm_addr == NULL)
+ h->next = NULL;
+ else
+ h->next = idm->idm_addr;
+
+ idm->idm_addr = h;
+
+ data += sizeof(h->ss);
+ dlen -= sizeof(h->ss);
+ }
+ if (dlen != 0)
+ fatalx("IMSG_HOST_DNS: dlen != 0");
+
+ client_addr_init(idm);
+
+ break;
+ default:
+ break;
+ }
+ imsg_free(&imsg);
+ }
+
+ TAILQ_FOREACH(idm, &env->sc_idms, idm_entry) {
+ if (client_try_idm(env, idm) == -1)
+ idm->idm_state = STATE_LDAP_FAIL;
+
+ if (idm->idm_state < STATE_LDAP_DONE)
+ wait_cnt++;
+ }
+ if (wait_cnt == 0)
+ imsg_compose_event(env->sc_iev, IMSG_END_UPDATE, 0, 0, -1,
+ NULL, 0);
+
+done:
+ if (!shut)
+ imsg_event_add(iev);
+ else {
+ /* this pipe is dead, so remove the event handler */
+ event_del(&iev->ev);
+ event_loopexit(NULL);
+ }
+}
+
+void
+client_dispatch_parent(int fd, short events, void *p)
+{
+ int n;
+ int shut = 0;
+ struct imsg imsg;
+ struct env *env = p;
+ struct imsgev *iev = env->sc_iev;
+ struct imsgbuf *ibuf = &iev->ibuf;
+
+ if ((events & (EV_READ | EV_WRITE)) == 0)
+ fatalx("unknown event");
+
+ if (events & EV_READ) {
+ if ((n = imsg_read(ibuf)) == -1)
+ fatal("imsg_read error");
+ if (n == 0)
+ shut = 1;
+ }
+ if (events & EV_WRITE) {
+ if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
+ fatal("msgbuf_write");
+ if (n == 0)
+ shut = 1;
+ goto done;
+ }
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ fatal("client_dispatch_parent: imsg_get error");
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ case IMSG_CONF_START: {
+ struct env params;
+
+ if (env->sc_flags & F_CONFIGURING) {
+ log_warnx("configuration already in progress");
+ break;
+ }
+ memcpy(&params, imsg.data, sizeof(params));
+ log_debug("configuration starting");
+ env->sc_flags |= F_CONFIGURING;
+ purge_config(env);
+ memcpy(&env->sc_conf_tv, &params.sc_conf_tv,
+ sizeof(env->sc_conf_tv));
+ env->sc_flags |= params.sc_flags;
+ break;
+ }
+ case IMSG_CONF_IDM: {
+ struct idm *idm;
+
+ if (!(env->sc_flags & F_CONFIGURING))
+ break;
+ if ((idm = calloc(1, sizeof(*idm))) == NULL)
+ fatal(NULL);
+ memcpy(idm, imsg.data, sizeof(*idm));
+ idm->idm_env = env;
+ TAILQ_INSERT_TAIL(&env->sc_idms, idm, idm_entry);
+ break;
+ }
+ case IMSG_CONF_END:
+ env->sc_flags &= ~F_CONFIGURING;
+ log_debug("applying configuration");
+ client_configure(env);
+ break;
+ default:
+ log_debug("client_dispatch_parent: unexpect imsg %d",
+ imsg.hdr.type);
+
+ break;
+ }
+ imsg_free(&imsg);
+ }
+
+done:
+ if (!shut)
+ imsg_event_add(iev);
+ else {
+ /* this pipe is dead, so remove the event handler */
+ event_del(&iev->ev);
+ event_loopexit(NULL);
+ }
+}
+
+void
+client_shutdown(void)
+{
+ log_info("ldap client exiting");
+ _exit(0);
+}
+
+pid_t
+ldapclient(int pipe_main2client[2])
+{
+ pid_t pid, dns_pid;
+ int pipe_dns[2];
+ struct passwd *pw;
+ struct event ev_sigint;
+ struct event ev_sigterm;
+ struct env env;
+
+ switch (pid = fork()) {
+ case -1:
+ fatal("cannot fork");
+ break;
+ case 0:
+ break;
+ default:
+ return (pid);
+ }
+
+ bzero(&env, sizeof(env));
+ TAILQ_INIT(&env.sc_idms);
+
+ if ((pw = getpwnam(YPLDAP_USER)) == NULL)
+ fatal("getpwnam");
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_dns) == -1)
+ fatal("socketpair");
+ dns_pid = ypldap_dns(pipe_dns, pw);
+ close(pipe_dns[1]);
+
+#ifndef DEBUG
+ if (chroot(pw->pw_dir) == -1)
+ fatal("chroot");
+ if (chdir("/") == -1)
+ fatal("chdir");
+#else
+#warning disabling chrooting in DEBUG mode
+#endif
+ setproctitle("ldap client");
+ ypldap_process = PROC_CLIENT;
+
+#ifndef DEBUG
+ if (setgroups(1, &pw->pw_gid) ||
+ setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
+ setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
+ fatal("cannot drop privileges");
+#else
+#warning disabling privilege revocation in DEBUG mode
+#endif
+
+ event_init();
+ signal(SIGPIPE, SIG_IGN);
+ signal_set(&ev_sigint, SIGINT, client_sig_handler, NULL);
+ signal_set(&ev_sigterm, SIGTERM, client_sig_handler, NULL);
+ signal_add(&ev_sigint, NULL);
+ signal_add(&ev_sigterm, NULL);
+
+ close(pipe_main2client[0]);
+ if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL)
+ fatal(NULL);
+ if ((env.sc_iev_dns = calloc(1, sizeof(*env.sc_iev_dns))) == NULL)
+ fatal(NULL);
+
+ env.sc_iev->events = EV_READ;
+ env.sc_iev->data = &env;
+ imsg_init(&env.sc_iev->ibuf, pipe_main2client[1]);
+ env.sc_iev->handler = client_dispatch_parent;
+ event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events,
+ env.sc_iev->handler, &env);
+ event_add(&env.sc_iev->ev, NULL);
+
+ env.sc_iev_dns->events = EV_READ;
+ env.sc_iev_dns->data = &env;
+ imsg_init(&env.sc_iev_dns->ibuf, pipe_dns[0]);
+ env.sc_iev_dns->handler = client_dispatch_dns;
+ event_set(&env.sc_iev_dns->ev, env.sc_iev_dns->ibuf.fd,
+ env.sc_iev_dns->events, env.sc_iev_dns->handler, &env);
+ event_add(&env.sc_iev_dns->ev, NULL);
+
+ event_dispatch();
+ client_shutdown();
+
+ return (0);
+
+}
+
+int
+client_build_req(struct idm *idm, struct idm_req *ir, struct aldap_message *m,
+ int min_attr, int max_attr)
+{
+ char **ldap_attrs;
+ int i, k;
+
+ bzero(ir, sizeof(*ir));
+ for (i = min_attr; i < max_attr; i++) {
+ if (idm->idm_flags & F_FIXED_ATTR(i)) {
+ if (strlcat(ir->ir_line, idm->idm_attrs[i],
+ sizeof(ir->ir_line)) >= sizeof(ir->ir_line))
+ /*
+ * entry yields a line > 1024, trash it.
+ */
+ return (-1);
+
+ if (i == ATTR_UID) {
+ ir->ir_key.ik_uid = strtonum(
+ idm->idm_attrs[i], 0,
+ UID_MAX, NULL);
+ } else if (i == ATTR_GR_GID) {
+ ir->ir_key.ik_gid = strtonum(
+ idm->idm_attrs[i], 0,
+ GID_MAX, NULL);
+ }
+ } else if (idm->idm_list & F_LIST(i)) {
+ aldap_match_attr(m, idm->idm_attrs[i], &ldap_attrs);
+ for (k = 0; k >= 0 && ldap_attrs && ldap_attrs[k] != NULL; k++) {
+ /* XXX: Fail when attributes have illegal characters e.g. ',' */
+ if (strlcat(ir->ir_line, ldap_attrs[k],
+ sizeof(ir->ir_line)) >= sizeof(ir->ir_line))
+ continue;
+ if (ldap_attrs[k+1] != NULL)
+ if (strlcat(ir->ir_line, ",",
+ sizeof(ir->ir_line))
+ >= sizeof(ir->ir_line)) {
+ aldap_free_attr(ldap_attrs);
+ return (-1);
+ }
+ }
+ aldap_free_attr(ldap_attrs);
+ } else {
+ if (aldap_match_attr(m, idm->idm_attrs[i], &ldap_attrs) == -1)
+ return (-1);
+ if (ldap_attrs[0] == NULL)
+ return (-1);
+ if (strlcat(ir->ir_line, ldap_attrs[0],
+ sizeof(ir->ir_line)) >= sizeof(ir->ir_line)) {
+ aldap_free_attr(ldap_attrs);
+ return (-1);
+ }
+ if (i == ATTR_UID) {
+ ir->ir_key.ik_uid = strtonum(
+ ldap_attrs[0], 0, UID_MAX, NULL);
+ } else if (i == ATTR_GR_GID) {
+ ir->ir_key.ik_uid = strtonum(
+ ldap_attrs[0], 0, GID_MAX, NULL);
+ }
+ aldap_free_attr(ldap_attrs);
+ }
+
+ if (i + 1 != max_attr)
+ if (strlcat(ir->ir_line, ":",
+ sizeof(ir->ir_line)) >= sizeof(ir->ir_line))
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+client_search_idm(struct env *env, struct idm *idm, struct aldap *al,
+ char **attrs, char *filter, int min_attr, int max_attr,
+ enum imsg_type type)
+{
+ struct idm_req ir;
+ struct aldap_message *m;
+ struct aldap_page_control *pg = NULL;
+ const char *errstr;
+ char *dn;
+
+ dn = idm->idm_basedn;
+ if (type == IMSG_GRP_ENTRY && idm->idm_groupdn[0] != '\0')
+ dn = idm->idm_groupdn;
+
+ do {
+ if (aldap_search(al, dn, LDAP_SCOPE_SUBTREE,
+ filter, attrs, 0, 0, 0, pg) == -1) {
+ aldap_get_errno(al, &errstr);
+ log_debug("%s", errstr);
+ return (-1);
+ }
+
+ if (pg != NULL) {
+ aldap_freepage(pg);
+ pg = NULL;
+ }
+
+ while ((m = aldap_parse(al)) != NULL) {
+ if (al->msgid != m->msgid) {
+ goto fail;
+ }
+
+ if (m->message_type == LDAP_RES_SEARCH_RESULT) {
+ if (m->page != NULL && m->page->cookie_len != 0)
+ pg = m->page;
+ else
+ pg = NULL;
+
+ aldap_freemsg(m);
+ break;
+ }
+
+ if (m->message_type != LDAP_RES_SEARCH_ENTRY) {
+ goto fail;
+ }
+
+ if (client_build_req(idm, &ir, m, min_attr, max_attr) == 0)
+ imsg_compose_event(env->sc_iev, type, 0, 0, -1,
+ &ir, sizeof(ir));
+
+ aldap_freemsg(m);
+ }
+ } while (pg != NULL);
+
+ return (0);
+
+fail:
+ aldap_freemsg(m);
+ if (pg != NULL) {
+ aldap_freepage(pg);
+ }
+
+ return (-1);
+}
+
+int
+client_try_idm(struct env *env, struct idm *idm)
+{
+ const char *where;
+ char *attrs[ATTR_MAX+1];
+ int i, j;
+ struct aldap_message *m;
+ struct aldap *al;
+
+ where = "connect";
+ if ((al = client_aldap_open(idm->idm_addr)) == NULL)
+ return (-1);
+
+ if (idm->idm_flags & F_NEEDAUTH) {
+ where = "binding";
+ if (aldap_bind(al, idm->idm_binddn, idm->idm_bindcred) == -1)
+ goto bad;
+
+ where = "parsing";
+ if ((m = aldap_parse(al)) == NULL)
+ goto bad;
+ where = "verifying msgid";
+ if (al->msgid != m->msgid) {
+ aldap_freemsg(m);
+ goto bad;
+ }
+ aldap_freemsg(m);
+ }
+
+ bzero(attrs, sizeof(attrs));
+ for (i = 0, j = 0; i < ATTR_MAX; i++) {
+ if (idm->idm_flags & F_FIXED_ATTR(i))
+ continue;
+ attrs[j++] = idm->idm_attrs[i];
+ }
+ attrs[j] = NULL;
+
+ /*
+ * build password line.
+ */
+ where = "search";
+ log_debug("searching password entries");
+ if (client_search_idm(env, idm, al, attrs,
+ idm->idm_filters[FILTER_USER], 0, ATTR_MAX, IMSG_PW_ENTRY) == -1)
+ goto bad;
+
+ bzero(attrs, sizeof(attrs));
+ for (i = ATTR_GR_MIN, j = 0; i < ATTR_GR_MAX; i++) {
+ if (idm->idm_flags & F_FIXED_ATTR(i))
+ continue;
+ attrs[j++] = idm->idm_attrs[i];
+ }
+ attrs[j] = NULL;
+
+ /*
+ * build group line.
+ */
+ where = "search";
+ log_debug("searching group entries");
+ if (client_search_idm(env, idm, al, attrs,
+ idm->idm_filters[FILTER_GROUP], ATTR_GR_MIN, ATTR_GR_MAX,
+ IMSG_GRP_ENTRY) == -1)
+ goto bad;
+
+ aldap_close(al);
+
+ idm->idm_state = STATE_LDAP_DONE;
+
+ return (0);
+bad:
+ aldap_close(al);
+ log_debug("directory %s errored out in %s", idm->idm_name, where);
+ return (-1);
+}
+
+void
+client_periodic_update(int fd, short event, void *p)
+{
+ struct env *env = p;
+
+ struct idm *idm;
+ int fail_cnt = 0;
+
+ /* If LDAP isn't finished, notify the master process to trash the
+ * update. */
+ TAILQ_FOREACH(idm, &env->sc_idms, idm_entry) {
+ if (idm->idm_state < STATE_LDAP_DONE)
+ fail_cnt++;
+
+ idm->idm_state = STATE_NONE;
+
+ client_addr_free(idm);
+ }
+ if (fail_cnt > 0) {
+ log_debug("trash the update");
+ imsg_compose_event(env->sc_iev, IMSG_TRASH_UPDATE, 0, 0, -1,
+ NULL, 0);
+ }
+
+ client_configure(env);
+}
+
+void
+client_configure(struct env *env)
+{
+ struct timeval tv;
+ struct idm *idm;
+ u_int16_t dlen;
+
+ log_debug("connecting to directories");
+
+ imsg_compose_event(env->sc_iev, IMSG_START_UPDATE, 0, 0, -1, NULL, 0);
+
+ /* Start the DNS lookups */
+ TAILQ_FOREACH(idm, &env->sc_idms, idm_entry) {
+ dlen = strlen(idm->idm_name) + 1;
+ imsg_compose_event(env->sc_iev_dns, IMSG_HOST_DNS, idm->idm_id,
+ 0, -1, idm->idm_name, dlen);
+ }
+
+ tv.tv_sec = env->sc_conf_tv.tv_sec;
+ tv.tv_usec = env->sc_conf_tv.tv_usec;
+ evtimer_set(&env->sc_conf_ev, client_periodic_update, env);
+ evtimer_add(&env->sc_conf_ev, &tv);
+}
diff --git a/usr.sbin/ypldap/log.c b/usr.sbin/ypldap/log.c
new file mode 100644
index 0000000..7fec6f7
--- /dev/null
+++ b/usr.sbin/ypldap/log.c
@@ -0,0 +1,162 @@
+/* $OpenBSD: log.c,v 1.1 2008/06/26 15:10:01 pyr Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, 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 <sys/types.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+
+void log_init(int);
+void log_warn(const char *, ...);
+void log_warnx(const char *, ...);
+void log_info(const char *, ...);
+void log_debug(const char *, ...);
+__dead2 void fatal(const char *);
+__dead2 void fatalx(const char *);
+
+int debug;
+
+void vlog(int, const char *, va_list);
+void logit(int, const char *, ...);
+
+void
+log_init(int n_debug)
+{
+ extern char *__progname;
+
+ debug = n_debug;
+
+ if (!debug)
+ openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
+
+ tzset();
+}
+
+void
+logit(int pri, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vlog(pri, fmt, ap);
+ va_end(ap);
+}
+
+void
+vlog(int pri, const char *fmt, va_list ap)
+{
+ char *nfmt;
+
+ if (debug) {
+ /* best effort in out of mem situations */
+ if (asprintf(&nfmt, "%s\n", fmt) == -1) {
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ } else {
+ vfprintf(stderr, nfmt, ap);
+ free(nfmt);
+ }
+ fflush(stderr);
+ } else
+ vsyslog(pri, fmt, ap);
+}
+
+
+void
+log_warn(const char *emsg, ...)
+{
+ char *nfmt;
+ va_list ap;
+
+ /* best effort to even work in out of memory situations */
+ if (emsg == NULL)
+ logit(LOG_CRIT, "%s", strerror(errno));
+ else {
+ va_start(ap, emsg);
+
+ if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
+ /* we tried it... */
+ vlog(LOG_CRIT, emsg, ap);
+ logit(LOG_CRIT, "%s", strerror(errno));
+ } else {
+ vlog(LOG_CRIT, nfmt, ap);
+ free(nfmt);
+ }
+ va_end(ap);
+ }
+}
+
+void
+log_warnx(const char *emsg, ...)
+{
+ va_list ap;
+
+ va_start(ap, emsg);
+ vlog(LOG_CRIT, emsg, ap);
+ va_end(ap);
+}
+
+void
+log_info(const char *emsg, ...)
+{
+ va_list ap;
+
+ va_start(ap, emsg);
+ vlog(LOG_INFO, emsg, ap);
+ va_end(ap);
+}
+
+void
+log_debug(const char *emsg, ...)
+{
+ va_list ap;
+
+ if (debug > 1) {
+ va_start(ap, emsg);
+ vlog(LOG_DEBUG, emsg, ap);
+ va_end(ap);
+ }
+}
+
+void
+fatal(const char *emsg)
+{
+ if (emsg == NULL)
+ logit(LOG_CRIT, "fatal: %s", strerror(errno));
+ else
+ if (errno)
+ logit(LOG_CRIT, "fatal: %s: %s",
+ emsg, strerror(errno));
+ else
+ logit(LOG_CRIT, "fatal: %s", emsg);
+
+ exit(1);
+}
+
+void
+fatalx(const char *emsg)
+{
+ errno = 0;
+ fatal(emsg);
+}
diff --git a/usr.sbin/ypldap/parse.y b/usr.sbin/ypldap/parse.y
new file mode 100644
index 0000000..15d3ff2
--- /dev/null
+++ b/usr.sbin/ypldap/parse.y
@@ -0,0 +1,838 @@
+/* $OpenBSD: parse.y,v 1.18 2015/01/16 06:40:22 deraadt Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
+ * Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
+ * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
+ * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
+ * Copyright (c) 2001 Theo de Raadt. All rights reserved.
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <event.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "ypldap.h"
+
+TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
+static struct file {
+ TAILQ_ENTRY(file) entry;
+ FILE *stream;
+ char *name;
+ int lineno;
+ int errors;
+} *file, *topfile;
+struct file *pushfile(const char *, int);
+int popfile(void);
+int check_file_secrecy(int, const char *);
+int yyparse(void);
+int yylex(void);
+int yyerror(const char *, ...)
+ __attribute__((__format__ (printf, 1, 2)))
+ __attribute__((__nonnull__ (1)));
+int kw_cmp(const void *, const void *);
+int lookup(char *);
+int lgetc(int);
+int lungetc(int);
+int findeol(void);
+
+TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
+struct sym {
+ TAILQ_ENTRY(sym) entry;
+ int used;
+ int persist;
+ char *nam;
+ char *val;
+};
+int symset(const char *, const char *, int);
+char *symget(const char *);
+
+struct env *conf = NULL;
+struct idm *idm = NULL;
+static int errors = 0;
+
+typedef struct {
+ union {
+ int64_t number;
+ char *string;
+ } v;
+ int lineno;
+} YYSTYPE;
+
+%}
+
+%token SERVER FILTER ATTRIBUTE BASEDN BINDDN GROUPDN BINDCRED MAPS CHANGE DOMAIN PROVIDE
+%token USER GROUP TO EXPIRE HOME SHELL GECOS UID GID INTERVAL
+%token PASSWD NAME FIXED LIST GROUPNAME GROUPPASSWD GROUPGID MAP
+%token INCLUDE DIRECTORY CLASS PORT ERROR GROUPMEMBERS
+%token <v.string> STRING
+%token <v.number> NUMBER
+%type <v.number> opcode attribute
+%type <v.string> port
+
+%%
+
+grammar : /* empty */
+ | grammar '\n'
+ | grammar include '\n'
+ | grammar varset '\n'
+ | grammar directory '\n'
+ | grammar main '\n'
+ | grammar error '\n' { file->errors++; }
+ ;
+
+nl : '\n' optnl
+ ;
+
+optnl : '\n' optnl
+ | /* empty */
+ ;
+
+
+include : INCLUDE STRING {
+ struct file *nfile;
+
+ if ((nfile = pushfile($2, 0)) == NULL) {
+ yyerror("failed to include file %s", $2);
+ free($2);
+ YYERROR;
+ }
+ free($2);
+
+ file = nfile;
+ lungetc('\n');
+ }
+ ;
+
+varset : STRING '=' STRING {
+ if (symset($1, $3, 0) == -1)
+ fatal("cannot store variable");
+ free($1);
+ free($3);
+ }
+ ;
+
+port : /* empty */ { $$ = NULL; }
+ | PORT STRING { $$ = $2; }
+ ;
+
+opcode : GROUP { $$ = 0; }
+ | PASSWD { $$ = 1; }
+ ;
+
+
+attribute : NAME { $$ = 0; }
+ | PASSWD { $$ = 1; }
+ | UID { $$ = 2; }
+ | GID { $$ = 3; }
+ | CLASS { $$ = 4; }
+ | CHANGE { $$ = 5; }
+ | EXPIRE { $$ = 6; }
+ | GECOS { $$ = 7; }
+ | HOME { $$ = 8; }
+ | SHELL { $$ = 9; }
+ | GROUPNAME { $$ = 10; }
+ | GROUPPASSWD { $$ = 11; }
+ | GROUPGID { $$ = 12; }
+ | GROUPMEMBERS { $$ = 13; }
+ ;
+
+diropt : BINDDN STRING {
+ idm->idm_flags |= F_NEEDAUTH;
+ if (strlcpy(idm->idm_binddn, $2,
+ sizeof(idm->idm_binddn)) >=
+ sizeof(idm->idm_binddn)) {
+ yyerror("directory binddn truncated");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ }
+ | BINDCRED STRING {
+ idm->idm_flags |= F_NEEDAUTH;
+ if (strlcpy(idm->idm_bindcred, $2,
+ sizeof(idm->idm_bindcred)) >=
+ sizeof(idm->idm_bindcred)) {
+ yyerror("directory bindcred truncated");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ }
+ | BASEDN STRING {
+ if (strlcpy(idm->idm_basedn, $2,
+ sizeof(idm->idm_basedn)) >=
+ sizeof(idm->idm_basedn)) {
+ yyerror("directory basedn truncated");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ }
+ | GROUPDN STRING {
+ if(strlcpy(idm->idm_groupdn, $2,
+ sizeof(idm->idm_groupdn)) >=
+ sizeof(idm->idm_groupdn)) {
+ yyerror("directory groupdn truncated");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ }
+ | opcode FILTER STRING {
+ if (strlcpy(idm->idm_filters[$1], $3,
+ sizeof(idm->idm_filters[$1])) >=
+ sizeof(idm->idm_filters[$1])) {
+ yyerror("filter truncated");
+ free($3);
+ YYERROR;
+ }
+ free($3);
+ }
+ | ATTRIBUTE attribute MAPS TO STRING {
+ if (strlcpy(idm->idm_attrs[$2], $5,
+ sizeof(idm->idm_attrs[$2])) >=
+ sizeof(idm->idm_attrs[$2])) {
+ yyerror("attribute truncated");
+ free($5);
+ YYERROR;
+ }
+ free($5);
+ }
+ | FIXED ATTRIBUTE attribute STRING {
+ if (strlcpy(idm->idm_attrs[$3], $4,
+ sizeof(idm->idm_attrs[$3])) >=
+ sizeof(idm->idm_attrs[$3])) {
+ yyerror("attribute truncated");
+ free($4);
+ YYERROR;
+ }
+ idm->idm_flags |= F_FIXED_ATTR($3);
+ free($4);
+ }
+ | LIST attribute MAPS TO STRING {
+ if (strlcpy(idm->idm_attrs[$2], $5,
+ sizeof(idm->idm_attrs[$2])) >=
+ sizeof(idm->idm_attrs[$2])) {
+ yyerror("attribute truncated");
+ free($5);
+ YYERROR;
+ }
+ idm->idm_list |= F_LIST($2);
+ free($5);
+ }
+ ;
+
+directory : DIRECTORY STRING port {
+ if ((idm = calloc(1, sizeof(*idm))) == NULL)
+ fatal(NULL);
+ idm->idm_id = conf->sc_maxid++;
+
+ if (strlcpy(idm->idm_name, $2,
+ sizeof(idm->idm_name)) >=
+ sizeof(idm->idm_name)) {
+ yyerror("attribute truncated");
+ free($2);
+ YYERROR;
+ }
+
+ free($2);
+ } '{' optnl diropts '}' {
+ TAILQ_INSERT_TAIL(&conf->sc_idms, idm, idm_entry);
+ idm = NULL;
+ }
+ ;
+
+main : INTERVAL NUMBER {
+ conf->sc_conf_tv.tv_sec = $2;
+ conf->sc_conf_tv.tv_usec = 0;
+ }
+ | DOMAIN STRING {
+ if (strlcpy(conf->sc_domainname, $2,
+ sizeof(conf->sc_domainname)) >=
+ sizeof(conf->sc_domainname)) {
+ yyerror("domainname truncated");
+ free($2);
+ YYERROR;
+ }
+ free($2);
+ }
+ | PROVIDE MAP STRING {
+ if (strcmp($3, "passwd.byname") == 0)
+ conf->sc_flags |= YPMAP_PASSWD_BYNAME;
+ else if (strcmp($3, "passwd.byuid") == 0)
+ conf->sc_flags |= YPMAP_PASSWD_BYUID;
+ else if (strcmp($3, "master.passwd.byname") == 0)
+ conf->sc_flags |= YPMAP_MASTER_PASSWD_BYNAME;
+ else if (strcmp($3, "master.passwd.byuid") == 0)
+ conf->sc_flags |= YPMAP_MASTER_PASSWD_BYUID;
+ else if (strcmp($3, "group.byname") == 0)
+ conf->sc_flags |= YPMAP_GROUP_BYNAME;
+ else if (strcmp($3, "group.bygid") == 0)
+ conf->sc_flags |= YPMAP_GROUP_BYGID;
+ else if (strcmp($3, "netid.byname") == 0)
+ conf->sc_flags |= YPMAP_NETID_BYNAME;
+ else {
+ yyerror("unsupported map type: %s", $3);
+ free($3);
+ YYERROR;
+ }
+ free($3);
+ }
+ ;
+
+diropts : diropts diropt nl
+ | diropt optnl
+ ;
+
+%%
+
+struct keywords {
+ const char *k_name;
+ int k_val;
+};
+
+int
+yyerror(const char *fmt, ...)
+{
+ va_list ap;
+ char *msg;
+
+ file->errors++;
+ va_start(ap, fmt);
+ if (vasprintf(&msg, fmt, ap) == -1)
+ fatalx("yyerror vasprintf");
+ va_end(ap);
+ logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
+ free(msg);
+ return (0);
+}
+
+int
+kw_cmp(const void *k, const void *e)
+{
+ return (strcmp(k, ((const struct keywords *)e)->k_name));
+}
+
+int
+lookup(char *s)
+{
+ /* this has to be sorted always */
+ static const struct keywords keywords[] = {
+ { "attribute", ATTRIBUTE },
+ { "basedn", BASEDN },
+ { "bindcred", BINDCRED },
+ { "binddn", BINDDN },
+ { "change", CHANGE },
+ { "class", CLASS },
+ { "directory", DIRECTORY },
+ { "domain", DOMAIN },
+ { "expire", EXPIRE },
+ { "filter", FILTER },
+ { "fixed", FIXED },
+ { "gecos", GECOS },
+ { "gid", GID },
+ { "group", GROUP },
+ { "groupdn", GROUPDN },
+ { "groupgid", GROUPGID },
+ { "groupmembers", GROUPMEMBERS },
+ { "groupname", GROUPNAME },
+ { "grouppasswd", GROUPPASSWD },
+ { "home", HOME },
+ { "include", INCLUDE },
+ { "interval", INTERVAL },
+ { "list", LIST },
+ { "map", MAP },
+ { "maps", MAPS },
+ { "name", NAME },
+ { "passwd", PASSWD },
+ { "port", PORT },
+ { "provide", PROVIDE },
+ { "server", SERVER },
+ { "shell", SHELL },
+ { "to", TO },
+ { "uid", UID },
+ { "user", USER },
+ };
+ const struct keywords *p;
+
+ p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
+ sizeof(keywords[0]), kw_cmp);
+
+ if (p)
+ return (p->k_val);
+ else
+ return (STRING);
+}
+
+#define MAXPUSHBACK 128
+
+u_char *parsebuf;
+int parseindex;
+u_char pushback_buffer[MAXPUSHBACK];
+int pushback_index = 0;
+
+int
+lgetc(int quotec)
+{
+ int c, next;
+
+ if (parsebuf) {
+ /* Read character from the parsebuffer instead of input. */
+ if (parseindex >= 0) {
+ c = parsebuf[parseindex++];
+ if (c != '\0')
+ return (c);
+ parsebuf = NULL;
+ } else
+ parseindex++;
+ }
+
+ if (pushback_index)
+ return (pushback_buffer[--pushback_index]);
+
+ if (quotec) {
+ if ((c = getc(file->stream)) == EOF) {
+ yyerror("reached end of file while parsing "
+ "quoted string");
+ if (file == topfile || popfile() == EOF)
+ return (EOF);
+ return (quotec);
+ }
+ return (c);
+ }
+
+ while ((c = getc(file->stream)) == '\\') {
+ next = getc(file->stream);
+ if (next != '\n') {
+ c = next;
+ break;
+ }
+ yylval.lineno = file->lineno;
+ file->lineno++;
+ }
+
+ while (c == EOF) {
+ if (file == topfile || popfile() == EOF)
+ return (EOF);
+ c = getc(file->stream);
+ }
+ return (c);
+}
+
+int
+lungetc(int c)
+{
+ if (c == EOF)
+ return (EOF);
+ if (parsebuf) {
+ parseindex--;
+ if (parseindex >= 0)
+ return (c);
+ }
+ if (pushback_index < MAXPUSHBACK-1)
+ return (pushback_buffer[pushback_index++] = c);
+ else
+ return (EOF);
+}
+
+int
+findeol(void)
+{
+ int c;
+
+ parsebuf = NULL;
+
+ /* skip to either EOF or the first real EOL */
+ while (1) {
+ if (pushback_index)
+ c = pushback_buffer[--pushback_index];
+ else
+ c = lgetc(0);
+ if (c == '\n') {
+ file->lineno++;
+ break;
+ }
+ if (c == EOF)
+ break;
+ }
+ return (ERROR);
+}
+
+int
+yylex(void)
+{
+ u_char buf[8096];
+ u_char *p, *val;
+ int quotec, next, c;
+ int token;
+
+top:
+ p = buf;
+ while ((c = lgetc(0)) == ' ' || c == '\t')
+ ; /* nothing */
+
+ yylval.lineno = file->lineno;
+ if (c == '#')
+ while ((c = lgetc(0)) != '\n' && c != EOF)
+ ; /* nothing */
+ if (c == '$' && parsebuf == NULL) {
+ while (1) {
+ if ((c = lgetc(0)) == EOF)
+ return (0);
+
+ if (p + 1 >= buf + sizeof(buf) - 1) {
+ yyerror("string too long");
+ return (findeol());
+ }
+ if (isalnum(c) || c == '_') {
+ *p++ = c;
+ continue;
+ }
+ *p = '\0';
+ lungetc(c);
+ break;
+ }
+ val = symget(buf);
+ if (val == NULL) {
+ yyerror("macro '%s' not defined", buf);
+ return (findeol());
+ }
+ parsebuf = val;
+ parseindex = 0;
+ goto top;
+ }
+
+ switch (c) {
+ case '\'':
+ case '"':
+ quotec = c;
+ while (1) {
+ if ((c = lgetc(quotec)) == EOF)
+ return (0);
+ if (c == '\n') {
+ file->lineno++;
+ continue;
+ } else if (c == '\\') {
+ if ((next = lgetc(quotec)) == EOF)
+ return (0);
+ if (next == quotec || c == ' ' || c == '\t')
+ c = next;
+ else if (next == '\n') {
+ file->lineno++;
+ continue;
+ } else
+ lungetc(next);
+ } else if (c == quotec) {
+ *p = '\0';
+ break;
+ } else if (c == '\0') {
+ yyerror("syntax error");
+ return (findeol());
+ }
+ if (p + 1 >= buf + sizeof(buf) - 1) {
+ yyerror("string too long");
+ return (findeol());
+ }
+ *p++ = c;
+ }
+ yylval.v.string = strdup(buf);
+ if (yylval.v.string == NULL)
+ err(1, "yylex: strdup");
+ return (STRING);
+ }
+
+#define allowed_to_end_number(x) \
+ (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
+
+ if (c == '-' || isdigit(c)) {
+ do {
+ *p++ = c;
+ if ((unsigned)(p-buf) >= sizeof(buf)) {
+ yyerror("string too long");
+ return (findeol());
+ }
+ } while ((c = lgetc(0)) != EOF && isdigit(c));
+ lungetc(c);
+ if (p == buf + 1 && buf[0] == '-')
+ goto nodigits;
+ if (c == EOF || allowed_to_end_number(c)) {
+ const char *errstr = NULL;
+
+ *p = '\0';
+ yylval.v.number = strtonum(buf, LLONG_MIN,
+ LLONG_MAX, &errstr);
+ if (errstr) {
+ yyerror("\"%s\" invalid number: %s",
+ buf, errstr);
+ return (findeol());
+ }
+ return (NUMBER);
+ } else {
+nodigits:
+ while (p > buf + 1)
+ lungetc(*--p);
+ c = *--p;
+ if (c == '-')
+ return (c);
+ }
+ }
+
+#define allowed_in_string(x) \
+ (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
+ x != '{' && x != '}' && x != '<' && x != '>' && \
+ x != '!' && x != '=' && x != '#' && \
+ x != ','))
+
+ if (isalnum(c) || c == ':' || c == '_') {
+ do {
+ *p++ = c;
+ if ((unsigned)(p-buf) >= sizeof(buf)) {
+ yyerror("string too long");
+ return (findeol());
+ }
+ } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
+ lungetc(c);
+ *p = '\0';
+ if ((token = lookup(buf)) == STRING)
+ if ((yylval.v.string = strdup(buf)) == NULL)
+ err(1, "yylex: strdup");
+ return (token);
+ }
+ if (c == '\n') {
+ yylval.lineno = file->lineno;
+ file->lineno++;
+ }
+ if (c == EOF)
+ return (0);
+ return (c);
+}
+
+int
+check_file_secrecy(int fd, const char *fname)
+{
+ struct stat st;
+
+ if (fstat(fd, &st)) {
+ log_warn("cannot stat %s", fname);
+ return (-1);
+ }
+ if (st.st_uid != 0 && st.st_uid != getuid()) {
+ log_warnx("%s: owner not root or current user", fname);
+ return (-1);
+ }
+ if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
+ log_warnx("%s: group writable or world read/writable", fname);
+ return (-1);
+ }
+ return (0);
+}
+
+struct file *
+pushfile(const char *name, int secret)
+{
+ struct file *nfile;
+
+ if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
+ log_warn("malloc");
+ return (NULL);
+ }
+ if ((nfile->name = strdup(name)) == NULL) {
+ log_warn("malloc");
+ free(nfile);
+ return (NULL);
+ }
+ if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
+ log_warn("%s", nfile->name);
+ free(nfile->name);
+ free(nfile);
+ return (NULL);
+ } else if (secret &&
+ check_file_secrecy(fileno(nfile->stream), nfile->name)) {
+ fclose(nfile->stream);
+ free(nfile->name);
+ free(nfile);
+ return (NULL);
+ }
+ nfile->lineno = 1;
+ TAILQ_INSERT_TAIL(&files, nfile, entry);
+ return (nfile);
+}
+
+int
+popfile(void)
+{
+ struct file *prev;
+
+ if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
+ prev->errors += file->errors;
+
+ TAILQ_REMOVE(&files, file, entry);
+ fclose(file->stream);
+ free(file->name);
+ free(file);
+ file = prev;
+ return (file ? 0 : EOF);
+}
+
+int
+parse_config(struct env *x_conf, const char *filename, int opts)
+{
+ struct sym *sym, *next;
+
+ conf = x_conf;
+ bzero(conf, sizeof(*conf));
+
+ TAILQ_INIT(&conf->sc_idms);
+ conf->sc_conf_tv.tv_sec = DEFAULT_INTERVAL;
+ conf->sc_conf_tv.tv_usec = 0;
+
+ errors = 0;
+
+ if ((file = pushfile(filename, 1)) == NULL) {
+ return (-1);
+ }
+ topfile = file;
+
+ /*
+ * parse configuration
+ */
+ setservent(1);
+ yyparse();
+ endservent();
+ errors = file->errors;
+ popfile();
+
+ /* Free macros and check which have not been used. */
+ for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
+ next = TAILQ_NEXT(sym, entry);
+ if ((opts & YPLDAP_OPT_VERBOSE) && !sym->used)
+ fprintf(stderr, "warning: macro '%s' not "
+ "used\n", sym->nam);
+ if (!sym->persist) {
+ free(sym->nam);
+ free(sym->val);
+ TAILQ_REMOVE(&symhead, sym, entry);
+ free(sym);
+ }
+ }
+
+ if (errors) {
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+symset(const char *nam, const char *val, int persist)
+{
+ struct sym *sym;
+
+ for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
+ sym = TAILQ_NEXT(sym, entry))
+ ; /* nothing */
+
+ if (sym != NULL) {
+ if (sym->persist == 1)
+ return (0);
+ else {
+ free(sym->nam);
+ free(sym->val);
+ TAILQ_REMOVE(&symhead, sym, entry);
+ free(sym);
+ }
+ }
+ if ((sym = calloc(1, sizeof(*sym))) == NULL)
+ return (-1);
+
+ sym->nam = strdup(nam);
+ if (sym->nam == NULL) {
+ free(sym);
+ return (-1);
+ }
+ sym->val = strdup(val);
+ if (sym->val == NULL) {
+ free(sym->nam);
+ free(sym);
+ return (-1);
+ }
+ sym->used = 0;
+ sym->persist = persist;
+ TAILQ_INSERT_TAIL(&symhead, sym, entry);
+ return (0);
+}
+
+int
+cmdline_symset(char *s)
+{
+ char *sym, *val;
+ int ret;
+ size_t len;
+
+ if ((val = strrchr(s, '=')) == NULL)
+ return (-1);
+
+ len = strlen(s) - strlen(val) + 1;
+ if ((sym = malloc(len)) == NULL)
+ errx(1, "cmdline_symset: malloc");
+
+ (void)strlcpy(sym, s, len);
+
+ ret = symset(sym, val + 1, 1);
+ free(sym);
+
+ return (ret);
+}
+
+char *
+symget(const char *nam)
+{
+ struct sym *sym;
+
+ TAILQ_FOREACH(sym, &symhead, entry)
+ if (strcmp(nam, sym->nam) == 0) {
+ sym->used = 1;
+ return (sym->val);
+ }
+ return (NULL);
+}
diff --git a/usr.sbin/ypldap/yp.c b/usr.sbin/ypldap/yp.c
new file mode 100644
index 0000000..e461136
--- /dev/null
+++ b/usr.sbin/ypldap/yp.c
@@ -0,0 +1,652 @@
+/* $OpenBSD: yp.c,v 1.14 2015/02/11 01:26:00 pelikan Exp $ */
+/* $FreeBSD$ */
+/*
+ * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/tree.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <event.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_rmt.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+#include "ypldap.h"
+
+void yp_dispatch(struct svc_req *, SVCXPRT *);
+void yp_disable_events(void);
+void yp_fd_event(int, short, void *);
+int yp_check(struct svc_req *);
+int yp_valid_domain(char *, struct ypresp_val *);
+void yp_make_val(struct ypresp_val *, char *, int);
+void yp_make_keyval(struct ypresp_key_val *, char *, char *);
+
+static struct env *env;
+
+struct yp_event {
+ TAILQ_ENTRY(yp_event) ye_entry;
+ struct event ye_event;
+};
+
+struct yp_data {
+ SVCXPRT *yp_trans_udp;
+ SVCXPRT *yp_trans_tcp;
+ TAILQ_HEAD(, yp_event) yd_events;
+};
+
+void
+yp_disable_events(void)
+{
+ struct yp_event *ye;
+
+ while ((ye = TAILQ_FIRST(&env->sc_yp->yd_events)) != NULL) {
+ TAILQ_REMOVE(&env->sc_yp->yd_events, ye, ye_entry);
+ event_del(&ye->ye_event);
+ free(ye);
+ }
+}
+
+void
+yp_enable_events(void)
+{
+ int i;
+ extern fd_set svc_fdset;
+ struct yp_event *ye;
+
+ for (i = 0; i < getdtablesize(); i++) {
+ if (FD_ISSET(i, &svc_fdset)) {
+ if ((ye = calloc(1, sizeof(*ye))) == NULL)
+ fatal(NULL);
+ event_set(&ye->ye_event, i, EV_READ, yp_fd_event, NULL);
+ event_add(&ye->ye_event, NULL);
+ TAILQ_INSERT_TAIL(&env->sc_yp->yd_events, ye, ye_entry);
+ }
+ }
+}
+
+void
+yp_fd_event(int fd, short event, void *p)
+{
+ svc_getreq_common(fd);
+ yp_disable_events();
+ yp_enable_events();
+}
+
+void
+yp_init(struct env *x_env)
+{
+ struct yp_data *yp;
+
+ if ((yp = calloc(1, sizeof(*yp))) == NULL)
+ fatal(NULL);
+ TAILQ_INIT(&yp->yd_events);
+
+ env = x_env;
+ env->sc_yp = yp;
+
+ (void)pmap_unset(YPPROG, YPVERS);
+
+ if ((yp->yp_trans_udp = svcudp_create(RPC_ANYSOCK)) == NULL)
+ fatal("cannot create udp service");
+ if ((yp->yp_trans_tcp = svctcp_create(RPC_ANYSOCK, 0, 0)) == NULL)
+ fatal("cannot create tcp service");
+
+ if (!svc_register(yp->yp_trans_udp, YPPROG, YPVERS,
+ yp_dispatch, IPPROTO_UDP)) {
+ fatal("unable to register (YPPROG, YPVERS, udp)");
+ }
+ if (!svc_register(yp->yp_trans_tcp, YPPROG, YPVERS,
+ yp_dispatch, IPPROTO_TCP)) {
+ fatal("unable to register (YPPROG, YPVERS, tcp)");
+ }
+}
+
+/*
+ * lots of inspiration from ypserv by Mats O Jansson
+ */
+void
+yp_dispatch(struct svc_req *req, SVCXPRT *trans)
+{
+ xdrproc_t xdr_argument;
+ xdrproc_t xdr_result;
+ char *result;
+ char *(*cb)(char *, struct svc_req *);
+ union {
+ domainname ypproc_domain_2_arg;
+ domainname ypproc_domain_nonack_2_arg;
+ ypreq_key ypproc_match_2_arg;
+ ypreq_nokey ypproc_first_2_arg;
+ ypreq_key ypproc_next_2_arg;
+ ypreq_xfr ypproc_xfr_2_arg;
+ ypreq_nokey ypproc_all_2_arg;
+ ypreq_nokey ypproc_master_2_arg;
+ ypreq_nokey ypproc_order_2_arg;
+ domainname ypproc_maplist_2_arg;
+ } argument;
+
+ xdr_argument = (xdrproc_t) xdr_void;
+ xdr_result = (xdrproc_t) xdr_void;
+ cb = NULL;
+ switch (req->rq_proc) {
+ case YPPROC_NULL:
+ xdr_argument = (xdrproc_t) xdr_void;
+ xdr_result = (xdrproc_t) xdr_void;
+ if (yp_check(req) == -1)
+ return;
+ result = NULL;
+ if (!svc_sendreply(trans, (xdrproc_t) xdr_void,
+ (void *)&result))
+ svcerr_systemerr(trans);
+ return;
+ case YPPROC_DOMAIN:
+ xdr_argument = (xdrproc_t) xdr_domainname;
+ xdr_result = (xdrproc_t) xdr_bool;
+ if (yp_check(req) == -1)
+ return;
+ cb = (void *)ypproc_domain_2_svc;
+ break;
+ case YPPROC_DOMAIN_NONACK:
+ xdr_argument = (xdrproc_t) xdr_domainname;
+ xdr_result = (xdrproc_t) xdr_bool;
+ if (yp_check(req) == -1)
+ return;
+ cb = (void *)ypproc_domain_nonack_2_svc;
+ break;
+ case YPPROC_MATCH:
+ xdr_argument = (xdrproc_t) xdr_ypreq_key;
+ xdr_result = (xdrproc_t) xdr_ypresp_val;
+ if (yp_check(req) == -1)
+ return;
+ cb = (void *)ypproc_match_2_svc;
+ break;
+ case YPPROC_FIRST:
+ xdr_argument = (xdrproc_t) xdr_ypreq_nokey;
+ xdr_result = (xdrproc_t) xdr_ypresp_key_val;
+ if (yp_check(req) == -1)
+ return;
+ cb = (void *)ypproc_first_2_svc;
+ break;
+ case YPPROC_NEXT:
+ xdr_argument = (xdrproc_t) xdr_ypreq_key;
+ xdr_result = (xdrproc_t) xdr_ypresp_key_val;
+ if (yp_check(req) == -1)
+ return;
+ cb = (void *)ypproc_next_2_svc;
+ break;
+ case YPPROC_XFR:
+ if (yp_check(req) == -1)
+ return;
+ svcerr_noproc(trans);
+ return;
+ case YPPROC_CLEAR:
+ log_debug("ypproc_clear");
+ if (yp_check(req) == -1)
+ return;
+ svcerr_noproc(trans);
+ return;
+ case YPPROC_ALL:
+ log_debug("ypproc_all");
+ if (yp_check(req) == -1)
+ return;
+ cb = (void *)ypproc_all_2_svc;
+ break;
+ case YPPROC_MASTER:
+ log_debug("ypproc_master");
+ if (yp_check(req) == -1)
+ return;
+ cb = (void *)ypproc_master_2_svc;
+ break;
+ case YPPROC_ORDER:
+ log_debug("ypproc_order");
+ if (yp_check(req) == -1)
+ return;
+ svcerr_noproc(trans);
+ return;
+ case YPPROC_MAPLIST:
+ log_debug("ypproc_maplist");
+ if (yp_check(req) == -1)
+ return;
+ cb = (void *)ypproc_maplist_2_svc;
+ break;
+ default:
+ svcerr_noproc(trans);
+ return;
+ }
+ (void)memset(&argument, 0, sizeof(argument));
+
+ if (!svc_getargs(trans, xdr_argument, (caddr_t)&argument)) {
+ svcerr_decode(trans);
+ return;
+ }
+ result = (*cb)((char *)&argument, req);
+ if (result != NULL && !svc_sendreply(trans, xdr_result, result))
+ svcerr_systemerr(trans);
+ if (!svc_freeargs(trans, xdr_argument, (caddr_t)&argument)) {
+ /*
+ * ypserv does it too.
+ */
+ fatal("unable to free arguments");
+ }
+}
+
+int
+yp_check(struct svc_req *req)
+{
+ struct sockaddr_in *caller;
+
+ caller = svc_getcaller(req->rq_xprt);
+ /*
+ * We might want to know who we allow here.
+ */
+ return (0);
+}
+
+int
+yp_valid_domain(char *domain, struct ypresp_val *res)
+{
+ if (domain == NULL) {
+ log_debug("NULL domain !");
+ return (-1);
+ }
+ if (strcmp(domain, env->sc_domainname) != 0) {
+ res->stat = YP_NODOM;
+ return (-1);
+ }
+ return (0);
+}
+
+bool_t *
+ypproc_domain_2_svc(domainname *arg, struct svc_req *req)
+{
+ static bool_t res;
+
+ res = (bool_t)1;
+ if (strcmp(*arg, env->sc_domainname) != 0)
+ res = (bool_t)0;
+ return (&res);
+}
+
+bool_t *
+ypproc_domain_nonack_2_svc(domainname *arg, struct svc_req *req)
+{
+ static bool_t res;
+
+ if (strcmp(*arg, env->sc_domainname) != 0)
+ return NULL;
+ res = (bool_t)1;
+ return (&res);
+}
+
+ypresp_val *
+ypproc_match_2_svc(ypreq_key *arg, struct svc_req *req)
+{
+ struct userent ukey;
+ struct userent *ue;
+ struct groupent gkey;
+ struct groupent *ge;
+ static struct ypresp_val res;
+ const char *estr;
+ char *bp, *cp;
+ char key[YPMAXRECORD+1];
+
+ log_debug("matching '%.*s' in map %s", arg->key.keydat_len,
+ arg->key.keydat_val, arg->map);
+
+ if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
+ return (&res);
+
+ if (env->sc_user_names == NULL) {
+ /*
+ * tree not ready.
+ */
+ return (NULL);
+ }
+
+ if (arg->key.keydat_len > YPMAXRECORD) {
+ log_debug("argument too long");
+ return (NULL);
+ }
+ bzero(key, sizeof(key));
+ (void)strncpy(key, arg->key.keydat_val, arg->key.keydat_len);
+
+ if (strcmp(arg->map, "passwd.byname") == 0 ||
+ strcmp(arg->map, "master.passwd.byname") == 0) {
+ ukey.ue_line = key;
+ if ((ue = RB_FIND(user_name_tree, env->sc_user_names,
+ &ukey)) == NULL) {
+ res.stat = YP_NOKEY;
+ return (&res);
+ }
+
+ yp_make_val(&res, ue->ue_line, 1);
+ return (&res);
+ } else if (strcmp(arg->map, "passwd.byuid") == 0 ||
+ strcmp(arg->map, "master.passwd.byuid") == 0) {
+ ukey.ue_uid = strtonum(key, 0, UID_MAX, &estr);
+ if (estr) {
+ res.stat = YP_BADARGS;
+ return (&res);
+ }
+
+ if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids,
+ &ukey)) == NULL) {
+ res.stat = YP_NOKEY;
+ return (&res);
+ }
+
+ yp_make_val(&res, ue->ue_line, 1);
+ return (&res);
+ } else if (strcmp(arg->map, "group.bygid") == 0) {
+ gkey.ge_gid = strtonum(key, 0, GID_MAX, &estr);
+ if (estr) {
+ res.stat = YP_BADARGS;
+ return (&res);
+ }
+ if ((ge = RB_FIND(group_gid_tree, &env->sc_group_gids,
+ &gkey)) == NULL) {
+ res.stat = YP_NOKEY;
+ return (&res);
+ }
+
+ yp_make_val(&res, ge->ge_line, 1);
+ return (&res);
+ } else if (strcmp(arg->map, "group.byname") == 0) {
+ gkey.ge_line = key;
+ if ((ge = RB_FIND(group_name_tree, env->sc_group_names,
+ &gkey)) == NULL) {
+ res.stat = YP_NOKEY;
+ return (&res);
+ }
+
+ yp_make_val(&res, ge->ge_line, 1);
+ return (&res);
+ } else if (strcmp(arg->map, "netid.byname") == 0) {
+ bp = cp = key;
+
+ if (strncmp(bp, "unix.", strlen("unix.")) != 0) {
+ res.stat = YP_BADARGS;
+ return (&res);
+ }
+
+ bp += strlen("unix.");
+
+ if (*bp == '\0') {
+ res.stat = YP_BADARGS;
+ return (&res);
+ }
+
+ if (!(cp = strsep(&bp, "@"))) {
+ res.stat = YP_BADARGS;
+ return (&res);
+ }
+
+ if (strcmp(bp, arg->domain) != 0) {
+ res.stat = YP_BADARGS;
+ return (&res);
+ }
+
+ ukey.ue_uid = strtonum(cp, 0, UID_MAX, &estr);
+ if (estr) {
+ res.stat = YP_BADARGS;
+ return (&res);
+ }
+
+ if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids,
+ &ukey)) == NULL) {
+ res.stat = YP_NOKEY;
+ return (&res);
+ }
+
+ yp_make_val(&res, ue->ue_netid_line, 0);
+ return (&res);
+
+ } else {
+ log_debug("unknown map %s", arg->map);
+ res.stat = YP_NOMAP;
+ return (&res);
+ }
+}
+
+ypresp_key_val *
+ypproc_first_2_svc(ypreq_nokey *arg, struct svc_req *req)
+{
+ static struct ypresp_key_val res;
+
+ if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
+ return (&res);
+
+ if (strcmp(arg->map, "passwd.byname") == 0 ||
+ strcmp(arg->map, "master.passwd.byname") == 0) {
+ if (env->sc_user_lines == NULL)
+ return (NULL);
+
+ yp_make_keyval(&res, env->sc_user_lines, env->sc_user_lines);
+ } else if (strcmp(arg->map, "group.byname") == 0) {
+ if (env->sc_group_lines == NULL)
+ return (NULL);
+
+ yp_make_keyval(&res, env->sc_group_lines, env->sc_group_lines);
+ } else {
+ log_debug("unknown map %s", arg->map);
+ res.stat = YP_NOMAP;
+ }
+
+ return (&res);
+}
+
+ypresp_key_val *
+ypproc_next_2_svc(ypreq_key *arg, struct svc_req *req)
+{
+ struct userent ukey;
+ struct userent *ue;
+ struct groupent gkey;
+ struct groupent *ge;
+ char *line;
+ static struct ypresp_key_val res;
+ char key[YPMAXRECORD+1];
+
+ if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
+ return (&res);
+
+ if (strcmp(arg->map, "passwd.byname") == 0 ||
+ strcmp(arg->map, "master.passwd.byname") == 0) {
+ bzero(key, sizeof(key));
+ (void)strncpy(key, arg->key.keydat_val,
+ arg->key.keydat_len);
+ ukey.ue_line = key;
+ if ((ue = RB_FIND(user_name_tree, env->sc_user_names,
+ &ukey)) == NULL) {
+ /*
+ * canacar's trick:
+ * the user might have been deleted in between calls
+ * to next since the tree may be modified by a reload.
+ * next should still return the next user in
+ * lexicographical order, hence insert the search key
+ * and look up the next field, then remove it again.
+ */
+ RB_INSERT(user_name_tree, env->sc_user_names, &ukey);
+ if ((ue = RB_NEXT(user_name_tree, &env->sc_user_names,
+ &ukey)) == NULL) {
+ RB_REMOVE(user_name_tree, env->sc_user_names,
+ &ukey);
+ res.stat = YP_NOKEY;
+ return (&res);
+ }
+ RB_REMOVE(user_name_tree, env->sc_user_names, &ukey);
+ }
+ line = ue->ue_line + (strlen(ue->ue_line) + 1);
+ line = line + (strlen(line) + 1);
+ yp_make_keyval(&res, line, line);
+ return (&res);
+
+
+ } else if (strcmp(arg->map, "group.byname") == 0) {
+ bzero(key, sizeof(key));
+ (void)strncpy(key, arg->key.keydat_val,
+ arg->key.keydat_len);
+
+ gkey.ge_line = key;
+ if ((ge = RB_FIND(group_name_tree, env->sc_group_names,
+ &gkey)) == NULL) {
+ /*
+ * canacar's trick reloaded.
+ */
+ RB_INSERT(group_name_tree, env->sc_group_names, &gkey);
+ if ((ge = RB_NEXT(group_name_tree, &env->sc_group_names,
+ &gkey)) == NULL) {
+ RB_REMOVE(group_name_tree, env->sc_group_names,
+ &gkey);
+ res.stat = YP_NOKEY;
+ return (&res);
+ }
+ RB_REMOVE(group_name_tree, env->sc_group_names, &gkey);
+ }
+
+ line = ge->ge_line + (strlen(ge->ge_line) + 1);
+ line = line + (strlen(line) + 1);
+ yp_make_keyval(&res, line, line);
+ return (&res);
+ } else {
+ log_debug("unknown map %s", arg->map);
+ res.stat = YP_NOMAP;
+ return (&res);
+ }
+}
+
+ypresp_all *
+ypproc_all_2_svc(ypreq_nokey *arg, struct svc_req *req)
+{
+ static struct ypresp_all res;
+
+ if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
+ return (&res);
+
+ svcerr_auth(req->rq_xprt, AUTH_FAILED);
+ return (NULL);
+}
+
+ypresp_master *
+ypproc_master_2_svc(ypreq_nokey *arg, struct svc_req *req)
+{
+ static struct ypresp_master res;
+
+ if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1)
+ return (&res);
+
+ res.stat = YP_YPERR;
+ return (&res);
+}
+
+ypresp_maplist *
+ypproc_maplist_2_svc(domainname *arg, struct svc_req *req)
+{
+ size_t i;
+ static struct {
+ char *name;
+ int cond;
+ } mapnames[] = {
+ { "passwd.byname", YPMAP_PASSWD_BYNAME },
+ { "passwd.byuid", YPMAP_PASSWD_BYUID },
+ { "master.passwd.byname", YPMAP_MASTER_PASSWD_BYNAME },
+ { "master.passwd.byuid", YPMAP_MASTER_PASSWD_BYUID },
+ { "group.byname", YPMAP_GROUP_BYNAME },
+ { "group.bygid", YPMAP_GROUP_BYGID },
+ { "netid.byname", YPMAP_NETID_BYNAME },
+ };
+ static ypresp_maplist res;
+ static struct ypmaplist maps[sizeof(mapnames) / sizeof(mapnames[0])];
+
+ if (yp_valid_domain(*arg, (struct ypresp_val *)&res) == -1)
+ return (&res);
+
+ res.stat = YP_TRUE;
+ res.maps = NULL;
+ for (i = 0; i < sizeof(mapnames) / sizeof(mapnames[0]); i++) {
+ if (!(env->sc_flags & mapnames[i].cond))
+ continue;
+ maps[i].map = mapnames[i].name;
+ maps[i].next = res.maps;
+ res.maps = &maps[i];
+ }
+
+ return (&res);
+}
+
+void
+yp_make_val(struct ypresp_val *res, char *line, int replacecolon)
+{
+ static char buf[LINE_WIDTH];
+
+ bzero(buf, sizeof(buf));
+
+ if (replacecolon)
+ line[strlen(line)] = ':';
+ (void)strlcpy(buf, line, sizeof(buf));
+ if (replacecolon)
+ line[strcspn(line, ":")] = '\0';
+ log_debug("sending out %s", buf);
+
+ res->stat = YP_TRUE;
+ res->val.valdat_len = strlen(buf);
+ res->val.valdat_val = buf;
+}
+
+void
+yp_make_keyval(struct ypresp_key_val *res, char *key, char *line)
+{
+ static char keybuf[YPMAXRECORD+1];
+ static char buf[LINE_WIDTH];
+
+ bzero(keybuf, sizeof(keybuf));
+ bzero(buf, sizeof(buf));
+
+ (void)strlcpy(keybuf, key, sizeof(keybuf));
+ res->key.keydat_len = strlen(keybuf);
+ res->key.keydat_val = keybuf;
+
+ if (*line == '\0') {
+ res->stat = YP_NOMORE;
+ return;
+ }
+ res->stat = YP_TRUE;
+ line[strlen(line)] = ':';
+ (void)strlcpy(buf, line, sizeof(buf));
+ line[strcspn(line, ":")] = '\0';
+ log_debug("sending out %s => %s", keybuf, buf);
+
+ res->val.valdat_len = strlen(buf);
+ res->val.valdat_val = buf;
+}
diff --git a/usr.sbin/ypldap/ypldap.8 b/usr.sbin/ypldap/ypldap.8
new file mode 100644
index 0000000..2974e24
--- /dev/null
+++ b/usr.sbin/ypldap/ypldap.8
@@ -0,0 +1,82 @@
+.\" $OpenBSD: ypldap.8,v 1.10 2015/07/27 17:28:40 sobrado Exp $
+.\" $FreeBSD$
+.\"
+.\" Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
+.\"
+.\" 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+.\"
+.Dd $Mdocdate: July 27 2015 $
+.Dt YPLDAP 8
+.Os
+.Sh NAME
+.Nm ypldap
+.Nd YP map server using LDAP backend
+.Sh SYNOPSIS
+.Nm
+.Op Fl dnv
+.Op Fl D Ar macro Ns = Ns Ar value
+.Op Fl f Ar file
+.Sh DESCRIPTION
+.Nm
+is a daemon providing YP maps using LDAP as a backend.
+RFC 2307 or similar LDAP schemas can be tied to the different YP maps.
+.Nm
+has the same role as
+.Xr ypserv 8
+and the two daemons are exclusive.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl D Ar macro Ns = Ns Ar value
+Define
+.Ar macro
+to be set to
+.Ar value
+on the command line.
+Overrides the definition of
+.Ar macro
+in the configuration file.
+.It Fl d
+Do not daemonize.
+If this option is specified,
+.Nm
+will run in the foreground and log to
+.Em stderr .
+.It Fl f Ar file
+Specify an alternative configuration file.
+.It Fl n
+Configtest mode.
+Only check the configuration file for validity.
+.It Fl v
+Produce more verbose output.
+.El
+.Sh FILES
+.Bl -tag -width "/etc/ypldap.confXX" -compact
+.It Pa /etc/ypldap.conf
+Default
+.Nm
+configuration file.
+.El
+.Sh SEE ALSO
+.Xr ypldap.conf 5 ,
+.Xr ypbind 8
+.Sh HISTORY
+The
+.Nm
+program first appeared in
+.Ox 4.4 .
+.Sh AUTHORS
+The
+.Nm
+program was written by
+.An Pierre-Yves Ritschard .
diff --git a/usr.sbin/ypldap/ypldap.c b/usr.sbin/ypldap/ypldap.c
new file mode 100644
index 0000000..ad7209a
--- /dev/null
+++ b/usr.sbin/ypldap/ypldap.c
@@ -0,0 +1,651 @@
+/* $OpenBSD: ypldap.c,v 1.16 2015/11/02 10:06:06 jmatthew Exp $ */
+/* $FreeBSD */
+
+/*
+ * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/signal.h>
+#include <sys/tree.h>
+#include <sys/wait.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <event.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "ypldap.h"
+
+__dead2 void usage(void);
+int check_child(pid_t, const char *);
+void main_sig_handler(int, short, void *);
+void main_shutdown(void);
+void main_dispatch_client(int, short, void *);
+void main_configure_client(struct env *);
+void main_init_timer(int, short, void *);
+void main_start_update(struct env *);
+void main_trash_update(struct env *);
+void main_end_update(struct env *);
+int main_create_user_groups(struct env *);
+void purge_config(struct env *);
+void reconfigure(struct env *);
+
+int pipe_main2client[2];
+
+pid_t client_pid = 0;
+char *conffile = YPLDAP_CONF_FILE;
+int opts = 0;
+
+void
+usage(void)
+{
+ extern const char *__progname;
+
+ fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",
+ __progname);
+ exit(1);
+}
+
+int
+check_child(pid_t pid, const char *pname)
+{
+ int status;
+
+ if (waitpid(pid, &status, WNOHANG) > 0) {
+ if (WIFEXITED(status)) {
+ log_warnx("check_child: lost child %s exited", pname);
+ return (1);
+ }
+ if (WIFSIGNALED(status)) {
+ log_warnx("check_child: lost child %s terminated; "
+ "signal %d", pname, WTERMSIG(status));
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/* ARGUSED */
+void
+main_sig_handler(int sig, short event, void *p)
+{
+ int die = 0;
+
+ switch (sig) {
+ case SIGTERM:
+ case SIGINT:
+ die = 1;
+ /* FALLTHROUGH */
+ case SIGCHLD:
+ if (check_child(client_pid, "ldap client")) {
+ client_pid = 0;
+ die = 1;
+ }
+ if (die)
+ main_shutdown();
+ break;
+ case SIGHUP:
+ /* reconfigure */
+ break;
+ default:
+ fatalx("unexpected signal");
+ }
+}
+
+void
+main_shutdown(void)
+{
+ _exit(0);
+}
+
+void
+main_start_update(struct env *env)
+{
+ env->update_trashed = 0;
+
+ log_debug("starting directory update");
+ env->sc_user_line_len = 0;
+ env->sc_group_line_len = 0;
+ if ((env->sc_user_names_t = calloc(1,
+ sizeof(*env->sc_user_names_t))) == NULL ||
+ (env->sc_group_names_t = calloc(1,
+ sizeof(*env->sc_group_names_t))) == NULL)
+ fatal(NULL);
+ RB_INIT(env->sc_user_names_t);
+ RB_INIT(env->sc_group_names_t);
+}
+
+/*
+ * XXX: Currently this function should only be called when updating is
+ * finished. A notification should be send to ldapclient that it should stop
+ * sending new pwd/grp entries before it can be called from different places.
+ */
+void
+main_trash_update(struct env *env)
+{
+ struct userent *ue;
+ struct groupent *ge;
+
+ env->update_trashed = 1;
+
+ while ((ue = RB_ROOT(env->sc_user_names_t)) != NULL) {
+ RB_REMOVE(user_name_tree,
+ env->sc_user_names_t, ue);
+ free(ue->ue_line);
+ free(ue->ue_netid_line);
+ free(ue);
+ }
+ free(env->sc_user_names_t);
+ env->sc_user_names_t = NULL;
+ while ((ge = RB_ROOT(env->sc_group_names_t))
+ != NULL) {
+ RB_REMOVE(group_name_tree,
+ env->sc_group_names_t, ge);
+ free(ge->ge_line);
+ free(ge);
+ }
+ free(env->sc_group_names_t);
+ env->sc_group_names_t = NULL;
+}
+
+int
+main_create_user_groups(struct env *env)
+{
+ struct userent *ue;
+ struct userent ukey;
+ struct groupent *ge;
+ gid_t pw_gid;
+ char *bp, *cp;
+ char *p;
+ const char *errstr = NULL;
+ size_t len;
+
+ RB_FOREACH(ue, user_name_tree, env->sc_user_names_t) {
+ bp = cp = ue->ue_line;
+
+ /* name */
+ bp += strlen(bp) + 1;
+
+ /* password */
+ bp += strcspn(bp, ":") + 1;
+
+ /* uid */
+ bp += strcspn(bp, ":") + 1;
+
+ /* gid */
+ bp[strcspn(bp, ":")] = '\0';
+
+ pw_gid = (gid_t)strtonum(bp, 0, GID_MAX, &errstr);
+ if (errstr) {
+ log_warnx("main: failed to parse gid for uid: %d\n", ue->ue_uid);
+ return (-1);
+ }
+
+ /* bring gid column back to its proper state */
+ bp[strlen(bp)] = ':';
+
+ if ((ue->ue_netid_line = calloc(1, LINE_WIDTH)) == NULL) {
+ return (-1);
+ }
+
+ if (snprintf(ue->ue_netid_line, LINE_WIDTH-1, "%d:%d", ue->ue_uid, pw_gid) >= LINE_WIDTH) {
+
+ return (-1);
+ }
+
+ ue->ue_gid = pw_gid;
+ }
+
+ RB_FOREACH(ge, group_name_tree, env->sc_group_names_t) {
+ bp = cp = ge->ge_line;
+
+ /* name */
+ bp += strlen(bp) + 1;
+
+ /* password */
+ bp += strcspn(bp, ":") + 1;
+
+ /* gid */
+ bp += strcspn(bp, ":") + 1;
+
+ cp = bp;
+ if (*bp == '\0')
+ continue;
+ bp = cp;
+ for (;;) {
+ if (!(cp = strsep(&bp, ",")))
+ break;
+ ukey.ue_line = cp;
+ if ((ue = RB_FIND(user_name_tree, env->sc_user_names_t,
+ &ukey)) == NULL) {
+ /* User not found */
+ log_warnx("main: user: %s is referenced as a "
+ "group member, but can't be found in the "
+ "users map.\n", ukey.ue_line);
+ if (bp != NULL)
+ *(bp-1) = ',';
+ continue;
+ }
+ if (bp != NULL)
+ *(bp-1) = ',';
+
+ /* Make sure the new group doesn't equal to the main gid */
+ if (ge->ge_gid == ue->ue_gid)
+ continue;
+
+ len = strlen(ue->ue_netid_line);
+ p = ue->ue_netid_line + len;
+
+ if ((snprintf(p, LINE_WIDTH-len-1, ",%d",
+ ge->ge_gid)) >= (int)(LINE_WIDTH-len)) {
+ return (-1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+void
+main_end_update(struct env *env)
+{
+ struct userent *ue;
+ struct groupent *ge;
+
+ if (env->update_trashed)
+ return;
+
+ log_debug("updates are over, cleaning up trees now");
+
+ if (main_create_user_groups(env) == -1) {
+ main_trash_update(env);
+ return;
+ }
+
+ if (env->sc_user_names == NULL) {
+ env->sc_user_names = env->sc_user_names_t;
+ env->sc_user_lines = NULL;
+ env->sc_user_names_t = NULL;
+
+ env->sc_group_names = env->sc_group_names_t;
+ env->sc_group_lines = NULL;
+ env->sc_group_names_t = NULL;
+
+ flatten_entries(env);
+ goto make_uids;
+ }
+
+ /*
+ * clean previous tree.
+ */
+ while ((ue = RB_ROOT(env->sc_user_names)) != NULL) {
+ RB_REMOVE(user_name_tree, env->sc_user_names,
+ ue);
+ free(ue->ue_netid_line);
+ free(ue);
+ }
+ free(env->sc_user_names);
+ free(env->sc_user_lines);
+
+ env->sc_user_names = env->sc_user_names_t;
+ env->sc_user_lines = NULL;
+ env->sc_user_names_t = NULL;
+
+ while ((ge = RB_ROOT(env->sc_group_names)) != NULL) {
+ RB_REMOVE(group_name_tree,
+ env->sc_group_names, ge);
+ free(ge);
+ }
+ free(env->sc_group_names);
+ free(env->sc_group_lines);
+
+ env->sc_group_names = env->sc_group_names_t;
+ env->sc_group_lines = NULL;
+ env->sc_group_names_t = NULL;
+
+
+ flatten_entries(env);
+
+ /*
+ * trees are flat now. build up uid, gid and netid trees.
+ */
+
+make_uids:
+ RB_INIT(&env->sc_user_uids);
+ RB_INIT(&env->sc_group_gids);
+ RB_FOREACH(ue, user_name_tree, env->sc_user_names)
+ RB_INSERT(user_uid_tree,
+ &env->sc_user_uids, ue);
+ RB_FOREACH(ge, group_name_tree, env->sc_group_names)
+ RB_INSERT(group_gid_tree,
+ &env->sc_group_gids, ge);
+
+}
+
+void
+main_dispatch_client(int fd, short events, void *p)
+{
+ int n;
+ int shut = 0;
+ struct env *env = p;
+ struct imsgev *iev = env->sc_iev;
+ struct imsgbuf *ibuf = &iev->ibuf;
+ struct idm_req ir;
+ struct imsg imsg;
+
+ if ((events & (EV_READ | EV_WRITE)) == 0)
+ fatalx("unknown event");
+
+ if (events & EV_READ) {
+ if ((n = imsg_read(ibuf)) == -1)
+ fatal("imsg_read error");
+ if (n == 0)
+ shut = 1;
+ }
+ if (events & EV_WRITE) {
+ if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
+ fatal("msgbuf_write");
+ if (n == 0)
+ shut = 1;
+ goto done;
+ }
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ fatal("main_dispatch_client: imsg_get error");
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ case IMSG_START_UPDATE:
+ main_start_update(env);
+ break;
+ case IMSG_PW_ENTRY: {
+ struct userent *ue;
+ size_t len;
+
+ if (env->update_trashed)
+ break;
+
+ (void)memcpy(&ir, imsg.data, sizeof(ir));
+ if ((ue = calloc(1, sizeof(*ue))) == NULL ||
+ (ue->ue_line = strdup(ir.ir_line)) == NULL) {
+ /*
+ * should cancel tree update instead.
+ */
+ fatal("out of memory");
+ }
+ ue->ue_uid = ir.ir_key.ik_uid;
+ len = strlen(ue->ue_line) + 1;
+ ue->ue_line[strcspn(ue->ue_line, ":")] = '\0';
+ if (RB_INSERT(user_name_tree, env->sc_user_names_t,
+ ue) != NULL) { /* dup */
+ free(ue->ue_line);
+ free(ue);
+ } else
+ env->sc_user_line_len += len;
+ break;
+ }
+ case IMSG_GRP_ENTRY: {
+ struct groupent *ge;
+ size_t len;
+
+ if (env->update_trashed)
+ break;
+
+ (void)memcpy(&ir, imsg.data, sizeof(ir));
+ if ((ge = calloc(1, sizeof(*ge))) == NULL ||
+ (ge->ge_line = strdup(ir.ir_line)) == NULL) {
+ /*
+ * should cancel tree update instead.
+ */
+ fatal("out of memory");
+ }
+ ge->ge_gid = ir.ir_key.ik_gid;
+ len = strlen(ge->ge_line) + 1;
+ ge->ge_line[strcspn(ge->ge_line, ":")] = '\0';
+ if (RB_INSERT(group_name_tree, env->sc_group_names_t,
+ ge) != NULL) { /* dup */
+ free(ge->ge_line);
+ free(ge);
+ } else
+ env->sc_group_line_len += len;
+ break;
+ }
+ case IMSG_TRASH_UPDATE:
+ main_trash_update(env);
+ break;
+ case IMSG_END_UPDATE: {
+ main_end_update(env);
+ break;
+ }
+ default:
+ log_debug("main_dispatch_client: unexpected imsg %d",
+ imsg.hdr.type);
+ break;
+ }
+ imsg_free(&imsg);
+ }
+
+done:
+ if (!shut)
+ imsg_event_add(iev);
+ else {
+ log_debug("king bula sez: ran into dead pipe");
+ event_del(&iev->ev);
+ event_loopexit(NULL);
+ }
+}
+
+void
+main_configure_client(struct env *env)
+{
+ struct idm *idm;
+ struct imsgev *iev = env->sc_iev;
+
+ imsg_compose_event(iev, IMSG_CONF_START, 0, 0, -1, env, sizeof(*env));
+ TAILQ_FOREACH(idm, &env->sc_idms, idm_entry) {
+ imsg_compose_event(iev, IMSG_CONF_IDM, 0, 0, -1,
+ idm, sizeof(*idm));
+ }
+ imsg_compose_event(iev, IMSG_CONF_END, 0, 0, -1, NULL, 0);
+}
+
+void
+main_init_timer(int fd, short event, void *p)
+{
+ struct env *env = p;
+
+ main_configure_client(env);
+}
+
+void
+purge_config(struct env *env)
+{
+ struct idm *idm;
+
+ while ((idm = TAILQ_FIRST(&env->sc_idms)) != NULL) {
+ TAILQ_REMOVE(&env->sc_idms, idm, idm_entry);
+ free(idm);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c;
+ int debug;
+ struct passwd *pw;
+ struct env env;
+ struct event ev_sigint;
+ struct event ev_sigterm;
+ struct event ev_sigchld;
+ struct event ev_sighup;
+ struct event ev_timer;
+ struct timeval tv;
+
+ debug = 0;
+ ypldap_process = PROC_MAIN;
+
+ log_init(1);
+
+ while ((c = getopt(argc, argv, "dD:nf:v")) != -1) {
+ switch (c) {
+ case 'd':
+ debug = 2;
+ break;
+ case 'D':
+ if (cmdline_symset(optarg) < 0)
+ log_warnx("could not parse macro definition %s",
+ optarg);
+ break;
+ case 'n':
+ debug = 2;
+ opts |= YPLDAP_OPT_NOACTION;
+ break;
+ case 'f':
+ conffile = optarg;
+ break;
+ case 'v':
+ opts |= YPLDAP_OPT_VERBOSE;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc)
+ usage();
+
+ RB_INIT(&env.sc_user_uids);
+ RB_INIT(&env.sc_group_gids);
+
+ if (parse_config(&env, conffile, opts))
+ exit(1);
+ if (opts & YPLDAP_OPT_NOACTION) {
+ fprintf(stderr, "configuration OK\n");
+ exit(0);
+ }
+
+ if (geteuid())
+ errx(1, "need root privileges");
+
+ log_init(debug);
+
+ if (!debug) {
+ if (daemon(1, 0) == -1)
+ err(1, "failed to daemonize");
+ }
+
+ log_info("startup%s", (debug > 1)?" [debug mode]":"");
+
+ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, PF_UNSPEC,
+ pipe_main2client) == -1)
+ fatal("socketpair");
+
+ client_pid = ldapclient(pipe_main2client);
+
+ setproctitle("parent");
+ event_init();
+
+ signal_set(&ev_sigint, SIGINT, main_sig_handler, &env);
+ signal_set(&ev_sigterm, SIGTERM, main_sig_handler, &env);
+ signal_set(&ev_sighup, SIGHUP, main_sig_handler, &env);
+ signal_set(&ev_sigchld, SIGCHLD, main_sig_handler, &env);
+ signal_add(&ev_sigint, NULL);
+ signal_add(&ev_sigterm, NULL);
+ signal_add(&ev_sighup, NULL);
+ signal_add(&ev_sigchld, NULL);
+
+ close(pipe_main2client[1]);
+ if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL)
+ fatal(NULL);
+ imsg_init(&env.sc_iev->ibuf, pipe_main2client[0]);
+ env.sc_iev->handler = main_dispatch_client;
+
+ env.sc_iev->events = EV_READ;
+ env.sc_iev->data = &env;
+ event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events,
+ env.sc_iev->handler, &env);
+ event_add(&env.sc_iev->ev, NULL);
+
+ yp_init(&env);
+
+ if ((pw = getpwnam(YPLDAP_USER)) == NULL)
+ fatal("getpwnam");
+
+#ifndef DEBUG
+ if (setgroups(1, &pw->pw_gid) ||
+ setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
+ setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
+ fatal("cannot drop privileges");
+#else
+#warning disabling privilege revocation in debug mode
+#endif
+
+ bzero(&tv, sizeof(tv));
+ evtimer_set(&ev_timer, main_init_timer, &env);
+ evtimer_add(&ev_timer, &tv);
+
+ yp_enable_events();
+ event_dispatch();
+ main_shutdown();
+
+ return (0);
+}
+
+void
+imsg_event_add(struct imsgev *iev)
+{
+ if (iev->handler == NULL) {
+ imsg_flush(&iev->ibuf);
+ return;
+ }
+
+ iev->events = EV_READ;
+ if (iev->ibuf.w.queued)
+ iev->events |= EV_WRITE;
+
+ event_del(&iev->ev);
+ event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data);
+ event_add(&iev->ev, NULL);
+}
+
+int
+imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid,
+ pid_t pid, int fd, void *data, u_int16_t datalen)
+{
+ int ret;
+
+ if ((ret = imsg_compose(&iev->ibuf, type, peerid,
+ pid, fd, data, datalen)) != -1)
+ imsg_event_add(iev);
+ return (ret);
+}
diff --git a/usr.sbin/ypldap/ypldap.conf.5 b/usr.sbin/ypldap/ypldap.conf.5
new file mode 100644
index 0000000..5c22b3b
--- /dev/null
+++ b/usr.sbin/ypldap/ypldap.conf.5
@@ -0,0 +1,167 @@
+.\" $OpenBSD: ypldap.conf.5,v 1.19 2012/04/30 11:28:25 jmatthew Exp $
+.\" $FreeBSD$
+.\"
+.\" Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
+.\"
+.\" 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+.\"
+.Dd $Mdocdate: April 30 2012 $
+.Dt YPLDAP.CONF 5
+.Os
+.Sh NAME
+.Nm ypldap.conf
+.Nd LDAP YP map daemon configuration file
+.Sh DESCRIPTION
+The
+.Xr ypldap 8
+daemon provides YP maps using LDAP as a backend.
+.Sh SECTIONS
+The
+.Nm
+config file is divided into three main sections.
+.Bl -tag -width xxxx
+.It Sy Macros
+User-defined variables may be defined and used later, simplifying the
+configuration file.
+.It Sy Global Configuration
+Global settings for
+.Xr ypldap 8 .
+.It Sy Directories
+LDAP Directory specific parameters.
+.El
+.Sh MACROS
+Much like
+.Xr cpp 1
+or
+.Xr m4 1 ,
+macros can be defined that will later be expanded in context.
+Macro names must start with a letter, digit, or underscore,
+and may contain any of those characters.
+Macro names may not be reserved words (for example,
+.Ic domain ) .
+Macros are not expanded inside quotes.
+.Pp
+For example:
+.Bd -literal -offset indent
+
+fixed_gecos="Pulled from LDAP"
+
+fixed attribute gecos $fixed_gecos
+.Ed
+.Sh GLOBAL CONFIGURATION
+Global settings concern the main behaviour of the daemon.
+.Pp
+.Bl -tag -width Ds -compact
+.It domain Ar string
+Specify the name of the NIS domain
+.Nm
+will provide.
+.It interval Ar seconds
+Specify the interval in seconds at which the whole directory will be pulled
+from LDAP.
+.It provide map Ar string
+Specify a map that should be provided by
+.Nm
+The currently implemented maps are: passwd.byname, passwd.byuid,
+group.byname, group.bygid.
+.El
+.Sh DIRECTORIES
+Directories are used to describe the LDAP schema and help
+.Nm
+convert LDAP entries to
+.Xr passwd 5 ,
+.Xr master.passwd 5 ,
+and
+.Xr group 5
+lines.
+A directory declaration is of the following form:
+.Bd -literal -offset indent
+directory "some.host" {
+ # directives
+}
+.Ed
+.Pp
+Valid directives for directories are:
+.Bl -tag -width Ds
+.It Xo
+.Ic attribute Ar name Ic maps to Ar string
+.Xc
+Map the
+.Xr passwd 5 ,
+.Xr master.passwd 5 ,
+or
+.Xr group 5
+attribute to the LDAP attribute name supplied.
+.It Ic basedn Ar string
+Use the supplied search base as starting point for the directory search.
+.It Ic groupdn Ar string
+Use the supplied search base as starting point for the directory search for
+groups.
+If not supplied, the basedn value will be used.
+.It Ic bindcred Ar string
+Use the supplied credentials for simple authentication against the directory.
+.It Ic binddn Ar string
+Use the supplied Distinguished Name to bind to the directory.
+.It Ic fixed attribute Ar attribute string
+Do not retrieve the specified attribute from LDAP but
+instead set it unconditionally to the supplied value for
+every entry.
+.It Ic group filter Ar string
+Use the supplied LDAP filter to retrieve group entries.
+.It Xo
+.Ic list Ar name Ic maps to Ar string
+.Xc
+Map the
+.Xr passwd 5 ,
+.Xr master.passwd 5 ,
+or
+.Xr group 5
+attribute to the LDAP attribute name supplied.
+A list creates a comma separated list of all the LDAP attributes found.
+.Pp
+Valid attributes are:
+.Pp
+.Bl -tag -width groupmembers -offset indent -compact
+.It Ic name
+.It Ic passwd
+.It Ic uid
+.It Ic gid
+.It Ic gecos
+.It Ic home
+.It Ic shell
+.It Ic change
+.It Ic expire
+.It Ic class
+.It Ic groupname
+.It Ic grouppasswd
+.It Ic groupgid
+.It Ic groupmembers
+.El
+.It Ic passwd filter Ar string
+Use the supplied LDAP filter to retrieve password entries.
+.El
+.Sh FILES
+.Bl -tag -width "/etc/ypldap.conf" -compact
+.It Pa /etc/ypldap.conf
+.Xr ypldap 8
+configuration file.
+.El
+.Sh SEE ALSO
+.Xr ypbind 8 ,
+.Xr ypldap 8 ,
+.Xr ypserv 8
+.Sh HISTORY
+The
+.Nm
+file format first appeared in
+.Ox 4.4 .
diff --git a/usr.sbin/ypldap/ypldap.h b/usr.sbin/ypldap/ypldap.h
new file mode 100644
index 0000000..b5e5fc0
--- /dev/null
+++ b/usr.sbin/ypldap/ypldap.h
@@ -0,0 +1,222 @@
+/* $OpenBSD: ypldap.h,v 1.16 2015/01/16 06:40:22 deraadt Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <imsg.h>
+
+#define YPLDAP_USER "_ypldap"
+#define YPLDAP_CONF_FILE "/etc/ypldap.conf"
+#define DEFAULT_INTERVAL 600
+#define LINE_WIDTH 1024
+#define FILTER_WIDTH 128
+#define ATTR_WIDTH 32
+
+#define MAX_SERVERS_DNS 8
+
+enum imsg_type {
+ IMSG_NONE,
+ IMSG_CONF_START,
+ IMSG_CONF_IDM,
+ IMSG_CONF_END,
+ IMSG_START_UPDATE,
+ IMSG_END_UPDATE,
+ IMSG_TRASH_UPDATE,
+ IMSG_PW_ENTRY,
+ IMSG_GRP_ENTRY,
+ IMSG_HOST_DNS
+};
+
+struct ypldap_addr {
+ struct ypldap_addr *next;
+ struct sockaddr_storage ss;
+};
+
+enum {
+ PROC_MAIN,
+ PROC_CLIENT
+} ypldap_process;
+
+struct userent {
+ RB_ENTRY(userent) ue_name_node;
+ RB_ENTRY(userent) ue_uid_node;
+ uid_t ue_uid;
+ char *ue_line;
+ char *ue_netid_line;
+ gid_t ue_gid;
+};
+
+struct groupent {
+ RB_ENTRY(groupent) ge_name_node;
+ RB_ENTRY(groupent) ge_gid_node;
+ gid_t ge_gid;
+ char *ge_line;
+};
+
+enum client_state {
+ STATE_NONE,
+ STATE_DNS_INPROGRESS,
+ STATE_DNS_TEMPFAIL,
+ STATE_DNS_DONE,
+ STATE_LDAP_FAIL,
+ STATE_LDAP_DONE
+};
+
+/*
+ * beck, djm, dlg: pay attention to the struct name
+ */
+struct idm {
+ TAILQ_ENTRY(idm) idm_entry;
+ u_int32_t idm_id;
+ char idm_name[MAXHOSTNAMELEN];
+#define F_SSL 0x00100000
+#define F_CONFIGURING 0x00200000
+#define F_NEEDAUTH 0x00400000
+#define F_FIXED_ATTR(n) (1<<n)
+#define F_LIST(n) (1<<n)
+ enum client_state idm_state;
+ u_int32_t idm_flags; /* lower 20 reserved */
+ u_int32_t idm_list;
+ struct ypldap_addr *idm_addr;
+ in_port_t idm_port;
+ char idm_binddn[LINE_WIDTH];
+ char idm_bindcred[LINE_WIDTH];
+ char idm_basedn[LINE_WIDTH];
+ char idm_groupdn[LINE_WIDTH];
+#define FILTER_USER 1
+#define FILTER_GROUP 0
+ char idm_filters[2][FILTER_WIDTH];
+#define ATTR_NAME 0
+#define ATTR_PASSWD 1
+#define ATTR_UID 2
+#define ATTR_GID 3
+#define ATTR_CLASS 4
+#define ATTR_CHANGE 5
+#define ATTR_EXPIRE 6
+#define ATTR_GECOS 7
+#define ATTR_DIR 8
+#define ATTR_SHELL 9
+#define ATTR_GR_NAME 10
+#define ATTR_GR_PASSWD 11
+#define ATTR_GR_GID 12
+#define ATTR_GR_MEMBERS 13
+#define ATTR_MAX 10
+#define ATTR_GR_MIN 10
+#define ATTR_GR_MAX 14
+ char idm_attrs[14][ATTR_WIDTH];
+ struct env *idm_env;
+ struct event idm_ev;
+#ifdef SSL
+ struct ssl *idm_ssl;
+#endif
+};
+
+struct idm_req {
+ union {
+ uid_t ik_uid;
+ uid_t ik_gid;
+ } ir_key;
+ char ir_line[LINE_WIDTH];
+};
+
+struct imsgev {
+ struct imsgbuf ibuf;
+ void (*handler)(int, short, void *);
+ struct event ev;
+ void *data;
+ short events;
+};
+
+struct env {
+#define YPLDAP_OPT_VERBOSE 0x01
+#define YPLDAP_OPT_NOACTION 0x02
+ u_int8_t sc_opts;
+#define YPMAP_PASSWD_BYNAME 0x00000001
+#define YPMAP_PASSWD_BYUID 0x00000002
+#define YPMAP_MASTER_PASSWD_BYNAME 0x00000004
+#define YPMAP_MASTER_PASSWD_BYUID 0x00000008
+#define YPMAP_GROUP_BYNAME 0x00000010
+#define YPMAP_GROUP_BYGID 0x00000020
+#define YPMAP_NETID_BYNAME 0x00000040
+ u_int32_t sc_flags;
+
+ u_int32_t sc_maxid;
+
+ char sc_domainname[MAXHOSTNAMELEN];
+ struct timeval sc_conf_tv;
+ struct event sc_conf_ev;
+ TAILQ_HEAD(idm_list, idm) sc_idms;
+ struct imsgev *sc_iev;
+ struct imsgev *sc_iev_dns;
+
+ RB_HEAD(user_name_tree,userent) *sc_user_names;
+ RB_HEAD(user_uid_tree,userent) sc_user_uids;
+ RB_HEAD(group_name_tree,groupent)*sc_group_names;
+ RB_HEAD(group_gid_tree,groupent) sc_group_gids;
+ struct user_name_tree *sc_user_names_t;
+ struct group_name_tree *sc_group_names_t;
+ size_t sc_user_line_len;
+ size_t sc_group_line_len;
+ char *sc_user_lines;
+ char *sc_group_lines;
+
+ struct yp_data *sc_yp;
+
+ int update_trashed;
+};
+
+/* log.c */
+void log_init(int);
+void log_warn(const char *, ...);
+void log_warnx(const char *, ...);
+void log_info(const char *, ...);
+void log_debug(const char *, ...);
+void logit(int, const char *, ...);
+void vlog(int, const char *, va_list);
+__dead2 void fatal(const char *);
+__dead2 void fatalx(const char *);
+
+/* parse.y */
+int parse_config(struct env *, const char *, int);
+int cmdline_symset(char *);
+
+/* ldapclient.c */
+pid_t ldapclient(int []);
+
+/* ypldap.c */
+void purge_config(struct env *);
+void imsg_event_add(struct imsgev *);
+int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t,
+ pid_t, int, void *, u_int16_t);
+
+/* entries.c */
+void flatten_entries(struct env *);
+int userent_name_cmp(struct userent *, struct userent *);
+int userent_uid_cmp(struct userent *, struct userent *);
+int groupent_name_cmp(struct groupent *, struct groupent *);
+int groupent_gid_cmp(struct groupent *, struct groupent *);
+RB_PROTOTYPE( user_name_tree, userent, ue_name_node, userent_name_cmp);
+RB_PROTOTYPE( user_uid_tree, userent, ue_uid_node, userent_uid_cmp);
+RB_PROTOTYPE( group_name_tree, groupent, ge_name_node, groupent_name_cmp);
+RB_PROTOTYPE( group_gid_tree, groupent, ge_gid_node, groupent_gid_cmp);
+
+/* yp.c */
+void yp_init(struct env *);
+void yp_enable_events(void);
+
+/* ypldap_dns.c */
+pid_t ypldap_dns(int[2], struct passwd *);
diff --git a/usr.sbin/ypldap/ypldap_dns.c b/usr.sbin/ypldap/ypldap_dns.c
new file mode 100644
index 0000000..84836f1
--- /dev/null
+++ b/usr.sbin/ypldap/ypldap_dns.c
@@ -0,0 +1,254 @@
+/* $OpenBSD: ypldap_dns.c,v 1.8 2015/01/16 06:40:22 deraadt Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 2003-2008 Henning Brauer <henning@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, 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 <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/tree.h>
+#include <sys/queue.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <netdb.h>
+#include <pwd.h>
+#include <errno.h>
+#include <event.h>
+#include <resolv.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "ypldap.h"
+
+volatile sig_atomic_t quit_dns = 0;
+struct imsgev *iev_dns;
+
+void dns_dispatch_imsg(int, short, void *);
+void dns_sig_handler(int, short, void *);
+void dns_shutdown(void);
+int host_dns(const char *s, struct ypldap_addr **hn);
+
+void
+dns_sig_handler(int sig, short event, void *p)
+{
+ switch (sig) {
+ case SIGINT:
+ case SIGTERM:
+ dns_shutdown();
+ break;
+ default:
+ fatalx("unexpected signal");
+ }
+}
+
+void
+dns_shutdown(void)
+{
+ log_info("dns engine exiting");
+ _exit(0);
+}
+
+pid_t
+ypldap_dns(int pipe_ntp[2], struct passwd *pw)
+{
+ pid_t pid;
+ struct event ev_sigint;
+ struct event ev_sigterm;
+ struct event ev_sighup;
+ struct env env;
+
+ switch (pid = fork()) {
+ case -1:
+ fatal("cannot fork");
+ break;
+ case 0:
+ break;
+ default:
+ return (pid);
+ }
+
+ setproctitle("dns engine");
+ close(pipe_ntp[0]);
+
+ if (setgroups(1, &pw->pw_gid) ||
+ setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
+ setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
+ fatal("can't drop privileges");
+ endservent();
+
+ event_init();
+ signal_set(&ev_sigint, SIGINT, dns_sig_handler, NULL);
+ signal_set(&ev_sigterm, SIGTERM, dns_sig_handler, NULL);
+ signal_set(&ev_sighup, SIGHUP, dns_sig_handler, NULL);
+ signal_add(&ev_sigint, NULL);
+ signal_add(&ev_sigterm, NULL);
+ signal_add(&ev_sighup, NULL);
+
+ if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL)
+ fatal(NULL);
+
+ env.sc_iev->events = EV_READ;
+ env.sc_iev->data = &env;
+ imsg_init(&env.sc_iev->ibuf, pipe_ntp[1]);
+ env.sc_iev->handler = dns_dispatch_imsg;
+ event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events,
+ env.sc_iev->handler, &env);
+ event_add(&env.sc_iev->ev, NULL);
+
+ event_dispatch();
+ dns_shutdown();
+
+ return (0);
+}
+
+void
+dns_dispatch_imsg(int fd, short events, void *p)
+{
+ struct imsg imsg;
+ int n, cnt;
+ char *name;
+ struct ypldap_addr *h, *hn;
+ struct ibuf *buf;
+ struct env *env = p;
+ struct imsgev *iev = env->sc_iev;
+ struct imsgbuf *ibuf = &iev->ibuf;
+ int shut = 0;
+
+ if ((events & (EV_READ | EV_WRITE)) == 0)
+ fatalx("unknown event");
+
+ if (events & EV_READ) {
+ if ((n = imsg_read(ibuf)) == -1)
+ fatal("imsg_read error");
+ if (n == 0)
+ shut = 1;
+ }
+ if (events & EV_WRITE) {
+ if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
+ fatal("msgbuf_write");
+ if (n == 0)
+ shut = 1;
+ goto done;
+ }
+
+ for (;;) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ fatal("client_dispatch_imsg: imsg_get error");
+ if (n == 0)
+ break;
+
+ switch (imsg.hdr.type) {
+ case IMSG_HOST_DNS:
+ name = imsg.data;
+ if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE)
+ fatalx("invalid IMSG_HOST_DNS received");
+ imsg.hdr.len -= 1 + IMSG_HEADER_SIZE;
+ if (name[imsg.hdr.len] != '\0' ||
+ strlen(name) != imsg.hdr.len)
+ fatalx("invalid IMSG_HOST_DNS received");
+ if ((cnt = host_dns(name, &hn)) == -1)
+ break;
+ buf = imsg_create(ibuf, IMSG_HOST_DNS,
+ imsg.hdr.peerid, 0,
+ cnt * sizeof(struct sockaddr_storage));
+ if (buf == NULL)
+ break;
+ if (cnt > 0) {
+ h = hn;
+ while (h != NULL) {
+ imsg_add(buf, &h->ss, sizeof(h->ss));
+ hn = h->next;
+ free(h);
+ h = hn;
+ }
+ }
+
+ imsg_close(ibuf, buf);
+ break;
+ default:
+ break;
+ }
+ imsg_free(&imsg);
+ }
+
+done:
+ if (!shut)
+ imsg_event_add(iev);
+ else {
+ /* this pipe is dead, so remove the event handler */
+ event_del(&iev->ev);
+ event_loopexit(NULL);
+ }
+}
+
+int
+host_dns(const char *s, struct ypldap_addr **hn)
+{
+ struct addrinfo hints, *res0, *res;
+ int error, cnt = 0;
+ struct sockaddr_in *sa_in;
+ struct sockaddr_in6 *sa_in6;
+ struct ypldap_addr *h, *hh = NULL;
+
+ bzero(&hints, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
+ error = getaddrinfo(s, NULL, &hints, &res0);
+ if (error == EAI_AGAIN || error == EAI_NONAME)
+ return (0);
+ if (error) {
+ log_warnx("could not parse \"%s\": %s", s,
+ gai_strerror(error));
+ return (-1);
+ }
+
+ for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) {
+ if (res->ai_family != AF_INET &&
+ res->ai_family != AF_INET6)
+ continue;
+ if ((h = calloc(1, sizeof(struct ypldap_addr))) == NULL)
+ fatal(NULL);
+ h->ss.ss_family = res->ai_family;
+ if (res->ai_family == AF_INET) {
+ sa_in = (struct sockaddr_in *)&h->ss;
+ sa_in->sin_len = sizeof(struct sockaddr_in);
+ sa_in->sin_addr.s_addr = ((struct sockaddr_in *)
+ res->ai_addr)->sin_addr.s_addr;
+ } else {
+ sa_in6 = (struct sockaddr_in6 *)&h->ss;
+ sa_in6->sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&sa_in6->sin6_addr, &((struct sockaddr_in6 *)
+ res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
+ }
+
+ h->next = hh;
+ hh = h;
+ cnt++;
+ }
+ freeaddrinfo(res0);
+
+ *hn = hh;
+ return (cnt);
+}
OpenPOWER on IntegriCloud