Merge from head

This commit is contained in:
Baptiste Daroussin 2015-10-19 11:51:10 +00:00
commit 031c294c1d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/collation/; revision=289573
634 changed files with 42534 additions and 11579 deletions

View file

@ -243,14 +243,8 @@ cleanworld:
# Handle the user-driven targets, using the source relative mk files.
#
.if !(!empty(.MAKEFLAGS:M-n) && ${.MAKEFLAGS:M-n} == "-n")
# skip this for -n to avoid changing previous behavior of
# 'make -n buildworld' etc. Using -n -n will run it.
${TGTS}: .MAKE
tinderbox toolchains kernel-toolchains: .MAKE
.endif
${TGTS}:
${TGTS}: .PHONY .MAKE
${_+_}@cd ${.CURDIR}; ${_MAKE} ${.TARGET}
# The historic default "all" target creates files which may cause stale
@ -259,9 +253,9 @@ ${TGTS}:
# if they want the historic behavior.
.MAIN: _guard
_guard:
_guard: .PHONY
@echo
@echo "Explicit target required (use \"all\" for historic behavior)"
@echo "Explicit target required. Likely \"${SUBDIR_OVERRIDE:Dall:Ubuildworld}\" is wanted. See build(7)."
@echo
@false

View file

@ -50,16 +50,23 @@
.include <bsd.arch.inc.mk>
.include <bsd.compiler.mk>
# We must do lib/ and libexec/ before bin/, because if installworld
# installs a new /bin/sh, the 'make' command will *immediately*
# use that new version. And the new (dynamically-linked) /bin/sh
# will expect to find appropriate libraries in /lib and /libexec.
#
# We must do lib/ and libexec/ before bin/ in case of a mid-install error to
# keep the users system reasonably usable. For static->dynamic root upgrades,
# we don't want to install a dynamic binary without rtld and the needed
# libraries. More commonly, for dynamic root, we don't want to install a
# binary that requires a newer library version that hasn't been installed yet.
# This ordering is not a guarantee though. The only guarantee of a working
# system here would require fine-grained ordering of all components based
# on their dependencies.
SRCDIR?= ${.CURDIR}
.if defined(SUBDIR_OVERRIDE)
SUBDIR= ${SUBDIR_OVERRIDE}
.else
SUBDIR= lib libexec
.if make(install*)
# Ensure libraries are installed before progressing.
SUBDIR+=.WAIT
.endif
SUBDIR+=bin
.if ${MK_CDDL} != "no"
SUBDIR+=cddl
@ -85,10 +92,6 @@ SUBDIR+= tests
.if ${MK_OFED} != "no"
SUBDIR+=contrib/ofed
.endif
#
# We must do etc/ last for install/distribute to work.
#
SUBDIR+=etc
# Local directories are last, since it is nice to at least get the base
# system rebuilt before you do them.
@ -112,6 +115,15 @@ SUBDIR+= ${_DIR}
.endfor
.endif
# We must do etc/ last as it hooks into building the man whatis file
# by calling 'makedb' in share/man. This is only relevant for
# install/distribute so they build the whatis file after every manpage is
# installed.
.if make(install*)
SUBDIR+=.WAIT
.endif
SUBDIR+=etc
.if defined(NOCLEAN)
NO_CLEAN= ${NOCLEAN}
.endif
@ -136,14 +148,17 @@ OSRELDATE!= awk '/^\#define[[:space:]]*__FreeBSD_version/ { print $$3 }' \
.else
OSRELDATE= 0
.endif
.export OSRELDATE
.endif
# Set VERSION for CTFMERGE to use via the default CTFFLAGS=-L VERSION.
.if !defined(VERSION)
REVISION!= ${MAKE} -C ${SRCDIR}/release -V REVISION
BRANCH!= ${MAKE} -C ${SRCDIR}/release -V BRANCH
SRCRELDATE!= awk '/^\#define[[:space:]]*__FreeBSD_version/ { print $$3 }' \
${SRCDIR}/sys/sys/param.h
VERSION= FreeBSD ${REVISION}-${BRANCH:C/-p[0-9]+$//} ${TARGET_ARCH} ${SRCRELDATE}
.export VERSION
.endif
KNOWN_ARCHES?= aarch64/arm64 amd64 arm armeb/arm armv6/arm armv6hf/arm i386 i386/pc98 mips mipsel/mips mips64el/mips mips64/mips mipsn32el/mips mipsn32/mips powerpc powerpc64/powerpc sparc64
@ -252,7 +267,6 @@ CROSSENV+= ${TARGET_CFLAGS}
BMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${BPATH}:${PATH} \
WORLDTMP=${WORLDTMP} \
VERSION="${VERSION}" \
MAKEFLAGS="-m ${.CURDIR}/tools/build/mk ${.MAKEFLAGS}"
# need to keep this in sync with targets/pseudo/bootstrap-tools/Makefile
BSARGS= DESTDIR= \
@ -289,8 +303,7 @@ XMAKE= TOOLS_PREFIX=${WORLDTMP} ${BMAKE} \
# kernel-tools stage
KTMAKEENV= INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${BPATH}:${PATH} \
WORLDTMP=${WORLDTMP} \
VERSION="${VERSION}"
WORLDTMP=${WORLDTMP}
KTMAKE= TOOLS_PREFIX=${WORLDTMP} MAKEOBJDIRPREFIX=${WORLDTMP} \
${KTMAKEENV} ${MAKE} ${WORLD_FLAGS} -f Makefile.inc1 \
DESTDIR= \
@ -303,7 +316,6 @@ KTMAKE= TOOLS_PREFIX=${WORLDTMP} MAKEOBJDIRPREFIX=${WORLDTMP} \
# world stage
WMAKEENV= ${CROSSENV} \
_LDSCRIPTROOT= \
VERSION="${VERSION}" \
INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${TMPPATH}
@ -313,10 +325,6 @@ HMAKE= PATH=${TMPPATH} ${MAKE} LOCAL_MTREE=${LOCAL_MTREE:Q}
HMAKE+= PATH=${TMPPATH} METALOG=${METALOG} -DNO_ROOT
.endif
.if ${MK_CDDL} == "no"
WMAKEENV+= MK_CTF=no
.endif
.if defined(CROSS_TOOLCHAIN)
LOCALBASE?= /usr/local
.include "${LOCALBASE}/share/toolchains/${CROSS_TOOLCHAIN}.mk"
@ -446,7 +454,6 @@ LIB32FLAGS+= --sysroot=${WORLDTMP}
# Yes, the flags are redundant.
LIB32WMAKEENV+= MAKEOBJDIRPREFIX=${LIB32_OBJTREE} \
_LDSCRIPTROOT=${LIB32TMP} \
VERSION="${VERSION}" \
INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${TMPPATH} \
LIBDIR=/usr/lib32 \
@ -557,6 +564,11 @@ _worldtmp:
mkdir -p ${WORLDTMP}${TESTSBASE}
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
-p ${WORLDTMP}${TESTSBASE} >/dev/null
.if ${MK_DEBUG_FILES} != "no"
mkdir -p ${WORLDTMP}/usr/lib/debug/${TESTSBASE}
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
-p ${WORLDTMP}/usr/lib/debug/${TESTSBASE} >/dev/null
.endif
.endif
.for _mtree in ${LOCAL_MTREE}
mtree -deU -f ${.CURDIR}/${_mtree} -p ${WORLDTMP} > /dev/null
@ -579,9 +591,9 @@ _cleanobj:
@echo "--------------------------------------------------------------"
@echo ">>> stage 2.1: cleaning up the object tree"
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; ${WMAKE} ${CLEANDIR:S/^/par-/}
${_+_}cd ${.CURDIR}; ${WMAKE} ${CLEANDIR}
.if defined(LIB32TMP)
${_+_}cd ${.CURDIR}; ${LIB32WMAKE} -f Makefile.inc1 ${CLEANDIR:S/^/par-/}
${_+_}cd ${.CURDIR}; ${LIB32WMAKE} -f Makefile.inc1 ${CLEANDIR}
.endif
.endif
_obj:
@ -589,7 +601,7 @@ _obj:
@echo "--------------------------------------------------------------"
@echo ">>> stage 2.2: rebuilding the object tree"
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; ${WMAKE} par-obj
${_+_}cd ${.CURDIR}; ${WMAKE} obj
_build-tools:
@echo
@echo "--------------------------------------------------------------"
@ -608,7 +620,8 @@ _includes:
@echo "--------------------------------------------------------------"
@echo ">>> stage 4.1: building includes"
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; ${WMAKE} SHARED=symlinks par-includes
${_+_}cd ${.CURDIR}; ${WMAKE} SHARED=symlinks buildincludes
${_+_}cd ${.CURDIR}; ${WMAKE} SHARED=symlinks installincludes
_libraries:
@echo
@echo "--------------------------------------------------------------"
@ -622,7 +635,7 @@ _depend:
@echo "--------------------------------------------------------------"
@echo ">>> stage 4.3: make dependencies"
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; ${WMAKE} par-depend
${_+_}cd ${.CURDIR}; ${WMAKE} depend
everything:
@echo
@echo "--------------------------------------------------------------"
@ -731,7 +744,7 @@ buildworld_epilogue:
# to quote multiword values.
#
buildenvvars:
@echo ${WMAKEENV:Q}
@echo ${WMAKEENV:Q} ${.MAKE.EXPORTED:@v@$v=\"${$v}\"@}
.if ${.TARGETS:Mbuildenv}
.if ${.MAKEFLAGS:M-j}
@ -815,7 +828,7 @@ _zoneinfo= zic tzsetup
ITOOLS= [ awk cap_mkdb cat chflags chmod chown cmp cp \
date echo egrep find grep id install ${_install-info} \
ln lockf make mkdir mtree mv pwd_mkdb \
ln make mkdir mtree mv pwd_mkdb \
rm sed services_mkdb sh strip sysctl test true uname wc ${_zoneinfo} \
${LOCAL_ITOOLS}
@ -892,6 +905,10 @@ distributeworld installworld: _installcheck_world
-mkdir -p ${DESTDIR}/${DISTDIR}/${dist}${TESTSBASE}
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
-p ${DESTDIR}/${DISTDIR}/${dist}${TESTSBASE} >/dev/null
.if ${MK_DEBUG_FILES} != "no"
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.tests.dist \
-p ${DESTDIR}/${DISTDIR}/${dist}/usr/lib/debug/${TESTSBASE} >/dev/null
.endif
.endif
.if defined(NO_ROOT)
${IMAKEENV} mtree -C -f ${.CURDIR}/etc/mtree/BSD.root.dist | \
@ -1054,7 +1071,7 @@ INSTALLKERNEL= ${_kernel}
.endif
.endfor
buildkernel ${WMAKE_TGTS} ${.ALLTARGETS:M_*}: .MAKE
buildkernel ${WMAKE_TGTS:N_worldtmp:Nbuild32} ${.ALLTARGETS:M_*:N_worldtmp}: .MAKE .PHONY
#
# buildkernel
@ -1485,7 +1502,7 @@ build-tools: .MAKE
#
# kernel-tools: Build kernel-building tools
#
kernel-tools: .MAKE
kernel-tools:
mkdir -p ${MAKEOBJDIRPREFIX}/usr
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
-p ${MAKEOBJDIRPREFIX}/usr >/dev/null
@ -1566,7 +1583,6 @@ cross-tools: .MAKE
NXBENV= MAKEOBJDIRPREFIX=${OBJTREE}/nxb \
INSTALL="sh ${.CURDIR}/tools/install.sh" \
VERSION="${VERSION}" \
PATH=${PATH}:${OBJTREE}/gperf_for_gcc/usr/bin
NXBMAKE= ${NXBENV} ${MAKE} \
TBLGEN=${OBJTREE}/nxb-bin/usr/bin/tblgen \
@ -1585,7 +1601,7 @@ NXBMAKE= ${NXBENV} ${MAKE} \
# For non-clang enabled targets that are still using the in tree gcc
# we must build a gperf binary for one instance of its Makefiles. On
# clang-enabled systems, the gperf binary is obsolete.
native-xtools: .MAKE
native-xtools:
.if ${MK_GCC_BOOTSTRAP} != "no"
mkdir -p ${OBJTREE}/gperf_for_gcc/usr/bin
${_+_}@${ECHODIR} "===> ${_gperf} (obj,depend,all,install)"; \
@ -1931,22 +1947,18 @@ _startup_libs: ${_startup_libs:S/$/__L/}
_prebuild_libs: ${_prebuild_libs:S/$/__L/}
_generic_libs: ${_generic_libs:S/$/__L/}
.for __target in all clean cleandepend cleandir depend includes obj
.for entry in ${SUBDIR}
${entry}.${__target}__D: .PHONY .MAKE
${_+_}@set -e; if test -d ${.CURDIR}/${entry}.${MACHINE_ARCH}; then \
${ECHODIR} "===> ${DIRPRFX}${entry}.${MACHINE_ARCH} (${__target})"; \
edir=${entry}.${MACHINE_ARCH}; \
cd ${.CURDIR}/$${edir}; \
else \
${ECHODIR} "===> ${DIRPRFX}${entry} (${__target})"; \
edir=${entry}; \
cd ${.CURDIR}/$${edir}; \
fi; \
${MAKE} ${__target} DIRPRFX=${DIRPRFX}$${edir}/
.endfor
par-${__target}: ${SUBDIR:S/$/.${__target}__D/}
.endfor
# Enable SUBDIR_PARALLEL when not calling 'make all', unless called as
# 'par-all'. This is because it is unlikely that running 'make all' from
# the top-level, especially with a SUBDIR_OVERRIDE or LOCAL_DIRS set,
# will have a reliable build if SUBDIRs are built in parallel. This is
# safe for the world stage of buildworld though since it has already
# built libraries in a proper order and installed includes into WORLDTMP.
# Special handling is done for SUBDIR ordering for 'install*' to avoid
# trashing a system if it crashes mid-install.
par-all: all .PHONY
.if !make(all)
SUBDIR_PARALLEL=
.endif
.include <bsd.subdir.mk>
@ -1988,6 +2000,13 @@ delete-old-files:
chflags noschg "${DESTDIR}/$${file}" 2>/dev/null || true; \
rm ${RM_I} "${DESTDIR}/$${file}" <&3; \
fi; \
for ext in debug symbols; do \
if ! [ -e "${DESTDIR}/$${file}" ] && [ -f \
"${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" ]; then \
rm ${RM_I} "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" \
<&3; \
fi; \
done; \
done
# Remove catpages without corresponding manpages.
@exec 3<&0; \
@ -2010,6 +2029,11 @@ check-old-files:
if [ -f "${DESTDIR}/$${file}" -o -L "${DESTDIR}/$${file}" ]; then \
echo "${DESTDIR}/$${file}"; \
fi; \
for ext in debug symbols; do \
if [ -f "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}" ]; then \
echo "${DESTDIR}${DEBUGDIR}/$${file}.$${ext}"; \
fi; \
done; \
done
# Check for catpages without corresponding manpages.
@find ${DESTDIR}/usr/share/man/cat* ! -type d | \
@ -2242,7 +2266,9 @@ _xi-cross-tools:
.endfor
_xi-includes:
${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 par-includes \
${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 buildincludes \
DESTDIR=${XDDESTDIR}
${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 installincludes \
DESTDIR=${XDDESTDIR}
_xi-libraries:

View file

@ -97,6 +97,410 @@ OLD_FILES+=usr/bin/colldef
OLD_FILES+=usr/share/man/man1/colldef.1.gz
OLD_FILES+=usr/bin/mklocale
OLD_FILES+=usr/share/man/man1/mklocale.1.gz
# 20151015: test symbols moved to /usr/lib/debug
OLD_DIRS+=usr/tests/lib/atf/libatf-c++/.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/.debug/atf_c++_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/.debug/build_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/.debug/check_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/.debug/config_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/.debug/macros_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/.debug/tests_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/.debug/utils_test.debug
OLD_DIRS+=usr/tests/lib/atf/libatf-c++/detail/.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/.debug/application_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/.debug/env_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/.debug/exceptions_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/.debug/fs_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/.debug/process_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/.debug/sanity_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/.debug/text_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c++/detail/.debug/version_helper.debug
OLD_DIRS+=usr/tests/lib/atf/libatf-c/.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/.debug/atf_c_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/.debug/build_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/.debug/check_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/.debug/config_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/.debug/error_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/.debug/macros_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/.debug/tc_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/.debug/tp_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/.debug/utils_test.debug
OLD_DIRS+=usr/tests/lib/atf/libatf-c/detail/.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/dynstr_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/env_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/fs_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/list_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/map_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/process_helpers.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/process_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/sanity_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/text_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/user_test.debug
OLD_FILES+=usr/tests/lib/atf/libatf-c/detail/.debug/version_helper.debug
OLD_DIRS+=usr/tests/lib/atf/test-programs/.debug
OLD_FILES+=usr/tests/lib/atf/test-programs/.debug/c_helpers.debug
OLD_FILES+=usr/tests/lib/atf/test-programs/.debug/cpp_helpers.debug
OLD_DIRS+=usr/tests/lib/libc/c063/.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/faccessat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/fchmodat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/fchownat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/fexecve.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/fstatat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/linkat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/mkdirat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/mkfifoat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/mknodat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/openat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/readlinkat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/renameat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/symlinkat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/unlinkat.debug
OLD_FILES+=usr/tests/lib/libc/c063/.debug/utimensat.debug
OLD_DIRS+=usr/tests/lib/libc/db/.debug
OLD_FILES+=usr/tests/lib/libc/db/.debug/h_db.debug
OLD_DIRS+=usr/tests/lib/libc/gen/.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/alarm_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/arc4random_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/assert_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/basedirname_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/dir_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/floatunditf_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/fnmatch_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/fpclassify2_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/fpclassify_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/fpsetmask_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/fpsetround_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/ftok_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/getcwd_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/getgrent_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/glob_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/humanize_number_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/isnan_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/nice_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/pause_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/raise_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/realpath_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/setdomainname_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/sethostname_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/sleep_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/syslog_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/time_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/ttyname_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/.debug/vis_test.debug
OLD_DIRS+=usr/tests/lib/libc/gen/execve/.debug
OLD_FILES+=usr/tests/lib/libc/gen/execve/.debug/execve_test.debug
OLD_DIRS+=usr/tests/lib/libc/gen/posix_spawn/.debug
OLD_FILES+=usr/tests/lib/libc/gen/posix_spawn/.debug/fileactions_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/posix_spawn/.debug/h_fileactions.debug
OLD_FILES+=usr/tests/lib/libc/gen/posix_spawn/.debug/h_spawn.debug
OLD_FILES+=usr/tests/lib/libc/gen/posix_spawn/.debug/h_spawnattr.debug
OLD_FILES+=usr/tests/lib/libc/gen/posix_spawn/.debug/spawn_test.debug
OLD_FILES+=usr/tests/lib/libc/gen/posix_spawn/.debug/spawnattr_test.debug
OLD_DIRS+=usr/tests/lib/libc/hash/.debug
OLD_FILES+=usr/tests/lib/libc/hash/.debug/h_hash.debug
OLD_FILES+=usr/tests/lib/libc/hash/.debug/sha2_test.debug
OLD_DIRS+=usr/tests/lib/libc/inet/.debug
OLD_FILES+=usr/tests/lib/libc/inet/.debug/inet_network_test.debug
OLD_DIRS+=usr/tests/lib/libc/locale/.debug
OLD_FILES+=usr/tests/lib/libc/locale/.debug/io_test.debug
OLD_FILES+=usr/tests/lib/libc/locale/.debug/mbrtowc_test.debug
OLD_FILES+=usr/tests/lib/libc/locale/.debug/mbsnrtowcs_test.debug
OLD_FILES+=usr/tests/lib/libc/locale/.debug/mbstowcs_test.debug
OLD_FILES+=usr/tests/lib/libc/locale/.debug/mbtowc_test.debug
OLD_FILES+=usr/tests/lib/libc/locale/.debug/wcscspn_test.debug
OLD_FILES+=usr/tests/lib/libc/locale/.debug/wcspbrk_test.debug
OLD_FILES+=usr/tests/lib/libc/locale/.debug/wcsspn_test.debug
OLD_FILES+=usr/tests/lib/libc/locale/.debug/wcstod_test.debug
OLD_FILES+=usr/tests/lib/libc/locale/.debug/wctomb_test.debug
OLD_DIRS+=usr/tests/lib/libc/net/.debug
OLD_FILES+=usr/tests/lib/libc/net/.debug/ether_aton_test.debug
OLD_FILES+=usr/tests/lib/libc/net/.debug/getprotoent_test.debug
OLD_FILES+=usr/tests/lib/libc/net/.debug/h_dns_server.debug
OLD_FILES+=usr/tests/lib/libc/net/.debug/h_nsd_recurse.debug
OLD_FILES+=usr/tests/lib/libc/net/.debug/h_protoent.debug
OLD_FILES+=usr/tests/lib/libc/net/.debug/h_servent.debug
OLD_DIRS+=usr/tests/lib/libc/regex/.debug
OLD_FILES+=usr/tests/lib/libc/regex/.debug/exhaust_test.debug
OLD_FILES+=usr/tests/lib/libc/regex/.debug/h_regex.debug
OLD_FILES+=usr/tests/lib/libc/regex/.debug/regex_att_test.debug
OLD_DIRS+=usr/tests/lib/libc/ssp/.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_fgets.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_getcwd.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_gets.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_memcpy.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_memmove.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_memset.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_raw.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_read.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_readlink.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_snprintf.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_sprintf.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_stpcpy.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_stpncpy.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_strcat.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_strcpy.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_strncat.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_strncpy.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_vsnprintf.debug
OLD_FILES+=usr/tests/lib/libc/ssp/.debug/h_vsprintf.debug
OLD_DIRS+=usr/tests/lib/libc/stdio/.debug
OLD_FILES+=usr/tests/lib/libc/stdio/.debug/clearerr_test.debug
OLD_FILES+=usr/tests/lib/libc/stdio/.debug/fflush_test.debug
OLD_FILES+=usr/tests/lib/libc/stdio/.debug/fmemopen2_test.debug
OLD_FILES+=usr/tests/lib/libc/stdio/.debug/fmemopen_test.debug
OLD_FILES+=usr/tests/lib/libc/stdio/.debug/fopen_test.debug
OLD_FILES+=usr/tests/lib/libc/stdio/.debug/fputc_test.debug
OLD_FILES+=usr/tests/lib/libc/stdio/.debug/mktemp_test.debug
OLD_FILES+=usr/tests/lib/libc/stdio/.debug/popen_test.debug
OLD_FILES+=usr/tests/lib/libc/stdio/.debug/printf_test.debug
OLD_FILES+=usr/tests/lib/libc/stdio/.debug/scanf_test.debug
OLD_DIRS+=usr/tests/lib/libc/stdlib/.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/abs_test.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/atoi_test.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/div_test.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/exit_test.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/getenv_test.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/h_getopt.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/h_getopt_long.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/hsearch_test.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/posix_memalign_test.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/random_test.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/strtod_test.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/strtol_test.debug
OLD_FILES+=usr/tests/lib/libc/stdlib/.debug/system_test.debug
OLD_DIRS+=usr/tests/lib/libc/string/.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/memchr.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/memcpy.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/memmem.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/memset.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/strcat.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/strchr.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/strcmp.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/strcpy.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/strcspn.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/strerror.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/strlen.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/strpbrk.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/strrchr.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/strspn.debug
OLD_FILES+=usr/tests/lib/libc/string/.debug/swab.debug
OLD_DIRS+=usr/tests/lib/libc/sys/.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/access_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/chroot_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/clock_gettime_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/connect_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/dup_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/fsync_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/getcontext_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/getgroups_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/getitimer_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/getlogin_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/getpid_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/getrusage_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/getsid_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/gettimeofday_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/issetugid_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/kevent_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/kill_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/link_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/listen_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/mincore_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/mkdir_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/mkfifo_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/mknod_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/mlock_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/mmap_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/mprotect_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/msgctl_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/msgget_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/msgrcv_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/msgsnd_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/msync_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/nanosleep_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/pipe2_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/pipe_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/poll_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/revoke_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/select_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/setrlimit_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/setuid_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/sigaction_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/sigqueue_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/sigtimedwait_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/socketpair_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/stat_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/timer_create_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/truncate_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/ucontext_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/umask_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/unlink_test.debug
OLD_FILES+=usr/tests/lib/libc/sys/.debug/write_test.debug
OLD_DIRS+=usr/tests/lib/libc/termios/.debug
OLD_FILES+=usr/tests/lib/libc/termios/.debug/tcsetpgrp_test.debug
OLD_DIRS+=usr/tests/lib/libc/tls/.debug
OLD_FILES+=usr/tests/lib/libc/tls/.debug/h_tls_dlopen.so.debug
OLD_FILES+=usr/tests/lib/libc/tls/.debug/libh_tls_dynamic.so.1.debug
OLD_FILES+=usr/tests/lib/libc/tls/.debug/tls_dlopen_test.debug
OLD_FILES+=usr/tests/lib/libc/tls/.debug/tls_dynamic_test.debug
OLD_DIRS+=usr/tests/lib/libc/ttyio/.debug
OLD_FILES+=usr/tests/lib/libc/ttyio/.debug/ttyio_test.debug
OLD_DIRS+=usr/tests/lib/libcrypt/.debug
OLD_FILES+=usr/tests/lib/libcrypt/.debug/crypt_tests.debug
OLD_DIRS+=usr/tests/lib/libmp/.debug
OLD_FILES+=usr/tests/lib/libmp/.debug/legacy_test.debug
OLD_DIRS+=usr/tests/lib/libnv/.debug
OLD_FILES+=usr/tests/lib/libnv/.debug/dnv_tests.debug
OLD_FILES+=usr/tests/lib/libnv/.debug/nv_array_tests.debug
OLD_FILES+=usr/tests/lib/libnv/.debug/nv_tests.debug
OLD_FILES+=usr/tests/lib/libnv/.debug/nvlist_add_test.debug
OLD_FILES+=usr/tests/lib/libnv/.debug/nvlist_exists_test.debug
OLD_FILES+=usr/tests/lib/libnv/.debug/nvlist_free_test.debug
OLD_FILES+=usr/tests/lib/libnv/.debug/nvlist_get_test.debug
OLD_FILES+=usr/tests/lib/libnv/.debug/nvlist_move_test.debug
OLD_FILES+=usr/tests/lib/libnv/.debug/nvlist_send_recv_test.debug
OLD_DIRS+=usr/tests/lib/libpam/.debug
OLD_FILES+=usr/tests/lib/libpam/.debug/t_openpam_ctype.debug
OLD_FILES+=usr/tests/lib/libpam/.debug/t_openpam_readlinev.debug
OLD_FILES+=usr/tests/lib/libpam/.debug/t_openpam_readword.debug
OLD_DIRS+=usr/tests/lib/libproc/.debug
OLD_FILES+=usr/tests/lib/libproc/.debug/proc_test.debug
OLD_FILES+=usr/tests/lib/libproc/.debug/target_prog.debug
OLD_DIRS+=usr/tests/lib/librt/.debug
OLD_FILES+=usr/tests/lib/librt/.debug/sched_test.debug
OLD_FILES+=usr/tests/lib/librt/.debug/sem_test.debug
OLD_DIRS+=usr/tests/lib/libthr/.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/barrier_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/cond_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/condwait_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/detach_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/equal_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/fork_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/fpu_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/h_atexit.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/h_cancel.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/h_exit.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/h_resolv.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/join_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/kill_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/mutex_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/once_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/preempt_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/rwlock_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/sem_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/siglongjmp_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/sigmask_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/sigsuspend_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/sleep_test.debug
OLD_FILES+=usr/tests/lib/libthr/.debug/swapcontext_test.debug
OLD_DIRS+=usr/tests/lib/libthr/dlopen/.debug
OLD_FILES+=usr/tests/lib/libthr/dlopen/.debug/dlopen_test.debug
OLD_FILES+=usr/tests/lib/libthr/dlopen/.debug/h_pthread_dlopen.so.1.debug
OLD_FILES+=usr/tests/lib/libthr/dlopen/.debug/main_pthread_create_test.debug
OLD_DIRS+=usr/tests/lib/libutil/.debug
OLD_FILES+=usr/tests/lib/libutil/.debug/flopen_test.debug
OLD_FILES+=usr/tests/lib/libutil/.debug/grp_test.debug
OLD_FILES+=usr/tests/lib/libutil/.debug/humanize_number_test.debug
OLD_FILES+=usr/tests/lib/libutil/.debug/pidfile_test.debug
OLD_FILES+=usr/tests/lib/libutil/.debug/trimdomain-nodomain_test.debug
OLD_FILES+=usr/tests/lib/libutil/.debug/trimdomain_test.debug
OLD_DIRS+=usr/tests/lib/libxo/.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/libenc_test.so.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_01.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_02.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_03.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_04.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_05.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_06.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_07.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_08.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_09.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_10.debug
OLD_FILES+=usr/tests/lib/libxo/.debug/test_11.debug
OLD_DIRS+=usr/tests/lib/msun/.debug
OLD_FILES+=usr/tests/lib/msun/.debug/acos_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/asin_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/atan_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/cbrt_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/ceil_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/cos_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/cosh_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/erf_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/exp_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/fmod_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/infinity_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/ldexp_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/log_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/pow_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/precision_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/round_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/scalbn_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/sin_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/sinh_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/sqrt_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/tan_test.debug
OLD_FILES+=usr/tests/lib/msun/.debug/tanh_test.debug
OLD_DIRS+=usr/tests/libexec/rtld-elf/.debug
OLD_FILES+=usr/tests/libexec/rtld-elf/.debug/ld_library_pathfds.debug
OLD_FILES+=usr/tests/libexec/rtld-elf/.debug/libpythagoras.so.0.debug
OLD_FILES+=usr/tests/libexec/rtld-elf/.debug/target.debug
OLD_DIRS+=usr/tests/sbin/devd/.debug
OLD_FILES+=usr/tests/sbin/devd/.debug/client_test.debug
OLD_DIRS+=usr/tests/sbin/dhclient/.debug
OLD_FILES+=usr/tests/sbin/dhclient/.debug/option-domain-search_test.debug
OLD_DIRS+=usr/tests/share/examples/tests/atf/.debug
OLD_FILES+=usr/tests/share/examples/tests/atf/.debug/printf_test.debug
OLD_DIRS+=usr/tests/share/examples/tests/plain/.debug
OLD_FILES+=usr/tests/share/examples/tests/plain/.debug/printf_test.debug
OLD_DIRS+=usr/tests/sys/aio/.debug
OLD_FILES+=usr/tests/sys/aio/.debug/aio_kqueue_test.debug
OLD_FILES+=usr/tests/sys/aio/.debug/aio_test.debug
OLD_FILES+=usr/tests/sys/aio/.debug/lio_kqueue_test.debug
OLD_DIRS+=usr/tests/sys/fifo/.debug
OLD_FILES+=usr/tests/sys/fifo/.debug/fifo_create.debug
OLD_FILES+=usr/tests/sys/fifo/.debug/fifo_io.debug
OLD_FILES+=usr/tests/sys/fifo/.debug/fifo_misc.debug
OLD_FILES+=usr/tests/sys/fifo/.debug/fifo_open.debug
OLD_DIRS+=usr/tests/sys/file/.debug
OLD_FILES+=usr/tests/sys/file/.debug/closefrom_test.debug
OLD_FILES+=usr/tests/sys/file/.debug/dup_test.debug
OLD_FILES+=usr/tests/sys/file/.debug/fcntlflags_test.debug
OLD_FILES+=usr/tests/sys/file/.debug/flock_helper.debug
OLD_FILES+=usr/tests/sys/file/.debug/ftruncate_test.debug
OLD_FILES+=usr/tests/sys/file/.debug/newfileops_on_fork_test.debug
OLD_DIRS+=usr/tests/sys/kern/.debug
OLD_FILES+=usr/tests/sys/kern/.debug/kern_descrip_test.debug
OLD_FILES+=usr/tests/sys/kern/.debug/ptrace_test.debug
OLD_FILES+=usr/tests/sys/kern/.debug/unix_seqpacket_test.debug
OLD_DIRS+=usr/tests/sys/kern/execve/.debug
OLD_FILES+=usr/tests/sys/kern/execve/.debug/execve_helper.debug
OLD_FILES+=usr/tests/sys/kern/execve/.debug/good_aout.debug
OLD_DIRS+=usr/tests/sys/kqueue/.debug
OLD_FILES+=usr/tests/sys/kqueue/.debug/kqtest.debug
OLD_DIRS+=usr/tests/sys/mqueue/.debug
OLD_FILES+=usr/tests/sys/mqueue/.debug/mqtest1.debug
OLD_FILES+=usr/tests/sys/mqueue/.debug/mqtest2.debug
OLD_FILES+=usr/tests/sys/mqueue/.debug/mqtest3.debug
OLD_FILES+=usr/tests/sys/mqueue/.debug/mqtest4.debug
OLD_FILES+=usr/tests/sys/mqueue/.debug/mqtest5.debug
OLD_DIRS+=usr/tests/sys/netinet/.debug
OLD_FILES+=usr/tests/sys/netinet/.debug/udp_dontroute.debug
OLD_DIRS+=usr/tests/sys/pjdfstest/.debug
OLD_FILES+=usr/tests/sys/pjdfstest/.debug/pjdfstest.debug
OLD_DIRS+=usr/tests/sys/vm/.debug
OLD_FILES+=usr/tests/sys/vm/.debug/mmap_test.debug
# 20151015: Rename files due to file-installed-as-dir bug
OLD_FILES+=usr/share/doc/legal/realtek
OLD_FILES+=usr/share/doc/legal/realtek/LICENSE
OLD_DIRS+=usr/share/doc/legal/realtek
OLD_DIRS+=usr/share/doc/legal/intel_ipw
OLD_FILES+=usr/share/doc/legal/intel_ipw/LICENSE
OLD_FILES+=usr/share/doc/legal/intel_iwn
OLD_FILES+=usr/share/doc/legal/intel_iwn/LICENSE
OLD_DIRS+=usr/share/doc/legal/intel_iwn
OLD_DIRS+=usr/share/doc/legal/intel_iwi
OLD_FILES+=usr/share/doc/legal/intel_iwi/LICENSE
OLD_DIRS+=usr/share/doc/legal/intel_wpi
OLD_FILES+=usr/share/doc/legal/intel_wpi/LICENSE
# 20151006: new libc++ import
OLD_FILES+=usr/include/c++/__tuple_03
# 20151006: new clang import which bumps version from 3.6.1 to 3.7.0.

View file

@ -31,6 +31,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
20151017:
The build previously allowed using 'make -n' to not recurse into
sub-directories while showing what commands would be executed, and
'make -n -n' to recursively show commands. Now 'make -n' will recurse
and 'make -N' will not.
20151012:
If you specify SENDMAIL_MC or SENDMAIL_CF in make.conf, mergemaster
and etcupdate will now use this file. A custom sendmail.cf is now

View file

@ -1,6 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 5/31/93
# $FreeBSD$
.include <src.opts.mk>
PROG= dd
SRCS= args.c conv.c conv_tab.c dd.c misc.c position.c
@ -24,4 +26,8 @@ test: ${PROG} gen
.endfor
@rm -f gen
.if ${MK_TESTS} != "no"
SUBDIR+= tests
.endif
.include <bsd.prog.mk>

7
bin/dd/tests/Makefile Normal file
View file

@ -0,0 +1,7 @@
# $FreeBSD$
NETBSD_ATF_TESTS_SH= dd_test
.include <netbsd-tests.test.mk>
.include <bsd.test.mk>

View file

@ -11,6 +11,6 @@ SRCS= fmt.c keyword.c nlist.c print.c ps.c
# on large systems.
#
CFLAGS+=-DLAZY_PS
LIBADD= m kvm jail xo util
LIBADD= m kvm jail xo
.include <bsd.prog.mk>

View file

@ -10,4 +10,6 @@ TESTS_SUBDIRS+= parameters
TESTS_SUBDIRS+= parser
TESTS_SUBDIRS+= set-e
SUBDIR_PARALLEL=
.include <bsd.test.mk>

View file

@ -2,7 +2,7 @@
#-
# Copyright (c) June 1996 Wolfram Schneider <wosch@FreeBSD.org>. Berlin.
# All rights reserved.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@ -31,7 +31,7 @@
# $FreeBSD$
# force a specified test program, e.g. `env test=/bin/test sh regress.sh'
: ${test=test}
: ${test=test}
t ()
{
@ -54,13 +54,13 @@ t ()
count=0
echo "1..130"
t 0 'b = b'
t 0 'b == b'
t 1 'b != b'
t 0 '\( b = b \)'
t 0 '\( b == b \)'
t 1 '! \( b = b \)'
t 1 '! \( b == b \)'
t 0 'b = b'
t 0 'b == b'
t 1 'b != b'
t 0 '\( b = b \)'
t 0 '\( b == b \)'
t 1 '! \( b = b \)'
t 1 '! \( b == b \)'
t 1 '! -f /etc/passwd'
t 0 '-h = -h'

View file

@ -2,10 +2,13 @@
.include <src.opts.mk>
SUBDIR= lib sbin usr.bin usr.sbin
SUBDIR= lib .WAIT \
sbin usr.bin usr.sbin
.if ${MK_TESTS} != "no"
SUBDIR+=tests
.endif
SUBDIR_PARALLEL=
.include <bsd.subdir.mk>

View file

@ -18,7 +18,7 @@
.\" information: Portions Copyright [yyyy] [name of copyright owner]
.\"
.\" Copyright (c) 2010, Sun Microsystems, Inc. All Rights Reserved.
.\" Copyright (c) 2014 by Delphix. All rights reserved.
.\" Copyright (c) 2011, 2014 by Delphix. All rights reserved.
.\" Copyright (c) 2011, Pawel Jakub Dawidek <pjd@FreeBSD.org>
.\" Copyright (c) 2012, Glen Barber <gjb@FreeBSD.org>
.\" Copyright (c) 2012, Bryan Drewery <bdrewery@FreeBSD.org>
@ -117,7 +117,7 @@
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Nm
.Cm set
.Ar property Ns = Ns Ar value
.Ar property Ns = Ns Ar value Oc ...
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ...
.Nm
.Cm get
@ -189,17 +189,25 @@
.Op Fl i Ar snapshot Ns | Ns bookmark
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Nm
.Cm send
.Op Fl Penv
.Fl t Ar receive_resume_token
.Nm
.Cm receive Ns | Ns Cm recv
.Op Fl vnFu
.Op Fl vnsFu
.Op Fl o Sy origin Ns = Ns Ar snapshot
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Nm
.Cm receive Ns | Ns Cm recv
.Op Fl vnFu
.Op Fl vnsFu
.Op Fl d | e
.Op Fl o Sy origin Ns = Ns Ar snapshot
.Ar filesystem
.Nm
.Cm receive Ns | Ns Cm recv
.Fl A
.Ar filesystem Ns | Ns Ar volume
.Nm
.Cm allow
.Ar filesystem Ns | Ns Ar volume
.Nm
@ -597,6 +605,13 @@ For cloned file systems or volumes, the snapshot from which the clone was
created. See also the
.Sy clones
property.
.It Sy receive_resume_token
For filesystems or volumes which have saved partially-completed state from
.Sy zfs receive -s ,
this opaque token can be provided to
.Sy zfs send -t
to resume and complete the
.Sy zfs receive .
.It Sy referenced
The amount of data that is accessible by this dataset, which may or may not be
shared with other datasets in the pool. When a snapshot or clone is created, it
@ -2106,14 +2121,14 @@ option, but sorts by property in descending order.
.It Xo
.Nm
.Cm set
.Ar property Ns = Ns Ar value
.Ar property Ns = Ns Ar value Oc ...
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Xc
.Pp
Sets the property to the given value for each dataset. Only some properties can
be edited. See the "Properties" section for more information on what properties
can be set and acceptable values. Numeric values can be specified as exact
values, or in a human-readable form with a suffix of
Sets the property or list of properties to the given value(s) for each dataset.
Only some properties can be edited. See the "Properties" section for more
information on what properties can be set and acceptable values. Numeric values
can be specified as exact values, or in a human-readable form with a suffix of
.Sy B , K , M , G , T , P , E , Z
(for bytes, kilobytes, megabytes, gigabytes, terabytes, petabytes, exabytes, or
zettabytes, respectively). User properties can be set on snapshots. For more
@ -2630,6 +2645,9 @@ useful in conjunction with the
or
.Fl P
flags to determine what data will be sent.
In this case, the verbose output will be written to
standard output (contrast with a non-dry-run, where the stream is written
to standard output and the verbose output goes to standard error).
.It Fl P
Print machine-parsable verbose information about the stream package generated.
.It Fl v
@ -2711,15 +2729,28 @@ feature.
.El
.It Xo
.Nm
.Cm send
.Op Fl Penv
.Fl t
.Ar receive_resume_token
.Xc
Creates a send stream which resumes an interrupted receive. The
.Ar receive_resume_token
is the value of this property on the filesystem
or volume that was being received into. See the documentation for
.Sy zfs receive -s
for more details.
.It Xo
.Nm
.Cm receive Ns | Ns Cm recv
.Op Fl vnFu
.Op Fl vnsFu
.Op Fl o Sy origin Ns = Ns Ar snapshot
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
.Xc
.It Xo
.Nm
.Cm receive Ns | Ns Cm recv
.Op Fl vnFu
.Op Fl vnsFu
.Op Fl d | e
.Op Fl o Sy origin Ns = Ns Ar snapshot
.Ar filesystem
@ -2816,9 +2847,42 @@ performing the receive operation. If receiving an incremental replication
stream (for example, one generated by
.Qq Nm Cm send Fl R Bro Fl i | Fl I Brc ) ,
destroy snapshots and file systems that do not exist on the sending side.
.It Fl s
If the receive is interrupted, save the partially received state, rather
than deleting it. Interruption may be due to premature termination of
the stream
.Po e.g. due to network failure or failure of the remote system
if the stream is being read over a network connection
.Pc ,
a checksum error in the stream, termination of the
.Nm zfs Cm receive
process, or unclean shutdown of the system.
.Pp
The receive can be resumed with a stream generated by
.Nm zfs Cm send Fl t Ar token ,
where the
.Ar token
is the value of the
.Sy receive_resume_token
property of the filesystem or volume which is received into.
.Pp
To use this flag, the storage pool must have the
.Sy extensible_dataset
feature enabled. See
.Xr zpool-features 5
for details on ZFS feature flags.
.El
.It Xo
.Nm
.Cm receive Ns | Ns Cm recv
.Fl A
.Ar filesystem Ns | Ns Ar volume
.Xc
Abort an interrupted
.Nm zfs Cm receive Fl s ,
deleting its saved partially received state.
.It Xo
.Nm
.Cm allow
.Ar filesystem Ns | Ns Ar volume
.Xc

View file

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright 2012 Milan Jurik. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
@ -263,10 +263,11 @@ get_usage(zfs_help_t idx)
case HELP_PROMOTE:
return (gettext("\tpromote <clone-filesystem>\n"));
case HELP_RECEIVE:
return (gettext("\treceive|recv [-vnFu] <filesystem|volume|"
return (gettext("\treceive|recv [-vnsFu] <filesystem|volume|"
"snapshot>\n"
"\treceive|recv [-vnFu] [-o origin=<snapshot>] [-d | -e] "
"<filesystem>\n"));
"\treceive|recv [-vnsFu] [-o origin=<snapshot>] [-d | -e] "
"<filesystem>\n"
"\treceive|recv -A <filesystem|volume>\n"));
case HELP_RENAME:
return (gettext("\trename [-f] <filesystem|volume|snapshot> "
"<filesystem|volume|snapshot>\n"
@ -279,9 +280,10 @@ get_usage(zfs_help_t idx)
return (gettext("\tsend [-DnPpRvLe] [-[iI] snapshot] "
"<snapshot>\n"
"\tsend [-Le] [-i snapshot|bookmark] "
"<filesystem|volume|snapshot>\n"));
"<filesystem|volume|snapshot>\n"
"\tsend [-nvPe] -t <receive_resume_token>\n"));
case HELP_SET:
return (gettext("\tset <property=value> "
return (gettext("\tset <property=value> ... "
"<filesystem|volume|snapshot> ...\n"));
case HELP_SHARE:
return (gettext("\tshare <-a | filesystem>\n"));
@ -496,6 +498,10 @@ usage(boolean_t requested)
exit(requested ? 0 : 2);
}
/*
* Take a property=value argument string and add it to the given nvlist.
* Modifies the argument inplace.
*/
static int
parseprop(nvlist_t *props, char *propname)
{
@ -503,7 +509,7 @@ parseprop(nvlist_t *props, char *propname)
if ((propval = strchr(propname, '=')) == NULL) {
(void) fprintf(stderr, gettext("missing "
"'=' for -o option\n"));
"'=' for property=value argument\n"));
return (-1);
}
*propval = '\0';
@ -630,7 +636,7 @@ zfs_do_clone(int argc, char **argv)
while ((c = getopt(argc, argv, "o:p")) != -1) {
switch (c) {
case 'o':
if (parseprop(props, optarg))
if (parseprop(props, optarg) != 0)
return (1);
break;
case 'p':
@ -839,10 +845,12 @@ zfs_do_create(int argc, char **argv)
if (type == ZFS_TYPE_VOLUME && !noreserve) {
zpool_handle_t *zpool_handle;
nvlist_t *real_props;
uint64_t spa_version;
char *p;
zfs_prop_t resv_prop;
char *strval;
char msg[1024];
if (p = strchr(argv[0], '/'))
*p = '\0';
@ -853,12 +861,22 @@ zfs_do_create(int argc, char **argv)
goto error;
spa_version = zpool_get_prop_int(zpool_handle,
ZPOOL_PROP_VERSION, NULL);
zpool_close(zpool_handle);
if (spa_version >= SPA_VERSION_REFRESERVATION)
resv_prop = ZFS_PROP_REFRESERVATION;
else
resv_prop = ZFS_PROP_RESERVATION;
volsize = zvol_volsize_to_reservation(volsize, props);
(void) snprintf(msg, sizeof (msg),
gettext("cannot create '%s'"), argv[0]);
if (props && (real_props = zfs_valid_proplist(g_zfs, type,
props, 0, NULL, zpool_handle, msg)) == NULL) {
zpool_close(zpool_handle);
goto error;
}
zpool_close(zpool_handle);
volsize = zvol_volsize_to_reservation(volsize, real_props);
nvlist_free(real_props);
if (nvlist_lookup_string(props, zfs_prop_to_name(resv_prop),
&strval) != 0) {
@ -3530,21 +3548,17 @@ zfs_do_rollback(int argc, char **argv)
}
/*
* zfs set property=value { fs | snap | vol } ...
* zfs set property=value ... { fs | snap | vol } ...
*
* Sets the given property for all datasets specified on the command line.
* Sets the given properties for all datasets specified on the command line.
*/
typedef struct set_cbdata {
char *cb_propname;
char *cb_value;
} set_cbdata_t;
static int
set_callback(zfs_handle_t *zhp, void *data)
{
set_cbdata_t *cbp = data;
nvlist_t *props = data;
if (zfs_prop_set(zhp, cbp->cb_propname, cbp->cb_value) != 0) {
if (zfs_prop_set_list(zhp, props) != 0) {
switch (libzfs_errno(g_zfs)) {
case EZFS_MOUNTFAILED:
(void) fprintf(stderr, gettext("property may be set "
@ -3563,7 +3577,8 @@ set_callback(zfs_handle_t *zhp, void *data)
static int
zfs_do_set(int argc, char **argv)
{
set_cbdata_t cb;
nvlist_t *props = NULL;
int ds_start = -1; /* argv idx of first dataset arg */
int ret = 0;
/* check for options */
@ -3575,36 +3590,51 @@ zfs_do_set(int argc, char **argv)
/* check number of arguments */
if (argc < 2) {
(void) fprintf(stderr, gettext("missing property=value "
"argument\n"));
(void) fprintf(stderr, gettext("missing arguments\n"));
usage(B_FALSE);
}
if (argc < 3) {
(void) fprintf(stderr, gettext("missing dataset name\n"));
if (strchr(argv[1], '=') == NULL) {
(void) fprintf(stderr, gettext("missing property=value "
"argument(s)\n"));
} else {
(void) fprintf(stderr, gettext("missing dataset "
"name(s)\n"));
}
usage(B_FALSE);
}
/* validate property=value argument */
cb.cb_propname = argv[1];
if (((cb.cb_value = strchr(cb.cb_propname, '=')) == NULL) ||
(cb.cb_value[1] == '\0')) {
(void) fprintf(stderr, gettext("missing value in "
"property=value argument\n"));
/* validate argument order: prop=val args followed by dataset args */
for (int i = 1; i < argc; i++) {
if (strchr(argv[i], '=') != NULL) {
if (ds_start > 0) {
/* out-of-order prop=val argument */
(void) fprintf(stderr, gettext("invalid "
"argument order\n"), i);
usage(B_FALSE);
}
} else if (ds_start < 0) {
ds_start = i;
}
}
if (ds_start < 0) {
(void) fprintf(stderr, gettext("missing dataset name(s)\n"));
usage(B_FALSE);
}
*cb.cb_value = '\0';
cb.cb_value++;
if (*cb.cb_propname == '\0') {
(void) fprintf(stderr,
gettext("missing property in property=value argument\n"));
usage(B_FALSE);
/* Populate a list of property settings */
if (nvlist_alloc(&props, NV_UNIQUE_NAME, 0) != 0)
nomem();
for (int i = 1; i < ds_start; i++) {
if ((ret = parseprop(props, argv[i])) != 0)
goto error;
}
ret = zfs_for_each(argc - 2, argv + 2, 0,
ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, &cb);
ret = zfs_for_each(argc - ds_start, argv + ds_start, 0,
ZFS_TYPE_DATASET, NULL, NULL, 0, set_callback, props);
error:
nvlist_free(props);
return (ret);
}
@ -3728,6 +3758,7 @@ zfs_do_send(int argc, char **argv)
{
char *fromname = NULL;
char *toname = NULL;
char *resume_token = NULL;
char *cp;
zfs_handle_t *zhp;
sendflags_t flags = { 0 };
@ -3736,7 +3767,7 @@ zfs_do_send(int argc, char **argv)
boolean_t extraverbose = B_FALSE;
/* check options */
while ((c = getopt(argc, argv, ":i:I:RDpvnPLe")) != -1) {
while ((c = getopt(argc, argv, ":i:I:RDpvnPLet:")) != -1) {
switch (c) {
case 'i':
if (fromname)
@ -3777,6 +3808,9 @@ zfs_do_send(int argc, char **argv)
case 'e':
flags.embed_data = B_TRUE;
break;
case 't':
resume_token = optarg;
break;
case ':':
(void) fprintf(stderr, gettext("missing argument for "
"'%c' option\n"), optopt);
@ -3792,14 +3826,28 @@ zfs_do_send(int argc, char **argv)
argc -= optind;
argv += optind;
/* check number of arguments */
if (argc < 1) {
(void) fprintf(stderr, gettext("missing snapshot argument\n"));
usage(B_FALSE);
}
if (argc > 1) {
(void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE);
if (resume_token != NULL) {
if (fromname != NULL || flags.replicate || flags.props ||
flags.dedup) {
(void) fprintf(stderr,
gettext("invalid flags combined with -t\n"));
usage(B_FALSE);
}
if (argc != 0) {
(void) fprintf(stderr, gettext("no additional "
"arguments are permitted with -t\n"));
usage(B_FALSE);
}
} else {
if (argc < 1) {
(void) fprintf(stderr,
gettext("missing snapshot argument\n"));
usage(B_FALSE);
}
if (argc > 1) {
(void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE);
}
}
if (!flags.dryrun && isatty(STDOUT_FILENO)) {
@ -3809,6 +3857,11 @@ zfs_do_send(int argc, char **argv)
return (1);
}
if (resume_token != NULL) {
return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
resume_token));
}
/*
* Special case sending a filesystem, or from a bookmark.
*/
@ -3914,8 +3967,6 @@ zfs_do_send(int argc, char **argv)
}
/*
* zfs receive [-vnFu] [-d | -e] <fs@snap>
*
* Restore a backup stream from stdin.
*/
static int
@ -3923,6 +3974,8 @@ zfs_do_receive(int argc, char **argv)
{
int c, err;
recvflags_t flags = { 0 };
boolean_t abort_resumable = B_FALSE;
nvlist_t *props;
nvpair_t *nvp = NULL;
@ -3930,7 +3983,7 @@ zfs_do_receive(int argc, char **argv)
nomem();
/* check options */
while ((c = getopt(argc, argv, ":o:denuvF")) != -1) {
while ((c = getopt(argc, argv, ":o:denuvFsA")) != -1) {
switch (c) {
case 'o':
if (parseprop(props, optarg) != 0)
@ -3952,9 +4005,15 @@ zfs_do_receive(int argc, char **argv)
case 'v':
flags.verbose = B_TRUE;
break;
case 's':
flags.resumable = B_TRUE;
break;
case 'F':
flags.force = B_TRUE;
break;
case 'A':
abort_resumable = B_TRUE;
break;
case ':':
(void) fprintf(stderr, gettext("missing argument for "
"'%c' option\n"), optopt);
@ -3987,6 +4046,44 @@ zfs_do_receive(int argc, char **argv)
}
}
if (abort_resumable) {
if (flags.isprefix || flags.istail || flags.dryrun ||
flags.resumable || flags.nomount) {
(void) fprintf(stderr, gettext("invalid option"));
usage(B_FALSE);
}
char namebuf[ZFS_MAXNAMELEN];
(void) snprintf(namebuf, sizeof (namebuf),
"%s/%%recv", argv[0]);
if (zfs_dataset_exists(g_zfs, namebuf,
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME)) {
zfs_handle_t *zhp = zfs_open(g_zfs,
namebuf, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
if (zhp == NULL)
return (1);
err = zfs_destroy(zhp, B_FALSE);
} else {
zfs_handle_t *zhp = zfs_open(g_zfs,
argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
if (zhp == NULL)
usage(B_FALSE);
if (!zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) ||
zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
NULL, 0, NULL, NULL, 0, B_TRUE) == -1) {
(void) fprintf(stderr,
gettext("'%s' does not have any "
"resumable receive state to abort\n"),
argv[0]);
return (1);
}
err = zfs_destroy(zhp, B_FALSE);
}
return (err != 0);
}
if (isatty(STDIN_FILENO)) {
(void) fprintf(stderr,
gettext("Error: Backup stream can not be read "
@ -3994,7 +4091,6 @@ zfs_do_receive(int argc, char **argv)
"You must redirect standard input.\n"));
return (1);
}
err = zfs_receive(g_zfs, argv[0], props, &flags, STDIN_FILENO, NULL);
return (err != 0);
@ -5815,6 +5911,24 @@ share_mount_one(zfs_handle_t *zhp, int op, int flags, char *protocol,
return (0);
}
/*
* If this filesystem is inconsistent and has a receive resume
* token, we can not mount it.
*/
if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) &&
zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
NULL, 0, NULL, NULL, 0, B_TRUE) == 0) {
if (!explicit)
return (0);
(void) fprintf(stderr, gettext("cannot %s '%s': "
"Contains partially-completed state from "
"\"zfs receive -r\", which can be resumed with "
"\"zfs send -t\"\n"),
cmdname, zfs_get_name(zhp));
return (1);
}
/*
* At this point, we have verified that the mountpoint and/or
* shareopts are appropriate for auto management. If the

View file

@ -199,7 +199,8 @@ static boolean_t log_history = B_TRUE;
static uint_t timestamp_fmt = NODATE;
static const char *
get_usage(zpool_help_t idx) {
get_usage(zpool_help_t idx)
{
switch (idx) {
case HELP_ADD:
return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
@ -2940,6 +2941,9 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
uint_t c, children;
char *vname;
boolean_t scripted = cb->cb_scripted;
uint64_t islog = B_FALSE;
boolean_t haslog = B_FALSE;
char *dashes = "%-*s - - - - - -\n";
verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
(uint64_t **)&vs, &c) == 0);
@ -2990,24 +2994,47 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
continue;
if (nvlist_lookup_uint64(child[c],
ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
haslog = B_TRUE;
continue;
}
vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
print_list_stats(zhp, vname, child[c], cb, depth + 2);
free(vname);
}
/*
* Include level 2 ARC devices in iostat output
*/
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
&child, &children) != 0)
return;
if (children > 0) {
(void) printf("%-*s - - - - - "
"-\n", cb->cb_namewidth, "cache");
if (haslog == B_TRUE) {
/* LINTED E_SEC_PRINTF_VAR_FMT */
(void) printf(dashes, cb->cb_namewidth, "log");
for (c = 0; c < children; c++) {
vname = zpool_vdev_name(g_zfs, zhp, child[c],
B_FALSE);
if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
&islog) != 0 || !islog)
continue;
vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
print_list_stats(zhp, vname, child[c], cb, depth + 2);
free(vname);
}
}
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
&child, &children) == 0 && children > 0) {
/* LINTED E_SEC_PRINTF_VAR_FMT */
(void) printf(dashes, cb->cb_namewidth, "cache");
for (c = 0; c < children; c++) {
vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
print_list_stats(zhp, vname, child[c], cb, depth + 2);
free(vname);
}
}
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
&children) == 0 && children > 0) {
/* LINTED E_SEC_PRINTF_VAR_FMT */
(void) printf(dashes, cb->cb_namewidth, "spare");
for (c = 0; c < children; c++) {
vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
print_list_stats(zhp, vname, child[c], cb, depth + 2);
free(vname);
}

View file

@ -125,7 +125,7 @@ read_hdr(dmu_replay_record_t *drr, zio_cksum_t *cksum)
saved_cksum.zc_word[1],
saved_cksum.zc_word[2],
saved_cksum.zc_word[3]);
exit(1);
return (0);
}
return (sizeof (*drr));
}
@ -346,8 +346,7 @@ main(int argc, char *argv[])
if (verbose)
(void) printf("\n");
if ((DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
DMU_COMPOUNDSTREAM) && drr->drr_payloadlen != 0) {
if (drr->drr_payloadlen != 0) {
nvlist_t *nv;
int sz = drr->drr_payloadlen;

View file

@ -23,7 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
@ -426,10 +426,11 @@ extern const char *zfs_prop_column_name(zfs_prop_t);
extern boolean_t zfs_prop_align_right(zfs_prop_t);
extern nvlist_t *zfs_valid_proplist(libzfs_handle_t *, zfs_type_t,
nvlist_t *, uint64_t, zfs_handle_t *, const char *);
nvlist_t *, uint64_t, zfs_handle_t *, zpool_handle_t *, const char *);
extern const char *zfs_prop_to_name(zfs_prop_t);
extern int zfs_prop_set(zfs_handle_t *, const char *, const char *);
extern int zfs_prop_set_list(zfs_handle_t *, nvlist_t *);
extern int zfs_prop_get(zfs_handle_t *, zfs_prop_t, char *, size_t,
zprop_source_t *, char *, size_t, boolean_t);
extern int zfs_prop_get_recvd(zfs_handle_t *, const char *, char *, size_t,
@ -621,6 +622,10 @@ typedef boolean_t (snapfilter_cb_t)(zfs_handle_t *, void *);
extern int zfs_send(zfs_handle_t *, const char *, const char *,
sendflags_t *, int, snapfilter_cb_t, void *, nvlist_t **);
extern int zfs_send_one(zfs_handle_t *, const char *, int, enum lzc_send_flags);
extern int zfs_send_resume(libzfs_handle_t *, sendflags_t *, int outfd,
const char *);
extern nvlist_t *zfs_send_resume_token_to_nvlist(libzfs_handle_t *hdl,
const char *token);
extern int zfs_promote(zfs_handle_t *);
extern int zfs_hold(zfs_handle_t *, const char *, const char *,
@ -661,6 +666,12 @@ typedef struct recvflags {
/* set "canmount=off" on all modified filesystems */
boolean_t canmountoff;
/*
* Mark the file systems as "resumable" and do not destroy them if the
* receive is interrupted
*/
boolean_t resumable;
/* byteswap flag is used internally; callers need not specify */
boolean_t byteswap;

View file

@ -74,6 +74,9 @@ zcmd_ioctl(int fd, int request, zfs_cmd_t *zc)
if (zfs_ioctl_version >= ZFS_IOCVER_DEADMAN) {
switch (zfs_ioctl_version) {
case ZFS_IOCVER_EDBP:
cflag = ZFS_CMD_COMPAT_EDBP;
break;
case ZFS_IOCVER_ZCMD:
cflag = ZFS_CMD_COMPAT_ZCMD;
break;

View file

@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2011-2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
@ -890,7 +890,8 @@ zfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop)
*/
nvlist_t *
zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
uint64_t zoned, zfs_handle_t *zhp, const char *errbuf)
uint64_t zoned, zfs_handle_t *zhp, zpool_handle_t *zpool_hdl,
const char *errbuf)
{
nvpair_t *elem;
uint64_t intval;
@ -1084,8 +1085,8 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
case ZFS_PROP_RECORDSIZE:
{
int maxbs = SPA_MAXBLOCKSIZE;
if (zhp != NULL) {
maxbs = zpool_get_prop_int(zhp->zpool_hdl,
if (zpool_hdl != NULL) {
maxbs = zpool_get_prop_int(zpool_hdl,
ZPOOL_PROP_MAXBLOCKSIZE, NULL);
}
/*
@ -1403,6 +1404,7 @@ zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl)
uint64_t old_reservation;
uint64_t new_reservation;
zfs_prop_t resv_prop;
nvlist_t *props;
/*
* If this is an existing volume, and someone is setting the volsize,
@ -1412,16 +1414,25 @@ zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl)
if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
return (-1);
old_reservation = zfs_prop_get_int(zhp, resv_prop);
if ((zvol_volsize_to_reservation(old_volsize, zhp->zfs_props) !=
old_reservation) || nvlist_lookup_uint64(nvl,
zfs_prop_to_name(resv_prop), &new_reservation) != ENOENT) {
props = fnvlist_alloc();
fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
if ((zvol_volsize_to_reservation(old_volsize, props) !=
old_reservation) || nvlist_exists(nvl,
zfs_prop_to_name(resv_prop))) {
fnvlist_free(props);
return (0);
}
if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
&new_volsize) != 0)
&new_volsize) != 0) {
fnvlist_free(props);
return (-1);
new_reservation = zvol_volsize_to_reservation(new_volsize,
zhp->zfs_props);
}
new_reservation = zvol_volsize_to_reservation(new_volsize, props);
fnvlist_free(props);
if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
new_reservation) != 0) {
(void) no_memory(zhp->zfs_hdl);
@ -1493,6 +1504,12 @@ zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
"property setting is not allowed on "
"bootable datasets"));
(void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
} else if (prop == ZFS_PROP_CHECKSUM ||
prop == ZFS_PROP_DEDUP) {
(void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"property setting is not allowed on "
"root pools"));
(void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
} else {
(void) zfs_standard_error(hdl, err, errbuf);
}
@ -1528,15 +1545,10 @@ zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
int
zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
{
zfs_cmd_t zc = { 0 };
int ret = -1;
prop_changelist_t *cl = NULL;
char errbuf[1024];
libzfs_handle_t *hdl = zhp->zfs_hdl;
nvlist_t *nvl = NULL, *realprops;
zfs_prop_t prop;
boolean_t do_prefix = B_TRUE;
int added_resv;
nvlist_t *nvl = NULL;
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
@ -1548,79 +1560,149 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
goto error;
}
if ((realprops = zfs_valid_proplist(hdl, zhp->zfs_type, nvl,
zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, errbuf)) == NULL)
goto error;
ret = zfs_prop_set_list(zhp, nvl);
error:
nvlist_free(nvl);
nvl = realprops;
return (ret);
}
prop = zfs_name_to_prop(propname);
/* We don't support those properties on FreeBSD. */
switch (prop) {
case ZFS_PROP_DEVICES:
case ZFS_PROP_ISCSIOPTIONS:
case ZFS_PROP_XATTR:
case ZFS_PROP_VSCAN:
case ZFS_PROP_NBMAND:
case ZFS_PROP_MLSLABEL:
(void) snprintf(errbuf, sizeof (errbuf),
"property '%s' not supported on FreeBSD", propname);
ret = zfs_error(hdl, EZFS_PERM, errbuf);
/*
* Given an nvlist of property names and values, set the properties for the
* given dataset.
*/
int
zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
{
zfs_cmd_t zc = { 0 };
int ret = -1;
prop_changelist_t **cls = NULL;
int cl_idx;
char errbuf[1024];
libzfs_handle_t *hdl = zhp->zfs_hdl;
nvlist_t *nvl;
int nvl_len;
int added_resv;
(void) snprintf(errbuf, sizeof (errbuf),
dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
zhp->zfs_name);
if ((nvl = zfs_valid_proplist(hdl, zhp->zfs_type, props,
zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, zhp->zpool_hdl,
errbuf)) == NULL)
goto error;
}
if (prop == ZFS_PROP_VOLSIZE) {
if ((added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1)
goto error;
}
if ((cl = changelist_gather(zhp, prop, 0, 0)) == NULL)
goto error;
if (prop == ZFS_PROP_MOUNTPOINT && changelist_haszonedchild(cl)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"child dataset with inherited mountpoint is used "
"in a non-global zone"));
ret = zfs_error(hdl, EZFS_ZONED, errbuf);
goto error;
}
/*
* We don't want to unmount & remount the dataset when changing
* its canmount property to 'on' or 'noauto'. We only use
* the changelist logic to unmount when setting canmount=off.
* We have to check for any extra properties which need to be added
* before computing the length of the nvlist.
*/
if (prop == ZFS_PROP_CANMOUNT) {
uint64_t idx;
int err = zprop_string_to_index(prop, propval, &idx,
ZFS_TYPE_DATASET);
if (err == 0 && idx != ZFS_CANMOUNT_OFF)
do_prefix = B_FALSE;
for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
elem != NULL;
elem = nvlist_next_nvpair(nvl, elem)) {
if (zfs_name_to_prop(nvpair_name(elem)) == ZFS_PROP_VOLSIZE &&
(added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1) {
goto error;
}
}
if (do_prefix && (ret = changelist_prefix(cl)) != 0)
/*
* Check how many properties we're setting and allocate an array to
* store changelist pointers for postfix().
*/
nvl_len = 0;
for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
elem != NULL;
elem = nvlist_next_nvpair(nvl, elem))
nvl_len++;
if ((cls = calloc(nvl_len, sizeof (prop_changelist_t *))) == NULL)
goto error;
cl_idx = 0;
for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
elem != NULL;
elem = nvlist_next_nvpair(nvl, elem)) {
zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
assert(cl_idx < nvl_len);
/*
* We don't want to unmount & remount the dataset when changing
* its canmount property to 'on' or 'noauto'. We only use
* the changelist logic to unmount when setting canmount=off.
*/
if (!(prop == ZFS_PROP_CANMOUNT &&
fnvpair_value_uint64(elem) != ZFS_CANMOUNT_OFF)) {
cls[cl_idx] = changelist_gather(zhp, prop, 0, 0);
if (cls[cl_idx] == NULL)
goto error;
}
if (prop == ZFS_PROP_MOUNTPOINT &&
changelist_haszonedchild(cls[cl_idx])) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"child dataset with inherited mountpoint is used "
"in a non-global zone"));
ret = zfs_error(hdl, EZFS_ZONED, errbuf);
goto error;
}
/* We don't support those properties on FreeBSD. */
switch (prop) {
case ZFS_PROP_DEVICES:
case ZFS_PROP_ISCSIOPTIONS:
case ZFS_PROP_XATTR:
case ZFS_PROP_VSCAN:
case ZFS_PROP_NBMAND:
case ZFS_PROP_MLSLABEL:
(void) snprintf(errbuf, sizeof (errbuf),
"property '%s' not supported on FreeBSD",
nvpair_name(elem));
ret = zfs_error(hdl, EZFS_PERM, errbuf);
goto error;
}
if (cls[cl_idx] != NULL &&
(ret = changelist_prefix(cls[cl_idx])) != 0)
goto error;
cl_idx++;
}
assert(cl_idx == nvl_len);
/*
* Execute the corresponding ioctl() to set this property.
* Execute the corresponding ioctl() to set this list of properties.
*/
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
if (zcmd_write_src_nvlist(hdl, &zc, nvl) != 0)
if ((ret = zcmd_write_src_nvlist(hdl, &zc, nvl)) != 0 ||
(ret = zcmd_alloc_dst_nvlist(hdl, &zc, 0)) != 0)
goto error;
ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
if (ret != 0) {
zfs_setprop_error(hdl, prop, errno, errbuf);
/* Get the list of unset properties back and report them. */
nvlist_t *errorprops = NULL;
if (zcmd_read_dst_nvlist(hdl, &zc, &errorprops) != 0)
goto error;
for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
elem != NULL;
elem = nvlist_next_nvpair(nvl, elem)) {
zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
zfs_setprop_error(hdl, prop, errno, errbuf);
}
nvlist_free(errorprops);
if (added_resv && errno == ENOSPC) {
/* clean up the volsize property we tried to set */
uint64_t old_volsize = zfs_prop_get_int(zhp,
ZFS_PROP_VOLSIZE);
nvlist_free(nvl);
nvl = NULL;
zcmd_free_nvlists(&zc);
if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
goto error;
if (nvlist_add_uint64(nvl,
@ -1632,8 +1714,13 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
(void) zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
}
} else {
if (do_prefix)
ret = changelist_postfix(cl);
for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) {
if (cls[cl_idx] != NULL) {
int clp_err = changelist_postfix(cls[cl_idx]);
if (clp_err != 0)
ret = clp_err;
}
}
/*
* Refresh the statistics so the new property value
@ -1646,8 +1733,13 @@ zfs_prop_set(zfs_handle_t *zhp, const char *propname, const char *propval)
error:
nvlist_free(nvl);
zcmd_free_nvlists(&zc);
if (cl)
changelist_free(cl);
if (cls != NULL) {
for (cl_idx = 0; cl_idx < nvl_len; cl_idx++) {
if (cls[cl_idx] != NULL)
changelist_free(cls[cl_idx]);
}
free(cls);
}
return (ret);
}
@ -1778,22 +1870,21 @@ getprop_uint64(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
return (value);
}
static char *
static const char *
getprop_string(zfs_handle_t *zhp, zfs_prop_t prop, char **source)
{
nvlist_t *nv;
char *value;
const char *value;
*source = NULL;
if (nvlist_lookup_nvlist(zhp->zfs_props,
zfs_prop_to_name(prop), &nv) == 0) {
verify(nvlist_lookup_string(nv, ZPROP_VALUE, &value) == 0);
value = fnvlist_lookup_string(nv, ZPROP_VALUE);
(void) nvlist_lookup_string(nv, ZPROP_SOURCE, source);
} else {
verify(!zhp->zfs_props_table ||
zhp->zfs_props_table[prop] == B_TRUE);
if ((value = (char *)zfs_prop_default_string(prop)) == NULL)
value = "";
value = zfs_prop_default_string(prop);
*source = "";
}
@ -2195,7 +2286,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
{
char *source = NULL;
uint64_t val;
char *str;
const char *str;
const char *strval;
boolean_t received = zfs_is_recvd_props_mode(zhp);
@ -2300,14 +2391,10 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
break;
case ZFS_PROP_ORIGIN:
(void) strlcpy(propbuf, getprop_string(zhp, prop, &source),
proplen);
/*
* If there is no parent at all, return failure to indicate that
* it doesn't apply to this dataset.
*/
if (propbuf[0] == '\0')
str = getprop_string(zhp, prop, &source);
if (str == NULL)
return (-1);
(void) strlcpy(propbuf, str, proplen);
break;
case ZFS_PROP_CLONES:
@ -2488,8 +2575,10 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
break;
case PROP_TYPE_STRING:
(void) strlcpy(propbuf,
getprop_string(zhp, prop, &source), proplen);
str = getprop_string(zhp, prop, &source);
if (str == NULL)
return (-1);
(void) strlcpy(propbuf, str, proplen);
break;
case PROP_TYPE_INDEX:
@ -3167,9 +3256,23 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
else
ost = DMU_OST_ZFS;
/* open zpool handle for prop validation */
char pool_path[MAXNAMELEN];
(void) strlcpy(pool_path, path, sizeof (pool_path));
/* truncate pool_path at first slash */
char *p = strchr(pool_path, '/');
if (p != NULL)
*p = '\0';
zpool_handle_t *zpool_handle = zpool_open(hdl, pool_path);
if (props && (props = zfs_valid_proplist(hdl, type, props,
zoned, NULL, errbuf)) == 0)
zoned, NULL, zpool_handle, errbuf)) == 0) {
zpool_close(zpool_handle);
return (-1);
}
zpool_close(zpool_handle);
if (type == ZFS_TYPE_VOLUME) {
/*
@ -3237,13 +3340,6 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
"parent '%s' is not a filesystem"), parent);
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
case EDOM:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"volume block size must be power of 2 from "
"512B to 128KB"));
return (zfs_error(hdl, EZFS_BADPROP, errbuf));
case ENOTSUP:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"pool must be upgraded to set this "
@ -3438,7 +3534,7 @@ zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
type = ZFS_TYPE_FILESYSTEM;
}
if ((props = zfs_valid_proplist(hdl, type, props, zoned,
zhp, errbuf)) == NULL)
zhp, zhp->zpool_hdl, errbuf)) == NULL)
return (-1);
}
@ -3582,11 +3678,23 @@ zfs_snapshot_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, nvlist_t *props)
}
}
/*
* get pool handle for prop validation. assumes all snaps are in the
* same pool, as does lzc_snapshot (below).
*/
char pool[MAXNAMELEN];
elem = nvlist_next_nvpair(snaps, NULL);
(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
pool[strcspn(pool, "/@")] = '\0';
zpool_handle_t *zpool_hdl = zpool_open(hdl, pool);
if (props != NULL &&
(props = zfs_valid_proplist(hdl, ZFS_TYPE_SNAPSHOT,
props, B_FALSE, NULL, errbuf)) == NULL) {
props, B_FALSE, NULL, zpool_hdl, errbuf)) == NULL) {
zpool_close(zpool_hdl);
return (-1);
}
zpool_close(zpool_hdl);
ret = lzc_snapshot(snaps, props, &errors);
@ -4200,7 +4308,7 @@ zfs_smb_acl_mgmt(libzfs_handle_t *hdl, char *dataset, char *path,
if (cmd == ZFS_SMB_ACL_RENAME) {
if (nvlist_alloc(&nvlist, NV_UNIQUE_NAME, 0) != 0) {
(void) no_memory(hdl);
return (NULL);
return (0);
}
}

View file

@ -21,6 +21,7 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
@ -624,9 +625,12 @@ get_snapshot_names(differ_info_t *di, const char *fromsnap,
zhp = zfs_open(hdl, di->ds, ZFS_TYPE_FILESYSTEM);
while (zhp != NULL) {
(void) zfs_prop_get(zhp, ZFS_PROP_ORIGIN,
origin, sizeof (origin), &src, NULL, 0, B_FALSE);
if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin,
sizeof (origin), &src, NULL, 0, B_FALSE) != 0) {
(void) zfs_close(zhp);
zhp = NULL;
break;
}
if (strncmp(origin, fromsnap, fsnlen) == 0)
break;

View file

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
@ -315,7 +315,8 @@ typedef struct {
} snapspec_arg_t;
static int
snapspec_cb(zfs_handle_t *zhp, void *arg) {
snapspec_cb(zfs_handle_t *zhp, void *arg)
{
snapspec_arg_t *ssa = arg;
char *shortsnapname;
int err = 0;

View file

@ -1072,6 +1072,17 @@ mount_cb(zfs_handle_t *zhp, void *data)
return (0);
}
/*
* If this filesystem is inconsistent and has a receive resume
* token, we can not mount it.
*/
if (zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT) &&
zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
NULL, 0, NULL, NULL, 0, B_TRUE) == 0) {
zfs_close(zhp);
return (0);
}
libzfs_add_handle(cbp, zhp);
if (zfs_iter_filesystems(zhp, mount_cb, cbp) != 0) {
zfs_close(zhp);

View file

@ -22,7 +22,7 @@
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
@ -402,29 +402,6 @@ bootfs_name_valid(const char *pool, char *bootfs)
return (B_FALSE);
}
/*
* Inspect the configuration to determine if any of the devices contain
* an EFI label.
*/
static boolean_t
pool_uses_efi(nvlist_t *config)
{
#ifdef illumos
nvlist_t **child;
uint_t c, children;
if (nvlist_lookup_nvlist_array(config, ZPOOL_CONFIG_CHILDREN,
&child, &children) != 0)
return (read_efi_label(config, NULL) >= 0);
for (c = 0; c < children; c++) {
if (pool_uses_efi(child[c]))
return (B_TRUE);
}
#endif /* illumos */
return (B_FALSE);
}
boolean_t
zpool_is_bootable(zpool_handle_t *zhp)
{
@ -453,7 +430,6 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
char *slash, *check;
struct stat64 statbuf;
zpool_handle_t *zhp;
nvlist_t *nvroot;
if (nvlist_alloc(&retprops, NV_UNIQUE_NAME, 0) != 0) {
(void) no_memory(hdl);
@ -572,23 +548,6 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
(void) zfs_error(hdl, EZFS_OPENFAILED, errbuf);
goto error;
}
verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
#ifdef illumos
/*
* bootfs property cannot be set on a disk which has
* been EFI labeled.
*/
if (pool_uses_efi(nvroot)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"property '%s' not supported on "
"EFI labeled devices"), propname);
(void) zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf);
zpool_close(zhp);
goto error;
}
#endif /* illumos */
zpool_close(zhp);
break;
@ -1164,8 +1123,8 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
zfs_prop_to_name(ZFS_PROP_ZONED), &zonestr) == 0) &&
strcmp(zonestr, "on") == 0);
if ((zc_fsprops = zfs_valid_proplist(hdl,
ZFS_TYPE_FILESYSTEM, fsprops, zoned, NULL, msg)) == NULL) {
if ((zc_fsprops = zfs_valid_proplist(hdl, ZFS_TYPE_FILESYSTEM,
fsprops, zoned, NULL, NULL, msg)) == NULL) {
goto create_failed;
}
if (!zc_props &&
@ -1201,6 +1160,21 @@ zpool_create(libzfs_handle_t *hdl, const char *pool, nvlist_t *nvroot,
"one or more vdevs refer to the same device"));
return (zfs_error(hdl, EZFS_BADDEV, msg));
case ERANGE:
/*
* This happens if the record size is smaller or larger
* than the allowed size range, or not a power of 2.
*
* NOTE: although zfs_valid_proplist is called earlier,
* this case may have slipped through since the
* pool does not exist yet and it is therefore
* impossible to read properties e.g. max blocksize
* from the pool.
*/
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"record size invalid"));
return (zfs_error(hdl, EZFS_BADPROP, msg));
case EOVERFLOW:
/*
* This occurs when one of the devices is below
@ -1311,25 +1285,6 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
return (zfs_error(hdl, EZFS_BADVERSION, msg));
}
if (zpool_is_bootable(zhp) && nvlist_lookup_nvlist_array(nvroot,
ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) {
uint64_t s;
for (s = 0; s < nspares; s++) {
char *path;
if (nvlist_lookup_string(spares[s], ZPOOL_CONFIG_PATH,
&path) == 0 && pool_uses_efi(spares[s])) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"device '%s' contains an EFI label and "
"cannot be used on root pools."),
zpool_vdev_name(hdl, NULL, spares[s],
B_FALSE));
return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
}
}
}
if (zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL) <
SPA_VERSION_L2CACHE &&
nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
@ -1930,7 +1885,8 @@ zpool_scan(zpool_handle_t *zhp, pool_scan_func_t func)
* and the like.
*/
static int
ctd_check_path(char *str) {
ctd_check_path(char *str)
{
/*
* If it starts with a slash, check the last component.
*/
@ -2350,11 +2306,9 @@ zpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
return (EZFS_INVALCONFIG);
/*
* root pool can not have EFI labeled disks and can only have
* a single top-level vdev.
* root pool can only have a single top-level vdev.
*/
if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1 ||
pool_uses_efi(vdev_root))
if (strcmp(type, VDEV_TYPE_ROOT) != 0 || count != 1)
return (EZFS_POOL_INVALARG);
(void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz,
@ -2658,16 +2612,6 @@ zpool_vdev_attach(zpool_handle_t *zhp,
(void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
"cannot attach %s to %s"), new_disk, old_disk);
/*
* If this is a root pool, make sure that we're not attaching an
* EFI labeled device.
*/
if (rootpool && pool_uses_efi(nvroot)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"EFI labeled devices are not supported on root pools."));
return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
}
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
if ((tgt = zpool_find_vdev(zhp, old_disk, &avail_spare, &l2cache,
&islog)) == 0)
@ -3786,17 +3730,18 @@ zpool_history_unpack(char *buf, uint64_t bytes_read, uint64_t *leftover,
int
zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
{
char *buf = NULL;
uint64_t bufsize = HIS_BUF_LEN_DEF;
char *buf;
uint64_t buflen = HIS_BUF_LEN_DEF;
uint64_t off = 0;
nvlist_t **records = NULL;
uint_t numrecords = 0;
int err, i;
if ((buf = malloc(bufsize)) == NULL)
buf = malloc(buflen);
if (buf == NULL)
return (ENOMEM);
do {
uint64_t bytes_read = bufsize;
uint64_t bytes_read = buflen;
uint64_t leftover;
if ((err = get_history(zhp, buf, &off, &bytes_read)) != 0)
@ -3810,18 +3755,16 @@ zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
&leftover, &records, &numrecords)) != 0)
break;
off -= leftover;
/*
* If the history block is too big, double the buffer
* size and try again.
*/
if (leftover == bytes_read) {
/*
* no progress made, because buffer is not big enough
* to hold this record; resize and retry.
*/
buflen *= 2;
free(buf);
buf = NULL;
bufsize <<= 1;
if ((bufsize >= HIS_BUF_LEN_MAX) ||
((buf = malloc(bufsize)) == NULL)) {
if ((buflen >= HIS_BUF_LEN_MAX) ||
((buf = malloc(buflen)) == NULL)) {
err = ENOMEM;
break;
}
@ -3829,6 +3772,7 @@ zpool_get_history(zpool_handle_t *zhp, nvlist_t **nvhisp)
/* CONSTCOND */
} while (1);
free(buf);
if (!err) {
@ -3981,13 +3925,6 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name)
if (zhp) {
nvlist_t *nvroot;
if (zpool_is_bootable(zhp)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"EFI labeled devices are not supported on root "
"pools."));
return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf));
}
verify(nvlist_lookup_nvlist(zhp->zpool_config,
ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);

View file

@ -21,7 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
@ -51,6 +51,7 @@
#include "zfs_prop.h"
#include "zfs_fletcher.h"
#include "libzfs_impl.h"
#include <zlib.h>
#include <sha2.h>
#include <sys/zio_checksum.h>
#include <sys/ddt.h>
@ -67,6 +68,8 @@ extern void zfs_setprop_error(libzfs_handle_t *, zfs_prop_t, int, char *);
static int zfs_receive_impl(libzfs_handle_t *, const char *, const char *,
recvflags_t *, int, const char *, nvlist_t *, avl_tree_t *, char **, int,
uint64_t *);
static int guid_to_name(libzfs_handle_t *, const char *,
uint64_t, boolean_t, char *);
static const zio_cksum_t zero_cksum = { 0 };
@ -284,8 +287,7 @@ cksummer(void *arg)
DMU_BACKUP_FEATURE_DEDUPPROPS);
DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags);
if (DMU_GET_STREAM_HDRTYPE(drrb->drr_versioninfo) ==
DMU_COMPOUNDSTREAM && drr->drr_payloadlen != 0) {
if (drr->drr_payloadlen != 0) {
sz = drr->drr_payloadlen;
if (sz > SPA_MAXBLOCKSIZE) {
@ -818,7 +820,8 @@ typedef struct send_dump_data {
char prevsnap[ZFS_MAXNAMELEN];
uint64_t prevsnap_obj;
boolean_t seenfrom, seento, replicate, doall, fromorigin;
boolean_t verbose, dryrun, parsable, progress, embed_data, large_block;
boolean_t verbose, dryrun, parsable, progress, embed_data, std_out;
boolean_t large_block;
int outfd;
boolean_t err;
nvlist_t *fss;
@ -994,17 +997,14 @@ static void *
send_progress_thread(void *arg)
{
progress_arg_t *pa = arg;
zfs_cmd_t zc = { 0 };
zfs_handle_t *zhp = pa->pa_zhp;
libzfs_handle_t *hdl = zhp->zfs_hdl;
unsigned long long bytes;
char buf[16];
time_t t;
struct tm *tm;
assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
if (!pa->pa_parsable)
@ -1037,6 +1037,51 @@ send_progress_thread(void *arg)
}
}
static void
send_print_verbose(FILE *fout, const char *tosnap, const char *fromsnap,
uint64_t size, boolean_t parsable)
{
if (parsable) {
if (fromsnap != NULL) {
(void) fprintf(fout, "incremental\t%s\t%s",
fromsnap, tosnap);
} else {
(void) fprintf(fout, "full\t%s",
tosnap);
}
} else {
if (fromsnap != NULL) {
if (strchr(fromsnap, '@') == NULL &&
strchr(fromsnap, '#') == NULL) {
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
"send from @%s to %s"),
fromsnap, tosnap);
} else {
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
"send from %s to %s"),
fromsnap, tosnap);
}
} else {
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
"full send of %s"),
tosnap);
}
}
if (size != 0) {
if (parsable) {
(void) fprintf(fout, "\t%llu",
(longlong_t)size);
} else {
char buf[16];
zfs_nicenum(size, buf, sizeof (buf));
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
" estimated size is %s"), buf);
}
}
(void) fprintf(fout, "\n");
}
static int
dump_snapshot(zfs_handle_t *zhp, void *arg)
{
@ -1047,6 +1092,7 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
int err;
boolean_t isfromsnap, istosnap, fromorigin;
boolean_t exclude = B_FALSE;
FILE *fout = sdd->std_out ? stdout : stderr;
err = 0;
thissnap = strchr(zhp->zfs_name, '@') + 1;
@ -1115,37 +1161,14 @@ dump_snapshot(zfs_handle_t *zhp, void *arg)
(sdd->fromorigin || sdd->replicate);
if (sdd->verbose) {
uint64_t size;
err = estimate_ioctl(zhp, sdd->prevsnap_obj,
uint64_t size = 0;
(void) estimate_ioctl(zhp, sdd->prevsnap_obj,
fromorigin, &size);
if (sdd->parsable) {
if (sdd->prevsnap[0] != '\0') {
(void) fprintf(stderr, "incremental\t%s\t%s",
sdd->prevsnap, zhp->zfs_name);
} else {
(void) fprintf(stderr, "full\t%s",
zhp->zfs_name);
}
} else {
(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
"send from @%s to %s"),
sdd->prevsnap, zhp->zfs_name);
}
if (err == 0) {
if (sdd->parsable) {
(void) fprintf(stderr, "\t%llu\n",
(longlong_t)size);
} else {
char buf[16];
zfs_nicenum(size, buf, sizeof (buf));
(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
" estimated size is %s\n"), buf);
}
sdd->size += size;
} else {
(void) fprintf(stderr, "\n");
}
send_print_verbose(fout, zhp->zfs_name,
sdd->prevsnap[0] ? sdd->prevsnap : NULL,
size, sdd->parsable);
sdd->size += size;
}
if (!sdd->dryrun) {
@ -1356,6 +1379,233 @@ dump_filesystems(zfs_handle_t *rzhp, void *arg)
return (0);
}
nvlist_t *
zfs_send_resume_token_to_nvlist(libzfs_handle_t *hdl, const char *token)
{
unsigned int version;
int nread;
unsigned long long checksum, packed_len;
/*
* Decode token header, which is:
* <token version>-<checksum of payload>-<uncompressed payload length>
* Note that the only supported token version is 1.
*/
nread = sscanf(token, "%u-%llx-%llx-",
&version, &checksum, &packed_len);
if (nread != 3) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"resume token is corrupt (invalid format)"));
return (NULL);
}
if (version != ZFS_SEND_RESUME_TOKEN_VERSION) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"resume token is corrupt (invalid version %u)"),
version);
return (NULL);
}
/* convert hexadecimal representation to binary */
token = strrchr(token, '-') + 1;
int len = strlen(token) / 2;
unsigned char *compressed = zfs_alloc(hdl, len);
for (int i = 0; i < len; i++) {
nread = sscanf(token + i * 2, "%2hhx", compressed + i);
if (nread != 1) {
free(compressed);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"resume token is corrupt "
"(payload is not hex-encoded)"));
return (NULL);
}
}
/* verify checksum */
zio_cksum_t cksum;
fletcher_4_native(compressed, len, NULL, &cksum);
if (cksum.zc_word[0] != checksum) {
free(compressed);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"resume token is corrupt (incorrect checksum)"));
return (NULL);
}
/* uncompress */
void *packed = zfs_alloc(hdl, packed_len);
uLongf packed_len_long = packed_len;
if (uncompress(packed, &packed_len_long, compressed, len) != Z_OK ||
packed_len_long != packed_len) {
free(packed);
free(compressed);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"resume token is corrupt (decompression failed)"));
return (NULL);
}
/* unpack nvlist */
nvlist_t *nv;
int error = nvlist_unpack(packed, packed_len, &nv, KM_SLEEP);
free(packed);
free(compressed);
if (error != 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"resume token is corrupt (nvlist_unpack failed)"));
return (NULL);
}
return (nv);
}
int
zfs_send_resume(libzfs_handle_t *hdl, sendflags_t *flags, int outfd,
const char *resume_token)
{
char errbuf[1024];
char *toname;
char *fromname = NULL;
uint64_t resumeobj, resumeoff, toguid, fromguid, bytes;
zfs_handle_t *zhp;
int error = 0;
char name[ZFS_MAXNAMELEN];
enum lzc_send_flags lzc_flags = 0;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot resume send"));
nvlist_t *resume_nvl =
zfs_send_resume_token_to_nvlist(hdl, resume_token);
if (resume_nvl == NULL) {
/*
* zfs_error_aux has already been set by
* zfs_send_resume_token_to_nvlist
*/
return (zfs_error(hdl, EZFS_FAULT, errbuf));
}
if (flags->verbose) {
(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
"resume token contents:\n"));
nvlist_print(stderr, resume_nvl);
}
if (nvlist_lookup_string(resume_nvl, "toname", &toname) != 0 ||
nvlist_lookup_uint64(resume_nvl, "object", &resumeobj) != 0 ||
nvlist_lookup_uint64(resume_nvl, "offset", &resumeoff) != 0 ||
nvlist_lookup_uint64(resume_nvl, "bytes", &bytes) != 0 ||
nvlist_lookup_uint64(resume_nvl, "toguid", &toguid) != 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"resume token is corrupt"));
return (zfs_error(hdl, EZFS_FAULT, errbuf));
}
fromguid = 0;
(void) nvlist_lookup_uint64(resume_nvl, "fromguid", &fromguid);
if (flags->embed_data || nvlist_exists(resume_nvl, "embedok"))
lzc_flags |= LZC_SEND_FLAG_EMBED_DATA;
if (guid_to_name(hdl, toname, toguid, B_FALSE, name) != 0) {
if (zfs_dataset_exists(hdl, toname, ZFS_TYPE_DATASET)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"'%s' is no longer the same snapshot used in "
"the initial send"), toname);
} else {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"'%s' used in the initial send no longer exists"),
toname);
}
return (zfs_error(hdl, EZFS_BADPATH, errbuf));
}
zhp = zfs_open(hdl, name, ZFS_TYPE_DATASET);
if (zhp == NULL) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"unable to access '%s'"), name);
return (zfs_error(hdl, EZFS_BADPATH, errbuf));
}
if (fromguid != 0) {
if (guid_to_name(hdl, toname, fromguid, B_TRUE, name) != 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"incremental source %#llx no longer exists"),
(longlong_t)fromguid);
return (zfs_error(hdl, EZFS_BADPATH, errbuf));
}
fromname = name;
}
if (flags->verbose) {
uint64_t size = 0;
error = lzc_send_space(zhp->zfs_name, fromname, &size);
if (error == 0)
size = MAX(0, (int64_t)(size - bytes));
send_print_verbose(stderr, zhp->zfs_name, fromname,
size, flags->parsable);
}
if (!flags->dryrun) {
progress_arg_t pa = { 0 };
pthread_t tid;
/*
* If progress reporting is requested, spawn a new thread to
* poll ZFS_IOC_SEND_PROGRESS at a regular interval.
*/
if (flags->progress) {
pa.pa_zhp = zhp;
pa.pa_fd = outfd;
pa.pa_parsable = flags->parsable;
error = pthread_create(&tid, NULL,
send_progress_thread, &pa);
if (error != 0) {
zfs_close(zhp);
return (error);
}
}
error = lzc_send_resume(zhp->zfs_name, fromname, outfd,
lzc_flags, resumeobj, resumeoff);
if (flags->progress) {
(void) pthread_cancel(tid);
(void) pthread_join(tid, NULL);
}
char errbuf[1024];
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"warning: cannot send '%s'"), zhp->zfs_name);
zfs_close(zhp);
switch (error) {
case 0:
return (0);
case EXDEV:
case ENOENT:
case EDQUOT:
case EFBIG:
case EIO:
case ENOLINK:
case ENOSPC:
#ifdef illumos
case ENOSTR:
#endif
case ENXIO:
case EPIPE:
case ERANGE:
case EFAULT:
case EROFS:
zfs_error_aux(hdl, strerror(errno));
return (zfs_error(hdl, EZFS_BADBACKUP, errbuf));
default:
return (zfs_standard_error(hdl, errno, errbuf));
}
}
zfs_close(zhp);
return (error);
}
/*
* Generate a send stream for the dataset identified by the argument zhp.
*
@ -1388,6 +1638,7 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
int pipefd[2];
dedup_arg_t dda = { 0 };
int featureflags = 0;
FILE *fout;
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot send '%s'"), zhp->zfs_name);
@ -1515,6 +1766,9 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
sdd.filter_cb_arg = cb_arg;
if (debugnvp)
sdd.debugnv = *debugnvp;
if (sdd.verbose && sdd.dryrun)
sdd.std_out = B_TRUE;
fout = sdd.std_out ? stdout : stderr;
/*
* Some flags require that we place user holds on the datasets that are
@ -1554,12 +1808,12 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
if (flags->verbose) {
if (flags->parsable) {
(void) fprintf(stderr, "size\t%llu\n",
(void) fprintf(fout, "size\t%llu\n",
(longlong_t)sdd.size);
} else {
char buf[16];
zfs_nicenum(sdd.size, buf, sizeof (buf));
(void) fprintf(stderr, dgettext(TEXT_DOMAIN,
(void) fprintf(fout, dgettext(TEXT_DOMAIN,
"total estimated size is %s\n"), buf);
}
}
@ -1891,6 +2145,7 @@ recv_destroy(libzfs_handle_t *hdl, const char *name, int baselen,
typedef struct guid_to_name_data {
uint64_t guid;
boolean_t bookmark_ok;
char *name;
char *skip;
} guid_to_name_data_t;
@ -1899,20 +2154,25 @@ static int
guid_to_name_cb(zfs_handle_t *zhp, void *arg)
{
guid_to_name_data_t *gtnd = arg;
const char *slash;
int err;
if (gtnd->skip != NULL &&
strcmp(zhp->zfs_name, gtnd->skip) == 0) {
(slash = strrchr(zhp->zfs_name, '/')) != NULL &&
strcmp(slash + 1, gtnd->skip) == 0) {
zfs_close(zhp);
return (0);
}
if (zhp->zfs_dmustats.dds_guid == gtnd->guid) {
if (zfs_prop_get_int(zhp, ZFS_PROP_GUID) == gtnd->guid) {
(void) strcpy(gtnd->name, zhp->zfs_name);
zfs_close(zhp);
return (EEXIST);
}
err = zfs_iter_children(zhp, guid_to_name_cb, gtnd);
if (err != EEXIST && gtnd->bookmark_ok)
err = zfs_iter_bookmarks(zhp, guid_to_name_cb, gtnd);
zfs_close(zhp);
return (err);
}
@ -1926,45 +2186,48 @@ guid_to_name_cb(zfs_handle_t *zhp, void *arg)
*/
static int
guid_to_name(libzfs_handle_t *hdl, const char *parent, uint64_t guid,
char *name)
boolean_t bookmark_ok, char *name)
{
/* exhaustive search all local snapshots */
char pname[ZFS_MAXNAMELEN];
guid_to_name_data_t gtnd;
int err = 0;
zfs_handle_t *zhp;
char *cp;
gtnd.guid = guid;
gtnd.bookmark_ok = bookmark_ok;
gtnd.name = name;
gtnd.skip = NULL;
(void) strlcpy(pname, parent, sizeof (pname));
/*
* Search progressively larger portions of the hierarchy. This will
* Search progressively larger portions of the hierarchy, starting
* with the filesystem specified by 'parent'. This will
* select the "most local" version of the origin snapshot in the case
* that there are multiple matching snapshots in the system.
*/
while ((cp = strrchr(pname, '/')) != NULL) {
(void) strlcpy(pname, parent, sizeof (pname));
char *cp = strrchr(pname, '@');
if (cp == NULL)
cp = strchr(pname, '\0');
for (; cp != NULL; cp = strrchr(pname, '/')) {
/* Chop off the last component and open the parent */
*cp = '\0';
zhp = make_dataset_handle(hdl, pname);
zfs_handle_t *zhp = make_dataset_handle(hdl, pname);
if (zhp == NULL)
continue;
err = zfs_iter_children(zhp, guid_to_name_cb, &gtnd);
int err = guid_to_name_cb(zfs_handle_dup(zhp), &gtnd);
if (err != EEXIST)
err = zfs_iter_children(zhp, guid_to_name_cb, &gtnd);
if (err != EEXIST && bookmark_ok)
err = zfs_iter_bookmarks(zhp, guid_to_name_cb, &gtnd);
zfs_close(zhp);
if (err == EEXIST)
return (0);
/*
* Remember the dataset that we already searched, so we
* skip it next time through.
* Remember the last portion of the dataset so we skip it next
* time through (as we've already searched that portion of the
* hierarchy).
*/
gtnd.skip = pname;
gtnd.skip = strrchr(pname, '/') + 1;
}
return (ENOENT);
@ -2562,11 +2825,9 @@ recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
switch (drr->drr_type) {
case DRR_BEGIN:
/* NB: not to be used on v2 stream packages */
if (drr->drr_payloadlen != 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"invalid substream header"));
return (zfs_error(hdl, EZFS_BADSTREAM, errbuf));
(void) recv_read(hdl, fd, buf,
drr->drr_payloadlen, B_FALSE, NULL);
}
break;
@ -2627,6 +2888,40 @@ recv_skip(libzfs_handle_t *hdl, int fd, boolean_t byteswap)
return (-1);
}
static void
recv_ecksum_set_aux(libzfs_handle_t *hdl, const char *target_snap,
boolean_t resumable)
{
char target_fs[ZFS_MAXNAMELEN];
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"checksum mismatch or incomplete stream"));
if (!resumable)
return;
(void) strlcpy(target_fs, target_snap, sizeof (target_fs));
*strchr(target_fs, '@') = '\0';
zfs_handle_t *zhp = zfs_open(hdl, target_fs,
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
if (zhp == NULL)
return;
char token_buf[ZFS_MAXPROPLEN];
int error = zfs_prop_get(zhp, ZFS_PROP_RECEIVE_RESUME_TOKEN,
token_buf, sizeof (token_buf),
NULL, NULL, 0, B_TRUE);
if (error == 0) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"checksum mismatch or incomplete stream.\n"
"Partially received snapshot is saved.\n"
"A resuming stream can be generated on the sending "
"system by running:\n"
" zfs send -t %s"),
token_buf);
}
zfs_close(zhp);
}
/*
* Restores a backup of tosnap from the file descriptor specified by infd.
*/
@ -2790,7 +3085,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
*/
if (drrb->drr_flags & DRR_FLAG_CLONE) {
if (guid_to_name(hdl, zc.zc_value,
drrb->drr_fromguid, zc.zc_string) != 0) {
drrb->drr_fromguid, B_FALSE, zc.zc_string) != 0) {
zcmd_free_nvlists(&zc);
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"local origin for clone %s does not exist"),
@ -2806,8 +3101,10 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
zc.zc_string);
}
boolean_t resuming = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo) &
DMU_BACKUP_FEATURE_RESUMING;
stream_wantsnewfs = (drrb->drr_fromguid == 0 ||
(drrb->drr_flags & DRR_FLAG_CLONE) || originsnap);
(drrb->drr_flags & DRR_FLAG_CLONE) || originsnap) && !resuming;
if (stream_wantsnewfs) {
/*
@ -2826,7 +3123,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
char suffix[ZFS_MAXNAMELEN];
(void) strcpy(suffix, strrchr(zc.zc_value, '/'));
if (guid_to_name(hdl, zc.zc_name, parent_snapguid,
zc.zc_value) == 0) {
B_FALSE, zc.zc_value) == 0) {
*strchr(zc.zc_value, '@') = '\0';
(void) strcat(zc.zc_value, suffix);
}
@ -2853,7 +3150,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
char snap[ZFS_MAXNAMELEN];
(void) strcpy(snap, strchr(zc.zc_value, '@'));
if (guid_to_name(hdl, zc.zc_name, drrb->drr_fromguid,
zc.zc_value) == 0) {
B_FALSE, zc.zc_value) == 0) {
*strchr(zc.zc_value, '@') = '\0';
(void) strcat(zc.zc_value, snap);
}
@ -2867,11 +3164,12 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
zfs_handle_t *zhp;
/*
* Destination fs exists. Therefore this should either
* be an incremental, or the stream specifies a new fs
* (full stream or clone) and they want us to blow it
* away (and have therefore specified -F and removed any
* snapshots).
* Destination fs exists. It must be one of these cases:
* - an incremental send stream
* - the stream specifies a new fs (full stream or clone)
* and they want us to blow away the existing fs (and
* have therefore specified -F and removed any snapshots)
* - we are resuming a failed receive.
*/
if (stream_wantsnewfs) {
if (!flags->force) {
@ -2926,6 +3224,18 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
return (-1);
}
}
/*
* If we are resuming a newfs, set newfs here so that we will
* mount it if the recv succeeds this time. We can tell
* that it was a newfs on the first recv because the fs
* itself will be inconsistent (if the fs existed when we
* did the first recv, we would have received it into
* .../%recv).
*/
if (resuming && zfs_prop_get_int(zhp, ZFS_PROP_INCONSISTENT))
newfs = B_TRUE;
zfs_close(zhp);
} else {
/*
@ -2958,9 +3268,10 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
newfs = B_TRUE;
}
zc.zc_begin_record = drr_noswap->drr_u.drr_begin;
zc.zc_begin_record = *drr_noswap;
zc.zc_cookie = infd;
zc.zc_guid = flags->force;
zc.zc_resumable = flags->resumable;
if (flags->verbose) {
(void) printf("%s %s stream of %s into %s\n",
flags->dryrun ? "would receive" : "receiving",
@ -3097,8 +3408,7 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
case ECKSUM:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"invalid stream (checksum mismatch)"));
recv_ecksum_set_aux(hdl, zc.zc_value, flags->resumable);
(void) zfs_error(hdl, EZFS_BADSTREAM, errbuf);
break;
case ENOTSUP:
@ -3300,7 +3610,8 @@ zfs_receive_impl(libzfs_handle_t *hdl, const char *tosnap,
* Restores a backup of tosnap from the file descriptor specified by infd.
* Return 0 on total success, -2 if some things couldn't be
* destroyed/renamed/promoted, -1 if some things couldn't be received.
* (-1 will override -2).
* (-1 will override -2, if -1 and the resumable flag was specified the
* transfer can be resumed if the sending side supports it).
*/
int
zfs_receive(libzfs_handle_t *hdl, const char *tosnap, nvlist_t *props,

View file

@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2011, 2015 by Delphix. All rights reserved.
*/
/*
@ -782,8 +782,9 @@ zcmd_alloc_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc, size_t len)
if (len == 0)
len = 16 * 1024;
zc->zc_nvlist_dst_size = len;
if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
zfs_alloc(hdl, zc->zc_nvlist_dst_size)) == 0)
zc->zc_nvlist_dst =
(uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
if (zc->zc_nvlist_dst == 0)
return (-1);
return (0);
@ -798,9 +799,9 @@ int
zcmd_expand_dst_nvlist(libzfs_handle_t *hdl, zfs_cmd_t *zc)
{
free((void *)(uintptr_t)zc->zc_nvlist_dst);
if ((zc->zc_nvlist_dst = (uint64_t)(uintptr_t)
zfs_alloc(hdl, zc->zc_nvlist_dst_size))
== 0)
zc->zc_nvlist_dst =
(uint64_t)(uintptr_t)zfs_alloc(hdl, zc->zc_nvlist_dst_size);
if (zc->zc_nvlist_dst == 0)
return (-1);
return (0);
@ -815,6 +816,9 @@ zcmd_free_nvlists(zfs_cmd_t *zc)
free((void *)(uintptr_t)zc->zc_nvlist_conf);
free((void *)(uintptr_t)zc->zc_nvlist_src);
free((void *)(uintptr_t)zc->zc_nvlist_dst);
zc->zc_nvlist_conf = NULL;
zc->zc_nvlist_src = NULL;
zc->zc_nvlist_dst = NULL;
}
static int

View file

@ -514,6 +514,13 @@ lzc_get_holds(const char *snapname, nvlist_t **holdsp)
int
lzc_send(const char *snapname, const char *from, int fd,
enum lzc_send_flags flags)
{
return (lzc_send_resume(snapname, from, fd, flags, 0, 0));
}
int
lzc_send_resume(const char *snapname, const char *from, int fd,
enum lzc_send_flags flags, uint64_t resumeobj, uint64_t resumeoff)
{
nvlist_t *args;
int err;
@ -526,6 +533,10 @@ lzc_send(const char *snapname, const char *from, int fd,
fnvlist_add_boolean(args, "largeblockok");
if (flags & LZC_SEND_FLAG_EMBED_DATA)
fnvlist_add_boolean(args, "embedok");
if (resumeobj != 0 || resumeoff != 0) {
fnvlist_add_uint64(args, "resume_object", resumeobj);
fnvlist_add_uint64(args, "resume_offset", resumeoff);
}
err = lzc_ioctl(ZFS_IOC_SEND_NEW, snapname, args, NULL);
nvlist_free(args);
return (err);
@ -583,22 +594,9 @@ recv_read(int fd, void *buf, int ilen)
return (0);
}
/*
* The simplest receive case: receive from the specified fd, creating the
* specified snapshot. Apply the specified properties a "received" properties
* (which can be overridden by locally-set properties). If the stream is a
* clone, its origin snapshot must be specified by 'origin'. The 'force'
* flag will cause the target filesystem to be rolled back or destroyed if
* necessary to receive.
*
* Return 0 on success or an errno on failure.
*
* Note: this interface does not work on dedup'd streams
* (those with DMU_BACKUP_FEATURE_DEDUP).
*/
int
lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
boolean_t force, int fd)
static int
lzc_receive_impl(const char *snapname, nvlist_t *props, const char *origin,
boolean_t force, boolean_t resumable, int fd)
{
/*
* The receive ioctl is still legacy, so we need to construct our own
@ -608,7 +606,6 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
char *atp;
char *packed = NULL;
size_t size;
dmu_replay_record_t drr;
int error;
ASSERT3S(g_refcount, >, 0);
@ -644,10 +641,9 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
(void) strlcpy(zc.zc_string, origin, sizeof (zc.zc_string));
/* zc_begin_record is non-byteswapped BEGIN record */
error = recv_read(fd, &drr, sizeof (drr));
error = recv_read(fd, &zc.zc_begin_record, sizeof (zc.zc_begin_record));
if (error != 0)
goto out;
zc.zc_begin_record = drr.drr_u.drr_begin;
/* zc_cookie is fd to read from */
zc.zc_cookie = fd;
@ -655,6 +651,8 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
/* zc guid is force flag */
zc.zc_guid = force;
zc.zc_resumable = resumable;
/* zc_cleanup_fd is unused */
zc.zc_cleanup_fd = -1;
@ -669,6 +667,39 @@ lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
return (error);
}
/*
* The simplest receive case: receive from the specified fd, creating the
* specified snapshot. Apply the specified properties as "received" properties
* (which can be overridden by locally-set properties). If the stream is a
* clone, its origin snapshot must be specified by 'origin'. The 'force'
* flag will cause the target filesystem to be rolled back or destroyed if
* necessary to receive.
*
* Return 0 on success or an errno on failure.
*
* Note: this interface does not work on dedup'd streams
* (those with DMU_BACKUP_FEATURE_DEDUP).
*/
int
lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
boolean_t force, int fd)
{
return (lzc_receive_impl(snapname, props, origin, force, B_FALSE, fd));
}
/*
* Like lzc_receive, but if the receive fails due to premature stream
* termination, the intermediate state will be preserved on disk. In this
* case, ECKSUM will be returned. The receive may subsequently be resumed
* with a resuming send stream generated by lzc_send_resume().
*/
int
lzc_receive_resumable(const char *snapname, nvlist_t *props, const char *origin,
boolean_t force, int fd)
{
return (lzc_receive_impl(snapname, props, origin, force, B_TRUE, fd));
}
/*
* Roll back this filesystem or volume to its most recent snapshot.
* If snapnamebuf is not NULL, it will be filled in with the name

View file

@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2013 by Martin Matuska <mm@FreeBSD.org>. All rights reserved.
*/
@ -59,7 +59,11 @@ enum lzc_send_flags {
};
int lzc_send(const char *, const char *, int, enum lzc_send_flags);
int lzc_send_resume(const char *, const char *, int,
enum lzc_send_flags, uint64_t, uint64_t);
int lzc_receive(const char *, nvlist_t *, const char *, boolean_t, int);
int lzc_receive_resumable(const char *, nvlist_t *, const char *,
boolean_t, int);
int lzc_send_space(const char *, const char *, uint64_t *);
boolean_t lzc_exists(const char *);

View file

@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2012, 2015 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
@ -523,7 +523,7 @@ vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
/*ARGSUSED*/
int
vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
{
ssize_t iolen, split;

View file

@ -8,10 +8,10 @@
LIB= zfs
DPADD= ${LIBMD} ${LIBPTHREAD} ${LIBUMEM} ${LIBUTIL} ${LIBM} ${LIBNVPAIR} \
${LIBAVL} ${LIBZFS_CORE} ${LIBUUTIL} ${LIBBSDXML} ${LIBGEOM} \
${LIBNVPAIR}
${LIBNVPAIR} ${LIBZ}
LDADD= -lmd -lpthread -lumem -lutil -luutil -lm -lnvpair -lavl \
-lbsdxml -lgeom -lnvpair -lzfs_core
-lbsdxml -lgeom -lnvpair -lz -lzfs_core
SRCS= deviceid.c \
fsshare.c \

View file

@ -0,0 +1,182 @@
Pull in r248379 from upstream clang trunk (by Jörg Sonnenberger):
Refactor library decision for -fopenmp support from Darwin into a
function for sharing with other platforms.
Pull in r248424 from upstream clang trunk (by Jörg Sonnenberger):
Push OpenMP linker flags after linker input on Darwin. Don't add any
libraries if -nostdlib is specified. Test.
Pull in r248426 from upstream clang trunk (by Jörg Sonnenberger):
Support linking against OpenMP runtime on NetBSD.
Pull in r250657 from upstream clang trunk (by Dimitry Andric):
Support linking against OpenMP runtime on FreeBSD.
Introduced here: http://svnweb.freebsd.org/changeset/base/289523
Index: tools/clang/lib/Driver/Tools.cpp
===================================================================
--- tools/clang/lib/Driver/Tools.cpp
+++ tools/clang/lib/Driver/Tools.cpp
@@ -2460,6 +2460,28 @@ static OpenMPRuntimeKind getOpenMPRuntime(const To
return RT;
}
+static void addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
+ const ArgList &Args) {
+ if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
+ options::OPT_fno_openmp, false))
+ return;
+
+ switch (getOpenMPRuntime(TC, Args)) {
+ case OMPRT_OMP:
+ CmdArgs.push_back("-lomp");
+ break;
+ case OMPRT_GOMP:
+ CmdArgs.push_back("-lgomp");
+ break;
+ case OMPRT_IOMP5:
+ CmdArgs.push_back("-liomp5");
+ break;
+ case OMPRT_Unknown:
+ // Already diagnosed.
+ break;
+ }
+}
+
static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, StringRef Sanitizer,
bool IsShared) {
@@ -6527,24 +6549,6 @@ void darwin::Linker::ConstructJob(Compilation &C,
Args.AddAllArgs(CmdArgs, options::OPT_L);
- if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
- options::OPT_fno_openmp, false)) {
- switch (getOpenMPRuntime(getToolChain(), Args)) {
- case OMPRT_OMP:
- CmdArgs.push_back("-lomp");
- break;
- case OMPRT_GOMP:
- CmdArgs.push_back("-lgomp");
- break;
- case OMPRT_IOMP5:
- CmdArgs.push_back("-liomp5");
- break;
- case OMPRT_Unknown:
- // Already diagnosed.
- break;
- }
- }
-
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
// Build the input file for -filelist (list of linker input files) in case we
// need it later
@@ -6563,6 +6567,10 @@ void darwin::Linker::ConstructJob(Compilation &C,
InputFileList.push_back(II.getFilename());
}
+ if (!Args.hasArg(options::OPT_nostdlib) &&
+ !Args.hasArg(options::OPT_nodefaultlibs))
+ addOpenMPRuntime(CmdArgs, getToolChain(), Args);
+
if (isObjCRuntimeLinked(Args) && !Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
// We use arclite library for both ARC and subscripting support.
@@ -7358,6 +7366,7 @@ void freebsd::Linker::ConstructJob(Compilation &C,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
+ addOpenMPRuntime(CmdArgs, ToolChain, Args);
if (D.CCCIsCXX()) {
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
@@ -7673,6 +7682,7 @@ void netbsd::Linker::ConstructJob(Compilation &C,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
+ addOpenMPRuntime(CmdArgs, getToolChain(), Args);
if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");
Index: tools/clang/test/Driver/fopenmp.c
===================================================================
--- tools/clang/test/Driver/fopenmp.c
+++ tools/clang/test/Driver/fopenmp.c
@@ -1,6 +1,15 @@
// RUN: %clang -target x86_64-linux-gnu -fopenmp=libomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
// RUN: %clang -target x86_64-linux-gnu -fopenmp=libgomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-NO-OPENMP
// RUN: %clang -target x86_64-linux-gnu -fopenmp=libiomp5 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
+// RUN: %clang -target x86_64-apple-darwin -fopenmp=libomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
+// RUN: %clang -target x86_64-apple-darwin -fopenmp=libgomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-NO-OPENMP
+// RUN: %clang -target x86_64-apple-darwin -fopenmp=libiomp5 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
+// RUN: %clang -target x86_64-freebsd -fopenmp=libomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
+// RUN: %clang -target x86_64-freebsd -fopenmp=libgomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-NO-OPENMP
+// RUN: %clang -target x86_64-freebsd -fopenmp=libiomp5 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
+// RUN: %clang -target x86_64-netbsd -fopenmp=libomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
+// RUN: %clang -target x86_64-netbsd -fopenmp=libgomp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-NO-OPENMP
+// RUN: %clang -target x86_64-netbsd -fopenmp=libiomp5 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CC1-OPENMP
//
// CHECK-CC1-OPENMP: "-cc1"
// CHECK-CC1-OPENMP: "-fopenmp"
@@ -12,6 +21,30 @@
// RUN: %clang -target x86_64-linux-gnu -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-GOMP
// RUN: %clang -target x86_64-linux-gnu -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-IOMP5
//
+// RUN: %clang -nostdlib -target x86_64-linux-gnu -fopenmp=libomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OMP
+// RUN: %clang -nostdlib -target x86_64-linux-gnu -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-GOMP
+// RUN: %clang -nostdlib -target x86_64-linux-gnu -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-IOMP5
+//
+// RUN: %clang -target x86_64-darwin -fopenmp=libomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-OMP
+// RUN: %clang -target x86_64-darwin -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-GOMP
+// RUN: %clang -target x86_64-darwin -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-IOMP5
+//
+// RUN: %clang -nostdlib -target x86_64-darwin -fopenmp=libomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OMP
+// RUN: %clang -nostdlib -target x86_64-darwin -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-GOMP
+// RUN: %clang -nostdlib -target x86_64-darwin -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-IOMP5
+//
+// RUN: %clang -target x86_64-netbsd -fopenmp=libomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-OMP
+// RUN: %clang -target x86_64-netbsd -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-GOMP
+// RUN: %clang -target x86_64-netbsd -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-IOMP5
+//
+// RUN: %clang -nostdlib -target x86_64-freebsd -fopenmp=libomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OMP
+// RUN: %clang -nostdlib -target x86_64-freebsd -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-GOMP
+// RUN: %clang -nostdlib -target x86_64-freebsd -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-IOMP5
+//
+// RUN: %clang -nostdlib -target x86_64-netbsd -fopenmp=libomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-OMP
+// RUN: %clang -nostdlib -target x86_64-netbsd -fopenmp=libgomp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-GOMP
+// RUN: %clang -nostdlib -target x86_64-netbsd -fopenmp=libiomp5 %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-IOMP5
+//
// CHECK-LD-OMP: "{{.*}}ld{{(.exe)?}}"
// CHECK-LD-OMP: "-lomp"
//
@@ -21,6 +54,15 @@
// CHECK-LD-IOMP5: "{{.*}}ld{{(.exe)?}}"
// CHECK-LD-IOMP5: "-liomp5"
//
+// CHECK-NO-OMP: "{{.*}}ld{{(.exe)?}}"
+// CHECK-NO-OMP-NOT: "-lomp"
+//
+// CHECK-NO-GOMP: "{{.*}}ld{{(.exe)?}}"
+// CHECK-NO-GOMP-NOT: "-lgomp"
+//
+// CHECK-NO-IOMP5: "{{.*}}ld{{(.exe)?}}"
+// CHECK-NO-IOMP5-NOT: "-liomp5"
+//
// We'd like to check that the default is sane, but until we have the ability
// to *always* semantically analyze OpenMP without always generating runtime
// calls (in the event of an unsupported runtime), we don't have a good way to
@@ -28,6 +70,9 @@
// OpenMP runtime.
//
// RUN: %clang -target x86_64-linux-gnu -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANY
+// RUN: %clang -target x86_64-darwin -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANY
+// RUN: %clang -target x86_64-freebsd -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANY
+// RUN: %clang -target x86_64-netbsd -fopenmp %s -o %t -### 2>&1 | FileCheck %s --check-prefix=CHECK-LD-ANY
//
// CHECK-LD-ANY: "{{.*}}ld{{(.exe)?}}"
// CHECK-LD-ANY: "-l{{(omp|gomp|iomp5)}}"

View file

@ -2460,6 +2460,28 @@ static OpenMPRuntimeKind getOpenMPRuntime(const ToolChain &TC,
return RT;
}
static void addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
const ArgList &Args) {
if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false))
return;
switch (getOpenMPRuntime(TC, Args)) {
case OMPRT_OMP:
CmdArgs.push_back("-lomp");
break;
case OMPRT_GOMP:
CmdArgs.push_back("-lgomp");
break;
case OMPRT_IOMP5:
CmdArgs.push_back("-liomp5");
break;
case OMPRT_Unknown:
// Already diagnosed.
break;
}
}
static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs, StringRef Sanitizer,
bool IsShared) {
@ -6527,24 +6549,6 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddAllArgs(CmdArgs, options::OPT_L);
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false)) {
switch (getOpenMPRuntime(getToolChain(), Args)) {
case OMPRT_OMP:
CmdArgs.push_back("-lomp");
break;
case OMPRT_GOMP:
CmdArgs.push_back("-lgomp");
break;
case OMPRT_IOMP5:
CmdArgs.push_back("-liomp5");
break;
case OMPRT_Unknown:
// Already diagnosed.
break;
}
}
AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs);
// Build the input file for -filelist (list of linker input files) in case we
// need it later
@ -6563,6 +6567,10 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
InputFileList.push_back(II.getFilename());
}
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs))
addOpenMPRuntime(CmdArgs, getToolChain(), Args);
if (isObjCRuntimeLinked(Args) && !Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
// We use arclite library for both ARC and subscripting support.
@ -7358,6 +7366,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
addOpenMPRuntime(CmdArgs, ToolChain, Args);
if (D.CCCIsCXX()) {
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
if (Args.hasArg(options::OPT_pg))
@ -7673,6 +7682,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasArg(options::OPT_nostdlib) &&
!Args.hasArg(options::OPT_nodefaultlibs)) {
addOpenMPRuntime(CmdArgs, getToolChain(), Args);
if (D.CCCIsCXX()) {
getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
CmdArgs.push_back("-lm");

View file

@ -44,6 +44,12 @@ length_head() {
"the one expected to fail. (NetBSD PR bin/8521)"
}
length_body() {
# Begin FreeBSD
if ! df /dev/fd | grep -q '^fdescfs'; then
atf_skip "fdescfs is not mounted on /dev/fd"
fi
# End FreeBSD
test_dd_length 512 \
"dd if=/dev/zero of=/dev/fd/5 count=1 5>&1 >/dev/null 2>/dev/null"
test_dd_length 512 \

View file

@ -481,7 +481,7 @@ kill \-HUP `cat @UNBOUND_PIDFILE@`
.fi
triggers a reload,
.nf
kill \-QUIT `cat @UNBOUND_PIDFILE@`
kill \-TERM `cat @UNBOUND_PIDFILE@`
.fi
gracefully terminates.
.TP

View file

@ -1,5 +1,41 @@
ChangeLog for hostapd
2015-09-27 - v2.5
* fixed WPS UPnP vulnerability with HTTP chunked transfer encoding
[http://w1.fi/security/2015-2/] (CVE-2015-4141)
* fixed WMM Action frame parser
[http://w1.fi/security/2015-3/] (CVE-2015-4142)
* fixed EAP-pwd server missing payload length validation
[http://w1.fi/security/2015-4/]
(CVE-2015-4143, CVE-2015-4144, CVE-2015-4145)
* fixed validation of WPS and P2P NFC NDEF record payload length
[http://w1.fi/security/2015-5/]
* nl80211:
- fixed vendor command handling to check OUI properly
* fixed hlr_auc_gw build with OpenSSL
* hlr_auc_gw: allow Milenage RES length to be reduced
* disable HT for a station that does not support WMM/QoS
* added support for hashed password (NtHash) in EAP-pwd server
* fixed and extended dynamic VLAN cases
* added EAP-EKE server support for deriving Session-Id
* set Acct-Session-Id to a random value to make it more likely to be
unique even if the device does not have a proper clock
* added more 2.4 GHz channels for 20/40 MHz HT co-ex scan
* modified SAE routines to be more robust and PWE generation to be
stronger against timing attacks
* added support for Brainpool Elliptic Curves with SAE
* increases maximum value accepted for cwmin/cwmax
* added support for CCMP-256 and GCMP-256 as group ciphers with FT
* added Fast Session Transfer (FST) module
* removed optional fields from RSNE when using FT with PMF
(workaround for interoperability issues with iOS 8.4)
* added EAP server support for TLS session resumption
* fixed key derivation for Suite B 192-bit AKM (this breaks
compatibility with the earlier version)
* added mechanism to track unconnected stations and do minimal band
steering
* number of small fixes
2015-03-15 - v2.4
* allow OpenSSL cipher configuration to be set for internal EAP server
(openssl_ciphers parameter)

View file

@ -222,9 +222,15 @@ static int hostapd_config_read_eap_user(const char *fname,
return 0;
if (os_strncmp(fname, "sqlite:", 7) == 0) {
#ifdef CONFIG_SQLITE
os_free(conf->eap_user_sqlite);
conf->eap_user_sqlite = os_strdup(fname + 7);
return 0;
#else /* CONFIG_SQLITE */
wpa_printf(MSG_ERROR,
"EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build.");
return -1;
#endif /* CONFIG_SQLITE */
}
f = fopen(fname, "r");
@ -775,6 +781,24 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
}
static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val)
{
char *pos;
/* for backwards compatibility, translate ' ' in conf str to ',' */
pos = val;
while (pos) {
pos = os_strchr(pos, ' ');
if (pos)
*pos++ = ',';
}
if (freq_range_list_parse(&conf->acs_ch_list, val))
return -1;
return 0;
}
static int hostapd_parse_intlist(int **int_list, char *val)
{
int *list;
@ -875,7 +899,9 @@ static int hostapd_config_read_int10(const char *value)
static int valid_cw(int cw)
{
return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 ||
cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023);
cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 ||
cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 ||
cw == 32767);
}
@ -886,11 +912,11 @@ enum {
IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */
};
static int hostapd_config_tx_queue(struct hostapd_config *conf, char *name,
char *val)
static int hostapd_config_tx_queue(struct hostapd_config *conf,
const char *name, const char *val)
{
int num;
char *pos;
const char *pos;
struct hostapd_tx_queue_params *queue;
/* skip 'tx_queue_' prefix */
@ -1134,13 +1160,23 @@ static int hostapd_config_vht_capab(struct hostapd_config *conf,
if (os_strstr(capab, "[BF-ANTENNA-2]") &&
(conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
conf->vht_capab |= (1 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
if (os_strstr(capab, "[BF-ANTENNA-3]") &&
(conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
conf->vht_capab |= (2 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
if (os_strstr(capab, "[BF-ANTENNA-4]") &&
(conf->vht_capab & VHT_CAP_SU_BEAMFORMEE_CAPABLE))
conf->vht_capab |= (3 << VHT_CAP_BEAMFORMEE_STS_OFFSET);
if (os_strstr(capab, "[SOUNDING-DIMENSION-2]") &&
(conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
conf->vht_capab |= (1 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
if (os_strstr(capab, "[SOUNDING-DIMENSION-3]") &&
(conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
conf->vht_capab |= (2 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
if (os_strstr(capab, "[SOUNDING-DIMENSION-4]") &&
(conf->vht_capab & VHT_CAP_SU_BEAMFORMER_CAPABLE))
conf->vht_capab |= (3 << VHT_CAP_SOUNDING_DIMENSION_OFFSET);
if (os_strstr(capab, "[MU-BEAMFORMER]"))
conf->vht_capab |= VHT_CAP_MU_BEAMFORMER_CAPABLE;
if (os_strstr(capab, "[MU-BEAMFORMEE]"))
conf->vht_capab |= VHT_CAP_MU_BEAMFORMEE_CAPABLE;
if (os_strstr(capab, "[VHT-TXOP-PS]"))
conf->vht_capab |= VHT_CAP_VHT_TXOP_PS;
if (os_strstr(capab, "[HTC-VHT]"))
@ -1699,7 +1735,7 @@ static int hs20_parse_osu_ssid(struct hostapd_bss_config *bss,
char *str;
str = wpa_config_parse_string(pos, &slen);
if (str == NULL || slen < 1 || slen > HOSTAPD_MAX_SSID_LEN) {
if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
wpa_printf(MSG_ERROR, "Line %d: Invalid SSID '%s'", line, pos);
os_free(str);
return -1;
@ -1900,7 +1936,7 @@ static int hostapd_config_parse_acs_chan_bias(struct hostapd_config *conf,
static int hostapd_config_fill(struct hostapd_config *conf,
struct hostapd_bss_config *bss,
char *buf, char *pos, int line)
const char *buf, char *pos, int line)
{
if (os_strcmp(buf, "interface") == 0) {
os_strlcpy(conf->bss[0]->iface, pos,
@ -1946,7 +1982,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line);
} else if (os_strcmp(buf, "ssid") == 0) {
bss->ssid.ssid_len = os_strlen(pos);
if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN ||
if (bss->ssid.ssid_len > SSID_MAX_LEN ||
bss->ssid.ssid_len < 1) {
wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
line, pos);
@ -1957,7 +1993,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "ssid2") == 0) {
size_t slen;
char *str = wpa_config_parse_string(pos, &slen);
if (str == NULL || slen < 1 || slen > HOSTAPD_MAX_SSID_LEN) {
if (str == NULL || slen < 1 || slen > SSID_MAX_LEN) {
wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'",
line, pos);
os_free(str);
@ -2043,6 +2079,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->private_key_passwd = os_strdup(pos);
} else if (os_strcmp(buf, "check_crl") == 0) {
bss->check_crl = atoi(pos);
} else if (os_strcmp(buf, "tls_session_lifetime") == 0) {
bss->tls_session_lifetime = atoi(pos);
} else if (os_strcmp(buf, "ocsp_stapling_response") == 0) {
os_free(bss->ocsp_stapling_response);
bss->ocsp_stapling_response = os_strdup(pos);
@ -2515,13 +2553,17 @@ static int hostapd_config_fill(struct hostapd_config *conf,
conf->hw_mode = HOSTAPD_MODE_IEEE80211G;
else if (os_strcmp(pos, "ad") == 0)
conf->hw_mode = HOSTAPD_MODE_IEEE80211AD;
else if (os_strcmp(pos, "any") == 0)
conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY;
else {
wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'",
line, pos);
return 1;
}
} else if (os_strcmp(buf, "wps_rf_bands") == 0) {
if (os_strcmp(pos, "a") == 0)
if (os_strcmp(pos, "ad") == 0)
bss->wps_rf_bands = WPS_RF_60GHZ;
else if (os_strcmp(pos, "a") == 0)
bss->wps_rf_bands = WPS_RF_50GHZ;
else if (os_strcmp(pos, "g") == 0 ||
os_strcmp(pos, "b") == 0)
@ -2542,12 +2584,15 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line);
return 1;
#else /* CONFIG_ACS */
conf->acs = 1;
conf->channel = 0;
#endif /* CONFIG_ACS */
} else
} else {
conf->channel = atoi(pos);
conf->acs = conf->channel == 0;
}
} else if (os_strcmp(buf, "chanlist") == 0) {
if (hostapd_parse_intlist(&conf->chanlist, pos)) {
if (hostapd_parse_chanlist(conf, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid channel list",
line);
return 1;
@ -2810,7 +2855,7 @@ static int hostapd_config_fill(struct hostapd_config *conf,
os_free(bss->wps_pin_requests);
bss->wps_pin_requests = os_strdup(pos);
} else if (os_strcmp(buf, "device_name") == 0) {
if (os_strlen(pos) > 32) {
if (os_strlen(pos) > WPS_DEV_NAME_MAX_LEN) {
wpa_printf(MSG_ERROR, "Line %d: Too long "
"device_name", line);
return 1;
@ -3111,6 +3156,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->disable_dgaf = atoi(pos);
} else if (os_strcmp(buf, "proxy_arp") == 0) {
bss->proxy_arp = atoi(pos);
} else if (os_strcmp(buf, "na_mcast_to_ucast") == 0) {
bss->na_mcast_to_ucast = atoi(pos);
} else if (os_strcmp(buf, "osen") == 0) {
bss->osen = atoi(pos);
} else if (os_strcmp(buf, "anqp_domain_id") == 0) {
@ -3223,6 +3270,24 @@ static int hostapd_config_fill(struct hostapd_config *conf,
bss->bss_load_test_set = 1;
} else if (os_strcmp(buf, "radio_measurements") == 0) {
bss->radio_measurements = atoi(pos);
} else if (os_strcmp(buf, "own_ie_override") == 0) {
struct wpabuf *tmp;
size_t len = os_strlen(pos) / 2;
tmp = wpabuf_alloc(len);
if (!tmp)
return 1;
if (hexstr2bin(pos, wpabuf_put(tmp, len), len)) {
wpabuf_free(tmp);
wpa_printf(MSG_ERROR,
"Line %d: Invalid own_ie_override '%s'",
line, pos);
return 1;
}
wpabuf_free(bss->own_ie_override);
bss->own_ie_override = tmp;
#endif /* CONFIG_TESTING_OPTIONS */
} else if (os_strcmp(buf, "vendor_elements") == 0) {
struct wpabuf *elems;
@ -3276,6 +3341,74 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "wowlan_triggers") == 0) {
os_free(bss->wowlan_triggers);
bss->wowlan_triggers = os_strdup(pos);
#ifdef CONFIG_FST
} else if (os_strcmp(buf, "fst_group_id") == 0) {
size_t len = os_strlen(pos);
if (!len || len >= sizeof(conf->fst_cfg.group_id)) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid fst_group_id value '%s'",
line, pos);
return 1;
}
if (conf->fst_cfg.group_id[0]) {
wpa_printf(MSG_ERROR,
"Line %d: Duplicate fst_group value '%s'",
line, pos);
return 1;
}
os_strlcpy(conf->fst_cfg.group_id, pos,
sizeof(conf->fst_cfg.group_id));
} else if (os_strcmp(buf, "fst_priority") == 0) {
char *endp;
long int val;
if (!*pos) {
wpa_printf(MSG_ERROR,
"Line %d: fst_priority value not supplied (expected 1..%u)",
line, FST_MAX_PRIO_VALUE);
return -1;
}
val = strtol(pos, &endp, 0);
if (*endp || val < 1 || val > FST_MAX_PRIO_VALUE) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid fst_priority %ld (%s) (expected 1..%u)",
line, val, pos, FST_MAX_PRIO_VALUE);
return 1;
}
conf->fst_cfg.priority = (u8) val;
} else if (os_strcmp(buf, "fst_llt") == 0) {
char *endp;
long int val;
if (!*pos) {
wpa_printf(MSG_ERROR,
"Line %d: fst_llt value not supplied (expected 1..%u)",
line, FST_MAX_LLT_MS);
return -1;
}
val = strtol(pos, &endp, 0);
if (*endp || val < 1 || val > FST_MAX_LLT_MS) {
wpa_printf(MSG_ERROR,
"Line %d: Invalid fst_llt %ld (%s) (expected 1..%u)",
line, val, pos, FST_MAX_LLT_MS);
return 1;
}
conf->fst_cfg.llt = (u32) val;
#endif /* CONFIG_FST */
} else if (os_strcmp(buf, "track_sta_max_num") == 0) {
conf->track_sta_max_num = atoi(pos);
} else if (os_strcmp(buf, "track_sta_max_age") == 0) {
conf->track_sta_max_age = atoi(pos);
} else if (os_strcmp(buf, "no_probe_resp_if_seen_on") == 0) {
os_free(bss->no_probe_resp_if_seen_on);
bss->no_probe_resp_if_seen_on = os_strdup(pos);
} else if (os_strcmp(buf, "no_auth_if_seen_on") == 0) {
os_free(bss->no_auth_if_seen_on);
bss->no_auth_if_seen_on = os_strdup(pos);
} else {
wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'",
@ -3378,7 +3511,8 @@ struct hostapd_config * hostapd_config_read(const char *fname)
int hostapd_set_iface(struct hostapd_config *conf,
struct hostapd_bss_config *bss, char *field, char *value)
struct hostapd_bss_config *bss, const char *field,
char *value)
{
int errors;
size_t i;

View file

@ -11,7 +11,7 @@
struct hostapd_config * hostapd_config_read(const char *fname);
int hostapd_set_iface(struct hostapd_config *conf,
struct hostapd_bss_config *bss, char *field,
struct hostapd_bss_config *bss, const char *field,
char *value);
#endif /* CONFIG_FILE_H */

File diff suppressed because it is too large Load diff

View file

@ -240,6 +240,12 @@ CONFIG_IPV6=y
# requirements described above.
#CONFIG_NO_RANDOM_POOL=y
# Should we use poll instead of select? Select is used by default.
#CONFIG_ELOOP_POLL=y
# Should we use epoll instead of select? Select is used by default.
#CONFIG_ELOOP_EPOLL=y
# Select TLS implementation
# openssl = OpenSSL (default)
# gnutls = GnuTLS
@ -283,6 +289,12 @@ CONFIG_IPV6=y
# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
#CONFIG_SQLITE=y
# Enable Fast Session Transfer (FST)
#CONFIG_FST=y
# Enable CLI commands for FST testing
#CONFIG_FST_TEST=y
# Testing options
# This can be used to enable some testing options (see also the example
# configuration file) that are really useful only for testing clients that

View file

@ -87,6 +87,7 @@ struct milenage_parameters {
u8 amf[2];
u8 sqn[6];
int set;
size_t res_len;
};
static struct milenage_parameters *milenage_db = NULL;
@ -96,6 +97,7 @@ static struct milenage_parameters *milenage_db = NULL;
#define EAP_AKA_RAND_LEN 16
#define EAP_AKA_AUTN_LEN 16
#define EAP_AKA_AUTS_LEN 14
#define EAP_AKA_RES_MIN_LEN 4
#define EAP_AKA_RES_MAX_LEN 16
#define EAP_AKA_IK_LEN 16
#define EAP_AKA_CK_LEN 16
@ -124,7 +126,8 @@ static int db_table_create_milenage(sqlite3 *db)
" ki CHAR(32) NOT NULL,"
" opc CHAR(32) NOT NULL,"
" amf CHAR(4) NOT NULL,"
" sqn CHAR(12) NOT NULL"
" sqn CHAR(12) NOT NULL,"
" res_len INTEGER"
");";
printf("Adding database table for milenage information\n");
@ -190,6 +193,10 @@ static int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[])
printf("Invalid sqn value in database\n");
return -1;
}
if (os_strcmp(col[i], "res_len") == 0 && argv[i]) {
m->res_len = atoi(argv[i]);
}
}
return 0;
@ -206,8 +213,7 @@ static struct milenage_parameters * db_get_milenage(const char *imsi_txt)
os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi),
"%llu", imsi);
os_snprintf(cmd, sizeof(cmd),
"SELECT ki,opc,amf,sqn FROM milenage WHERE imsi=%llu;",
imsi);
"SELECT * FROM milenage WHERE imsi=%llu;", imsi);
if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage,
NULL) != SQLITE_OK)
return NULL;
@ -424,7 +430,7 @@ static int read_milenage(const char *fname)
while (fgets(buf, sizeof(buf), f)) {
line++;
/* Parse IMSI Ki OPc AMF SQN */
/* Parse IMSI Ki OPc AMF SQN [RES_len] */
buf[sizeof(buf) - 1] = '\0';
if (buf[0] == '#')
continue;
@ -515,7 +521,19 @@ static int read_milenage(const char *fname)
ret = -1;
break;
}
pos = pos2 + 1;
if (pos2) {
pos = pos2 + 1;
m->res_len = atoi(pos);
if (m->res_len &&
(m->res_len < EAP_AKA_RES_MIN_LEN ||
m->res_len > EAP_AKA_RES_MAX_LEN)) {
printf("%s:%d - Invalid RES_len (%s)\n",
fname, line, pos);
ret = -1;
break;
}
}
m->next = milenage_db;
milenage_db = m;
@ -532,7 +550,7 @@ static int read_milenage(const char *fname)
static void update_milenage_file(const char *fname)
{
FILE *f, *f2;
char buf[500], *pos;
char name[500], buf[500], *pos;
char *end = buf + sizeof(buf);
struct milenage_parameters *m;
size_t imsi_len;
@ -543,10 +561,10 @@ static void update_milenage_file(const char *fname)
return;
}
snprintf(buf, sizeof(buf), "%s.new", fname);
f2 = fopen(buf, "w");
snprintf(name, sizeof(name), "%s.new", fname);
f2 = fopen(name, "w");
if (f2 == NULL) {
printf("Could not write Milenage data file '%s'\n", buf);
printf("Could not write Milenage data file '%s'\n", name);
fclose(f);
return;
}
@ -588,14 +606,14 @@ static void update_milenage_file(const char *fname)
fclose(f2);
fclose(f);
snprintf(buf, sizeof(buf), "%s.bak", fname);
if (rename(fname, buf) < 0) {
snprintf(name, sizeof(name), "%s.bak", fname);
if (rename(fname, name) < 0) {
perror("rename");
return;
}
snprintf(buf, sizeof(buf), "%s.new", fname);
if (rename(buf, fname) < 0) {
snprintf(name, sizeof(name), "%s.new", fname);
if (rename(name, fname) < 0) {
perror("rename");
return;
}
@ -798,6 +816,10 @@ static int aka_req_auth(char *imsi, char *resp, size_t resp_len)
}
milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand,
autn, ik, ck, res, &res_len);
if (m->res_len >= EAP_AKA_RES_MIN_LEN &&
m->res_len <= EAP_AKA_RES_MAX_LEN &&
m->res_len < res_len)
res_len = m->res_len;
} else {
printf("Unknown IMSI: %s\n", imsi);
#ifdef AKA_USE_FIXED_TEST_VALUES

View file

@ -5,8 +5,10 @@
# authentication. In case of GSM/EAP-SIM, AMF and SQN values are not used, but
# dummy values will need to be included in this file.
# IMSI Ki OPc AMF SQN
# IMSI Ki OPc AMF SQN [RES_len]
232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000
# Example using truncated 32-bit RES instead of 64-bit default
232010000000001 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000 4
# These values are from Test Set 19 which has the AMF separation bit set to 1
# and as such, is suitable for EAP-AKA' test.

View file

@ -127,7 +127,9 @@ ssid=test
# Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g,
# ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to
# specify band)
# specify band). When using ACS (see channel parameter), a special value "any"
# can be used to indicate that any support band can be used. This special case
# is currently supported only with drivers with which offloaded ACS is used.
# Default: IEEE 802.11b
hw_mode=g
@ -170,8 +172,11 @@ channel=1
# Channel list restriction. This option allows hostapd to select one of the
# provided channels when a channel should be automatically selected.
# Default: not set (allow any enabled channel to be selected)
# Channel list can be provided as range using hyphen ('-') or individual
# channels can be specified by space (' ') seperated values
# Default: all channels allowed in selected hw_mode
#chanlist=100 104 108 112 116
#chanlist=1 6 11-13
# Beacon interval in kus (1.024 ms) (default: 100; range 15..65535)
beacon_int=100
@ -275,8 +280,9 @@ ignore_broadcast_ssid=0
# (data0 is the highest priority queue)
# parameters:
# aifs: AIFS (default 2)
# cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023)
# cwmax: cwMax (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023); cwMax >= cwMin
# cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191,
# 16383, 32767)
# cwmax: cwMax (same values as cwMin, cwMax >= cwMin)
# burst: maximum length (in milliseconds with precision of up to 0.1 ms) for
# bursting
#
@ -337,8 +343,9 @@ ignore_broadcast_ssid=0
# note - txop_limit is in units of 32microseconds
# note - acm is admission control mandatory flag. 0 = admission control not
# required, 1 = mandatory
# note - here cwMin and cmMax are in exponent form. the actual cw value used
# will be (2^n)-1 where n is the value given here
# note - Here cwMin and cmMax are in exponent form. The actual cw value used
# will be (2^n)-1 where n is the value given here. The allowed range for these
# wmm_ac_??_{cwmin,cwmax} is 0..15 with cwmax >= cwmin.
#
wmm_enabled=1
#
@ -575,14 +582,16 @@ wmm_ac_vo_acm=0
# 0 = Not supported (default)
# 1 = Supported
#
# Compressed Steering Number of Beamformer Antennas Supported: [BF-ANTENNA-2]
# Compressed Steering Number of Beamformer Antennas Supported:
# [BF-ANTENNA-2] [BF-ANTENNA-3] [BF-ANTENNA-4]
# Beamformee's capability indicating the maximum number of beamformer
# antennas the beamformee can support when sending compressed beamforming
# feedback
# If SU beamformer capable, set to maximum value minus 1
# else reserved (default)
#
# Number of Sounding Dimensions: [SOUNDING-DIMENSION-2]
# Number of Sounding Dimensions:
# [SOUNDING-DIMENSION-2] [SOUNDING-DIMENSION-3] [SOUNDING-DIMENSION-4]
# Beamformer's capability indicating the maximum value of the NUM_STS parameter
# in the TXVECTOR of a VHT NDP
# If SU beamformer capable, set to maximum value minus 1
@ -593,11 +602,6 @@ wmm_ac_vo_acm=0
# 0 = Not supported or sent by Non-AP STA (default)
# 1 = Supported
#
# MU Beamformee Capable: [MU-BEAMFORMEE]
# Indicates support for operation as an MU beamformee
# 0 = Not supported or sent by AP (default)
# 1 = Supported
#
# VHT TXOP PS: [VHT-TXOP-PS]
# Indicates whether or not the AP supports VHT TXOP Power Save Mode
# or whether or not the STA is in VHT TXOP Power Save mode
@ -764,6 +768,12 @@ eap_server=0
# 2 = check all CRLs in the certificate path
#check_crl=1
# TLS Session Lifetime in seconds
# This can be used to allow TLS sessions to be cached and resumed with an
# abbreviated handshake when using EAP-TLS/TTLS/PEAP.
# (default: 0 = session caching and resumption disabled)
#tls_session_lifetime=3600
# Cached OCSP stapling response (DER encoded)
# If set, this file is sent as a certificate status response by the EAP server
# if the EAP peer requests certificate status in the ClientHello message.
@ -787,7 +797,7 @@ eap_server=0
# is in DSA parameters format, it will be automatically converted into DH
# params. This parameter is required if anonymous EAP-FAST is used.
# You can generate DH parameters file with OpenSSL, e.g.,
# "openssl dhparam -out /etc/hostapd.dh.pem 1024"
# "openssl dhparam -out /etc/hostapd.dh.pem 2048"
#dh_file=/etc/hostapd.dh.pem
# OpenSSL cipher string
@ -1247,6 +1257,11 @@ own_ip_addr=127.0.0.1
# 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived
#pmk_r1_push=1
# Whether to enable FT-over-DS
# 0 = FT-over-DS disabled
# 1 = FT-over-DS enabled (default)
#ft_over_ds=1
##### Neighbor table ##########################################################
# Maximum number of entries kept in AP table (either for neigbor table or for
# detecting Overlapping Legacy BSS Condition). The oldest entry will be
@ -1264,6 +1279,43 @@ own_ip_addr=127.0.0.1
# default: 60
#ap_table_expiration_time=3600
# Maximum number of stations to track on the operating channel
# This can be used to detect dualband capable stations before they have
# associated, e.g., to provide guidance on which colocated BSS to use.
# Default: 0 (disabled)
#track_sta_max_num=100
# Maximum age of a station tracking entry in seconds
# Default: 180
#track_sta_max_age=180
# Do not reply to group-addressed Probe Request from a station that was seen on
# another radio.
# Default: Disabled
#
# This can be used with enabled track_sta_max_num configuration on another
# interface controlled by the same hostapd process to restrict Probe Request
# frame handling from replying to group-addressed Probe Request frames from a
# station that has been detected to be capable of operating on another band,
# e.g., to try to reduce likelihood of the station selecting a 2.4 GHz BSS when
# the AP operates both a 2.4 GHz and 5 GHz BSS concurrently.
#
# Note: Enabling this can cause connectivity issues and increase latency for
# discovering the AP.
#no_probe_resp_if_seen_on=wlan1
# Reject authentication from a station that was seen on another radio.
# Default: Disabled
#
# This can be used with enabled track_sta_max_num configuration on another
# interface controlled by the same hostapd process to reject authentication
# attempts from a station that has been detected to be capable of operating on
# another band, e.g., to try to reduce likelihood of the station selecting a
# 2.4 GHz BSS when the AP operates both a 2.4 GHz and 5 GHz BSS concurrently.
#
# Note: Enabling this can cause connectivity issues and increase latency for
# connecting with the AP.
#no_auth_if_seen_on=wlan1
##### Wi-Fi Protected Setup (WPS) #############################################
@ -1430,7 +1482,7 @@ own_ip_addr=127.0.0.1
# 12-digit, all-numeric code that identifies the consumer package.
#upc=123456789012
# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band)
# WPS RF Bands (a = 5G, b = 2.4G, g = 2.4G, ag = dual band, ad = 60 GHz)
# This value should be set according to RF band(s) supported by the AP if
# hw_mode is not set. For dual band dual concurrent devices, this needs to be
# set to ag to allow both RF bands to be advertized.
@ -1490,6 +1542,13 @@ own_ip_addr=127.0.0.1
# 1 = enabled
#proxy_arp=1
# IPv6 Neighbor Advertisement multicast-to-unicast conversion
# This can be used with Proxy ARP to allow multicast NAs to be forwarded to
# associated STAs using link layer unicast delivery.
# 0 = disabled (default)
# 1 = enabled
#na_mcast_to_ucast=0
##### IEEE 802.11u-2011 #######################################################
# Enable Interworking service
@ -1738,6 +1797,32 @@ own_ip_addr=127.0.0.1
#
#osu_server_uri=...
##### Fast Session Transfer (FST) support #####################################
#
# The options in this section are only available when the build configuration
# option CONFIG_FST is set while compiling hostapd. They allow this interface
# to be a part of FST setup.
#
# FST is the transfer of a session from a channel to another channel, in the
# same or different frequency bands.
#
# For detals, see IEEE Std 802.11ad-2012.
# Identifier of an FST Group the interface belongs to.
#fst_group_id=bond0
# Interface priority within the FST Group.
# Announcing a higher priority for an interface means declaring it more
# preferable for FST switch.
# fst_priority is in 1..255 range with 1 being the lowest priority.
#fst_priority=100
# Default LLT value for this interface in milliseconds. The value used in case
# no value provided during session setup. Default is 50 ms.
# fst_llt is in 1..4294967 range (due to spec limitation, see 10.32.2.2
# Transitioning between states).
#fst_llt=100
##### TESTING OPTIONS #########################################################
#
# The options in this section are only available when the build configuration

View file

@ -10,22 +10,23 @@
#include <dirent.h>
#include "common/wpa_ctrl.h"
#include "common/ieee802_11_defs.h"
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/edit.h"
#include "common/version.h"
static const char *hostapd_cli_version =
static const char *const hostapd_cli_version =
"hostapd_cli v" VERSION_STR "\n"
"Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi> and contributors";
static const char *hostapd_cli_license =
static const char *const hostapd_cli_license =
"This software may be distributed under the terms of the BSD license.\n"
"See README for more details.\n";
static const char *hostapd_cli_full_license =
static const char *const hostapd_cli_full_license =
"This software may be distributed under the terms of the BSD license.\n"
"\n"
"Redistribution and use in source and binary forms, with or without\n"
@ -56,7 +57,7 @@ static const char *hostapd_cli_full_license =
"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
"\n";
static const char *commands_help =
static const char *const commands_help =
"Commands:\n"
" mib get MIB variables (dot1x, dot11, radius)\n"
" sta <addr> get MIB variables for one station\n"
@ -96,6 +97,7 @@ static int hostapd_cli_attached = 0;
#define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
#endif /* CONFIG_CTRL_IFACE_DIR */
static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
static const char *client_socket_dir = NULL;
static char *ctrl_ifname = NULL;
static const char *pid_file = NULL;
@ -111,13 +113,15 @@ static void usage(void)
"\n"
"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
"[-a<path>] \\\n"
" [-G<ping interval>] [command..]\n"
" [-P<pid file>] [-G<ping interval>] [command..]\n"
"\n"
"Options:\n"
" -h help (show this usage text)\n"
" -v shown version information\n"
" -p<path> path to find control sockets (default: "
"/var/run/hostapd)\n"
" -s<dir_path> dir path to open client sockets (default: "
CONFIG_CTRL_IFACE_DIR ")\n"
" -a<file> run in daemon mode executing the action file "
"based on events\n"
" from hostapd\n"
@ -144,7 +148,14 @@ static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
return NULL;
snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
ctrl_conn = wpa_ctrl_open(cfile);
if (client_socket_dir && client_socket_dir[0] &&
access(client_socket_dir, F_OK) < 0) {
perror(client_socket_dir);
free(cfile);
return NULL;
}
ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
free(cfile);
return ctrl_conn;
}
@ -541,7 +552,7 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
char buf[256];
char ssid_hex[2 * 32 + 1];
char ssid_hex[2 * SSID_MAX_LEN + 1];
char key_hex[2 * 64 + 1];
int i;
@ -552,7 +563,7 @@ static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
}
ssid_hex[0] = '\0';
for (i = 0; i < 32; i++) {
for (i = 0; i < SSID_MAX_LEN; i++) {
if (argv[0][i] == '\0')
break;
os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
@ -921,6 +932,35 @@ static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
#ifdef CONFIG_FST
static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
char cmd[256];
int res;
int i;
int total;
if (argc <= 0) {
printf("FST command: parameters are required.\n");
return -1;
}
total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
for (i = 0; i < argc; i++) {
res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
argv[i]);
if (os_snprintf_error(sizeof(cmd) - total, res)) {
printf("Too long fst command.\n");
return -1;
}
total += res;
}
return wpa_ctrl_command(ctrl, cmd);
}
#endif /* CONFIG_FST */
static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
int argc, char *argv[])
{
@ -1009,12 +1049,31 @@ static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
}
static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
char cmd[256];
int res;
res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
argc >= 1 ? " " : "",
argc >= 1 ? argv[0] : "",
argc == 2 ? " " : "",
argc == 2 ? argv[1] : "");
if (os_snprintf_error(sizeof(cmd), res)) {
printf("Too long option\n");
return -1;
}
return wpa_ctrl_command(ctrl, cmd);
}
struct hostapd_cli_cmd {
const char *cmd;
int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
};
static struct hostapd_cli_cmd hostapd_cli_commands[] = {
static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "ping", hostapd_cli_cmd_ping },
{ "mib", hostapd_cli_cmd_mib },
{ "relog", hostapd_cli_cmd_relog },
@ -1048,6 +1107,9 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "get_config", hostapd_cli_cmd_get_config },
{ "help", hostapd_cli_cmd_help },
{ "interface", hostapd_cli_cmd_interface },
#ifdef CONFIG_FST
{ "fst", hostapd_cli_cmd_fst },
#endif /* CONFIG_FST */
{ "level", hostapd_cli_cmd_level },
{ "license", hostapd_cli_cmd_license },
{ "quit", hostapd_cli_cmd_quit },
@ -1063,13 +1125,14 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "reload", hostapd_cli_cmd_reload },
{ "disable", hostapd_cli_cmd_disable },
{ "erp_flush", hostapd_cli_cmd_erp_flush },
{ "log_level", hostapd_cli_cmd_log_level },
{ NULL, NULL }
};
static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
struct hostapd_cli_cmd *cmd, *match = NULL;
const struct hostapd_cli_cmd *cmd, *match = NULL;
int count;
count = 0;
@ -1284,7 +1347,7 @@ int main(int argc, char *argv[])
return -1;
for (;;) {
c = getopt(argc, argv, "a:BhG:i:p:v");
c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
if (c < 0)
break;
switch (c) {
@ -1310,6 +1373,12 @@ int main(int argc, char *argv[])
case 'p':
ctrl_iface_dir = optarg;
break;
case 'P':
pid_file = optarg;
break;
case 's':
client_socket_dir = optarg;
break;
default:
usage();
return -1;

View file

@ -24,6 +24,7 @@
#include "ap/hostapd.h"
#include "ap/ap_config.h"
#include "ap/ap_drv_ops.h"
#include "fst/fst.h"
#include "config_file.h"
#include "eap_register.h"
#include "ctrl_iface.h"
@ -533,6 +534,28 @@ static int gen_uuid(const char *txt_addr)
#endif /* CONFIG_WPS */
#ifndef HOSTAPD_CLEANUP_INTERVAL
#define HOSTAPD_CLEANUP_INTERVAL 10
#endif /* HOSTAPD_CLEANUP_INTERVAL */
static int hostapd_periodic_call(struct hostapd_iface *iface, void *ctx)
{
hostapd_periodic_iface(iface);
return 0;
}
/* Periodic cleanup tasks */
static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx)
{
struct hapd_interfaces *interfaces = eloop_ctx;
eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
hostapd_periodic, interfaces, NULL);
hostapd_for_each_interface(interfaces, hostapd_periodic_call, NULL);
}
int main(int argc, char *argv[])
{
struct hapd_interfaces interfaces;
@ -561,6 +584,7 @@ int main(int argc, char *argv[])
interfaces.global_iface_path = NULL;
interfaces.global_iface_name = NULL;
interfaces.global_ctrl_sock = -1;
interfaces.global_ctrl_dst = NULL;
for (;;) {
c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:");
@ -661,10 +685,24 @@ int main(int argc, char *argv[])
}
if (hostapd_global_init(&interfaces, entropy_file)) {
wpa_printf(MSG_ERROR, "Failed to initilize global context");
wpa_printf(MSG_ERROR, "Failed to initialize global context");
return -1;
}
eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0,
hostapd_periodic, &interfaces, NULL);
if (fst_global_init()) {
wpa_printf(MSG_ERROR,
"Failed to initialize global FST context");
goto out;
}
#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
if (!fst_global_add_ctrl(fst_ctrl_cli))
wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
#endif /* CONFIG_FST && CONFIG_CTRL_IFACE */
/* Allocate and parse configuration for full interface files */
for (i = 0; i < interfaces.count; i++) {
interfaces.iface[i] = hostapd_interface_init(&interfaces,
@ -749,6 +787,7 @@ int main(int argc, char *argv[])
}
os_free(interfaces.iface);
eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL);
hostapd_global_deinit(pid_file);
os_free(pid_file);
@ -758,6 +797,8 @@ int main(int argc, char *argv[])
os_free(bss_config);
fst_global_deinit();
os_program_deinit();
return ret;

View file

@ -67,7 +67,13 @@ OBJS += ../../src/crypto/sha256-internal.o
CFLAGS += $(shell xml2-config --cflags)
LIBS += $(shell xml2-config --libs)
# Allow static/custom linking of libcurl.
ifdef CUST_CURL_LINKAGE
LIBS += ${CUST_CURL_LINKAGE}
else
LIBS += -lcurl
endif
CFLAGS += -DEAP_TLS_OPENSSL
LIBS += -lssl -lcrypto

View file

@ -25,6 +25,8 @@
#include "crypto/sha256.h"
#include "osu_client.h"
const char *spp_xsd_fname = "spp.xsd";
void write_result(struct hs20_osu_client *ctx, const char *fmt, ...)
{
@ -540,6 +542,7 @@ int hs20_add_pps_mo(struct hs20_osu_client *ctx, const char *uri,
uri);
write_result(ctx, "Unsupported location for addMO to "
"add PPS MO (extra directory): '%s'", uri);
free(fqdn);
return -1;
}
*pos = '\0'; /* remove trailing slash and PPS node name */
@ -547,8 +550,9 @@ int hs20_add_pps_mo(struct hs20_osu_client *ctx, const char *uri,
wpa_printf(MSG_INFO, "SP FQDN: %s", fqdn);
if (!server_dnsname_suffix_match(ctx, fqdn)) {
wpa_printf(MSG_INFO, "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values",
fqdn);
wpa_printf(MSG_INFO,
"FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values, count: %d",
fqdn, (int) ctx->server_dnsname_count);
write_result(ctx, "FQDN '%s' for new PPS MO did not have suffix match with server's dNSName values",
fqdn);
free(fqdn);
@ -2094,10 +2098,14 @@ static int osu_connect(struct hs20_osu_client *ctx, const char *bssid,
}
ctx->no_reconnect = 1;
if (methods & 0x02)
if (methods & 0x02) {
wpa_printf(MSG_DEBUG, "Calling cmd_prov from osu_connect");
res = cmd_prov(ctx, url);
else if (methods & 0x01)
} else if (methods & 0x01) {
wpa_printf(MSG_DEBUG,
"Calling cmd_oma_dm_prov from osu_connect");
res = cmd_oma_dm_prov(ctx, url);
}
wpa_printf(MSG_INFO, "Remove OSU network connection");
write_summary(ctx, "Remove OSU network connection");
@ -2139,7 +2147,7 @@ static int cmd_osu_select(struct hs20_osu_client *ctx, const char *dir,
snprintf(fname, sizeof(fname), "%s/osu-providers.txt", dir);
osu = parse_osu_providers(fname, &osu_count);
if (osu == NULL) {
wpa_printf(MSG_INFO, "Could not any OSU providers from %s",
wpa_printf(MSG_INFO, "Could not find any OSU providers from %s",
fname);
write_result(ctx, "No OSU providers available");
return -1;
@ -2290,12 +2298,19 @@ static int cmd_osu_select(struct hs20_osu_client *ctx, const char *dir,
}
if (connect == 2) {
if (last->methods & 0x02)
if (last->methods & 0x02) {
wpa_printf(MSG_DEBUG,
"Calling cmd_prov from cmd_osu_select");
ret = cmd_prov(ctx, last->url);
else if (last->methods & 0x01)
} else if (last->methods & 0x01) {
wpa_printf(MSG_DEBUG,
"Calling cmd_oma_dm_prov from cmd_osu_select");
ret = cmd_oma_dm_prov(ctx, last->url);
else
} else {
wpa_printf(MSG_DEBUG,
"No supported OSU provisioning method");
ret = -1;
}
} else if (connect)
ret = osu_connect(ctx, last->bssid, last->osu_ssid,
last->url, last->methods,
@ -2690,7 +2705,7 @@ static char * get_hostname(const char *url)
end = os_strchr(pos, '/');
end2 = os_strchr(pos, ':');
if (end && end2 && end2 < end)
if ((end && end2 && end2 < end) || (!end && end2))
end = end2;
if (end)
end--;
@ -2720,8 +2735,8 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
int found;
char *host = NULL;
wpa_printf(MSG_INFO, "osu_cert_cb(osu_cert_validation=%d)",
!ctx->no_osu_cert_validation);
wpa_printf(MSG_INFO, "osu_cert_cb(osu_cert_validation=%d, url=%s)",
!ctx->no_osu_cert_validation, ctx->server_url);
host = get_hostname(ctx->server_url);
@ -2810,17 +2825,21 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
char *name = ctx->icon_filename[j];
size_t name_len = os_strlen(name);
wpa_printf(MSG_INFO, "Looking for icon file name '%s' match",
name);
wpa_printf(MSG_INFO,
"[%i] Looking for icon file name '%s' match",
j, name);
for (i = 0; i < cert->num_logo; i++) {
struct http_logo *logo = &cert->logo[i];
size_t uri_len = os_strlen(logo->uri);
char *pos;
wpa_printf(MSG_INFO, "Comparing to '%s' uri_len=%d name_len=%d",
logo->uri, (int) uri_len, (int) name_len);
if (uri_len < 1 + name_len)
wpa_printf(MSG_INFO,
"[%i] Comparing to '%s' uri_len=%d name_len=%d",
i, logo->uri, (int) uri_len, (int) name_len);
if (uri_len < 1 + name_len) {
wpa_printf(MSG_INFO, "URI Length is too short");
continue;
}
pos = &logo->uri[uri_len - name_len - 1];
if (*pos != '/')
continue;
@ -2847,17 +2866,30 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert)
for (i = 0; i < cert->num_logo; i++) {
struct http_logo *logo = &cert->logo[i];
if (logo->hash_len != 32)
if (logo->hash_len != 32) {
wpa_printf(MSG_INFO,
"[%i][%i] Icon hash length invalid (should be 32): %d",
j, i, (int) logo->hash_len);
continue;
}
if (os_memcmp(logo->hash, ctx->icon_hash[j], 32) == 0) {
found = 1;
break;
}
wpa_printf(MSG_DEBUG,
"[%u][%u] Icon hash did not match", j, i);
wpa_hexdump_ascii(MSG_DEBUG, "logo->hash",
logo->hash, 32);
wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]",
ctx->icon_hash[j], 32);
}
if (!found) {
wpa_printf(MSG_INFO, "No icon hash match found");
write_result(ctx, "No icon hash match found");
wpa_printf(MSG_INFO,
"No icon hash match (by hash) found");
write_result(ctx,
"No icon hash match (by hash) found");
return -1;
}
}
@ -2955,6 +2987,7 @@ static void usage(void)
" [-w<wpa_supplicant ctrl_iface dir>] "
"[-r<result file>] [-f<debug file>] \\\n"
" [-s<summary file>] \\\n"
" [-x<spp.xsd file name>] \\\n"
" <command> [arguments..]\n"
"commands:\n"
"- to_tnds <XML MO> <XML MO in TNDS format> [URN]\n"
@ -2996,7 +3029,7 @@ int main(int argc, char *argv[])
return -1;
for (;;) {
c = getopt(argc, argv, "df:hi:KNO:qr:s:S:tw:");
c = getopt(argc, argv, "df:hKNO:qr:s:S:tw:x:");
if (c < 0)
break;
switch (c) {
@ -3034,6 +3067,9 @@ int main(int argc, char *argv[])
case 'w':
wpas_ctrl_path = optarg;
break;
case 'x':
spp_xsd_fname = optarg;
break;
case 'h':
default:
usage();
@ -3108,6 +3144,7 @@ int main(int argc, char *argv[])
exit(0);
}
ctx.ca_fname = argv[optind + 2];
wpa_printf(MSG_DEBUG, "Calling cmd_prov from main");
cmd_prov(&ctx, argv[optind + 1]);
} else if (strcmp(argv[optind], "sim_prov") == 0) {
if (argc - optind < 2) {

View file

@ -21,6 +21,8 @@
#include "osu_client.h"
extern const char *spp_xsd_fname;
static int hs20_spp_update_response(struct hs20_osu_client *ctx,
const char *session_id,
const char *spp_status,
@ -59,7 +61,7 @@ static int hs20_spp_validate(struct hs20_osu_client *ctx, xml_node_t *node,
return -1;
}
ret = xml_validate(xctx, node, "spp.xsd", &err);
ret = xml_validate(xctx, node, spp_xsd_fname, &err);
if (ret < 0) {
wpa_printf(MSG_INFO, "XML schema validation error(s)\n%s", err);
write_summary(ctx, "SPP XML schema validation failed");
@ -77,9 +79,14 @@ static void add_mo_container(struct xml_node_ctx *ctx, xml_namespace_t *ns,
xml_node_t *fnode, *tnds;
char *str;
errno = 0;
fnode = node_from_file(ctx, fname);
if (!fnode)
if (!fnode) {
wpa_printf(MSG_ERROR,
"Failed to create XML node from file: %s, possible error: %s",
fname, strerror(errno));
return;
}
tnds = mo_to_tnds(ctx, fnode, 0, urn, "syncml:dmddf1.2");
xml_node_free(ctx, fnode);
if (!tnds)
@ -952,7 +959,9 @@ int cmd_prov(struct hs20_osu_client *ctx, const char *url)
return -1;
}
wpa_printf(MSG_INFO, "Credential provisioning requested");
wpa_printf(MSG_INFO,
"Credential provisioning requested - URL: %s ca_fname: %s",
url, ctx->ca_fname ? ctx->ca_fname : "N/A");
os_free(ctx->server_url);
ctx->server_url = os_strdup(url);

View file

@ -0,0 +1,398 @@
This patch adds support for TLS SessionTicket extension (RFC 5077) for
the parts used by EAP-FAST (RFC 4851).
This is based on the patch from Alexey Kobozev <akobozev@cisco.com>
(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300).
OpenSSL 0.9.8zf does not enable TLS extension support by default, so it
will need to be enabled by adding enable-tlsext to config script
command line.
diff -upr openssl-0.9.8zf.orig/ssl/s3_clnt.c openssl-0.9.8zf/ssl/s3_clnt.c
--- openssl-0.9.8zf.orig/ssl/s3_clnt.c 2015-03-19 15:46:46.000000000 +0200
+++ openssl-0.9.8zf/ssl/s3_clnt.c 2015-03-24 16:19:14.043911769 +0200
@@ -760,6 +760,23 @@ int ssl3_get_server_hello(SSL *s)
goto f_err;
}
+#ifndef OPENSSL_NO_TLSEXT
+ /* check if we want to resume the session based on external pre-shared secret */
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) {
+ SSL_CIPHER *pref_cipher = NULL;
+
+ s->session->master_key_length = sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key,
+ &s->session->master_key_length,
+ NULL, &pref_cipher,
+ s->tls_session_secret_cb_arg)) {
+ s->session->cipher = pref_cipher ?
+ pref_cipher : ssl_get_cipher_by_char(s, p + j);
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
+ }
+ }
+#endif /* OPENSSL_NO_TLSEXT */
+
if (j != 0 && j == s->session->session_id_length
&& memcmp(p, s->session->session_id, j) == 0) {
if (s->sid_ctx_length != s->session->sid_ctx_length
@@ -2684,12 +2701,8 @@ int ssl3_check_finished(SSL *s)
{
int ok;
long n;
- /*
- * If we have no ticket or session ID is non-zero length (a match of a
- * non-zero session length would never reach here) it cannot be a resumed
- * session.
- */
- if (!s->session->tlsext_tick || s->session->session_id_length)
+ /* If we have no ticket it cannot be a resumed session. */
+ if (!s->session->tlsext_tick)
return 1;
/*
* this function is called when we really expect a Certificate message,
diff -upr openssl-0.9.8zf.orig/ssl/s3_srvr.c openssl-0.9.8zf/ssl/s3_srvr.c
--- openssl-0.9.8zf.orig/ssl/s3_srvr.c 2015-03-19 15:46:46.000000000 +0200
+++ openssl-0.9.8zf/ssl/s3_srvr.c 2015-03-24 16:23:34.567909681 +0200
@@ -999,6 +999,59 @@ int ssl3_get_client_hello(SSL *s)
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
goto err;
}
+
+ /* Check if we want to use external pre-shared secret for this
+ * handshake for not reused session only. We need to generate
+ * server_random before calling tls_session_secret_cb in order to allow
+ * SessionTicket processing to use it in key derivation. */
+ {
+ unsigned long Time;
+ unsigned char *pos;
+ Time = (unsigned long)time(NULL); /* Time */
+ pos = s->s3->server_random;
+ l2n(Time, pos);
+ if (RAND_pseudo_bytes(pos, SSL3_RANDOM_SIZE - 4) <= 0) {
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
+ }
+ }
+
+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) {
+ SSL_CIPHER *pref_cipher = NULL;
+
+ s->session->master_key_length = sizeof(s->session->master_key);
+ if (s->tls_session_secret_cb(s, s->session->master_key,
+ &s->session->master_key_length,
+ ciphers, &pref_cipher,
+ s->tls_session_secret_cb_arg)) {
+ s->hit = 1;
+ s->session->ciphers = ciphers;
+ s->session->verify_result = X509_V_OK;
+
+ ciphers = NULL;
+
+ /* check if some cipher was preferred by call back */
+ pref_cipher = pref_cipher ? pref_cipher :
+ ssl3_choose_cipher(s, s->session->ciphers,
+ SSL_get_ciphers(s));
+ if (pref_cipher == NULL) {
+ al = SSL_AD_HANDSHAKE_FAILURE;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER);
+ goto f_err;
+ }
+
+ s->session->cipher = pref_cipher;
+
+ if (s->cipher_list)
+ sk_SSL_CIPHER_free(s->cipher_list);
+
+ if (s->cipher_list_by_id)
+ sk_SSL_CIPHER_free(s->cipher_list_by_id);
+
+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
+ }
+ }
#endif
/*
* Worst case, we will use the NULL compression, but if we have other
@@ -1143,15 +1196,21 @@ int ssl3_send_server_hello(SSL *s)
unsigned char *buf;
unsigned char *p, *d;
int i, sl;
- unsigned long l, Time;
+ unsigned long l;
+#ifdef OPENSSL_NO_TLSEXT
+ unsigned long Time;
+#endif
if (s->state == SSL3_ST_SW_SRVR_HELLO_A) {
buf = (unsigned char *)s->init_buf->data;
+#ifdef OPENSSL_NO_TLSEXT
p = s->s3->server_random;
+ /* Generate server_random if it was not needed previously */
Time = (unsigned long)time(NULL); /* Time */
l2n(Time, p);
if (RAND_pseudo_bytes(p, SSL3_RANDOM_SIZE - 4) <= 0)
return -1;
+#endif
/* Do the message type and length last */
d = p = &(buf[4]);
diff -upr openssl-0.9.8zf.orig/ssl/ssl_err.c openssl-0.9.8zf/ssl/ssl_err.c
--- openssl-0.9.8zf.orig/ssl/ssl_err.c 2015-03-19 15:46:46.000000000 +0200
+++ openssl-0.9.8zf/ssl/ssl_err.c 2015-03-24 16:35:58.627903717 +0200
@@ -316,6 +316,7 @@ static ERR_STRING_DATA SSL_str_functs[]
{ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"},
{ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"},
{ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"},
+ {ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"},
{0, NULL}
};
diff -upr openssl-0.9.8zf.orig/ssl/ssl.h openssl-0.9.8zf/ssl/ssl.h
--- openssl-0.9.8zf.orig/ssl/ssl.h 2015-03-19 15:46:46.000000000 +0200
+++ openssl-0.9.8zf/ssl/ssl.h 2015-03-24 16:25:44.339908641 +0200
@@ -349,6 +349,7 @@ extern "C" {
* function parameters used to prototype callbacks in SSL_CTX.
*/
typedef struct ssl_st *ssl_crock_st;
+typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
/* used to hold info on the particular ciphers used */
typedef struct ssl_cipher_st {
@@ -366,6 +367,12 @@ typedef struct ssl_cipher_st {
DECLARE_STACK_OF(SSL_CIPHER)
+typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data,
+ int len, void *arg);
+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers,
+ SSL_CIPHER **cipher, void *arg);
+
/* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
typedef struct ssl_method_st {
int version;
@@ -1116,6 +1123,18 @@ struct ssl_st {
int tlsext_ocsp_resplen;
/* RFC4507 session ticket expected to be received or sent */
int tlsext_ticket_expected;
+
+ /* TLS Session Ticket extension override */
+ TLS_SESSION_TICKET_EXT *tlsext_session_ticket;
+
+ /* TLS Session Ticket extension callback */
+ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb;
+ void *tls_session_ticket_ext_cb_arg;
+
+ /* TLS pre-shared secret session resumption */
+ tls_session_secret_cb_fn tls_session_secret_cb;
+ void *tls_session_secret_cb_arg;
+
SSL_CTX *initial_ctx; /* initial ctx, used to store sessions */
# define session_ctx initial_ctx
# else
@@ -1772,6 +1791,17 @@ void *SSL_COMP_get_compression_methods(v
int SSL_COMP_add_compression_method(int id, void *cm);
# endif
+/* TLS extensions functions */
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
+
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
+ void *arg);
+
+/* Pre-shared secret session resumption functions */
+int SSL_set_session_secret_cb(SSL *s,
+ tls_session_secret_cb_fn tls_session_secret_cb,
+ void *arg);
+
/* BEGIN ERROR CODES */
/*
* The following lines are auto generated by the script mkerr.pl. Any changes
@@ -1977,6 +2007,7 @@ void ERR_load_SSL_strings(void);
# define SSL_F_TLS1_ENC 210
# define SSL_F_TLS1_SETUP_KEY_BLOCK 211
# define SSL_F_WRITE_PENDING 212
+#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213
/* Reason codes. */
# define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff -upr openssl-0.9.8zf.orig/ssl/ssl_sess.c openssl-0.9.8zf/ssl/ssl_sess.c
--- openssl-0.9.8zf.orig/ssl/ssl_sess.c 2015-03-19 15:46:46.000000000 +0200
+++ openssl-0.9.8zf/ssl/ssl_sess.c 2015-03-24 16:28:04.819907515 +0200
@@ -716,6 +716,61 @@ long SSL_CTX_get_timeout(const SSL_CTX *
return (s->session_timeout);
}
+#ifndef OPENSSL_NO_TLSEXT
+int SSL_set_session_secret_cb(
+ SSL *s,
+ int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len,
+ STACK_OF(SSL_CIPHER) *peer_ciphers,
+ SSL_CIPHER **cipher, void *arg), void *arg)
+{
+ if (s == NULL)
+ return 0;
+ s->tls_session_secret_cb = tls_session_secret_cb;
+ s->tls_session_secret_cb_arg = arg;
+ return 1;
+}
+
+int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb,
+ void *arg)
+{
+ if (s == NULL)
+ return 0;
+ s->tls_session_ticket_ext_cb = cb;
+ s->tls_session_ticket_ext_cb_arg = arg;
+ return 1;
+}
+
+int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len)
+{
+ if (s->version >= TLS1_VERSION) {
+ if (s->tlsext_session_ticket) {
+ OPENSSL_free(s->tlsext_session_ticket);
+ s->tlsext_session_ticket = NULL;
+ }
+
+ s->tlsext_session_ticket = OPENSSL_malloc(
+ sizeof(TLS_SESSION_TICKET_EXT) + ext_len);
+ if (!s->tlsext_session_ticket) {
+ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ if (ext_data) {
+ s->tlsext_session_ticket->length = ext_len;
+ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1;
+ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len);
+ } else {
+ s->tlsext_session_ticket->length = 0;
+ s->tlsext_session_ticket->data = NULL;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+#endif /* OPENSSL_NO_TLSEXT */
+
typedef struct timeout_param_st {
SSL_CTX *ctx;
long time;
diff -upr openssl-0.9.8zf.orig/ssl/t1_lib.c openssl-0.9.8zf/ssl/t1_lib.c
--- openssl-0.9.8zf.orig/ssl/t1_lib.c 2015-03-19 15:46:46.000000000 +0200
+++ openssl-0.9.8zf/ssl/t1_lib.c 2015-03-24 16:32:46.923905254 +0200
@@ -108,6 +108,11 @@ int tls1_new(SSL *s)
void tls1_free(SSL *s)
{
+#ifndef OPENSSL_NO_TLSEXT
+ if (s->tlsext_session_ticket) {
+ OPENSSL_free(s->tlsext_session_ticket);
+ }
+#endif
ssl3_free(s);
}
@@ -206,8 +211,20 @@ unsigned char *ssl_add_clienthello_tlsex
int ticklen;
if (!s->new_session && s->session && s->session->tlsext_tick)
ticklen = s->session->tlsext_ticklen;
- else
+ else if (s->session && s->tlsext_session_ticket &&
+ s->tlsext_session_ticket->data) {
+ ticklen = s->tlsext_session_ticket->length;
+ s->session->tlsext_tick = OPENSSL_malloc(ticklen);
+ if (!s->session->tlsext_tick)
+ return NULL;
+ memcpy(s->session->tlsext_tick, s->tlsext_session_ticket->data,
+ ticklen);
+ s->session->tlsext_ticklen = ticklen;
+ } else
ticklen = 0;
+ if (ticklen == 0 && s->tlsext_session_ticket &&
+ s->tlsext_session_ticket->data == NULL)
+ goto skip_ext;
/*
* Check for enough room 2 for extension type, 2 for len rest for
* ticket
@@ -221,6 +238,7 @@ unsigned char *ssl_add_clienthello_tlsex
ret += ticklen;
}
}
+skip_ext:
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp &&
s->version != DTLS1_VERSION) {
@@ -560,6 +578,14 @@ int ssl_parse_clienthello_tlsext(SSL *s,
if (!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
return 0;
renegotiate_seen = 1;
+ } else if (type == TLSEXT_TYPE_session_ticket) {
+ if (s->tls_session_ticket_ext_cb &&
+ !s->tls_session_ticket_ext_cb(s, data, size,
+ s->tls_session_ticket_ext_cb_arg))
+ {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
} else if (type == TLSEXT_TYPE_status_request &&
s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb) {
@@ -710,6 +736,13 @@ int ssl_parse_serverhello_tlsext(SSL *s,
}
tlsext_servername = 1;
} else if (type == TLSEXT_TYPE_session_ticket) {
+ if (s->tls_session_ticket_ext_cb &&
+ !s->tls_session_ticket_ext_cb(
+ s, data, size,
+ s->tls_session_ticket_ext_cb_arg)) {
+ *al = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
if ((SSL_get_options(s) & SSL_OP_NO_TICKET)
|| (size > 0)) {
*al = TLS1_AD_UNSUPPORTED_EXTENSION;
@@ -993,6 +1026,14 @@ int tls1_process_ticket(SSL *s, unsigned
s->tlsext_ticket_expected = 1;
return 0; /* Cache miss */
}
+ if (s->tls_session_secret_cb) {
+ /* Indicate cache miss here and instead of
+ * generating the session from ticket now,
+ * trigger abbreviated handshake based on
+ * external mechanism to calculate the master
+ * secret later. */
+ return 0;
+ }
return tls_decrypt_ticket(s, p, size, session_id, len, ret);
}
p += size;
diff -upr openssl-0.9.8zf.orig/ssl/tls1.h openssl-0.9.8zf/ssl/tls1.h
--- openssl-0.9.8zf.orig/ssl/tls1.h 2015-03-19 15:46:46.000000000 +0200
+++ openssl-0.9.8zf/ssl/tls1.h 2015-03-24 16:33:31.855904894 +0200
@@ -460,6 +460,12 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T
# define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"
# endif
+/* TLS extension struct */
+struct tls_session_ticket_ext_st {
+ unsigned short length;
+ void *data;
+};
+
#ifdef __cplusplus
}
#endif
diff -upr openssl-0.9.8zf.orig/util/ssleay.num openssl-0.9.8zf/util/ssleay.num
--- openssl-0.9.8zf.orig/util/ssleay.num 2015-03-19 15:47:15.000000000 +0200
+++ openssl-0.9.8zf/util/ssleay.num 2015-03-24 16:33:51.127904739 +0200
@@ -242,3 +242,5 @@ SSL_set_SSL_CTX
SSL_get_servername 291 EXIST::FUNCTION:TLSEXT
SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT
SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE
+SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT
+SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT

View file

@ -459,10 +459,14 @@ int accounting_init(struct hostapd_data *hapd)
{
struct os_time now;
/* Acct-Session-Id should be unique over reboots. If reliable clock is
* not available, this could be replaced with reboot counter, etc. */
/* Acct-Session-Id should be unique over reboots. Using a random number
* is preferred. If that is not available, take the current time. Mix
* in microseconds to make this more likely to be unique. */
os_get_time(&now);
hapd->acct_session_id_hi = now.sec;
if (os_get_random((u8 *) &hapd->acct_session_id_hi,
sizeof(hapd->acct_session_id_hi)) < 0)
hapd->acct_session_id_hi = now.sec;
hapd->acct_session_id_hi ^= now.usec;
if (radius_client_register(hapd->radius, RADIUS_ACCT,
accounting_receive, hapd))
@ -475,7 +479,7 @@ int accounting_init(struct hostapd_data *hapd)
/**
* accounting_deinit: Deinitilize accounting
* accounting_deinit: Deinitialize accounting
* @hapd: hostapd BSS data
*/
void accounting_deinit(struct hostapd_data *hapd)

View file

@ -479,16 +479,10 @@ static int acs_usable_chan(struct hostapd_channel_data *chan)
static int is_in_chanlist(struct hostapd_iface *iface,
struct hostapd_channel_data *chan)
{
int *entry;
if (!iface->conf->chanlist)
if (!iface->conf->acs_ch_list.num)
return 1;
for (entry = iface->conf->chanlist; *entry != -1; entry++) {
if (*entry == chan->chan)
return 1;
}
return 0;
return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
}
@ -900,6 +894,9 @@ static int acs_request_scan(struct hostapd_iface *iface)
if (chan->flag & HOSTAPD_CHAN_DISABLED)
continue;
if (!is_in_chanlist(iface, chan))
continue;
*freq++ = chan->freq;
}
*freq = 0;

View file

@ -172,6 +172,7 @@ struct hostapd_config * hostapd_config_defaults(void)
conf->ap_table_max_size = 255;
conf->ap_table_expiration_time = 60;
conf->track_sta_max_age = 180;
#ifdef CONFIG_TESTING_OPTIONS
conf->ignore_probe_probability = 0.0;
@ -181,6 +182,8 @@ struct hostapd_config * hostapd_config_defaults(void)
conf->corrupt_gtk_rekey_mic_probability = 0.0;
#endif /* CONFIG_TESTING_OPTIONS */
conf->acs = 0;
conf->acs_ch_list.num = 0;
#ifdef CONFIG_ACS
conf->acs_num_scans = 5;
#endif /* CONFIG_ACS */
@ -559,6 +562,13 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(conf->server_id);
#ifdef CONFIG_TESTING_OPTIONS
wpabuf_free(conf->own_ie_override);
#endif /* CONFIG_TESTING_OPTIONS */
os_free(conf->no_probe_resp_if_seen_on);
os_free(conf->no_auth_if_seen_on);
os_free(conf);
}
@ -579,7 +589,7 @@ void hostapd_config_free(struct hostapd_config *conf)
os_free(conf->bss);
os_free(conf->supported_rates);
os_free(conf->basic_rates);
os_free(conf->chanlist);
os_free(conf->acs_ch_list.range);
os_free(conf->driver_params);
#ifdef CONFIG_ACS
os_free(conf->acs_chan_bias);
@ -817,9 +827,9 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
if (full_config && bss->wps_state && bss->wpa &&
(!(bss->wpa & 2) ||
!(bss->rsn_pairwise & WPA_CIPHER_CCMP))) {
!(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)))) {
wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without "
"WPA2/CCMP forced WPS to be disabled");
"WPA2/CCMP/GCMP forced WPS to be disabled");
bss->wps_state = 0;
}
#endif /* CONFIG_WPS */
@ -841,6 +851,29 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
}
static int hostapd_config_check_cw(struct hostapd_config *conf, int queue)
{
int tx_cwmin = conf->tx_queue[queue].cwmin;
int tx_cwmax = conf->tx_queue[queue].cwmax;
int ac_cwmin = conf->wmm_ac_params[queue].cwmin;
int ac_cwmax = conf->wmm_ac_params[queue].cwmax;
if (tx_cwmin > tx_cwmax) {
wpa_printf(MSG_ERROR,
"Invalid TX queue cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)",
tx_cwmin, tx_cwmax);
return -1;
}
if (ac_cwmin > ac_cwmax) {
wpa_printf(MSG_ERROR,
"Invalid WMM AC cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)",
ac_cwmin, ac_cwmax);
return -1;
}
return 0;
}
int hostapd_config_check(struct hostapd_config *conf, int full_config)
{
size_t i;
@ -870,6 +903,11 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config)
return -1;
}
for (i = 0; i < NUM_TX_QUEUES; i++) {
if (hostapd_config_check_cw(conf, i))
return -1;
}
for (i = 0; i < conf->num_bss; i++) {
if (hostapd_config_check_bss(conf->bss[i], conf, full_config))
return -1;
@ -937,10 +975,11 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss,
bss->rsn_pairwise = WPA_CIPHER_CCMP;
} else {
bss->ssid.security_policy = SECURITY_PLAINTEXT;
bss->wpa_group = WPA_CIPHER_NONE;
bss->wpa_pairwise = WPA_CIPHER_NONE;
bss->rsn_pairwise = WPA_CIPHER_NONE;
if (full_config)
if (full_config) {
bss->wpa_group = WPA_CIPHER_NONE;
bss->wpa_pairwise = WPA_CIPHER_NONE;
bss->rsn_pairwise = WPA_CIPHER_NONE;
bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE;
}
}
}

View file

@ -1,6 +1,6 @@
/*
* hostapd / Configuration definitions and helpers functions
* Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -12,8 +12,10 @@
#include "common/defs.h"
#include "ip_addr.h"
#include "common/wpa_common.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "wps/wps.h"
#include "fst/fst.h"
/**
* mesh_conf - local MBSS state and settings
@ -31,8 +33,8 @@ struct mesh_conf {
u8 mesh_sp_id;
/* Authentication Protocol Identifier */
u8 mesh_auth_id;
u8 *ies;
int ie_len;
u8 *rsn_ie;
int rsn_ie_len;
#define MESH_CONF_SEC_NONE BIT(0)
#define MESH_CONF_SEC_AUTH BIT(1)
#define MESH_CONF_SEC_AMPE BIT(2)
@ -57,8 +59,6 @@ struct hostapd_radius_servers;
struct ft_remote_r0kh;
struct ft_remote_r1kh;
#define HOSTAPD_MAX_SSID_LEN 32
#define NUM_WEP_KEYS 4
struct hostapd_wep_keys {
u8 idx;
@ -78,7 +78,7 @@ typedef enum hostap_security_policy {
} secpolicy;
struct hostapd_ssid {
u8 ssid[HOSTAPD_MAX_SSID_LEN];
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
unsigned int ssid_set:1;
unsigned int utf8_ssid:1;
@ -114,12 +114,10 @@ struct hostapd_vlan {
struct hostapd_vlan *next;
int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */
char ifname[IFNAMSIZ + 1];
int configured;
int dynamic_vlan;
#ifdef CONFIG_FULL_DYNAMIC_VLAN
#define DVLAN_CLEAN_BR 0x1
#define DVLAN_CLEAN_VLAN 0x2
#define DVLAN_CLEAN_VLAN_PORT 0x4
#define DVLAN_CLEAN_WLAN_PORT 0x8
int clean;
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
@ -332,6 +330,7 @@ struct hostapd_bss_config {
char *private_key;
char *private_key_passwd;
int check_crl;
unsigned int tls_session_lifetime;
char *ocsp_stapling_response;
char *dh_file;
char *openssl_ciphers;
@ -490,6 +489,7 @@ struct hostapd_bss_config {
int osen;
int proxy_arp;
int na_mcast_to_ucast;
#ifdef CONFIG_HS20
int hs20;
int disable_dgaf;
@ -510,7 +510,7 @@ struct hostapd_bss_config {
char file[256];
} *hs20_icons;
size_t hs20_icons_count;
u8 osu_ssid[HOSTAPD_MAX_SSID_LEN];
u8 osu_ssid[SSID_MAX_LEN];
size_t osu_ssid_len;
struct hs20_osu_provider {
unsigned int friendly_name_count;
@ -545,6 +545,7 @@ struct hostapd_bss_config {
#ifdef CONFIG_TESTING_OPTIONS
u8 bss_load_test[5];
u8 bss_load_test_set;
struct wpabuf *own_ie_override;
#endif /* CONFIG_TESTING_OPTIONS */
#define MESH_ENABLED BIT(0)
@ -553,6 +554,9 @@ struct hostapd_bss_config {
int radio_measurements;
int vendor_vht;
char *no_probe_resp_if_seen_on;
char *no_auth_if_seen_on;
};
@ -568,7 +572,8 @@ struct hostapd_config {
int fragm_threshold;
u8 send_probe_response;
u8 channel;
int *chanlist;
u8 acs;
struct wpa_freq_range_list acs_ch_list;
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
enum {
LONG_PREAMBLE = 0,
@ -584,6 +589,9 @@ struct hostapd_config {
int ap_table_max_size;
int ap_table_expiration_time;
unsigned int track_sta_max_num;
unsigned int track_sta_max_age;
char country[3]; /* first two octets: country code as described in
* ISO/IEC 3166-1. Third octet:
* ' ' (ascii 32): all environments
@ -620,6 +628,7 @@ struct hostapd_config {
u16 ht_capab;
int ieee80211n;
int secondary_channel;
int no_pri_sec_switch;
int require_ht;
int obss_interval;
u32 vht_capab;
@ -629,6 +638,10 @@ struct hostapd_config {
u8 vht_oper_centr_freq_seg0_idx;
u8 vht_oper_centr_freq_seg1_idx;
#ifdef CONFIG_FST
struct fst_iface_cfg fst_cfg;
#endif /* CONFIG_FST */
#ifdef CONFIG_P2P
u8 p2p_go_ctwindow;
#endif /* CONFIG_P2P */

View file

@ -81,6 +81,22 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
wpabuf_put_data(proberesp, buf, pos - buf);
}
#ifdef CONFIG_FST
if (hapd->iface->fst_ies) {
size_t add = wpabuf_len(hapd->iface->fst_ies);
if (wpabuf_resize(&beacon, add) < 0)
goto fail;
wpabuf_put_buf(beacon, hapd->iface->fst_ies);
if (wpabuf_resize(&proberesp, add) < 0)
goto fail;
wpabuf_put_buf(proberesp, hapd->iface->fst_ies);
if (wpabuf_resize(&assocresp, add) < 0)
goto fail;
wpabuf_put_buf(assocresp, hapd->iface->fst_ies);
}
#endif /* CONFIG_FST */
if (hapd->wps_beacon_ie) {
if (wpabuf_resize(&beacon, wpabuf_len(hapd->wps_beacon_ie)) <
0)
@ -217,6 +233,15 @@ void hostapd_free_ap_extra_ies(struct hostapd_data *hapd,
}
int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd)
{
if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
return 0;
return hapd->driver->set_ap_wps_ie(hapd->drv_priv, NULL, NULL, NULL);
}
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
{
struct wpabuf *beacon, *proberesp, *assocresp;
@ -281,8 +306,14 @@ int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname,
params.wpa = hapd->conf->wpa;
params.ieee802_1x = hapd->conf->ieee802_1x;
params.wpa_group = hapd->conf->wpa_group;
params.wpa_pairwise = hapd->conf->wpa_pairwise |
hapd->conf->rsn_pairwise;
if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) ==
(WPA_PROTO_WPA | WPA_PROTO_RSN))
params.wpa_pairwise = hapd->conf->wpa_pairwise |
hapd->conf->rsn_pairwise;
else if (hapd->conf->wpa & WPA_PROTO_RSN)
params.wpa_pairwise = hapd->conf->rsn_pairwise;
else if (hapd->conf->wpa & WPA_PROTO_WPA)
params.wpa_pairwise = hapd->conf->wpa_pairwise;
params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt;
params.rsn_preauth = hapd->conf->rsn_preauth;
#ifdef CONFIG_IEEE80211W
@ -618,7 +649,7 @@ int hostapd_drv_send_mlme(struct hostapd_data *hapd,
{
if (hapd->driver == NULL || hapd->driver->send_mlme == NULL)
return 0;
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack);
return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0);
}
@ -712,16 +743,100 @@ int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
}
static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd,
struct hostapd_hw_modes *mode,
int acs_ch_list_all,
int **freq_list)
{
int i;
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *chan = &mode->channels[i];
if ((acs_ch_list_all ||
freq_range_list_includes(&hapd->iface->conf->acs_ch_list,
chan->chan)) &&
!(chan->flag & HOSTAPD_CHAN_DISABLED))
int_array_add_unique(freq_list, chan->freq);
}
}
int hostapd_drv_do_acs(struct hostapd_data *hapd)
{
struct drv_acs_params params;
int ret, i, acs_ch_list_all = 0;
u8 *channels = NULL;
unsigned int num_channels = 0;
struct hostapd_hw_modes *mode;
int *freq_list = NULL;
if (hapd->driver == NULL || hapd->driver->do_acs == NULL)
return 0;
os_memset(&params, 0, sizeof(params));
params.hw_mode = hapd->iface->conf->hw_mode;
/*
* If no chanlist config parameter is provided, include all enabled
* channels of the selected hw_mode.
*/
if (!hapd->iface->conf->acs_ch_list.num)
acs_ch_list_all = 1;
mode = hapd->iface->current_mode;
if (mode) {
channels = os_malloc(mode->num_channels);
if (channels == NULL)
return -1;
for (i = 0; i < mode->num_channels; i++) {
struct hostapd_channel_data *chan = &mode->channels[i];
if (!acs_ch_list_all &&
!freq_range_list_includes(
&hapd->iface->conf->acs_ch_list,
chan->chan))
continue;
if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) {
channels[num_channels++] = chan->chan;
int_array_add_unique(&freq_list, chan->freq);
}
}
} else {
for (i = 0; i < hapd->iface->num_hw_features; i++) {
mode = &hapd->iface->hw_features[i];
hostapd_get_hw_mode_any_channels(hapd, mode,
acs_ch_list_all,
&freq_list);
}
}
params.ch_list = channels;
params.ch_list_len = num_channels;
params.freq_list = freq_list;
params.ht_enabled = !!(hapd->iface->conf->ieee80211n);
params.ht40_enabled = !!(hapd->iface->conf->ht_capab &
HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
return hapd->driver->do_acs(hapd->drv_priv, &params);
params.vht_enabled = !!(hapd->iface->conf->ieee80211ac);
params.ch_width = 20;
if (hapd->iface->conf->ieee80211n && params.ht40_enabled)
params.ch_width = 40;
/* Note: VHT20 is defined by combination of ht_capab & vht_oper_chwidth
*/
if (hapd->iface->conf->ieee80211ac && params.ht40_enabled) {
if (hapd->iface->conf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
params.ch_width = 80;
else if (hapd->iface->conf->vht_oper_chwidth ==
VHT_CHANWIDTH_160MHZ ||
hapd->iface->conf->vht_oper_chwidth ==
VHT_CHANWIDTH_80P80MHZ)
params.ch_width = 160;
}
ret = hapd->driver->do_acs(hapd->drv_priv, &params);
os_free(channels);
return ret;
}

View file

@ -24,6 +24,7 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
struct wpabuf *proberesp,
struct wpabuf *assocresp);
int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd);
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
int hostapd_set_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized);

View file

@ -193,14 +193,14 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
elems->supp_rates, elems->supp_rates_len,
elems->ext_supp_rates, elems->ext_supp_rates_len);
if (elems->erp_info && elems->erp_info_len == 1)
if (elems->erp_info)
ap->erp = elems->erp_info[0];
else
ap->erp = -1;
if (elems->ds_params && elems->ds_params_len == 1)
if (elems->ds_params)
ap->channel = elems->ds_params[0];
else if (elems->ht_operation && elems->ht_operation_len >= 1)
else if (elems->ht_operation)
ap->channel = elems->ht_operation[0];
else if (fi)
ap->channel = fi->channel;
@ -248,15 +248,12 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
}
static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
void ap_list_timer(struct hostapd_iface *iface)
{
struct hostapd_iface *iface = eloop_ctx;
struct os_reltime now;
struct ap_info *ap;
int set_beacon = 0;
eloop_register_timeout(10, 0, ap_list_timer, iface, NULL);
if (!iface->ap_list)
return;
@ -305,13 +302,11 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
int ap_list_init(struct hostapd_iface *iface)
{
eloop_register_timeout(10, 0, ap_list_timer, iface, NULL);
return 0;
}
void ap_list_deinit(struct hostapd_iface *iface)
{
eloop_cancel_timeout(ap_list_timer, iface, NULL);
hostapd_free_aps(iface);
}

View file

@ -39,6 +39,7 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
#ifdef NEED_AP_MLME
int ap_list_init(struct hostapd_iface *iface);
void ap_list_deinit(struct hostapd_iface *iface);
void ap_list_timer(struct hostapd_iface *iface);
#else /* NEED_AP_MLME */
static inline int ap_list_init(struct hostapd_iface *iface)
{
@ -48,6 +49,10 @@ static inline int ap_list_init(struct hostapd_iface *iface)
static inline void ap_list_deinit(struct hostapd_iface *iface)
{
}
static inline void ap_list_timer(struct hostapd_iface *iface)
{
}
#endif /* NEED_AP_MLME */
#endif /* AP_LIST_H */

View file

@ -55,10 +55,11 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
{
const struct hostapd_eap_user *eap_user;
int i;
int rv = -1;
eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
if (eap_user == NULL)
return -1;
goto out;
if (user == NULL)
return 0;
@ -72,7 +73,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
if (eap_user->password) {
user->password = os_malloc(eap_user->password_len);
if (user->password == NULL)
return -1;
goto out;
os_memcpy(user->password, eap_user->password,
eap_user->password_len);
user->password_len = eap_user->password_len;
@ -83,8 +84,13 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
user->ttls_auth = eap_user->ttls_auth;
user->remediation = eap_user->remediation;
user->accept_attr = eap_user->accept_attr;
rv = 0;
return 0;
out:
if (rv)
wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__);
return rv;
}
@ -126,6 +132,7 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
#endif /* CONFIG_HS20 */
srv.erp = conf->eap_server_erp;
srv.erp_domain = conf->erp_domain;
srv.tls_session_lifetime = conf->tls_session_lifetime;
hapd->radius_srv = radius_server_init(&srv);
if (hapd->radius_srv == NULL) {
@ -145,9 +152,12 @@ int authsrv_init(struct hostapd_data *hapd)
if (hapd->conf->eap_server &&
(hapd->conf->ca_cert || hapd->conf->server_cert ||
hapd->conf->private_key || hapd->conf->dh_file)) {
struct tls_config conf;
struct tls_connection_params params;
hapd->ssl_ctx = tls_init(NULL);
os_memset(&conf, 0, sizeof(conf));
conf.tls_session_lifetime = hapd->conf->tls_session_lifetime;
hapd->ssl_ctx = tls_init(&conf);
if (hapd->ssl_ctx == NULL) {
wpa_printf(MSG_ERROR, "Failed to initialize TLS");
authsrv_deinit(hapd);

View file

@ -360,7 +360,6 @@ static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos,
static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
struct sta_info *sta,
const struct ieee80211_mgmt *req,
int is_p2p, size_t *resp_len)
{
@ -378,6 +377,10 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
if (hapd->p2p_probe_resp_ie)
buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
#endif /* CONFIG_P2P */
#ifdef CONFIG_FST
if (hapd->iface->fst_ies)
buflen += wpabuf_len(hapd->iface->fst_ies);
#endif /* CONFIG_FST */
if (hapd->conf->vendor_elements)
buflen += wpabuf_len(hapd->conf->vendor_elements);
if (hapd->conf->vendor_vht) {
@ -402,7 +405,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
/* hardware or low-level driver will setup seq_ctrl and timestamp */
resp->u.probe_resp.capab_info =
host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
host_to_le16(hostapd_own_capab_info(hapd));
pos = resp->u.probe_resp.variable;
*pos++ = WLAN_EID_SSID;
@ -450,6 +453,15 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp,
&hapd->cs_c_off_proberesp);
#ifdef CONFIG_FST
if (hapd->iface->fst_ies) {
os_memcpy(pos, wpabuf_head(hapd->iface->fst_ies),
wpabuf_len(hapd->iface->fst_ies));
pos += wpabuf_len(hapd->iface->fst_ies);
}
#endif /* CONFIG_FST */
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
pos = hostapd_eid_vht_capabilities(hapd, pos);
@ -540,6 +552,102 @@ static enum ssid_match_result ssid_match(struct hostapd_data *hapd,
}
void sta_track_expire(struct hostapd_iface *iface, int force)
{
struct os_reltime now;
struct hostapd_sta_info *info;
if (!iface->num_sta_seen)
return;
os_get_reltime(&now);
while ((info = dl_list_first(&iface->sta_seen, struct hostapd_sta_info,
list))) {
if (!force &&
!os_reltime_expired(&now, &info->last_seen,
iface->conf->track_sta_max_age))
break;
force = 0;
wpa_printf(MSG_MSGDUMP, "%s: Expire STA tracking entry for "
MACSTR, iface->bss[0]->conf->iface,
MAC2STR(info->addr));
dl_list_del(&info->list);
iface->num_sta_seen--;
os_free(info);
}
}
static struct hostapd_sta_info * sta_track_get(struct hostapd_iface *iface,
const u8 *addr)
{
struct hostapd_sta_info *info;
dl_list_for_each(info, &iface->sta_seen, struct hostapd_sta_info, list)
if (os_memcmp(addr, info->addr, ETH_ALEN) == 0)
return info;
return NULL;
}
void sta_track_add(struct hostapd_iface *iface, const u8 *addr)
{
struct hostapd_sta_info *info;
info = sta_track_get(iface, addr);
if (info) {
/* Move the most recent entry to the end of the list */
dl_list_del(&info->list);
dl_list_add_tail(&iface->sta_seen, &info->list);
os_get_reltime(&info->last_seen);
return;
}
/* Add a new entry */
info = os_zalloc(sizeof(*info));
os_memcpy(info->addr, addr, ETH_ALEN);
os_get_reltime(&info->last_seen);
if (iface->num_sta_seen >= iface->conf->track_sta_max_num) {
/* Expire oldest entry to make room for a new one */
sta_track_expire(iface, 1);
}
wpa_printf(MSG_MSGDUMP, "%s: Add STA tracking entry for "
MACSTR, iface->bss[0]->conf->iface, MAC2STR(addr));
dl_list_add_tail(&iface->sta_seen, &info->list);
iface->num_sta_seen++;
}
struct hostapd_data *
sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr,
const char *ifname)
{
struct hapd_interfaces *interfaces = iface->interfaces;
size_t i, j;
for (i = 0; i < interfaces->count; i++) {
struct hostapd_data *hapd = NULL;
iface = interfaces->iface[i];
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
if (os_strcmp(ifname, hapd->conf->iface) == 0)
break;
hapd = NULL;
}
if (hapd && sta_track_get(iface, addr))
return hapd;
}
return NULL;
}
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len,
int ssi_signal)
@ -548,7 +656,6 @@ void handle_probe_req(struct hostapd_data *hapd,
struct ieee802_11_elems elems;
const u8 *ie;
size_t ie_len;
struct sta_info *sta = NULL;
size_t i, resp_len;
int noack;
enum ssid_match_result res;
@ -556,6 +663,8 @@ void handle_probe_req(struct hostapd_data *hapd,
ie = mgmt->u.probe_req.variable;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
return;
if (hapd->iconf->track_sta_max_num)
sta_track_add(hapd->iface, mgmt->sa);
ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
@ -590,7 +699,7 @@ void handle_probe_req(struct hostapd_data *hapd,
* is less likely to see them (Probe Request frame sent on a
* neighboring, but partially overlapping, channel).
*/
if (elems.ds_params && elems.ds_params_len == 1 &&
if (elems.ds_params &&
hapd->iface->current_mode &&
(hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G ||
hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B) &&
@ -635,8 +744,6 @@ void handle_probe_req(struct hostapd_data *hapd,
return;
}
sta = ap_get_sta(hapd, mgmt->sa);
#ifdef CONFIG_P2P
if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
@ -649,10 +756,7 @@ void handle_probe_req(struct hostapd_data *hapd,
res = ssid_match(hapd, elems.ssid, elems.ssid_len,
elems.ssid_list, elems.ssid_list_len);
if (res != NO_SSID_MATCH) {
if (sta)
sta->ssid_probe = &hapd->conf->ssid;
} else {
if (res == NO_SSID_MATCH) {
if (!(mgmt->da[0] & 0x01)) {
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
" for foreign SSID '%s' (DA " MACSTR ")%s",
@ -709,6 +813,18 @@ void handle_probe_req(struct hostapd_data *hapd,
/* TODO: verify that supp_rates contains at least one matching rate
* with AP configuration */
if (hapd->conf->no_probe_resp_if_seen_on &&
is_multicast_ether_addr(mgmt->da) &&
is_multicast_ether_addr(mgmt->bssid) &&
sta_track_seen_on(hapd->iface, mgmt->sa,
hapd->conf->no_probe_resp_if_seen_on)) {
wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
" since STA has been seen on %s",
hapd->conf->iface, MAC2STR(mgmt->sa),
hapd->conf->no_probe_resp_if_seen_on);
return;
}
#ifdef CONFIG_TESTING_OPTIONS
if (hapd->iconf->ignore_probe_probability > 0.0 &&
drand48() < hapd->iconf->ignore_probe_probability) {
@ -719,7 +835,7 @@ void handle_probe_req(struct hostapd_data *hapd,
}
#endif /* CONFIG_TESTING_OPTIONS */
resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL,
&resp_len);
if (resp == NULL)
return;
@ -774,7 +890,7 @@ static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
"this");
/* Generate a Probe Response template for the non-P2P case */
return hostapd_gen_probe_resp(hapd, NULL, NULL, 0, resp_len);
return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len);
}
#endif /* NEED_AP_MLME */
@ -804,6 +920,10 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
if (hapd->p2p_beacon_ie)
tail_len += wpabuf_len(hapd->p2p_beacon_ie);
#endif /* CONFIG_P2P */
#ifdef CONFIG_FST
if (hapd->iface->fst_ies)
tail_len += wpabuf_len(hapd->iface->fst_ies);
#endif /* CONFIG_FST */
if (hapd->conf->vendor_elements)
tail_len += wpabuf_len(hapd->conf->vendor_elements);
@ -833,7 +953,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
host_to_le16(hapd->iconf->beacon_int);
/* hardware or low-level driver will setup seq_ctrl and timestamp */
capab_info = hostapd_own_capab_info(hapd, NULL, 0);
capab_info = hostapd_own_capab_info(hapd);
head->u.beacon.capab_info = host_to_le16(capab_info);
pos = &head->u.beacon.variable[0];
@ -902,6 +1022,15 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
tailpos = hostapd_add_csa_elems(hapd, tailpos, tail,
&hapd->cs_c_off_beacon);
#ifdef CONFIG_FST
if (hapd->iface->fst_ies) {
os_memcpy(tailpos, wpabuf_head(hapd->iface->fst_ies),
wpabuf_len(hapd->iface->fst_ies));
tailpos += wpabuf_len(hapd->iface->fst_ies);
}
#endif /* CONFIG_FST */
#ifdef CONFIG_IEEE80211AC
if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
@ -963,8 +1092,14 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
params->basic_rates = hapd->iface->basic_rates;
params->ssid = hapd->conf->ssid.ssid;
params->ssid_len = hapd->conf->ssid.ssid_len;
params->pairwise_ciphers = hapd->conf->wpa_pairwise |
hapd->conf->rsn_pairwise;
if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) ==
(WPA_PROTO_WPA | WPA_PROTO_RSN))
params->pairwise_ciphers = hapd->conf->wpa_pairwise |
hapd->conf->rsn_pairwise;
else if (hapd->conf->wpa & WPA_PROTO_RSN)
params->pairwise_ciphers = hapd->conf->rsn_pairwise;
else if (hapd->conf->wpa & WPA_PROTO_WPA)
params->pairwise_ciphers = hapd->conf->wpa_pairwise;
params->group_cipher = hapd->conf->wpa_group;
params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
params->auth_algs = hapd->conf->auth_algs;

View file

@ -21,5 +21,10 @@ int ieee802_11_update_beacons(struct hostapd_iface *iface);
int ieee802_11_build_ap_params(struct hostapd_data *hapd,
struct wpa_driver_ap_params *params);
void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params);
void sta_track_add(struct hostapd_iface *iface, const u8 *addr);
void sta_track_expire(struct hostapd_iface *iface, int force);
struct hostapd_data *
sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr,
const char *ifname);
#endif /* BEACON_H */

View file

@ -12,6 +12,7 @@
#include "common/ieee802_11_defs.h"
#include "common/sae.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "fst/fst_ctrl_iface.h"
#include "hostapd.h"
#include "ieee802_1x.h"
#include "wpa_auth.h"
@ -153,6 +154,13 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
}
#endif /* CONFIG_SAE */
if (sta->vlan_id > 0) {
res = os_snprintf(buf + len, buflen - len, "vlan_id=%d\n",
sta->vlan_id);
if (!os_snprintf_error(buflen - len, res))
len += res;
}
return len;
}
@ -199,7 +207,10 @@ int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
return -1;
}
return hostapd_ctrl_iface_sta_mib(hapd, sta, buf, buflen);
ret = hostapd_ctrl_iface_sta_mib(hapd, sta, buf, buflen);
ret += fst_ctrl_iface_mb_info(addr, buf + ret, buflen - ret);
return ret;
}

View file

@ -122,6 +122,20 @@ static int dfs_is_chan_allowed(struct hostapd_channel_data *chan, int n_chans)
}
static struct hostapd_channel_data *
dfs_get_chan_data(struct hostapd_hw_modes *mode, int freq, int first_chan_idx)
{
int i;
for (i = first_chan_idx; i < mode->num_channels; i++) {
if (mode->channels[i].freq == freq)
return &mode->channels[i];
}
return NULL;
}
static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
int first_chan_idx, int num_chans,
int skip_radar)
@ -129,15 +143,15 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
struct hostapd_channel_data *first_chan, *chan;
int i;
if (first_chan_idx + num_chans >= mode->num_channels)
if (first_chan_idx + num_chans > mode->num_channels)
return 0;
first_chan = &mode->channels[first_chan_idx];
for (i = 0; i < num_chans; i++) {
chan = &mode->channels[first_chan_idx + i];
if (first_chan->freq + i * 20 != chan->freq)
chan = dfs_get_chan_data(mode, first_chan->freq + i * 20,
first_chan_idx);
if (!chan)
return 0;
if (!dfs_channel_available(chan, skip_radar))
@ -151,16 +165,10 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode,
static int is_in_chanlist(struct hostapd_iface *iface,
struct hostapd_channel_data *chan)
{
int *entry;
if (!iface->conf->chanlist)
if (!iface->conf->acs_ch_list.num)
return 1;
for (entry = iface->conf->chanlist; *entry != -1; entry++) {
if (*entry == chan->chan)
return 1;
}
return 0;
return freq_range_list_includes(&iface->conf->acs_ch_list, chan->chan);
}

View file

@ -18,6 +18,7 @@
#include "crypto/random.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
#include "fst/fst.h"
#include "wnm_ap.h"
#include "hostapd.h"
#include "ieee802_11.h"
@ -42,10 +43,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
struct ieee802_11_elems elems;
const u8 *ie;
size_t ielen;
#ifdef CONFIG_IEEE80211R
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
u8 *p = buf;
#endif /* CONFIG_IEEE80211R */
#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */
u16 reason = WLAN_REASON_UNSPECIFIED;
u16 status = WLAN_STATUS_SUCCESS;
const u8 *p2p_dev_addr = NULL;
@ -58,8 +59,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
* running, so better make sure we stop processing such an
* event here.
*/
wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with "
"no address");
wpa_printf(MSG_DEBUG,
"hostapd_notif_assoc: Skip event with no address");
return -1;
}
random_add_randomness(addr, ETH_ALEN);
@ -89,8 +90,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
} else {
ie = NULL;
ielen = 0;
wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in "
"(Re)AssocReq");
wpa_printf(MSG_DEBUG,
"STA did not include WPS/RSN/WPA IE in (Re)AssocReq");
}
sta = ap_get_sta(hapd, addr);
@ -126,8 +127,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
#ifdef CONFIG_IEEE80211N
#ifdef NEED_AP_MLME
if (elems.ht_capabilities &&
elems.ht_capabilities_len >=
sizeof(struct ieee80211_ht_capabilities) &&
(hapd->iface->conf->ht_capab &
HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
struct ieee80211_ht_capabilities *ht_cap =
@ -157,13 +156,20 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
sta->hs20_ie = NULL;
#endif /* CONFIG_HS20 */
#ifdef CONFIG_FST
wpabuf_free(sta->mb_ies);
if (hapd->iface->fst)
sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
else
sta->mb_ies = NULL;
#endif /* CONFIG_FST */
if (hapd->conf->wpa) {
if (ie == NULL || ielen == 0) {
#ifdef CONFIG_WPS
if (hapd->conf->wps_state) {
wpa_printf(MSG_DEBUG, "STA did not include "
"WPA/RSN IE in (Re)Association "
"Request - possible WPS use");
wpa_printf(MSG_DEBUG,
"STA did not include WPA/RSN IE in (Re)Association Request - possible WPS use");
sta->flags |= WLAN_STA_MAYBE_WPS;
goto skip_wpa_check;
}
@ -176,13 +182,14 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
struct wpabuf *wps;
sta->flags |= WLAN_STA_WPS;
wps = ieee802_11_vendor_ie_concat(ie, ielen,
WPS_IE_VENDOR_TYPE);
if (wps) {
if (wps_is_20(wps)) {
wpa_printf(MSG_DEBUG, "WPS: STA "
"supports WPS 2.0");
wpa_printf(MSG_DEBUG,
"WPS: STA supports WPS 2.0");
sta->flags |= WLAN_STA_WPS2;
}
wpabuf_free(wps);
@ -196,16 +203,17 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
sta->addr,
p2p_dev_addr);
if (sta->wpa_sm == NULL) {
wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
"machine");
wpa_printf(MSG_ERROR,
"Failed to initialize WPA state machine");
return -1;
}
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
ie, ielen,
elems.mdie, elems.mdie_len);
if (res != WPA_IE_OK) {
wpa_printf(MSG_DEBUG, "WPA/RSN information element "
"rejected? (res %u)", res);
wpa_printf(MSG_DEBUG,
"WPA/RSN information element rejected? (res %u)",
res);
wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
if (res == WPA_INVALID_GROUP) {
reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
@ -248,14 +256,12 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
if (sta->sa_query_count == 0)
ap_sta_start_sa_query(hapd, sta);
#ifdef CONFIG_IEEE80211R
status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
p - buf);
#endif /* CONFIG_IEEE80211R */
return 0;
}
@ -283,6 +289,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
} else if (hapd->conf->wps_state) {
#ifdef CONFIG_WPS
struct wpabuf *wps;
if (req_ies)
wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
WPS_IE_VENDOR_TYPE);
@ -299,8 +306,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
if (wps) {
sta->flags |= WLAN_STA_WPS;
if (wps_is_20(wps)) {
wpa_printf(MSG_DEBUG, "WPS: STA supports "
"WPS 2.0");
wpa_printf(MSG_DEBUG,
"WPS: STA supports WPS 2.0");
sta->flags |= WLAN_STA_WPS2;
}
} else
@ -322,8 +329,8 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
sta->addr, NULL);
if (sta->wpa_sm == NULL) {
wpa_printf(MSG_WARNING, "Failed to initialize WPA "
"state machine");
wpa_printf(MSG_WARNING,
"Failed to initialize WPA state machine");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
@ -395,8 +402,8 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
* was running, so better make sure we stop processing such an
* event here.
*/
wpa_printf(MSG_DEBUG, "hostapd_notif_disassoc: Skip event "
"with no address");
wpa_printf(MSG_DEBUG,
"hostapd_notif_disassoc: Skip event with no address");
return;
}
@ -405,8 +412,9 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr)
sta = ap_get_sta(hapd, addr);
if (sta == NULL) {
wpa_printf(MSG_DEBUG, "Disassociation notification for "
"unknown STA " MACSTR, MAC2STR(addr));
wpa_printf(MSG_DEBUG,
"Disassociation notification for unknown STA "
MACSTR, MAC2STR(addr));
return;
}
@ -427,8 +435,8 @@ void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr)
return;
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_INFO, "disconnected due to excessive "
"missing ACKs");
HOSTAPD_LEVEL_INFO,
"disconnected due to excessive missing ACKs");
hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK);
if (sta)
ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK);
@ -452,8 +460,8 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
channel = hostapd_hw_get_channel(hapd, freq);
if (!channel) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING, "driver switched to "
"bad channel!");
HOSTAPD_LEVEL_WARNING,
"driver switched to bad channel!");
return;
}
@ -532,10 +540,9 @@ void hostapd_event_connect_failed_reason(struct hostapd_data *hapd,
#ifdef CONFIG_ACS
static void hostapd_acs_channel_selected(struct hostapd_data *hapd,
u8 pri_channel, u8 sec_channel)
struct acs_selected_channels *acs_res)
{
int channel;
int ret;
int ret, i;
if (hapd->iconf->channel) {
wpa_printf(MSG_INFO, "ACS: Channel was already set to %d",
@ -543,29 +550,73 @@ static void hostapd_acs_channel_selected(struct hostapd_data *hapd,
return;
}
hapd->iface->freq = hostapd_hw_get_freq(hapd, pri_channel);
if (!hapd->iface->current_mode) {
for (i = 0; i < hapd->iface->num_hw_features; i++) {
struct hostapd_hw_modes *mode =
&hapd->iface->hw_features[i];
channel = pri_channel;
if (!channel) {
if (mode->mode == acs_res->hw_mode) {
hapd->iface->current_mode = mode;
break;
}
}
if (!hapd->iface->current_mode) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"driver selected to bad hw_mode");
return;
}
}
hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel);
if (!acs_res->pri_channel) {
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"driver switched to bad channel");
return;
}
hapd->iconf->channel = channel;
hapd->iconf->channel = acs_res->pri_channel;
hapd->iconf->acs = 1;
if (sec_channel == 0)
if (acs_res->sec_channel == 0)
hapd->iconf->secondary_channel = 0;
else if (sec_channel < pri_channel)
else if (acs_res->sec_channel < acs_res->pri_channel)
hapd->iconf->secondary_channel = -1;
else if (sec_channel > pri_channel)
else if (acs_res->sec_channel > acs_res->pri_channel)
hapd->iconf->secondary_channel = 1;
else {
wpa_printf(MSG_ERROR, "Invalid secondary channel!");
return;
}
if (hapd->iface->conf->ieee80211ac) {
/* set defaults for backwards compatibility */
hapd->iconf->vht_oper_centr_freq_seg1_idx = 0;
hapd->iconf->vht_oper_centr_freq_seg0_idx = 0;
hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT;
if (acs_res->ch_width == 80) {
hapd->iconf->vht_oper_centr_freq_seg0_idx =
acs_res->vht_seg0_center_ch;
hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ;
} else if (acs_res->ch_width == 160) {
if (acs_res->vht_seg1_center_ch == 0) {
hapd->iconf->vht_oper_centr_freq_seg0_idx =
acs_res->vht_seg0_center_ch;
hapd->iconf->vht_oper_chwidth =
VHT_CHANWIDTH_160MHZ;
} else {
hapd->iconf->vht_oper_centr_freq_seg0_idx =
acs_res->vht_seg0_center_ch;
hapd->iconf->vht_oper_centr_freq_seg1_idx =
acs_res->vht_seg1_center_ch;
hapd->iconf->vht_oper_chwidth =
VHT_CHANWIDTH_80P80MHZ;
}
}
}
ret = hostapd_acs_completed(hapd->iface, 0);
if (ret) {
wpa_printf(MSG_ERROR,
@ -647,8 +698,8 @@ static void hostapd_notif_auth(struct hostapd_data *hapd,
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
sta->addr, NULL);
if (sta->wpa_sm == NULL) {
wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
"state machine");
wpa_printf(MSG_DEBUG,
"FT: Failed to initialize WPA state machine");
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
goto fail;
}
@ -683,7 +734,7 @@ static void hostapd_action_rx(struct hostapd_data *hapd,
if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION)
return; /* handled by the driver */
wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
mgmt->u.action.category, (int) plen);
sta = ap_get_sta(hapd, mgmt->sa);
@ -694,6 +745,7 @@ static void hostapd_action_rx(struct hostapd_data *hapd,
#ifdef CONFIG_IEEE80211R
if (mgmt->u.action.category == WLAN_ACTION_FT) {
const u8 *payload = drv_mgmt->frame + 24 + 1;
wpa_ft_action_rx(sta->wpa_sm, payload, plen);
}
#endif /* CONFIG_IEEE80211R */
@ -710,6 +762,13 @@ static void hostapd_action_rx(struct hostapd_data *hapd,
ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len);
}
#endif /* CONFIG_WNM */
#ifdef CONFIG_FST
if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) {
fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len);
return;
}
#endif /* CONFIG_FST */
}
@ -761,6 +820,7 @@ static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
if (hapd->ext_mgmt_frame_handling) {
size_t hex_len = 2 * rx_mgmt->frame_len + 1;
char *hex = os_malloc(hex_len);
if (hex) {
wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame,
rx_mgmt->frame_len);
@ -778,8 +838,7 @@ static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
hapd = get_hapd_bssid(iface, bssid);
if (hapd == NULL) {
u16 fc;
fc = le_to_host16(hdr->frame_control);
u16 fc = le_to_host16(hdr->frame_control);
/*
* Drop frames to unknown BSSIDs except for Beacon frames which
@ -798,6 +857,7 @@ static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt)
if (hapd == HAPD_BROADCAST) {
size_t i;
ret = 0;
for (i = 0; i < iface->num_bss; i++) {
/* if bss is set, driver will call this function for
@ -824,6 +884,7 @@ static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
size_t len, u16 stype, int ok)
{
struct ieee80211_hdr *hdr;
hdr = (struct ieee80211_hdr *) buf;
hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len));
if (hapd == NULL || hapd == HAPD_BROADCAST)
@ -837,6 +898,7 @@ static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf,
static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr)
{
struct sta_info *sta = ap_get_sta(hapd, addr);
if (sta)
return 0;
@ -863,11 +925,10 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src,
size_t j;
for (j = 0; j < iface->num_bss; j++) {
if ((sta = ap_get_sta(iface->bss[j], src))) {
if (sta->flags & WLAN_STA_ASSOC) {
hapd = iface->bss[j];
break;
}
sta = ap_get_sta(iface->bss[j], src);
if (sta && sta->flags & WLAN_STA_ASSOC) {
hapd = iface->bss[j];
break;
}
}
@ -927,7 +988,8 @@ static void hostapd_single_channel_get_survey(struct hostapd_iface *iface,
if (!chan || chan->flag & HOSTAPD_CHAN_DISABLED)
return;
wpa_printf(MSG_DEBUG, "Single Channel Survey: (freq=%d channel_time=%ld channel_time_busy=%ld)",
wpa_printf(MSG_DEBUG,
"Single Channel Survey: (freq=%d channel_time=%ld channel_time_busy=%ld)",
survey->freq,
(unsigned long int) survey->channel_time,
(unsigned long int) survey->channel_time_busy);
@ -1061,6 +1123,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
data->rx_mgmt.frame_len >= 24) {
const struct ieee80211_hdr *hdr;
u16 fc;
hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame;
fc = le_to_host16(hdr->frame_control);
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
@ -1248,9 +1311,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
#ifdef CONFIG_ACS
case EVENT_ACS_CHANNEL_SELECTED:
hostapd_acs_channel_selected(
hapd, data->acs_selected_channels.pri_channel,
data->acs_selected_channels.sec_channel);
hostapd_acs_channel_selected(hapd,
&data->acs_selected_channels);
break;
#endif /* CONFIG_ACS */
default:

View file

@ -138,8 +138,12 @@ eap_user_sqlite_get(struct hostapd_data *hapd, const u8 *identity,
char id_str[256], cmd[300];
size_t i;
if (identity_len >= sizeof(id_str))
if (identity_len >= sizeof(id_str)) {
wpa_printf(MSG_DEBUG, "%s: identity len too big: %d >= %d",
__func__, (int) identity_len,
(int) (sizeof(id_str)));
return NULL;
}
os_memcpy(id_str, identity, identity_len);
id_str[identity_len] = '\0';
for (i = 0; i < identity_len; i++) {
@ -182,7 +186,9 @@ eap_user_sqlite_get(struct hostapd_data *hapd, const u8 *identity,
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
if (sqlite3_exec(db, cmd, get_user_cb, &hapd->tmp_eap_user, NULL) !=
SQLITE_OK) {
wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL operation");
wpa_printf(MSG_DEBUG,
"DB: Failed to complete SQL operation: %s db: %s",
sqlite3_errmsg(db), hapd->conf->eap_user_sqlite);
} else if (hapd->tmp_eap_user.next)
user = &hapd->tmp_eap_user;
@ -192,8 +198,10 @@ eap_user_sqlite_get(struct hostapd_data *hapd, const u8 *identity,
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
if (sqlite3_exec(db, cmd, get_wildcard_cb, &hapd->tmp_eap_user,
NULL) != SQLITE_OK) {
wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL "
"operation");
wpa_printf(MSG_DEBUG,
"DB: Failed to complete SQL operation: %s db: %s",
sqlite3_errmsg(db),
hapd->conf->eap_user_sqlite);
} else if (hapd->tmp_eap_user.next) {
user = &hapd->tmp_eap_user;
os_free(user->identity);

View file

@ -17,6 +17,7 @@
#include "eap_server/tncs.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "eapol_auth/eapol_auth_sm_i.h"
#include "fst/fst.h"
#include "hostapd.h"
#include "authsrv.h"
#include "sta_info.h"
@ -179,6 +180,7 @@ int hostapd_reload_config(struct hostapd_iface *iface)
hapd = iface->bss[j];
hapd->iconf = newconf;
hapd->iconf->channel = oldconf->channel;
hapd->iconf->acs = oldconf->acs;
hapd->iconf->secondary_channel = oldconf->secondary_channel;
hapd->iconf->ieee80211n = oldconf->ieee80211n;
hapd->iconf->ieee80211ac = oldconf->ieee80211ac;
@ -259,6 +261,7 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd)
{
os_free(hapd->probereq_cb);
hapd->probereq_cb = NULL;
hapd->num_probereq_cb = 0;
#ifdef CONFIG_P2P
wpabuf_free(hapd->p2p_beacon_ie);
@ -353,6 +356,22 @@ static void hostapd_cleanup(struct hostapd_data *hapd)
}
static void sta_track_deinit(struct hostapd_iface *iface)
{
struct hostapd_sta_info *info;
if (!iface->num_sta_seen)
return;
while ((info = dl_list_first(&iface->sta_seen, struct hostapd_sta_info,
list))) {
dl_list_del(&info->list);
iface->num_sta_seen--;
os_free(info);
}
}
static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
{
wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
@ -368,6 +387,7 @@ static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface)
os_free(iface->basic_rates);
iface->basic_rates = NULL;
ap_list_deinit(iface);
sta_track_deinit(iface);
}
@ -861,7 +881,7 @@ hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr)
static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
{
struct hostapd_bss_config *conf = hapd->conf;
u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
u8 ssid[SSID_MAX_LEN + 1];
int ssid_len, set_ssid;
char force_ifname[IFNAMSIZ];
u8 if_addr[ETH_ALEN];
@ -1363,6 +1383,132 @@ static int setup_interface2(struct hostapd_iface *iface)
}
#ifdef CONFIG_FST
static const u8 * fst_hostapd_get_bssid_cb(void *ctx)
{
struct hostapd_data *hapd = ctx;
return hapd->own_addr;
}
static void fst_hostapd_get_channel_info_cb(void *ctx,
enum hostapd_hw_mode *hw_mode,
u8 *channel)
{
struct hostapd_data *hapd = ctx;
*hw_mode = ieee80211_freq_to_chan(hapd->iface->freq, channel);
}
static void fst_hostapd_set_ies_cb(void *ctx, const struct wpabuf *fst_ies)
{
struct hostapd_data *hapd = ctx;
if (hapd->iface->fst_ies != fst_ies) {
hapd->iface->fst_ies = fst_ies;
if (ieee802_11_set_beacon(hapd))
wpa_printf(MSG_WARNING, "FST: Cannot set beacon");
}
}
static int fst_hostapd_send_action_cb(void *ctx, const u8 *da,
struct wpabuf *buf)
{
struct hostapd_data *hapd = ctx;
return hostapd_drv_send_action(hapd, hapd->iface->freq, 0, da,
wpabuf_head(buf), wpabuf_len(buf));
}
static const struct wpabuf * fst_hostapd_get_mb_ie_cb(void *ctx, const u8 *addr)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta = ap_get_sta(hapd, addr);
return sta ? sta->mb_ies : NULL;
}
static void fst_hostapd_update_mb_ie_cb(void *ctx, const u8 *addr,
const u8 *buf, size_t size)
{
struct hostapd_data *hapd = ctx;
struct sta_info *sta = ap_get_sta(hapd, addr);
if (sta) {
struct mb_ies_info info;
if (!mb_ies_info_by_ies(&info, buf, size)) {
wpabuf_free(sta->mb_ies);
sta->mb_ies = mb_ies_by_info(&info);
}
}
}
static const u8 * fst_hostapd_get_sta(struct fst_get_peer_ctx **get_ctx,
Boolean mb_only)
{
struct sta_info *s = (struct sta_info *) *get_ctx;
if (mb_only) {
for (; s && !s->mb_ies; s = s->next)
;
}
if (s) {
*get_ctx = (struct fst_get_peer_ctx *) s->next;
return s->addr;
}
*get_ctx = NULL;
return NULL;
}
static const u8 * fst_hostapd_get_peer_first(void *ctx,
struct fst_get_peer_ctx **get_ctx,
Boolean mb_only)
{
struct hostapd_data *hapd = ctx;
*get_ctx = (struct fst_get_peer_ctx *) hapd->sta_list;
return fst_hostapd_get_sta(get_ctx, mb_only);
}
static const u8 * fst_hostapd_get_peer_next(void *ctx,
struct fst_get_peer_ctx **get_ctx,
Boolean mb_only)
{
return fst_hostapd_get_sta(get_ctx, mb_only);
}
void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
struct fst_wpa_obj *iface_obj)
{
iface_obj->ctx = hapd;
iface_obj->get_bssid = fst_hostapd_get_bssid_cb;
iface_obj->get_channel_info = fst_hostapd_get_channel_info_cb;
iface_obj->set_ies = fst_hostapd_set_ies_cb;
iface_obj->send_action = fst_hostapd_send_action_cb;
iface_obj->get_mb_ie = fst_hostapd_get_mb_ie_cb;
iface_obj->update_mb_ie = fst_hostapd_update_mb_ie_cb;
iface_obj->get_peer_first = fst_hostapd_get_peer_first;
iface_obj->get_peer_next = fst_hostapd_get_peer_next;
}
#endif /* CONFIG_FST */
/**
* hostapd_setup_interface_complete - Complete interface setup
*
@ -1495,6 +1641,7 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
hostapd_tx_queue_params(iface);
ap_list_init(iface);
dl_list_init(&iface->sta_seen);
hostapd_set_acl(hapd);
@ -1528,6 +1675,22 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
#ifdef NEED_AP_MLME
dfs_offload:
#endif /* NEED_AP_MLME */
#ifdef CONFIG_FST
if (hapd->iconf->fst_cfg.group_id[0]) {
struct fst_wpa_obj iface_obj;
fst_hostapd_fill_iface_obj(hapd, &iface_obj);
iface->fst = fst_attach(hapd->conf->iface, hapd->own_addr,
&iface_obj, &hapd->iconf->fst_cfg);
if (!iface->fst) {
wpa_printf(MSG_ERROR, "Could not attach to FST %s",
hapd->iconf->fst_cfg.group_id);
goto fail;
}
}
#endif /* CONFIG_FST */
hostapd_set_state(iface, HAPD_IFACE_ENABLED);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
if (hapd->setup_complete_cb)
@ -1544,6 +1707,12 @@ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
wpa_printf(MSG_ERROR, "Interface initialization failed");
hostapd_set_state(iface, HAPD_IFACE_DISABLED);
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
#ifdef CONFIG_FST
if (iface->fst) {
fst_detach(iface->fst);
iface->fst = NULL;
}
#endif /* CONFIG_FST */
if (iface->interfaces && iface->interfaces->terminate_on_error)
eloop_terminate();
return -1;
@ -1643,6 +1812,13 @@ void hostapd_interface_deinit(struct hostapd_iface *iface)
eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
iface->wait_channel_update = 0;
#ifdef CONFIG_FST
if (iface->fst) {
fst_detach(iface->fst);
iface->fst = NULL;
}
#endif /* CONFIG_FST */
for (j = iface->num_bss - 1; j >= 0; j--)
hostapd_bss_deinit(iface->bss[j]);
}
@ -2029,7 +2205,7 @@ hostapd_iface_alloc(struct hapd_interfaces *interfaces)
static struct hostapd_config *
hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname,
const char *ctrl_iface)
const char *ctrl_iface, const char *driver)
{
struct hostapd_bss_config *bss;
struct hostapd_config *conf;
@ -2042,6 +2218,21 @@ hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname,
return NULL;
}
if (driver) {
int j;
for (j = 0; wpa_drivers[j]; j++) {
if (os_strcmp(driver, wpa_drivers[j]->name) == 0) {
conf->driver = wpa_drivers[j];
goto skip;
}
}
wpa_printf(MSG_ERROR,
"Invalid/unknown driver '%s' - registering the default driver",
driver);
}
conf->driver = wpa_drivers[0];
if (conf->driver == NULL) {
wpa_printf(MSG_ERROR, "No driver wrappers registered!");
@ -2049,6 +2240,7 @@ hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname,
return NULL;
}
skip:
bss = conf->last_bss = conf->bss[0];
os_strlcpy(bss->iface, ifname, sizeof(bss->iface));
@ -2209,8 +2401,14 @@ int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf)
if (conf && conf->bss)
os_strlcpy(conf->bss[0]->iface, buf,
sizeof(conf->bss[0]->iface));
} else
conf = hostapd_config_alloc(interfaces, buf, ptr);
} else {
char *driver = os_strchr(ptr, ' ');
if (driver)
*driver++ = '\0';
conf = hostapd_config_alloc(interfaces, buf, ptr, driver);
}
if (conf == NULL || conf->bss == NULL) {
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory "
"for configuration", __func__);
@ -2722,4 +2920,43 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
hostapd_enable_iface(iface);
}
struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
const char *ifname)
{
size_t i, j;
for (i = 0; i < interfaces->count; i++) {
struct hostapd_iface *iface = interfaces->iface[i];
for (j = 0; j < iface->num_bss; j++) {
struct hostapd_data *hapd = iface->bss[j];
if (os_strcmp(ifname, hapd->conf->iface) == 0)
return hapd;
}
}
return NULL;
}
#endif /* NEED_AP_MLME */
void hostapd_periodic_iface(struct hostapd_iface *iface)
{
size_t i;
ap_list_timer(iface);
for (i = 0; i < iface->num_bss; i++) {
struct hostapd_data *hapd = iface->bss[i];
if (!hapd->started)
continue;
#ifndef CONFIG_NO_RADIUS
hostapd_acl_expire(hapd);
#endif /* CONFIG_NO_RADIUS */
}
}

View file

@ -41,6 +41,7 @@ struct hapd_interfaces {
size_t count;
int global_ctrl_sock;
struct wpa_ctrl_dst *global_ctrl_dst;
char *global_iface_path;
char *global_iface_name;
#ifndef CONFIG_NATIVE_WINDOWS
@ -49,6 +50,9 @@ struct hapd_interfaces {
struct hostapd_iface **iface;
size_t terminate_on_error;
#ifndef CONFIG_NO_VLAN
struct dynamic_iface *vlan_priv;
#endif /* CONFIG_NO_VLAN */
};
enum hostapd_chan_status {
@ -265,6 +269,7 @@ struct hostapd_data {
/** Key used for generating SAE anti-clogging tokens */
u8 sae_token_key[8];
struct os_reltime last_sae_token_key_update;
int dot11RSNASAERetransPeriod; /* msec */
#endif /* CONFIG_SAE */
#ifdef CONFIG_TESTING_OPTIONS
@ -276,6 +281,12 @@ struct hostapd_data {
};
struct hostapd_sta_info {
struct dl_list list;
u8 addr[ETH_ALEN];
struct os_reltime last_seen;
};
/**
* struct hostapd_iface - hostapd per-interface data structure
*/
@ -305,6 +316,10 @@ struct hostapd_iface {
unsigned int wait_channel_update:1;
unsigned int cac_started:1;
#ifdef CONFIG_FST
struct fst_iface *fst;
const struct wpabuf *fst_ies;
#endif /* CONFIG_FST */
/*
* When set, indicates that the driver will handle the AP
@ -400,6 +415,9 @@ struct hostapd_iface {
void (*scan_cb)(struct hostapd_iface *iface);
int num_ht40_scan_tries;
struct dl_list sta_seen; /* struct hostapd_sta_info */
unsigned int num_sta_seen;
};
/* hostapd.c */
@ -437,6 +455,7 @@ void
hostapd_switch_channel_fallback(struct hostapd_iface *iface,
const struct hostapd_freq_params *freq_params);
void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
void hostapd_periodic_iface(struct hostapd_iface *iface);
/* utils.c */
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
@ -464,4 +483,12 @@ const struct hostapd_eap_user *
hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity,
size_t identity_len, int phase2);
struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces,
const char *ifname);
#ifdef CONFIG_FST
void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
struct fst_wpa_obj *iface_obj);
#endif /* CONFIG_FST */
#endif /* HOSTAPD_H */

View file

@ -260,8 +260,14 @@ static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan);
if (res == 2)
ieee80211n_switch_pri_sec(iface);
if (res == 2) {
if (iface->conf->no_pri_sec_switch) {
wpa_printf(MSG_DEBUG,
"Cannot switch PRI/SEC channels due to local constraint");
} else {
ieee80211n_switch_pri_sec(iface);
}
}
return !!res;
}
@ -347,8 +353,13 @@ static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface,
sec_freq = pri_freq + 20;
else
sec_freq = pri_freq - 20;
affected_start = (pri_freq + sec_freq) / 2 - 25;
affected_end = (pri_freq + sec_freq) / 2 + 25;
/*
* Note: Need to find the PRI channel also in cases where the affected
* channel is the SEC channel of a 40 MHz BSS, so need to include the
* scanning coverage here to be 40 MHz from the center frequency.
*/
affected_start = (pri_freq + sec_freq) / 2 - 40;
affected_end = (pri_freq + sec_freq) / 2 + 40;
wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
affected_start, affected_end);
@ -510,7 +521,11 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
return 0;
}
if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
/*
* Driver ACS chosen channel may not be HT40 due to internal driver
* restrictions.
*/
if (!iface->conf->acs && (conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) &&
!(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
wpa_printf(MSG_ERROR, "Driver does not support configured "
"HT capability [HT40*]");
@ -717,6 +732,15 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
int ret;
if (!iface->conf->ieee80211n)
return 0;
if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211B &&
iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G &&
(iface->conf->ht_capab & HT_CAP_INFO_DSSS_CCK40MHZ)) {
wpa_printf(MSG_DEBUG,
"Disable HT capability [DSSS_CCK-40] on 5 GHz band");
iface->conf->ht_capab &= ~HT_CAP_INFO_DSSS_CCK40MHZ;
}
if (!ieee80211n_supported_ht_capab(iface))
return -1;
#ifdef CONFIG_IEEE80211AC
@ -740,6 +764,9 @@ static int hostapd_is_usable_chan(struct hostapd_iface *iface,
int i;
struct hostapd_channel_data *chan;
if (!iface->current_mode)
return 0;
for (i = 0; i < iface->current_mode->num_channels; i++) {
chan = &iface->current_mode->channels[i];
if (chan->chan != channel)
@ -801,6 +828,12 @@ hostapd_check_chans(struct hostapd_iface *iface)
static void hostapd_notify_bad_chans(struct hostapd_iface *iface)
{
if (!iface->current_mode) {
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Hardware does not support configured mode");
return;
}
hostapd_logger(iface->bss[0], NULL,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
@ -891,14 +924,18 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
}
if (iface->current_mode == NULL) {
wpa_printf(MSG_ERROR, "Hardware does not support configured "
"mode");
hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Hardware does not support configured mode "
"(%d) (hw_mode in hostapd.conf)",
(int) iface->conf->hw_mode);
return -2;
if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) ||
!(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY))
{
wpa_printf(MSG_ERROR,
"Hardware does not support configured mode");
hostapd_logger(iface->bss[0], NULL,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Hardware does not support configured mode (%d) (hw_mode in hostapd.conf)",
(int) iface->conf->hw_mode);
return -2;
}
}
switch (hostapd_check_chans(iface)) {

View file

@ -36,6 +36,11 @@ static inline int hostapd_get_hw_features(struct hostapd_iface *iface)
return -1;
}
static inline int hostapd_acs_completed(struct hostapd_iface *iface, int err)
{
return -1;
}
static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
{
return -100;

View file

@ -23,6 +23,7 @@
#include "radius/radius_client.h"
#include "p2p/p2p.h"
#include "wps/wps.h"
#include "fst/fst.h"
#include "hostapd.h"
#include "beacon.h"
#include "ieee802_11_auth.h"
@ -38,6 +39,7 @@
#include "p2p_hostapd.h"
#include "ap_drv_ops.h"
#include "wnm_ap.h"
#include "hw_features.h"
#include "ieee802_11.h"
#include "dfs.h"
@ -132,8 +134,7 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
}
u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
int probe)
u16 hostapd_own_capab_info(struct hostapd_data *hapd)
{
int capab = WLAN_CAPABILITY_ESS;
int privacy;
@ -166,20 +167,6 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
privacy = 1;
#endif /* CONFIG_HS20 */
if (sta) {
int policy, def_klen;
if (probe && sta->ssid_probe) {
policy = sta->ssid_probe->security_policy;
def_klen = sta->ssid_probe->wep.default_len;
} else {
policy = sta->ssid->security_policy;
def_klen = sta->ssid->wep.default_len;
}
privacy = policy != SECURITY_PLAINTEXT;
if (policy == SECURITY_IEEE_802_1X && def_klen == 0)
privacy = 0;
}
if (privacy)
capab |= WLAN_CAPABILITY_PRIVACY;
@ -206,6 +193,7 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
}
#ifndef CONFIG_NO_RC4
static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
u16 auth_transaction, const u8 *challenge,
int iswep)
@ -259,6 +247,7 @@ static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
return 0;
}
#endif /* CONFIG_NO_RC4 */
static void send_auth_reply(struct hostapd_data *hapd,
@ -328,7 +317,6 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
#ifdef CONFIG_SAE
#define dot11RSNASAERetransPeriod 40 /* msec */
#define dot11RSNASAESync 5 /* attempts */
@ -511,12 +499,14 @@ static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
switch (sta->sae->state) {
case SAE_COMMITTED:
ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
eloop_register_timeout(0,
hapd->dot11RSNASAERetransPeriod * 1000,
auth_sae_retransmit_timer, hapd, sta);
break;
case SAE_CONFIRMED:
ret = auth_sae_send_confirm(hapd, sta, hapd->own_addr);
eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
eloop_register_timeout(0,
hapd->dot11RSNASAERetransPeriod * 1000,
auth_sae_retransmit_timer, hapd, sta);
break;
default:
@ -542,7 +532,7 @@ static void sae_set_retransmit_timer(struct hostapd_data *hapd,
return;
eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
eloop_register_timeout(0, dot11RSNASAERetransPeriod * 1000,
eloop_register_timeout(0, hapd->dot11RSNASAERetransPeriod * 1000,
auth_sae_retransmit_timer, hapd, sta);
}
@ -624,7 +614,7 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
return WLAN_STATUS_SUCCESS;
sta->sae->sync++;
ret = auth_sae_send_commit(hapd, sta, bssid, 1);
ret = auth_sae_send_commit(hapd, sta, bssid, 0);
if (ret)
return ret;
@ -784,6 +774,12 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
((const u8 *) mgmt) + len -
mgmt->u.auth.variable, &token,
&token_len, hapd->conf->sae_groups);
if (resp == SAE_SILENTLY_DISCARD) {
wpa_printf(MSG_DEBUG,
"SAE: Drop commit message from " MACSTR " due to reflection attack",
MAC2STR(sta->addr));
return;
}
if (token && check_sae_token(hapd, sta->addr, token, token_len)
< 0) {
wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
@ -934,6 +930,16 @@ static void handle_auth(struct hostapd_data *hapd,
challenge ? " challenge" : "",
seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
#ifdef CONFIG_NO_RC4
if (auth_alg == WLAN_AUTH_SHARED_KEY) {
wpa_printf(MSG_INFO,
"Unsupported authentication algorithm (%d)",
auth_alg);
resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
goto fail;
}
#endif /* CONFIG_NO_RC4 */
if (hapd->tkip_countermeasures) {
resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
goto fail;
@ -972,6 +978,61 @@ static void handle_auth(struct hostapd_data *hapd,
goto fail;
}
if (hapd->conf->no_auth_if_seen_on) {
struct hostapd_data *other;
other = sta_track_seen_on(hapd->iface, mgmt->sa,
hapd->conf->no_auth_if_seen_on);
if (other) {
u8 *pos;
u32 info;
u8 op_class, channel, phytype;
wpa_printf(MSG_DEBUG, "%s: Reject authentication from "
MACSTR " since STA has been seen on %s",
hapd->conf->iface, MAC2STR(mgmt->sa),
hapd->conf->no_auth_if_seen_on);
resp = WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION;
pos = &resp_ies[0];
*pos++ = WLAN_EID_NEIGHBOR_REPORT;
*pos++ = 13;
os_memcpy(pos, other->own_addr, ETH_ALEN);
pos += ETH_ALEN;
info = 0; /* TODO: BSSID Information */
WPA_PUT_LE32(pos, info);
pos += 4;
if (other->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD)
phytype = 8; /* dmg */
else if (other->iconf->ieee80211ac)
phytype = 9; /* vht */
else if (other->iconf->ieee80211n)
phytype = 7; /* ht */
else if (other->iconf->hw_mode ==
HOSTAPD_MODE_IEEE80211A)
phytype = 4; /* ofdm */
else if (other->iconf->hw_mode ==
HOSTAPD_MODE_IEEE80211G)
phytype = 6; /* erp */
else
phytype = 5; /* hrdsss */
if (ieee80211_freq_to_channel_ext(
hostapd_hw_get_freq(other,
other->iconf->channel),
other->iconf->secondary_channel,
other->iconf->ieee80211ac,
&op_class, &channel) == NUM_HOSTAPD_MODES) {
op_class = 0;
channel = other->iconf->channel;
}
*pos++ = op_class;
*pos++ = channel;
*pos++ = phytype;
resp_ies_len = pos - &resp_ies[0];
goto fail;
}
}
res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
&session_timeout,
&acct_interim_interval, &vlan_id,
@ -1081,6 +1142,7 @@ static void handle_auth(struct hostapd_data *hapd,
sta->auth_alg = WLAN_AUTH_OPEN;
mlme_authenticate_indication(hapd, sta);
break;
#ifndef CONFIG_NO_RC4
case WLAN_AUTH_SHARED_KEY:
resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
fc & WLAN_FC_ISWEP);
@ -1094,6 +1156,7 @@ static void handle_auth(struct hostapd_data *hapd,
resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN;
}
break;
#endif /* CONFIG_NO_RC4 */
#ifdef CONFIG_IEEE80211R
case WLAN_AUTH_FT:
sta->auth_alg = WLAN_AUTH_FT;
@ -1297,8 +1360,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
if (resp != WLAN_STATUS_SUCCESS)
return resp;
#ifdef CONFIG_IEEE80211N
resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities,
elems.ht_capabilities_len);
resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
@ -1311,14 +1373,15 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
#endif /* CONFIG_IEEE80211N */
#ifdef CONFIG_IEEE80211AC
resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities,
elems.vht_capabilities_len);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
if (hapd->iconf->ieee80211ac) {
resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
if (resp != WLAN_STATUS_SUCCESS)
return resp;
}
if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
!(sta->flags & WLAN_STA_VHT)) {
@ -1546,6 +1609,14 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
sta->hs20_ie = NULL;
#endif /* CONFIG_HS20 */
#ifdef CONFIG_FST
wpabuf_free(sta->mb_ies);
if (hapd->iface->fst)
sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
else
sta->mb_ies = NULL;
#endif /* CONFIG_FST */
return WLAN_STATUS_SUCCESS;
}
@ -1594,7 +1665,7 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
send_len = IEEE80211_HDRLEN;
send_len += sizeof(reply->u.assoc_resp);
reply->u.assoc_resp.capab_info =
host_to_le16(hostapd_own_capab_info(hapd, sta, 0));
host_to_le16(hostapd_own_capab_info(hapd));
reply->u.assoc_resp.status_code = host_to_le16(status_code);
reply->u.assoc_resp.aid = host_to_le16(sta->aid | BIT(14) | BIT(15));
/* Supported rates */
@ -1634,6 +1705,14 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
if (sta->qos_map_enabled)
p = hostapd_eid_qos_map_set(hapd, p);
#ifdef CONFIG_FST
if (hapd->iface->fst_ies) {
os_memcpy(p, wpabuf_head(hapd->iface->fst_ies),
wpabuf_len(hapd->iface->fst_ies));
p += wpabuf_len(hapd->iface->fst_ies);
}
#endif /* CONFIG_FST */
#ifdef CONFIG_IEEE80211AC
if (hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT))
p = hostapd_eid_vendor_vht(hapd, p);
@ -2112,10 +2191,20 @@ static int handle_action(struct hostapd_data *hapd,
ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
return 1;
#endif /* CONFIG_WNM */
#ifdef CONFIG_FST
case WLAN_ACTION_FST:
if (hapd->iface->fst)
fst_rx_action(hapd->iface->fst, mgmt, len);
else
wpa_printf(MSG_DEBUG,
"FST: Ignore FST Action frame - no FST attached");
return 1;
#endif /* CONFIG_FST */
case WLAN_ACTION_PUBLIC:
case WLAN_ACTION_PROTECTED_DUAL:
#ifdef CONFIG_IEEE80211N
if (mgmt->u.action.u.public_action.action ==
if (len >= IEEE80211_HDRLEN + 2 &&
mgmt->u.action.u.public_action.action ==
WLAN_PA_20_40_BSS_COEX) {
wpa_printf(MSG_DEBUG,
"HT20/40 coex mgmt frame received from STA "
@ -2248,6 +2337,9 @@ int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
return 0;
}
if (hapd->iconf->track_sta_max_num)
sta_track_add(hapd->iface, mgmt->sa);
switch (stype) {
case WLAN_FC_STYPE_AUTH:
wpa_printf(MSG_DEBUG, "mgmt::auth");
@ -2335,7 +2427,7 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
char *ifname_wds)
{
int i;
struct hostapd_ssid *ssid = sta->ssid;
struct hostapd_ssid *ssid = &hapd->conf->ssid;
if (hapd->conf->ieee802_1x || hapd->conf->wpa)
return;
@ -2473,11 +2565,11 @@ static void handle_assoc_cb(struct hostapd_data *hapd,
* so bind it to the selected VLAN interface now, since the
* interface selection is not going to change anymore.
*/
if (ap_sta_bind_vlan(hapd, sta, 0) < 0)
if (ap_sta_bind_vlan(hapd, sta) < 0)
return;
} else if (sta->vlan_id) {
/* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
if (ap_sta_bind_vlan(hapd, sta, 0) < 0)
if (ap_sta_bind_vlan(hapd, sta) < 0)
return;
}

View file

@ -14,6 +14,7 @@ struct hostapd_data;
struct sta_info;
struct hostapd_frame_info;
struct ieee80211_ht_capabilities;
struct ieee80211_vht_capabilities;
struct ieee80211_mgmt;
int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
@ -40,8 +41,7 @@ static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd,
return 0;
}
#endif /* NEED_AP_MLME */
u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta,
int probe);
u16 hostapd_own_capab_info(struct hostapd_data *hapd);
void ap_ht2040_timeout(void *eloop_data, void *user_data);
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid);
u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid);
@ -62,7 +62,7 @@ void hostapd_get_vht_capab(struct hostapd_data *hapd,
struct ieee80211_vht_capabilities *vht_cap,
struct ieee80211_vht_capabilities *neg_vht_cap);
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ht_capab, size_t ht_capab_len);
const u8 *ht_capab);
u16 copy_sta_vendor_vht(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ie, size_t len);
@ -70,7 +70,7 @@ void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta);
void ht40_intolerant_add(struct hostapd_iface *iface, struct sta_info *sta);
void ht40_intolerant_remove(struct hostapd_iface *iface, struct sta_info *sta);
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_capab, size_t vht_capab_len);
const u8 *vht_capab);
u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_opmode);
void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,

View file

@ -399,19 +399,15 @@ static void hostapd_acl_expire_queries(struct hostapd_data *hapd,
/**
* hostapd_acl_expire - ACL cache expiration callback
* @eloop_ctx: struct hostapd_data *
* @timeout_ctx: Not used
* @hapd: struct hostapd_data *
*/
static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx)
void hostapd_acl_expire(struct hostapd_data *hapd)
{
struct hostapd_data *hapd = eloop_ctx;
struct os_reltime now;
os_get_reltime(&now);
hostapd_acl_expire_cache(hapd, &now);
hostapd_acl_expire_queries(hapd, &now);
eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
}
@ -561,6 +557,19 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req,
if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED &&
!cache->psk)
cache->accepted = HOSTAPD_ACL_REJECT;
if (cache->vlan_id &&
!hostapd_vlan_id_valid(hapd->conf->vlan, cache->vlan_id)) {
hostapd_logger(hapd, query->addr,
HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
"Invalid VLAN ID %d received from RADIUS server",
cache->vlan_id);
cache->vlan_id = 0;
}
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED &&
!cache->vlan_id)
cache->accepted = HOSTAPD_ACL_REJECT;
} else
cache->accepted = HOSTAPD_ACL_REJECT;
cache->next = hapd->acl_cache;
@ -602,8 +611,6 @@ int hostapd_acl_init(struct hostapd_data *hapd)
if (radius_client_register(hapd->radius, RADIUS_AUTH,
hostapd_acl_recv_radius, hapd))
return -1;
eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL);
#endif /* CONFIG_NO_RADIUS */
return 0;
@ -619,8 +626,6 @@ void hostapd_acl_deinit(struct hostapd_data *hapd)
struct hostapd_acl_query_data *query, *prev;
#ifndef CONFIG_NO_RADIUS
eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL);
hostapd_acl_cache_free(hapd->acl_cache);
#endif /* CONFIG_NO_RADIUS */

View file

@ -24,5 +24,6 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
int hostapd_acl_init(struct hostapd_data *hapd);
void hostapd_acl_deinit(struct hostapd_data *hapd);
void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk);
void hostapd_acl_expire(struct hostapd_data *hapd);
#endif /* IEEE802_11_AUTH_H */

View file

@ -209,7 +209,7 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
struct hostapd_iface *iface = hapd->iface;
struct ieee80211_2040_bss_coex_ie *bc_ie;
struct ieee80211_2040_intol_chan_report *ic_report;
int is_ht_allowed = 1;
int is_ht40_allowed = 1;
int i;
const u8 *start = (const u8 *) mgmt;
const u8 *data = start + IEEE80211_HDRLEN + 2;
@ -242,7 +242,7 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"20 MHz BSS width request bit is set in BSS coexistence information field");
is_ht_allowed = 0;
is_ht40_allowed = 0;
}
if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_40MHZ_INTOL) {
@ -250,7 +250,7 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"40 MHz intolerant bit is set in BSS coexistence information field");
is_ht_allowed = 0;
is_ht40_allowed = 0;
}
if (start + len - data >= 3 &&
@ -276,13 +276,13 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
HOSTAPD_LEVEL_DEBUG,
"20_40_INTOLERANT channel %d reported",
chan);
is_ht_allowed = 0;
is_ht40_allowed = 0;
}
}
wpa_printf(MSG_DEBUG, "is_ht_allowed=%d num_sta_ht40_intolerant=%d",
is_ht_allowed, iface->num_sta_ht40_intolerant);
wpa_printf(MSG_DEBUG, "is_ht40_allowed=%d num_sta_ht40_intolerant=%d",
is_ht40_allowed, iface->num_sta_ht40_intolerant);
if (!is_ht_allowed &&
if (!is_ht40_allowed &&
(iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) {
if (iface->conf->secondary_channel) {
hostapd_logger(hapd, mgmt->sa,
@ -310,12 +310,15 @@ void hostapd_2040_coex_action(struct hostapd_data *hapd,
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ht_capab, size_t ht_capab_len)
const u8 *ht_capab)
{
/* Disable HT caps for STAs associated to no-HT BSSes. */
/*
* Disable HT caps for STAs associated to no-HT BSSes, or for stations
* that did not specify a valid WMM IE in the (Re)Association Request
* frame.
*/
if (!ht_capab ||
ht_capab_len < sizeof(struct ieee80211_ht_capabilities) ||
hapd->conf->disable_11n) {
!(sta->flags & WLAN_STA_WMM) || hapd->conf->disable_11n) {
sta->flags &= ~WLAN_STA_HT;
os_free(sta->ht_capabilities);
sta->ht_capabilities = NULL;

View file

@ -132,11 +132,10 @@ static int check_valid_vht_mcs(struct hostapd_hw_modes *mode,
u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *vht_capab, size_t vht_capab_len)
const u8 *vht_capab)
{
/* Disable VHT caps for STAs associated to no-VHT BSSes. */
if (!vht_capab ||
vht_capab_len < sizeof(struct ieee80211_vht_capabilities) ||
hapd->conf->disable_11ac ||
!check_valid_vht_mcs(hapd->iface->current_mode, vht_capab)) {
sta->flags &= ~WLAN_STA_VHT;

View file

@ -125,6 +125,9 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
}
#ifndef CONFIG_FIPS
#ifndef CONFIG_NO_RC4
static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
struct sta_info *sta,
int idx, int broadcast,
@ -204,7 +207,7 @@ static void ieee802_1x_tx_key_one(struct hostapd_data *hapd,
}
void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
static void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
{
struct eapol_authenticator *eapol = hapd->eapol_auth;
struct eapol_state_machine *sm = sta->eapol_sm;
@ -259,6 +262,9 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta)
}
}
#endif /* CONFIG_NO_RC4 */
#endif /* CONFIG_FIPS */
const char *radius_mode_txt(struct hostapd_data *hapd)
{
@ -346,7 +352,8 @@ static int add_common_radius_sta_attr_rsn(struct hostapd_data *hapd,
return -1;
}
suite = wpa_cipher_to_suite((hapd->conf->wpa & 0x2) ?
suite = wpa_cipher_to_suite(((hapd->conf->wpa & 0x2) ||
hapd->conf->osen) ?
WPA_PROTO_RSN : WPA_PROTO_WPA,
hapd->conf->wpa_group);
if (!hostapd_config_get_radius_attr(req_attr,
@ -453,7 +460,7 @@ static int add_common_radius_sta_attr(struct hostapd_data *hapd,
}
#endif /* CONFIG_IEEE80211R */
if (hapd->conf->wpa && sta->wpa_sm &&
if ((hapd->conf->wpa || hapd->conf->osen) && sta->wpa_sm &&
add_common_radius_sta_attr_rsn(hapd, req_attr, sta, msg) < 0)
return -1;
@ -599,7 +606,7 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
goto fail;
}
if (eap && !radius_msg_add_eap(msg, eap, len)) {
if (!radius_msg_add_eap(msg, eap, len)) {
wpa_printf(MSG_INFO, "Could not add EAP-Message");
goto fail;
}
@ -1108,8 +1115,6 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
pmksa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
if (pmksa) {
int old_vlanid;
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X,
HOSTAPD_LEVEL_DEBUG,
"PMK from PMKSA cache - skip IEEE 802.1X/EAP");
@ -1123,11 +1128,8 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
sta->eapol_sm->authFail = FALSE;
if (sta->eapol_sm->eap)
eap_sm_notify_cached(sta->eapol_sm->eap);
old_vlanid = sta->vlan_id;
pmksa_cache_to_eapol_data(pmksa, sta->eapol_sm);
if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
sta->vlan_id = 0;
ap_sta_bind_vlan(hapd, sta, old_vlanid);
ap_sta_bind_vlan(hapd, sta);
} else {
if (reassoc) {
/*
@ -1290,7 +1292,7 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
struct sta_info *sta,
struct radius_msg *msg)
{
u8 *class;
u8 *attr_class;
size_t class_len;
struct eapol_state_machine *sm = sta->eapol_sm;
int count, i;
@ -1312,12 +1314,12 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
nclass_count = 0;
class = NULL;
attr_class = NULL;
for (i = 0; i < count; i++) {
do {
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CLASS,
&class, &class_len,
class) < 0) {
&attr_class, &class_len,
attr_class) < 0) {
i = count;
break;
}
@ -1327,7 +1329,7 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd,
if (nclass[nclass_count].data == NULL)
break;
os_memcpy(nclass[nclass_count].data, class, class_len);
os_memcpy(nclass[nclass_count].data, attr_class, class_len);
nclass[nclass_count].len = class_len;
nclass_count++;
}
@ -1590,7 +1592,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
struct hostapd_data *hapd = data;
struct sta_info *sta;
u32 session_timeout = 0, termination_action, acct_interim_interval;
int session_timeout_set, old_vlanid = 0;
int session_timeout_set, vlan_id = 0;
struct eapol_state_machine *sm;
int override_eapReq = 0;
struct radius_hdr *hdr = radius_msg_get_hdr(msg);
@ -1657,20 +1659,27 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
switch (hdr->code) {
case RADIUS_CODE_ACCESS_ACCEPT:
if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
sta->vlan_id = 0;
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
vlan_id = 0;
#ifndef CONFIG_NO_VLAN
else {
old_vlanid = sta->vlan_id;
sta->vlan_id = radius_msg_get_vlanid(msg);
}
if (sta->vlan_id > 0 &&
hostapd_vlan_id_valid(hapd->conf->vlan, sta->vlan_id)) {
else
vlan_id = radius_msg_get_vlanid(msg);
if (vlan_id > 0 &&
hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
"VLAN ID %d", sta->vlan_id);
} else if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_REQUIRED) {
"VLAN ID %d", vlan_id);
} else if (vlan_id > 0) {
sta->eapol_sm->authFail = TRUE;
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_RADIUS,
HOSTAPD_LEVEL_INFO,
"Invalid VLAN ID %d received from RADIUS server",
vlan_id);
break;
} else if (hapd->conf->ssid.dynamic_vlan ==
DYNAMIC_VLAN_REQUIRED) {
sta->eapol_sm->authFail = TRUE;
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE8021X,
@ -1681,7 +1690,9 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
}
#endif /* CONFIG_NO_VLAN */
if (ap_sta_bind_vlan(hapd, sta, old_vlanid) < 0)
sta->vlan_id = vlan_id;
if ((sta->flags & WLAN_STA_ASSOC) &&
ap_sta_bind_vlan(hapd, sta) < 0)
break;
sta->session_timeout_set = !!session_timeout_set;
@ -1926,10 +1937,11 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
struct hostapd_data *hapd = ctx;
const struct hostapd_eap_user *eap_user;
int i;
int rv = -1;
eap_user = hostapd_get_eap_user(hapd, identity, identity_len, phase2);
if (eap_user == NULL)
return -1;
goto out;
os_memset(user, 0, sizeof(*user));
user->phase2 = phase2;
@ -1941,7 +1953,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
if (eap_user->password) {
user->password = os_malloc(eap_user->password_len);
if (user->password == NULL)
return -1;
goto out;
os_memcpy(user->password, eap_user->password,
eap_user->password_len);
user->password_len = eap_user->password_len;
@ -1951,8 +1963,13 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity,
user->macacl = eap_user->macacl;
user->ttls_auth = eap_user->ttls_auth;
user->remediation = eap_user->remediation;
rv = 0;
return 0;
out:
if (rv)
wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__);
return rv;
}
@ -2012,9 +2029,13 @@ static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx)
static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx)
{
#ifndef CONFIG_FIPS
#ifndef CONFIG_NO_RC4
struct hostapd_data *hapd = ctx;
struct sta_info *sta = sta_ctx;
ieee802_1x_tx_key(hapd, sta);
#endif /* CONFIG_NO_RC4 */
#endif /* CONFIG_FIPS */
}
@ -2085,6 +2106,7 @@ int ieee802_1x_init(struct hostapd_data *hapd)
conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start;
conf.erp_domain = hapd->conf->erp_domain;
conf.erp = hapd->conf->eap_server_erp;
conf.tls_session_lifetime = hapd->conf->tls_session_lifetime;
conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key;
conf.eap_fast_a_id = hapd->conf->eap_fast_a_id;
conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len;
@ -2332,9 +2354,9 @@ void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth)
}
static const char * bool_txt(Boolean bool)
static const char * bool_txt(Boolean val)
{
return bool ? "TRUE" : "FALSE";
return val ? "TRUE" : "FALSE";
}

View file

@ -23,7 +23,6 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf,
void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta);
void ieee802_1x_free_station(struct sta_info *sta);
void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta);
void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta);
void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd,
struct sta_info *sta, int authorized);

View file

@ -81,12 +81,24 @@ static int sta_has_ip6addr(struct sta_info *sta, struct in6_addr *addr)
}
static void ucast_to_stas(struct hostapd_data *hapd, const u8 *buf, size_t len)
{
struct sta_info *sta;
for (sta = hapd->sta_list; sta; sta = sta->next) {
if (!(sta->flags & WLAN_STA_AUTHORIZED))
continue;
x_snoop_mcast_to_ucast_convert_send(hapd, sta, (u8 *) buf, len);
}
}
static void handle_ndisc(void *ctx, const u8 *src_addr, const u8 *buf,
size_t len)
{
struct hostapd_data *hapd = ctx;
struct icmpv6_ndmsg *msg;
struct in6_addr *saddr;
struct in6_addr saddr;
struct sta_info *sta;
int res;
char addrtxt[INET6_ADDRSTRLEN + 1];
@ -101,25 +113,30 @@ static void handle_ndisc(void *ctx, const u8 *src_addr, const u8 *buf,
if (msg->opt_type != SOURCE_LL_ADDR)
return;
saddr = &msg->ipv6h.ip6_src;
if (!(saddr->s6_addr32[0] == 0 && saddr->s6_addr32[1] == 0 &&
saddr->s6_addr32[2] == 0 && saddr->s6_addr32[3] == 0)) {
/*
* IPv6 header may not be 32-bit aligned in the buffer, so use
* a local copy to avoid unaligned reads.
*/
os_memcpy(&saddr, &msg->ipv6h.ip6_src, sizeof(saddr));
if (!(saddr.s6_addr32[0] == 0 && saddr.s6_addr32[1] == 0 &&
saddr.s6_addr32[2] == 0 && saddr.s6_addr32[3] == 0)) {
if (len < ETH_HLEN + sizeof(*msg) + ETH_ALEN)
return;
sta = ap_get_sta(hapd, msg->opt_lladdr);
if (!sta)
return;
if (sta_has_ip6addr(sta, saddr))
if (sta_has_ip6addr(sta, &saddr))
return;
if (inet_ntop(AF_INET6, saddr, addrtxt, sizeof(addrtxt))
== NULL)
if (inet_ntop(AF_INET6, &saddr, addrtxt,
sizeof(addrtxt)) == NULL)
addrtxt[0] = '\0';
wpa_printf(MSG_DEBUG, "ndisc_snoop: Learned new IPv6 address %s for "
MACSTR, addrtxt, MAC2STR(sta->addr));
hostapd_drv_br_delete_ip_neigh(hapd, 6, (u8 *) saddr);
res = hostapd_drv_br_add_ip_neigh(hapd, 6, (u8 *) saddr,
hostapd_drv_br_delete_ip_neigh(hapd, 6, (u8 *) &saddr);
res = hostapd_drv_br_add_ip_neigh(hapd, 6,
(u8 *) &saddr,
128, sta->addr);
if (res) {
wpa_printf(MSG_ERROR,
@ -128,21 +145,17 @@ static void handle_ndisc(void *ctx, const u8 *src_addr, const u8 *buf,
return;
}
if (sta_ip6addr_add(sta, saddr))
if (sta_ip6addr_add(sta, &saddr))
return;
}
break;
case ROUTER_ADVERTISEMENT:
if (!hapd->conf->disable_dgaf)
return;
/* fall through */
if (hapd->conf->disable_dgaf)
ucast_to_stas(hapd, buf, len);
break;
case NEIGHBOR_ADVERTISEMENT:
for (sta = hapd->sta_list; sta; sta = sta->next) {
if (!(sta->flags & WLAN_STA_AUTHORIZED))
continue;
x_snoop_mcast_to_ucast_convert_send(hapd, sta,
(u8 *) buf, len);
}
if (hapd->conf->na_mcast_to_ucast)
ucast_to_stas(hapd, buf, len);
break;
default:
break;

View file

@ -16,6 +16,7 @@
#include "radius/radius.h"
#include "radius/radius_client.h"
#include "p2p/p2p.h"
#include "fst/fst.h"
#include "hostapd.h"
#include "accounting.h"
#include "ieee802_1x.h"
@ -171,6 +172,19 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
!(sta->flags & WLAN_STA_PREAUTH))
hostapd_drv_sta_remove(hapd, sta->addr);
#ifndef CONFIG_NO_VLAN
if (sta->vlan_id_bound) {
/*
* Need to remove the STA entry before potentially removing the
* VLAN.
*/
if (hapd->iface->driver_ap_teardown &&
!(sta->flags & WLAN_STA_PREAUTH))
hostapd_drv_sta_remove(hapd, sta->addr);
vlan_remove_dynamic(hapd, sta->vlan_id_bound);
}
#endif /* CONFIG_NO_VLAN */
ap_sta_hash_del(hapd, sta);
ap_sta_list_del(hapd, sta);
@ -283,6 +297,9 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
wpabuf_free(sta->wps_ie);
wpabuf_free(sta->p2p_ie);
wpabuf_free(sta->hs20_ie);
#ifdef CONFIG_FST
wpabuf_free(sta->mb_ies);
#endif /* CONFIG_FST */
os_free(sta->ht_capabilities);
os_free(sta->vht_capabilities);
@ -619,7 +636,6 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
hapd->sta_list = sta;
hapd->num_sta++;
ap_sta_hash_add(hapd, sta);
sta->ssid = &hapd->conf->ssid;
ap_sta_remove_in_other_bss(hapd, sta);
sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
dl_list_init(&sta->ip6addr);
@ -768,26 +784,19 @@ int ap_sta_wps_cancel(struct hostapd_data *hapd,
#endif /* CONFIG_WPS */
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
int old_vlanid)
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta)
{
#ifndef CONFIG_NO_VLAN
const char *iface;
struct hostapd_vlan *vlan = NULL;
int ret;
/*
* Do not proceed furthur if the vlan id remains same. We do not want
* duplicate dynamic vlan entries.
*/
if (sta->vlan_id == old_vlanid)
return 0;
int old_vlanid = sta->vlan_id_bound;
iface = hapd->conf->iface;
if (sta->ssid->vlan[0])
iface = sta->ssid->vlan;
if (hapd->conf->ssid.vlan[0])
iface = hapd->conf->ssid.vlan;
if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED)
if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
sta->vlan_id = 0;
else if (sta->vlan_id > 0) {
struct hostapd_vlan *wildcard_vlan = NULL;
@ -805,6 +814,14 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
iface = vlan->ifname;
}
/*
* Do not increment ref counters if the VLAN ID remains same, but do
* not skip hostapd_drv_set_sta_vlan() as hostapd_drv_sta_remove() might
* have been called before.
*/
if (sta->vlan_id == old_vlanid)
goto skip_counting;
if (sta->vlan_id > 0 && vlan == NULL) {
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not find VLAN for "
@ -825,7 +842,7 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
}
iface = vlan->ifname;
if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
if (vlan_setup_encryption_dyn(hapd, iface) != 0) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not "
@ -838,7 +855,7 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN "
"interface '%s'", iface);
} else if (vlan && vlan->vlan_id == sta->vlan_id) {
if (sta->vlan_id > 0) {
if (vlan->dynamic_vlan > 0) {
vlan->dynamic_vlan++;
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
@ -852,7 +869,7 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
* configuration for the case where hostapd did not yet know
* which keys are to be used when the interface was added.
*/
if (vlan_setup_encryption_dyn(hapd, sta->ssid, iface) != 0) {
if (vlan_setup_encryption_dyn(hapd, iface) != 0) {
hostapd_logger(hapd, sta->addr,
HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "could not "
@ -862,6 +879,10 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
}
}
/* ref counters have been increased, so mark the station */
sta->vlan_id_bound = sta->vlan_id;
skip_counting:
hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG, "binding station to interface "
"'%s'", iface);
@ -876,10 +897,10 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
"entry to vlan_id=%d", sta->vlan_id);
}
done:
/* During 1x reauth, if the vlan id changes, then remove the old id. */
if (old_vlanid > 0)
if (old_vlanid > 0 && old_vlanid != sta->vlan_id)
vlan_remove_dynamic(hapd, old_vlanid);
done:
return ret;
#else /* CONFIG_NO_VLAN */
@ -1043,6 +1064,16 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
AP_STA_DISCONNECTED "%s", buf);
}
#ifdef CONFIG_FST
if (hapd->iface->fst) {
if (authorized)
fst_notify_peer_connected(hapd->iface->fst, sta->addr);
else
fst_notify_peer_disconnected(hapd->iface->fst,
sta->addr);
}
#endif /* CONFIG_FST */
}

View file

@ -117,10 +117,8 @@ struct sta_info {
struct wpa_state_machine *wpa_sm;
struct rsn_preauth_interface *preauth_iface;
struct hostapd_ssid *ssid; /* SSID selection based on (Re)AssocReq */
struct hostapd_ssid *ssid_probe; /* SSID selection based on ProbeReq */
int vlan_id;
int vlan_id; /* 0: none, >0: VID */
int vlan_id_bound; /* updated by ap_sta_bind_vlan() */
/* PSKs from RADIUS authentication server */
struct hostapd_sta_wpa_psk_short *psk;
@ -155,6 +153,9 @@ struct sta_info {
struct wpabuf *hs20_deauth_req;
char *hs20_session_info_url;
int hs20_disassoc_timer;
#ifdef CONFIG_FST
struct wpabuf *mb_ies; /* MB IEs from (Re)Association Request */
#endif /* CONFIG_FST */
struct os_reltime connected_time;
@ -218,8 +219,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta,
int ap_sta_wps_cancel(struct hostapd_data *hapd,
struct sta_info *sta, void *ctx);
#endif /* CONFIG_WPS */
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
int old_vlanid);
int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);

View file

@ -10,6 +10,7 @@
#include "common.h"
#include "common/ieee802_11_defs.h"
#include "fst/fst.h"
#include "sta_info.h"
#include "hostapd.h"
@ -55,10 +56,20 @@ static int prune_associations(struct hostapd_iface *iface, void *ctx)
ohapd = iface->bss[j];
if (ohapd == data->hapd)
continue;
#ifdef CONFIG_FST
/* Don't prune STAs belong to same FST */
if (ohapd->iface->fst &&
data->hapd->iface->fst &&
fst_are_ifaces_aggregated(ohapd->iface->fst,
data->hapd->iface->fst))
continue;
#endif /* CONFIG_FST */
osta = ap_get_sta(ohapd, data->addr);
if (!osta)
continue;
wpa_printf(MSG_INFO, "%s: Prune association for " MACSTR,
ohapd->conf->iface, MAC2STR(osta->addr));
ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED);
}

View file

@ -9,6 +9,13 @@
*/
#include "utils/includes.h"
#ifdef CONFIG_FULL_DYNAMIC_VLAN
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/sockios.h>
#include <linux/if_vlan.h>
#include <linux/if_bridge.h>
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
#include "utils/common.h"
#include "hostapd.h"
@ -20,12 +27,6 @@
#ifdef CONFIG_FULL_DYNAMIC_VLAN
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/sockios.h>
#include <linux/if_vlan.h>
#include <linux/if_bridge.h>
#include "drivers/priv_netlink.h"
#include "utils/eloop.h"
@ -34,6 +35,90 @@ struct full_dynamic_vlan {
int s; /* socket on which to listen for new/removed interfaces. */
};
#define DVLAN_CLEAN_BR 0x1
#define DVLAN_CLEAN_VLAN 0x2
#define DVLAN_CLEAN_VLAN_PORT 0x4
struct dynamic_iface {
char ifname[IFNAMSIZ + 1];
int usage;
int clean;
struct dynamic_iface *next;
};
/* Increment ref counter for ifname and add clean flag.
* If not in list, add it only if some flags are given.
*/
static void dyn_iface_get(struct hostapd_data *hapd, const char *ifname,
int clean)
{
struct dynamic_iface *next, **dynamic_ifaces;
struct hapd_interfaces *interfaces;
interfaces = hapd->iface->interfaces;
dynamic_ifaces = &interfaces->vlan_priv;
for (next = *dynamic_ifaces; next; next = next->next) {
if (os_strcmp(ifname, next->ifname) == 0)
break;
}
if (next) {
next->usage++;
next->clean |= clean;
return;
}
if (!clean)
return;
next = os_zalloc(sizeof(*next));
if (!next)
return;
os_strlcpy(next->ifname, ifname, sizeof(next->ifname));
next->usage = 1;
next->clean = clean;
next->next = *dynamic_ifaces;
*dynamic_ifaces = next;
}
/* Decrement reference counter for given ifname.
* Return clean flag iff reference counter was decreased to zero, else zero
*/
static int dyn_iface_put(struct hostapd_data *hapd, const char *ifname)
{
struct dynamic_iface *next, *prev = NULL, **dynamic_ifaces;
struct hapd_interfaces *interfaces;
int clean;
interfaces = hapd->iface->interfaces;
dynamic_ifaces = &interfaces->vlan_priv;
for (next = *dynamic_ifaces; next; next = next->next) {
if (os_strcmp(ifname, next->ifname) == 0)
break;
prev = next;
}
if (!next)
return 0;
next->usage--;
if (next->usage)
return 0;
if (prev)
prev->next = next->next;
else
*dynamic_ifaces = next->next;
clean = next->clean;
os_free(next);
return clean;
}
static int ifconfig_helper(const char *if_name, int up)
{
@ -481,11 +566,13 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
struct hostapd_vlan *vlan = hapd->conf->vlan;
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
int vlan_naming = hapd->conf->ssid.vlan_naming;
int clean;
wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
while (vlan) {
if (os_strcmp(ifname, vlan->ifname) == 0) {
if (os_strcmp(ifname, vlan->ifname) == 0 && !vlan->configured) {
vlan->configured = 1;
if (hapd->conf->vlan_bridge[0]) {
os_snprintf(br_name, sizeof(br_name), "%s%d",
@ -500,8 +587,8 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
"brvlan%d", vlan->vlan_id);
}
if (!br_addbr(br_name))
vlan->clean |= DVLAN_CLEAN_BR;
dyn_iface_get(hapd, br_name,
br_addbr(br_name) ? 0 : DVLAN_CLEAN_BR);
ifconfig_up(br_name);
@ -517,13 +604,16 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
sizeof(vlan_ifname),
"vlan%d", vlan->vlan_id);
clean = 0;
ifconfig_up(tagged_interface);
if (!vlan_add(tagged_interface, vlan->vlan_id,
vlan_ifname))
vlan->clean |= DVLAN_CLEAN_VLAN;
clean |= DVLAN_CLEAN_VLAN;
if (!br_addif(br_name, vlan_ifname))
vlan->clean |= DVLAN_CLEAN_VLAN_PORT;
clean |= DVLAN_CLEAN_VLAN_PORT;
dyn_iface_get(hapd, vlan_ifname, clean);
ifconfig_up(vlan_ifname);
}
@ -547,13 +637,15 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
int vlan_naming = hapd->conf->ssid.vlan_naming;
int clean;
wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
first = prev = vlan;
while (vlan) {
if (os_strcmp(ifname, vlan->ifname) == 0) {
if (os_strcmp(ifname, vlan->ifname) == 0 &&
vlan->configured) {
if (hapd->conf->vlan_bridge[0]) {
os_snprintf(br_name, sizeof(br_name), "%s%d",
hapd->conf->vlan_bridge,
@ -581,20 +673,27 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
os_snprintf(vlan_ifname,
sizeof(vlan_ifname),
"vlan%d", vlan->vlan_id);
if (vlan->clean & DVLAN_CLEAN_VLAN_PORT)
br_delif(br_name, vlan_ifname);
ifconfig_down(vlan_ifname);
if (vlan->clean & DVLAN_CLEAN_VLAN)
clean = dyn_iface_put(hapd, vlan_ifname);
if (clean & DVLAN_CLEAN_VLAN_PORT)
br_delif(br_name, vlan_ifname);
if (clean & DVLAN_CLEAN_VLAN) {
ifconfig_down(vlan_ifname);
vlan_rem(vlan_ifname);
}
}
if ((vlan->clean & DVLAN_CLEAN_BR) &&
clean = dyn_iface_put(hapd, br_name);
if ((clean & DVLAN_CLEAN_BR) &&
br_getnumports(br_name) == 0) {
ifconfig_down(br_name);
br_delbr(br_name);
}
}
if (os_strcmp(ifname, vlan->ifname) == 0) {
if (vlan == first) {
hapd->conf->vlan = vlan->next;
} else {
@ -651,6 +750,11 @@ vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
if (!ifname[0])
return;
if (del && if_nametoindex(ifname)) {
/* interface still exists, race condition ->
* iface has just been recreated */
return;
}
wpa_printf(MSG_DEBUG,
"VLAN: RTM_%sLINK: ifi_index=%d ifname=%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
@ -778,8 +882,7 @@ static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
struct hostapd_ssid *mssid, const char *dyn_vlan)
int vlan_setup_encryption_dyn(struct hostapd_data *hapd, const char *dyn_vlan)
{
int i;
@ -789,10 +892,11 @@ int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
/* Static WEP keys are set here; IEEE 802.1X and WPA uses their own
* functions for setting up dynamic broadcast keys. */
for (i = 0; i < 4; i++) {
if (mssid->wep.key[i] &&
if (hapd->conf->ssid.wep.key[i] &&
hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
i == mssid->wep.idx, NULL, 0,
mssid->wep.key[i], mssid->wep.len[i]))
i == hapd->conf->ssid.wep.idx, NULL, 0,
hapd->conf->ssid.wep.key[i],
hapd->conf->ssid.wep.len[i]))
{
wpa_printf(MSG_ERROR, "VLAN: Could not set WEP "
"encryption for dynamic VLAN");
@ -953,7 +1057,8 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID)
return 1;
wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__, vlan_id);
wpa_printf(MSG_DEBUG, "VLAN: %s(ifname=%s vlan_id=%d)",
__func__, hapd->conf->iface, vlan_id);
vlan = hapd->conf->vlan;
while (vlan) {
@ -967,8 +1072,12 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
if (vlan == NULL)
return 1;
if (vlan->dynamic_vlan == 0)
if (vlan->dynamic_vlan == 0) {
hostapd_vlan_if_remove(hapd, vlan->ifname);
#ifdef CONFIG_FULL_DYNAMIC_VLAN
vlan_dellink(vlan->ifname, hapd);
#endif /* CONFIG_FULL_DYNAMIC_VLAN */
}
return 0;
}

View file

@ -18,7 +18,6 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
int vlan_id);
int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id);
int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
struct hostapd_ssid *mssid,
const char *dyn_vlan);
#else /* CONFIG_NO_VLAN */
static inline int vlan_init(struct hostapd_data *hapd)
@ -43,7 +42,6 @@ static inline int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
}
static inline int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
struct hostapd_ssid *mssid,
const char *dyn_vlan)
{
return -1;

View file

@ -31,7 +31,7 @@
*/
int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
{
int ret = -1;
int err, ret = -1;
struct nl_sock *handle = NULL;
struct nl_cache *cache = NULL;
struct rtnl_link *rlink = NULL;
@ -58,14 +58,18 @@ int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
goto vlan_add_error;
}
if (nl_connect(handle, NETLINK_ROUTE) < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
err = nl_connect(handle, NETLINK_ROUTE);
if (err < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s",
nl_geterror(err));
goto vlan_add_error;
}
if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
err = rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache);
if (err < 0) {
cache = NULL;
wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache: %s",
nl_geterror(err));
goto vlan_add_error;
}
@ -92,23 +96,29 @@ int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
goto vlan_add_error;
}
if (rtnl_link_set_type(rlink, "vlan") < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to set link type");
err = rtnl_link_set_type(rlink, "vlan");
if (err < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to set link type: %s",
nl_geterror(err));
goto vlan_add_error;
}
rtnl_link_set_link(rlink, if_idx);
rtnl_link_set_name(rlink, vlan_if_name);
if (rtnl_link_vlan_set_id(rlink, vid) < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id");
err = rtnl_link_vlan_set_id(rlink, vid);
if (err < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id: %s",
nl_geterror(err));
goto vlan_add_error;
}
if (rtnl_link_add(handle, rlink, NLM_F_CREATE) < 0) {
err = rtnl_link_add(handle, rlink, NLM_F_CREATE);
if (err < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for "
"vlan %d on %s (%d)",
vlan_if_name, vid, if_name, if_idx);
"vlan %d on %s (%d): %s",
vlan_if_name, vid, if_name, if_idx,
nl_geterror(err));
goto vlan_add_error;
}
@ -127,7 +137,7 @@ int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
int vlan_rem(const char *if_name)
{
int ret = -1;
int err, ret = -1;
struct nl_sock *handle = NULL;
struct nl_cache *cache = NULL;
struct rtnl_link *rlink = NULL;
@ -140,14 +150,18 @@ int vlan_rem(const char *if_name)
goto vlan_rem_error;
}
if (nl_connect(handle, NETLINK_ROUTE) < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
err = nl_connect(handle, NETLINK_ROUTE);
if (err < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s",
nl_geterror(err));
goto vlan_rem_error;
}
if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
err = rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache);
if (err < 0) {
cache = NULL;
wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache: %s",
nl_geterror(err));
goto vlan_rem_error;
}
@ -158,9 +172,10 @@ int vlan_rem(const char *if_name)
goto vlan_rem_error;
}
if (rtnl_link_delete(handle, rlink) < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s",
if_name);
err = rtnl_link_delete(handle, rlink);
if (err < 0) {
wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s: %s",
if_name, nl_geterror(err));
goto vlan_rem_error;
}

View file

@ -274,6 +274,9 @@ void hostapd_wmm_action(struct hostapd_data *hapd,
return;
}
if (left < 0)
return; /* not a valid WMM Action frame */
/* extract the tspec info element */
if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,

View file

@ -45,6 +45,12 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
const u8 *pmk, struct wpa_ptk *ptk);
static void wpa_group_free(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static void wpa_group_get(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static void wpa_group_put(struct wpa_authenticator *wpa_auth,
struct wpa_group *group);
static const u32 dot11RSNAConfigGroupUpdateCount = 4;
static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
@ -67,6 +73,14 @@ static inline int wpa_auth_mic_failure_report(
}
static inline void wpa_auth_psk_failure_report(
struct wpa_authenticator *wpa_auth, const u8 *addr)
{
if (wpa_auth->cb.psk_failure_report)
wpa_auth->cb.psk_failure_report(wpa_auth->cb.ctx, addr);
}
static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth,
const u8 *addr, wpa_eapol_variable var,
int value)
@ -254,15 +268,22 @@ static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx)
{
struct wpa_authenticator *wpa_auth = eloop_ctx;
struct wpa_group *group;
struct wpa_group *group, *next;
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK");
for (group = wpa_auth->group; group; group = group->next) {
group = wpa_auth->group;
while (group) {
wpa_group_get(wpa_auth, group);
group->GTKReKey = TRUE;
do {
group->changed = FALSE;
wpa_group_sm_step(wpa_auth, group);
} while (group->changed);
next = group->next;
wpa_group_put(wpa_auth, group);
group = next;
}
if (wpa_auth->conf.wpa_group_rekey) {
@ -565,6 +586,7 @@ wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr,
sm->wpa_auth = wpa_auth;
sm->group = wpa_auth->group;
wpa_group_get(sm->wpa_auth, sm->group);
return sm;
}
@ -643,6 +665,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm)
#endif /* CONFIG_IEEE80211R */
os_free(sm->last_rx_eapol_key);
os_free(sm->wpa_ie);
wpa_group_put(sm->wpa_auth, sm->group);
os_free(sm);
}
@ -1517,6 +1540,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
else
WPA_PUT_BE16(key->key_data_length,
key_data_len);
#ifndef CONFIG_NO_RC4
} else if (sm->PTK.kek_len == 16) {
u8 ek[32];
os_memcpy(key->key_iv,
@ -1532,6 +1556,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth,
else
WPA_PUT_BE16(key->key_data_length,
key_data_len);
#endif /* CONFIG_NO_RC4 */
} else {
os_free(hdr);
os_free(buf);
@ -1646,7 +1671,7 @@ void wpa_remove_ptk(struct wpa_state_machine *sm)
}
int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
{
int remove_ptk = 1;
@ -1734,6 +1759,14 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event)
wpa_remove_ptk(sm);
}
if (sm->in_step_loop) {
/*
* wpa_sm_step() is already running - avoid recursive call to
* it by making the existing loop process the new update.
*/
sm->changed = TRUE;
return 0;
}
return wpa_sm_step(sm);
}
@ -1818,9 +1851,13 @@ static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth,
group->reject_4way_hs_for_entropy = FALSE;
}
wpa_group_init_gmk_and_counter(wpa_auth, group);
wpa_gtk_update(wpa_auth, group);
wpa_group_config_group_keys(wpa_auth, group);
if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 ||
wpa_gtk_update(wpa_auth, group) < 0 ||
wpa_group_config_group_keys(wpa_auth, group) < 0) {
wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed");
group->first_sta_seen = FALSE;
group->reject_4way_hs_for_entropy = TRUE;
}
}
@ -1985,7 +2022,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce,
SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
{
struct wpa_ptk PTK;
int ok = 0;
int ok = 0, psk_found = 0;
const u8 *pmk = NULL;
SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk);
@ -2001,6 +2038,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
sm->p2p_dev_addr, pmk);
if (pmk == NULL)
break;
psk_found = 1;
} else
pmk = sm->PMK;
@ -2020,6 +2058,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
if (!ok) {
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
"invalid MIC in msg 2/4 of 4-Way Handshake");
if (psk_found)
wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr);
return;
}
@ -2983,9 +3023,9 @@ void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth)
}
static const char * wpa_bool_txt(int bool)
static const char * wpa_bool_txt(int val)
{
return bool ? "TRUE" : "FALSE";
return val ? "TRUE" : "FALSE";
}
@ -3270,6 +3310,63 @@ void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
}
/*
* Remove and free the group from wpa_authenticator. This is triggered by a
* callback to make sure nobody is currently iterating the group list while it
* gets modified.
*/
static void wpa_group_free(struct wpa_authenticator *wpa_auth,
struct wpa_group *group)
{
struct wpa_group *prev = wpa_auth->group;
wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d",
group->vlan_id);
while (prev) {
if (prev->next == group) {
/* This never frees the special first group as needed */
prev->next = group->next;
os_free(group);
break;
}
prev = prev->next;
}
}
/* Increase the reference counter for group */
static void wpa_group_get(struct wpa_authenticator *wpa_auth,
struct wpa_group *group)
{
/* Skip the special first group */
if (wpa_auth->group == group)
return;
group->references++;
}
/* Decrease the reference counter and maybe free the group */
static void wpa_group_put(struct wpa_authenticator *wpa_auth,
struct wpa_group *group)
{
/* Skip the special first group */
if (wpa_auth->group == group)
return;
group->references--;
if (group->references)
return;
wpa_group_free(wpa_auth, group);
}
/*
* Add a group that has its references counter set to zero. Caller needs to
* call wpa_group_get() on the return value to mark the entry in use.
*/
static struct wpa_group *
wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id)
{
@ -3320,7 +3417,10 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id)
wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state "
"machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id);
wpa_group_get(sm->wpa_auth, group);
wpa_group_put(sm->wpa_auth, sm->group);
sm->group = group;
return 0;
}

View file

@ -1,6 +1,6 @@
/*
* hostapd - IEEE 802.11i-2004 / WPA Authenticator
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -12,6 +12,9 @@
#include "common/defs.h"
#include "common/eapol_common.h"
#include "common/wpa_common.h"
#include "common/ieee802_11_defs.h"
#define MAX_OWN_IE_OVERRIDE 256
#ifdef _MSC_VER
#pragma pack(push, 1)
@ -146,8 +149,7 @@ struct wpa_auth_config {
int group_mgmt_cipher;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
#define SSID_LEN 32
u8 ssid[SSID_LEN];
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN];
u8 r0_key_holder[FT_R0KH_ID_MAX_LEN];
@ -164,6 +166,8 @@ struct wpa_auth_config {
int ap_mlme;
#ifdef CONFIG_TESTING_OPTIONS
double corrupt_gtk_rekey_mic_probability;
u8 own_ie_override[MAX_OWN_IE_OVERRIDE];
size_t own_ie_override_len;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P
u8 ip_addr_go[4];
@ -189,6 +193,7 @@ struct wpa_auth_callbacks {
const char *txt);
void (*disconnect)(void *ctx, const u8 *addr, u16 reason);
int (*mic_failure_report)(void *ctx, const u8 *addr);
void (*psk_failure_report)(void *ctx, const u8 *addr);
void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var,
int value);
int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var);
@ -251,12 +256,12 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm);
void wpa_receive(struct wpa_authenticator *wpa_auth,
struct wpa_state_machine *sm,
u8 *data, size_t data_len);
typedef enum {
enum wpa_event {
WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
WPA_REAUTH_EAPOL, WPA_ASSOC_FT
} wpa_event;
};
void wpa_remove_ptk(struct wpa_state_machine *sm);
int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event);
int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event);
void wpa_auth_sm_notify(struct wpa_state_machine *sm);
void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth);
int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen);

View file

@ -534,10 +534,8 @@ static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
return pos;
}
#ifdef NEED_AP_MLME
if (parse.wmm_tspec && sm->wpa_auth->conf.ap_mlme) {
if (parse.wmm_tspec) {
struct wmm_tspec_element *tspec;
int res;
if (parse.wmm_tspec_len + 2 < (int) sizeof(*tspec)) {
wpa_printf(MSG_DEBUG, "FT: Too short WMM TSPEC IE "
@ -555,7 +553,13 @@ static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
}
tspec = (struct wmm_tspec_element *) pos;
os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec));
res = wmm_process_tspec(tspec);
}
#ifdef NEED_AP_MLME
if (parse.wmm_tspec && sm->wpa_auth->conf.ap_mlme) {
int res;
res = wmm_process_tspec((struct wmm_tspec_element *) pos);
wpa_printf(MSG_DEBUG, "FT: ADDTS processing result: %d", res);
if (res == WMM_ADDTS_STATUS_INVALID_PARAMETERS)
rdie->status_code =
@ -566,20 +570,17 @@ static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
else {
/* TSPEC accepted; include updated TSPEC in response */
rdie->descr_count = 1;
pos += sizeof(*tspec);
pos += sizeof(struct wmm_tspec_element);
}
return pos;
}
#endif /* NEED_AP_MLME */
if (parse.wmm_tspec && !sm->wpa_auth->conf.ap_mlme) {
struct wmm_tspec_element *tspec;
int res;
tspec = (struct wmm_tspec_element *) pos;
os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec));
res = wpa_ft_add_tspec(sm->wpa_auth, sm->addr, pos,
sizeof(*tspec));
sizeof(struct wmm_tspec_element));
if (res >= 0) {
if (res)
rdie->status_code = host_to_le16(res);
@ -587,7 +588,7 @@ static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
/* TSPEC accepted; include updated TSPEC in
* response */
rdie->descr_count = 1;
pos += sizeof(*tspec);
pos += sizeof(struct wmm_tspec_element);
}
return pos;
}

View file

@ -11,6 +11,7 @@
#include "utils/common.h"
#include "common/ieee802_11_defs.h"
#include "common/sae.h"
#include "common/wpa_ctrl.h"
#include "eapol_auth/eapol_auth_sm.h"
#include "eapol_auth/eapol_auth_sm_i.h"
#include "eap_server/eap.h"
@ -53,8 +54,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
wconf->ssid_len = conf->ssid.ssid_len;
if (wconf->ssid_len > SSID_LEN)
wconf->ssid_len = SSID_LEN;
if (wconf->ssid_len > SSID_MAX_LEN)
wconf->ssid_len = SSID_MAX_LEN;
os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len);
os_memcpy(wconf->mobility_domain, conf->mobility_domain,
MOBILITY_DOMAIN_ID_LEN);
@ -91,6 +92,13 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
#ifdef CONFIG_TESTING_OPTIONS
wconf->corrupt_gtk_rekey_mic_probability =
iconf->corrupt_gtk_rekey_mic_probability;
if (conf->own_ie_override &&
wpabuf_len(conf->own_ie_override) <= MAX_OWN_IE_OVERRIDE) {
wconf->own_ie_override_len = wpabuf_len(conf->own_ie_override);
os_memcpy(wconf->own_ie_override,
wpabuf_head(conf->own_ie_override),
wconf->own_ie_override_len);
}
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_P2P
os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4);
@ -144,6 +152,14 @@ static int hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
}
static void hostapd_wpa_auth_psk_failure_report(void *ctx, const u8 *addr)
{
struct hostapd_data *hapd = ctx;
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
MAC2STR(addr));
}
static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr,
wpa_eapol_variable var, int value)
{
@ -579,6 +595,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
cb.logger = hostapd_wpa_auth_logger;
cb.disconnect = hostapd_wpa_auth_disconnect;
cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report;
cb.psk_failure_report = hostapd_wpa_auth_psk_failure_report;
cb.set_eapol = hostapd_wpa_auth_set_eapol;
cb.get_eapol = hostapd_wpa_auth_get_eapol;
cb.get_psk = hostapd_wpa_auth_get_psk;
@ -620,7 +637,8 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
}
#ifdef CONFIG_IEEE80211R
if (!hostapd_drv_none(hapd)) {
if (!hostapd_drv_none(hapd) && hapd->conf->ft_over_ds &&
wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt)) {
hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ?
hapd->conf->bridge :
hapd->conf->iface, NULL, ETH_P_RRB,

View file

@ -169,6 +169,8 @@ struct wpa_group {
u8 IGTK[2][WPA_IGTK_MAX_LEN];
int GN_igtk, GM_igtk;
#endif /* CONFIG_IEEE80211W */
/* Number of references except those in struct wpa_group->next */
unsigned int references;
};

View file

@ -261,7 +261,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
#ifdef CONFIG_IEEE80211W
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION &&
conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) {
if (pos + 2 + 4 > buf + len)
return -1;
if (pmkid == NULL) {
@ -377,6 +378,23 @@ int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth)
u8 *pos, buf[128];
int res;
#ifdef CONFIG_TESTING_OPTIONS
if (wpa_auth->conf.own_ie_override_len) {
wpa_hexdump(MSG_DEBUG, "WPA: Forced own IE(s) for testing",
wpa_auth->conf.own_ie_override,
wpa_auth->conf.own_ie_override_len);
os_free(wpa_auth->wpa_ie);
wpa_auth->wpa_ie =
os_malloc(wpa_auth->conf.own_ie_override_len);
if (wpa_auth->wpa_ie == NULL)
return -1;
os_memcpy(wpa_auth->wpa_ie, wpa_auth->conf.own_ie_override,
wpa_auth->conf.own_ie_override_len);
wpa_auth->wpa_ie_len = wpa_auth->conf.own_ie_override_len;
return 0;
}
#endif /* CONFIG_TESTING_OPTIONS */
pos = buf;
if (wpa_auth->conf.wpa == WPA_PROTO_OSEN) {

View file

@ -324,7 +324,7 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd,
wpa_printf(MSG_DEBUG, "WPS: Updating in-memory configuration");
bss->wps_state = 2;
if (cred->ssid_len <= HOSTAPD_MAX_SSID_LEN) {
if (cred->ssid_len <= SSID_MAX_LEN) {
os_memcpy(bss->ssid.ssid, cred->ssid, cred->ssid_len);
bss->ssid.ssid_len = cred->ssid_len;
bss->ssid.ssid_set = 1;
@ -347,8 +347,12 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd,
bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
bss->wpa_pairwise = 0;
if (cred->encr_type & WPS_ENCR_AES)
bss->wpa_pairwise |= WPA_CIPHER_CCMP;
if (cred->encr_type & WPS_ENCR_AES) {
if (hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD)
bss->wpa_pairwise |= WPA_CIPHER_GCMP;
else
bss->wpa_pairwise |= WPA_CIPHER_CCMP;
}
if (cred->encr_type & WPS_ENCR_TKIP)
bss->wpa_pairwise |= WPA_CIPHER_TKIP;
bss->rsn_pairwise = bss->wpa_pairwise;
@ -448,6 +452,11 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
os_free(hapd->wps->network_key);
hapd->wps->network_key = NULL;
hapd->wps->network_key_len = 0;
} else if ((cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) &&
(cred->key_len < 8 || cred->key_len > 2 * PMK_LEN)) {
wpa_printf(MSG_INFO, "WPS: Invalid key length %lu for WPA/WPA2",
(unsigned long) cred->key_len);
return -1;
} else {
if (hapd->wps->network_key == NULL ||
hapd->wps->network_key_len < cred->key_len) {
@ -530,7 +539,11 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
fprintf(nconf, "wpa_pairwise=");
prefix = "";
if (cred->encr_type & WPS_ENCR_AES) {
fprintf(nconf, "CCMP");
if (hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD)
fprintf(nconf, "GCMP");
else
fprintf(nconf, "CCMP");
prefix = " ";
}
if (cred->encr_type & WPS_ENCR_TKIP) {
@ -844,7 +857,9 @@ static int hostapd_wps_rf_band_cb(void *ctx)
struct hostapd_data *hapd = ctx;
return hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
WPS_RF_50GHZ :
hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD ?
WPS_RF_60GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
}
@ -856,8 +871,10 @@ static void hostapd_wps_clear_ies(struct hostapd_data *hapd, int deinit_only)
wpabuf_free(hapd->wps_probe_resp_ie);
hapd->wps_probe_resp_ie = NULL;
if (deinit_only)
if (deinit_only) {
hostapd_reset_ap_wps_ie(hapd);
return;
}
hostapd_set_ap_wps_ie(hapd);
}
@ -1039,7 +1056,9 @@ int hostapd_init_wps(struct hostapd_data *hapd,
} else {
wps->dev.rf_bands =
hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
WPS_RF_50GHZ :
hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD ?
WPS_RF_60GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
}
if (conf->wpa & WPA_PROTO_RSN) {
@ -1285,30 +1304,53 @@ int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
}
struct wps_button_pushed_ctx {
const u8 *p2p_dev_addr;
unsigned int count;
};
static int wps_button_pushed(struct hostapd_data *hapd, void *ctx)
{
const u8 *p2p_dev_addr = ctx;
if (hapd->wps == NULL)
return -1;
return wps_registrar_button_pushed(hapd->wps->registrar, p2p_dev_addr);
struct wps_button_pushed_ctx *data = ctx;
if (hapd->wps) {
data->count++;
return wps_registrar_button_pushed(hapd->wps->registrar,
data->p2p_dev_addr);
}
return 0;
}
int hostapd_wps_button_pushed(struct hostapd_data *hapd,
const u8 *p2p_dev_addr)
{
return hostapd_wps_for_each(hapd, wps_button_pushed,
(void *) p2p_dev_addr);
struct wps_button_pushed_ctx ctx;
int ret;
os_memset(&ctx, 0, sizeof(ctx));
ctx.p2p_dev_addr = p2p_dev_addr;
ret = hostapd_wps_for_each(hapd, wps_button_pushed, &ctx);
if (ret == 0 && !ctx.count)
ret = -1;
return ret;
}
struct wps_cancel_ctx {
unsigned int count;
};
static int wps_cancel(struct hostapd_data *hapd, void *ctx)
{
if (hapd->wps == NULL)
return -1;
struct wps_cancel_ctx *data = ctx;
wps_registrar_wps_cancel(hapd->wps->registrar);
ap_for_each_sta(hapd, ap_sta_wps_cancel, NULL);
if (hapd->wps) {
data->count++;
wps_registrar_wps_cancel(hapd->wps->registrar);
ap_for_each_sta(hapd, ap_sta_wps_cancel, NULL);
}
return 0;
}
@ -1316,7 +1358,14 @@ static int wps_cancel(struct hostapd_data *hapd, void *ctx)
int hostapd_wps_cancel(struct hostapd_data *hapd)
{
return hostapd_wps_for_each(hapd, wps_cancel, NULL);
struct wps_cancel_ctx ctx;
int ret;
os_memset(&ctx, 0, sizeof(ctx));
ret = hostapd_wps_for_each(hapd, wps_cancel, &ctx);
if (ret == 0 && !ctx.count)
ret = -1;
return ret;
}
@ -1546,6 +1595,10 @@ struct wps_ap_pin_data {
static int wps_ap_pin_set(struct hostapd_data *hapd, void *ctx)
{
struct wps_ap_pin_data *data = ctx;
if (!hapd->wps)
return 0;
os_free(hapd->conf->ap_pin);
hapd->conf->ap_pin = os_strdup(data->pin_txt);
#ifdef CONFIG_WPS_UPNP

View file

@ -51,6 +51,14 @@ int x_snoop_init(struct hostapd_data *hapd)
return -1;
}
#ifdef CONFIG_IPV6
if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
wpa_printf(MSG_DEBUG,
"x_snoop: Failed to enable multicast snooping on the bridge");
return -1;
}
#endif /* CONFIG_IPV6 */
return 0;
}

View file

@ -1,6 +1,6 @@
/*
* common module tests
* Copyright (c) 2014, Jouni Malinen <j@w1.fi>
* Copyright (c) 2014-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -10,6 +10,8 @@
#include "utils/common.h"
#include "ieee802_11_common.h"
#include "ieee802_11_defs.h"
#include "gas.h"
#include "wpa_common.h"
@ -46,6 +48,10 @@ static const struct ieee802_11_parse_test_data parse_tests[] = {
{ (u8 *) "\x6e\x00", 2, ParseOK, 1 },
{ (u8 *) "\xc7\x00", 2, ParseOK, 1 },
{ (u8 *) "\xc7\x01\x00", 3, ParseOK, 1 },
{ (u8 *) "\x03\x00\x2a\x00\x36\x00\x37\x00\x38\x00\x2d\x00\x3d\x00\xbf\x00\xc0\x00",
18, ParseOK, 9 },
{ (u8 *) "\x8b\x00", 2, ParseOK, 1 },
{ (u8 *) "\xdd\x04\x00\x90\x4c\x04", 6, ParseUnknown, 1 },
{ NULL, 0, ParseOK, 0 }
};
@ -158,6 +164,34 @@ static int rsn_ie_parse_tests(void)
}
static int gas_tests(void)
{
struct wpabuf *buf;
wpa_printf(MSG_INFO, "gas tests");
gas_anqp_set_len(NULL);
buf = wpabuf_alloc(1);
if (buf == NULL)
return -1;
gas_anqp_set_len(buf);
wpabuf_free(buf);
buf = wpabuf_alloc(20);
if (buf == NULL)
return -1;
wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_REQ);
wpabuf_put_u8(buf, 0);
wpabuf_put_be32(buf, 0);
wpabuf_put_u8(buf, 0);
gas_anqp_set_len(buf);
wpabuf_free(buf);
return 0;
}
int common_module_tests(void)
{
int ret = 0;
@ -165,6 +199,7 @@ int common_module_tests(void)
wpa_printf(MSG_INFO, "common module tests");
if (ieee802_11_parse_tests() < 0 ||
gas_tests() < 0 ||
rsn_ie_parse_tests() < 0)
ret = -1;

View file

@ -174,7 +174,7 @@ enum wpa_states {
/**
* WPA_INTERFACE_DISABLED - Interface disabled
*
* This stat eis entered if the network interface is disabled, e.g.,
* This state is entered if the network interface is disabled, e.g.,
* due to rfkill. wpa_supplicant refuses any new operations that would
* use the radio until the interface has been enabled.
*/
@ -295,6 +295,7 @@ enum hostapd_hw_mode {
HOSTAPD_MODE_IEEE80211G,
HOSTAPD_MODE_IEEE80211A,
HOSTAPD_MODE_IEEE80211AD,
HOSTAPD_MODE_IEEE80211ANY,
NUM_HOSTAPD_MODES
};
@ -310,6 +311,7 @@ enum wpa_ctrl_req_type {
WPA_CTRL_REQ_EAP_OTP,
WPA_CTRL_REQ_EAP_PASSPHRASE,
WPA_CTRL_REQ_SIM,
WPA_CTRL_REQ_PSK_PASSPHRASE,
NUM_WPA_CTRL_REQS
};
@ -326,4 +328,10 @@ enum mesh_plink_state {
PLINK_BLOCKED,
};
enum set_band {
WPA_SETBAND_AUTO,
WPA_SETBAND_5G,
WPA_SETBAND_2G
};
#endif /* DEFS_H */

View file

@ -88,8 +88,8 @@ int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan,
int sec_chan)
{
int ok, j, first;
int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
184, 192 };
int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140,
149, 157, 184, 192 };
size_t k;
if (pri_chan == sec_chan || !sec_chan)
@ -152,8 +152,7 @@ void get_pri_sec_chan(struct wpa_scan_res *bss, int *pri_chan, int *sec_chan)
*pri_chan = *sec_chan = 0;
ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0);
if (elems.ht_operation &&
elems.ht_operation_len >= sizeof(*oper)) {
if (elems.ht_operation) {
oper = (struct ieee80211_ht_operation *) elems.ht_operation;
*pri_chan = oper->primary_chan;
if (oper->ht_param & HT_INFO_HT_PARAM_STA_CHNL_WIDTH) {
@ -177,10 +176,8 @@ int check_40mhz_5g(struct hostapd_hw_modes *mode,
size_t i;
int match;
if (!mode || !scan_res || !pri_chan || !sec_chan)
return 0;
if (pri_chan == sec_chan)
if (!mode || !scan_res || !pri_chan || !sec_chan ||
pri_chan == sec_chan)
return 0;
pri_freq = hw_get_freq(mode, pri_chan);
@ -238,7 +235,8 @@ int check_40mhz_5g(struct hostapd_hw_modes *mode,
}
int check_20mhz_bss(struct wpa_scan_res *bss, int pri_freq, int start, int end)
static int check_20mhz_bss(struct wpa_scan_res *bss, int pri_freq, int start,
int end)
{
struct ieee802_11_elems elems;
struct ieee80211_ht_operation *oper;
@ -253,8 +251,7 @@ int check_20mhz_bss(struct wpa_scan_res *bss, int pri_freq, int start, int end)
return 1;
}
if (elems.ht_operation &&
elems.ht_operation_len >= sizeof(*oper)) {
if (elems.ht_operation) {
oper = (struct ieee80211_ht_operation *) elems.ht_operation;
if (oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)
return 0;
@ -275,10 +272,8 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
int affected_start, affected_end;
size_t i;
if (!mode || !scan_res || !pri_chan || !sec_chan)
return 0;
if (pri_chan == sec_chan)
if (!mode || !scan_res || !pri_chan || !sec_chan ||
pri_chan == sec_chan)
return 0;
pri_freq = hw_get_freq(mode, pri_chan);
@ -335,9 +330,7 @@ int check_40mhz_2g4(struct hostapd_hw_modes *mode,
ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems,
0);
if (elems.ht_capabilities &&
elems.ht_capabilities_len >=
sizeof(struct ieee80211_ht_capabilities)) {
if (elems.ht_capabilities) {
struct ieee80211_ht_capabilities *ht_cap =
(struct ieee80211_ht_capabilities *)
elems.ht_capabilities;
@ -363,8 +356,6 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
int vht_oper_chwidth, int center_segment0,
int center_segment1, u32 vht_caps)
{
int tmp;
os_memset(data, 0, sizeof(*data));
data->mode = mode;
data->freq = freq;
@ -378,11 +369,10 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
if (data->vht_enabled) switch (vht_oper_chwidth) {
case VHT_CHANWIDTH_USE_HT:
if (center_segment1)
return -1;
if (center_segment0 != 0 &&
5000 + center_segment0 * 5 != data->center_freq1 &&
2407 + center_segment0 * 5 != data->center_freq1)
if (center_segment1 ||
(center_segment0 != 0 &&
5000 + center_segment0 * 5 != data->center_freq1 &&
2407 + center_segment0 * 5 != data->center_freq1))
return -1;
break;
case VHT_CHANWIDTH_80P80MHZ:
@ -398,19 +388,38 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
/* fall through */
case VHT_CHANWIDTH_80MHZ:
data->bandwidth = 80;
if (vht_oper_chwidth == 1 && center_segment1)
if ((vht_oper_chwidth == 1 && center_segment1) ||
(vht_oper_chwidth == 3 && !center_segment1) ||
!sec_channel_offset)
return -1;
if (vht_oper_chwidth == 3 && !center_segment1)
return -1;
if (!sec_channel_offset)
return -1;
/* primary 40 part must match the HT configuration */
tmp = (30 + freq - 5000 - center_segment0 * 5) / 20;
tmp /= 2;
if (data->center_freq1 != 5000 +
center_segment0 * 5 - 20 + 40 * tmp)
return -1;
data->center_freq1 = 5000 + center_segment0 * 5;
if (!center_segment0) {
if (channel <= 48)
center_segment0 = 42;
else if (channel <= 64)
center_segment0 = 58;
else if (channel <= 112)
center_segment0 = 106;
else if (channel <= 128)
center_segment0 = 122;
else if (channel <= 144)
center_segment0 = 138;
else if (channel <= 161)
center_segment0 = 155;
data->center_freq1 = 5000 + center_segment0 * 5;
} else {
/*
* Note: HT/VHT config and params are coupled. Check if
* HT40 channel band is in VHT80 Pri channel band
* configuration.
*/
if (center_segment0 == channel + 6 ||
center_segment0 == channel + 2 ||
center_segment0 == channel - 2 ||
center_segment0 == channel - 6)
data->center_freq1 = 5000 + center_segment0 * 5;
else
return -1;
}
break;
case VHT_CHANWIDTH_160MHZ:
data->bandwidth = 160;
@ -424,13 +433,21 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
return -1;
if (!sec_channel_offset)
return -1;
/* primary 40 part must match the HT configuration */
tmp = (70 + freq - 5000 - center_segment0 * 5) / 20;
tmp /= 2;
if (data->center_freq1 != 5000 +
center_segment0 * 5 - 60 + 40 * tmp)
/*
* Note: HT/VHT config and params are coupled. Check if
* HT40 channel band is in VHT160 channel band configuration.
*/
if (center_segment0 == channel + 14 ||
center_segment0 == channel + 10 ||
center_segment0 == channel + 6 ||
center_segment0 == channel + 2 ||
center_segment0 == channel - 2 ||
center_segment0 == channel - 6 ||
center_segment0 == channel - 10 ||
center_segment0 == channel - 14)
data->center_freq1 = 5000 + center_segment0 * 5;
else
return -1;
data->center_freq1 = 5000 + center_segment0 * 5;
break;
}

View file

@ -26,7 +26,6 @@ void get_pri_sec_chan(struct wpa_scan_res *bss, int *pri_chan, int *sec_chan);
int check_40mhz_5g(struct hostapd_hw_modes *mode,
struct wpa_scan_results *scan_res, int pri_chan,
int sec_chan);
int check_20mhz_bss(struct wpa_scan_res *bss, int pri_freq, int start, int end);
int check_40mhz_2g4(struct hostapd_hw_modes *mode,
struct wpa_scan_results *scan_res, int pri_chan,
int sec_chan);

View file

@ -1,6 +1,6 @@
/*
* IEEE 802.11 Common routines
* Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -10,6 +10,8 @@
#include "common.h"
#include "defs.h"
#include "wpa_common.h"
#include "qca-vendor.h"
#include "ieee802_11_defs.h"
#include "ieee802_11_common.h"
@ -146,6 +148,20 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
}
break;
case OUI_QCA:
switch (pos[3]) {
case QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST:
elems->pref_freq_list = pos;
elems->pref_freq_list_len = elen;
break;
default:
wpa_printf(MSG_EXCESSIVE,
"Unknown QCA information element ignored (type=%d len=%lu)",
pos[3], (unsigned long) elen);
return -1;
}
break;
default:
wpa_printf(MSG_EXCESSIVE, "unknown vendor specific "
"information element ignored (vendor OUI "
@ -196,6 +212,12 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
switch (id) {
case WLAN_EID_SSID:
if (elen > SSID_MAX_LEN) {
wpa_printf(MSG_DEBUG,
"Ignored too long SSID element (elen=%u)",
elen);
break;
}
elems->ssid = pos;
elems->ssid_len = elen;
break;
@ -204,8 +226,9 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->supp_rates_len = elen;
break;
case WLAN_EID_DS_PARAMS:
if (elen < 1)
break;
elems->ds_params = pos;
elems->ds_params_len = elen;
break;
case WLAN_EID_CF_PARAMS:
case WLAN_EID_TIM:
@ -215,8 +238,9 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->challenge_len = elen;
break;
case WLAN_EID_ERP_INFO:
if (elen < 1)
break;
elems->erp_info = pos;
elems->erp_info_len = elen;
break;
case WLAN_EID_EXT_SUPP_RATES:
elems->ext_supp_rates = pos;
@ -239,24 +263,31 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->supp_channels_len = elen;
break;
case WLAN_EID_MOBILITY_DOMAIN:
if (elen < sizeof(struct rsn_mdie))
break;
elems->mdie = pos;
elems->mdie_len = elen;
break;
case WLAN_EID_FAST_BSS_TRANSITION:
if (elen < sizeof(struct rsn_ftie))
break;
elems->ftie = pos;
elems->ftie_len = elen;
break;
case WLAN_EID_TIMEOUT_INTERVAL:
if (elen != 5)
break;
elems->timeout_int = pos;
elems->timeout_int_len = elen;
break;
case WLAN_EID_HT_CAP:
if (elen < sizeof(struct ieee80211_ht_capabilities))
break;
elems->ht_capabilities = pos;
elems->ht_capabilities_len = elen;
break;
case WLAN_EID_HT_OPERATION:
if (elen < sizeof(struct ieee80211_ht_operation))
break;
elems->ht_operation = pos;
elems->ht_operation_len = elen;
break;
case WLAN_EID_MESH_CONFIG:
elems->mesh_config = pos;
@ -271,12 +302,14 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
elems->peer_mgmt_len = elen;
break;
case WLAN_EID_VHT_CAP:
if (elen < sizeof(struct ieee80211_vht_capabilities))
break;
elems->vht_capabilities = pos;
elems->vht_capabilities_len = elen;
break;
case WLAN_EID_VHT_OPERATION:
if (elen < sizeof(struct ieee80211_vht_operation))
break;
elems->vht_operation = pos;
elems->vht_operation_len = elen;
break;
case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION:
if (elen != 1)
@ -321,6 +354,18 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len,
/* after mic everything is encrypted, so stop. */
left = elen;
break;
case WLAN_EID_MULTI_BAND:
if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) {
wpa_printf(MSG_MSGDUMP,
"IEEE 802.11 element parse ignored MB IE (id=%d elen=%d)",
id, elen);
break;
}
elems->mb_ies.ies[elems->mb_ies.nof_ies].ie = pos;
elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen;
elems->mb_ies.nof_ies++;
break;
default:
unknown++;
if (!show_errors)
@ -486,14 +531,14 @@ int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
ac->aifs = v;
} else if (os_strcmp(pos, "cwmin") == 0) {
v = atoi(val);
if (v < 0 || v > 12) {
if (v < 0 || v > 15) {
wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v);
return -1;
}
ac->cwmin = v;
} else if (os_strcmp(pos, "cwmax") == 0) {
v = atoi(val);
if (v < 0 || v > 12) {
if (v < 0 || v > 15) {
wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v);
return -1;
}
@ -523,50 +568,163 @@ int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel)
{
enum hostapd_hw_mode mode = NUM_HOSTAPD_MODES;
u8 op_class;
if (freq >= 2412 && freq <= 2472) {
mode = HOSTAPD_MODE_IEEE80211G;
*channel = (freq - 2407) / 5;
} else if (freq == 2484) {
mode = HOSTAPD_MODE_IEEE80211B;
*channel = 14;
} else if (freq >= 4900 && freq < 5000) {
mode = HOSTAPD_MODE_IEEE80211A;
*channel = (freq - 4000) / 5;
} else if (freq >= 5000 && freq < 5900) {
mode = HOSTAPD_MODE_IEEE80211A;
*channel = (freq - 5000) / 5;
} else if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
mode = HOSTAPD_MODE_IEEE80211AD;
*channel = (freq - 56160) / 2160;
}
return mode;
return ieee80211_freq_to_channel_ext(freq, 0, 0, &op_class, channel);
}
static const char *us_op_class_cc[] = {
/**
* ieee80211_freq_to_channel_ext - Convert frequency into channel info
* for HT40 and VHT. DFS channels are not covered.
* @freq: Frequency (MHz) to convert
* @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below
* @vht: 0 - non-VHT, 1 - 80 MHz
* @op_class: Buffer for returning operating class
* @channel: Buffer for returning channel number
* Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure
*/
enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
int sec_channel, int vht,
u8 *op_class, u8 *channel)
{
/* TODO: more operating classes */
if (sec_channel > 1 || sec_channel < -1)
return NUM_HOSTAPD_MODES;
if (freq >= 2412 && freq <= 2472) {
if ((freq - 2407) % 5)
return NUM_HOSTAPD_MODES;
if (vht)
return NUM_HOSTAPD_MODES;
/* 2.407 GHz, channels 1..13 */
if (sec_channel == 1)
*op_class = 83;
else if (sec_channel == -1)
*op_class = 84;
else
*op_class = 81;
*channel = (freq - 2407) / 5;
return HOSTAPD_MODE_IEEE80211G;
}
if (freq == 2484) {
if (sec_channel || vht)
return NUM_HOSTAPD_MODES;
*op_class = 82; /* channel 14 */
*channel = 14;
return HOSTAPD_MODE_IEEE80211B;
}
if (freq >= 4900 && freq < 5000) {
if ((freq - 4000) % 5)
return NUM_HOSTAPD_MODES;
*channel = (freq - 4000) / 5;
*op_class = 0; /* TODO */
return HOSTAPD_MODE_IEEE80211A;
}
/* 5 GHz, channels 36..48 */
if (freq >= 5180 && freq <= 5240) {
if ((freq - 5000) % 5)
return NUM_HOSTAPD_MODES;
if (sec_channel == 1)
*op_class = 116;
else if (sec_channel == -1)
*op_class = 117;
else if (vht)
*op_class = 128;
else
*op_class = 115;
*channel = (freq - 5000) / 5;
return HOSTAPD_MODE_IEEE80211A;
}
/* 5 GHz, channels 149..161 */
if (freq >= 5745 && freq <= 5805) {
if ((freq - 5000) % 5)
return NUM_HOSTAPD_MODES;
if (sec_channel == 1)
*op_class = 126;
else if (sec_channel == -1)
*op_class = 127;
else if (vht)
*op_class = 128;
else
*op_class = 124;
*channel = (freq - 5000) / 5;
return HOSTAPD_MODE_IEEE80211A;
}
/* 5 GHz, channels 149..169 */
if (freq >= 5745 && freq <= 5845) {
if ((freq - 5000) % 5)
return NUM_HOSTAPD_MODES;
*op_class = 125;
*channel = (freq - 5000) / 5;
return HOSTAPD_MODE_IEEE80211A;
}
if (freq >= 5000 && freq < 5900) {
if ((freq - 5000) % 5)
return NUM_HOSTAPD_MODES;
*channel = (freq - 5000) / 5;
*op_class = 0; /* TODO */
return HOSTAPD_MODE_IEEE80211A;
}
/* 56.16 GHz, channel 1..4 */
if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) {
if (sec_channel || vht)
return NUM_HOSTAPD_MODES;
*channel = (freq - 56160) / 2160;
*op_class = 180;
return HOSTAPD_MODE_IEEE80211AD;
}
return NUM_HOSTAPD_MODES;
}
static const char *const us_op_class_cc[] = {
"US", "CA", NULL
};
static const char *eu_op_class_cc[] = {
static const char *const eu_op_class_cc[] = {
"AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE",
"DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT",
"LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT",
"RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL
};
static const char *jp_op_class_cc[] = {
static const char *const jp_op_class_cc[] = {
"JP", NULL
};
static const char *cn_op_class_cc[] = {
"CN", "CA", NULL
static const char *const cn_op_class_cc[] = {
"CN", NULL
};
static int country_match(const char *cc[], const char *country)
static int country_match(const char *const cc[], const char *const country)
{
int i;
@ -612,6 +770,10 @@ static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan)
if (chan < 149 || chan > 161)
return -1;
return 5000 + 5 * chan;
case 5: /* channels 149,153,157,161,165 */
if (chan < 149 || chan > 165)
return -1;
return 5000 + 5 * chan;
case 34: /* 60 GHz band, channels 1..3 */
if (chan < 1 || chan > 3)
return -1;
@ -764,12 +926,15 @@ static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan)
return -1;
return 5000 + 5 * chan;
case 124: /* channels 149,153,157,161 */
case 125: /* channels 149,153,157,161,165,169 */
case 126: /* channels 149,157; 40 MHz */
case 127: /* channels 153,161; 40 MHz */
if (chan < 149 || chan > 161)
return -1;
return 5000 + 5 * chan;
case 125: /* channels 149,153,157,161,165,169 */
if (chan < 149 || chan > 169)
return -1;
return 5000 + 5 * chan;
case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */
if (chan < 36 || chan > 161)
@ -921,3 +1086,62 @@ const char * fc2str(u16 fc)
return "WLAN_FC_TYPE_UNKNOWN";
#undef C2S
}
int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
size_t ies_len)
{
os_memset(info, 0, sizeof(*info));
while (ies_buf && ies_len >= 2 &&
info->nof_ies < MAX_NOF_MB_IES_SUPPORTED) {
size_t len = 2 + ies_buf[1];
if (len > ies_len) {
wpa_hexdump(MSG_DEBUG, "Truncated IEs",
ies_buf, ies_len);
return -1;
}
if (ies_buf[0] == WLAN_EID_MULTI_BAND) {
wpa_printf(MSG_DEBUG, "MB IE of %zu bytes found", len);
info->ies[info->nof_ies].ie = ies_buf + 2;
info->ies[info->nof_ies].ie_len = ies_buf[1];
info->nof_ies++;
}
ies_len -= len;
ies_buf += len;
}
return 0;
}
struct wpabuf * mb_ies_by_info(struct mb_ies_info *info)
{
struct wpabuf *mb_ies = NULL;
WPA_ASSERT(info != NULL);
if (info->nof_ies) {
u8 i;
size_t mb_ies_size = 0;
for (i = 0; i < info->nof_ies; i++)
mb_ies_size += 2 + info->ies[i].ie_len;
mb_ies = wpabuf_alloc(mb_ies_size);
if (mb_ies) {
for (i = 0; i < info->nof_ies; i++) {
wpabuf_put_u8(mb_ies, WLAN_EID_MULTI_BAND);
wpabuf_put_u8(mb_ies, info->ies[i].ie_len);
wpabuf_put_data(mb_ies,
info->ies[i].ie,
info->ies[i].ie_len);
}
}
}
return mb_ies;
}

View file

@ -9,6 +9,16 @@
#ifndef IEEE802_11_COMMON_H
#define IEEE802_11_COMMON_H
#define MAX_NOF_MB_IES_SUPPORTED 5
struct mb_ies_info {
struct {
const u8 *ie;
u8 ie_len;
} ies[MAX_NOF_MB_IES_SUPPORTED];
u8 nof_ies;
};
/* Parsed Information Elements */
struct ieee802_11_elems {
const u8 *ssid;
@ -48,12 +58,11 @@ struct ieee802_11_elems {
const u8 *osen;
const u8 *ampe;
const u8 *mic;
const u8 *pref_freq_list;
u8 ssid_len;
u8 supp_rates_len;
u8 ds_params_len;
u8 challenge_len;
u8 erp_info_len;
u8 ext_supp_rates_len;
u8 wpa_ie_len;
u8 rsn_ie_len;
@ -63,14 +72,9 @@ struct ieee802_11_elems {
u8 supp_channels_len;
u8 mdie_len;
u8 ftie_len;
u8 timeout_int_len;
u8 ht_capabilities_len;
u8 ht_operation_len;
u8 mesh_config_len;
u8 mesh_id_len;
u8 peer_mgmt_len;
u8 vht_capabilities_len;
u8 vht_operation_len;
u8 vendor_ht_cap_len;
u8 vendor_vht_len;
u8 p2p_len;
@ -83,6 +87,8 @@ struct ieee802_11_elems {
u8 osen_len;
u8 ampe_len;
u8 mic_len;
u8 pref_freq_list_len;
struct mb_ies_info mb_ies;
};
typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
@ -108,9 +114,15 @@ int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[],
const char *name, const char *val);
enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel);
int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan);
enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq,
int sec_channel, int vht,
u8 *op_class, u8 *channel);
int ieee80211_is_dfs(int freq);
int supp_rates_11b_only(struct ieee802_11_elems *elems);
int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf,
size_t ies_len);
struct wpabuf * mb_ies_by_info(struct mb_ies_info *info);
const char * fc2str(u16 fc);
#endif /* IEEE802_11_COMMON_H */

View file

@ -10,6 +10,8 @@
#ifndef IEEE802_11_DEFS_H
#define IEEE802_11_DEFS_H
#include <utils/common.h>
/* IEEE 802.11 defines */
#define WLAN_FC_PVER 0x0003
@ -163,7 +165,10 @@
#define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76
#define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77
#define WLAN_STATUS_TRANSMISSION_FAILURE 79
#define WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION 82
#define WLAN_STATUS_PENDING_ADMITTING_FST_SESSION 86
#define WLAN_STATUS_QUERY_RESP_OUTSTANDING 95
#define WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL 99
#define WLAN_STATUS_ASSOC_DENIED_NO_VHT 104
/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */
@ -269,6 +274,8 @@
#define WLAN_EID_AMPE 139
#define WLAN_EID_MIC 140
#define WLAN_EID_CCKM 156
#define WLAN_EID_MULTI_BAND 158
#define WLAN_EID_SESSION_TRANSITION 164
#define WLAN_EID_VHT_CAP 191
#define WLAN_EID_VHT_OPERATION 192
#define WLAN_EID_VHT_EXTENDED_BSS_LOAD 193
@ -297,6 +304,7 @@
#define WLAN_ACTION_TDLS 12
#define WLAN_ACTION_SELF_PROTECTED 15
#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */
#define WLAN_ACTION_FST 18
#define WLAN_ACTION_VENDOR_SPECIFIC 127
/* Public action codes */
@ -470,35 +478,35 @@ struct ieee80211_mgmt {
le16 auth_transaction;
le16 status_code;
/* possibly followed by Challenge text */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED auth;
struct {
le16 reason_code;
u8 variable[0];
u8 variable[];
} STRUCT_PACKED deauth;
struct {
le16 capab_info;
le16 listen_interval;
/* followed by SSID and Supported rates */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED assoc_req;
struct {
le16 capab_info;
le16 status_code;
le16 aid;
/* followed by Supported rates */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED assoc_resp, reassoc_resp;
struct {
le16 capab_info;
le16 listen_interval;
u8 current_ap[6];
/* followed by SSID and Supported rates */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED reassoc_req;
struct {
le16 reason_code;
u8 variable[0];
u8 variable[];
} STRUCT_PACKED disassoc;
struct {
u8 timestamp[8];
@ -506,7 +514,7 @@ struct ieee80211_mgmt {
le16 capab_info;
/* followed by some of SSID, Supported rates,
* FH Params, DS Params, CF Params, IBSS Params, TIM */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED beacon;
struct {
/* only variable items: SSID, Supported rates */
@ -518,7 +526,7 @@ struct ieee80211_mgmt {
le16 capab_info;
/* followed by some of SSID, Supported rates,
* FH Params, DS Params, CF Params, IBSS Params */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED probe_resp;
struct {
u8 category;
@ -527,7 +535,7 @@ struct ieee80211_mgmt {
u8 action_code;
u8 dialog_token;
u8 status_code;
u8 variable[0];
u8 variable[];
} STRUCT_PACKED wmm_action;
struct{
u8 action_code;
@ -541,14 +549,14 @@ struct ieee80211_mgmt {
u8 action;
u8 sta_addr[ETH_ALEN];
u8 target_ap_addr[ETH_ALEN];
u8 variable[0]; /* FT Request */
u8 variable[]; /* FT Request */
} STRUCT_PACKED ft_action_req;
struct {
u8 action;
u8 sta_addr[ETH_ALEN];
u8 target_ap_addr[ETH_ALEN];
le16 status_code;
u8 variable[0]; /* FT Request */
u8 variable[]; /* FT Request */
} STRUCT_PACKED ft_action_resp;
struct {
u8 action;
@ -561,23 +569,23 @@ struct ieee80211_mgmt {
struct {
u8 action;
u8 dialogtoken;
u8 variable[0];
u8 variable[];
} STRUCT_PACKED wnm_sleep_req;
struct {
u8 action;
u8 dialogtoken;
le16 keydata_len;
u8 variable[0];
u8 variable[];
} STRUCT_PACKED wnm_sleep_resp;
struct {
u8 action;
u8 variable[0];
u8 variable[];
} STRUCT_PACKED public_action;
struct {
u8 action; /* 9 */
u8 oui[3];
/* Vendor-specific content */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED vs_public_action;
struct {
u8 action; /* 7 */
@ -589,7 +597,7 @@ struct ieee80211_mgmt {
* Session Information URL (optional),
* BSS Transition Candidate List
* Entries */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED bss_tm_req;
struct {
u8 action; /* 8 */
@ -599,7 +607,7 @@ struct ieee80211_mgmt {
/* Target BSSID (optional),
* BSS Transition Candidate List
* Entries (optional) */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED bss_tm_resp;
struct {
u8 action; /* 6 */
@ -607,12 +615,16 @@ struct ieee80211_mgmt {
u8 query_reason;
/* BSS Transition Candidate List
* Entries (optional) */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED bss_tm_query;
struct {
u8 action; /* 15 */
u8 variable[0];
u8 variable[];
} STRUCT_PACKED slf_prot_action;
struct {
u8 action;
u8 variable[];
} STRUCT_PACKED fst_action;
} u;
} STRUCT_PACKED action;
} u;
@ -1065,6 +1077,15 @@ enum p2p_attr_id {
#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6)
#define P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION BIT(7)
/* P2PS Coordination Protocol Transport Bitmap */
#define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0)
#define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1)
struct p2ps_feature_capab {
u8 cpt;
u8 reserved;
} STRUCT_PACKED;
/* Invitation Flags */
#define P2P_INVITATION_FLAGS_TYPE BIT(0)
@ -1354,4 +1375,62 @@ struct rrm_link_measurement_report {
u8 variable[0];
} STRUCT_PACKED;
#define SSID_MAX_LEN 32
/* IEEE Std 802.11ad-2012 - Multi-band element */
struct multi_band_ie {
u8 eid; /* WLAN_EID_MULTI_BAND */
u8 len;
u8 mb_ctrl;
u8 band_id;
u8 op_class;
u8 chan;
u8 bssid[ETH_ALEN];
le16 beacon_int;
u8 tsf_offs[8];
u8 mb_connection_capability;
u8 fst_session_tmout;
/* Optional:
* STA MAC Address
* Pairwise Cipher Suite Count
* Pairwise Cipher Suite List
*/
u8 variable[0];
} STRUCT_PACKED;
enum mb_ctrl_sta_role {
MB_STA_ROLE_AP = 0,
MB_STA_ROLE_TDLS_STA = 1,
MB_STA_ROLE_IBSS_STA = 2,
MB_STA_ROLE_PCP = 3,
MB_STA_ROLE_NON_PCP_NON_AP = 4
};
#define MB_CTRL_ROLE_MASK (BIT(0) | BIT(1) | BIT(2))
#define MB_CTRL_ROLE(ctrl) ((u8) ((ctrl) & MB_CTRL_ROLE_MASK))
#define MB_CTRL_STA_MAC_PRESENT ((u8) (BIT(3)))
#define MB_CTRL_PAIRWISE_CIPHER_SUITE_PRESENT ((u8) (BIT(4)))
enum mb_band_id {
MB_BAND_ID_WIFI_2_4GHZ = 2, /* 2.4 GHz */
MB_BAND_ID_WIFI_5GHZ = 4, /* 4.9 and 5 GHz */
MB_BAND_ID_WIFI_60GHZ = 5, /* 60 GHz */
};
#define MB_CONNECTION_CAPABILITY_AP ((u8) (BIT(0)))
#define MB_CONNECTION_CAPABILITY_PCP ((u8) (BIT(1)))
#define MB_CONNECTION_CAPABILITY_DLS ((u8) (BIT(2)))
#define MB_CONNECTION_CAPABILITY_TDLS ((u8) (BIT(3)))
#define MB_CONNECTION_CAPABILITY_IBSS ((u8) (BIT(4)))
/* IEEE Std 802.11ad-2014 - FST Action field */
enum fst_action {
FST_ACTION_SETUP_REQUEST = 0,
FST_ACTION_SETUP_RESPONSE = 1,
FST_ACTION_TEAR_DOWN = 2,
FST_ACTION_ACK_REQUEST = 3,
FST_ACTION_ACK_RESPONSE = 4,
FST_ACTION_ON_CHANNEL_TUNNEL = 5,
};
#endif /* IEEE802_11_DEFS_H */

View file

@ -9,6 +9,8 @@
#ifndef PRIVSEP_COMMANDS_H
#define PRIVSEP_COMMANDS_H
#include "common/ieee802_11_defs.h"
enum privsep_cmd {
PRIVSEP_CMD_REGISTER,
PRIVSEP_CMD_UNREGISTER,
@ -24,12 +26,31 @@ enum privsep_cmd {
PRIVSEP_CMD_L2_NOTIFY_AUTH_START,
PRIVSEP_CMD_L2_SEND,
PRIVSEP_CMD_SET_COUNTRY,
PRIVSEP_CMD_AUTHENTICATE,
};
struct privsep_cmd_authenticate
{
int freq;
u8 bssid[ETH_ALEN];
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
int auth_alg;
size_t ie_len;
u8 wep_key[4][16];
size_t wep_key_len[4];
int wep_tx_keyidx;
int local_state_change;
int p2p;
size_t sae_data_len;
/* followed by ie_len bytes of ie */
/* followed by sae_data_len bytes of sae_data */
};
struct privsep_cmd_associate
{
u8 bssid[ETH_ALEN];
u8 ssid[32];
u8 ssid[SSID_MAX_LEN];
size_t ssid_len;
int hwmode;
int freq;
@ -66,6 +87,18 @@ enum privsep_event {
PRIVSEP_EVENT_STKSTART,
PRIVSEP_EVENT_FT_RESPONSE,
PRIVSEP_EVENT_RX_EAPOL,
PRIVSEP_EVENT_SCAN_STARTED,
PRIVSEP_EVENT_AUTH,
};
struct privsep_event_auth {
u8 peer[ETH_ALEN];
u8 bssid[ETH_ALEN];
u16 auth_type;
u16 auth_transaction;
u16 status_code;
size_t ies_len;
/* followed by ies_len bytes of ies */
};
#endif /* PRIVSEP_COMMANDS_H */

View file

@ -132,7 +132,7 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY = 50,
QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH = 51,
QCA_NL80211_VENDOR_SUBCMD_APFIND = 52,
/* 53 - reserved for QCA */
/* 53 - reserved - was used by QCA, but not in use anymore */
QCA_NL80211_VENDOR_SUBCMD_DO_ACS = 54,
QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES = 55,
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_CAC_STARTED = 56,
@ -142,6 +142,20 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED = 60,
/* 61-90 - reserved for QCA */
QCA_NL80211_VENDOR_SUBCMD_DATA_OFFLOAD = 91,
QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG = 92,
QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME = 93,
QCA_NL80211_VENDOR_SUBCMD_OCB_START_TIMING_ADVERT = 94,
QCA_NL80211_VENDOR_SUBCMD_OCB_STOP_TIMING_ADVERT = 95,
QCA_NL80211_VENDOR_SUBCMD_OCB_GET_TSF_TIMER = 96,
QCA_NL80211_VENDOR_SUBCMD_DCC_GET_STATS = 97,
QCA_NL80211_VENDOR_SUBCMD_DCC_CLEAR_STATS = 98,
QCA_NL80211_VENDOR_SUBCMD_DCC_UPDATE_NDL = 99,
QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT = 100,
QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES = 101,
QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG = 102,
QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103,
QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL = 104,
QCA_NL80211_VENDOR_SUBCMD_SETBAND = 105,
};
@ -162,6 +176,15 @@ enum qca_wlan_vendor_attr {
/* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */
QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS = 7,
QCA_WLAN_VENDOR_ATTR_TEST = 8,
/* used by QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES */
/* Unsigned 32-bit value. */
QCA_WLAN_VENDOR_ATTR_CONCURRENCY_CAPA = 9,
/* Unsigned 32-bit value */
QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND = 10,
/* Unsigned 32-bit value */
QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11,
/* Unsigned 32-bit value from enum qca_set_band. */
QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12,
/* keep last */
QCA_WLAN_VENDOR_ATTR_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1,
@ -195,6 +218,12 @@ enum qca_wlan_vendor_attr_acs_offload {
QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE,
QCA_WLAN_VENDOR_ATTR_ACS_HT_ENABLED,
QCA_WLAN_VENDOR_ATTR_ACS_HT40_ENABLED,
QCA_WLAN_VENDOR_ATTR_ACS_VHT_ENABLED,
QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH,
QCA_WLAN_VENDOR_ATTR_ACS_CH_LIST,
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL,
QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL,
QCA_WLAN_VENDOR_ATTR_ACS_FREQ_LIST,
/* keep last */
QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_ACS_MAX =
@ -206,6 +235,7 @@ enum qca_wlan_vendor_acs_hw_mode {
QCA_ACS_MODE_IEEE80211G,
QCA_ACS_MODE_IEEE80211A,
QCA_ACS_MODE_IEEE80211AD,
QCA_ACS_MODE_IEEE80211ANY,
};
/**
@ -215,10 +245,13 @@ enum qca_wlan_vendor_acs_hw_mode {
* management offload, a mechanism where the station's firmware
* does the exchange with the AP to establish the temporal keys
* after roaming, rather than having the user space wpa_supplicant do it.
* @QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY: Device supports automatic
* band selection based on channel selection results.
* @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
*/
enum qca_wlan_vendor_features {
QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD = 0,
QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY = 1,
NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
};
@ -243,4 +276,82 @@ enum qca_wlan_vendor_attr_data_offload_ind {
QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_MAX =
QCA_WLAN_VENDOR_ATTR_DATA_OFFLOAD_IND_AFTER_LAST - 1
};
enum qca_vendor_attr_get_preferred_freq_list {
QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_INVALID,
/* A 32-unsigned value; the interface type/mode for which the preferred
* frequency list is requested (see enum qca_iface_type for possible
* values); used in GET_PREFERRED_FREQ_LIST command from user-space to
* kernel and in the kernel response back to user-space.
*/
QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE,
/* An array of 32-unsigned values; values are frequency (MHz); sent
* from kernel space to user space.
*/
QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST,
/* keep last */
QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_MAX =
QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_AFTER_LAST - 1
};
enum qca_vendor_attr_probable_oper_channel {
QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_INVALID,
/* 32-bit unsigned value; indicates the connection/iface type likely to
* come on this channel (see enum qca_iface_type).
*/
QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE,
/* 32-bit unsigned value; the frequency (MHz) of the probable channel */
QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ,
/* keep last */
QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_MAX =
QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_AFTER_LAST - 1
};
enum qca_iface_type {
QCA_IFACE_TYPE_STA,
QCA_IFACE_TYPE_AP,
QCA_IFACE_TYPE_P2P_CLIENT,
QCA_IFACE_TYPE_P2P_GO,
QCA_IFACE_TYPE_IBSS,
QCA_IFACE_TYPE_TDLS,
};
enum qca_set_band {
QCA_SETBAND_AUTO,
QCA_SETBAND_5G,
QCA_SETBAND_2G,
};
/* IEEE 802.11 Vendor Specific elements */
/**
* enum qca_vendor_element_id - QCA Vendor Specific element types
*
* These values are used to identify QCA Vendor Specific elements. The
* payload of the element starts with the three octet OUI (OUI_QCA) and
* is followed by a single octet type which is defined by this enum.
*
* @QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST: P2P preferred channel list.
* This element can be used to specify preference order for supported
* channels. The channels in this list are in preference order (the first
* one has the highest preference) and are described as a pair of
* (global) Operating Class and Channel Number (each one octet) fields.
*
* This extends the standard P2P functionality by providing option to have
* more than one preferred operating channel. When this element is present,
* it replaces the preference indicated in the Operating Channel attribute.
* For supporting other implementations, the Operating Channel attribute is
* expected to be used with the highest preference channel. Similarly, all
* the channels included in this Preferred channel list element are
* expected to be included in the Channel List attribute.
*
* This vendor element may be included in GO Negotiation Request, P2P
* Invitation Request, and Provision Discovery Request frames.
*/
enum qca_vendor_element_id {
QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST = 0,
};
#endif /* QCA_VENDOR_H */

View file

@ -1,6 +1,6 @@
/*
* Simultaneous authentication of equals
* Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
* Copyright (c) 2012-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@ -124,9 +124,7 @@ static struct crypto_bignum * sae_get_rand(struct sae_data *sae)
return NULL;
for (;;) {
if (iter++ > 100)
return NULL;
if (random_get_bytes(val, order_len) < 0)
if (iter++ > 100 || random_get_bytes(val, order_len) < 0)
return NULL;
if (order_len_bits % 8)
buf_shift_right(val, order_len, 8 - order_len_bits % 8);
@ -171,17 +169,107 @@ static void sae_pwd_seed_key(const u8 *addr1, const u8 *addr2, u8 *key)
}
static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
struct crypto_ec_point *pwe)
static struct crypto_bignum *
get_rand_1_to_p_1(const u8 *prime, size_t prime_len, size_t prime_bits,
int *r_odd)
{
u8 pwd_value[SAE_MAX_ECC_PRIME_LEN], prime[SAE_MAX_ECC_PRIME_LEN];
struct crypto_bignum *x;
int y_bit;
for (;;) {
struct crypto_bignum *r;
u8 tmp[SAE_MAX_ECC_PRIME_LEN];
if (random_get_bytes(tmp, prime_len) < 0)
break;
if (prime_bits % 8)
buf_shift_right(tmp, prime_len, 8 - prime_bits % 8);
if (os_memcmp(tmp, prime, prime_len) >= 0)
continue;
r = crypto_bignum_init_set(tmp, prime_len);
if (!r)
break;
if (crypto_bignum_is_zero(r)) {
crypto_bignum_deinit(r, 0);
continue;
}
*r_odd = tmp[prime_len - 1] & 0x01;
return r;
}
return NULL;
}
static int is_quadratic_residue_blind(struct sae_data *sae,
const u8 *prime, size_t bits,
const struct crypto_bignum *qr,
const struct crypto_bignum *qnr,
const struct crypto_bignum *y_sqr)
{
struct crypto_bignum *r, *num;
int r_odd, check, res = -1;
/*
* Use the blinding technique to mask y_sqr while determining
* whether it is a quadratic residue modulo p to avoid leaking
* timing information while determining the Legendre symbol.
*
* v = y_sqr
* r = a random number between 1 and p-1, inclusive
* num = (v * r * r) modulo p
*/
r = get_rand_1_to_p_1(prime, sae->tmp->prime_len, bits, &r_odd);
if (!r)
return -1;
num = crypto_bignum_init();
if (!num ||
crypto_bignum_mulmod(y_sqr, r, sae->tmp->prime, num) < 0 ||
crypto_bignum_mulmod(num, r, sae->tmp->prime, num) < 0)
goto fail;
if (r_odd) {
/*
* num = (num * qr) module p
* LGR(num, p) = 1 ==> quadratic residue
*/
if (crypto_bignum_mulmod(num, qr, sae->tmp->prime, num) < 0)
goto fail;
check = 1;
} else {
/*
* num = (num * qnr) module p
* LGR(num, p) = -1 ==> quadratic residue
*/
if (crypto_bignum_mulmod(num, qnr, sae->tmp->prime, num) < 0)
goto fail;
check = -1;
}
res = crypto_bignum_legendre(num, sae->tmp->prime);
if (res == -2) {
res = -1;
goto fail;
}
res = res == check;
fail:
crypto_bignum_deinit(num, 1);
crypto_bignum_deinit(r, 1);
return res;
}
static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
const u8 *prime,
const struct crypto_bignum *qr,
const struct crypto_bignum *qnr,
struct crypto_bignum **ret_x_cand)
{
u8 pwd_value[SAE_MAX_ECC_PRIME_LEN];
struct crypto_bignum *y_sqr, *x_cand;
int res;
size_t bits;
if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
sae->tmp->prime_len) < 0)
return -1;
*ret_x_cand = NULL;
wpa_hexdump_key(MSG_DEBUG, "SAE: pwd-seed", pwd_seed, SHA256_MAC_LEN);
@ -197,20 +285,23 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed,
if (os_memcmp(pwd_value, prime, sae->tmp->prime_len) >= 0)
return 0;
y_bit = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
x = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
if (x == NULL)
x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len);
if (!x_cand)
return -1;
y_sqr = crypto_ec_point_compute_y_sqr(sae->tmp->ec, x_cand);
if (!y_sqr) {
crypto_bignum_deinit(x_cand, 1);
return -1;
if (crypto_ec_point_solve_y_coord(sae->tmp->ec, pwe, x, y_bit) < 0) {
crypto_bignum_deinit(x, 0);
wpa_printf(MSG_DEBUG, "SAE: No solution found");
return 0;
}
crypto_bignum_deinit(x, 0);
wpa_printf(MSG_DEBUG, "SAE: PWE found");
res = is_quadratic_residue_blind(sae, prime, bits, qr, qnr, y_sqr);
crypto_bignum_deinit(y_sqr, 1);
if (res <= 0) {
crypto_bignum_deinit(x_cand, 1);
return res;
}
*ret_x_cand = x_cand;
return 1;
}
@ -288,24 +379,77 @@ static int sae_test_pwd_seed_ffc(struct sae_data *sae, const u8 *pwd_seed,
}
static int get_random_qr_qnr(const u8 *prime, size_t prime_len,
const struct crypto_bignum *prime_bn,
size_t prime_bits, struct crypto_bignum **qr,
struct crypto_bignum **qnr)
{
*qr = NULL;
*qnr = NULL;
while (!(*qr) || !(*qnr)) {
u8 tmp[SAE_MAX_ECC_PRIME_LEN];
struct crypto_bignum *q;
int res;
if (random_get_bytes(tmp, prime_len) < 0)
break;
if (prime_bits % 8)
buf_shift_right(tmp, prime_len, 8 - prime_bits % 8);
if (os_memcmp(tmp, prime, prime_len) >= 0)
continue;
q = crypto_bignum_init_set(tmp, prime_len);
if (!q)
break;
res = crypto_bignum_legendre(q, prime_bn);
if (res == 1 && !(*qr))
*qr = q;
else if (res == -1 && !(*qnr))
*qnr = q;
else
crypto_bignum_deinit(q, 0);
}
return (*qr && *qnr) ? 0 : -1;
}
static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
const u8 *addr2, const u8 *password,
size_t password_len)
{
u8 counter, k = 4;
u8 counter, k = 40;
u8 addrs[2 * ETH_ALEN];
const u8 *addr[2];
size_t len[2];
int found = 0;
struct crypto_ec_point *pwe_tmp;
u8 dummy_password[32];
size_t dummy_password_len;
int pwd_seed_odd = 0;
u8 prime[SAE_MAX_ECC_PRIME_LEN];
size_t prime_len;
struct crypto_bignum *x = NULL, *qr, *qnr;
size_t bits;
int res;
if (sae->tmp->pwe_ecc == NULL) {
sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec);
if (sae->tmp->pwe_ecc == NULL)
return -1;
}
pwe_tmp = crypto_ec_point_init(sae->tmp->ec);
if (pwe_tmp == NULL)
dummy_password_len = password_len;
if (dummy_password_len > sizeof(dummy_password))
dummy_password_len = sizeof(dummy_password);
if (random_get_bytes(dummy_password, dummy_password_len) < 0)
return -1;
prime_len = sae->tmp->prime_len;
if (crypto_bignum_to_bin(sae->tmp->prime, prime, sizeof(prime),
prime_len) < 0)
return -1;
bits = crypto_ec_prime_len_bits(sae->tmp->ec);
/*
* Create a random quadratic residue (qr) and quadratic non-residue
* (qnr) modulo p for blinding purposes during the loop.
*/
if (get_random_qr_qnr(prime, prime_len, sae->tmp->prime, bits,
&qr, &qnr) < 0)
return -1;
wpa_hexdump_ascii_key(MSG_DEBUG, "SAE: password",
@ -313,8 +457,9 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
/*
* H(salt, ikm) = HMAC-SHA256(salt, ikm)
* base = password
* pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC),
* password || counter)
* base || counter)
*/
sae_pwd_seed_key(addr1, addr2, addrs);
@ -328,9 +473,9 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
* attacks that attempt to determine the number of iterations required
* in the loop.
*/
for (counter = 1; counter < k || !found; counter++) {
for (counter = 1; counter <= k || !x; counter++) {
u8 pwd_seed[SHA256_MAC_LEN];
int res;
struct crypto_bignum *x_cand;
if (counter > 200) {
/* This should not happen in practice */
@ -342,25 +487,58 @@ static int sae_derive_pwe_ecc(struct sae_data *sae, const u8 *addr1,
if (hmac_sha256_vector(addrs, sizeof(addrs), 2, addr, len,
pwd_seed) < 0)
break;
res = sae_test_pwd_seed_ecc(sae, pwd_seed,
found ? pwe_tmp :
sae->tmp->pwe_ecc);
prime, qr, qnr, &x_cand);
if (res < 0)
break;
if (res == 0)
continue;
if (found) {
wpa_printf(MSG_DEBUG, "SAE: Ignore this PWE (one was "
"already selected)");
} else {
wpa_printf(MSG_DEBUG, "SAE: Use this PWE");
found = 1;
goto fail;
if (res > 0 && !x) {
wpa_printf(MSG_DEBUG,
"SAE: Selected pwd-seed with counter %u",
counter);
x = x_cand;
pwd_seed_odd = pwd_seed[SHA256_MAC_LEN - 1] & 0x01;
os_memset(pwd_seed, 0, sizeof(pwd_seed));
/*
* Use a dummy password for the following rounds, if
* any.
*/
addr[0] = dummy_password;
len[0] = dummy_password_len;
} else if (res > 0) {
crypto_bignum_deinit(x_cand, 1);
}
}
crypto_ec_point_deinit(pwe_tmp, 1);
if (!x) {
wpa_printf(MSG_DEBUG, "SAE: Could not generate PWE");
res = -1;
goto fail;
}
return found ? 0 : -1;
if (!sae->tmp->pwe_ecc)
sae->tmp->pwe_ecc = crypto_ec_point_init(sae->tmp->ec);
if (!sae->tmp->pwe_ecc)
res = -1;
else
res = crypto_ec_point_solve_y_coord(sae->tmp->ec,
sae->tmp->pwe_ecc, x,
pwd_seed_odd);
crypto_bignum_deinit(x, 1);
if (res < 0) {
/*
* This should not happen since we already checked that there
* is a result.
*/
wpa_printf(MSG_DEBUG, "SAE: Could not solve y");
}
fail:
crypto_bignum_deinit(qr, 0);
crypto_bignum_deinit(qnr, 0);
return res;
}
@ -472,27 +650,41 @@ static int sae_derive_commit(struct sae_data *sae)
{
struct crypto_bignum *mask;
int ret = -1;
unsigned int counter = 0;
mask = sae_get_rand_and_mask(sae);
if (mask == NULL) {
wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
return -1;
}
do {
counter++;
if (counter > 100) {
/*
* This cannot really happen in practice if the random
* number generator is working. Anyway, to avoid even a
* theoretical infinite loop, break out after 100
* attemps.
*/
return -1;
}
/* commit-scalar = (rand + mask) modulo r */
if (!sae->tmp->own_commit_scalar) {
sae->tmp->own_commit_scalar = crypto_bignum_init();
if (!sae->tmp->own_commit_scalar)
goto fail;
}
crypto_bignum_add(sae->tmp->sae_rand, mask,
sae->tmp->own_commit_scalar);
crypto_bignum_mod(sae->tmp->own_commit_scalar, sae->tmp->order,
sae->tmp->own_commit_scalar);
mask = sae_get_rand_and_mask(sae);
if (mask == NULL) {
wpa_printf(MSG_DEBUG, "SAE: Could not get rand/mask");
return -1;
}
if (sae->tmp->ec && sae_derive_commit_element_ecc(sae, mask) < 0)
goto fail;
if (sae->tmp->dh && sae_derive_commit_element_ffc(sae, mask) < 0)
/* commit-scalar = (rand + mask) modulo r */
if (!sae->tmp->own_commit_scalar) {
sae->tmp->own_commit_scalar = crypto_bignum_init();
if (!sae->tmp->own_commit_scalar)
goto fail;
}
crypto_bignum_add(sae->tmp->sae_rand, mask,
sae->tmp->own_commit_scalar);
crypto_bignum_mod(sae->tmp->own_commit_scalar, sae->tmp->order,
sae->tmp->own_commit_scalar);
} while (crypto_bignum_is_zero(sae->tmp->own_commit_scalar) ||
crypto_bignum_is_one(sae->tmp->own_commit_scalar));
if ((sae->tmp->ec && sae_derive_commit_element_ecc(sae, mask) < 0) ||
(sae->tmp->dh && sae_derive_commit_element_ffc(sae, mask) < 0))
goto fail;
ret = 0;
@ -506,15 +698,12 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2,
const u8 *password, size_t password_len,
struct sae_data *sae)
{
if (sae->tmp == NULL)
return -1;
if (sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
password_len) < 0)
return -1;
if (sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
password_len) < 0)
return -1;
if (sae_derive_commit(sae) < 0)
if (sae->tmp == NULL ||
(sae->tmp->ec && sae_derive_pwe_ecc(sae, addr1, addr2, password,
password_len) < 0) ||
(sae->tmp->dh && sae_derive_pwe_ffc(sae, addr1, addr2, password,
password_len) < 0) ||
sae_derive_commit(sae) < 0)
return -1;
return 0;
}
@ -780,8 +969,9 @@ static u16 sae_parse_commit_scalar(struct sae_data *sae, const u8 **pos,
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
/* 0 < scalar < r */
/* 1 < scalar < r */
if (crypto_bignum_is_zero(peer_scalar) ||
crypto_bignum_is_one(peer_scalar) ||
crypto_bignum_cmp(peer_scalar, sae->tmp->order) >= 0) {
wpa_printf(MSG_DEBUG, "SAE: Invalid peer scalar");
crypto_bignum_deinit(peer_scalar, 0);
@ -847,7 +1037,8 @@ static u16 sae_parse_commit_element_ecc(struct sae_data *sae, const u8 *pos,
static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos,
const u8 *end)
{
struct crypto_bignum *res;
struct crypto_bignum *res, *one;
const u8 one_bin[1] = { 0x01 };
if (pos + sae->tmp->prime_len > end) {
wpa_printf(MSG_DEBUG, "SAE: Not enough data for "
@ -862,18 +1053,23 @@ static u16 sae_parse_commit_element_ffc(struct sae_data *sae, const u8 *pos,
crypto_bignum_init_set(pos, sae->tmp->prime_len);
if (sae->tmp->peer_commit_element_ffc == NULL)
return WLAN_STATUS_UNSPECIFIED_FAILURE;
if (crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
/* 1 < element < p - 1 */
res = crypto_bignum_init();
one = crypto_bignum_init_set(one_bin, sizeof(one_bin));
if (!res || !one ||
crypto_bignum_sub(sae->tmp->prime, one, res) ||
crypto_bignum_is_zero(sae->tmp->peer_commit_element_ffc) ||
crypto_bignum_is_one(sae->tmp->peer_commit_element_ffc) ||
crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc,
sae->tmp->prime) >= 0) {
crypto_bignum_cmp(sae->tmp->peer_commit_element_ffc, res) >= 0) {
crypto_bignum_deinit(res, 0);
crypto_bignum_deinit(one, 0);
wpa_printf(MSG_DEBUG, "SAE: Invalid peer element");
return WLAN_STATUS_UNSPECIFIED_FAILURE;
}
crypto_bignum_deinit(one, 0);
/* scalar-op(r, ELEMENT) = 1 modulo p */
res = crypto_bignum_init();
if (res == NULL ||
crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc,
if (crypto_bignum_exptmod(sae->tmp->peer_commit_element_ffc,
sae->tmp->order, sae->tmp->prime, res) < 0 ||
!crypto_bignum_is_one(res)) {
wpa_printf(MSG_DEBUG, "SAE: Invalid peer element (scalar-op)");
@ -918,7 +1114,34 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
return res;
/* commit-element */
return sae_parse_commit_element(sae, pos, end);
res = sae_parse_commit_element(sae, pos, end);
if (res != WLAN_STATUS_SUCCESS)
return res;
/*
* Check whether peer-commit-scalar and PEER-COMMIT-ELEMENT are same as
* the values we sent which would be evidence of a reflection attack.
*/
if (!sae->tmp->own_commit_scalar ||
crypto_bignum_cmp(sae->tmp->own_commit_scalar,
sae->peer_commit_scalar) != 0 ||
(sae->tmp->dh &&
(!sae->tmp->own_commit_element_ffc ||
crypto_bignum_cmp(sae->tmp->own_commit_element_ffc,
sae->tmp->peer_commit_element_ffc) != 0)) ||
(sae->tmp->ec &&
(!sae->tmp->own_commit_element_ecc ||
crypto_ec_point_cmp(sae->tmp->ec,
sae->tmp->own_commit_element_ecc,
sae->tmp->peer_commit_element_ecc) != 0)))
return WLAN_STATUS_SUCCESS; /* scalars/elements are different */
/*
* This is a reflection attack - return special value to trigger caller
* to silently discard the frame instead of replying with a specific
* status code.
*/
return SAE_SILENTLY_DISCARD;
}

View file

@ -18,6 +18,9 @@
#define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN)
#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_PRIME_LEN)
/* Special value returned by sae_parse_commit() */
#define SAE_SILENTLY_DISCARD 65535
struct sae_temporary_data {
u8 kck[SAE_KCK_LEN];
struct crypto_bignum *own_commit_scalar;

View file

@ -5,6 +5,6 @@
#define VERSION_STR_POSTFIX ""
#endif /* VERSION_STR_POSTFIX */
#define VERSION_STR "2.4" VERSION_STR_POSTFIX
#define VERSION_STR "2.5" VERSION_STR_POSTFIX
#endif /* VERSION_H */

Some files were not shown because too many files have changed in this diff Show more