diff --git a/MAINTAINERS b/MAINTAINERS index 16cc5f1d0424..b22accb39e4d 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 d9f01be97e47..cc48d208e35d 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 be5e9c760554..4e6978332cb4 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 18ed81b5789a..8c4ca72a6a23 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 f7c6735f9e33..621798275bb1 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 000000000000..4c4dbd5cf1a6 --- /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 fb6036f959ba..f02895c3d74f 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 44b5fdb7f2ec..2367ae67c254 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 int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md); diff --git a/etc/Makefile b/etc/Makefile index 4a4422d10610..ddb7769f9b7b 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 eb6822119571..3fced3017a1b 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 61bfbc69dedd..d59900f245a4 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 15798b215d17..7be335f0801c 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 .include diff --git a/lib/libpmc/pmc.h b/lib/libpmc/pmc.h index 81672d21d56c..f237285121f4 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 c828b21145f8..3b17e106e058 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -70,66 +70,26 @@ SUBDIR=adjkerntz \ tunefs \ umount -.if ${MK_ATM} != "no" -SUBDIR+= atm -.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 -.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_TESTS}+= tests .include diff --git a/secure/lib/libcrypto/Makefile.inc b/secure/lib/libcrypto/Makefile.inc index c791d79b893d..8f41603411b9 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 239d1e1b4a83..8a55ce5c5ec3 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 87ad24252f92..e850ff14e179 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 47ee71f539ca..bce645d94da0 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 \& \& 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 677cc4b29618..000000000000 --- 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 -\& -\& 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 47074f9a9210..6f48c016e6da 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 56a5607f5e55..4a75970b9a3f 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 similarity index 100% rename from share/ctypedef/en_GB.ISO8859-15.src rename to share/ctypedef/en_US.ISO8859-1.src diff --git a/share/locale-links/Makefile b/share/locale-links/Makefile index 20080eb674f6..d59cedf5fe42 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 c3c19d22d0a0..a989f953b265 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 833ac800d643..a790cbc3b978 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 4ec1a6b8adab..6b6f8477a309 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 12397a368bb2..2fb532c47d4c 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 similarity index 100% rename from share/monetdef/en_ZA.ISO8859-1.src rename to 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 similarity index 100% rename from share/monetdef/fr_CA.ISO8859-1.src rename to share/monetdef/fr_CA.ISO8859-15.src diff --git a/share/msgdef/Makefile b/share/msgdef/Makefile index a303dcc1073c..d6425daacb18 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 727fe339a9bb..222021620cc7 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 fbbe7e123ec3..dde32a26ee50 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 similarity index 100% rename from share/timedef/fr_CA.ISO8859-1.src rename to 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 a75574072548..fe446b90f610 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 2fba6a837416..c269b47a8be3 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 29078e955fbb..390758bb24ab 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 b1b7cd55745a..5fcb7af955ab 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 9234a641a705..66839377a4af 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 7d5a561e31cc..7dff914d6407 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 7aa9840881ba..912f015d899c 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 1dbd5a9f3285..100f7aaa8be6 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 346e22ee7abf..4938dda6a969 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 4926947c7da7..27f29524fdfa 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 024a54fc2aaf..7f46573e22a6 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 9b8ce725edb4..fed5a6e19bae 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) { + if (fcp->isp_loopstate < LOOP_FSCAN_DONE) { + return (-1); + } + if (fcp->isp_loopstate > LOOP_SYNCING_PDB) { 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); - 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); - } - } - } - - 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 0b9294fcb199..cb356fec62a9 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 fa1fa8fe666f..43e35104233d 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)); - } } @@ -2169,6 +2156,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) { @@ -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 2e575b27068c..1e5feefa2943 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 daa199cef5d4..315870e55364 100644 --- a/sys/dev/isp/isp_stds.h +++ b/sys/dev/isp/isp_stds.h @@ -138,6 +138,20 @@ typedef struct { uint32_t rftid_fc4types[8]; } 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 cf355016496d..f8b1930131c0 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(¬ify, 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 25b57d5b7ae6..b0d74a64025d 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 233c88c11925..0bf592f40cba 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 28f63056408c..8b392e951b09 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 24f3912ecc4c..220d6356f01f 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 7ed7e4cce832..d4f49300e546 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 22f91f57576b..246b3d4cd010 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 b2810a097273..ee0b37badb08 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 __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 5faf716acf4d..be249c9fcb51 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 ddf4a7d228e7..04e75f861e31 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 f2851eea65f9..6a351d831ec8 100644 --- a/sys/dev/xen/control/control.c +++ b/sys/dev/xen/control/control.c @@ -128,6 +128,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include #include @@ -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 b165b96776b1..14a4d1830e41 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 6aecd7892fa0..3e3ae8f3fa78 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 62c79419f83d..90b78951f468 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 b33247c51033..1fd2fdd3ace5 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 000000000000..296f0c84534e --- /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 000000000000..eb95d004d3b3 --- /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 000000000000..94c8a3375e0b --- /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 000000000000..d3a68695d72a --- /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 000000000000..ec2a46489d1a --- /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 000000000000..4bbb083e44fe --- /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 7b64cd1b0190..f5f608fb0465 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 bab26fe9411e..c9b276954a36 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 328e8a37eb78..c01e54fcd8f6 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 9927509a4524..01c589e86673 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, @@ -1208,6 +1208,29 @@ key_unlink(struct secpolicy *sp) KEY_FREESP(&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 9f645c0c4f55..c8b5f16417f1 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 083244d3590f..9db59a290f71 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 d58bc722e45d..adc171c7bb02 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 dfdd6f2acaf7..412f8161fd58 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 cb44bfad029a..3dee3664e0a4 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 3766d866e6ac..90cb4a326ad0 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 a601fcbcc30b..b2ca5ae37a67 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 658c4eb41527..0b47a632a446 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 e94a1d832b06..6608b4d520c7 100644 --- a/sys/powerpc/mpc85xx/mpc85xx.c +++ b/sys/powerpc/mpc85xx/mpc85xx.c @@ -27,6 +27,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_platform.h" #include #include #include @@ -45,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include + /* * 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 66e7ace98642..31adc58e565d 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 d7ec7fc5a88c..d085af9889b0 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 d9ea5c05d0a0..3a92acf4c2f0 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 246b8868e2bb..cde3c74ed78f 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 16b7575c75b3..b0cf020f4c15 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 004f8f0ade3c..765d94624cd0 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 7a60ba2a7c90..58da0b3307fd 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 9fc4541c0788..4544fefd2ab3 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 da9ea22d7cd1..513dc8eb5ff7 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 261f92b0d89e..ede23870f076 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", ®, sizeof(reg)); + OF_getencprop(node, "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 26dbcc07a215..04e359dd5704 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 9b638ef46c0c..0623aef9539c 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 b1fc948bf541..ba43783e7b77 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 5edbf6d50474..eab2ce26e421 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 90a7e6b46b09..9d8460cc485e 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 aee0f58cd88e..f1546603f6cf 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 * @@ -59,13 +58,6 @@ dumpsys_unmap_chunk(vm_paddr_t pa, size_t s, void *va) dumpsys_gen_unmap_chunk(pa, s, 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 1f28b6d3b5db..9cb1aabd132c 100644 --- a/sys/sparc64/sparc64/dump_machdep.c +++ b/sys/sparc64/sparc64/dump_machdep.c @@ -54,18 +54,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 6ed909bf143f..47662fab48d7 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 d81c9132dd8c..35ec99253be4 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 c969e262b956..a8b14fda4c5c 100644 --- a/sys/x86/xen/hvm.c +++ b/sys/x86/xen/hvm.c @@ -58,15 +58,8 @@ __FBSDID("$FreeBSD$"); #include /*--------------------------- 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 1c0ae3ae0f3c..a7b89fc7970f 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 694a7740cb00..1ef88ffce77c 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 c28bd89ef50e..e39f6ce8faec 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 f0552cacdcc5..0723dc3324e7 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 3d74b8d721bf..0b6551aee55f 100644 --- a/tools/tools/locale/etc/charmaps.xml +++ b/tools/tools/locale/etc/charmaps.xml @@ -28,7 +28,7 @@ --> @@ -60,7 +60,7 @@ encoding="ISO8859-1 ISO8859-15 US-ASCII" countries="GB" /> diff --git a/tools/tools/shlib-compat/shlib-compat.py b/tools/tools/shlib-compat/shlib-compat.py index ca6f036639d1..c0fb2d276811 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 f2f689d673cc..9b8ff70c5974 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 1d3927321f25..c1056b5ad7b6 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 4f003029477e..bda14c3ee5ba 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 +SUBDIR.${MK_AUDIT}+= 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}+= 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 +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 -.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_TESTS}+= tests .include diff --git a/usr.sbin/mpsutil/Makefile b/usr.sbin/mpsutil/Makefile index b559b7f64d0b..8ee4ec54dc59 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 2701773a8118..876243f9c04c 100644 --- a/usr.sbin/mpsutil/mps_cmd.c +++ b/usr.sbin/mpsutil/mps_cmd.c @@ -1,4 +1,6 @@ /*- + * Copyright (c) 2015 Baptiste Daroussin + * * Copyright (c) 2015 Netflix, Inc. * All rights reserved. * Written by: Scott Long @@ -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 000000000000..e22f29c7f829 --- /dev/null +++ b/usr.sbin/mpsutil/mps_flash.c @@ -0,0 +1,237 @@ +/*- + * Copyright (c) 2015 Baptiste Daroussin + * + * 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 +__RCSID("$FreeBSD$"); + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 7b6dae4da6d2..6634b3742c3a 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 dd6fc0b9581e..46c7d44a9f7f 100644 --- a/usr.sbin/mpsutil/mpsutil.h +++ b/usr.sbin/mpsutil/mpsutil.h @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -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 9ff78e845ccb..5fc9b41ef414 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 */ 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)); + if (args.pa_flags & FLAG_DO_WIDE_GPROF_HC) { + whc = (WIDEHISTCOUNTER *) ((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; + /* 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 25ff7a6d9ffd..bc4bb74fada5 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 914fc17d1f8e..81b0cd091a5c 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 29dfeb790fa2..5b1d3d916792 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 000000000000..1d3cabc39457 --- /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 diff --git a/usr.sbin/ypldap/aldap.c b/usr.sbin/ypldap/aldap.c new file mode 100644 index 000000000000..03e52248a122 --- /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 + * Copyright (c) 2006, 2007 Marc Balmer + * + * 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 +#include +#include +#include +#include + +#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: (%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, "\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, "\n"); + break; + } + fprintf(stderr, "value %lld\n", v); + break; + case BER_TYPE_ENUMERATED: + if (ber_get_enumerated(root, &v) == -1) { + fprintf(stderr, "\n"); + break; + } + fprintf(stderr, "value %lld\n", v); + break; + case BER_TYPE_BITSTRING: + if (ber_get_bitstring(root, (void *)&buf, &len) == -1) { + fprintf(stderr, "\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, "\n"); + break; + } + fprintf(stderr, "\n"); + break; + case BER_TYPE_OCTETSTRING: + if (ber_get_nstring(root, (void *)&buf, &len) == -1) { + fprintf(stderr, "\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 000000000000..cdf5316e8328 --- /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 + * Copyright (c) 2006, 2007 Marc Balmer + * + * 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 +#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 000000000000..a2950dc88462 --- /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 + * Copyright (c) 2006, 2007 Claudio Jeker + * Copyright (c) 2006, 2007 Marc Balmer + * + * 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 + +#include +#include +#include +#include /* XXX for debug output */ +#include /* XXX for debug output */ +#include +#include +#include +#include + +#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 000000000000..eec02d4ac1b4 --- /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 + * Copyright (c) 2006, 2007 Claudio Jeker + * + * 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 000000000000..1adce5a77a97 --- /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 + * + * 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 +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 000000000000..897ceb2b090d --- /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 + * Copyright (c) 2008 Pierre-Yves Ritschard + * + * 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 +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(¶ms, imsg.data, sizeof(params)); + log_debug("configuration starting"); + env->sc_flags |= F_CONFIGURING; + purge_config(env); + memcpy(&env->sc_conf_tv, ¶ms.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 000000000000..7fec6f7427b7 --- /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 + * + * 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 + +#include +#include +#include +#include +#include +#include +#include + +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 000000000000..15d3ff202320 --- /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 + * Copyright (c) 2007, 2008 Reyk Floeter + * Copyright (c) 2004, 2005 Esben Norby + * Copyright (c) 2004 Ryan McBride + * Copyright (c) 2002, 2003, 2004 Henning Brauer + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 STRING +%token NUMBER +%type opcode attribute +%type 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 000000000000..e46113636d44 --- /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 + * + * 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 +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 000000000000..2974e245f973 --- /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 +.\" +.\" 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 000000000000..ad7209a53383 --- /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 + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 000000000000..5c22b3ba51cc --- /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 +.\" +.\" 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 000000000000..b5e5fc0f367b --- /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 + * + * 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 + +#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< + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); +}