diff options
Diffstat (limited to 'lib')
191 files changed, 8150 insertions, 1029 deletions
diff --git a/lib/Makefile b/lib/Makefile index 9447cc4551c0..d43e4d395f56 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -157,6 +157,7 @@ SUBDIR_DEPEND_liblzma= libthr SUBDIR_DEPEND_libpcap= ofed .endif SUBDIR_DEPEND_nss_tacplus= libtacplus +SUBDIR_DEPEND_virtual_oss= libsamplerate # NB: keep these sorted by MK_* knobs @@ -173,18 +174,19 @@ SUBDIR+= clang .endif SUBDIR.${MK_CUSE}+= libcuse +SUBDIR.${MK_CUSE}+= virtual_oss SUBDIR.${MK_TOOLCHAIN}+=libpe SUBDIR.${MK_DIALOG}+= libdpv libfigpar SUBDIR.${MK_FDT}+= libfdt SUBDIR.${MK_FILE}+= libmagic SUBDIR.${MK_GPIO}+= libgpio .if ${MK_MITKRB5} == "no" -SUBDIR.${MK_GSSAPI}+= libgssapi +SUBDIR.${MK_KERBEROS}+= libgssapi .endif -SUBDIR.${MK_GSSAPI}+= librpcsec_gss +SUBDIR.${MK_KERBEROS}+= librpcsec_gss SUBDIR.${MK_ICONV}+= libiconv_modules .if ${MK_MITKRB5} == "no" -SUBDIR.${MK_KERBEROS_SUPPORT}+= libcom_err +SUBDIR.${MK_KERBEROS}+= libcom_err .endif SUBDIR.${MK_LDNS}+= libldns SUBDIR.${MK_STATS}+= libstats diff --git a/lib/atf/Makefile.inc b/lib/atf/Makefile.inc index f8f329842eb4..bebed0280596 100644 --- a/lib/atf/Makefile.inc +++ b/lib/atf/Makefile.inc @@ -24,6 +24,8 @@ # SUCH DAMAGE. # +PACKAGE= atf +LIB_PACKAGE= CFLAGS+= -DHAVE_CONFIG_H WARNS?= 3 diff --git a/lib/atf/libatf-c++/Makefile b/lib/atf/libatf-c++/Makefile index 985a79b7dc03..4f4f7f12ec05 100644 --- a/lib/atf/libatf-c++/Makefile +++ b/lib/atf/libatf-c++/Makefile @@ -27,7 +27,6 @@ .include <src.opts.mk> .include <bsd.init.mk> -PACKAGE= tests LIB_CXX= atf-c++ PRIVATELIB= true SHLIB_MAJOR= 2 diff --git a/lib/atf/libatf-c++/tests/Makefile b/lib/atf/libatf-c++/tests/Makefile index dc052c19df67..839c6902d6b1 100644 --- a/lib/atf/libatf-c++/tests/Makefile +++ b/lib/atf/libatf-c++/tests/Makefile @@ -1,7 +1,5 @@ .include <bsd.init.mk> -PACKAGE= tests - TESTS_SUBDIRS= detail ATF= ${SRCTOP}/contrib/atf diff --git a/lib/atf/libatf-c/Makefile b/lib/atf/libatf-c/Makefile index 4cfee2ed824f..c0890abc7640 100644 --- a/lib/atf/libatf-c/Makefile +++ b/lib/atf/libatf-c/Makefile @@ -27,7 +27,6 @@ .include <src.opts.mk> .include <bsd.init.mk> -PACKAGE= tests LIB= atf-c PRIVATELIB= true SHLIB_MAJOR= 1 diff --git a/lib/atf/libatf-c/tests/Makefile b/lib/atf/libatf-c/tests/Makefile index c81c18a91f00..5647e7b9fcbe 100644 --- a/lib/atf/libatf-c/tests/Makefile +++ b/lib/atf/libatf-c/tests/Makefile @@ -1,7 +1,5 @@ .include <bsd.init.mk> -PACKAGE= tests - TESTS_SUBDIRS= detail ATF= ${SRCTOP}/contrib/atf diff --git a/lib/clang/freebsd_cc_version.h b/lib/clang/freebsd_cc_version.h index 277744ae8624..b493dc96db5e 100644 --- a/lib/clang/freebsd_cc_version.h +++ b/lib/clang/freebsd_cc_version.h @@ -1 +1 @@ -#define FREEBSD_CC_VERSION 1500000 +#define FREEBSD_CC_VERSION 1600000 diff --git a/lib/clang/include/lld/Common/Version.inc b/lib/clang/include/lld/Common/Version.inc index 0643da4abbf4..0def3da7469c 100644 --- a/lib/clang/include/lld/Common/Version.inc +++ b/lib/clang/include/lld/Common/Version.inc @@ -1,4 +1,4 @@ // Local identifier in __FreeBSD_version style -#define LLD_FREEBSD_VERSION 1500001 +#define LLD_FREEBSD_VERSION 1600000 #define LLD_VERSION_STRING "19.1.7 (FreeBSD llvmorg-19.1.7-0-gcd708029e0b2-" __XSTRING(LLD_FREEBSD_VERSION) ")" diff --git a/lib/libbe/Makefile b/lib/libbe/Makefile index b04becc38d74..3ba456aee4b7 100644 --- a/lib/libbe/Makefile +++ b/lib/libbe/Makefile @@ -3,6 +3,7 @@ SHLIBDIR?= /lib .include <src.opts.mk> PACKAGE= zfs +LIB_PACKAGE= LIB= be SHLIB_MAJOR= 1 SHLIB_MINOR= 0 diff --git a/lib/libbsdstat/bsdstat.h b/lib/libbsdstat/bsdstat.h index 1b0d1f24e93f..b293cd652a72 100644 --- a/lib/libbsdstat/bsdstat.h +++ b/lib/libbsdstat/bsdstat.h @@ -76,7 +76,7 @@ struct fmt { * classes derived from it are useful. */ struct bsdstat { - const char *name; /* statistics name, e.g. wlanstats */ + const char *name; /* statistics name, e.g. wlanstat */ const struct fmt *stats; /* statistics in class */ int nstats; /* number of stats */ #define FMTS_IS_STAT 0x80 /* the following two bytes are the stat id */ diff --git a/lib/libbsm/Makefile b/lib/libbsm/Makefile index 67802eef62ac..4413a5dd79f7 100644 --- a/lib/libbsm/Makefile +++ b/lib/libbsm/Makefile @@ -1,9 +1,8 @@ -# -# +PACKAGE= audit +LIB_PACKAGE= -PACKAGE= lib${LIB} -OPENBSMDIR= ${SRCTOP}/contrib/openbsm -_LIBBSMDIR= ${OPENBSMDIR}/libbsm +OPENBSMDIR= ${SRCTOP}/contrib/openbsm +_LIBBSMDIR= ${OPENBSMDIR}/libbsm LIB= bsm SHLIB_MAJOR= 3 diff --git a/lib/libbz2/Makefile b/lib/libbz2/Makefile index f7ea21b1a085..d773f202dd67 100644 --- a/lib/libbz2/Makefile +++ b/lib/libbz2/Makefile @@ -1,4 +1,6 @@ -PACKAGE= lib${LIB} +PACKAGE= bzip2 +LIB_PACKAGE= + BZ2DIR= ${SRCTOP}/contrib/bzip2 .PATH: ${BZ2DIR} diff --git a/lib/libc/Makefile b/lib/libc/Makefile index d0c254e33396..8705568f6d34 100644 --- a/lib/libc/Makefile +++ b/lib/libc/Makefile @@ -109,7 +109,6 @@ NOASM= .include "${LIBC_SRCTOP}/inet/Makefile.inc" .include "${LIBC_SRCTOP}/isc/Makefile.inc" .include "${LIBC_SRCTOP}/locale/Makefile.inc" -.include "${LIBC_SRCTOP}/md/Makefile.inc" .include "${LIBC_SRCTOP}/nameser/Makefile.inc" .include "${LIBC_SRCTOP}/net/Makefile.inc" .include "${LIBC_SRCTOP}/nls/Makefile.inc" diff --git a/lib/libc/Versions.def b/lib/libc/Versions.def index 184e107d225a..1c7b34bef35b 100644 --- a/lib/libc/Versions.def +++ b/lib/libc/Versions.def @@ -42,6 +42,10 @@ FBSD_1.7 { FBSD_1.8 { } FBSD_1.7; +# This version was first added to 16.0-current. +FBSD_1.9 { +} FBSD_1.8; + # This is our private namespace. Any global interfaces that are # strictly for use only by other FreeBSD applications and libraries # are listed here. We use a separate namespace so we can write @@ -49,4 +53,4 @@ FBSD_1.8 { # # Please do NOT increment the version of this namespace. FBSDprivate_1.0 { -} FBSD_1.8; +} FBSD_1.9; diff --git a/lib/libc/aarch64/string/timingsafe_memcmp.S b/lib/libc/aarch64/string/timingsafe_memcmp.S index 28fdd911a387..4cc10a152aa8 100644 --- a/lib/libc/aarch64/string/timingsafe_memcmp.S +++ b/lib/libc/aarch64/string/timingsafe_memcmp.S @@ -114,4 +114,4 @@ ENTRY(timingsafe_memcmp) csetm w0, lo csinc w0, w0, wzr, ls ret -END(timingsafe_bcmp) +END(timingsafe_memcmp) diff --git a/lib/libc/gdtoa/_hdtoa.c b/lib/libc/gdtoa/_hdtoa.c index 8ae739acf0db..9c42630cd918 100644 --- a/lib/libc/gdtoa/_hdtoa.c +++ b/lib/libc/gdtoa/_hdtoa.c @@ -40,6 +40,7 @@ #define DBL_ADJ (DBL_MAX_EXP - 2) #define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1) +#define MAX_HEX_DIGITS ((DBL_MANT_DIG + 3 - 1) / 4 + 1) static const float one[] = { 1.0f, -1.0f }; @@ -111,7 +112,7 @@ __hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, s0 = rv_alloc(bufsize); /* Round to the desired number of digits. */ - if (SIGFIGS > ndigits && ndigits > 0) { + if (MAX_HEX_DIGITS > ndigits && ndigits > 0) { float redux = one[u.bits.sign]; int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG; u.bits.exp = offset; diff --git a/lib/libc/gdtoa/_hldtoa.c b/lib/libc/gdtoa/_hldtoa.c index 965d2349d103..5f10d12c5c09 100644 --- a/lib/libc/gdtoa/_hldtoa.c +++ b/lib/libc/gdtoa/_hldtoa.c @@ -65,6 +65,7 @@ typedef uint32_t manl_t; #define LDBL_ADJ (LDBL_MAX_EXP - 2) #define SIGFIGS ((LDBL_MANT_DIG + 3) / 4 + 1) +#define MAX_HEX_DIGITS ((LDBL_MANT_DIG + 3 - 1) / 4 + 1) static const float one[] = { 1.0f, -1.0f }; @@ -125,7 +126,7 @@ __hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign, s0 = rv_alloc(bufsize); /* Round to the desired number of digits. */ - if (SIGFIGS > ndigits && ndigits > 0) { + if (MAX_HEX_DIGITS > ndigits && ndigits > 0) { float redux = one[u.bits.sign]; int offset = 4 * ndigits + LDBL_MAX_EXP - 4 - LDBL_MANT_DIG; #ifdef __i386__ diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 26f638568efc..494b65bc5cc1 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -193,7 +193,6 @@ FBSD_1.0 { __isinff; __isinfl; isatty; - initgroups; jrand48; lcong48; ldexp; @@ -462,6 +461,7 @@ FBSD_1.8 { fdscandir_b; fts_open_b; glob_b; + initgroups; inotify_add_watch; inotify_init; inotify_init1; diff --git a/lib/libc/gen/_rand48.c b/lib/libc/gen/_rand48.c index 990e2c86949b..114c1595b33d 100644 --- a/lib/libc/gen/_rand48.c +++ b/lib/libc/gen/_rand48.c @@ -13,34 +13,6 @@ #include "rand48.h" -unsigned short _rand48_seed[3] = { - RAND48_SEED_0, - RAND48_SEED_1, - RAND48_SEED_2 -}; -unsigned short _rand48_mult[3] = { - RAND48_MULT_0, - RAND48_MULT_1, - RAND48_MULT_2 -}; -unsigned short _rand48_add = RAND48_ADD; - -void -_dorand48(unsigned short xseed[3]) -{ - unsigned long accu; - unsigned short temp[2]; - - accu = (unsigned long) _rand48_mult[0] * (unsigned long) xseed[0] + - (unsigned long) _rand48_add; - temp[0] = (unsigned short) accu; /* lower 16 bits */ - accu >>= sizeof(unsigned short) * 8; - accu += (unsigned long) _rand48_mult[0] * (unsigned long) xseed[1] + - (unsigned long) _rand48_mult[1] * (unsigned long) xseed[0]; - temp[1] = (unsigned short) accu; /* middle 16 bits */ - accu >>= sizeof(unsigned short) * 8; - accu += _rand48_mult[0] * xseed[2] + _rand48_mult[1] * xseed[1] + _rand48_mult[2] * xseed[0]; - xseed[0] = temp[0]; - xseed[1] = temp[1]; - xseed[2] = (unsigned short) accu; -} +uint48 _rand48_seed = RAND48_SEED; +uint48 _rand48_mult = RAND48_MULT; +uint48 _rand48_add = RAND48_ADD; diff --git a/lib/libc/gen/drand48.c b/lib/libc/gen/drand48.c index cec04a6a2425..f7f43ff20468 100644 --- a/lib/libc/gen/drand48.c +++ b/lib/libc/gen/drand48.c @@ -13,10 +13,10 @@ #include "rand48.h" -extern unsigned short _rand48_seed[3]; - double drand48(void) { - return erand48(_rand48_seed); + ERAND48_BEGIN; + _DORAND48(_rand48_seed); + ERAND48_END(_rand48_seed); } diff --git a/lib/libc/gen/erand48.c b/lib/libc/gen/erand48.c index 286904c27839..38d4774a9fe6 100644 --- a/lib/libc/gen/erand48.c +++ b/lib/libc/gen/erand48.c @@ -16,8 +16,9 @@ double erand48(unsigned short xseed[3]) { - _dorand48(xseed); - return ldexp((double) xseed[0], -48) + - ldexp((double) xseed[1], -32) + - ldexp((double) xseed[2], -16); + uint48 tmp; + + ERAND48_BEGIN; + DORAND48(tmp, xseed); + ERAND48_END(tmp); } diff --git a/lib/libc/gen/fts-compat.c b/lib/libc/gen/fts-compat.c index f87cabf085f7..62a1e0a81f62 100644 --- a/lib/libc/gen/fts-compat.c +++ b/lib/libc/gen/fts-compat.c @@ -44,9 +44,9 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> -#include "gen-compat.h" #include "fts-compat.h" #include "un-namespace.h" +#include "gen-compat.h" #include "gen-private.h" diff --git a/lib/libc/gen/fts-compat11.c b/lib/libc/gen/fts-compat11.c index 0351ce5ac690..5abb378f5f08 100644 --- a/lib/libc/gen/fts-compat11.c +++ b/lib/libc/gen/fts-compat11.c @@ -43,9 +43,9 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> -#include "gen-compat.h" #include "fts-compat11.h" #include "un-namespace.h" +#include "gen-compat.h" #include "gen-private.h" diff --git a/lib/libc/gen/fts.3 b/lib/libc/gen/fts.3 index ee558b892c8c..b937607b48e0 100644 --- a/lib/libc/gen/fts.3 +++ b/lib/libc/gen/fts.3 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 30, 2025 +.Dd October 1, 2025 .Dt FTS 3 .Os .Sh NAME @@ -376,7 +376,44 @@ The .Fa fts_name field is always .Dv NUL Ns -terminated . -.Sh FTS_OPEN +.Ss Thread Safety +The +.Nm +functions can safely be used in multi-threaded programs provided no +two threads access the same +.Vt FTS +or +.Vt FTSENT +structure simultaneously. +However, unless the +.Dv FTS_NOCHDIR +flag was passed to +.Fn fts_open +or +.Fn fts_open_b , +calls to +.Fn fts_read +and +.Fn fts_children +may change the current working directory, which will affect all +threads. +Conversely, changing the current working directory either during or +between calls to +.Fn fts_read +or +.Fn fts_children +(even in a single-thread program) may cause +.Nm +to malfunction unless the +.Dv FTS_NOCHDIR +flag was passed to +.Fn fts_open +or +.Fn fts_open_b +and all paths in +.Va path_argv +were absolute. +.Ss Fn fts_open The .Fn fts_open function takes a pointer to an array of character pointers naming one @@ -545,7 +582,7 @@ the directory traversal order is in the order listed in .Fa path_argv for the root paths, and in the order listed in the directory for everything else. -.Sh FTS_OPEN_B +.Ss Fn fts_open_b The .Fn fts_open_b function is identical to @@ -554,7 +591,7 @@ except that it takes a block pointer instead of a function pointer. The block is copied before .Fn fts_open_b returns, so the original can safely go out of scope or be released. -.Sh FTS_READ +.Ss Fn fts_read The .Fn fts_read function returns a pointer to an @@ -605,7 +642,7 @@ after the structure has been returned by the function .Fn fts_read in post-order. -.Sh FTS_CHILDREN +.Ss Fn fts_children The .Fn fts_children function returns a pointer to an @@ -679,7 +716,7 @@ and .Fa fts_namelen fields. .El -.Sh FTS_SET +.Ss Fn fts_set The function .Fn fts_set allows the user application to determine further processing for the @@ -749,7 +786,7 @@ The file may be one of those most recently returned by either or .Fn fts_read . .El -.Sh FTS_CLOSE +.Ss Fn fts_close The .Fn fts_close function closes a file hierarchy stream diff --git a/lib/libc/gen/gen-compat.h b/lib/libc/gen/gen-compat.h index 08e80ede6b6e..19b9addb4321 100644 --- a/lib/libc/gen/gen-compat.h +++ b/lib/libc/gen/gen-compat.h @@ -40,16 +40,50 @@ struct freebsd11_statfs; struct freebsd11_dirent *freebsd11_readdir(DIR *); int freebsd11_readdir_r(DIR *, struct freebsd11_dirent *, struct freebsd11_dirent **); -int freebsd11_stat(const char *, struct freebsd11_stat *); -int freebsd11_lstat(const char *, struct freebsd11_stat *); -int freebsd11_fstat(int, struct freebsd11_stat *); -int freebsd11_fstatat(int, const char *, struct freebsd11_stat *, int); -int freebsd11_statfs(const char *, struct freebsd11_statfs *); -int freebsd11_getfsstat(struct freebsd11_statfs *, long, int); int freebsd11_getmntinfo(struct freebsd11_statfs **, int); char *freebsd11_devname(__uint32_t dev, __mode_t type); -char *freebsd11_devname_r(__uint32_t dev, __mode_t type, char *buf, int len); +char *freebsd11_devname_r(__uint32_t dev, __mode_t type, char *buf, + int len); + +/* + * We want freebsd11_fstat in C source to result in resolution to + * - fstat@FBSD_1.0 for libc.so (but we do not need the _definition_ + * of this fstat, it is provided by libsys.so which we want to use). + * - freebsd11_fstat for libc.a (since if we make it fstat@FBSD_1.0 + * for libc.a, then final linkage into static object ignores version + * and would reference fstat, which is the current syscall, not the + * compat syscall). libc.a provides the freebsd11_fstat implementation. + * Note that freebsd11_fstat from libc.a is not used for anything, but + * we make it correct nonetheless, just in case it would. + * This is arranged by COMPAT_SYSCALL, and libc can just use freebsd11_fstat. + */ +#ifdef PIC +#define COMPAT_SYSCALL(rtype, fun, args, sym, ver) \ + rtype fun args; __sym_compat(sym, fun, ver); +#else +#define COMPAT_SYSCALL(rtype, fun, args, sym, ver) \ + rtype fun args; +#endif + +COMPAT_SYSCALL(int, freebsd11_stat, (const char *, struct freebsd11_stat *), + stat, FBSD_1.0); +COMPAT_SYSCALL(int, freebsd11_lstat, (const char *, struct freebsd11_stat *), + lstat, FBSD_1.0); +COMPAT_SYSCALL(int, freebsd11_fstat, (int, struct freebsd11_stat *), + fstat, FBSD_1.0); +COMPAT_SYSCALL(int, freebsd11_fstatat, (int, const char *, + struct freebsd11_stat *, int), fstatat, FBSD_1.1); + +COMPAT_SYSCALL(int, freebsd11_statfs, (const char *, + struct freebsd11_statfs *), statfs, FBSD_1.0); +COMPAT_SYSCALL(int, freebsd11_getfsstat, (struct freebsd11_statfs *, long, + int), getfsstat, FBSD_1.0); + +COMPAT_SYSCALL(int, freebsd14_setgroups, (int gidsize, const __gid_t *gidset), + setgroups, FBSD_1.0); + +#undef COMPAT_SYSCALL #endif /* _GEN_COMPAT_H_ */ diff --git a/lib/libc/gen/getgrouplist.3 b/lib/libc/gen/getgrouplist.3 index e9a980f99751..e3939fc2481a 100644 --- a/lib/libc/gen/getgrouplist.3 +++ b/lib/libc/gen/getgrouplist.3 @@ -1,5 +1,13 @@ +.\"- +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 1991, 1993 .\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2025 The FreeBSD Foundation +.\" +.\" Portions of this documentation were written by Olivier Certner +.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD +.\" Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -25,12 +33,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 26, 2014 +.Dd August 29, 2025 .Dt GETGROUPLIST 3 .Os .Sh NAME .Nm getgrouplist -.Nd calculate group access list +.Nd produce a user's effective group list .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -40,16 +48,16 @@ .Sh DESCRIPTION The .Fn getgrouplist -function reads through the group file and calculates -the group access list for the user specified in -.Fa name . -The +function reads through the group database to retrieve the supplementary groups +for the user specified in +.Fa name , +and returns the effective group list, whose first group is the value of +.Fa basegid +and the others are the retrieved supplementary groups. .Fa basegid -is automatically included in the groups list. -Typically this value is given as -the group number from the password file. +typically is the user's group number from the password database. .Pp -The resulting group list is returned in the array pointed to by +The effective group list is returned in the array pointed to by .Fa groups . The caller specifies the size of the .Fa groups @@ -70,6 +78,7 @@ Here, the group array will be filled with as many groups as will fit. group membership list .El .Sh SEE ALSO +.Xr setcred 2 , .Xr setgroups 2 , .Xr initgroups 3 .Sh HISTORY diff --git a/lib/libc/gen/getgrouplist.c b/lib/libc/gen/getgrouplist.c index 5bd06bc5121f..9c57b7031336 100644 --- a/lib/libc/gen/getgrouplist.c +++ b/lib/libc/gen/getgrouplist.c @@ -29,13 +29,8 @@ * SUCH DAMAGE. */ -/* - * get credential - */ #include <sys/types.h> -#include <grp.h> -#include <string.h> #include <unistd.h> #include <ssp/ssp.h> @@ -46,4 +41,3 @@ __ssp_real(getgrouplist)(const char *uname, gid_t agroup, gid_t *groups, int *gr { return __getgroupmembership(uname, agroup, groups, *grpcnt, grpcnt); } - diff --git a/lib/libc/gen/initgroups.3 b/lib/libc/gen/initgroups.3 index 03bd07494fc9..4f538fb180ec 100644 --- a/lib/libc/gen/initgroups.3 +++ b/lib/libc/gen/initgroups.3 @@ -1,5 +1,13 @@ +.\"- +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2025 The FreeBSD Foundation +.\" +.\" Portions of this documentation were written by Olivier Certner +.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD +.\" Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -25,12 +33,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 26, 2014 +.Dd September 17, 2025 .Dt INITGROUPS 3 .Os .Sh NAME .Nm initgroups -.Nd initialize group access list +.Nd initialize supplementary groups as per the group database .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -40,19 +48,18 @@ .Sh DESCRIPTION The .Fn initgroups -function -uses the -.Xr getgrouplist 3 -function to calculate the group access list for the user -specified in +function initializes the current process' supplementary groups as prescribed by +its arguments and the system's group database. +.Pp +It first uses the +.Fn getgrouplist +function to compute a list of groups containing the passed +.Fa basegid , +which typically is the user's initial numerical group ID from the password +database, and the supplementary groups in the group database for the user named .Fa name . -This group list is then setup for the current process using -.Xr setgroups 2 . -The -.Fa basegid -is automatically included in the groups list. -Typically this value is given as -the group number from the password file. +It then installs this list as the current process' supplementary groups using +.Fn setgroups . .Sh RETURN VALUES .Rv -std initgroups .Sh ERRORS @@ -60,7 +67,7 @@ The .Fn initgroups function may fail and set .Va errno -for any of the errors specified for the library function +to any of the errors specified for the library function .Xr setgroups 2 . It may also return: .Bl -tag -width Er @@ -77,3 +84,67 @@ The .Fn initgroups function appeared in .Bx 4.2 . +.Pp +The +.Fn initgroups +function changed semantics in +.Fx 15 , +following that of +.Xr setgroups 2 +in the same release. +Before that, it would also set the effective group ID to +.Fa basegid , +and would not include the latter in the supplementary groups except before +.Fx 8 . +Its current behavior in these respects is known to be compatible with that of +the following systems up to the specified versions that are current at time of +this writing: +.Bl -dash -width "-" -compact +.It +Linux (up to 6.6) with the GNU libc (up to 2.42) +.It +.Nx 1.1 and greater (up to 10) +.It +.Ox (up to 7.7) +.It +Systems based on illumos (up to August 2025 sources) +.El +.Sh SECURITY CONSIDERATIONS +As +.Fa basegid +is typically the user's initial numerical group ID, to which the current +process' effective group ID is generally initialized, processes using functions +to change their effective group ID +.Pq via Xr setgid 2 or similar +or that are spawned from executables with the set-group-ID mode bit set will not +be able to relinquish the access rights deriving from being a member of +.Fa basegid , +as these functions do not change the supplementary groups. +.Pp +This behavior is generally desirable in order to paper over the difference of +treatment between the effective group and supplementary ones in this situation, +as they are all in the end indiscriminately used in traditional UNIX +discretionary access checks. +It blends well with the practice of allocating each user its own private group, +as processes launched from a set-group-ID executable keep the same user and +consistently stay also in the same user's group. +Finally, it was also chosen for compatibility with other systems +.Po +see the +.Sx HISTORY +section +.Pc . +.Pp +This convention of including +.Fa basegid +in the supplementary groups is however only enforced by the +.Fn initgroups +function, and not by the +.Xr setgroups 2 +system call, so applications expressly wanting to include in the supplementary +groups only those specified by the group database can themselves call +.Fn getgrouplist +and then +.Fn setgroups +on the result with the first element skipped +.Pq see Xr getgrouplist 3 . diff --git a/lib/libc/gen/initgroups.c b/lib/libc/gen/initgroups.c index b6697dd7ed8f..a1a7d92250e2 100644 --- a/lib/libc/gen/initgroups.c +++ b/lib/libc/gen/initgroups.c @@ -3,6 +3,11 @@ * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this software were developed by Olivier Certner + * <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD + * Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,34 +34,52 @@ * SUCH DAMAGE. */ -#include <sys/param.h> +/* For __sym_compat(). */ +#include <sys/cdefs.h> -#include "namespace.h" -#include <err.h> -#include "un-namespace.h" #include <errno.h> -#include <stdio.h> #include <stdlib.h> #include <unistd.h> -int -initgroups(const char *uname, gid_t agroup) +/* For freebsd14_setgroups(). */ +#include "gen-compat.h" + +static int +initgroups_impl(const char *uname, gid_t agroup, + int (*setgroups)(int, const gid_t *)) { - int ngroups, ret; - long ngroups_max; gid_t *groups; + long ngroups_max; + int ngroups, ret; /* - * Provide space for one group more than possible to allow - * setgroups to fail and set errno. + * Provide space for one group more than possible to allow setgroups() + * to fail and set 'errno' in case we get back more than {NGROUPS_MAX} + + * 1 groups. */ ngroups_max = sysconf(_SC_NGROUPS_MAX) + 2; - if ((groups = malloc(sizeof(*groups) * ngroups_max)) == NULL) - return (ENOMEM); + groups = malloc(sizeof(*groups) * ngroups_max); + if (groups == NULL) + return (-1); /* malloc() set 'errno'. */ ngroups = (int)ngroups_max; - getgrouplist(uname, agroup, groups, &ngroups); - ret = setgroups(ngroups, groups); + (void)getgrouplist(uname, agroup, groups, &ngroups); + ret = (*setgroups)(ngroups, groups); + free(groups); - return (ret); + return (ret); /* setgroups() set 'errno'. */ } + +int +initgroups(const char *uname, gid_t agroup) +{ + return (initgroups_impl(uname, agroup, setgroups)); +} + +int +freebsd14_initgroups(const char *uname, gid_t agroup) +{ + return (initgroups_impl(uname, agroup, freebsd14_setgroups)); +} + +__sym_compat(initgroups, freebsd14_initgroups, FBSD_1.0); diff --git a/lib/libc/gen/jrand48.c b/lib/libc/gen/jrand48.c index 0a9f780a9e5c..93442439d49e 100644 --- a/lib/libc/gen/jrand48.c +++ b/lib/libc/gen/jrand48.c @@ -11,14 +11,13 @@ * to anyone/anything when using this software. */ -#include <stdint.h> - #include "rand48.h" long jrand48(unsigned short xseed[3]) { + uint48 tmp; - _dorand48(xseed); - return ((int32_t)(((uint32_t)xseed[2] << 16) | (uint32_t)xseed[1])); + DORAND48(tmp, xseed); + return ((int)((tmp >> 16) & 0xffffffff)); } diff --git a/lib/libc/gen/lcong48.c b/lib/libc/gen/lcong48.c index f13826b3d3f3..871b2110ed94 100644 --- a/lib/libc/gen/lcong48.c +++ b/lib/libc/gen/lcong48.c @@ -13,18 +13,10 @@ #include "rand48.h" -extern unsigned short _rand48_seed[3]; -extern unsigned short _rand48_mult[3]; -extern unsigned short _rand48_add; - void lcong48(unsigned short p[7]) { - _rand48_seed[0] = p[0]; - _rand48_seed[1] = p[1]; - _rand48_seed[2] = p[2]; - _rand48_mult[0] = p[3]; - _rand48_mult[1] = p[4]; - _rand48_mult[2] = p[5]; + LOADRAND48(_rand48_seed, &p[0]); + LOADRAND48(_rand48_mult, &p[3]); _rand48_add = p[6]; } diff --git a/lib/libc/gen/lrand48.c b/lib/libc/gen/lrand48.c index a3d0111cf4d5..cc07044b8af9 100644 --- a/lib/libc/gen/lrand48.c +++ b/lib/libc/gen/lrand48.c @@ -13,11 +13,9 @@ #include "rand48.h" -extern unsigned short _rand48_seed[3]; - long lrand48(void) { - _dorand48(_rand48_seed); - return ((long) _rand48_seed[2] << 15) + ((long) _rand48_seed[1] >> 1); + _DORAND48(_rand48_seed); + return (_rand48_seed >> 17) & 0x7fffffff; } diff --git a/lib/libc/gen/mrand48.c b/lib/libc/gen/mrand48.c index 15b0bfb1bd6e..f9128a6d4188 100644 --- a/lib/libc/gen/mrand48.c +++ b/lib/libc/gen/mrand48.c @@ -15,13 +15,9 @@ #include "rand48.h" -extern unsigned short _rand48_seed[3]; - long mrand48(void) { - - _dorand48(_rand48_seed); - return ((int32_t)(((uint32_t)_rand48_seed[2] << 16) | - (uint32_t)_rand48_seed[1])); + _DORAND48(_rand48_seed); + return ((int)((_rand48_seed >> 16) & 0xffffffff)); } diff --git a/lib/libc/gen/nrand48.c b/lib/libc/gen/nrand48.c index 6c54065e7e0f..f6f4e231105c 100644 --- a/lib/libc/gen/nrand48.c +++ b/lib/libc/gen/nrand48.c @@ -16,6 +16,8 @@ long nrand48(unsigned short xseed[3]) { - _dorand48(xseed); - return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1); + uint48 tmp; + + DORAND48(tmp, xseed); + return ((tmp >> 17) & 0x7fffffff); } diff --git a/lib/libc/gen/psignal.3 b/lib/libc/gen/psignal.3 index 098b7b02a9b9..bf6a99b4b113 100644 --- a/lib/libc/gen/psignal.3 +++ b/lib/libc/gen/psignal.3 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 10, 2025 +.Dd September 23, 2025 .Dt PSIGNAL 3 .Os .Sh NAME @@ -141,6 +141,13 @@ The name in can be either the name of the signal, with or without the .Dq SIG prefix, or a decimal number. +.Sh RETURN VALUES +The +.Fn sig2str +and +.Fn str2sig +return 0 on success and -1 on translation failure. +In the latter case the memory to store the translation result is left intact. .Sh SEE ALSO .Xr sigaction 2 , .Xr perror 3 , diff --git a/lib/libc/gen/rand48.3 b/lib/libc/gen/rand48.3 index 1e47c843058e..3ea649354270 100644 --- a/lib/libc/gen/rand48.3 +++ b/lib/libc/gen/rand48.3 @@ -9,7 +9,7 @@ .\" of any kind. I shall in no event be liable for anything that happens .\" to anyone/anything when using this software. .\" -.Dd September 4, 2012 +.Dd September 11, 2025 .Dt RAND48 3 .Os .Sh NAME @@ -183,5 +183,8 @@ generator calls. .Xr arc4random 3 , .Xr rand 3 , .Xr random 3 +.Sh STANDARDS +The functions described in this page are expected to conform to +.St -p1003.1-2008 . .Sh AUTHORS .An Martin Birgmeier diff --git a/lib/libc/gen/rand48.h b/lib/libc/gen/rand48.h index 9861e99683cb..d3326e851491 100644 --- a/lib/libc/gen/rand48.h +++ b/lib/libc/gen/rand48.h @@ -14,10 +14,11 @@ #ifndef _RAND48_H_ #define _RAND48_H_ +#include <sys/types.h> #include <math.h> #include <stdlib.h> -void _dorand48(unsigned short[3]); +#include "fpmath.h" #define RAND48_SEED_0 (0x330e) #define RAND48_SEED_1 (0xabcd) @@ -27,4 +28,62 @@ void _dorand48(unsigned short[3]); #define RAND48_MULT_2 (0x0005) #define RAND48_ADD (0x000b) +typedef uint64_t uint48; + +extern uint48 _rand48_seed; +extern uint48 _rand48_mult; +extern uint48 _rand48_add; + +#define TOUINT48(x, y, z) \ + ((uint48)(x) + (((uint48)(y)) << 16) + (((uint48)(z)) << 32)) + +#define RAND48_SEED TOUINT48(RAND48_SEED_0, RAND48_SEED_1, RAND48_SEED_2) +#define RAND48_MULT TOUINT48(RAND48_MULT_0, RAND48_MULT_1, RAND48_MULT_2) + +#define LOADRAND48(l, x) do { \ + (l) = TOUINT48((x)[0], (x)[1], (x)[2]); \ +} while (0) + +#define STORERAND48(l, x) do { \ + (x)[0] = (unsigned short)(l); \ + (x)[1] = (unsigned short)((l) >> 16); \ + (x)[2] = (unsigned short)((l) >> 32); \ +} while (0) + +#define _DORAND48(l) do { \ + (l) = (l) * _rand48_mult + _rand48_add; \ +} while (0) + +#define DORAND48(l, x) do { \ + LOADRAND48(l, x); \ + _DORAND48(l); \ + STORERAND48(l, x); \ +} while (0) + +#define ERAND48_BEGIN \ + union { \ + union IEEEd2bits ieee; \ + uint64_t u64; \ + } u; \ + int s + +/* + * Optimization for speed: assume doubles are IEEE 754 and use bit fiddling + * rather than converting to double. Specifically, clamp the result to 48 bits + * and convert to a double in [0.0, 1.0) via division by 2^48. Normalize by + * shifting the most significant bit into the implicit one position and + * adjusting the exponent accordingly. The store to the exponent field + * overwrites the implicit one. + */ +#define ERAND48_END(x) do { \ + u.u64 = ((x) & 0xffffffffffffULL); \ + if (u.u64 == 0) \ + return (0.0); \ + u.u64 <<= 5; \ + for (s = 0; !(u.u64 & (1LL << 52)); s++, u.u64 <<= 1) \ + ; \ + u.ieee.bits.exp = 1022 - s; \ + return (u.ieee.d); \ +} while (0) + #endif /* _RAND48_H_ */ diff --git a/lib/libc/gen/seed48.c b/lib/libc/gen/seed48.c index 258c4bac3c9f..f57656ce1121 100644 --- a/lib/libc/gen/seed48.c +++ b/lib/libc/gen/seed48.c @@ -13,24 +13,14 @@ #include "rand48.h" -extern unsigned short _rand48_seed[3]; -extern unsigned short _rand48_mult[3]; -extern unsigned short _rand48_add; - unsigned short * seed48(unsigned short xseed[3]) { static unsigned short sseed[3]; - sseed[0] = _rand48_seed[0]; - sseed[1] = _rand48_seed[1]; - sseed[2] = _rand48_seed[2]; - _rand48_seed[0] = xseed[0]; - _rand48_seed[1] = xseed[1]; - _rand48_seed[2] = xseed[2]; - _rand48_mult[0] = RAND48_MULT_0; - _rand48_mult[1] = RAND48_MULT_1; - _rand48_mult[2] = RAND48_MULT_2; + STORERAND48(_rand48_seed, sseed); + LOADRAND48(_rand48_seed, xseed); + _rand48_mult = RAND48_MULT; _rand48_add = RAND48_ADD; - return sseed; + return (sseed); } diff --git a/lib/libc/gen/srand48.c b/lib/libc/gen/srand48.c index fd369a094c51..4b82ece72db8 100644 --- a/lib/libc/gen/srand48.c +++ b/lib/libc/gen/srand48.c @@ -13,18 +13,11 @@ #include "rand48.h" -extern unsigned short _rand48_seed[3]; -extern unsigned short _rand48_mult[3]; -extern unsigned short _rand48_add; - void srand48(long seed) { - _rand48_seed[0] = RAND48_SEED_0; - _rand48_seed[1] = (unsigned short) seed; - _rand48_seed[2] = (unsigned short) (seed >> 16); - _rand48_mult[0] = RAND48_MULT_0; - _rand48_mult[1] = RAND48_MULT_1; - _rand48_mult[2] = RAND48_MULT_2; + _rand48_seed = TOUINT48(RAND48_SEED_0, (unsigned short)seed, + (unsigned short)(seed >> 16)); + _rand48_mult = RAND48_MULT; _rand48_add = RAND48_ADD; } diff --git a/lib/libc/gen/sysconf.c b/lib/libc/gen/sysconf.c index 66562d0e29f0..b5b732eed05d 100644 --- a/lib/libc/gen/sysconf.c +++ b/lib/libc/gen/sysconf.c @@ -51,7 +51,7 @@ #include "un-namespace.h" #include "../stdlib/atexit.h" -#include "tzdir.h" /* from ../../../contrib/tzcode/stdtime */ +#include "tzdir.h" /* from ../../../contrib/tzcode */ #include "libc_private.h" #define _PATH_ZONEINFO TZDIR /* from tzfile.h */ diff --git a/lib/libc/i386/gen/makecontext.c b/lib/libc/i386/gen/makecontext.c index 7b4845ac6bee..9fedd8b99c47 100644 --- a/lib/libc/i386/gen/makecontext.c +++ b/lib/libc/i386/gen/makecontext.c @@ -124,7 +124,7 @@ __makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...) /* * Setup the top of the stack with the user start routine - * followed by all of its aguments and the pointer to the + * followed by all of its arguments and the pointer to the * ucontext. We need to leave a spare spot at the top of * the stack because setcontext will move eip to the top * of the stack before returning. diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h index 70fb8dcd97f3..630ffe7daae3 100644 --- a/lib/libc/include/compat.h +++ b/lib/libc/include/compat.h @@ -69,6 +69,9 @@ __sym_compat(kevent, freebsd11_kevent, FBSD_1.0); __sym_compat(swapoff, freebsd13_swapoff, FBSD_1.0); +__sym_compat(getgroups, freebsd14_getgroups, FBSD_1.0); +__sym_compat(setgroups, freebsd14_setgroups, FBSD_1.0); + #undef __sym_compat #define __weak_reference(sym,alias) \ @@ -77,4 +80,3 @@ __sym_compat(swapoff, freebsd13_swapoff, FBSD_1.0); #undef __weak_reference #endif /* __LIBC_COMPAT_H__ */ - diff --git a/lib/libc/include/port_before.h b/lib/libc/include/port_before.h index cfc43c53f157..aa2cd394104a 100644 --- a/lib/libc/include/port_before.h +++ b/lib/libc/include/port_before.h @@ -5,7 +5,6 @@ #define _LIBC 1 #define DO_PTHREADS 1 #define USE_POLL 1 -#define HAVE_MD5 1 #define ISC_SOCKLEN_T socklen_t #define ISC_FORMAT_PRINTF(fmt, args) \ diff --git a/lib/libc/md/Makefile.inc b/lib/libc/md/Makefile.inc deleted file mode 100644 index 82c5f0670485..000000000000 --- a/lib/libc/md/Makefile.inc +++ /dev/null @@ -1,3 +0,0 @@ -.PATH: ${SRCTOP}/sys/kern - -SRCS+= md5c.c diff --git a/lib/libc/net/gai_strerror.c b/lib/libc/net/gai_strerror.c index 0d4303e76a73..23f58b763573 100644 --- a/lib/libc/net/gai_strerror.c +++ b/lib/libc/net/gai_strerror.c @@ -45,22 +45,22 @@ * Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) were omitted from RFC 3493, * but are or may be used as extensions or in old code. */ -static const char *ai_errlist[] = { - "Success", /* 0 */ - "Address family for hostname not supported", /* EAI_ADDRFAMILY */ - "Name could not be resolved at this time", /* EAI_AGAIN */ - "Flags parameter had an invalid value", /* EAI_BADFLAGS */ - "Non-recoverable failure in name resolution", /* EAI_FAIL */ - "Address family not recognized", /* EAI_FAMILY */ - "Memory allocation failure", /* EAI_MEMORY */ - "No address associated with hostname", /* EAI_NODATA*/ - "Name does not resolve", /* EAI_NONAME */ - "Service was not recognized for socket type", /* EAI_SERVICE */ - "Intended socket type was not recognized", /* EAI_SOCKTYPE */ - "System error returned in errno", /* EAI_SYSTEM */ - "Invalid value for hints", /* EAI_BADHINTS */ - "Resolved protocol is unknown", /* EAI_PROTOCOL */ - "Argument buffer overflow" /* EAI_OVERFLOW */ +static const char *const ai_errlist[] = { + [0] = "Success", + [EAI_ADDRFAMILY] = "Address family for hostname not supported", + [EAI_AGAIN] = "Name could not be resolved at this time", + [EAI_BADFLAGS] = "Flags parameter had an invalid value", + [EAI_FAIL] = "Non-recoverable failure in name resolution", + [EAI_FAMILY] = "Address family not recognized", + [EAI_MEMORY] = "Memory allocation failure", + [EAI_NODATA] = "No address associated with hostname", + [EAI_NONAME] = "Name does not resolve", + [EAI_SERVICE] = "Service was not recognized for socket type", + [EAI_SOCKTYPE] = "Intended socket type was not recognized", + [EAI_SYSTEM] = "System error returned in errno", + [EAI_BADHINTS] = "Invalid value for hints", + [EAI_PROTOCOL] = "Resolved protocol is unknown", + [EAI_OVERFLOW] = "Argument buffer overflow", }; #if defined(NLS) @@ -72,7 +72,7 @@ static int gai_keycreated = 0; static void gai_keycreate(void) { - gai_keycreated = (thr_keycreate(&gai_key, free) == 0); + gai_keycreated = thr_keycreate(&gai_key, free) == 0; } #endif @@ -82,7 +82,9 @@ gai_strerror(int ecode) #if defined(NLS) nl_catd catd; char *buf; + int saved_errno; + saved_errno = errno; if (thr_main() != 0) buf = gai_buf; else { @@ -110,11 +112,13 @@ gai_strerror(int ecode) strlcpy(buf, catgets(catd, 3, NL_MSGMAX, "Unknown error"), sizeof(gai_buf)); catclose(catd); - return buf; + errno = saved_errno; + return (buf); thr_err: + errno = saved_errno; #endif if (ecode >= 0 && ecode < EAI_MAX) - return ai_errlist[ecode]; - return "Unknown error"; + return (ai_errlist[ecode]); + return ("Unknown error"); } diff --git a/lib/libc/nls/Makefile.inc b/lib/libc/nls/Makefile.inc index f26e04c187a5..c211026aba72 100644 --- a/lib/libc/nls/Makefile.inc +++ b/lib/libc/nls/Makefile.inc @@ -12,6 +12,11 @@ MAN+= catclose.3 catgets.3 catopen.3 # for translators. NLSNAME= libc +# We don't want libc's NLS catalogues to be installed in the clibs package. +# Put them in locales instead, since anyone interested in NLS will have +# that installed. +NLSPACKAGE= locales + NLS+= be_BY.UTF-8 NLS+= ca_ES.ISO8859-1 NLS+= de_DE.ISO8859-1 diff --git a/lib/libc/resolv/Symbol.map b/lib/libc/resolv/Symbol.map index 6b9c43298fb5..26daecbe2eff 100644 --- a/lib/libc/resolv/Symbol.map +++ b/lib/libc/resolv/Symbol.map @@ -103,6 +103,5 @@ FBSD_1.0 { }; FBSD_1.4 { - __res_rndinit; __res_nrandomid; }; diff --git a/lib/libc/resolv/res_init.c b/lib/libc/resolv/res_init.c index 71ab2dcb7038..5a2fce013c8c 100644 --- a/lib/libc/resolv/res_init.c +++ b/lib/libc/resolv/res_init.c @@ -86,19 +86,6 @@ #include <unistd.h> #include <netdb.h> -#ifndef HAVE_MD5 -# include "../dst/md5.h" -#else -# ifdef SOLARIS2 -# include <sys/md5.h> -# elif _LIBC -# include <md5.h> -# endif -#endif -#ifndef _MD5_H_ -# define _MD5_H_ 1 /*%< make sure we do not include rsaref md5.h file */ -#endif - #include "un-namespace.h" #include "port_after.h" @@ -184,8 +171,6 @@ __res_vinit(res_state statp, int preinit) { statp->options = RES_DEFAULT; } - statp->_rnd = malloc(16); - res_rndinit(statp); statp->id = res_nrandomid(statp); memset(u, 0, sizeof(u)); @@ -733,48 +718,18 @@ net_mask(struct in_addr in) /*!< XXX - should really use system's version of th } #endif -static u_char srnd[16]; - void -res_rndinit(res_state statp) +freebsd15_res_rndinit(res_state statp) { - struct timeval now; - u_int32_t u32; - u_int16_t u16; - u_char *rnd = statp->_rnd == NULL ? srnd : statp->_rnd; - - gettimeofday(&now, NULL); - u32 = now.tv_sec; - memcpy(rnd, &u32, 4); - u32 = now.tv_usec; - memcpy(rnd + 4, &u32, 4); - u32 += now.tv_sec; - memcpy(rnd + 8, &u32, 4); - u16 = getpid(); - memcpy(rnd + 12, &u16, 2); + (void)statp; } +__sym_compat(__res_rndinit, freebsd15_res_rndinit, FBSD_1.4); u_int res_nrandomid(res_state statp) { - struct timeval now; - u_int16_t u16; - MD5_CTX ctx; - u_char *rnd = statp->_rnd == NULL ? srnd : statp->_rnd; - - gettimeofday(&now, NULL); - u16 = (u_int16_t) (now.tv_sec ^ now.tv_usec); - memcpy(rnd + 14, &u16, 2); -#ifndef HAVE_MD5 - MD5_Init(&ctx); - MD5_Update(&ctx, rnd, 16); - MD5_Final(rnd, &ctx); -#else - MD5Init(&ctx); - MD5Update(&ctx, rnd, 16); - MD5Final(rnd, &ctx); -#endif - memcpy(&u16, rnd + 14, 2); - return ((u_int) u16); + (void) statp; + + return ((u_int)(arc4random() & 0xffff)); } /*% @@ -808,10 +763,6 @@ res_ndestroy(res_state statp) { free(statp->_u._ext.ext); statp->_u._ext.ext = NULL; } - if (statp->_rnd != NULL) { - free(statp->_rnd); - statp->_rnd = NULL; - } statp->options &= ~RES_INIT; } diff --git a/lib/libc/rpc/Symbol.map b/lib/libc/rpc/Symbol.map index 61e8e084b1e0..105d6fb6b54e 100644 --- a/lib/libc/rpc/Symbol.map +++ b/lib/libc/rpc/Symbol.map @@ -8,9 +8,13 @@ FBSD_1.0 { xdr_desargs; xdr_desresp; + authdes_seccreate; + authdes_pk_seccreate; authnone_create; authunix_create; authunix_create_default; + xdr_authdes_cred; + xdr_authdes_verf; xdr_authunix_parms; bindresvport; bindresvport_sa; @@ -54,6 +58,15 @@ FBSD_1.0 { endrpcent; getrpcent; getrpcport; + key_setsecret; + key_secretkey_is_set; + key_encryptsession_pk; + key_decryptsession_pk; + key_encryptsession; + key_decryptsession; + key_gendes; + key_setnet; + key_get_conv; xdr_keystatus; xdr_keybuf; xdr_netnamestr; @@ -117,6 +130,7 @@ FBSD_1.0 { callrpc; registerrpc; clnt_broadcast; + authdes_create; clntunix_create; svcunix_create; svcunixfd_create; @@ -166,6 +180,8 @@ FBSD_1.0 { _authenticate; _svcauth_null; svc_auth_reg; + _svcauth_des; + authdes_getucred; _svcauth_unix; _svcauth_short; svc_dg_create; @@ -189,6 +205,9 @@ FBSD_1.8 { FBSDprivate_1.0 { __des_crypt_LOCAL; + __key_encryptsession_pk_LOCAL; + __key_decryptsession_pk_LOCAL; + __key_gendes_LOCAL; __svc_clean_idle; __rpc_gss_unwrap; __rpc_gss_unwrap_stub; diff --git a/lib/libc/rpc/auth_des.c b/lib/libc/rpc/auth_des.c index 754d55cbed3e..c9b20de25cda 100644 --- a/lib/libc/rpc/auth_des.c +++ b/lib/libc/rpc/auth_des.c @@ -30,34 +30,463 @@ /* * Copyright (c) 1988 by Sun Microsystems, Inc. */ - /* - * Secure RPC DES authentication was removed in FreeBSD 15.0. - * These symbols are provided for backward compatibility, but provide no - * functionality and will always return an error. + * auth_des.c, client-side implementation of DES authentication */ #include "namespace.h" #include "reentrant.h" +#include <err.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <rpc/des_crypt.h> +#include <syslog.h> #include <rpc/types.h> #include <rpc/auth.h> #include <rpc/auth_des.h> +#include <rpc/clnt.h> +#include <rpc/xdr.h> +#include <sys/socket.h> +#undef NIS #include <rpcsvc/nis.h> #include "un-namespace.h" +#include "mt_misc.h" + +#define USEC_PER_SEC 1000000 +#define RTIME_TIMEOUT 5 /* seconds to wait for sync */ + +#define AUTH_PRIVATE(auth) (struct ad_private *) auth->ah_private +#define ALLOC(object_type) (object_type *) mem_alloc(sizeof(object_type)) +#define FREE(ptr, size) mem_free((char *)(ptr), (int) size) +#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) + +extern bool_t xdr_authdes_cred( XDR *, struct authdes_cred *); +extern bool_t xdr_authdes_verf( XDR *, struct authdes_verf *); +extern int key_encryptsession_pk(char *, netobj *, des_block *); + +extern bool_t __rpc_get_time_offset(struct timeval *, nis_server *, char *, + char **, char **); -static AUTH * -__authdes_seccreate(const char *servername, const u_int win, +/* + * DES authenticator operations vector + */ +static void authdes_nextverf(AUTH *); +static bool_t authdes_marshal(AUTH *, XDR *); +static bool_t authdes_validate(AUTH *, struct opaque_auth *); +static bool_t authdes_refresh(AUTH *, void *); +static void authdes_destroy(AUTH *); + +static struct auth_ops *authdes_ops(void); + +/* + * This struct is pointed to by the ah_private field of an "AUTH *" + */ +struct ad_private { + char *ad_fullname; /* client's full name */ + u_int ad_fullnamelen; /* length of name, rounded up */ + char *ad_servername; /* server's full name */ + u_int ad_servernamelen; /* length of name, rounded up */ + u_int ad_window; /* client specified window */ + bool_t ad_dosync; /* synchronize? */ + struct netbuf ad_syncaddr; /* remote host to synch with */ + char *ad_timehost; /* remote host to synch with */ + struct timeval ad_timediff; /* server's time - client's time */ + u_int ad_nickname; /* server's nickname for client */ + struct authdes_cred ad_cred; /* storage for credential */ + struct authdes_verf ad_verf; /* storage for verifier */ + struct timeval ad_timestamp; /* timestamp sent */ + des_block ad_xkey; /* encrypted conversation key */ + u_char ad_pkey[1024]; /* Server's actual public key */ + char *ad_netid; /* Timehost netid */ + char *ad_uaddr; /* Timehost uaddr */ + nis_server *ad_nis_srvr; /* NIS+ server struct */ +}; + +AUTH *authdes_pk_seccreate(const char *, netobj *, u_int, const char *, + const des_block *, nis_server *); + +/* + * documented version of authdes_seccreate + */ +/* + servername: network name of server + win: time to live + timehost: optional hostname to sync with + ckey: optional conversation key to use +*/ + +AUTH * +authdes_seccreate(const char *servername, const u_int win, const char *timehost, const des_block *ckey) { - return (NULL); + u_char pkey_data[1024]; + netobj pkey; + AUTH *dummy; + + if (! getpublickey(servername, (char *) pkey_data)) { + syslog(LOG_ERR, + "authdes_seccreate: no public key found for %s", + servername); + return (NULL); + } + + pkey.n_bytes = (char *) pkey_data; + pkey.n_len = (u_int)strlen((char *)pkey_data) + 1; + dummy = authdes_pk_seccreate(servername, &pkey, win, timehost, + ckey, NULL); + return (dummy); } -__sym_compat(authdes_seccreate, __authdes_seccreate, FBSD_1.0); -static AUTH * -__authdes_pk_seccreate(const char *servername __unused, netobj *pkey __unused, - u_int window __unused, const char *timehost __unused, - const des_block *ckey __unused, nis_server *srvr __unused) +/* + * Slightly modified version of authdessec_create which takes the public key + * of the server principal as an argument. This spares us a call to + * getpublickey() which in the nameserver context can cause a deadlock. + */ +AUTH * +authdes_pk_seccreate(const char *servername, netobj *pkey, u_int window, + const char *timehost, const des_block *ckey, nis_server *srvr) { + AUTH *auth; + struct ad_private *ad; + char namebuf[MAXNETNAMELEN+1]; + + /* + * Allocate everything now + */ + auth = ALLOC(AUTH); + if (auth == NULL) { + syslog(LOG_ERR, "authdes_pk_seccreate: out of memory"); + return (NULL); + } + ad = ALLOC(struct ad_private); + if (ad == NULL) { + syslog(LOG_ERR, "authdes_pk_seccreate: out of memory"); + goto failed; + } + ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */ + ad->ad_timehost = NULL; + ad->ad_netid = NULL; + ad->ad_uaddr = NULL; + ad->ad_nis_srvr = NULL; + ad->ad_timediff.tv_sec = 0; + ad->ad_timediff.tv_usec = 0; + memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len); + if (!getnetname(namebuf)) + goto failed; + ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf)); + ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1); + ad->ad_servernamelen = strlen(servername); + ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1); + + if (ad->ad_fullname == NULL || ad->ad_servername == NULL) { + syslog(LOG_ERR, "authdes_seccreate: out of memory"); + goto failed; + } + if (timehost != NULL) { + ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1); + if (ad->ad_timehost == NULL) { + syslog(LOG_ERR, "authdes_seccreate: out of memory"); + goto failed; + } + memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1); + ad->ad_dosync = TRUE; + } else if (srvr != NULL) { + ad->ad_nis_srvr = srvr; /* transient */ + ad->ad_dosync = TRUE; + } else { + ad->ad_dosync = FALSE; + } + memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1); + memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1); + ad->ad_window = window; + if (ckey == NULL) { + if (key_gendes(&auth->ah_key) < 0) { + syslog(LOG_ERR, + "authdes_seccreate: keyserv(1m) is unable to generate session key"); + goto failed; + } + } else { + auth->ah_key = *ckey; + } + + /* + * Set up auth handle + */ + auth->ah_cred.oa_flavor = AUTH_DES; + auth->ah_verf.oa_flavor = AUTH_DES; + auth->ah_ops = authdes_ops(); + auth->ah_private = (caddr_t)ad; + + if (!authdes_refresh(auth, NULL)) { + goto failed; + } + ad->ad_nis_srvr = NULL; /* not needed any longer */ + return (auth); + +failed: + if (auth) + FREE(auth, sizeof (AUTH)); + if (ad) { + if (ad->ad_fullname) + FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); + if (ad->ad_servername) + FREE(ad->ad_servername, ad->ad_servernamelen + 1); + if (ad->ad_timehost) + FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1); + if (ad->ad_netid) + FREE(ad->ad_netid, strlen(ad->ad_netid) + 1); + if (ad->ad_uaddr) + FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1); + FREE(ad, sizeof (struct ad_private)); + } return (NULL); } -__sym_compat(authdes_pk_seccreate, __authdes_pk_seccreate, FBSD_1.0); + +/* + * Implement the five authentication operations + */ + + +/* + * 1. Next Verifier + */ +/*ARGSUSED*/ +static void +authdes_nextverf(AUTH *auth __unused) +{ + /* what the heck am I supposed to do??? */ +} + + +/* + * 2. Marshal + */ +static bool_t +authdes_marshal(AUTH *auth, XDR *xdrs) +{ +/* LINTED pointer alignment */ + struct ad_private *ad = AUTH_PRIVATE(auth); + struct authdes_cred *cred = &ad->ad_cred; + struct authdes_verf *verf = &ad->ad_verf; + des_block cryptbuf[2]; + des_block ivec; + int status; + int len; + rpc_inline_t *ixdr; + + /* + * Figure out the "time", accounting for any time difference + * with the server if necessary. + */ + (void)gettimeofday(&ad->ad_timestamp, NULL); + ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec; + ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec; + while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) { + ad->ad_timestamp.tv_usec -= USEC_PER_SEC; + ad->ad_timestamp.tv_sec++; + } + + /* + * XDR the timestamp and possibly some other things, then + * encrypt them. + */ + ixdr = (rpc_inline_t *)cryptbuf; + IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec); + IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec); + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { + IXDR_PUT_U_INT32(ixdr, ad->ad_window); + IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1); + ivec.key.high = ivec.key.low = 0; + status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf, + (u_int) 2 * sizeof (des_block), + DES_ENCRYPT | DES_HW, (char *)&ivec); + } else { + status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf, + (u_int) sizeof (des_block), + DES_ENCRYPT | DES_HW); + } + if (DES_FAILED(status)) { + syslog(LOG_ERR, "authdes_marshal: DES encryption failure"); + return (FALSE); + } + ad->ad_verf.adv_xtimestamp = cryptbuf[0]; + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { + ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; + ad->ad_verf.adv_winverf = cryptbuf[1].key.low; + } else { + ad->ad_cred.adc_nickname = ad->ad_nickname; + ad->ad_verf.adv_winverf = 0; + } + + /* + * Serialize the credential and verifier into opaque + * authentication data. + */ + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { + len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); + } else { + len = (1 + 1)*BYTES_PER_XDR_UNIT; + } + + if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { + IXDR_PUT_INT32(ixdr, AUTH_DES); + IXDR_PUT_INT32(ixdr, len); + } else { + ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor)); + ATTEMPT(xdr_putint32(xdrs, &len)); + } + ATTEMPT(xdr_authdes_cred(xdrs, cred)); + + len = (2 + 1)*BYTES_PER_XDR_UNIT; + if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { + IXDR_PUT_INT32(ixdr, AUTH_DES); + IXDR_PUT_INT32(ixdr, len); + } else { + ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor)); + ATTEMPT(xdr_putint32(xdrs, &len)); + } + ATTEMPT(xdr_authdes_verf(xdrs, verf)); + return (TRUE); +} + + +/* + * 3. Validate + */ +static bool_t +authdes_validate(AUTH *auth, struct opaque_auth *rverf) +{ +/* LINTED pointer alignment */ + struct ad_private *ad = AUTH_PRIVATE(auth); + struct authdes_verf verf; + int status; + uint32_t *ixdr; + des_block buf; + + if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) { + return (FALSE); + } +/* LINTED pointer alignment */ + ixdr = (uint32_t *)rverf->oa_base; + buf.key.high = (uint32_t)*ixdr++; + buf.key.low = (uint32_t)*ixdr++; + verf.adv_int_u = (uint32_t)*ixdr++; + + /* + * Decrypt the timestamp + */ + status = ecb_crypt((char *)&auth->ah_key, (char *)&buf, + (u_int)sizeof (des_block), DES_DECRYPT | DES_HW); + + if (DES_FAILED(status)) { + syslog(LOG_ERR, "authdes_validate: DES decryption failure"); + return (FALSE); + } + + /* + * xdr the decrypted timestamp + */ +/* LINTED pointer alignment */ + ixdr = (uint32_t *)buf.c; + verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1; + verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr); + + /* + * validate + */ + if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp, + sizeof(struct timeval)) != 0) { + syslog(LOG_DEBUG, "authdes_validate: verifier mismatch"); + return (FALSE); + } + + /* + * We have a nickname now, let's use it + */ + ad->ad_nickname = verf.adv_nickname; + ad->ad_cred.adc_namekind = ADN_NICKNAME; + return (TRUE); +} + +/* + * 4. Refresh + */ +/*ARGSUSED*/ +static bool_t +authdes_refresh(AUTH *auth, void *dummy __unused) +{ +/* LINTED pointer alignment */ + struct ad_private *ad = AUTH_PRIVATE(auth); + struct authdes_cred *cred = &ad->ad_cred; + int ok; + netobj pkey; + + if (ad->ad_dosync) { + ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr, + ad->ad_timehost, &(ad->ad_uaddr), + &(ad->ad_netid)); + if (! ok) { + /* + * Hope the clocks are synced! + */ + ad->ad_dosync = 0; + syslog(LOG_DEBUG, + "authdes_refresh: unable to synchronize clock"); + } + } + ad->ad_xkey = auth->ah_key; + pkey.n_bytes = (char *)(ad->ad_pkey); + pkey.n_len = (u_int)strlen((char *)ad->ad_pkey) + 1; + if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) { + syslog(LOG_INFO, + "authdes_refresh: keyserv(1m) is unable to encrypt session key"); + return (FALSE); + } + cred->adc_fullname.key = ad->ad_xkey; + cred->adc_namekind = ADN_FULLNAME; + cred->adc_fullname.name = ad->ad_fullname; + return (TRUE); +} + + +/* + * 5. Destroy + */ +static void +authdes_destroy(AUTH *auth) +{ +/* LINTED pointer alignment */ + struct ad_private *ad = AUTH_PRIVATE(auth); + + FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); + FREE(ad->ad_servername, ad->ad_servernamelen + 1); + if (ad->ad_timehost) + FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1); + if (ad->ad_netid) + FREE(ad->ad_netid, strlen(ad->ad_netid) + 1); + if (ad->ad_uaddr) + FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1); + FREE(ad, sizeof (struct ad_private)); + FREE(auth, sizeof(AUTH)); +} + +static struct auth_ops * +authdes_ops(void) +{ + static struct auth_ops ops; + + /* VARIABLES PROTECTED BY ops_lock: ops */ + + mutex_lock(&authdes_ops_lock); + if (ops.ah_nextverf == NULL) { + ops.ah_nextverf = authdes_nextverf; + ops.ah_marshal = authdes_marshal; + ops.ah_validate = authdes_validate; + ops.ah_refresh = authdes_refresh; + ops.ah_destroy = authdes_destroy; + } + mutex_unlock(&authdes_ops_lock); + return (&ops); +} diff --git a/lib/libc/rpc/authdes_prot.c b/lib/libc/rpc/authdes_prot.c index 56b44daafe41..79a0e5baa084 100644 --- a/lib/libc/rpc/authdes_prot.c +++ b/lib/libc/rpc/authdes_prot.c @@ -42,16 +42,44 @@ #include <rpc/auth_des.h> #include "un-namespace.h" -static bool_t -__xdr_authdes_cred(XDR *xdrs, void *cred) +#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) + +bool_t +xdr_authdes_cred(XDR *xdrs, struct authdes_cred *cred) { - return (FALSE); + enum authdes_namekind *padc_namekind = &cred->adc_namekind; + /* + * Unrolled xdr + */ + ATTEMPT(xdr_enum(xdrs, (enum_t *) padc_namekind)); + switch (cred->adc_namekind) { + case ADN_FULLNAME: + ATTEMPT(xdr_string(xdrs, &cred->adc_fullname.name, + MAXNETNAMELEN)); + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.key, + sizeof(des_block))); + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.window, + sizeof(cred->adc_fullname.window))); + return (TRUE); + case ADN_NICKNAME: + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname, + sizeof(cred->adc_nickname))); + return (TRUE); + default: + return (FALSE); + } } -__sym_compat(xdr_authdes_cred, __xdr_authdes_cred, FBSD_1.0); -static bool_t -__xdr_authdes_verf(XDR *xdrs, void *verf) + +bool_t +xdr_authdes_verf(XDR *xdrs, struct authdes_verf *verf) { - return (FALSE); + /* + * Unrolled xdr + */ + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp, + sizeof(des_block))); + ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u, + sizeof(verf->adv_int_u))); + return (TRUE); } -__sym_compat(xdr_authdes_verf, __xdr_authdes_verf, FBSD_1.0); diff --git a/lib/libc/rpc/key_call.c b/lib/libc/rpc/key_call.c index eb274fcfff36..5c87881c815c 100644 --- a/lib/libc/rpc/key_call.c +++ b/lib/libc/rpc/key_call.c @@ -32,78 +32,426 @@ */ /* - * Secure RPC keyserver support was removed in FreeBSD 15.0. - * These symbols are provided for backward compatibility, but provide no - * functionality and will always return an error. + * key_call.c, Interface to keyserver + * + * setsecretkey(key) - set your secret key + * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent + * decryptsessionkey(agent, deskey) - decrypt ditto + * gendeskey(deskey) - generate a secure des key */ #include "namespace.h" #include "reentrant.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> #include <rpc/rpc.h> -#include <rpc/key_prot.h> #include <rpc/auth.h> +#include <rpc/auth_unix.h> +#include <rpc/key_prot.h> +#include <string.h> +#include <netconfig.h> +#include <sys/utsname.h> +#include <stdlib.h> +#include <signal.h> +#include <sys/wait.h> +#include <sys/fcntl.h> #include "un-namespace.h" #include "mt_misc.h" -static int -__key_setsecret(const char *secretkey) + +#define KEY_TIMEOUT 5 /* per-try timeout in seconds */ +#define KEY_NRETRY 12 /* number of retries */ + +#ifdef DEBUG +#define debug(msg) (void) fprintf(stderr, "%s\n", msg); +#else +#define debug(msg) +#endif /* DEBUG */ + +/* + * Hack to allow the keyserver to use AUTH_DES (for authenticated + * NIS+ calls, for example). The only functions that get called + * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. + * + * The approach is to have the keyserver fill in pointers to local + * implementations of these functions, and to call those in key_call(). + */ + +cryptkeyres *(*__key_encryptsession_pk_LOCAL)(uid_t, void *arg) = 0; +cryptkeyres *(*__key_decryptsession_pk_LOCAL)(uid_t, void *arg) = 0; +des_block *(*__key_gendes_LOCAL)(uid_t, void *) = 0; + +static int key_call( u_long, xdrproc_t, void *, xdrproc_t, void *); + +int +key_setsecret(const char *secretkey) { - return (-1); + keystatus status; + + if (!key_call((u_long) KEY_SET, (xdrproc_t)xdr_keybuf, + (void *)secretkey, + (xdrproc_t)xdr_keystatus, &status)) { + return (-1); + } + if (status != KEY_SUCCESS) { + debug("set status is nonzero"); + return (-1); + } + return (0); } -__sym_compat(key_setsecret, __key_setsecret, FBSD_1.0); -static int -__key_secretkey_is_set(void) + +/* key_secretkey_is_set() returns 1 if the keyserver has a secret key + * stored for the caller's effective uid; it returns 0 otherwise + * + * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't + * be using it, because it allows them to get the user's secret key. + */ + +int +key_secretkey_is_set(void) { + struct key_netstres kres; + + memset((void*)&kres, 0, sizeof (kres)); + if (key_call((u_long) KEY_NET_GET, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_key_netstres, &kres) && + (kres.status == KEY_SUCCESS) && + (kres.key_netstres_u.knet.st_priv_key[0] != 0)) { + /* avoid leaving secret key in memory */ + memset(kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES); + return (1); + } return (0); } -__sym_compat(key_secretkey_is_set, __key_secretkey_is_set, FBSD_1.0); -static int -__key_encryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) +int +key_encryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) { - return (-1); + cryptkeyarg2 arg; + cryptkeyres res; + + arg.remotename = remotename; + arg.remotekey = *remotekey; + arg.deskey = *deskey; + if (!key_call((u_long)KEY_ENCRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg, + (xdrproc_t)xdr_cryptkeyres, &res)) { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("encrypt status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); } -__sym_compat(key_encryptsession_pk, __key_encryptsession_pk, FBSD_1.0); -static int -__key_decryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) +int +key_decryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) { - return (-1); + cryptkeyarg2 arg; + cryptkeyres res; + + arg.remotename = remotename; + arg.remotekey = *remotekey; + arg.deskey = *deskey; + if (!key_call((u_long)KEY_DECRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg, + (xdrproc_t)xdr_cryptkeyres, &res)) { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("decrypt status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); } -__sym_compat(key_decryptsession_pk, __key_decryptsession_pk, FBSD_1.0); -static int -__key_encryptsession(const char *remotename, des_block *deskey) +int +key_encryptsession(const char *remotename, des_block *deskey) { - return (-1); + cryptkeyarg arg; + cryptkeyres res; + + arg.remotename = (char *) remotename; + arg.deskey = *deskey; + if (!key_call((u_long)KEY_ENCRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg, + (xdrproc_t)xdr_cryptkeyres, &res)) { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("encrypt status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); } -__sym_compat(key_encryptsession, __key_encryptsession, FBSD_1.0); -static int -__key_decryptsession(const char *remotename, des_block *deskey) +int +key_decryptsession(const char *remotename, des_block *deskey) { - return (-1); + cryptkeyarg arg; + cryptkeyres res; + + arg.remotename = (char *) remotename; + arg.deskey = *deskey; + if (!key_call((u_long)KEY_DECRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg, + (xdrproc_t)xdr_cryptkeyres, &res)) { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("decrypt status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); } -__sym_compat(key_decryptsession, __key_decryptsession, FBSD_1.0); -static int -__key_gendes(des_block *key) +int +key_gendes(des_block *key) { - return (-1); + if (!key_call((u_long)KEY_GEN, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_des_block, key)) { + return (-1); + } + return (0); } -__sym_compat(key_gendes, __key_gendes, FBSD_1.0); -static int -__key_setnet(struct key_netstarg *arg) +int +key_setnet(struct key_netstarg *arg) { - return (-1); + keystatus status; + + + if (!key_call((u_long) KEY_NET_PUT, (xdrproc_t)xdr_key_netstarg, arg, + (xdrproc_t)xdr_keystatus, &status)){ + return (-1); + } + + if (status != KEY_SUCCESS) { + debug("key_setnet status is nonzero"); + return (-1); + } + return (1); +} + + +int +key_get_conv(char *pkey, des_block *deskey) +{ + cryptkeyres res; + + if (!key_call((u_long) KEY_GET_CONV, (xdrproc_t)xdr_keybuf, pkey, + (xdrproc_t)xdr_cryptkeyres, &res)) { + return (-1); + } + if (res.status != KEY_SUCCESS) { + debug("get_conv status is nonzero"); + return (-1); + } + *deskey = res.cryptkeyres_u.deskey; + return (0); +} + +struct key_call_private { + CLIENT *client; /* Client handle */ + pid_t pid; /* process-id at moment of creation */ + uid_t uid; /* user-id at last authorization */ +}; +static struct key_call_private *key_call_private_main = NULL; +static thread_key_t key_call_key; +static once_t key_call_once = ONCE_INITIALIZER; +static int key_call_key_error; + +static void +key_call_destroy(void *vp) +{ + struct key_call_private *kcp = (struct key_call_private *)vp; + + if (kcp) { + if (kcp->client) + clnt_destroy(kcp->client); + free(kcp); + } +} + +static void +key_call_init(void) +{ + + key_call_key_error = thr_keycreate(&key_call_key, key_call_destroy); } -__sym_compat(key_setnet, __key_setnet, FBSD_1.0); + +/* + * Keep the handle cached. This call may be made quite often. + */ +static CLIENT * +getkeyserv_handle(int vers) +{ + void *localhandle; + struct netconfig *nconf; + struct netconfig *tpconf; + struct key_call_private *kcp; + struct timeval wait_time; + struct utsname u; + int main_thread; + int fd; + +#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */ +#define TOTAL_TRIES 5 /* Number of tries */ + + if ((main_thread = thr_main())) { + kcp = key_call_private_main; + } else { + if (thr_once(&key_call_once, key_call_init) != 0 || + key_call_key_error != 0) + return ((CLIENT *) NULL); + kcp = (struct key_call_private *)thr_getspecific(key_call_key); + } + if (kcp == (struct key_call_private *)NULL) { + kcp = (struct key_call_private *)malloc(sizeof (*kcp)); + if (kcp == (struct key_call_private *)NULL) { + return ((CLIENT *) NULL); + } + if (main_thread) + key_call_private_main = kcp; + else + thr_setspecific(key_call_key, (void *) kcp); + kcp->client = NULL; + } + + /* if pid has changed, destroy client and rebuild */ + if (kcp->client != NULL && kcp->pid != getpid()) { + clnt_destroy(kcp->client); + kcp->client = NULL; + } + + if (kcp->client != NULL) { + /* if uid has changed, build client handle again */ + if (kcp->uid != geteuid()) { + kcp->uid = geteuid(); + auth_destroy(kcp->client->cl_auth); + kcp->client->cl_auth = + authsys_create("", kcp->uid, 0, 0, NULL); + if (kcp->client->cl_auth == NULL) { + clnt_destroy(kcp->client); + kcp->client = NULL; + return ((CLIENT *) NULL); + } + } + /* Change the version number to the new one */ + clnt_control(kcp->client, CLSET_VERS, (void *)&vers); + return (kcp->client); + } + if (!(localhandle = setnetconfig())) { + return ((CLIENT *) NULL); + } + tpconf = NULL; +#if defined(__FreeBSD__) + if (uname(&u) == -1) +#else +#if defined(i386) + if (_nuname(&u) == -1) +#elif defined(sparc) + if (_uname(&u) == -1) +#else +#error Unknown architecture! +#endif +#endif + { + endnetconfig(localhandle); + return ((CLIENT *) NULL); + } + while ((nconf = getnetconfig(localhandle)) != NULL) { + if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { + /* + * We use COTS_ORD here so that the caller can + * find out immediately if the server is dead. + */ + if (nconf->nc_semantics == NC_TPI_COTS_ORD) { + kcp->client = clnt_tp_create(u.nodename, + KEY_PROG, vers, nconf); + if (kcp->client) + break; + } else { + tpconf = nconf; + } + } + } + if ((kcp->client == (CLIENT *) NULL) && (tpconf)) + /* Now, try the CLTS or COTS loopback transport */ + kcp->client = clnt_tp_create(u.nodename, + KEY_PROG, vers, tpconf); + endnetconfig(localhandle); + + if (kcp->client == (CLIENT *) NULL) { + return ((CLIENT *) NULL); + } + kcp->uid = geteuid(); + kcp->pid = getpid(); + kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL); + if (kcp->client->cl_auth == NULL) { + clnt_destroy(kcp->client); + kcp->client = NULL; + return ((CLIENT *) NULL); + } + + wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES; + wait_time.tv_usec = 0; + (void) clnt_control(kcp->client, CLSET_RETRY_TIMEOUT, + (char *)&wait_time); + if (clnt_control(kcp->client, CLGET_FD, (char *)&fd)) + _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */ + + return (kcp->client); +} + +/* returns 0 on failure, 1 on success */ static int -__key_get_conv(char *pkey, des_block *deskey) +key_call(u_long proc, xdrproc_t xdr_arg, void *arg, xdrproc_t xdr_rslt, + void *rslt) { - return (-1); + CLIENT *clnt; + struct timeval wait_time; + + if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) { + cryptkeyres *res; + res = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg); + *(cryptkeyres*)rslt = *res; + return (1); + } else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) { + cryptkeyres *res; + res = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg); + *(cryptkeyres*)rslt = *res; + return (1); + } else if (proc == KEY_GEN && __key_gendes_LOCAL) { + des_block *res; + res = (*__key_gendes_LOCAL)(geteuid(), 0); + *(des_block*)rslt = *res; + return (1); + } + + if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || + (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || + (proc == KEY_GET_CONV)) + clnt = getkeyserv_handle(2); /* talk to version 2 */ + else + clnt = getkeyserv_handle(1); /* talk to version 1 */ + + if (clnt == NULL) { + return (0); + } + + wait_time.tv_sec = TOTAL_TIMEOUT; + wait_time.tv_usec = 0; + + if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt, + wait_time) == RPC_SUCCESS) { + return (1); + } else { + return (0); + } } -__sym_compat(key_get_conv, __key_get_conv, FBSD_1.0); diff --git a/lib/libc/rpc/publickey.5 b/lib/libc/rpc/publickey.5 new file mode 100644 index 000000000000..db95c4617b50 --- /dev/null +++ b/lib/libc/rpc/publickey.5 @@ -0,0 +1,40 @@ +.Dd October 19, 1987 +.Dt PUBLICKEY 5 +.Os +.Sh NAME +.Nm publickey +.Nd "public key database" +.Sh SYNOPSIS +.Pa /etc/publickey +.Sh DESCRIPTION +.Pa /etc/publickey +is the public key database used for secure +RPC (Remote Procedure Calls). +Each entry in +the database consists of a network user +name (which may either refer to +a user or a hostname), followed by the user's +public key (in hex +notation), a colon, and then the user's +secret key encrypted with +its login password (also in hex notation). +.Pp +This file is altered either by the user through the +.Xr chkey 1 +command or by the system administrator through the +.Xr newkey 8 +command. +The file +.Pa /etc/publickey +should only contain data on the +.Tn NIS +master machine, where it +is converted into the +.Tn NIS +database +.Pa publickey.byname . +.Sh SEE ALSO +.Xr chkey 1 , +.Xr publickey 3 , +.Xr newkey 8 , +.Xr ypupdated 8 diff --git a/lib/libc/rpc/rpc_generic.c b/lib/libc/rpc/rpc_generic.c index 0e563f6a5996..8019f2d8f236 100644 --- a/lib/libc/rpc/rpc_generic.c +++ b/lib/libc/rpc/rpc_generic.c @@ -610,6 +610,10 @@ __rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf) return NULL; break; #endif + case AF_NETLINK: + if (asprintf(&ret, "%s", (char *)nbuf->buf) < 0) + return NULL; + break; case AF_LOCAL: sun = nbuf->buf; if (asprintf(&ret, "%.*s", (int)(sun->sun_len - diff --git a/lib/libc/rpc/rpc_secure.3 b/lib/libc/rpc/rpc_secure.3 index ca99b06b556d..ce59bba7115f 100644 --- a/lib/libc/rpc/rpc_secure.3 +++ b/lib/libc/rpc/rpc_secure.3 @@ -1,17 +1,34 @@ .\" -.Dd August 10, 2025 -.Dt RPC_SECURE 3 +.Dd February 16, 1988 +.Dt RPC 3 .Os .Sh NAME .Nm rpc_secure .Nd library routines for secure remote procedure calls .Sh SYNOPSIS .In rpc/rpc.h +.Ft AUTH * +.Fo authdes_create +.Fa "char *name" +.Fa "unsigned window" +.Fa "struct sockaddr *addr" +.Fa "des_block *ckey" +.Fc +.Ft int +.Fn authdes_getucred "struct authdes_cred *adc" "uid_t *uid" "gid_t *gid" "int *grouplen" "gid_t *groups" .Ft int .Fn getnetname "char *name" .Ft int .Fn host2netname "char *name" "const char *host" "const char *domain" .Ft int +.Fn key_decryptsession "const char *remotename" "des_block *deskey" +.Ft int +.Fn key_encryptsession "const char *remotename" "des_block *deskey" +.Ft int +.Fn key_gendes "des_block *deskey" +.Ft int +.Fn key_setsecret "const char *key" +.Ft int .Fn netname2host "char *name" "char *host" "int hostlen" .Ft int .Fn netname2user "char *name" "uid_t *uidp" "gid_t *gidp" "int *gidlenp" "gid_t *gidlist" @@ -21,11 +38,101 @@ These routines are part of the .Tn RPC library. +They implement +.Tn DES +Authentication. See .Xr rpc 3 for further details about .Tn RPC . .Pp +The +.Fn authdes_create +is the first of two routines which interface to the +.Tn RPC +secure authentication system, known as +.Tn DES +authentication. +The second is +.Fn authdes_getucred , +below. +.Pp +Note: the keyserver daemon +.Xr keyserv 8 +must be running for the +.Tn DES +authentication system to work. +.Pp +The +.Fn authdes_create +function, +used on the client side, returns an authentication handle that +will enable the use of the secure authentication system. +The first argument +.Fa name +is the network name, or +.Fa netname , +of the owner of the server process. +This field usually +represents a +.Fa hostname +derived from the utility routine +.Fn host2netname , +but could also represent a user name using +.Fn user2netname . +The second field is window on the validity of +the client credential, given in seconds. +A small +window is more secure than a large one, but choosing +too small of a window will increase the frequency of +resynchronizations because of clock drift. +The third +argument +.Fa addr +is optional. +If it is +.Dv NULL , +then the authentication system will assume +that the local clock is always in sync with the server's +clock, and will not attempt resynchronizations. +If an address +is supplied, however, then the system will use the address +for consulting the remote time service whenever +resynchronization +is required. +This argument is usually the +address of the +.Tn RPC +server itself. +The final argument +.Fa ckey +is also optional. +If it is +.Dv NULL , +then the authentication system will +generate a random +.Tn DES +key to be used for the encryption of credentials. +If it is supplied, however, then it will be used instead. +.Pp +The +.Fn authdes_getucred +function, +the second of the two +.Tn DES +authentication routines, +is used on the server side for converting a +.Tn DES +credential, which is +operating system independent, into a +.Ux +credential. +This routine differs from utility routine +.Fn netname2user +in that +.Fn authdes_getucred +pulls its information from a cache, and does not have to do a +Yellow Pages lookup every time it is called to get its information. .Pp The .Fn getnetname @@ -54,6 +161,72 @@ Inverse of .Fn netname2host . .Pp The +.Fn key_decryptsession +function +is an interface to the keyserver daemon, which is associated +with +.Tn RPC Ns 's +secure authentication system +.Tn ( DES +authentication). +User programs rarely need to call it, or its associated routines +.Fn key_encryptsession , +.Fn key_gendes +and +.Fn key_setsecret . +System commands such as +.Xr login 1 +and the +.Tn RPC +library are the main clients of these four routines. +.Pp +The +.Fn key_decryptsession +function +takes a server netname and a +.Tn DES +key, and decrypts the key by +using the public key of the server and the secret key +associated with the effective uid of the calling process. +It +is the inverse of +.Fn key_encryptsession . +.Pp +The +.Fn key_encryptsession +function +is a keyserver interface routine. +It +takes a server netname and a des key, and encrypts +it using the public key of the server and the secret key +associated with the effective uid of the calling process. +It +is the inverse of +.Fn key_decryptsession . +.Pp +The +.Fn key_gendes +function +is a keyserver interface routine. +It +is used to ask the keyserver for a secure conversation key. +Choosing one +.Qq random +is usually not good enough, +because +the common ways of choosing random numbers, such as using the +current time, are very easy to guess. +.Pp +The +.Fn key_setsecret +function +is a keyserver interface routine. +It is used to set the key for +the effective +.Fa uid +of the calling process. +.Pp +The .Fn netname2host function converts from an operating-system independent netname to a diff --git a/lib/libc/rpc/rpc_soc.3 b/lib/libc/rpc/rpc_soc.3 index e6fd8a0da6e4..4abd4b14c475 100644 --- a/lib/libc/rpc/rpc_soc.3 +++ b/lib/libc/rpc/rpc_soc.3 @@ -1,6 +1,6 @@ .\" $NetBSD: rpc_soc.3,v 1.2 2000/06/07 13:39:43 simonb Exp $ .\" -.Dd August 10, 2025 +.Dd February 16, 1988 .Dt RPC_SOC 3 .Os .Sh NAME @@ -100,6 +100,16 @@ to perform the requested service, and then sends back a reply. Finally, the procedure call returns to the client. .Pp +Routines that are used for Secure +.Tn RPC ( DES +authentication) are described in +.Xr rpc_secure 3 . +Secure +.Tn RPC +can be used only if +.Tn DES +encryption is available. +.Pp .Bl -tag -width indent -compact .It Xo .Ft void @@ -1691,6 +1701,7 @@ This routine modifies the global variable Service implementors usually do not need this routine. .El .Sh SEE ALSO +.Xr rpc_secure 3 , .Xr xdr 3 .Rs .%T "Remote Procedure Calls: Protocol Specification" diff --git a/lib/libc/rpc/rpc_soc.c b/lib/libc/rpc/rpc_soc.c index e293a2ccf22f..c63b89594ce6 100644 --- a/lib/libc/rpc/rpc_soc.c +++ b/lib/libc/rpc/rpc_soc.c @@ -379,13 +379,36 @@ clnt_broadcast(u_long prog, u_long vers, u_long proc, xdrproc_t xargs, * Create the client des authentication object. Obsoleted by * authdes_seccreate(). */ -static AUTH * -__authdes_create(char *servername, u_int window, struct sockaddr *syncaddr, +AUTH * +authdes_create(char *servername, u_int window, struct sockaddr *syncaddr, des_block *ckey) +/* + * char *servername; // network name of server + * u_int window; // time to live + * struct sockaddr *syncaddr; // optional hostaddr to sync with + * des_block *ckey; // optional conversation key to use + */ { - return (NULL); + AUTH *dummy; + AUTH *nauth; + char hostname[NI_MAXHOST]; + + if (syncaddr) { + /* + * Change addr to hostname, because that is the way + * new interface takes it. + */ + if (getnameinfo(syncaddr, syncaddr->sa_len, hostname, + sizeof hostname, NULL, 0, 0) != 0) + goto fallback; + + nauth = authdes_seccreate(servername, window, hostname, ckey); + return (nauth); + } +fallback: + dummy = authdes_seccreate(servername, window, NULL, ckey); + return (dummy); } -__sym_compat(authdes_create, __authdes_create, FBSD_1.0); /* * Create a client handle for a unix connection. Obsoleted by clnt_vc_create() diff --git a/lib/libc/rpc/svc_auth.c b/lib/libc/rpc/svc_auth.c index b8a9a8f33ebb..eb61171733d6 100644 --- a/lib/libc/rpc/svc_auth.c +++ b/lib/libc/rpc/svc_auth.c @@ -114,6 +114,11 @@ _authenticate(struct svc_req *rqst, struct rpc_msg *msg) case AUTH_SHORT: dummy = _svcauth_short(rqst, msg); return (dummy); +#ifdef DES_BUILTIN + case AUTH_DES: + dummy = _svcauth_des(rqst, msg); + return (dummy); +#endif default: break; } @@ -181,6 +186,9 @@ svc_auth_reg(int cred_flavor, case AUTH_NULL: case AUTH_SYS: case AUTH_SHORT: +#ifdef DES_BUILTIN + case AUTH_DES: +#endif /* already registered */ return (1); diff --git a/lib/libc/rpc/svc_auth_des.c b/lib/libc/rpc/svc_auth_des.c index 8fde5512e53f..d4736cc851e8 100644 --- a/lib/libc/rpc/svc_auth_des.c +++ b/lib/libc/rpc/svc_auth_des.c @@ -34,8 +34,17 @@ */ /* - * svcauth_des.c, server-side des authentication. - * This functionality was removed in FreeBSD 15.0. + * svcauth_des.c, server-side des authentication + * + * We insure for the service the following: + * (1) The timestamp microseconds do not exceed 1 million. + * (2) The timestamp plus the window is less than the current time. + * (3) The timestamp is not less than the one previously + * seen in the current session. + * + * It is up to the server to determine if the window size is + * too small . + * */ #include "namespace.h" @@ -56,27 +65,458 @@ #include <rpc/svc_auth.h> #include "libc_private.h" +extern int key_decryptsession_pk(const char *, netobj *, des_block *); + +#define debug(msg) printf("svcauth_des: %s\n", msg) + +#define USEC_PER_SEC ((u_long) 1000000L) +#define BEFORE(t1, t2) timercmp(t1, t2, <) + +/* + * LRU cache of conversation keys and some other useful items. + */ +#define AUTHDES_CACHESZ 64 +struct cache_entry { + des_block key; /* conversation key */ + char *rname; /* client's name */ + u_int window; /* credential lifetime window */ + struct timeval laststamp; /* detect replays of creds */ + char *localcred; /* generic local credential */ +}; +static struct cache_entry *authdes_cache/* [AUTHDES_CACHESZ] */; +static short *authdes_lru/* [AUTHDES_CACHESZ] */; + +static void cache_init(void); /* initialize the cache */ +static short cache_spot(des_block *, char *, struct timeval *); /* find an entry in the cache */ +static void cache_ref(short sid); /* note that sid was ref'd */ + +static void invalidate(char *); /* invalidate entry in cache */ + +/* + * cache statistics + */ +static struct { + u_long ncachehits; /* times cache hit, and is not replay */ + u_long ncachereplays; /* times cache hit, and is replay */ + u_long ncachemisses; /* times cache missed */ +} svcauthdes_stats; + /* * Service side authenticator for AUTH_DES */ -static enum auth_stat -__svcauth_des(struct svc_req *rqst, struct rpc_msg *msg) +enum auth_stat +_svcauth_des(struct svc_req *rqst, struct rpc_msg *msg) { - return (AUTH_FAILED); + + long *ixdr; + des_block cryptbuf[2]; + struct authdes_cred *cred; + struct authdes_verf verf; + int status; + struct cache_entry *entry; + short sid = 0; + des_block *sessionkey; + des_block ivec; + u_int window; + struct timeval timestamp; + u_long namelen; + struct area { + struct authdes_cred area_cred; + char area_netname[MAXNETNAMELEN+1]; + } *area; + + if (authdes_cache == NULL) { + cache_init(); + } + + area = (struct area *)rqst->rq_clntcred; + cred = (struct authdes_cred *)&area->area_cred; + + /* + * Get the credential + */ + ixdr = (long *)msg->rm_call.cb_cred.oa_base; + cred->adc_namekind = IXDR_GET_ENUM(ixdr, enum authdes_namekind); + switch (cred->adc_namekind) { + case ADN_FULLNAME: + namelen = IXDR_GET_U_LONG(ixdr); + if (namelen > MAXNETNAMELEN) { + return (AUTH_BADCRED); + } + cred->adc_fullname.name = area->area_netname; + bcopy((char *)ixdr, cred->adc_fullname.name, + (u_int)namelen); + cred->adc_fullname.name[namelen] = 0; + ixdr += (RNDUP(namelen) / BYTES_PER_XDR_UNIT); + cred->adc_fullname.key.key.high = (u_long)*ixdr++; + cred->adc_fullname.key.key.low = (u_long)*ixdr++; + cred->adc_fullname.window = (u_long)*ixdr++; + break; + case ADN_NICKNAME: + cred->adc_nickname = (u_long)*ixdr++; + break; + default: + return (AUTH_BADCRED); + } + + /* + * Get the verifier + */ + ixdr = (long *)msg->rm_call.cb_verf.oa_base; + verf.adv_xtimestamp.key.high = (u_long)*ixdr++; + verf.adv_xtimestamp.key.low = (u_long)*ixdr++; + verf.adv_int_u = (u_long)*ixdr++; + + + /* + * Get the conversation key + */ + if (cred->adc_namekind == ADN_FULLNAME) { + netobj pkey; + char pkey_data[1024]; + + sessionkey = &cred->adc_fullname.key; + if (! getpublickey(cred->adc_fullname.name, pkey_data)) { + debug("getpublickey"); + return(AUTH_BADCRED); + } + pkey.n_bytes = pkey_data; + pkey.n_len = strlen(pkey_data) + 1; + if (key_decryptsession_pk(cred->adc_fullname.name, &pkey, + sessionkey) < 0) { + debug("decryptsessionkey"); + return (AUTH_BADCRED); /* key not found */ + } + } else { /* ADN_NICKNAME */ + sid = (short)cred->adc_nickname; + if (sid < 0 || sid >= AUTHDES_CACHESZ) { + debug("bad nickname"); + return (AUTH_BADCRED); /* garbled credential */ + } + sessionkey = &authdes_cache[sid].key; + } + + + /* + * Decrypt the timestamp + */ + cryptbuf[0] = verf.adv_xtimestamp; + if (cred->adc_namekind == ADN_FULLNAME) { + cryptbuf[1].key.high = cred->adc_fullname.window; + cryptbuf[1].key.low = verf.adv_winverf; + ivec.key.high = ivec.key.low = 0; + status = cbc_crypt((char *)sessionkey, (char *)cryptbuf, + 2*sizeof(des_block), DES_DECRYPT | DES_HW, + (char *)&ivec); + } else { + status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, + sizeof(des_block), DES_DECRYPT | DES_HW); + } + if (DES_FAILED(status)) { + debug("decryption failure"); + return (AUTH_FAILED); /* system error */ + } + + /* + * XDR the decrypted timestamp + */ + ixdr = (long *)cryptbuf; + timestamp.tv_sec = IXDR_GET_LONG(ixdr); + timestamp.tv_usec = IXDR_GET_LONG(ixdr); + + /* + * Check for valid credentials and verifiers. + * They could be invalid because the key was flushed + * out of the cache, and so a new session should begin. + * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case. + */ + { + struct timeval current; + int nick; + int winverf; + + if (cred->adc_namekind == ADN_FULLNAME) { + window = IXDR_GET_U_LONG(ixdr); + winverf = IXDR_GET_U_LONG(ixdr); + if (winverf != window - 1) { + debug("window verifier mismatch"); + return (AUTH_BADCRED); /* garbled credential */ + } + sid = cache_spot(sessionkey, cred->adc_fullname.name, + ×tamp); + if (sid < 0) { + debug("replayed credential"); + return (AUTH_REJECTEDCRED); /* replay */ + } + nick = 0; + } else { /* ADN_NICKNAME */ + window = authdes_cache[sid].window; + nick = 1; + } + + if ((u_long)timestamp.tv_usec >= USEC_PER_SEC) { + debug("invalid usecs"); + /* cached out (bad key), or garbled verifier */ + return (nick ? AUTH_REJECTEDVERF : AUTH_BADVERF); + } + if (nick && BEFORE(×tamp, + &authdes_cache[sid].laststamp)) { + debug("timestamp before last seen"); + return (AUTH_REJECTEDVERF); /* replay */ + } + (void)gettimeofday(¤t, NULL); + current.tv_sec -= window; /* allow for expiration */ + if (!BEFORE(¤t, ×tamp)) { + debug("timestamp expired"); + /* replay, or garbled credential */ + return (nick ? AUTH_REJECTEDVERF : AUTH_BADCRED); + } + } + + /* + * Set up the reply verifier + */ + verf.adv_nickname = (u_long)sid; + + /* + * xdr the timestamp before encrypting + */ + ixdr = (long *)cryptbuf; + IXDR_PUT_LONG(ixdr, timestamp.tv_sec - 1); + IXDR_PUT_LONG(ixdr, timestamp.tv_usec); + + /* + * encrypt the timestamp + */ + status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, + sizeof(des_block), DES_ENCRYPT | DES_HW); + if (DES_FAILED(status)) { + debug("encryption failure"); + return (AUTH_FAILED); /* system error */ + } + verf.adv_xtimestamp = cryptbuf[0]; + + /* + * Serialize the reply verifier, and update rqst + */ + ixdr = (long *)msg->rm_call.cb_verf.oa_base; + *ixdr++ = (long)verf.adv_xtimestamp.key.high; + *ixdr++ = (long)verf.adv_xtimestamp.key.low; + *ixdr++ = (long)verf.adv_int_u; + + rqst->rq_xprt->xp_verf.oa_flavor = AUTH_DES; + rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base; + rqst->rq_xprt->xp_verf.oa_length = + (char *)ixdr - msg->rm_call.cb_verf.oa_base; + + /* + * We succeeded, commit the data to the cache now and + * finish cooking the credential. + */ + entry = &authdes_cache[sid]; + entry->laststamp = timestamp; + cache_ref(sid); + if (cred->adc_namekind == ADN_FULLNAME) { + cred->adc_fullname.window = window; + cred->adc_nickname = (u_long)sid; /* save nickname */ + if (entry->rname != NULL) { + mem_free(entry->rname, strlen(entry->rname) + 1); + } + entry->rname = (char *)mem_alloc((u_int)strlen(cred->adc_fullname.name) + + 1); + if (entry->rname != NULL) { + (void) strcpy(entry->rname, cred->adc_fullname.name); + } else { + debug("out of memory"); + } + entry->key = *sessionkey; + entry->window = window; + invalidate(entry->localcred); /* mark any cached cred invalid */ + } else { /* ADN_NICKNAME */ + /* + * nicknames are cooked into fullnames + */ + cred->adc_namekind = ADN_FULLNAME; + cred->adc_fullname.name = entry->rname; + cred->adc_fullname.key = entry->key; + cred->adc_fullname.window = entry->window; + } + return (AUTH_OK); /* we made it!*/ } -__sym_compat(_svcauth_des, __svcauth_des, FBSD_1.0); /* + * Initialize the cache + */ +static void +cache_init(void) +{ + int i; + + authdes_cache = (struct cache_entry *) + mem_alloc(sizeof(struct cache_entry) * AUTHDES_CACHESZ); + bzero((char *)authdes_cache, + sizeof(struct cache_entry) * AUTHDES_CACHESZ); + + authdes_lru = (short *)mem_alloc(sizeof(short) * AUTHDES_CACHESZ); + /* + * Initialize the lru list + */ + for (i = 0; i < AUTHDES_CACHESZ; i++) { + authdes_lru[i] = i; + } +} + + +/* + * Find the lru victim + */ +static short +cache_victim(void) +{ + return (authdes_lru[AUTHDES_CACHESZ-1]); +} + +/* + * Note that sid was referenced + */ +static void +cache_ref(short sid) +{ + int i; + short curr; + short prev; + + prev = authdes_lru[0]; + authdes_lru[0] = sid; + for (i = 1; prev != sid; i++) { + curr = authdes_lru[i]; + authdes_lru[i] = prev; + prev = curr; + } +} + + +/* + * Find a spot in the cache for a credential containing + * the items given. Return -1 if a replay is detected, otherwise + * return the spot in the cache. + */ +static short +cache_spot(des_block *key, char *name, struct timeval *timestamp) +{ + struct cache_entry *cp; + int i; + u_long hi; + + hi = key->key.high; + for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; i++, cp++) { + if (cp->key.key.high == hi && + cp->key.key.low == key->key.low && + cp->rname != NULL && + bcmp(cp->rname, name, strlen(name) + 1) == 0) { + if (BEFORE(timestamp, &cp->laststamp)) { + svcauthdes_stats.ncachereplays++; + return (-1); /* replay */ + } + svcauthdes_stats.ncachehits++; + return (i); /* refresh */ + } + } + svcauthdes_stats.ncachemisses++; + return (cache_victim()); /* new credential */ +} + + +#if (defined(sun) || defined(vax) || defined(__FreeBSD__)) +/* + * Local credential handling stuff. + * NOTE: bsd unix dependent. + * Other operating systems should put something else here. + */ +#define UNKNOWN -2 /* grouplen, if cached cred is unknown user */ +#define INVALID -1 /* grouplen, if cache entry is invalid */ + +struct bsdcred { + uid_t uid; /* cached uid */ + gid_t gid; /* cached gid */ + int grouplen; /* length of cached groups */ + gid_t groups[NGRPS]; /* cached groups */ +}; + +/* * Map a des credential into a unix cred. * We cache the credential here so the application does * not have to make an rpc call every time to interpret * the credential. */ -static int -__authdes_getucred(void *adc, uid_t *uid, gid_t *gid, +int +authdes_getucred(struct authdes_cred *adc, uid_t *uid, gid_t *gid, int *grouplen, gid_t *groups) { - return (0); + unsigned sid; + int i; + uid_t i_uid; + gid_t i_gid; + int i_grouplen; + struct bsdcred *cred; + + sid = adc->adc_nickname; + if (sid >= AUTHDES_CACHESZ) { + debug("invalid nickname"); + return (0); + } + cred = (struct bsdcred *)authdes_cache[sid].localcred; + if (cred == NULL) { + cred = (struct bsdcred *)mem_alloc(sizeof(struct bsdcred)); + authdes_cache[sid].localcred = (char *)cred; + cred->grouplen = INVALID; + } + if (cred->grouplen == INVALID) { + /* + * not in cache: lookup + */ + if (!netname2user(adc->adc_fullname.name, &i_uid, &i_gid, + &i_grouplen, groups)) + { + debug("unknown netname"); + cred->grouplen = UNKNOWN; /* mark as lookup up, but not found */ + return (0); + } + debug("missed ucred cache"); + *uid = cred->uid = i_uid; + *gid = cred->gid = i_gid; + *grouplen = cred->grouplen = i_grouplen; + for (i = i_grouplen - 1; i >= 0; i--) { + cred->groups[i] = groups[i]; /* int to short */ + } + return (1); + } else if (cred->grouplen == UNKNOWN) { + /* + * Already lookup up, but no match found + */ + return (0); + } + + /* + * cached credentials + */ + *uid = cred->uid; + *gid = cred->gid; + *grouplen = cred->grouplen; + for (i = cred->grouplen - 1; i >= 0; i--) { + groups[i] = cred->groups[i]; /* short to int */ + } + return (1); +} + +static void +invalidate(char *cred) +{ + if (cred == NULL) { + return; + } + ((struct bsdcred *)cred)->grouplen = INVALID; } -__sym_compat(authdes_getucred, __authdes_getucred, FBSD_1.0); +#endif + diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc index ca199a669be1..e7b9955b9646 100644 --- a/lib/libc/stdlib/Makefile.inc +++ b/lib/libc/stdlib/Makefile.inc @@ -10,7 +10,7 @@ MISRCS+=C99_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \ insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c \ merge.c mergesort_b.c ptsname.c qsort.c qsort_r.c qsort_r_compat.c \ qsort_s.c quick_exit.c radixsort.c rand.c \ - random.c reallocarray.c reallocf.c realpath.c remque.c \ + random.c reallocarray.c reallocf.c realpath.c recallocarray.c remque.c \ set_constraint_handler_s.c strfmon.c strtoimax.c \ strtol.c strtold.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \ strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c @@ -76,6 +76,7 @@ MLINKS+=random.3 initstate.3 \ random.3 srandom.3 \ random.3 srandomdev.3 MLINKS+=radixsort.3 sradixsort.3 +MLINKS+=reallocarray.3 recallocarray.3 MLINKS+=set_constraint_handler_s.3 abort_handler_s.3 MLINKS+=set_constraint_handler_s.3 ignore_handler_s.3 MLINKS+=strfmon.3 strfmon_l.3 diff --git a/lib/libc/stdlib/Symbol.map b/lib/libc/stdlib/Symbol.map index 2b79ca2ece8b..53d71bcafb7d 100644 --- a/lib/libc/stdlib/Symbol.map +++ b/lib/libc/stdlib/Symbol.map @@ -131,6 +131,10 @@ FBSD_1.8 { getenv_r; }; +FBSD_1.9 { + recallocarray; +}; + FBSDprivate_1.0 { __system; _system; diff --git a/lib/libc/stdlib/malloc/jemalloc/Makefile.inc b/lib/libc/stdlib/malloc/jemalloc/Makefile.inc index c10d79dbce6c..7722a7b755f3 100644 --- a/lib/libc/stdlib/malloc/jemalloc/Makefile.inc +++ b/lib/libc/stdlib/malloc/jemalloc/Makefile.inc @@ -1,15 +1,21 @@ .PATH: ${LIBC_SRCTOP}/stdlib/malloc/jemalloc JEMALLOCSRCS:= jemalloc.c arena.c background_thread.c base.c bin.c bitmap.c \ - ckh.c ctl.c div.c extent.c extent_dss.c extent_mmap.c hash.c hook.c \ - large.c log.c malloc_io.c mutex.c mutex_pool.c nstime.c pages.c \ - prng.c prof.c rtree.c safety_check.c sc.c stats.c sz.c tcache.c \ - test_hooks.c ticker.c tsd.c witness.c + ckh.c ctl.c div.c extent.c extent_dss.c extent_mmap.c hook.c \ + large.c log.c malloc_io.c mutex.c nstime.c pages.c \ + prof.c rtree.c safety_check.c sc.c stats.c sz.c tcache.c \ + test_hooks.c ticker.c tsd.c witness.c \ + bin_info.c san.c san_bump.c counter.c prof_data.c prof_log.c prof_recent.c prof_stats.c prof_sys.c \ + emap.c edata.c edata_cache.c pa.c pa_extra.c pac.c decay.c hpa.c hpa_hooks.c fxp.c hpdata.c pai.c \ + ecache.c ehooks.c eset.c sec.c cache_bin.c peak_event.c psset.c inspect.c exp_grow.c thread_event.c \ + buf_writer.c CFLAGS+=-I${SRCTOP}/contrib/jemalloc/include -I${LIBC_SRCTOP}/stdlib/malloc/jemalloc/include .if ${MK_JEMALLOC_LG_VADDR_WIDE} != no CFLAGS+=-D_USE_LG_VADDR_WIDE .endif +CFLAGS.gcc+=-Wno-error=missing-braces + .for src in ${JEMALLOCSRCS} MISRCS+=jemalloc_${src} diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h index 1aedb916976b..900ae867f321 100644 --- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h +++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_internal_defs.h @@ -45,17 +45,17 @@ #define LG_VADDR 48 /* Defined if C11 atomics are available. */ -#define JEMALLOC_C11_ATOMICS 1 +#define JEMALLOC_C11_ATOMICS /* Defined if GCC __atomic atomics are available. */ -#define JEMALLOC_GCC_ATOMIC_ATOMICS 1 +#define JEMALLOC_GCC_ATOMIC_ATOMICS /* and the 8-bit variant support. */ -#define JEMALLOC_GCC_U8_ATOMIC_ATOMICS 1 +#define JEMALLOC_GCC_U8_ATOMIC_ATOMICS /* Defined if GCC __sync atomics are available. */ -#define JEMALLOC_GCC_SYNC_ATOMICS 1 +#define JEMALLOC_GCC_SYNC_ATOMICS /* and the 8-bit variant support. */ -#define JEMALLOC_GCC_U8_SYNC_ATOMICS 1 +#define JEMALLOC_GCC_U8_SYNC_ATOMICS /* * Defined if __builtin_clz() and __builtin_clzl() are available. @@ -73,7 +73,7 @@ /* * Defined if secure_getenv(3) is available. */ -/* #undef JEMALLOC_HAVE_SECURE_GETENV */ +#define JEMALLOC_HAVE_SECURE_GETENV /* * Defined if issetugid(2) is available. @@ -84,17 +84,23 @@ #define JEMALLOC_HAVE_PTHREAD_ATFORK /* Defined if pthread_setname_np(3) is available. */ -/* #undef JEMALLOC_HAVE_PTHREAD_SETNAME_NP */ +#define JEMALLOC_HAVE_PTHREAD_SETNAME_NP + +/* Defined if pthread_getname_np(3) is available. */ +#define JEMALLOC_HAVE_PTHREAD_GETNAME_NP + +/* Defined if pthread_get_name_np(3) is available. */ +#define JEMALLOC_HAVE_PTHREAD_GET_NAME_NP /* * Defined if clock_gettime(CLOCK_MONOTONIC_COARSE, ...) is available. */ -/* #undef JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE */ +#define JEMALLOC_HAVE_CLOCK_MONOTONIC_COARSE /* * Defined if clock_gettime(CLOCK_MONOTONIC, ...) is available. */ -#define JEMALLOC_HAVE_CLOCK_MONOTONIC 1 +#define JEMALLOC_HAVE_CLOCK_MONOTONIC /* * Defined if mach_absolute_time() is available. @@ -102,6 +108,11 @@ /* #undef JEMALLOC_HAVE_MACH_ABSOLUTE_TIME */ /* + * Defined if clock_gettime(CLOCK_REALTIME, ...) is available. + */ +#define JEMALLOC_HAVE_CLOCK_REALTIME + +/* * Defined if _malloc_thread_cleanup() exists. At least in the case of * FreeBSD, pthread_key_create() allocates, which if used during malloc * bootstrapping will cause recursion into the pthreads library. Therefore, if @@ -122,7 +133,7 @@ * _pthread_mutex_init_calloc_cb(), in which case the function is used in order * to avoid recursive allocation during mutex initialization. */ -#define JEMALLOC_MUTEX_INIT_CB 1 +#define JEMALLOC_MUTEX_INIT_CB /* Non-empty if the tls_model attribute is supported. */ #define JEMALLOC_TLS_MODEL __attribute__((tls_model("initial-exec"))) @@ -163,6 +174,9 @@ /* Support utrace(2)-based tracing. */ #define JEMALLOC_UTRACE +/* Support utrace(2)-based tracing (label based signature). */ +/* #undef JEMALLOC_UTRACE_LABEL */ + /* Support optional abort() on OOM. */ #define JEMALLOC_XMALLOC @@ -178,6 +192,9 @@ /* One page is 2^LG_PAGE bytes. */ #define LG_PAGE 12 +/* Maximum number of regions in a slab. */ +/* #undef CONFIG_LG_SLAB_MAXREGS */ + /* * One huge page is 2^LG_HUGEPAGE bytes. Note that this is defined even if the * system does not explicitly support huge pages; system calls that require @@ -292,16 +309,45 @@ /* #undef JEMALLOC_MADVISE_DONTDUMP */ /* + * Defined if MADV_[NO]CORE is supported as an argument to madvise. + */ +#define JEMALLOC_MADVISE_NOCORE + +/* Defined if mprotect(2) is available. */ +#define JEMALLOC_HAVE_MPROTECT + +/* * Defined if transparent huge pages (THPs) are supported via the * MADV_[NO]HUGEPAGE arguments to madvise(2), and THP support is enabled. */ /* #undef JEMALLOC_THP */ +/* Defined if posix_madvise is available. */ +/* #undef JEMALLOC_HAVE_POSIX_MADVISE */ + +/* + * Method for purging unused pages using posix_madvise. + * + * posix_madvise(..., POSIX_MADV_DONTNEED) + */ +/* #undef JEMALLOC_PURGE_POSIX_MADVISE_DONTNEED */ +/* #undef JEMALLOC_PURGE_POSIX_MADVISE_DONTNEED_ZEROS */ + +/* + * Defined if memcntl page admin call is supported + */ +/* #undef JEMALLOC_HAVE_MEMCNTL */ + +/* + * Defined if malloc_size is supported + */ +/* #undef JEMALLOC_HAVE_MALLOC_SIZE */ + /* Define if operating system has alloca.h header. */ /* #undef JEMALLOC_HAS_ALLOCA_H */ /* C99 restrict keyword supported. */ -#define JEMALLOC_HAS_RESTRICT 1 +#define JEMALLOC_HAS_RESTRICT /* For use by hash code. */ /* #undef JEMALLOC_BIG_ENDIAN */ @@ -334,15 +380,15 @@ #define JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP /* GNU specific sched_getcpu support */ -/* #undef JEMALLOC_HAVE_SCHED_GETCPU */ +#define JEMALLOC_HAVE_SCHED_GETCPU /* GNU specific sched_setaffinity support */ -/* #undef JEMALLOC_HAVE_SCHED_SETAFFINITY */ +#define JEMALLOC_HAVE_SCHED_SETAFFINITY /* * If defined, all the features necessary for background threads are present. */ -#define JEMALLOC_BACKGROUND_THREAD 1 +#define JEMALLOC_BACKGROUND_THREAD /* * If defined, jemalloc symbols are not exported (doesn't work when @@ -354,7 +400,7 @@ #define JEMALLOC_CONFIG_MALLOC_CONF "abort_conf:false" /* If defined, jemalloc takes the malloc/free/etc. symbol names. */ -#define JEMALLOC_IS_MALLOC 1 +#define JEMALLOC_IS_MALLOC /* * Defined if strerror_r returns char * if _GNU_SOURCE is defined. @@ -364,4 +410,19 @@ /* Performs additional safety checks when defined. */ /* #undef JEMALLOC_OPT_SAFETY_CHECKS */ +/* Is C++ support being built? */ +#define JEMALLOC_ENABLE_CXX + +/* Performs additional size checks when defined. */ +/* #undef JEMALLOC_OPT_SIZE_CHECKS */ + +/* Allows sampled junk and stash for checking use-after-free when defined. */ +/* #undef JEMALLOC_UAF_DETECTION */ + +/* Darwin VM_MAKE_TAG support */ +/* #undef JEMALLOC_HAVE_VM_MAKE_TAG */ + +/* If defined, realloc(ptr, 0) defaults to "free" instead of "alloc". */ +/* #undef JEMALLOC_ZERO_REALLOC_DEFAULT_FREE */ + #endif /* JEMALLOC_INTERNAL_DEFS_H_ */ diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h index d1dcc50d5a3b..b6cf5864109d 100644 --- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h +++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/jemalloc_preamble.h @@ -4,12 +4,20 @@ #include "jemalloc_internal_defs.h" #include "jemalloc/internal/jemalloc_internal_decls.h" -#ifdef JEMALLOC_UTRACE +#if defined(JEMALLOC_UTRACE) || defined(JEMALLOC_UTRACE_LABEL) #include <sys/ktrace.h> +# if defined(JEMALLOC_UTRACE) +# define UTRACE_CALL(p, l) utrace(p, l) +# else +# define UTRACE_CALL(p, l) utrace("jemalloc_process", p, l) +# define JEMALLOC_UTRACE +# endif #endif +#ifndef JEMALLOC_PRIVATE_NAMESPACE #include "un-namespace.h" #include "libc_private.h" +#endif #define JEMALLOC_NO_DEMANGLE #ifdef JEMALLOC_JET @@ -177,6 +185,35 @@ static const bool config_opt_safety_checks = #endif ; +/* + * Extra debugging of sized deallocations too onerous to be included in the + * general safety checks. + */ +static const bool config_opt_size_checks = +#if defined(JEMALLOC_OPT_SIZE_CHECKS) || defined(JEMALLOC_DEBUG) + true +#else + false +#endif + ; + +static const bool config_uaf_detection = +#if defined(JEMALLOC_UAF_DETECTION) || defined(JEMALLOC_DEBUG) + true +#else + false +#endif + ; + +/* Whether or not the C++ extensions are enabled. */ +static const bool config_enable_cxx = +#ifdef JEMALLOC_ENABLE_CXX + true +#else + false +#endif +; + #if defined(_WIN32) || defined(JEMALLOC_HAVE_SCHED_GETCPU) /* Currently percpu_arena depends on sched_getcpu. */ #define JEMALLOC_PERCPU_ARENA @@ -206,5 +243,20 @@ static const bool have_background_thread = false #endif ; +static const bool config_high_res_timer = +#ifdef JEMALLOC_HAVE_CLOCK_REALTIME + true +#else + false +#endif + ; + +static const bool have_memcntl = +#ifdef JEMALLOC_HAVE_MEMCNTL + true +#else + false +#endif + ; #endif /* JEMALLOC_PREAMBLE_H */ diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/private_namespace.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/private_namespace.h index a448ad63fa54..08ce9219cbf8 100644 --- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/private_namespace.h +++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/private_namespace.h @@ -5,10 +5,9 @@ #define arena_init JEMALLOC_N(arena_init) #define arena_migrate JEMALLOC_N(arena_migrate) #define arena_set JEMALLOC_N(arena_set) -#define arena_tdata_get_hard JEMALLOC_N(arena_tdata_get_hard) #define arenas JEMALLOC_N(arenas) #define arenas_lock JEMALLOC_N(arenas_lock) -#define arenas_tdata_cleanup JEMALLOC_N(arenas_tdata_cleanup) +#define batch_alloc JEMALLOC_N(batch_alloc) #define bootstrap_calloc JEMALLOC_N(bootstrap_calloc) #define bootstrap_free JEMALLOC_N(bootstrap_free) #define bootstrap_malloc JEMALLOC_N(bootstrap_malloc) @@ -16,8 +15,10 @@ #define iarena_cleanup JEMALLOC_N(iarena_cleanup) #define je_sdallocx_noflags JEMALLOC_N(je_sdallocx_noflags) #define jemalloc_postfork_child JEMALLOC_N(jemalloc_postfork_child) +#define junk_alloc_callback JEMALLOC_N(junk_alloc_callback) +#define junk_free_callback JEMALLOC_N(junk_free_callback) #define malloc_default JEMALLOC_N(malloc_default) -#define malloc_initialized JEMALLOC_N(malloc_initialized) +#define malloc_init_state JEMALLOC_N(malloc_init_state) #define malloc_slow JEMALLOC_N(malloc_slow) #define manual_arena_base JEMALLOC_N(manual_arena_base) #define narenas_auto JEMALLOC_N(narenas_auto) @@ -25,49 +26,64 @@ #define ncpus JEMALLOC_N(ncpus) #define opt_abort JEMALLOC_N(opt_abort) #define opt_abort_conf JEMALLOC_N(opt_abort_conf) +#define opt_cache_oblivious JEMALLOC_N(opt_cache_oblivious) #define opt_confirm_conf JEMALLOC_N(opt_confirm_conf) +#define opt_experimental_infallible_new JEMALLOC_N(opt_experimental_infallible_new) +#define opt_hpa JEMALLOC_N(opt_hpa) +#define opt_hpa_opts JEMALLOC_N(opt_hpa_opts) +#define opt_hpa_sec_opts JEMALLOC_N(opt_hpa_sec_opts) #define opt_junk JEMALLOC_N(opt_junk) #define opt_junk_alloc JEMALLOC_N(opt_junk_alloc) #define opt_junk_free JEMALLOC_N(opt_junk_free) #define opt_narenas JEMALLOC_N(opt_narenas) +#define opt_narenas_ratio JEMALLOC_N(opt_narenas_ratio) +#define opt_trust_madvise JEMALLOC_N(opt_trust_madvise) #define opt_utrace JEMALLOC_N(opt_utrace) #define opt_xmalloc JEMALLOC_N(opt_xmalloc) #define opt_zero JEMALLOC_N(opt_zero) +#define opt_zero_realloc_action JEMALLOC_N(opt_zero_realloc_action) #define sdallocx_default JEMALLOC_N(sdallocx_default) -#define arena_alloc_junk_small JEMALLOC_N(arena_alloc_junk_small) +#define zero_realloc_count JEMALLOC_N(zero_realloc_count) +#define zero_realloc_mode_names JEMALLOC_N(zero_realloc_mode_names) #define arena_basic_stats_merge JEMALLOC_N(arena_basic_stats_merge) -#define arena_bin_choose_lock JEMALLOC_N(arena_bin_choose_lock) +#define arena_bin_choose JEMALLOC_N(arena_bin_choose) +#define arena_bin_offsets JEMALLOC_N(arena_bin_offsets) +#define arena_binind_div_info JEMALLOC_N(arena_binind_div_info) #define arena_boot JEMALLOC_N(arena_boot) +#define arena_cache_bin_fill_small JEMALLOC_N(arena_cache_bin_fill_small) #define arena_choose_huge JEMALLOC_N(arena_choose_huge) -#define arena_dalloc_bin_junked_locked JEMALLOC_N(arena_dalloc_bin_junked_locked) -#define arena_dalloc_junk_small JEMALLOC_N(arena_dalloc_junk_small) +#define arena_config_default JEMALLOC_N(arena_config_default) +#define arena_dalloc_bin_locked_handle_newly_empty JEMALLOC_N(arena_dalloc_bin_locked_handle_newly_empty) +#define arena_dalloc_bin_locked_handle_newly_nonempty JEMALLOC_N(arena_dalloc_bin_locked_handle_newly_nonempty) #define arena_dalloc_promoted JEMALLOC_N(arena_dalloc_promoted) #define arena_dalloc_small JEMALLOC_N(arena_dalloc_small) #define arena_decay JEMALLOC_N(arena_decay) +#define arena_decay_ms_get JEMALLOC_N(arena_decay_ms_get) +#define arena_decay_ms_set JEMALLOC_N(arena_decay_ms_set) #define arena_destroy JEMALLOC_N(arena_destroy) #define arena_dirty_decay_ms_default_get JEMALLOC_N(arena_dirty_decay_ms_default_get) #define arena_dirty_decay_ms_default_set JEMALLOC_N(arena_dirty_decay_ms_default_set) -#define arena_dirty_decay_ms_get JEMALLOC_N(arena_dirty_decay_ms_get) -#define arena_dirty_decay_ms_set JEMALLOC_N(arena_dirty_decay_ms_set) +#define arena_do_deferred_work JEMALLOC_N(arena_do_deferred_work) #define arena_dss_prec_get JEMALLOC_N(arena_dss_prec_get) #define arena_dss_prec_set JEMALLOC_N(arena_dss_prec_set) +#define arena_emap_global JEMALLOC_N(arena_emap_global) #define arena_extent_alloc_large JEMALLOC_N(arena_extent_alloc_large) #define arena_extent_dalloc_large_prep JEMALLOC_N(arena_extent_dalloc_large_prep) #define arena_extent_ralloc_large_expand JEMALLOC_N(arena_extent_ralloc_large_expand) #define arena_extent_ralloc_large_shrink JEMALLOC_N(arena_extent_ralloc_large_shrink) -#define arena_extent_sn_next JEMALLOC_N(arena_extent_sn_next) -#define arena_extents_dirty_dalloc JEMALLOC_N(arena_extents_dirty_dalloc) +#define arena_fill_small_fresh JEMALLOC_N(arena_fill_small_fresh) +#define arena_get_ehooks JEMALLOC_N(arena_get_ehooks) +#define arena_handle_deferred_work JEMALLOC_N(arena_handle_deferred_work) #define arena_init_huge JEMALLOC_N(arena_init_huge) #define arena_is_huge JEMALLOC_N(arena_is_huge) #define arena_malloc_hard JEMALLOC_N(arena_malloc_hard) #define arena_muzzy_decay_ms_default_get JEMALLOC_N(arena_muzzy_decay_ms_default_get) #define arena_muzzy_decay_ms_default_set JEMALLOC_N(arena_muzzy_decay_ms_default_set) -#define arena_muzzy_decay_ms_get JEMALLOC_N(arena_muzzy_decay_ms_get) -#define arena_muzzy_decay_ms_set JEMALLOC_N(arena_muzzy_decay_ms_set) #define arena_new JEMALLOC_N(arena_new) #define arena_nthreads_dec JEMALLOC_N(arena_nthreads_dec) #define arena_nthreads_get JEMALLOC_N(arena_nthreads_get) #define arena_nthreads_inc JEMALLOC_N(arena_nthreads_inc) +#define arena_pa_central_global JEMALLOC_N(arena_pa_central_global) #define arena_palloc JEMALLOC_N(arena_palloc) #define arena_postfork_child JEMALLOC_N(arena_postfork_child) #define arena_postfork_parent JEMALLOC_N(arena_postfork_parent) @@ -79,14 +95,15 @@ #define arena_prefork5 JEMALLOC_N(arena_prefork5) #define arena_prefork6 JEMALLOC_N(arena_prefork6) #define arena_prefork7 JEMALLOC_N(arena_prefork7) +#define arena_prefork8 JEMALLOC_N(arena_prefork8) #define arena_prof_promote JEMALLOC_N(arena_prof_promote) #define arena_ralloc JEMALLOC_N(arena_ralloc) #define arena_ralloc_no_move JEMALLOC_N(arena_ralloc_no_move) #define arena_reset JEMALLOC_N(arena_reset) #define arena_retain_grow_limit_get_set JEMALLOC_N(arena_retain_grow_limit_get_set) +#define arena_set_extent_hooks JEMALLOC_N(arena_set_extent_hooks) +#define arena_slab_dalloc JEMALLOC_N(arena_slab_dalloc) #define arena_stats_merge JEMALLOC_N(arena_stats_merge) -#define arena_tcache_fill_small JEMALLOC_N(arena_tcache_fill_small) -#define h_steps JEMALLOC_N(h_steps) #define opt_dirty_decay_ms JEMALLOC_N(opt_dirty_decay_ms) #define opt_muzzy_decay_ms JEMALLOC_N(opt_muzzy_decay_ms) #define opt_oversize_threshold JEMALLOC_N(opt_oversize_threshold) @@ -99,13 +116,14 @@ #define background_thread_ctl_init JEMALLOC_N(background_thread_ctl_init) #define background_thread_enabled_state JEMALLOC_N(background_thread_enabled_state) #define background_thread_info JEMALLOC_N(background_thread_info) -#define background_thread_interval_check JEMALLOC_N(background_thread_interval_check) +#define background_thread_is_started JEMALLOC_N(background_thread_is_started) #define background_thread_lock JEMALLOC_N(background_thread_lock) #define background_thread_postfork_child JEMALLOC_N(background_thread_postfork_child) #define background_thread_postfork_parent JEMALLOC_N(background_thread_postfork_parent) #define background_thread_prefork0 JEMALLOC_N(background_thread_prefork0) #define background_thread_prefork1 JEMALLOC_N(background_thread_prefork1) #define background_thread_stats_read JEMALLOC_N(background_thread_stats_read) +#define background_thread_wakeup_early JEMALLOC_N(background_thread_wakeup_early) #define background_threads_disable JEMALLOC_N(background_threads_disable) #define background_threads_enable JEMALLOC_N(background_threads_enable) #define max_background_threads JEMALLOC_N(max_background_threads) @@ -115,10 +133,11 @@ #define pthread_create_wrapper JEMALLOC_N(pthread_create_wrapper) #define b0get JEMALLOC_N(b0get) #define base_alloc JEMALLOC_N(base_alloc) -#define base_alloc_extent JEMALLOC_N(base_alloc_extent) +#define base_alloc_edata JEMALLOC_N(base_alloc_edata) #define base_boot JEMALLOC_N(base_boot) #define base_delete JEMALLOC_N(base_delete) -#define base_extent_hooks_get JEMALLOC_N(base_extent_hooks_get) +#define base_ehooks_get JEMALLOC_N(base_ehooks_get) +#define base_ehooks_get_for_metadata JEMALLOC_N(base_ehooks_get_for_metadata) #define base_extent_hooks_set JEMALLOC_N(base_extent_hooks_set) #define base_new JEMALLOC_N(base_new) #define base_postfork_child JEMALLOC_N(base_postfork_child) @@ -127,17 +146,28 @@ #define base_stats_get JEMALLOC_N(base_stats_get) #define metadata_thp_mode_names JEMALLOC_N(metadata_thp_mode_names) #define opt_metadata_thp JEMALLOC_N(opt_metadata_thp) -#define bin_boot JEMALLOC_N(bin_boot) -#define bin_infos JEMALLOC_N(bin_infos) #define bin_init JEMALLOC_N(bin_init) #define bin_postfork_child JEMALLOC_N(bin_postfork_child) #define bin_postfork_parent JEMALLOC_N(bin_postfork_parent) #define bin_prefork JEMALLOC_N(bin_prefork) #define bin_shard_sizes_boot JEMALLOC_N(bin_shard_sizes_boot) #define bin_update_shard_size JEMALLOC_N(bin_update_shard_size) +#define bin_info_boot JEMALLOC_N(bin_info_boot) +#define bin_infos JEMALLOC_N(bin_infos) #define bitmap_info_init JEMALLOC_N(bitmap_info_init) #define bitmap_init JEMALLOC_N(bitmap_init) #define bitmap_size JEMALLOC_N(bitmap_size) +#define buf_writer_cb JEMALLOC_N(buf_writer_cb) +#define buf_writer_flush JEMALLOC_N(buf_writer_flush) +#define buf_writer_init JEMALLOC_N(buf_writer_init) +#define buf_writer_pipe JEMALLOC_N(buf_writer_pipe) +#define buf_writer_terminate JEMALLOC_N(buf_writer_terminate) +#define cache_bin_info_compute_alloc JEMALLOC_N(cache_bin_info_compute_alloc) +#define cache_bin_info_init JEMALLOC_N(cache_bin_info_init) +#define cache_bin_init JEMALLOC_N(cache_bin_init) +#define cache_bin_postincrement JEMALLOC_N(cache_bin_postincrement) +#define cache_bin_preincrement JEMALLOC_N(cache_bin_preincrement) +#define cache_bin_still_zero_initialized JEMALLOC_N(cache_bin_still_zero_initialized) #define ckh_count JEMALLOC_N(ckh_count) #define ckh_delete JEMALLOC_N(ckh_delete) #define ckh_insert JEMALLOC_N(ckh_insert) @@ -149,61 +179,116 @@ #define ckh_search JEMALLOC_N(ckh_search) #define ckh_string_hash JEMALLOC_N(ckh_string_hash) #define ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp) +#define counter_accum_init JEMALLOC_N(counter_accum_init) +#define counter_postfork_child JEMALLOC_N(counter_postfork_child) +#define counter_postfork_parent JEMALLOC_N(counter_postfork_parent) +#define counter_prefork JEMALLOC_N(counter_prefork) #define ctl_boot JEMALLOC_N(ctl_boot) #define ctl_bymib JEMALLOC_N(ctl_bymib) +#define ctl_bymibname JEMALLOC_N(ctl_bymibname) #define ctl_byname JEMALLOC_N(ctl_byname) +#define ctl_mibnametomib JEMALLOC_N(ctl_mibnametomib) +#define ctl_mtx_assert_held JEMALLOC_N(ctl_mtx_assert_held) #define ctl_nametomib JEMALLOC_N(ctl_nametomib) #define ctl_postfork_child JEMALLOC_N(ctl_postfork_child) #define ctl_postfork_parent JEMALLOC_N(ctl_postfork_parent) #define ctl_prefork JEMALLOC_N(ctl_prefork) +#define decay_deadline_init JEMALLOC_N(decay_deadline_init) +#define decay_init JEMALLOC_N(decay_init) +#define decay_maybe_advance_epoch JEMALLOC_N(decay_maybe_advance_epoch) +#define decay_ms_valid JEMALLOC_N(decay_ms_valid) +#define decay_npages_purge_in JEMALLOC_N(decay_npages_purge_in) +#define decay_ns_until_purge JEMALLOC_N(decay_ns_until_purge) +#define decay_reinit JEMALLOC_N(decay_reinit) #define div_init JEMALLOC_N(div_init) -#define extent_alloc JEMALLOC_N(extent_alloc) +#define ecache_init JEMALLOC_N(ecache_init) +#define ecache_postfork_child JEMALLOC_N(ecache_postfork_child) +#define ecache_postfork_parent JEMALLOC_N(ecache_postfork_parent) +#define ecache_prefork JEMALLOC_N(ecache_prefork) +#define edata_avail_any JEMALLOC_N(edata_avail_any) +#define edata_avail_empty JEMALLOC_N(edata_avail_empty) +#define edata_avail_first JEMALLOC_N(edata_avail_first) +#define edata_avail_insert JEMALLOC_N(edata_avail_insert) +#define edata_avail_new JEMALLOC_N(edata_avail_new) +#define edata_avail_remove JEMALLOC_N(edata_avail_remove) +#define edata_avail_remove_any JEMALLOC_N(edata_avail_remove_any) +#define edata_avail_remove_first JEMALLOC_N(edata_avail_remove_first) +#define edata_heap_any JEMALLOC_N(edata_heap_any) +#define edata_heap_empty JEMALLOC_N(edata_heap_empty) +#define edata_heap_first JEMALLOC_N(edata_heap_first) +#define edata_heap_insert JEMALLOC_N(edata_heap_insert) +#define edata_heap_new JEMALLOC_N(edata_heap_new) +#define edata_heap_remove JEMALLOC_N(edata_heap_remove) +#define edata_heap_remove_any JEMALLOC_N(edata_heap_remove_any) +#define edata_heap_remove_first JEMALLOC_N(edata_heap_remove_first) +#define edata_cache_fast_disable JEMALLOC_N(edata_cache_fast_disable) +#define edata_cache_fast_get JEMALLOC_N(edata_cache_fast_get) +#define edata_cache_fast_init JEMALLOC_N(edata_cache_fast_init) +#define edata_cache_fast_put JEMALLOC_N(edata_cache_fast_put) +#define edata_cache_get JEMALLOC_N(edata_cache_get) +#define edata_cache_init JEMALLOC_N(edata_cache_init) +#define edata_cache_postfork_child JEMALLOC_N(edata_cache_postfork_child) +#define edata_cache_postfork_parent JEMALLOC_N(edata_cache_postfork_parent) +#define edata_cache_prefork JEMALLOC_N(edata_cache_prefork) +#define edata_cache_put JEMALLOC_N(edata_cache_put) +#define ehooks_default_alloc_impl JEMALLOC_N(ehooks_default_alloc_impl) +#define ehooks_default_commit_impl JEMALLOC_N(ehooks_default_commit_impl) +#define ehooks_default_dalloc_impl JEMALLOC_N(ehooks_default_dalloc_impl) +#define ehooks_default_decommit_impl JEMALLOC_N(ehooks_default_decommit_impl) +#define ehooks_default_destroy_impl JEMALLOC_N(ehooks_default_destroy_impl) +#define ehooks_default_extent_hooks JEMALLOC_N(ehooks_default_extent_hooks) +#define ehooks_default_guard_impl JEMALLOC_N(ehooks_default_guard_impl) +#define ehooks_default_merge JEMALLOC_N(ehooks_default_merge) +#define ehooks_default_merge_impl JEMALLOC_N(ehooks_default_merge_impl) +#define ehooks_default_purge_forced_impl JEMALLOC_N(ehooks_default_purge_forced_impl) +#define ehooks_default_purge_lazy_impl JEMALLOC_N(ehooks_default_purge_lazy_impl) +#define ehooks_default_split_impl JEMALLOC_N(ehooks_default_split_impl) +#define ehooks_default_unguard_impl JEMALLOC_N(ehooks_default_unguard_impl) +#define ehooks_default_zero_impl JEMALLOC_N(ehooks_default_zero_impl) +#define ehooks_init JEMALLOC_N(ehooks_init) +#define emap_deregister_boundary JEMALLOC_N(emap_deregister_boundary) +#define emap_deregister_interior JEMALLOC_N(emap_deregister_interior) +#define emap_do_assert_mapped JEMALLOC_N(emap_do_assert_mapped) +#define emap_do_assert_not_mapped JEMALLOC_N(emap_do_assert_not_mapped) +#define emap_init JEMALLOC_N(emap_init) +#define emap_merge_commit JEMALLOC_N(emap_merge_commit) +#define emap_merge_prepare JEMALLOC_N(emap_merge_prepare) +#define emap_register_boundary JEMALLOC_N(emap_register_boundary) +#define emap_register_interior JEMALLOC_N(emap_register_interior) +#define emap_release_edata JEMALLOC_N(emap_release_edata) +#define emap_remap JEMALLOC_N(emap_remap) +#define emap_split_commit JEMALLOC_N(emap_split_commit) +#define emap_split_prepare JEMALLOC_N(emap_split_prepare) +#define emap_try_acquire_edata_neighbor JEMALLOC_N(emap_try_acquire_edata_neighbor) +#define emap_try_acquire_edata_neighbor_expand JEMALLOC_N(emap_try_acquire_edata_neighbor_expand) +#define emap_update_edata_state JEMALLOC_N(emap_update_edata_state) +#define eset_fit JEMALLOC_N(eset_fit) +#define eset_init JEMALLOC_N(eset_init) +#define eset_insert JEMALLOC_N(eset_insert) +#define eset_nbytes_get JEMALLOC_N(eset_nbytes_get) +#define eset_nextents_get JEMALLOC_N(eset_nextents_get) +#define eset_npages_get JEMALLOC_N(eset_npages_get) +#define eset_remove JEMALLOC_N(eset_remove) +#define exp_grow_init JEMALLOC_N(exp_grow_init) +#define ecache_alloc JEMALLOC_N(ecache_alloc) +#define ecache_alloc_grow JEMALLOC_N(ecache_alloc_grow) +#define ecache_dalloc JEMALLOC_N(ecache_dalloc) +#define ecache_evict JEMALLOC_N(ecache_evict) #define extent_alloc_wrapper JEMALLOC_N(extent_alloc_wrapper) -#define extent_avail_any JEMALLOC_N(extent_avail_any) -#define extent_avail_empty JEMALLOC_N(extent_avail_empty) -#define extent_avail_first JEMALLOC_N(extent_avail_first) -#define extent_avail_insert JEMALLOC_N(extent_avail_insert) -#define extent_avail_new JEMALLOC_N(extent_avail_new) -#define extent_avail_remove JEMALLOC_N(extent_avail_remove) -#define extent_avail_remove_any JEMALLOC_N(extent_avail_remove_any) -#define extent_avail_remove_first JEMALLOC_N(extent_avail_remove_first) #define extent_boot JEMALLOC_N(extent_boot) #define extent_commit_wrapper JEMALLOC_N(extent_commit_wrapper) -#define extent_dalloc JEMALLOC_N(extent_dalloc) +#define extent_commit_zero JEMALLOC_N(extent_commit_zero) #define extent_dalloc_gap JEMALLOC_N(extent_dalloc_gap) #define extent_dalloc_wrapper JEMALLOC_N(extent_dalloc_wrapper) #define extent_decommit_wrapper JEMALLOC_N(extent_decommit_wrapper) #define extent_destroy_wrapper JEMALLOC_N(extent_destroy_wrapper) -#define extent_heap_any JEMALLOC_N(extent_heap_any) -#define extent_heap_empty JEMALLOC_N(extent_heap_empty) -#define extent_heap_first JEMALLOC_N(extent_heap_first) -#define extent_heap_insert JEMALLOC_N(extent_heap_insert) -#define extent_heap_new JEMALLOC_N(extent_heap_new) -#define extent_heap_remove JEMALLOC_N(extent_heap_remove) -#define extent_heap_remove_any JEMALLOC_N(extent_heap_remove_any) -#define extent_heap_remove_first JEMALLOC_N(extent_heap_remove_first) -#define extent_hooks_default JEMALLOC_N(extent_hooks_default) -#define extent_hooks_get JEMALLOC_N(extent_hooks_get) -#define extent_hooks_set JEMALLOC_N(extent_hooks_set) +#define extent_gdump_add JEMALLOC_N(extent_gdump_add) #define extent_merge_wrapper JEMALLOC_N(extent_merge_wrapper) -#define extent_mutex_pool JEMALLOC_N(extent_mutex_pool) #define extent_purge_forced_wrapper JEMALLOC_N(extent_purge_forced_wrapper) #define extent_purge_lazy_wrapper JEMALLOC_N(extent_purge_lazy_wrapper) +#define extent_record JEMALLOC_N(extent_record) +#define extent_sn_next JEMALLOC_N(extent_sn_next) #define extent_split_wrapper JEMALLOC_N(extent_split_wrapper) -#define extent_util_stats_get JEMALLOC_N(extent_util_stats_get) -#define extent_util_stats_verbose_get JEMALLOC_N(extent_util_stats_verbose_get) -#define extents_alloc JEMALLOC_N(extents_alloc) -#define extents_dalloc JEMALLOC_N(extents_dalloc) -#define extents_evict JEMALLOC_N(extents_evict) -#define extents_init JEMALLOC_N(extents_init) -#define extents_nbytes_get JEMALLOC_N(extents_nbytes_get) -#define extents_nextents_get JEMALLOC_N(extents_nextents_get) -#define extents_npages_get JEMALLOC_N(extents_npages_get) -#define extents_postfork_child JEMALLOC_N(extents_postfork_child) -#define extents_postfork_parent JEMALLOC_N(extents_postfork_parent) -#define extents_prefork JEMALLOC_N(extents_prefork) -#define extents_rtree JEMALLOC_N(extents_rtree) -#define extents_state_get JEMALLOC_N(extents_state_get) #define opt_lg_extent_max_active_fit JEMALLOC_N(opt_lg_extent_max_active_fit) #define dss_prec_names JEMALLOC_N(dss_prec_names) #define extent_alloc_dss JEMALLOC_N(extent_alloc_dss) @@ -216,24 +301,66 @@ #define extent_alloc_mmap JEMALLOC_N(extent_alloc_mmap) #define extent_dalloc_mmap JEMALLOC_N(extent_dalloc_mmap) #define opt_retain JEMALLOC_N(opt_retain) +#define fxp_parse JEMALLOC_N(fxp_parse) +#define fxp_print JEMALLOC_N(fxp_print) +#define opt_lg_san_uaf_align JEMALLOC_N(opt_lg_san_uaf_align) +#define opt_san_guard_large JEMALLOC_N(opt_san_guard_large) +#define opt_san_guard_small JEMALLOC_N(opt_san_guard_small) +#define san_cache_bin_nonfast_mask JEMALLOC_N(san_cache_bin_nonfast_mask) +#define san_check_stashed_ptrs JEMALLOC_N(san_check_stashed_ptrs) +#define san_guard_pages JEMALLOC_N(san_guard_pages) +#define san_init JEMALLOC_N(san_init) +#define san_unguard_pages JEMALLOC_N(san_unguard_pages) +#define san_unguard_pages_pre_destroy JEMALLOC_N(san_unguard_pages_pre_destroy) +#define tsd_san_init JEMALLOC_N(tsd_san_init) +#define san_bump_alloc JEMALLOC_N(san_bump_alloc) #define hook_boot JEMALLOC_N(hook_boot) #define hook_install JEMALLOC_N(hook_install) #define hook_invoke_alloc JEMALLOC_N(hook_invoke_alloc) #define hook_invoke_dalloc JEMALLOC_N(hook_invoke_dalloc) #define hook_invoke_expand JEMALLOC_N(hook_invoke_expand) #define hook_remove JEMALLOC_N(hook_remove) +#define hpa_central_extract JEMALLOC_N(hpa_central_extract) +#define hpa_central_init JEMALLOC_N(hpa_central_init) +#define hpa_shard_destroy JEMALLOC_N(hpa_shard_destroy) +#define hpa_shard_disable JEMALLOC_N(hpa_shard_disable) +#define hpa_shard_do_deferred_work JEMALLOC_N(hpa_shard_do_deferred_work) +#define hpa_shard_init JEMALLOC_N(hpa_shard_init) +#define hpa_shard_postfork_child JEMALLOC_N(hpa_shard_postfork_child) +#define hpa_shard_postfork_parent JEMALLOC_N(hpa_shard_postfork_parent) +#define hpa_shard_prefork3 JEMALLOC_N(hpa_shard_prefork3) +#define hpa_shard_prefork4 JEMALLOC_N(hpa_shard_prefork4) +#define hpa_shard_set_deferral_allowed JEMALLOC_N(hpa_shard_set_deferral_allowed) +#define hpa_shard_stats_accum JEMALLOC_N(hpa_shard_stats_accum) +#define hpa_shard_stats_merge JEMALLOC_N(hpa_shard_stats_merge) +#define hpa_supported JEMALLOC_N(hpa_supported) +#define hpa_hooks_default JEMALLOC_N(hpa_hooks_default) +#define hpdata_age_heap_any JEMALLOC_N(hpdata_age_heap_any) +#define hpdata_age_heap_empty JEMALLOC_N(hpdata_age_heap_empty) +#define hpdata_age_heap_first JEMALLOC_N(hpdata_age_heap_first) +#define hpdata_age_heap_insert JEMALLOC_N(hpdata_age_heap_insert) +#define hpdata_age_heap_new JEMALLOC_N(hpdata_age_heap_new) +#define hpdata_age_heap_remove JEMALLOC_N(hpdata_age_heap_remove) +#define hpdata_age_heap_remove_any JEMALLOC_N(hpdata_age_heap_remove_any) +#define hpdata_age_heap_remove_first JEMALLOC_N(hpdata_age_heap_remove_first) +#define hpdata_dehugify JEMALLOC_N(hpdata_dehugify) +#define hpdata_hugify JEMALLOC_N(hpdata_hugify) +#define hpdata_init JEMALLOC_N(hpdata_init) +#define hpdata_purge_begin JEMALLOC_N(hpdata_purge_begin) +#define hpdata_purge_end JEMALLOC_N(hpdata_purge_end) +#define hpdata_purge_next JEMALLOC_N(hpdata_purge_next) +#define hpdata_reserve_alloc JEMALLOC_N(hpdata_reserve_alloc) +#define hpdata_unreserve JEMALLOC_N(hpdata_unreserve) +#define inspect_extent_util_stats_get JEMALLOC_N(inspect_extent_util_stats_get) +#define inspect_extent_util_stats_verbose_get JEMALLOC_N(inspect_extent_util_stats_verbose_get) #define large_dalloc JEMALLOC_N(large_dalloc) #define large_dalloc_finish JEMALLOC_N(large_dalloc_finish) -#define large_dalloc_junk JEMALLOC_N(large_dalloc_junk) -#define large_dalloc_maybe_junk JEMALLOC_N(large_dalloc_maybe_junk) -#define large_dalloc_prep_junked_locked JEMALLOC_N(large_dalloc_prep_junked_locked) +#define large_dalloc_prep_locked JEMALLOC_N(large_dalloc_prep_locked) #define large_malloc JEMALLOC_N(large_malloc) #define large_palloc JEMALLOC_N(large_palloc) -#define large_prof_alloc_time_get JEMALLOC_N(large_prof_alloc_time_get) -#define large_prof_alloc_time_set JEMALLOC_N(large_prof_alloc_time_set) -#define large_prof_tctx_get JEMALLOC_N(large_prof_tctx_get) +#define large_prof_info_get JEMALLOC_N(large_prof_info_get) +#define large_prof_info_set JEMALLOC_N(large_prof_info_set) #define large_prof_tctx_reset JEMALLOC_N(large_prof_tctx_reset) -#define large_prof_tctx_set JEMALLOC_N(large_prof_tctx_set) #define large_ralloc JEMALLOC_N(large_ralloc) #define large_ralloc_no_move JEMALLOC_N(large_ralloc_no_move) #define large_salloc JEMALLOC_N(large_salloc) @@ -248,14 +375,17 @@ #define malloc_vcprintf JEMALLOC_N(malloc_vcprintf) #define malloc_vsnprintf JEMALLOC_N(malloc_vsnprintf) #define malloc_write JEMALLOC_N(malloc_write) +#define wrtmessage JEMALLOC_N(wrtmessage) +#define wrtmessage_1_0 JEMALLOC_N(wrtmessage_1_0) #define malloc_mutex_boot JEMALLOC_N(malloc_mutex_boot) +#define malloc_mutex_first_thread JEMALLOC_N(malloc_mutex_first_thread) #define malloc_mutex_init JEMALLOC_N(malloc_mutex_init) #define malloc_mutex_lock_slow JEMALLOC_N(malloc_mutex_lock_slow) #define malloc_mutex_postfork_child JEMALLOC_N(malloc_mutex_postfork_child) #define malloc_mutex_postfork_parent JEMALLOC_N(malloc_mutex_postfork_parent) #define malloc_mutex_prefork JEMALLOC_N(malloc_mutex_prefork) #define malloc_mutex_prof_data_reset JEMALLOC_N(malloc_mutex_prof_data_reset) -#define mutex_pool_init JEMALLOC_N(mutex_pool_init) +#define opt_mutex_max_spin JEMALLOC_N(opt_mutex_max_spin) #define nstime_add JEMALLOC_N(nstime_add) #define nstime_compare JEMALLOC_N(nstime_compare) #define nstime_copy JEMALLOC_N(nstime_copy) @@ -265,14 +395,56 @@ #define nstime_imultiply JEMALLOC_N(nstime_imultiply) #define nstime_init JEMALLOC_N(nstime_init) #define nstime_init2 JEMALLOC_N(nstime_init2) +#define nstime_init_update JEMALLOC_N(nstime_init_update) #define nstime_isubtract JEMALLOC_N(nstime_isubtract) #define nstime_monotonic JEMALLOC_N(nstime_monotonic) #define nstime_msec JEMALLOC_N(nstime_msec) #define nstime_ns JEMALLOC_N(nstime_ns) +#define nstime_ns_since JEMALLOC_N(nstime_ns_since) #define nstime_nsec JEMALLOC_N(nstime_nsec) +#define nstime_prof_init_update JEMALLOC_N(nstime_prof_init_update) +#define nstime_prof_update JEMALLOC_N(nstime_prof_update) #define nstime_sec JEMALLOC_N(nstime_sec) #define nstime_subtract JEMALLOC_N(nstime_subtract) #define nstime_update JEMALLOC_N(nstime_update) +#define opt_prof_time_res JEMALLOC_N(opt_prof_time_res) +#define prof_time_res_mode_names JEMALLOC_N(prof_time_res_mode_names) +#define pa_alloc JEMALLOC_N(pa_alloc) +#define pa_central_init JEMALLOC_N(pa_central_init) +#define pa_dalloc JEMALLOC_N(pa_dalloc) +#define pa_decay_ms_get JEMALLOC_N(pa_decay_ms_get) +#define pa_decay_ms_set JEMALLOC_N(pa_decay_ms_set) +#define pa_expand JEMALLOC_N(pa_expand) +#define pa_shard_destroy JEMALLOC_N(pa_shard_destroy) +#define pa_shard_disable_hpa JEMALLOC_N(pa_shard_disable_hpa) +#define pa_shard_do_deferred_work JEMALLOC_N(pa_shard_do_deferred_work) +#define pa_shard_enable_hpa JEMALLOC_N(pa_shard_enable_hpa) +#define pa_shard_init JEMALLOC_N(pa_shard_init) +#define pa_shard_reset JEMALLOC_N(pa_shard_reset) +#define pa_shard_retain_grow_limit_get_set JEMALLOC_N(pa_shard_retain_grow_limit_get_set) +#define pa_shard_set_deferral_allowed JEMALLOC_N(pa_shard_set_deferral_allowed) +#define pa_shard_time_until_deferred_work JEMALLOC_N(pa_shard_time_until_deferred_work) +#define pa_shrink JEMALLOC_N(pa_shrink) +#define pa_shard_basic_stats_merge JEMALLOC_N(pa_shard_basic_stats_merge) +#define pa_shard_mtx_stats_read JEMALLOC_N(pa_shard_mtx_stats_read) +#define pa_shard_postfork_child JEMALLOC_N(pa_shard_postfork_child) +#define pa_shard_postfork_parent JEMALLOC_N(pa_shard_postfork_parent) +#define pa_shard_prefork0 JEMALLOC_N(pa_shard_prefork0) +#define pa_shard_prefork2 JEMALLOC_N(pa_shard_prefork2) +#define pa_shard_prefork3 JEMALLOC_N(pa_shard_prefork3) +#define pa_shard_prefork4 JEMALLOC_N(pa_shard_prefork4) +#define pa_shard_prefork5 JEMALLOC_N(pa_shard_prefork5) +#define pa_shard_stats_merge JEMALLOC_N(pa_shard_stats_merge) +#define pai_alloc_batch_default JEMALLOC_N(pai_alloc_batch_default) +#define pai_dalloc_batch_default JEMALLOC_N(pai_dalloc_batch_default) +#define pac_decay_all JEMALLOC_N(pac_decay_all) +#define pac_decay_ms_get JEMALLOC_N(pac_decay_ms_get) +#define pac_decay_ms_set JEMALLOC_N(pac_decay_ms_set) +#define pac_destroy JEMALLOC_N(pac_destroy) +#define pac_init JEMALLOC_N(pac_init) +#define pac_maybe_decay_purge JEMALLOC_N(pac_maybe_decay_purge) +#define pac_reset JEMALLOC_N(pac_reset) +#define pac_retain_grow_limit_get_set JEMALLOC_N(pac_retain_grow_limit_get_set) #define init_system_thp_mode JEMALLOC_N(init_system_thp_mode) #define opt_thp JEMALLOC_N(opt_thp) #define pages_boot JEMALLOC_N(pages_boot) @@ -282,14 +454,23 @@ #define pages_dontdump JEMALLOC_N(pages_dontdump) #define pages_huge JEMALLOC_N(pages_huge) #define pages_map JEMALLOC_N(pages_map) +#define pages_mark_guards JEMALLOC_N(pages_mark_guards) #define pages_nohuge JEMALLOC_N(pages_nohuge) #define pages_purge_forced JEMALLOC_N(pages_purge_forced) #define pages_purge_lazy JEMALLOC_N(pages_purge_lazy) #define pages_set_thp_state JEMALLOC_N(pages_set_thp_state) #define pages_unmap JEMALLOC_N(pages_unmap) +#define pages_unmark_guards JEMALLOC_N(pages_unmark_guards) #define thp_mode_names JEMALLOC_N(thp_mode_names) -#define bt2gctx_mtx JEMALLOC_N(bt2gctx_mtx) -#define bt_init JEMALLOC_N(bt_init) +#define peak_alloc_event_handler JEMALLOC_N(peak_alloc_event_handler) +#define peak_alloc_new_event_wait JEMALLOC_N(peak_alloc_new_event_wait) +#define peak_alloc_postponed_event_wait JEMALLOC_N(peak_alloc_postponed_event_wait) +#define peak_dalloc_event_handler JEMALLOC_N(peak_dalloc_event_handler) +#define peak_dalloc_new_event_wait JEMALLOC_N(peak_dalloc_new_event_wait) +#define peak_dalloc_postponed_event_wait JEMALLOC_N(peak_dalloc_postponed_event_wait) +#define peak_event_max JEMALLOC_N(peak_event_max) +#define peak_event_update JEMALLOC_N(peak_event_update) +#define peak_event_zero JEMALLOC_N(peak_event_zero) #define lg_prof_sample JEMALLOC_N(lg_prof_sample) #define opt_lg_prof_interval JEMALLOC_N(opt_lg_prof_interval) #define opt_lg_prof_sample JEMALLOC_N(opt_lg_prof_sample) @@ -299,20 +480,25 @@ #define opt_prof_final JEMALLOC_N(opt_prof_final) #define opt_prof_gdump JEMALLOC_N(opt_prof_gdump) #define opt_prof_leak JEMALLOC_N(opt_prof_leak) -#define opt_prof_log JEMALLOC_N(opt_prof_log) +#define opt_prof_leak_error JEMALLOC_N(opt_prof_leak_error) #define opt_prof_prefix JEMALLOC_N(opt_prof_prefix) +#define opt_prof_sys_thread_name JEMALLOC_N(opt_prof_sys_thread_name) #define opt_prof_thread_active_init JEMALLOC_N(opt_prof_thread_active_init) -#define prof_accum_init JEMALLOC_N(prof_accum_init) -#define prof_active JEMALLOC_N(prof_active) +#define opt_prof_unbias JEMALLOC_N(opt_prof_unbias) #define prof_active_get JEMALLOC_N(prof_active_get) #define prof_active_set JEMALLOC_N(prof_active_set) +#define prof_active_state JEMALLOC_N(prof_active_state) #define prof_alloc_rollback JEMALLOC_N(prof_alloc_rollback) -#define prof_backtrace JEMALLOC_N(prof_backtrace) +#define prof_backtrace_hook JEMALLOC_N(prof_backtrace_hook) +#define prof_backtrace_hook_get JEMALLOC_N(prof_backtrace_hook_get) +#define prof_backtrace_hook_set JEMALLOC_N(prof_backtrace_hook_set) #define prof_boot0 JEMALLOC_N(prof_boot0) #define prof_boot1 JEMALLOC_N(prof_boot1) #define prof_boot2 JEMALLOC_N(prof_boot2) -#define prof_dump_header JEMALLOC_N(prof_dump_header) -#define prof_dump_open JEMALLOC_N(prof_dump_open) +#define prof_booted JEMALLOC_N(prof_booted) +#define prof_dump_hook JEMALLOC_N(prof_dump_hook) +#define prof_dump_hook_get JEMALLOC_N(prof_dump_hook_get) +#define prof_dump_hook_set JEMALLOC_N(prof_dump_hook_set) #define prof_free_sampled_object JEMALLOC_N(prof_free_sampled_object) #define prof_gdump JEMALLOC_N(prof_gdump) #define prof_gdump_get JEMALLOC_N(prof_gdump_get) @@ -320,18 +506,16 @@ #define prof_gdump_val JEMALLOC_N(prof_gdump_val) #define prof_idump JEMALLOC_N(prof_idump) #define prof_interval JEMALLOC_N(prof_interval) -#define prof_log_start JEMALLOC_N(prof_log_start) -#define prof_log_stop JEMALLOC_N(prof_log_stop) -#define prof_logging_state JEMALLOC_N(prof_logging_state) -#define prof_lookup JEMALLOC_N(prof_lookup) #define prof_malloc_sample_object JEMALLOC_N(prof_malloc_sample_object) #define prof_mdump JEMALLOC_N(prof_mdump) #define prof_postfork_child JEMALLOC_N(prof_postfork_child) #define prof_postfork_parent JEMALLOC_N(prof_postfork_parent) #define prof_prefork0 JEMALLOC_N(prof_prefork0) #define prof_prefork1 JEMALLOC_N(prof_prefork1) -#define prof_reset JEMALLOC_N(prof_reset) -#define prof_sample_threshold_update JEMALLOC_N(prof_sample_threshold_update) +#define prof_sample_event_handler JEMALLOC_N(prof_sample_event_handler) +#define prof_sample_new_event_wait JEMALLOC_N(prof_sample_new_event_wait) +#define prof_sample_postponed_event_wait JEMALLOC_N(prof_sample_postponed_event_wait) +#define prof_tctx_create JEMALLOC_N(prof_tctx_create) #define prof_tdata_cleanup JEMALLOC_N(prof_tdata_cleanup) #define prof_tdata_init JEMALLOC_N(prof_tdata_init) #define prof_tdata_reinit JEMALLOC_N(prof_tdata_reinit) @@ -341,42 +525,157 @@ #define prof_thread_active_set JEMALLOC_N(prof_thread_active_set) #define prof_thread_name_get JEMALLOC_N(prof_thread_name_get) #define prof_thread_name_set JEMALLOC_N(prof_thread_name_set) +#define bt2gctx_mtx JEMALLOC_N(bt2gctx_mtx) +#define gctx_locks JEMALLOC_N(gctx_locks) +#define prof_bt_count JEMALLOC_N(prof_bt_count) +#define prof_bt_hash JEMALLOC_N(prof_bt_hash) +#define prof_bt_keycomp JEMALLOC_N(prof_bt_keycomp) +#define prof_cnt_all JEMALLOC_N(prof_cnt_all) +#define prof_data_init JEMALLOC_N(prof_data_init) +#define prof_dump_impl JEMALLOC_N(prof_dump_impl) +#define prof_dump_mtx JEMALLOC_N(prof_dump_mtx) +#define prof_lookup JEMALLOC_N(prof_lookup) +#define prof_reset JEMALLOC_N(prof_reset) +#define prof_shifted_unbiased_cnt JEMALLOC_N(prof_shifted_unbiased_cnt) +#define prof_tctx_try_destroy JEMALLOC_N(prof_tctx_try_destroy) +#define prof_tdata_count JEMALLOC_N(prof_tdata_count) +#define prof_tdata_detach JEMALLOC_N(prof_tdata_detach) +#define prof_tdata_init_impl JEMALLOC_N(prof_tdata_init_impl) +#define prof_thread_name_alloc JEMALLOC_N(prof_thread_name_alloc) +#define prof_thread_name_set_impl JEMALLOC_N(prof_thread_name_set_impl) +#define prof_unbias_map_init JEMALLOC_N(prof_unbias_map_init) +#define prof_unbiased_sz JEMALLOC_N(prof_unbiased_sz) +#define tdata_locks JEMALLOC_N(tdata_locks) +#define tdatas_mtx JEMALLOC_N(tdatas_mtx) +#define log_mtx JEMALLOC_N(log_mtx) +#define opt_prof_log JEMALLOC_N(opt_prof_log) +#define prof_log_alloc_count JEMALLOC_N(prof_log_alloc_count) +#define prof_log_bt_count JEMALLOC_N(prof_log_bt_count) +#define prof_log_dummy_set JEMALLOC_N(prof_log_dummy_set) +#define prof_log_init JEMALLOC_N(prof_log_init) +#define prof_log_is_logging JEMALLOC_N(prof_log_is_logging) +#define prof_log_rep_check JEMALLOC_N(prof_log_rep_check) +#define prof_log_start JEMALLOC_N(prof_log_start) +#define prof_log_stop JEMALLOC_N(prof_log_stop) +#define prof_log_thr_count JEMALLOC_N(prof_log_thr_count) +#define prof_logging_state JEMALLOC_N(prof_logging_state) +#define prof_try_log JEMALLOC_N(prof_try_log) +#define edata_prof_recent_alloc_get_no_lock_test JEMALLOC_N(edata_prof_recent_alloc_get_no_lock_test) +#define edata_prof_recent_alloc_init JEMALLOC_N(edata_prof_recent_alloc_init) +#define opt_prof_recent_alloc_max JEMALLOC_N(opt_prof_recent_alloc_max) +#define prof_recent_alloc JEMALLOC_N(prof_recent_alloc) +#define prof_recent_alloc_dump JEMALLOC_N(prof_recent_alloc_dump) +#define prof_recent_alloc_edata_get_no_lock_test JEMALLOC_N(prof_recent_alloc_edata_get_no_lock_test) +#define prof_recent_alloc_list JEMALLOC_N(prof_recent_alloc_list) +#define prof_recent_alloc_max_ctl_read JEMALLOC_N(prof_recent_alloc_max_ctl_read) +#define prof_recent_alloc_max_ctl_write JEMALLOC_N(prof_recent_alloc_max_ctl_write) +#define prof_recent_alloc_mtx JEMALLOC_N(prof_recent_alloc_mtx) +#define prof_recent_alloc_prepare JEMALLOC_N(prof_recent_alloc_prepare) +#define prof_recent_alloc_reset JEMALLOC_N(prof_recent_alloc_reset) +#define prof_recent_dump_mtx JEMALLOC_N(prof_recent_dump_mtx) +#define prof_recent_init JEMALLOC_N(prof_recent_init) +#define opt_prof_stats JEMALLOC_N(opt_prof_stats) +#define prof_stats_dec JEMALLOC_N(prof_stats_dec) +#define prof_stats_get_accum JEMALLOC_N(prof_stats_get_accum) +#define prof_stats_get_live JEMALLOC_N(prof_stats_get_live) +#define prof_stats_inc JEMALLOC_N(prof_stats_inc) +#define prof_stats_mtx JEMALLOC_N(prof_stats_mtx) +#define bt_init JEMALLOC_N(bt_init) +#define prof_backtrace JEMALLOC_N(prof_backtrace) +#define prof_base JEMALLOC_N(prof_base) +#define prof_do_mock JEMALLOC_N(prof_do_mock) +#define prof_dump_filename_mtx JEMALLOC_N(prof_dump_filename_mtx) +#define prof_dump_open_file JEMALLOC_N(prof_dump_open_file) +#define prof_dump_open_maps JEMALLOC_N(prof_dump_open_maps) +#define prof_dump_write_file JEMALLOC_N(prof_dump_write_file) +#define prof_fdump_impl JEMALLOC_N(prof_fdump_impl) +#define prof_gdump_impl JEMALLOC_N(prof_gdump_impl) +#define prof_get_default_filename JEMALLOC_N(prof_get_default_filename) +#define prof_getpid JEMALLOC_N(prof_getpid) +#define prof_hooks_init JEMALLOC_N(prof_hooks_init) +#define prof_idump_impl JEMALLOC_N(prof_idump_impl) +#define prof_mdump_impl JEMALLOC_N(prof_mdump_impl) +#define prof_prefix_set JEMALLOC_N(prof_prefix_set) +#define prof_sys_thread_name_fetch JEMALLOC_N(prof_sys_thread_name_fetch) +#define prof_sys_thread_name_read JEMALLOC_N(prof_sys_thread_name_read) +#define prof_unwind_init JEMALLOC_N(prof_unwind_init) +#define psset_init JEMALLOC_N(psset_init) +#define psset_insert JEMALLOC_N(psset_insert) +#define psset_pick_alloc JEMALLOC_N(psset_pick_alloc) +#define psset_pick_hugify JEMALLOC_N(psset_pick_hugify) +#define psset_pick_purge JEMALLOC_N(psset_pick_purge) +#define psset_remove JEMALLOC_N(psset_remove) +#define psset_stats_accum JEMALLOC_N(psset_stats_accum) +#define psset_update_begin JEMALLOC_N(psset_update_begin) +#define psset_update_end JEMALLOC_N(psset_update_end) #define rtree_ctx_data_init JEMALLOC_N(rtree_ctx_data_init) -#define rtree_leaf_alloc JEMALLOC_N(rtree_leaf_alloc) -#define rtree_leaf_dalloc JEMALLOC_N(rtree_leaf_dalloc) #define rtree_leaf_elm_lookup_hard JEMALLOC_N(rtree_leaf_elm_lookup_hard) #define rtree_new JEMALLOC_N(rtree_new) -#define rtree_node_alloc JEMALLOC_N(rtree_node_alloc) -#define rtree_node_dalloc JEMALLOC_N(rtree_node_dalloc) #define safety_check_fail JEMALLOC_N(safety_check_fail) +#define safety_check_fail_sized_dealloc JEMALLOC_N(safety_check_fail_sized_dealloc) #define safety_check_set_abort JEMALLOC_N(safety_check_set_abort) +#define reg_size_compute JEMALLOC_N(reg_size_compute) +#define sc_boot JEMALLOC_N(sc_boot) +#define sc_data_init JEMALLOC_N(sc_data_init) +#define sc_data_update_slab_size JEMALLOC_N(sc_data_update_slab_size) +#define sec_disable JEMALLOC_N(sec_disable) +#define sec_flush JEMALLOC_N(sec_flush) +#define sec_init JEMALLOC_N(sec_init) +#define sec_mutex_stats_read JEMALLOC_N(sec_mutex_stats_read) +#define sec_postfork_child JEMALLOC_N(sec_postfork_child) +#define sec_postfork_parent JEMALLOC_N(sec_postfork_parent) +#define sec_prefork2 JEMALLOC_N(sec_prefork2) +#define sec_stats_merge JEMALLOC_N(sec_stats_merge) #define arena_mutex_names JEMALLOC_N(arena_mutex_names) #define global_mutex_names JEMALLOC_N(global_mutex_names) +#define opt_stats_interval JEMALLOC_N(opt_stats_interval) +#define opt_stats_interval_opts JEMALLOC_N(opt_stats_interval_opts) #define opt_stats_print JEMALLOC_N(opt_stats_print) #define opt_stats_print_opts JEMALLOC_N(opt_stats_print_opts) +#define stats_boot JEMALLOC_N(stats_boot) +#define stats_interval_event_handler JEMALLOC_N(stats_interval_event_handler) +#define stats_interval_new_event_wait JEMALLOC_N(stats_interval_new_event_wait) +#define stats_interval_postponed_event_wait JEMALLOC_N(stats_interval_postponed_event_wait) +#define stats_postfork_child JEMALLOC_N(stats_postfork_child) +#define stats_postfork_parent JEMALLOC_N(stats_postfork_parent) +#define stats_prefork JEMALLOC_N(stats_prefork) #define stats_print JEMALLOC_N(stats_print) -#define sc_boot JEMALLOC_N(sc_boot) -#define sc_data_global JEMALLOC_N(sc_data_global) -#define sc_data_init JEMALLOC_N(sc_data_init) -#define sc_data_update_slab_size JEMALLOC_N(sc_data_update_slab_size) #define sz_boot JEMALLOC_N(sz_boot) #define sz_index2size_tab JEMALLOC_N(sz_index2size_tab) +#define sz_large_pad JEMALLOC_N(sz_large_pad) #define sz_pind2sz_tab JEMALLOC_N(sz_pind2sz_tab) +#define sz_psz_quantize_ceil JEMALLOC_N(sz_psz_quantize_ceil) +#define sz_psz_quantize_floor JEMALLOC_N(sz_psz_quantize_floor) #define sz_size2index_tab JEMALLOC_N(sz_size2index_tab) #define nhbins JEMALLOC_N(nhbins) -#define opt_lg_tcache_max JEMALLOC_N(opt_lg_tcache_max) +#define opt_lg_tcache_flush_large_div JEMALLOC_N(opt_lg_tcache_flush_large_div) +#define opt_lg_tcache_flush_small_div JEMALLOC_N(opt_lg_tcache_flush_small_div) +#define opt_lg_tcache_nslots_mul JEMALLOC_N(opt_lg_tcache_nslots_mul) #define opt_tcache JEMALLOC_N(opt_tcache) +#define opt_tcache_gc_delay_bytes JEMALLOC_N(opt_tcache_gc_delay_bytes) +#define opt_tcache_gc_incr_bytes JEMALLOC_N(opt_tcache_gc_incr_bytes) +#define opt_tcache_max JEMALLOC_N(opt_tcache_max) +#define opt_tcache_nslots_large JEMALLOC_N(opt_tcache_nslots_large) +#define opt_tcache_nslots_small_max JEMALLOC_N(opt_tcache_nslots_small_max) +#define opt_tcache_nslots_small_min JEMALLOC_N(opt_tcache_nslots_small_min) #define tcache_alloc_small_hard JEMALLOC_N(tcache_alloc_small_hard) #define tcache_arena_associate JEMALLOC_N(tcache_arena_associate) #define tcache_arena_reassociate JEMALLOC_N(tcache_arena_reassociate) +#define tcache_assert_initialized JEMALLOC_N(tcache_assert_initialized) #define tcache_bin_flush_large JEMALLOC_N(tcache_bin_flush_large) #define tcache_bin_flush_small JEMALLOC_N(tcache_bin_flush_small) +#define tcache_bin_flush_stashed JEMALLOC_N(tcache_bin_flush_stashed) #define tcache_bin_info JEMALLOC_N(tcache_bin_info) #define tcache_boot JEMALLOC_N(tcache_boot) #define tcache_cleanup JEMALLOC_N(tcache_cleanup) #define tcache_create_explicit JEMALLOC_N(tcache_create_explicit) -#define tcache_event_hard JEMALLOC_N(tcache_event_hard) #define tcache_flush JEMALLOC_N(tcache_flush) +#define tcache_gc_dalloc_event_handler JEMALLOC_N(tcache_gc_dalloc_event_handler) +#define tcache_gc_dalloc_new_event_wait JEMALLOC_N(tcache_gc_dalloc_new_event_wait) +#define tcache_gc_dalloc_postponed_event_wait JEMALLOC_N(tcache_gc_dalloc_postponed_event_wait) +#define tcache_gc_event_handler JEMALLOC_N(tcache_gc_event_handler) +#define tcache_gc_new_event_wait JEMALLOC_N(tcache_gc_new_event_wait) +#define tcache_gc_postponed_event_wait JEMALLOC_N(tcache_gc_postponed_event_wait) #define tcache_maxclass JEMALLOC_N(tcache_maxclass) #define tcache_postfork_child JEMALLOC_N(tcache_postfork_child) #define tcache_postfork_parent JEMALLOC_N(tcache_postfork_parent) @@ -391,9 +690,13 @@ #define tsd_tcache_enabled_data_init JEMALLOC_N(tsd_tcache_enabled_data_init) #define test_hooks_arena_new_hook JEMALLOC_N(test_hooks_arena_new_hook) #define test_hooks_libc_hook JEMALLOC_N(test_hooks_libc_hook) +#define te_assert_invariants_debug JEMALLOC_N(te_assert_invariants_debug) +#define te_event_trigger JEMALLOC_N(te_event_trigger) +#define te_recompute_fast_threshold JEMALLOC_N(te_recompute_fast_threshold) +#define tsd_te_init JEMALLOC_N(tsd_te_init) +#define ticker_geom_table JEMALLOC_N(ticker_geom_table) #define malloc_tsd_boot0 JEMALLOC_N(malloc_tsd_boot0) #define malloc_tsd_boot1 JEMALLOC_N(malloc_tsd_boot1) -#define malloc_tsd_cleanup_register JEMALLOC_N(malloc_tsd_cleanup_register) #define malloc_tsd_dalloc JEMALLOC_N(malloc_tsd_dalloc) #define malloc_tsd_malloc JEMALLOC_N(malloc_tsd_malloc) #define tsd_booted JEMALLOC_N(tsd_booted) diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/public_namespace.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/public_namespace.h index 78d5c66377c3..6363f085f34b 100644 --- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/public_namespace.h +++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/internal/public_namespace.h @@ -7,11 +7,12 @@ #define je_mallctlnametomib JEMALLOC_N(mallctlnametomib) #define je_malloc JEMALLOC_N(malloc) #define je_malloc_conf JEMALLOC_N(malloc_conf) +#define je_malloc_conf_2_conf_harder JEMALLOC_N(malloc_conf_2_conf_harder) #define je_malloc_message JEMALLOC_N(malloc_message) #define je_malloc_stats_print JEMALLOC_N(malloc_stats_print) #define je_malloc_usable_size JEMALLOC_N(malloc_usable_size) #define je_mallocx JEMALLOC_N(mallocx) -#define je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 JEMALLOC_N(smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756) +#define je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c JEMALLOC_N(smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c) #define je_nallocx JEMALLOC_N(nallocx) #define je_posix_memalign JEMALLOC_N(posix_memalign) #define je_rallocx JEMALLOC_N(rallocx) @@ -19,4 +20,5 @@ #define je_sallocx JEMALLOC_N(sallocx) #define je_sdallocx JEMALLOC_N(sdallocx) #define je_xallocx JEMALLOC_N(xallocx) +#define je_memalign JEMALLOC_N(memalign) #define je_valloc JEMALLOC_N(valloc) diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc.h index c3fa08e83f22..f9ed38656a87 100644 --- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc.h +++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc.h @@ -19,6 +19,12 @@ extern "C" { /* Defined if format(printf, ...) attribute is supported. */ #define JEMALLOC_HAVE_ATTR_FORMAT_PRINTF +/* Defined if fallthrough attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_FALLTHROUGH + +/* Defined if cold attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_COLD + /* * Define overrides for non-standard allocator-related functions if they are * present on the system. @@ -68,11 +74,12 @@ extern "C" { # define je_mallctlnametomib mallctlnametomib # define je_malloc malloc # define je_malloc_conf malloc_conf +# define je_malloc_conf_2_conf_harder malloc_conf_2_conf_harder # define je_malloc_message malloc_message # define je_malloc_stats_print malloc_stats_print # define je_malloc_usable_size malloc_usable_size # define je_mallocx mallocx -# define je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 +# define je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c # define je_nallocx nallocx # define je_posix_memalign posix_memalign # define je_rallocx rallocx @@ -80,6 +87,7 @@ extern "C" { # define je_sallocx sallocx # define je_sdallocx sdallocx # define je_xallocx xallocx +# define je_memalign memalign # define je_valloc valloc #endif @@ -91,13 +99,13 @@ extern "C" { #include <limits.h> #include <strings.h> -#define JEMALLOC_VERSION "5.2.1-0-gea6b3e973b477b8061e0076bb257dbd7f3faa756" +#define JEMALLOC_VERSION "5.3.0-0-g54eaed1d8b56b1aa528be3bdd1877e59c56fa90c" #define JEMALLOC_VERSION_MAJOR 5 -#define JEMALLOC_VERSION_MINOR 2 -#define JEMALLOC_VERSION_BUGFIX 1 +#define JEMALLOC_VERSION_MINOR 3 +#define JEMALLOC_VERSION_BUGFIX 0 #define JEMALLOC_VERSION_NREV 0 -#define JEMALLOC_VERSION_GID "ea6b3e973b477b8061e0076bb257dbd7f3faa756" -#define JEMALLOC_VERSION_GID_IDENT ea6b3e973b477b8061e0076bb257dbd7f3faa756 +#define JEMALLOC_VERSION_GID "54eaed1d8b56b1aa528be3bdd1877e59c56fa90c" +#define JEMALLOC_VERSION_GID_IDENT 54eaed1d8b56b1aa528be3bdd1877e59c56fa90c #define MALLOCX_LG_ALIGN(la) ((int)(la)) #if LG_SIZEOF_PTR == 2 @@ -158,6 +166,7 @@ extern "C" { # endif # define JEMALLOC_FORMAT_ARG(i) # define JEMALLOC_FORMAT_PRINTF(s, i) +# define JEMALLOC_FALLTHROUGH # define JEMALLOC_NOINLINE __declspec(noinline) # ifdef __cplusplus # define JEMALLOC_NOTHROW __declspec(nothrow) @@ -171,6 +180,7 @@ extern "C" { # else # define JEMALLOC_ALLOCATOR # endif +# define JEMALLOC_COLD #elif defined(JEMALLOC_HAVE_ATTR) # define JEMALLOC_ATTR(s) __attribute__((s)) # define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s)) @@ -196,11 +206,21 @@ extern "C" { # else # define JEMALLOC_FORMAT_PRINTF(s, i) # endif +# ifdef JEMALLOC_HAVE_ATTR_FALLTHROUGH +# define JEMALLOC_FALLTHROUGH JEMALLOC_ATTR(fallthrough) +# else +# define JEMALLOC_FALLTHROUGH +# endif # define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline) # define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow) # define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s)) # define JEMALLOC_RESTRICT_RETURN # define JEMALLOC_ALLOCATOR +# ifdef JEMALLOC_HAVE_ATTR_COLD +# define JEMALLOC_COLD JEMALLOC_ATTR(__cold__) +# else +# define JEMALLOC_COLD +# endif #else # define JEMALLOC_ATTR(s) # define JEMALLOC_ALIGNED(s) @@ -208,11 +228,19 @@ extern "C" { # define JEMALLOC_ALLOC_SIZE2(s1, s2) # define JEMALLOC_EXPORT # define JEMALLOC_FORMAT_PRINTF(s, i) +# define JEMALLOC_FALLTHROUGH # define JEMALLOC_NOINLINE # define JEMALLOC_NOTHROW # define JEMALLOC_SECTION(s) # define JEMALLOC_RESTRICT_RETURN # define JEMALLOC_ALLOCATOR +# define JEMALLOC_COLD +#endif + +#if (defined(__APPLE__) || defined(__FreeBSD__)) && !defined(JEMALLOC_NO_RENAME) +# define JEMALLOC_SYS_NOTHROW +#else +# define JEMALLOC_SYS_NOTHROW JEMALLOC_NOTHROW #endif /* @@ -225,21 +253,22 @@ extern JEMALLOC_EXPORT void (*je_malloc_message)(void *cbopaque, const char *s); JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *je_malloc(size_t size) + void JEMALLOC_SYS_NOTHROW *je_malloc(size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1); JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *je_calloc(size_t num, size_t size) + void JEMALLOC_SYS_NOTHROW *je_calloc(size_t num, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2); -JEMALLOC_EXPORT int JEMALLOC_NOTHROW je_posix_memalign(void **memptr, - size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1)); +JEMALLOC_EXPORT int JEMALLOC_SYS_NOTHROW je_posix_memalign( + void **memptr, size_t alignment, size_t size) JEMALLOC_CXX_THROW + JEMALLOC_ATTR(nonnull(1)); JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *je_aligned_alloc(size_t alignment, + void JEMALLOC_SYS_NOTHROW *je_aligned_alloc(size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(2); JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *je_realloc(void *ptr, size_t size) + void JEMALLOC_SYS_NOTHROW *je_realloc(void *ptr, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2); -JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_free(void *ptr) +JEMALLOC_EXPORT void JEMALLOC_SYS_NOTHROW je_free(void *ptr) JEMALLOC_CXX_THROW; JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN @@ -269,16 +298,20 @@ JEMALLOC_EXPORT void JEMALLOC_NOTHROW je_malloc_stats_print( const char *opts); JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_malloc_usable_size( JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW; +#ifdef JEMALLOC_HAVE_MALLOC_SIZE +JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW je_malloc_size( + const void *ptr); +#endif #ifdef JEMALLOC_OVERRIDE_MEMALIGN JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *je_memalign(size_t alignment, size_t size) + void JEMALLOC_SYS_NOTHROW *je_memalign(size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc); #endif #ifdef JEMALLOC_OVERRIDE_VALLOC JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN - void JEMALLOC_NOTHROW *je_valloc(size_t size) JEMALLOC_CXX_THROW + void JEMALLOC_SYS_NOTHROW *je_valloc(size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc); #endif @@ -380,11 +413,12 @@ struct extent_hooks_s { # define mallctlnametomib je_mallctlnametomib # define malloc je_malloc # define malloc_conf je_malloc_conf +# define malloc_conf_2_conf_harder je_malloc_conf_2_conf_harder # define malloc_message je_malloc_message # define malloc_stats_print je_malloc_stats_print # define malloc_usable_size je_malloc_usable_size # define mallocx je_mallocx -# define smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 +# define smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c # define nallocx je_nallocx # define posix_memalign je_posix_memalign # define rallocx je_rallocx @@ -412,11 +446,12 @@ struct extent_hooks_s { # undef je_mallctlnametomib # undef je_malloc # undef je_malloc_conf +# undef je_malloc_conf_2_conf_harder # undef je_malloc_message # undef je_malloc_stats_print # undef je_malloc_usable_size # undef je_mallocx -# undef je_smallocx_ea6b3e973b477b8061e0076bb257dbd7f3faa756 +# undef je_smallocx_54eaed1d8b56b1aa528be3bdd1877e59c56fa90c # undef je_nallocx # undef je_posix_memalign # undef je_rallocx diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_FreeBSD.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_FreeBSD.h index e733906bc146..34c86271ab2e 100644 --- a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_FreeBSD.h +++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_FreeBSD.h @@ -2,6 +2,8 @@ * Override settings that were generated in jemalloc_defs.h as necessary. */ +#ifndef JEMALLOC_NO_PRIVATE_NAMESPACE + #undef JEMALLOC_OVERRIDE_VALLOC #ifndef MALLOC_PRODUCTION @@ -96,8 +98,12 @@ #include <machine/cpufunc.h> #define CPU_SPINWAIT cpu_spinwait() -/* Disable lazy-lock machinery, mangle isthreaded, and adjust its type. */ +/* + * Disable lazy-lock machinery, redirect isthreaded to libc's flag, undo + * jemalloc's namespace stuff for it and adjust its type. + */ #undef JEMALLOC_LAZY_LOCK +#undef isthreaded extern int __isthreaded; #define isthreaded ((bool)__isthreaded) @@ -197,3 +203,5 @@ __sym_compat(sallocm, weak_sallocm, FBSD_1.3); __sym_compat(dallocm, weak_dallocm, FBSD_1.3); __sym_compat(nallocm, weak_nallocm, FBSD_1.3); #endif + +#endif diff --git a/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_defs.h b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_defs.h new file mode 100644 index 000000000000..fb104aaeec98 --- /dev/null +++ b/lib/libc/stdlib/malloc/jemalloc/include/jemalloc/jemalloc_defs.h @@ -0,0 +1,55 @@ +/* include/jemalloc/jemalloc_defs.h. Generated from jemalloc_defs.h.in by configure. */ +/* Defined if __attribute__((...)) syntax is supported. */ +#define JEMALLOC_HAVE_ATTR + +/* Defined if alloc_size attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_ALLOC_SIZE + +/* Defined if format_arg(...) attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_FORMAT_ARG + +/* Defined if format(gnu_printf, ...) attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF + +/* Defined if format(printf, ...) attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_FORMAT_PRINTF + +/* Defined if fallthrough attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_FALLTHROUGH + +/* Defined if cold attribute is supported. */ +#define JEMALLOC_HAVE_ATTR_COLD + +/* + * Define overrides for non-standard allocator-related functions if they are + * present on the system. + */ +#define JEMALLOC_OVERRIDE_MEMALIGN +#define JEMALLOC_OVERRIDE_VALLOC + +/* + * At least Linux omits the "const" in: + * + * size_t malloc_usable_size(const void *ptr); + * + * Match the operating system's prototype. + */ +#define JEMALLOC_USABLE_SIZE_CONST const + +/* + * If defined, specify throw() for the public function prototypes when compiling + * with C++. The only justification for this is to match the prototypes that + * glibc defines. + */ +/* #undef JEMALLOC_USE_CXX_THROW */ + +#ifdef _MSC_VER +# ifdef _WIN64 +# define LG_SIZEOF_PTR_WIN 3 +# else +# define LG_SIZEOF_PTR_WIN 2 +# endif +#endif + +/* sizeof(void *) == 2^LG_SIZEOF_PTR. */ +#define LG_SIZEOF_PTR 3 diff --git a/lib/libc/stdlib/qsort.c b/lib/libc/stdlib/qsort.c index e0b06494cf98..400124593d07 100644 --- a/lib/libc/stdlib/qsort.c +++ b/lib/libc/stdlib/qsort.c @@ -106,13 +106,11 @@ local_qsort(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk) char *pa, *pb, *pc, *pd, *pl, *pm, *pn; size_t d1, d2; int cmp_result; - int swap_cnt; /* if there are less than 2 elements, then sorting is not needed */ if (__predict_false(n < 2)) return; loop: - swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) for (pl = pm; @@ -141,7 +139,6 @@ loop: for (;;) { while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { if (cmp_result == 0) { - swap_cnt = 1; swapfunc(pa, pb, es); pa += es; } @@ -149,7 +146,6 @@ loop: } while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { if (cmp_result == 0) { - swap_cnt = 1; swapfunc(pc, pd, es); pd -= es; } @@ -158,18 +154,9 @@ loop: if (pb > pc) break; swapfunc(pb, pc, es); - swap_cnt = 1; pb += es; pc -= es; } - if (swap_cnt == 0) { /* Switch to insertion sort */ - for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) - for (pl = pm; - pl > (char *)a && CMP(thunk, pl - es, pl) > 0; - pl -= es) - swapfunc(pl, pl - es, es); - return; - } pn = (char *)a + n * es; d1 = MIN(pa - (char *)a, pb - pa); diff --git a/lib/libc/stdlib/reallocarray.3 b/lib/libc/stdlib/reallocarray.3 index 80035c67a497..9a2ab5c7a840 100644 --- a/lib/libc/stdlib/reallocarray.3 +++ b/lib/libc/stdlib/reallocarray.3 @@ -26,7 +26,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 1, 2015 +.Dd October 2, 2025 .Dt REALLOCARRAY 3 .Os .Sh NAME @@ -38,6 +38,8 @@ .In stdlib.h .Ft void * .Fn reallocarray "void *ptr" "size_t nmemb" "size_t size" +.Ft void * +.Fn recallocarray "void *ptr" "size_t oldnmeb" "size_t nmemb" size_t size" .Sh DESCRIPTION The .Fn reallocarray @@ -52,6 +54,33 @@ and checks for integer overflow in the calculation .Fa nmemb * .Fa size . +.Pp +The +.Fn recallocarray +function is similar to the +.Fn reallocarray +function +except it ensures newly allocated memory is cleared similar to +.Fn calloc . +If +.Fa ptr +is +.Dv NULL , +.Fa oldnmemb +is ignored and the call is equivalent to +.Fn calloc . +If +.Fa ptr +is not +.Dv NULL , +.Fa oldnmemb +must be a value such that +.Fa oldnmemb +* +.Fa size +is the size of the earlier allocation that returned +.Fa ptr , +otherwise the behaviour is undefined. .Sh RETURN VALUES The .Fn reallocarray @@ -142,3 +171,9 @@ function first appeared in .Ox 5.6 and .Fx 11.0 . +The +.Fn recallocarray +function first appeared in +.Ox 6.1 +and +.Fx 16.0 . diff --git a/lib/libc/stdlib/reallocarray.c b/lib/libc/stdlib/reallocarray.c index 0868804486cc..3632734c84de 100644 --- a/lib/libc/stdlib/reallocarray.c +++ b/lib/libc/stdlib/reallocarray.c @@ -17,23 +17,19 @@ #include <sys/types.h> #include <errno.h> +#include <stdckdint.h> #include <stdint.h> #include <stdlib.h> -/* - * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX - * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW - */ -#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) - void * reallocarray(void *optr, size_t nmemb, size_t size) { + size_t nbytes; - if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && - nmemb > 0 && SIZE_MAX / nmemb < size) { + if (ckd_mul(&nbytes, nmemb, size)) { errno = ENOMEM; return (NULL); } - return (realloc(optr, size * nmemb)); + + return (realloc(optr, nbytes)); } diff --git a/lib/libopenbsd/recallocarray.c b/lib/libc/stdlib/recallocarray.c index 11e1fda744c7..cbf1fb2470cf 100644 --- a/lib/libopenbsd/recallocarray.c +++ b/lib/libc/stdlib/recallocarray.c @@ -16,17 +16,12 @@ */ #include <errno.h> +#include <stdckdint.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <unistd.h> -/* - * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX - * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW - */ -#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) - void *recallocarray(void *, size_t, size_t, size_t); void * @@ -38,19 +33,15 @@ recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) if (ptr == NULL) return calloc(newnmemb, size); - if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && - newnmemb > 0 && SIZE_MAX / newnmemb < size) { + if (ckd_mul(&newsize, newnmemb, size)) { errno = ENOMEM; return NULL; } - newsize = newnmemb * size; - if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && - oldnmemb > 0 && SIZE_MAX / oldnmemb < size) { + if (ckd_mul(&oldsize, oldnmemb, size)) { errno = EINVAL; return NULL; } - oldsize = oldnmemb * size; /* * Don't bother too much if we're shrinking just a bit, diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc index 647cbe6f40ba..1baa39a6c0a6 100644 --- a/lib/libc/stdtime/Makefile.inc +++ b/lib/libc/stdtime/Makefile.inc @@ -32,4 +32,5 @@ MLINKS+=strftime.3 strftime_l.3 MLINKS+=strptime.3 strptime_l.3 MLINKS+=time2posix.3 posix2time.3 MLINKS+=tzset.3 daylight.3 \ - tzset.3 timezone.3 + tzset.3 timezone.3 \ + tzset.3 tzname.3 diff --git a/lib/libc/stdtime/ctime.3 b/lib/libc/stdtime/ctime.3 index 96b7f775535a..6384e8bd959b 100644 --- a/lib/libc/stdtime/ctime.3 +++ b/lib/libc/stdtime/ctime.3 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 26, 2024 +.Dd September 23, 2025 .Dt CTIME 3 .Os .Sh NAME @@ -41,6 +41,8 @@ .Nm localtime , .Nm localtime_r , .Nm mktime , +.Nm offtime , +.Nm offtime_r , .Nm timegm .Nd transform binary date and time values .Sh LIBRARY @@ -68,14 +70,19 @@ .Fn localtime_r "const time_t *clock" "struct tm *result" .Ft time_t .Fn mktime "struct tm *tm" +.Ft struct tm * +.Fn offtime "const time_t *clock" "long offset" +.Ft struct tm * +.Fn offtime_r "const time_t *clock" "long offset" "struct tm *result" .Ft time_t .Fn timegm "struct tm *tm" .Sh DESCRIPTION The .Fn ctime , .Fn gmtime , +.Fn localtime , and -.Fn localtime +.Fn offtime functions all take as argument a pointer to a time value representing the time in seconds since the Epoch (00:00:00 UTC on January 1, 1970; see @@ -123,6 +130,18 @@ adjustment, and returns a pointer to a .Vt struct tm . .Pp The +.Fn offtime +function similarly converts the time value with a time zone adjustment +corresponding to the provided +.Fa offset , +which is expressed in seconds, with positive values indicating a time +zone ahead of UTC (east of the Prime Meridian). +It does not call +.Xr tzset 3 +or modify +.Va tzname . +.Pp +The .Fn ctime function adjusts the time value for the current time zone in the same manner as @@ -155,13 +174,15 @@ except the caller must provide the output buffer .Fa buf , which must be at least 26 characters long, to store the result in. The -.Fn localtime_r +.Fn localtime_r , +.Fn gmtime_r , and -.Fn gmtime_r +.Fn offtime_r functions provide the same functionality as -.Fn localtime +.Fn localtime , +.Fn gmtime , and -.Fn gmtime +.Fn offtime respectively, except the caller must provide the output buffer .Fa result . .Pp @@ -368,6 +389,12 @@ and .Fn localtime_r functions have been available since .Fx 8.0 . +The +.Fn offtime +and +.Fn offtime_r +functions were added in +.Fx 15.0 . .Sh BUGS Except for .Fn difftime , diff --git a/lib/libc/stdtime/tzset.3 b/lib/libc/stdtime/tzset.3 index 94ccbec9aba7..33e6a556306d 100644 --- a/lib/libc/stdtime/tzset.3 +++ b/lib/libc/stdtime/tzset.3 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 25, 2023 +.Dd September 30, 2025 .Dt TZSET 3 .Os .Sh NAME @@ -58,8 +58,8 @@ specifies how this is done. .Pp If .Ev TZ -does not appear in the environment, the best available approximation to -local wall clock time, as specified by the +does not appear in the environment, the best available approximation +to local wall clock time, as specified by the .Xr tzfile 5 Ns -format file .Pa /etc/localtime @@ -68,9 +68,7 @@ is used. If .Ev TZ appears in the environment but its value is a null string, Coordinated -Universal Time -.Pq Tn UTC -is used (without leap second correction). +Universal Time (UTC) is used (without leap second correction). .Pp If .Ev TZ @@ -81,13 +79,12 @@ the rest of its value is used as a pathname of a file from which to read the time conversion information. If the first character of the pathname is a slash .Pq Ql / -it is used as -an absolute pathname; otherwise, it is used as a pathname relative to -the system time conversion information directory. +it is used as an absolute pathname; otherwise, it is used as a +pathname relative to the system time conversion information directory. .Pp -If its value does not begin with a colon, it is first used as the pathname -of a file (as described above) from which to read the time conversion -information. +If its value does not begin with a colon, it is first used as the +pathname of a file (as described above) from which to read the time +conversion information. If that file cannot be read, the value is then interpreted as a direct specification (the format is described below) of the time conversion information. @@ -96,24 +93,23 @@ If the .Ev TZ environment variable does not specify a .Xr tzfile 5 Ns -format -file and cannot be interpreted as a direct specification, -.Tn UTC -is used. +file and cannot be interpreted as a direct specification, UTC is used. .Pp After the first call to .Nm tzset , the .Vt timezone -variable is set to the difference, in seconds, between Coordinated Universal -Time (UTC) and the local time. +variable is set to the difference, in seconds, between Coordinated +Universal Time (UTC) and the local time. The .Vt daylight variable is set to 0 if the local timezone is observing standard time. -It is set to 1 if the local timezone ever observes an alternate time, such as summer time. +It is set to 1 if the local timezone ever observes an alternate time, +such as summer time. The first element of the .Vt tzname -array is the timezone name of standard time, while the second element is the -name of the altnerative time zone. +array is the timezone name of standard time, while the second element +is the name of the altnerative time zone. .Sh SPECIFICATION FORMAT When .Ev TZ @@ -151,8 +147,7 @@ minus .Pq Ql \- , plus .Pq Ql + , -and -.Tn ASCII +and ASCII .Dv NUL are allowed. .It Em offset @@ -294,10 +289,8 @@ by the file .Em posixrules in the system time conversion information directory are used, with the -standard and summer time offsets from -.Tn UTC -replaced by those specified by -the +standard and summer time offsets from UTC replaced by those specified +by the .Em offset values in .Ev TZ . @@ -315,20 +308,14 @@ local time zone file .It Pa /usr/share/zoneinfo time zone directory .It Pa /usr/share/zoneinfo/posixrules -rules for -.Tn POSIX Ns -style -.Tn TZ Ns 's +rules for POSIX-style TZs .It Pa /usr/share/zoneinfo/Etc/GMT -for -.Tn UTC -leap seconds +for UTC leap seconds .El .Pp If the file .Pa /usr/share/zoneinfo/UTC -does not exist, -.Tn UTC -leap seconds are loaded from +does not exist, UTC leap seconds are loaded from .Pa /usr/share/zoneinfo/posixrules . .Sh SEE ALSO .Xr date 1 , diff --git a/lib/libc/tests/stdio/printfloat_test.c b/lib/libc/tests/stdio/printfloat_test.c index 031859124163..4493fe1c15d3 100644 --- a/lib/libc/tests/stdio/printfloat_test.c +++ b/lib/libc/tests/stdio/printfloat_test.c @@ -398,6 +398,18 @@ ATF_TC_BODY(subnormal_float, tc) testfmt("-0X1P-149", "%A", negative); } +ATF_TC_WITHOUT_HEAD(hexadecimal_rounding_fullprec); +ATF_TC_BODY(hexadecimal_rounding_fullprec, tc) +{ + /* Double: %.13a with binary64 mantissa=53 */ + testfmt("0x1.1234567890bbbp+0", "%.13a", 0x1.1234567890bbbp+0); + +#if defined(__aarch64__) + /* On arm64, long double is IEEE binary128 (mantissa=113) */ + testfmt("0x1.3c0ca428c59fbbbbbbbbbbbbbbbbp+0", "%.28La", 0x1.3c0ca428c59fbbbbbbbbbbbbbbbbp+0L); +#endif +} + ATF_TP_ADD_TCS(tp) { @@ -414,6 +426,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, hexadecimal_rounding); ATF_TP_ADD_TC(tp, subnormal_double); ATF_TP_ADD_TC(tp, subnormal_float); + ATF_TP_ADD_TC(tp, hexadecimal_rounding_fullprec); return (atf_no_error()); } diff --git a/lib/libc/tests/stdlib/Makefile b/lib/libc/tests/stdlib/Makefile index 50726a5d8af6..9d84becfbd1f 100644 --- a/lib/libc/tests/stdlib/Makefile +++ b/lib/libc/tests/stdlib/Makefile @@ -14,6 +14,7 @@ ATF_TESTS_C+= qsort_b_test ATF_TESTS_C+= qsort_r_compat_test ATF_TESTS_C+= qsort_r_test ATF_TESTS_C+= qsort_s_test +ATF_TESTS_C+= qsort_bench ATF_TESTS_C+= set_constraint_handler_s_test ATF_TESTS_C+= strfmon_test ATF_TESTS_C+= tsearch_test diff --git a/lib/libc/tests/stdlib/qsort_bench.c b/lib/libc/tests/stdlib/qsort_bench.c new file mode 100644 index 000000000000..5f2cfae40140 --- /dev/null +++ b/lib/libc/tests/stdlib/qsort_bench.c @@ -0,0 +1,113 @@ +/*- + * Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <atf-c.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +/*- + * Measures qsort(3) runtime with pathological input and verify that it + * stays close to N * log2(N). + * + * Thanks to Vivian Hussey for the proof of concept. + * + * The input we construct is similar to a sweep from 0 to N where each + * half, except for the first element, has been reversed; for instance, + * with N = 8, we get { 0, 3, 2, 1, 4, 8, 7, 6 }. This triggers a bug in + * the BSD qsort(3) where it will switch to insertion sort if the pivots + * are sorted. + * + * This article goes into more detail about the bug and its origin: + * + * https://www.raygard.net/2022/02/26/Re-engineering-a-qsort-part-3 + * + * With this optimization (the `if (swap_cnt == 0)` block), qsort(3) needs + * roughly N * N / 4 comparisons to sort our pathological input. Without + * it, it needs only a little more than N * log2(N) comparisons. + */ + +/* we stop testing once a single takes longer than this */ +#define MAXRUNSECS 10 + +static bool debugging; + +static uintmax_t ncmp; + +static int +intcmp(const void *a, const void *b) +{ + ncmp++; + return ((*(int *)a > *(int *)b) - (*(int *)a < *(int *)b)); +} + +static void +qsort_bench(int log2n) +{ + uintmax_t n = 1LLU << log2n; + int *buf; + + /* fill an array with a pathological pattern */ + ATF_REQUIRE(buf = malloc(n * sizeof(*buf))); + buf[0] = 0; + buf[n / 2] = n / 2; + for (unsigned int i = 1; i < n / 2; i++) { + buf[i] = n / 2 - i; + buf[n / 2 + i] = n - i; + } + + ncmp = 0; + qsort(buf, n, sizeof(*buf), intcmp); + + /* check result and free array */ + if (debugging) { + for (unsigned int i = 1; i < n; i++) { + ATF_REQUIRE_MSG(buf[i] > buf[i - 1], + "array is not sorted"); + } + } + free(buf); + + /* check that runtime does not exceed N² */ + ATF_CHECK_MSG(ncmp / n < n, + "runtime %ju exceeds N² for N = %ju", ncmp, n); + + /* check that runtime does not exceed N log N by much */ + ATF_CHECK_MSG(ncmp / n <= log2n + 1, + "runtime %ju exceeds N log N for N = %ju", ncmp, n); +} + +ATF_TC_WITHOUT_HEAD(qsort_bench); +ATF_TC_BODY(qsort_bench, tc) +{ + struct timespec t0, t1; + uintmax_t tus; + + for (int i = 10; i <= 30; i++) { + clock_gettime(CLOCK_UPTIME, &t0); + qsort_bench(i); + clock_gettime(CLOCK_UPTIME, &t1); + tus = t1.tv_sec * 1000000 + t1.tv_nsec / 1000; + tus -= t0.tv_sec * 1000000 + t0.tv_nsec / 1000; + if (debugging) { + fprintf(stderr, "N = 2^%d in %ju.%06jus\n", + i, tus / 1000000, tus % 1000000); + } + /* stop once an individual run exceeds our limit */ + if (tus / 1000000 >= MAXRUNSECS) + break; + } +} + +ATF_TP_ADD_TCS(tp) +{ + debugging = !getenv("__RUNNING_INSIDE_ATF_RUN") && + isatty(STDERR_FILENO); + ATF_TP_ADD_TC(tp, qsort_bench); + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdtime/Makefile b/lib/libc/tests/stdtime/Makefile index adb883cc5b9a..590dea22da31 100644 --- a/lib/libc/tests/stdtime/Makefile +++ b/lib/libc/tests/stdtime/Makefile @@ -1,8 +1,11 @@ .include <src.opts.mk> ATF_TESTS_C+= strptime_test -.if ${MK_DETECT_TZ_CHANGES} != "no" ATF_TESTS_C+= detect_tz_changes_test + +CFLAGS.detect_tz_changes_test+= -I${SRCTOP}/contrib/tzcode +.if ${MK_DETECT_TZ_CHANGES} != "no" +CFLAGS.detect_tz_changes_test+= -DDETECT_TZ_CHANGES .endif TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/} diff --git a/lib/libc/tests/stdtime/detect_tz_changes_test.c b/lib/libc/tests/stdtime/detect_tz_changes_test.c index 9722546747fd..06c31c9fbc3d 100644 --- a/lib/libc/tests/stdtime/detect_tz_changes_test.c +++ b/lib/libc/tests/stdtime/detect_tz_changes_test.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <sys/param.h> +#include <sys/conf.h> #include <sys/stat.h> #include <sys/wait.h> @@ -18,13 +20,34 @@ #include <time.h> #include <unistd.h> +#include "tzdir.h" + #include <atf-c.h> +struct tzcase { + const char *tzfn; + const char *expect; +}; + +static const struct tzcase tzcases[] = { + /* + * A handful of time zones and the expected result of + * strftime("%z (%Z)", tm) when that time zone is active + * and tm represents a date in the summer of 2025. + */ + { "America/Vancouver", "-0700 (PDT)" }, + { "America/New_York", "-0400 (EDT)" }, + { "Europe/London", "+0100 (BST)" }, + { "Europe/Paris", "+0200 (CEST)" }, + { "Asia/Kolkata", "+0530 (IST)" }, + { "Asia/Tokyo", "+0900 (JST)" }, + { "Australia/Canberra", "+1000 (AEST)" }, + { "UTC", "+0000 (UTC)" }, + { 0 }, +}; +static const struct tzcase utc = { "UTC", "+0000 (UTC)" }; +static const struct tzcase invalid = { "invalid", "+0000 (-00)" }; static const time_t then = 1751328000; /* 2025-07-01 00:00:00 UTC */ -static const char *tz_change_interval_sym = "__tz_change_interval"; -static int *tz_change_interval_p; -static const int tz_change_interval = 3; -static int tz_change_timeout = 90; static bool debugging; @@ -44,15 +67,15 @@ debug(const char *fmt, ...) static void change_tz(const char *tzn) { - static const char *zfn = "/usr/share/zoneinfo"; - static const char *tfn = "root/etc/.localtime"; - static const char *dfn = "root/etc/localtime"; + static const char *zfn = TZDIR; + static const char *tfn = "root" TZDEFAULT ".tmp"; + static const char *dfn = "root" TZDEFAULT; ssize_t clen; int zfd, sfd, dfd; ATF_REQUIRE((zfd = open(zfn, O_DIRECTORY | O_SEARCH)) >= 0); ATF_REQUIRE((sfd = openat(zfd, tzn, O_RDONLY)) >= 0); - ATF_REQUIRE((dfd = open(tfn, O_CREAT | O_TRUNC | O_WRONLY)) >= 0); + ATF_REQUIRE((dfd = open(tfn, O_CREAT | O_TRUNC | O_WRONLY, 0644)) >= 0); do { clen = copy_file_range(sfd, NULL, dfd, NULL, SSIZE_MAX, 0); ATF_REQUIRE_MSG(clen != -1, "failed to copy %s/%s: %m", @@ -65,6 +88,86 @@ change_tz(const char *tzn) debug("time zone %s installed", tzn); } +static void +test_tz(const char *expect) +{ + char buf[128]; + struct tm *tm; + size_t len; + + ATF_REQUIRE((tm = localtime(&then)) != NULL); + len = strftime(buf, sizeof(buf), "%z (%Z)", tm); + ATF_REQUIRE(len > 0); + ATF_CHECK_STREQ(expect, buf); +} + +ATF_TC(tz_default); +ATF_TC_HEAD(tz_default, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test default zone"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(tz_default, tc) +{ + /* prepare chroot with no /etc/localtime */ + ATF_REQUIRE_EQ(0, mkdir("root", 0755)); + ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755)); + /* enter chroot */ + ATF_REQUIRE_EQ(0, chroot("root")); + ATF_REQUIRE_EQ(0, chdir("/")); + /* check timezone */ + unsetenv("TZ"); + test_tz("+0000 (UTC)"); +} + +ATF_TC(tz_invalid_file); +ATF_TC_HEAD(tz_invalid_file, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test invalid zone file"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(tz_invalid_file, tc) +{ + static const char *dfn = "root/etc/localtime"; + int fd; + + /* prepare chroot with bogus /etc/localtime */ + ATF_REQUIRE_EQ(0, mkdir("root", 0755)); + ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755)); + ATF_REQUIRE((fd = open(dfn, O_RDWR | O_CREAT, 0644)) >= 0); + ATF_REQUIRE_EQ(8, write(fd, "invalid\n", 8)); + ATF_REQUIRE_EQ(0, close(fd)); + /* enter chroot */ + ATF_REQUIRE_EQ(0, chroot("root")); + ATF_REQUIRE_EQ(0, chdir("/")); + /* check timezone */ + unsetenv("TZ"); + test_tz(invalid.expect); +} + +ATF_TC(thin_jail); +ATF_TC_HEAD(thin_jail, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test typical thin jail scenario"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(thin_jail, tc) +{ + const struct tzcase *tzcase = tzcases; + + /* prepare chroot */ + ATF_REQUIRE_EQ(0, mkdir("root", 0755)); + ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755)); + change_tz(tzcase->tzfn); + /* enter chroot */ + ATF_REQUIRE_EQ(0, chroot("root")); + ATF_REQUIRE_EQ(0, chdir("/")); + /* check timezone */ + unsetenv("TZ"); + test_tz(tzcase->expect); +} + +#ifdef DETECT_TZ_CHANGES /* * Test time zone change detection. * @@ -82,6 +185,11 @@ change_tz(const char *tzn) * after we've received and discarded the first report from the child, * which should come almost immediately on startup. */ +static const char *tz_change_interval_sym = "__tz_change_interval"; +static int *tz_change_interval_p; +static const int tz_change_interval = 3; +static int tz_change_timeout = 90; + ATF_TC(detect_tz_changes); ATF_TC_HEAD(detect_tz_changes, tc) { @@ -91,25 +199,6 @@ ATF_TC_HEAD(detect_tz_changes, tc) } ATF_TC_BODY(detect_tz_changes, tc) { - static const struct tzcase { - const char *tzfn; - const char *expect; - } tzcases[] = { - /* - * A handful of time zones and the expected result of - * strftime("%z (%Z)", tm) when that time zone is active - * and tm represents a date in the summer of 2025. - */ - { "America/Vancouver", "-0700 (PDT)" }, - { "America/New_York", "-0400 (EDT)" }, - { "Europe/London", "+0100 (BST)" }, - { "Europe/Paris", "+0200 (CEST)" }, - { "Asia/Kolkata", "+0530 (IST)" }, - { "Asia/Tokyo", "+0900 (JST)" }, - { "Australia/Canberra", "+1000 (AEST)" }, - { "UTC", "+0000 (UTC)" }, - { 0 }, - }; char obuf[1024] = ""; char ebuf[1024] = ""; struct pollfd fds[3]; @@ -271,11 +360,118 @@ ATF_TC_BODY(detect_tz_changes, tc) ATF_REQUIRE(WIFEXITED(status)); ATF_REQUIRE_EQ(0, WEXITSTATUS(status)); } +#endif /* DETECT_TZ_CHANGES */ + +static void +test_tz_env(const char *tzval, const char *expect) +{ + setenv("TZ", tzval, 1); + test_tz(expect); +} + +static void +tz_env_common(void) +{ + char path[MAXPATHLEN]; + const struct tzcase *tzcase = tzcases; + int len; + + /* relative path */ + for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) + test_tz_env(tzcase->tzfn, tzcase->expect); + /* absolute path */ + for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) { + len = snprintf(path, sizeof(path), "%s/%s", TZDIR, tzcase->tzfn); + ATF_REQUIRE(len > 0 && (size_t)len < sizeof(path)); + test_tz_env(path, tzcase->expect); + } + /* absolute path with additional slashes */ + for (tzcase = tzcases; tzcase->tzfn != NULL; tzcase++) { + len = snprintf(path, sizeof(path), "%s/////%s", TZDIR, tzcase->tzfn); + ATF_REQUIRE(len > 0 && (size_t)len < sizeof(path)); + test_tz_env(path, tzcase->expect); + } +} + +ATF_TC(tz_env); +ATF_TC_HEAD(tz_env, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test TZ environment variable"); +} +ATF_TC_BODY(tz_env, tc) +{ + tz_env_common(); + /* escape from TZDIR is permitted when not setugid */ + test_tz_env("../zoneinfo/UTC", utc.expect); +} + + +ATF_TC(tz_invalid_env); +ATF_TC_HEAD(tz_invalid_env, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test invalid TZ value"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(tz_invalid_env, tc) +{ + test_tz_env("invalid", invalid.expect); + test_tz_env(":invalid", invalid.expect); +} + +ATF_TC(setugid); +ATF_TC_HEAD(setugid, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test setugid process"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(setugid, tc) +{ + const struct tzcase *tzcase = tzcases; + + /* prepare chroot */ + ATF_REQUIRE_EQ(0, mkdir("root", 0755)); + ATF_REQUIRE_EQ(0, mkdir("root/etc", 0755)); + change_tz(tzcase->tzfn); + /* enter chroot */ + ATF_REQUIRE_EQ(0, chroot("root")); + ATF_REQUIRE_EQ(0, chdir("/")); + /* become setugid */ + ATF_REQUIRE_EQ(0, seteuid(UID_NOBODY)); + ATF_REQUIRE(issetugid()); + /* check timezone */ + unsetenv("TZ"); + test_tz(tzcases->expect); +} + +ATF_TC(tz_env_setugid); +ATF_TC_HEAD(tz_env_setugid, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test TZ environment variable " + "in setugid process"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(tz_env_setugid, tc) +{ + ATF_REQUIRE_EQ(0, seteuid(UID_NOBODY)); + ATF_REQUIRE(issetugid()); + tz_env_common(); + /* escape from TZDIR is not permitted when setugid */ + test_tz_env("../zoneinfo/UTC", invalid.expect); +} ATF_TP_ADD_TCS(tp) { debugging = !getenv("__RUNNING_INSIDE_ATF_RUN") && isatty(STDERR_FILENO); + ATF_TP_ADD_TC(tp, tz_default); + ATF_TP_ADD_TC(tp, tz_invalid_file); + ATF_TP_ADD_TC(tp, thin_jail); +#ifdef DETECT_TZ_CHANGES ATF_TP_ADD_TC(tp, detect_tz_changes); +#endif /* DETECT_TZ_CHANGES */ + ATF_TP_ADD_TC(tp, tz_env); + ATF_TP_ADD_TC(tp, tz_invalid_env); + ATF_TP_ADD_TC(tp, setugid); + ATF_TP_ADD_TC(tp, tz_env_setugid); return (atf_no_error()); } diff --git a/lib/libc/tests/string/memcmp_test.c b/lib/libc/tests/string/memcmp_test.c index 5286a0b994f3..fa2f498ccfaf 100644 --- a/lib/libc/tests/string/memcmp_test.c +++ b/lib/libc/tests/string/memcmp_test.c @@ -41,14 +41,14 @@ #endif /* - * On FreeBSD we demand that memcmp returns the difference between the - * characters at the first site of mismatch. However, ISO/IEC 9899:1990 - * only specifies that a number greater than, equal to, or less than - * zero shall be returned. If a unit test for this less strict - * behaviour is desired, define RES(x) to be (((x) > 0) - ((x) < 0)). + * On FreeBSD we previously demanded that memcmp returns the difference + * between the characters at the first site of mismatch. However, + * ISO/IEC 9899:1990 only specifies that a number greater than, equal + * to, or less than zero shall be returned. If a unit test for the + * more strict behaviour is desired, define RES(x) to be (x). */ #ifndef RES -#define RES(x) (x) +#define RES(x) (((x) > 0) - ((x) < 0)) #endif static int (*memcmp_fn)(const void *, const void *, size_t); diff --git a/lib/libc/tests/tls/dso/Makefile b/lib/libc/tests/tls/dso/Makefile index 5efd8b29a6bd..783534ff7aae 100644 --- a/lib/libc/tests/tls/dso/Makefile +++ b/lib/libc/tests/tls/dso/Makefile @@ -6,6 +6,7 @@ SRCS= h_tls_dlopen.c MAN= PACKAGE= tests +NO_DEV_PACKAGE= LIBDIR= ${TESTSBASE}/lib/libc/tls SHLIB_MAJOR= 1 diff --git a/lib/libc/tests/tls_dso/Makefile b/lib/libc/tests/tls_dso/Makefile index 89296c643695..7cb8f98b431e 100644 --- a/lib/libc/tests/tls_dso/Makefile +++ b/lib/libc/tests/tls_dso/Makefile @@ -7,6 +7,7 @@ LIBDIR= ${TESTSBASE}/lib/libc/tls SHLIBDIR= ${TESTSBASE}/lib/libc/tls SHLIB_MAJOR= 1 PACKAGE= tests +NO_DEV_PACKAGE= WITHOUT_STATIC= WITHOUT_PROFILE= diff --git a/lib/libcom_err/Makefile b/lib/libcom_err/Makefile index f070fd534469..dab4794fcded 100644 --- a/lib/libcom_err/Makefile +++ b/lib/libcom_err/Makefile @@ -1,4 +1,5 @@ -PACKAGE= kerberos-lib +PACKAGE= kerberos +LIB_PACKAGE= LIB= com_err SRCS= com_err.c error.c diff --git a/lib/libcrypt/Makefile b/lib/libcrypt/Makefile index e939bae1bc25..2580c398155e 100644 --- a/lib/libcrypt/Makefile +++ b/lib/libcrypt/Makefile @@ -45,7 +45,7 @@ libcrypt.ald: ${.CURDIR}/${STATIC_LDSCRIPT} all: ${STATIC_LDSCRIPT} libcrypt.ald install-libcrypt.a: libcrypt.ald - ${INSTALL} ${TAG_ARGS:D${TAG_ARGS},dev} -S -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \ + ${INSTALL} ${DEV_TAG_ARGS} -S -C -o ${LIBOWN} -g ${LIBGRP} -m ${LIBMODE} \ ${_INSTALLFLAGS} libcrypt.ald ${DESTDIR}${_LIBDIR}/lib${LIB}.a realinstall: install-libcrypt.a diff --git a/lib/libdiff/Makefile b/lib/libdiff/Makefile index 8541ff424de2..25f849a69e05 100644 --- a/lib/libdiff/Makefile +++ b/lib/libdiff/Makefile @@ -8,7 +8,7 @@ INTERNALLIB= # API not published or supported. SRCS= diff_atomize_text.c diff_main.c diff_myers.c \ diff_patience.c diff_output.c diff_output_plain.c \ - diff_output_unidiff.c diff_output_edscript.c recallocarray.c + diff_output_unidiff.c diff_output_edscript.c WARNS= CFLAGS+= -I${SRCTOP}/contrib/libdiff/compat/include diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile index f0254c1f42bc..c7a54253dae9 100644 --- a/lib/libedit/Makefile +++ b/lib/libedit/Makefile @@ -1,7 +1,5 @@ # $NetBSD: Makefile,v 1.56 2016/03/02 19:24:20 christos Exp $ -PACKAGE=clibs - EDITDIR= ${SRCTOP}/contrib/libedit .PATH: ${EDITDIR} @@ -93,6 +91,7 @@ tc1.o: ${EDITDIR}/TEST/tc1.c test: tc1.o libedit.a ${DPADD} ${LIBTERMCAP} ${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} +.include "Makefile.inc" .include <bsd.lib.mk> CWARNFLAGS.chartype.c= ${NO_WUSE_AFTER_FREE} diff --git a/lib/libedit/Makefile.inc b/lib/libedit/Makefile.inc new file mode 100644 index 000000000000..9ec65b0d266f --- /dev/null +++ b/lib/libedit/Makefile.inc @@ -0,0 +1 @@ +PACKAGE?=runtime diff --git a/lib/libelftc/Makefile b/lib/libelftc/Makefile index a932b0c4b2a4..a6079b817d87 100644 --- a/lib/libelftc/Makefile +++ b/lib/libelftc/Makefile @@ -1,5 +1,6 @@ .include <bsd.own.mk> +PACKAGE= toolchain INTERNALLIB= ELFTCDIR= ${SRCTOP}/contrib/elftoolchain diff --git a/lib/libexpat/expat_config.h b/lib/libexpat/expat_config.h index 748f75ee157d..565404f1577b 100644 --- a/lib/libexpat/expat_config.h +++ b/lib/libexpat/expat_config.h @@ -31,7 +31,7 @@ /* Define to 1 if you have the <fcntl.h> header file. */ #define HAVE_FCNTL_H 1 -/* Define to 1 if you have the `getpagesize' function. */ +/* Define to 1 if you have the 'getpagesize' function. */ #define HAVE_GETPAGESIZE 1 /* Define to 1 if you have the `getrandom' function. */ @@ -40,10 +40,10 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #define HAVE_INTTYPES_H 1 -/* Define to 1 if you have the `bsd' library (-lbsd). */ +/* Define to 1 if you have the 'bsd' library (-lbsd). */ /* #undef HAVE_LIBBSD */ -/* Define to 1 if you have a working `mmap' system call. */ +/* Define to 1 if you have a working 'mmap' system call. */ #define HAVE_MMAP 1 /* Define to 1 if you have the <stdint.h> header file. */ @@ -89,7 +89,7 @@ #define PACKAGE_NAME "expat" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "expat 2.7.1" +#define PACKAGE_STRING "expat 2.7.3" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "expat" @@ -98,15 +98,15 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "2.7.1" +#define PACKAGE_VERSION "2.7.3" -/* Define to 1 if all of the C90 standard headers exist (not just the ones +/* Define to 1 if all of the C89 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #define STDC_HEADERS 1 /* Version number of package */ -#define VERSION "2.7.1" +#define VERSION "2.7.3" /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ @@ -140,10 +140,10 @@ /* Define to make XML Namespaces functionality available. */ #define XML_NS 1 -/* Define to empty if `const' does not conform to ANSI C. */ +/* Define to empty if 'const' does not conform to ANSI C. */ /* #undef const */ -/* Define to `long int' if <sys/types.h> does not define. */ +/* Define to 'long int' if <sys/types.h> does not define. */ /* #undef off_t */ #endif // ndef EXPAT_CONFIG_H diff --git a/lib/libexpat/libbsdxml.3 b/lib/libexpat/libbsdxml.3 index c91184840b70..d25249bbc155 100644 --- a/lib/libexpat/libbsdxml.3 +++ b/lib/libexpat/libbsdxml.3 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\"/ -.Dd April 7, 2025 +.Dd September 28, 2025 .Dt LIBBSDXML 3 .Os .Sh NAME @@ -34,7 +34,7 @@ .Sh DESCRIPTION The .Nm -library is a verbatim copy of the eXpat XML library version 2.7.1. +library is a verbatim copy of the eXpat XML library version 2.7.3. .Pp The .Nm diff --git a/lib/libfido2/Makefile b/lib/libfido2/Makefile index 10c008967e3d..021a32dd514b 100644 --- a/lib/libfido2/Makefile +++ b/lib/libfido2/Makefile @@ -43,7 +43,6 @@ SRCS+= u2f.c SRCS+= util.c SRCS+= openbsd-compat/freezero.c -SRCS+= openbsd-compat/recallocarray.c CFLAGS+= -I ${DIST}/src -I${SRCTOP}/contrib/libcbor/src -I${.CURDIR}/../libcbor CFLAGS+= -D_FIDO_INTERNAL diff --git a/lib/libgpio/Makefile b/lib/libgpio/Makefile index 42f822e97ba0..271595339792 100644 --- a/lib/libgpio/Makefile +++ b/lib/libgpio/Makefile @@ -27,6 +27,8 @@ MLINKS= gpio.3 gpio_open.3 \ gpio.3 gpio_pin_pulldown.3 \ gpio.3 gpio_pin_invin.3 \ gpio.3 gpio_pin_invout.3 \ - gpio.3 gpio_pin_pulsate.3 + gpio.3 gpio_pin_pulsate.3 \ + gpio.3 gpio_configure_events.3 \ + gpio.3 gpio_fileno.3 .include <bsd.lib.mk> diff --git a/lib/libgpio/gpio.3 b/lib/libgpio/gpio.3 index ed2860776c3c..cb413b838bd0 100644 --- a/lib/libgpio/gpio.3 +++ b/lib/libgpio/gpio.3 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd July 1, 2015 +.Dd September 3, 2025 .Dt GPIO 3 .Os .Sh NAME @@ -79,6 +79,10 @@ .Fn gpio_pin_invout "gpio_handle_t handle" "gpio_pin_t pin" .Ft int .Fn gpio_pin_pulsate "gpio_handle_t handle" "gpio_pin_t pin" +.Ft int +.Fn gpio_configure_events "gpio_handle_t handle" "uint32_t report_type" "uint32_t fifo_size" +.Ft int +.Fn gpio_fileno "gpio_handle_t handle" .Sh DESCRIPTION The .Nm libgpio @@ -125,7 +129,7 @@ The pin number should also be passed in through the variable. All other structure members will be ignored by this function. The list of flags can be found in -.Pa /usr/include/sys/gpio.h . +.In sys/gpio.h . .Pp The get or set the state of a GPIO pin, the functions .Fn gpio_pin_get @@ -156,6 +160,66 @@ and .Fn gpio_pin_pulsate are wrappers around .Fn gpio_pin_set_flags . +.Pp +The function +.Fn gpio_configure_events +configures the interrupt report type and FIFO size for buffered +gpio interrupts. +The report type is specified by one of the following values: +.Bl -tag -width indent +.It Dv GPIO_EVENT_REPORT_DETAIL +Events are reported using +.Ft struct gpio_event_detail . +.It Dv GPIO_EVENT_REPORT_SUMMARY +Events are reported using +.Ft struct gpio_event_summary . +.El +.Pp +By default, the report type is +.Dv GPIO_EVENT_REPORT_DETAIL , +with a default FIFO size of 2 * number of pins belonging to the +.Ft gpio_device_t +instance. +The FIFO argument is only meaningful when +.Fa report_type +is +.Dv GPIO_EVENT_REPORT_DETAIL . +The structures associated with each report type are defined in +.In sys/gpio.h . +This setting is tracked on a per device instance basis. +The FIFO size cannot be reduced below the default value, +nor can it be decreased after it has been increased. +If any pin on the device has already been configured for interrupts, +.Fn gpio_configure_events +fails and returns -1. +On success 0 is returned. +.Pp +The function +.Fn gpio_fileno +returns the file descriptor associated with the +.Ft gpio_handle_t +instance. +.Pp +File operations have the following semantics: +.Bl -tag -width "read (2)" +.It Xr read 2 +Read one or more gpio interrupts that have occured +since the last successful +.Xr read 2 . +The results are placed into the output buffer +of the type previously established via +.Fn gpio_configure_events . +If there are no pending interrupts, +.Xr read 2 +blocks until an interrupt occurs, unless +.Dv O_NONBLOCK +is set. +.It Xr poll 2 +When receiving notification via +.Xr poll 2 +or similar interfaces, the file descriptor becomes readable when +one or more gpio interrupts are pending. +.El .Sh EXAMPLES The following example shows how to configure pin 16 as output and then drive it high: diff --git a/lib/libgpio/gpio.c b/lib/libgpio/gpio.c index e37ac1cdf8e8..c789bb34cacd 100644 --- a/lib/libgpio/gpio.c +++ b/lib/libgpio/gpio.c @@ -274,3 +274,23 @@ gpio_pin_pulsate(gpio_handle_t handle, gpio_pin_t pin) { return (gpio_pin_set_flag(handle, pin, GPIO_PIN_PULSATE)); } + +int +gpio_configure_events(gpio_handle_t handle, uint32_t report_type, + uint32_t fifo_size) +{ + struct gpio_event_config gpevent_config; + + gpevent_config.gp_report_type = report_type; + gpevent_config.gp_fifo_size = fifo_size; + if (ioctl(handle, GPIOCONFIGEVENTS, &gpevent_config) < 0) + return (-1); + + return (0); +} + +int +gpio_fileno(gpio_handle_t handle) +{ + return (handle); +} diff --git a/lib/libgpio/libgpio.h b/lib/libgpio/libgpio.h index 35651ecd8cca..abffc7b1b6ab 100644 --- a/lib/libgpio/libgpio.h +++ b/lib/libgpio/libgpio.h @@ -102,6 +102,19 @@ int gpio_pin_pulldown(gpio_handle_t, gpio_pin_t); int gpio_pin_invin(gpio_handle_t, gpio_pin_t); int gpio_pin_invout(gpio_handle_t, gpio_pin_t); int gpio_pin_pulsate(gpio_handle_t, gpio_pin_t); +/* + * GPIO event reporting configuration + * + * Set the event reporting type, the default being GPIO_EVENT_REPORT_DETAIL, + * and fifo size of 2 * number of pins belonging to the gpioc device instance. + * FIFO size can only be changed when report_type is GPIO_EVENT_REPORT_DETAIL. + */ +int gpio_configure_events(gpio_handle_t, uint32_t, uint32_t); +/* + * Retrieve the file descriptor associated with gpio_handle_t, which can + * be used for gpio interrupts. + */ +int gpio_fileno(gpio_handle_t); __END_DECLS diff --git a/lib/libifconfig/Makefile b/lib/libifconfig/Makefile index e8e0651dc0d6..02629eb88f25 100644 --- a/lib/libifconfig/Makefile +++ b/lib/libifconfig/Makefile @@ -1,4 +1,3 @@ -PACKAGE= lib${LIB} LIB= ifconfig INTERNALLIB= true @@ -18,6 +17,7 @@ SRCS= libifconfig.c \ libifconfig_internal.c \ libifconfig_lagg.c \ libifconfig_media.c \ + libifconfig_nl.c \ libifconfig_sfp.c GEN= libifconfig_sfp_tables.h \ diff --git a/lib/libifconfig/Symbol.map b/lib/libifconfig/Symbol.map index 2d80fb31652a..2e11ff963909 100644 --- a/lib/libifconfig/Symbol.map +++ b/lib/libifconfig/Symbol.map @@ -40,7 +40,6 @@ FBSD_1.6 { ifconfig_open; ifconfig_set_capability; ifconfig_set_description; - ifconfig_set_fib; ifconfig_set_metric; ifconfig_set_mtu; ifconfig_set_name; @@ -81,7 +80,6 @@ FBSD_1.6 { ifconfig_sfp_fc_speed_symbol; ifconfig_sfp_id_description; ifconfig_sfp_id_display; - ifconfig_sfp_id_is_qsfp; ifconfig_sfp_id_symbol; ifconfig_sfp_rev_description; ifconfig_sfp_rev_symbol; diff --git a/lib/libifconfig/libifconfig.h b/lib/libifconfig/libifconfig.h index b2f0cf9744ea..817f52bd094e 100644 --- a/lib/libifconfig/libifconfig.h +++ b/lib/libifconfig/libifconfig.h @@ -35,6 +35,8 @@ #include <netinet/ip_carp.h> #include <netinet6/in6_var.h> +#include <stdbool.h> + #define ND6_IFF_DEFAULTIF 0x8000 typedef enum { @@ -171,7 +173,6 @@ int ifconfig_set_name(ifconfig_handle_t *h, const char *name, const char *newname); int ifconfig_get_orig_name(ifconfig_handle_t *h, const char *ifname, char **orig_name); -int ifconfig_set_fib(ifconfig_handle_t *h, const char *name, int fib); int ifconfig_get_fib(ifconfig_handle_t *h, const char *name, int *fib); int ifconfig_set_mtu(ifconfig_handle_t *h, const char *name, const int mtu); int ifconfig_get_mtu(ifconfig_handle_t *h, const char *name, int *mtu); @@ -382,3 +383,12 @@ int ifconfig_set_vlantag(ifconfig_handle_t *h, const char *name, * length of *lenp * IFNAMSIZ bytes. */ int ifconfig_list_cloners(ifconfig_handle_t *h, char **bufp, size_t *lenp); + +/** Brings the interface up/down + * @param h An open ifconfig state object + * @param ifname The interface name + * @param up true to bring the interface up, false to bring it down + * @return 0 on success, nonzero on failure. + * On failure, the error info on the handle is set. + */ +int ifconfig_set_up(ifconfig_handle_t *h, const char *ifname, bool up); diff --git a/lib/libifconfig/libifconfig_nl.c b/lib/libifconfig/libifconfig_nl.c new file mode 100644 index 000000000000..7d9decabe26f --- /dev/null +++ b/lib/libifconfig/libifconfig_nl.c @@ -0,0 +1,72 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025, Muhammad Saheed <saheed@FreeBSD.org> + */ + +#include <netlink/netlink.h> +#include <netlink/netlink_snl.h> +#include <netlink/route/common.h> +#include <netlink/route/interface.h> + +#include "libifconfig.h" +#include "libifconfig_internal.h" + +static int ifconfig_modify_flags(ifconfig_handle_t *h, const char *ifname, + int ifi_flags, int ifi_change); + +static int +ifconfig_modify_flags(ifconfig_handle_t *h, const char *ifname, int ifi_flags, + int ifi_change) +{ + int ret = 0; + struct snl_state ss; + struct snl_writer nw; + struct nlmsghdr *hdr; + struct ifinfomsg *ifi; + struct snl_errmsg_data e = { 0 }; + + if (!snl_init(&ss, NETLINK_ROUTE)) { + ifconfig_error(h, NETLINK, ENOTSUP); + return (-1); + } + + snl_init_writer(&ss, &nw); + hdr = snl_create_msg_request(&nw, NL_RTM_NEWLINK); + ifi = snl_reserve_msg_object(&nw, struct ifinfomsg); + snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname); + + ifi->ifi_flags = ifi_flags; + ifi->ifi_change = ifi_change; + + hdr = snl_finalize_msg(&nw); + if (hdr == NULL) { + ifconfig_error(h, NETLINK, ENOMEM); + ret = -1; + goto out; + } + + if (!snl_send_message(&ss, hdr)) { + ifconfig_error(h, NETLINK, EIO); + ret = -1; + goto out; + } + + if (!snl_read_reply_code(&ss, hdr->nlmsg_seq, &e)) { + ifconfig_error(h, NETLINK, e.error); + ret = -1; + goto out; + } + +out: + snl_free(&ss); + return (ret); +} + +int +ifconfig_set_up(ifconfig_handle_t *h, const char *ifname, bool up) +{ + int flag = up ? IFF_UP : ~IFF_UP; + + return (ifconfig_modify_flags(h, ifname, flag, IFF_UP)); +} diff --git a/lib/libiscsiutil/Makefile b/lib/libiscsiutil/Makefile index c99fb6366536..d9762302fd40 100644 --- a/lib/libiscsiutil/Makefile +++ b/lib/libiscsiutil/Makefile @@ -1,6 +1,5 @@ LIB= iscsiutil INTERNALLIB= -PACKAGE= iscsi INCS= libiscsiutil.h diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c index 30282e67866c..ad3348af0d2d 100644 --- a/lib/libjail/jail.c +++ b/lib/libjail/jail.c @@ -75,8 +75,9 @@ int jail_setv(int flags, ...) { va_list ap, tap; - struct jailparam *jp; - const char *name, *value; + struct jailparam *jp, *jp_desc; + const char *name; + char *value, *desc_value; int njp, jid; /* Create the parameter list and import the parameters. */ @@ -86,15 +87,24 @@ jail_setv(int flags, ...) (void)va_arg(tap, char *); va_end(tap); jp = alloca(njp * sizeof(struct jailparam)); - for (njp = 0; (name = va_arg(ap, char *)) != NULL;) { + jp_desc = NULL; + desc_value = NULL; + for (njp = 0; (name = va_arg(ap, char *)) != NULL; njp++) { value = va_arg(ap, char *); if (jailparam_init(jp + njp, name) < 0) goto error; - if (jailparam_import(jp + njp++, value) < 0) + if (jailparam_import(jp + njp, value) < 0) goto error; + if (!strcmp(name, "desc") && + (flags & (JAIL_GET_DESC | JAIL_OWN_DESC))) { + jp_desc = jp + njp; + desc_value = value; + } } va_end(ap); jid = jailparam_set(jp, njp, flags); + if (jid > 0 && jp_desc != NULL) + sprintf(desc_value, "%d", *(int *)jp_desc->jp_value); jailparam_free(jp, njp); return (jid); @@ -112,9 +122,10 @@ int jail_getv(int flags, ...) { va_list ap, tap; - struct jailparam *jp, *jp_lastjid, *jp_jid, *jp_name, *jp_key; + struct jailparam *jp, *jp_desc, *jp_lastjid, *jp_jid, *jp_name, *jp_key; char *valarg, *value; - const char *name, *key_value, *lastjid_value, *jid_value, *name_value; + const char *name, *key_value, *desc_value, *lastjid_value, *jid_value; + const char *name_value; int njp, i, jid; /* Create the parameter list and find the key. */ @@ -126,15 +137,19 @@ jail_getv(int flags, ...) jp = alloca(njp * sizeof(struct jailparam)); va_copy(tap, ap); - jp_lastjid = jp_jid = jp_name = NULL; - lastjid_value = jid_value = name_value = NULL; + jp_desc = jp_lastjid = jp_jid = jp_name = NULL; + desc_value = lastjid_value = jid_value = name_value = NULL; for (njp = 0; (name = va_arg(tap, char *)) != NULL; njp++) { value = va_arg(tap, char *); if (jailparam_init(jp + njp, name) < 0) { va_end(tap); goto error; } - if (!strcmp(jp[njp].jp_name, "lastjid")) { + if (!strcmp(jp[njp].jp_name, "desc") && + (flags & (JAIL_USE_DESC | JAIL_AT_DESC))) { + jp_desc = jp + njp; + desc_value = value; + } else if (!strcmp(jp[njp].jp_name, "lastjid")) { jp_lastjid = jp + njp; lastjid_value = value; } else if (!strcmp(jp[njp].jp_name, "jid")) { @@ -147,7 +162,10 @@ jail_getv(int flags, ...) } va_end(tap); /* Import the key parameter. */ - if (jp_lastjid != NULL) { + if (jp_desc != NULL && (flags & JAIL_USE_DESC)) { + jp_key = jp_desc; + key_value = desc_value; + } else if (jp_lastjid != NULL) { jp_key = jp_lastjid; key_value = lastjid_value; } else if (jp_jid != NULL && strtol(jid_value, NULL, 10) != 0) { @@ -163,6 +181,9 @@ jail_getv(int flags, ...) } if (jailparam_import(jp_key, key_value) < 0) goto error; + if (jp_desc != NULL && jp_desc != jp_key && + jailparam_import(jp_desc, desc_value) < 0) + goto error; /* Get the jail and export the parameters. */ jid = jailparam_get(jp, njp, flags); if (jid < 0) @@ -571,7 +592,7 @@ int jailparam_get(struct jailparam *jp, unsigned njp, int flags) { struct iovec *jiov; - struct jailparam *jp_lastjid, *jp_jid, *jp_name, *jp_key; + struct jailparam *jp_desc, *jp_lastjid, *jp_jid, *jp_name, *jp_key; int i, ai, ki, jid, arrays, sanity; unsigned j; @@ -580,10 +601,13 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags) * Find the key and any array parameters. */ jiov = alloca(sizeof(struct iovec) * 2 * (njp + 1)); - jp_lastjid = jp_jid = jp_name = NULL; + jp_desc = jp_lastjid = jp_jid = jp_name = NULL; arrays = 0; for (ai = j = 0; j < njp; j++) { - if (!strcmp(jp[j].jp_name, "lastjid")) + if (!strcmp(jp[j].jp_name, "desc") && + (flags & (JAIL_USE_DESC | JAIL_AT_DESC))) + jp_desc = jp + j; + else if (!strcmp(jp[j].jp_name, "lastjid")) jp_lastjid = jp + j; else if (!strcmp(jp[j].jp_name, "jid")) jp_jid = jp + j; @@ -599,7 +623,9 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags) ai++; } } - jp_key = jp_lastjid ? jp_lastjid : + jp_key = jp_desc && jp_desc->jp_valuelen == sizeof(int) && + jp_desc->jp_value && (flags & JAIL_USE_DESC) ? jp_desc : + jp_lastjid ? jp_lastjid : jp_jid && jp_jid->jp_valuelen == sizeof(int) && jp_jid->jp_value && *(int *)jp_jid->jp_value ? jp_jid : jp_name; if (jp_key == NULL || jp_key->jp_value == NULL) { @@ -622,6 +648,14 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags) jiov[ki].iov_len = JAIL_ERRMSGLEN; ki++; jail_errmsg[0] = 0; + if (jp_desc != NULL && jp_desc != jp_key) { + jiov[ki].iov_base = jp_desc->jp_name; + jiov[ki].iov_len = strlen(jp_desc->jp_name) + 1; + ki++; + jiov[ki].iov_base = jp_desc->jp_value; + jiov[ki].iov_len = jp_desc->jp_valuelen; + ki++; + } if (arrays && jail_get(jiov, ki, flags) < 0) { if (!jail_errmsg[0]) snprintf(jail_errmsg, sizeof(jail_errmsg), @@ -649,7 +683,7 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags) jiov[ai].iov_base = jp[j].jp_value; memset(jiov[ai].iov_base, 0, jiov[ai].iov_len); ai++; - } else if (jp + j != jp_key) { + } else if (jp + j != jp_key && jp + j != jp_desc) { jiov[i].iov_base = jp[j].jp_name; jiov[i].iov_len = strlen(jp[j].jp_name) + 1; i++; @@ -886,13 +920,21 @@ jailparam_type(struct jailparam *jp) } desc; int mib[CTL_MAXNAME]; - /* The "lastjid" parameter isn't real. */ + /* + * Some pseudo-parameters don't show up in the sysctl + * parameter list. + */ name = jp->jp_name; if (!strcmp(name, "lastjid")) { jp->jp_valuelen = sizeof(int); jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_WR; return (0); } + if (!strcmp(name, "desc")) { + jp->jp_valuelen = sizeof(int); + jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_RW; + return (0); + } /* Find the sysctl that describes the parameter. */ mib[0] = 0; diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c index b2b7c6ecce56..fed483978e62 100644 --- a/lib/libkvm/kvm_proc.c +++ b/lib/libkvm/kvm_proc.c @@ -150,13 +150,14 @@ kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p, kp->ki_cr_flags = 0; if (ucred.cr_flags & CRED_FLAG_CAPMODE) kp->ki_cr_flags |= KI_CRF_CAPABILITY_MODE; - if (ucred.cr_ngroups > KI_NGROUPS) { + if (1 + ucred.cr_ngroups > KI_NGROUPS) { kp->ki_ngroups = KI_NGROUPS; kp->ki_cr_flags |= KI_CRF_GRP_OVERFLOW; } else - kp->ki_ngroups = ucred.cr_ngroups; - kvm_read(kd, (u_long)ucred.cr_groups, kp->ki_groups, - kp->ki_ngroups * sizeof(gid_t)); + kp->ki_ngroups = 1 + ucred.cr_ngroups; + kp->ki_groups[0] = ucred.cr_gid; + kvm_read(kd, (u_long)ucred.cr_groups, kp->ki_groups + 1, + (kp->ki_ngroups - 1) * sizeof(gid_t)); if (ucred.cr_prison != NULL) { if (KREAD(kd, (u_long)ucred.cr_prison, &pr)) { _kvm_err(kd, kd->program, diff --git a/lib/liblzma/Makefile b/lib/liblzma/Makefile index 27e0521f5884..9c6ece74ffd0 100644 --- a/lib/liblzma/Makefile +++ b/lib/liblzma/Makefile @@ -1,4 +1,6 @@ -PACKAGE=lib${LIB} +PACKAGE= xz +LIB_PACKAGE= + LIB= lzma LZMADIR= ${SRCTOP}/contrib/xz/src/liblzma diff --git a/lib/libmilter/Makefile b/lib/libmilter/Makefile index dd6a481d1a15..ff16b4d00297 100644 --- a/lib/libmilter/Makefile +++ b/lib/libmilter/Makefile @@ -1,6 +1,6 @@ .include <src.opts.mk> -PACKAGE=sendmail +PACKAGE=lib${LIB} SENDMAIL_DIR=${SRCTOP}/contrib/sendmail .PATH: ${SENDMAIL_DIR}/libmilter ${SENDMAIL_DIR}/libsm diff --git a/lib/libmixer/Makefile b/lib/libmixer/Makefile index a0bb37a85fb8..49621ad1f188 100644 --- a/lib/libmixer/Makefile +++ b/lib/libmixer/Makefile @@ -1,3 +1,5 @@ +PACKAGE= sound + LIB= mixer SRCS= ${LIB}.c INCS= ${LIB}.h diff --git a/lib/libnetbsd/Makefile b/lib/libnetbsd/Makefile index 1639caf20d6b..4088c2b57176 100644 --- a/lib/libnetbsd/Makefile +++ b/lib/libnetbsd/Makefile @@ -1,6 +1,5 @@ .include <bsd.own.mk> -PACKAGE=lib${LIB} LIB= netbsd CFLAGS+= -I${.CURDIR} diff --git a/lib/libnvmf/Makefile b/lib/libnvmf/Makefile index b01f5ab82cac..945c31a2986c 100644 --- a/lib/libnvmf/Makefile +++ b/lib/libnvmf/Makefile @@ -3,7 +3,6 @@ LIB= nvmf INTERNALLIB= -PACKAGE= nvmf INCS= libnvmf.h diff --git a/lib/libnvmf/nvmf_tcp.c b/lib/libnvmf/nvmf_tcp.c index 6f41ca7ff502..48ddabaf506a 100644 --- a/lib/libnvmf/nvmf_tcp.c +++ b/lib/libnvmf/nvmf_tcp.c @@ -728,7 +728,7 @@ nvmf_tcp_handle_r2t(struct nvmf_tcp_qpair *qp, struct nvmf_tcp_rxpdu *pdu) } /* - * XXX: The spec does not specify how to handle R2T tranfers + * XXX: The spec does not specify how to handle R2T transfers * out of range of the original command. */ data_len = le32toh(r2t->r2tl); diff --git a/lib/libopenbsd/Makefile b/lib/libopenbsd/Makefile index dca1c08b0aed..80ae0f90621a 100644 --- a/lib/libopenbsd/Makefile +++ b/lib/libopenbsd/Makefile @@ -1,9 +1,12 @@ -PACKAGE=lib${LIB} LIB= openbsd SRCS= imsg-buffer.c \ imsg.c \ - ohash.c \ - recallocarray.c + ohash.c +.if defined(BOOTSTRAPPING) +.PATH: ${SRCTOP}/lib/libc/stdlib +SRCS+= recallocarray.c +.endif + .if !defined(BOOTSTRAPPING) # Skip getdtablecount.c when bootstrapping since it doesn't compile for Linux # and is not used by any of the bootstrap tools diff --git a/lib/libpfctl/Makefile b/lib/libpfctl/Makefile index d301d7850b44..4b16d81181a3 100644 --- a/lib/libpfctl/Makefile +++ b/lib/libpfctl/Makefile @@ -1,4 +1,3 @@ -PACKAGE= lib${LIB} LIB= pfctl INTERNALLIB= true diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index cbd9d4677146..8c4b26b98054 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -391,6 +391,8 @@ static const struct snl_attr_parser ap_getstatus[] = { { .type = PF_GS_CHKSUM, .off = _OUT(pf_chksum), .arg_u32 = PF_MD5_DIGEST_LENGTH, .cb = snl_attr_get_bytes }, { .type = PF_GS_BCOUNTERS, .off = _OUT(bcounters), .arg_u32 = 2 * 2, .cb = snl_attr_get_uint64_array }, { .type = PF_GS_PCOUNTERS, .off = _OUT(pcounters), .arg_u32 = 2 * 2 * 2, .cb = snl_attr_get_uint64_array }, + { .type = PF_GS_NCOUNTERS, .off = _OUT(ncounters), .cb = snl_attr_get_counters }, + { .type = PF_GS_FRAGMENTS, .off = _OUT(fragments), .cb = snl_attr_get_uint64 }, }; SNL_DECLARE_PARSER(getstatus_parser, struct genlmsghdr, snl_f_p_empty, ap_getstatus); #undef _OUT @@ -429,6 +431,7 @@ pfctl_get_status_h(struct pfctl_handle *h) TAILQ_INIT(&status->lcounters); TAILQ_INIT(&status->fcounters); TAILQ_INIT(&status->scounters); + TAILQ_INIT(&status->ncounters); while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { if (! snl_parse_nlmsg(&h->ss, hdr, &getstatus_parser, status)) @@ -558,6 +561,10 @@ pfctl_free_status(struct pfctl_status *status) free(c->name); free(c); } + TAILQ_FOREACH_SAFE(c, &status->ncounters, entry, tmp) { + free(c->name); + free(c); + } free(status); } @@ -1284,8 +1291,8 @@ snl_add_msg_attr_pf_rule(struct snl_writer *nw, uint32_t type, const struct pfct snl_add_msg_attr_u8(nw, PF_RT_KEEP_STATE, r->keep_state); snl_add_msg_attr_u8(nw, PF_RT_AF, r->af); snl_add_msg_attr_u8(nw, PF_RT_PROTO, r->proto); - snl_add_msg_attr_u8(nw, PF_RT_TYPE, r->type); - snl_add_msg_attr_u8(nw, PF_RT_CODE, r->code); + snl_add_msg_attr_u16(nw, PF_RT_TYPE_2, r->type); + snl_add_msg_attr_u16(nw, PF_RT_CODE_2, r->code); snl_add_msg_attr_u8(nw, PF_RT_FLAGS, r->flags); snl_add_msg_attr_u8(nw, PF_RT_FLAGSET, r->flagset); snl_add_msg_attr_u8(nw, PF_RT_MIN_TTL, r->min_ttl); @@ -1694,6 +1701,9 @@ static struct snl_attr_parser ap_getrule[] = { { .type = PF_RT_SRC_NODES_ROUTE, .off = _OUT(r.src_nodes_type[PF_SN_ROUTE]), .cb = snl_attr_get_uint64 }, { .type = PF_RT_PKTRATE, .off = _OUT(r.pktrate), .arg = &pfctl_threshold_parser, .cb = snl_attr_get_nested }, { .type = PF_RT_MAX_PKT_SIZE, .off =_OUT(r.max_pkt_size), .cb = snl_attr_get_uint16 }, + { .type = PF_RT_TYPE_2, .off = _OUT(r.type), .cb = snl_attr_get_uint16 }, + { .type = PF_RT_CODE_2, .off = _OUT(r.code), .cb = snl_attr_get_uint16 }, + { .type = PF_RT_EXPTIME, .off = _OUT(r.exptime), .cb = snl_attr_get_time_t }, }; #undef _OUT SNL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, snl_f_p_empty, ap_getrule); @@ -2453,7 +2463,7 @@ _pfctl_table_add_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct p snl_add_msg_attr_table(&nw, PF_TA_TABLE, tbl); snl_add_msg_attr_u32(&nw, PF_TA_FLAGS, flags); - for (int i = 0; i < size && i < 256; i++) + for (int i = 0; i < size; i++) snl_add_msg_attr_pfr_addr(&nw, PF_TA_ADDR, &addrs[i]); if ((hdr = snl_finalize_msg(&nw)) == NULL) @@ -2481,19 +2491,18 @@ pfctl_table_add_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct pf int ret; int off = 0; int partial_added; + int chunk_size; do { - ret = _pfctl_table_add_addrs_h(h, tbl, &addr[off], size - off, &partial_added, flags); + chunk_size = MIN(size - off, 256); + ret = _pfctl_table_add_addrs_h(h, tbl, &addr[off], chunk_size, &partial_added, flags); if (ret != 0) break; if (nadd) *nadd += partial_added; - off += partial_added; + off += chunk_size; } while (off < size); - if (nadd) - *nadd = off; - return (ret); } @@ -2521,7 +2530,7 @@ _pfctl_table_del_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct p snl_add_msg_attr_table(&nw, PF_TA_TABLE, tbl); snl_add_msg_attr_u32(&nw, PF_TA_FLAGS, flags); - for (int i = 0; i < size && i < 256; i++) + for (int i = 0; i < size; i++) snl_add_msg_attr_pfr_addr(&nw, PF_TA_ADDR, &addrs[i]); if ((hdr = snl_finalize_msg(&nw)) == NULL) @@ -2572,20 +2581,19 @@ pfctl_table_del_addrs_h(struct pfctl_handle *h, struct pfr_table *tbl, struct pf int ret; int off = 0; int partial_deleted; + int chunk_size; do { - ret = _pfctl_table_del_addrs_h(h, tbl, &addr[off], size - off, + chunk_size = MIN(size - off, 256); + ret = _pfctl_table_del_addrs_h(h, tbl, &addr[off], chunk_size, &partial_deleted, flags); if (ret != 0) break; if (ndel) *ndel += partial_deleted; - off += partial_deleted; + off += chunk_size; } while (off < size); - if (ndel) - *ndel = off; - return (ret); } diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index f6c8f6a2ccdb..5880e1a88371 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -62,6 +62,8 @@ struct pfctl_status { struct pfctl_status_counters lcounters; struct pfctl_status_counters fcounters; struct pfctl_status_counters scounters; + struct pfctl_status_counters ncounters; + uint64_t fragments; uint64_t pcounters[2][2][2]; uint64_t bcounters[2][2]; }; @@ -261,8 +263,8 @@ struct pfctl_rule { uint8_t keep_state; sa_family_t af; uint8_t proto; - uint8_t type; - uint8_t code; + uint16_t type; + uint16_t code; uint8_t flags; uint8_t flagset; uint8_t min_ttl; @@ -283,6 +285,8 @@ struct pfctl_rule { struct pf_addr addr; uint16_t port; } divert; + + time_t exptime; }; TAILQ_HEAD(pfctl_rulequeue, pfctl_rule); diff --git a/lib/libpmc/Makefile b/lib/libpmc/Makefile index 8728b0c1c76d..590f719ebff4 100644 --- a/lib/libpmc/Makefile +++ b/lib/libpmc/Makefile @@ -1,5 +1,5 @@ -LIB_CXX= pmc - +PACKAGE=pmc +LIB_CXX=pmc SRCS= libpmc.c pmclog.c libpmc_pmu_util.c libpmc_json.cc INCS= pmc.h pmclog.h pmcformat.h diff --git a/lib/libpmcstat/Makefile b/lib/libpmcstat/Makefile index d1d23cdd57c7..7ca93329e20f 100644 --- a/lib/libpmcstat/Makefile +++ b/lib/libpmcstat/Makefile @@ -1,4 +1,3 @@ -PACKAGE=lib${LIB} LIB= pmcstat INTERNALLIB= diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c index eb8137f6c76f..df77cabcd36b 100644 --- a/lib/libprocstat/libprocstat.c +++ b/lib/libprocstat/libprocstat.c @@ -1330,8 +1330,7 @@ procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst, return (1); } vn->vn_mntdir = getmnton(kd, vnode.v_mount); - if ((vnode.v_type == VBLK || vnode.v_type == VCHR) && - vnode.v_rdev != NULL){ + if (VTYPE_ISDEV(vnode.v_type) && vnode.v_rdev != NULL) { vn->vn_dev = dev2udev(kd, vnode.v_rdev); (void)kdevtoname(kd, vnode.v_rdev, vn->vn_devname); } else { @@ -1974,6 +1973,7 @@ procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp) struct ucred ucred; gid_t *groups; size_t len; + unsigned int ngroups; assert(kd != NULL); assert(kp != NULL); @@ -1991,19 +1991,22 @@ procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp) proc.p_ucred, kp->ki_pid); return (NULL); } - len = ucred.cr_ngroups * sizeof(gid_t); + ngroups = 1 + ucred.cr_ngroups; + len = ngroups * sizeof(gid_t); groups = malloc(len); if (groups == NULL) { warn("malloc(%zu)", len); return (NULL); } - if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups, len)) { + groups[0] = ucred.cr_gid; + if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups + 1, + len - sizeof(gid_t))) { warnx("can't read groups at %p for pid %d", ucred.cr_groups, kp->ki_pid); free(groups); return (NULL); } - *cntp = ucred.cr_ngroups; + *cntp = ngroups; return (groups); } diff --git a/lib/librpcsvc/Makefile b/lib/librpcsvc/Makefile index 04e57990a29d..bdd01c91adab 100644 --- a/lib/librpcsvc/Makefile +++ b/lib/librpcsvc/Makefile @@ -14,7 +14,7 @@ OTHERSRCS= rnusers.c rstat.c rwall.c SECRPCSRCS= secretkey.c xcrypt.c .if ${MK_NIS} != "no" -OTHERSRCS+= yp_passwd.c +OTHERSRCS+= yp_passwd.c yp_update.c .endif RPCCOM= RPCGEN_CPP=${CPP:Q} rpcgen -C diff --git a/lib/librpcsvc/yp_update.c b/lib/librpcsvc/yp_update.c new file mode 100644 index 000000000000..8a31b2c22d9b --- /dev/null +++ b/lib/librpcsvc/yp_update.c @@ -0,0 +1,199 @@ +/*- + * SPDX-License-Identifier: BSD-4-Clause + * + * Copyright (c) 1995, 1996 + * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * ypupdate client-side library function. + * + * Written by Bill Paul <wpaul@ctr.columbia.edu> + * Center for Telecommunications Research + * Columbia University, New York City + */ + +#include <sys/cdefs.h> +#include <stdlib.h> +#include <rpc/rpc.h> +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> +#include <rpcsvc/ypupdate_prot.h> +#include <rpc/key_prot.h> + +#ifndef WINDOW +#define WINDOW (60*60) +#endif + +#ifndef TIMEOUT +#define TIMEOUT 300 +#endif + +int +yp_update(char *domain, char *map, unsigned int ypop, char *key, int keylen, + char *data, int datalen) +{ + char *master; + int rval; + unsigned int res; + struct ypupdate_args upargs; + struct ypdelete_args delargs; + CLIENT *clnt; + char netname[MAXNETNAMELEN+1]; + des_block des_key; + struct timeval timeout; + + /* Get the master server name for 'domain.' */ + if ((rval = yp_master(domain, map, &master))) + return(rval); + + /* Check that ypupdated is running there. */ + if (getrpcport(master, YPU_PROG, YPU_VERS, ypop)) + return(YPERR_DOMAIN); + + /* Get a handle. */ + if ((clnt = clnt_create(master, YPU_PROG, YPU_VERS, "tcp")) == NULL) + return(YPERR_RPC); + + /* + * Assemble netname of server. + * NOTE: It's difficult to discern from the documentation, but + * when you make a Secure RPC call, the netname you pass should + * be the netname of the guy on the other side, not your own + * netname. This is how the client side knows what public key + * to use for the initial exchange. Passing your own netname + * only works if the server on the other side is running under + * your UID. + */ + if (!host2netname(netname, master, domain)) { + clnt_destroy(clnt); + return(YPERR_BADARGS); + } + + /* Make up a DES session key. */ + key_gendes(&des_key); + + /* Set up DES authentication. */ + if ((clnt->cl_auth = (AUTH *)authdes_create(netname, WINDOW, NULL, + &des_key)) == NULL) { + clnt_destroy(clnt); + return(YPERR_RESRC); + } + + /* Set a timeout for clnt_call(). */ + timeout.tv_usec = 0; + timeout.tv_sec = TIMEOUT; + + /* + * Make the call. Note that we use clnt_call() here rather than + * the rpcgen-erated client stubs. We could use those stubs, but + * then we'd have to do some gymnastics to get at the error + * information to figure out what error code to send back to the + * caller. With clnt_call(), we get the error status returned to + * us right away, and we only have to exert a small amount of + * extra effort. + */ + switch (ypop) { + case YPOP_CHANGE: + upargs.mapname = map; + upargs.key.yp_buf_len = keylen; + upargs.key.yp_buf_val = key; + upargs.datum.yp_buf_len = datalen; + upargs.datum.yp_buf_val = data; + + if ((rval = clnt_call(clnt, YPU_CHANGE, + (xdrproc_t)xdr_ypupdate_args, &upargs, + (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { + if (rval == RPC_AUTHERROR) + res = YPERR_ACCESS; + else + res = YPERR_RPC; + } + + break; + case YPOP_INSERT: + upargs.mapname = map; + upargs.key.yp_buf_len = keylen; + upargs.key.yp_buf_val = key; + upargs.datum.yp_buf_len = datalen; + upargs.datum.yp_buf_val = data; + + if ((rval = clnt_call(clnt, YPU_INSERT, + (xdrproc_t)xdr_ypupdate_args, &upargs, + (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { + if (rval == RPC_AUTHERROR) + res = YPERR_ACCESS; + else + res = YPERR_RPC; + } + + break; + case YPOP_DELETE: + delargs.mapname = map; + delargs.key.yp_buf_len = keylen; + delargs.key.yp_buf_val = key; + + if ((rval = clnt_call(clnt, YPU_DELETE, + (xdrproc_t)xdr_ypdelete_args, &delargs, + (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { + if (rval == RPC_AUTHERROR) + res = YPERR_ACCESS; + else + res = YPERR_RPC; + } + + break; + case YPOP_STORE: + upargs.mapname = map; + upargs.key.yp_buf_len = keylen; + upargs.key.yp_buf_val = key; + upargs.datum.yp_buf_len = datalen; + upargs.datum.yp_buf_val = data; + + if ((rval = clnt_call(clnt, YPU_STORE, + (xdrproc_t)xdr_ypupdate_args, &upargs, + (xdrproc_t)xdr_u_int, &res, timeout)) != RPC_SUCCESS) { + if (rval == RPC_AUTHERROR) + res = YPERR_ACCESS; + else + res = YPERR_RPC; + } + + break; + default: + res = YPERR_BADARGS; + break; + } + + /* All done: tear down the connection. */ + auth_destroy(clnt->cl_auth); + clnt_destroy(clnt); + free(master); + + return(res); +} diff --git a/lib/libsamplerate/Makefile b/lib/libsamplerate/Makefile index 256f2087284f..4c55d5c2cb82 100644 --- a/lib/libsamplerate/Makefile +++ b/lib/libsamplerate/Makefile @@ -1,7 +1,9 @@ .PATH: ${SRCTOP}/contrib/libsamplerate +PACKAGE= sound + LIB= samplerate -INTERNALLIB= +PRIVATELIB= SRCS= samplerate.c \ src_linear.c \ diff --git a/lib/libsdp/Makefile b/lib/libsdp/Makefile index f0153e756dfd..8177c9bdbd1a 100644 --- a/lib/libsdp/Makefile +++ b/lib/libsdp/Makefile @@ -1,6 +1,7 @@ # $Id: Makefile,v 1.2 2003/09/07 20:34:19 max Exp $ -PACKAGE=lib${LIB} +PACKAGE= bluetooth +LIB_PACKAGE= LIB= sdp MAN= sdp.3 diff --git a/lib/libsdp/sdp.3 b/lib/libsdp/sdp.3 index dcd9077798ea..015f9cd8fb44 100644 --- a/lib/libsdp/sdp.3 +++ b/lib/libsdp/sdp.3 @@ -24,7 +24,7 @@ .\" .\" $Id: sdp.3,v 1.1 2003/09/07 20:34:19 max Exp $ .\" -.Dd April 30, 2018 +.Dd September 16, 2025 .Dt SDP 3 .Os .Sh NAME @@ -87,7 +87,7 @@ .Fn sdp_uuid2desc "uint16_t uuid" .Ft int32_t .Fo sdp_register_service -.Fa "void *xss" "uint16_t uuid" "bdaddr_p const bdaddr" "uint8_t const *data" +.Fa "void *xss" "uint16_t uuid" "const bdaddr_t *bdaddr" "uint8_t const *data" .Fa "uint32_t datalen" "uint32_t *handle" .Fc .Ft int32_t diff --git a/lib/libsdp/sdp.h b/lib/libsdp/sdp.h index faad36aefca6..0c9474a70eff 100644 --- a/lib/libsdp/sdp.h +++ b/lib/libsdp/sdp.h @@ -702,7 +702,7 @@ typedef struct sdp_panu_profile sdp_panu_profile_t; typedef struct sdp_panu_profile * sdp_panu_profile_p; int32_t sdp_register_service (void *xss, uint16_t uuid, - bdaddr_p const bdaddr, uint8_t const *data, + const bdaddr_t *bdaddr, uint8_t const *data, uint32_t datalen, uint32_t *handle); int32_t sdp_unregister_service (void *xss, uint32_t handle); int32_t sdp_change_service (void *xss, uint32_t handle, diff --git a/lib/libsdp/service.c b/lib/libsdp/service.c index 9f07d1ba86ba..2cce6c133600 100644 --- a/lib/libsdp/service.c +++ b/lib/libsdp/service.c @@ -45,7 +45,7 @@ static int32_t sdp_receive_error_pdu(sdp_session_p ss); int32_t -sdp_register_service(void *xss, uint16_t uuid, bdaddr_p const bdaddr, +sdp_register_service(void *xss, uint16_t uuid, const bdaddr_t *bdaddr, uint8_t const *data, uint32_t datalen, uint32_t *handle) { sdp_session_p ss = (sdp_session_p) xss; diff --git a/lib/libsm/Makefile b/lib/libsm/Makefile index 448abad59192..538407754f6a 100644 --- a/lib/libsm/Makefile +++ b/lib/libsm/Makefile @@ -1,6 +1,5 @@ .include <src.opts.mk> -PACKAGE=sendmail SENDMAIL_DIR=${SRCTOP}/contrib/sendmail .PATH: ${SENDMAIL_DIR}/libsm diff --git a/lib/libsmdb/Makefile b/lib/libsmdb/Makefile index 898af78d6101..e82deda57615 100644 --- a/lib/libsmdb/Makefile +++ b/lib/libsmdb/Makefile @@ -1,4 +1,3 @@ -PACKAGE=lib${LIB} SENDMAIL_DIR=${SRCTOP}/contrib/sendmail .PATH: ${SENDMAIL_DIR}/libsmdb diff --git a/lib/libsmutil/Makefile b/lib/libsmutil/Makefile index ef526ff8656d..37ad71e84f58 100644 --- a/lib/libsmutil/Makefile +++ b/lib/libsmutil/Makefile @@ -1,6 +1,5 @@ .include <src.opts.mk> -PACKAGE=lib${LIB} SENDMAIL_DIR=${SRCTOP}/contrib/sendmail .PATH: ${SENDMAIL_DIR}/libsmutil diff --git a/lib/libstdbuf/Makefile b/lib/libstdbuf/Makefile index 102c6745c593..9e289e0018fc 100644 --- a/lib/libstdbuf/Makefile +++ b/lib/libstdbuf/Makefile @@ -1,6 +1,5 @@ .include <bsd.own.mk> -PACKAGE=lib${LIB} LIB= stdbuf SRCS= stdbuf.c SHLIB_MAJOR= 1 diff --git a/lib/libstdthreads/Makefile b/lib/libstdthreads/Makefile index 49d024052420..dcdac58efc12 100644 --- a/lib/libstdthreads/Makefile +++ b/lib/libstdthreads/Makefile @@ -1,4 +1,4 @@ -PACKAGE=lib${LIB} +PACKAGE=runtime LIB= stdthreads SHLIB_MAJOR= 0 diff --git a/lib/libsys/Symbol.map b/lib/libsys/Symbol.map index eb71c813ae86..ae12124ca210 100644 --- a/lib/libsys/Symbol.map +++ b/lib/libsys/Symbol.map @@ -4,10 +4,4 @@ FBSDprivate_1.0 { __getosreldate; __libsys_interposing_slot; _elf_aux_info; - freebsd11_fstat; - freebsd11_fstatat; - freebsd11_getfsstat; - freebsd11_lstat; - freebsd11_stat; - freebsd11_statfs; }; diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map index 45e0160100af..e3fd8ac10621 100644 --- a/lib/libsys/Symbol.sys.map +++ b/lib/libsys/Symbol.sys.map @@ -89,7 +89,6 @@ FBSD_1.0 { geteuid; getfh; getgid; - getgroups; getitimer; getpagesize; getpeername; @@ -204,7 +203,6 @@ FBSD_1.0 { setegid; seteuid; setgid; - setgroups; setitimer; setlogin; setpgid; @@ -380,11 +378,15 @@ FBSD_1.7 { FBSD_1.8 { exterrctl; fchroot; + getgroups; getrlimitusage; inotify_add_watch_at; inotify_rm_watch; + jail_attach_jd; + jail_remove_jd; kcmp; setcred; + setgroups; }; FBSDprivate_1.0 { diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h index 2f89e8fea92b..6bd768708a78 100644 --- a/lib/libsys/_libsys.h +++ b/lib/libsys/_libsys.h @@ -121,8 +121,6 @@ typedef int (__sys_munmap_t)(void *, size_t); typedef int (__sys_mprotect_t)(void *, size_t, int); typedef int (__sys_madvise_t)(void *, size_t, int); typedef int (__sys_mincore_t)(const void *, size_t, char *); -typedef int (__sys_getgroups_t)(int, gid_t *); -typedef int (__sys_setgroups_t)(int, const gid_t *); typedef int (__sys_getpgrp_t)(void); typedef int (__sys_setpgid_t)(int, int); typedef int (__sys_setitimer_t)(int, const struct itimerval *, struct itimerval *); @@ -468,6 +466,10 @@ typedef int (__sys_setcred_t)(u_int, const struct setcred *, size_t); typedef int (__sys_exterrctl_t)(u_int, u_int, void *); typedef int (__sys_inotify_add_watch_at_t)(int, int, const char *, uint32_t); typedef int (__sys_inotify_rm_watch_t)(int, int); +typedef int (__sys_getgroups_t)(int, gid_t *); +typedef int (__sys_setgroups_t)(int, const gid_t *); +typedef int (__sys_jail_attach_jd_t)(int); +typedef int (__sys_jail_remove_jd_t)(int); _Noreturn void __sys__exit(int rval); int __sys_fork(void); @@ -525,8 +527,6 @@ int __sys_munmap(void * addr, size_t len); int __sys_mprotect(void * addr, size_t len, int prot); int __sys_madvise(void * addr, size_t len, int behav); int __sys_mincore(const void * addr, size_t len, char * vec); -int __sys_getgroups(int gidsetsize, gid_t * gidset); -int __sys_setgroups(int gidsetsize, const gid_t * gidset); int __sys_getpgrp(void); int __sys_setpgid(int pid, int pgid); int __sys_setitimer(int which, const struct itimerval * itv, struct itimerval * oitv); @@ -872,6 +872,10 @@ int __sys_setcred(u_int flags, const struct setcred * wcred, size_t size); int __sys_exterrctl(u_int op, u_int flags, void * ptr); int __sys_inotify_add_watch_at(int fd, int dfd, const char * path, uint32_t mask); int __sys_inotify_rm_watch(int fd, int wd); +int __sys_getgroups(int gidsetsize, gid_t * gidset); +int __sys_setgroups(int gidsetsize, const gid_t * gidset); +int __sys_jail_attach_jd(int fd); +int __sys_jail_remove_jd(int fd); __END_DECLS #endif /* __LIBSYS_H_ */ diff --git a/lib/libsys/copy_file_range.2 b/lib/libsys/copy_file_range.2 index bcd9170842d5..829a5a5d3c13 100644 --- a/lib/libsys/copy_file_range.2 +++ b/lib/libsys/copy_file_range.2 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 28, 2023 +.Dd August 16, 2025 .Dt COPY_FILE_RANGE 2 .Os .Sh NAME @@ -74,6 +74,7 @@ argument must be opened for reading and the .Fa outfd argument must be opened for writing, but not .Dv O_APPEND . +.Pp If .Fa inoffp or @@ -101,9 +102,29 @@ respectively will be used/updated and the file offset for or .Fa outfd respectively will not be affected. -The +.Pp +The only +.Fa flags +argument currently defined is +.Dv COPY_FILE_RANGE_CLONE . +When this flag is set, +.Fn copy_file_range +will return +.Er EOPNOTSUPP +if the copy cannot be done via +block cloning. +When .Fa flags -argument must be 0. +is 0, a file system may do the copy via block cloning +or by data copying. +Block cloning is only possible when the offsets (plus +.Fa len +if not to EOF on the input file) are block +aligned. +The correct block alignment can normally be acquired via the +.Dv _PC_CLONE_BLKSIZE +query for +.Xr pathconf 2 . .Pp This system call attempts to maintain holes in the output file for the byte range being copied. @@ -203,9 +224,15 @@ refers to a directory. File system that stores .Fa outfd is full. +.It Bq Er EOPNOTSUPP +Cannot do the copy via block cloning and the +.Dv COPY_FILE_RANGE_CLONE +.Fa flags +argument is specified. .El .Sh SEE ALSO -.Xr lseek 2 +.Xr lseek 2 , +.Xr pathconf 2 .Sh STANDARDS The .Fn copy_file_range diff --git a/lib/libsys/getgroups.2 b/lib/libsys/getgroups.2 index 91cca2748ec2..4881a65d532e 100644 --- a/lib/libsys/getgroups.2 +++ b/lib/libsys/getgroups.2 @@ -1,5 +1,13 @@ +.\"- +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 1983, 1991, 1993 .\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2025 The FreeBSD Foundation +.\" +.\" Portions of this documentation were written by Olivier Certner +.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD +.\" Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -25,12 +33,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 21, 2011 +.Dd September 17, 2025 .Dt GETGROUPS 2 .Os .Sh NAME .Nm getgroups -.Nd get group access list +.Nd get the calling process' supplementary groups .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -40,36 +48,39 @@ .Sh DESCRIPTION The .Fn getgroups -system call -gets the current group access list of the user process -and stores it in the array -.Fa gidset . -The +system call gets the calling process' supplementary groups and stores them in +the +.Fa gidset +array in strictly ascending order. +The value of .Fa gidsetlen -argument -indicates the number of entries that may be placed in +indicates the maximum number of entries that may be placed in .Fa gidset . -The -.Fn getgroups -system call -returns the actual number of groups returned in -.Fa gidset . -At least one and as many as {NGROUPS_MAX}+1 values may be returned. +.Pp If .Fa gidsetlen is zero, .Fn getgroups -returns the number of supplementary group IDs associated with -the calling process without modifying the array pointed to by +returns the cardinal of the calling process' supplementary groups set and +ignores argument .Fa gidset . .Pp +No more than +.Dv {NGROUPS_MAX} +values may ever be returned. The value of .Dv {NGROUPS_MAX} should be obtained using .Xr sysconf 3 to avoid hard-coding it into the executable. .Sh RETURN VALUES -A successful call returns the number of groups in the group set. +On success, the +.Fn getgroups +system call returns the cardinal of the supplementary groups set. +It always succeeds if argument +.Fa gidsetlen +is zero. +.Pp A value of -1 indicates that an error occurred, and the error code is stored in the global variable .Va errno . @@ -81,12 +92,12 @@ are: .It Bq Er EINVAL The argument .Fa gidsetlen -is smaller than the number of groups in the group set. +is smaller than the number of supplementary groups +.Pq but not zero . .It Bq Er EFAULT -The argument +An invalid address was encountered while reading from the .Fa gidset -specifies -an invalid address. +array. .El .Sh SEE ALSO .Xr setgroups 2 , @@ -96,9 +107,51 @@ an invalid address. The .Fn getgroups system call conforms to -.St -p1003.1-2008 . +.St -p1003.1-2008 +with the additional properties that supplementary groups are reported in +strictly ascending order and the returned size coincides with the cardinal of +the set. .Sh HISTORY The .Fn getgroups system call appeared in .Bx 4.2 . +.Pp +Since +.Fx 14.3 , +the +.Fn getgroups +system call has treated the supplementary groups as a set, reporting them in +strictly ascending order and returning the cardinal of the set. +.Pp +Before +.Fx 15.0 , +the +.Fn getgroups +system call would additionally return the effective group ID as the first +element of the array, before the supplementary groups. +.Sh SECURITY CONSIDERATIONS +The +.Fn getgroups +system call gets the supplementary groups set in the +.Fa gidset +array. +In particular, as evoked in +.Sx HISTORY , +it does not anymore retrieve the effective GID in the first slot of +.Fa gidset . +Programs should not make any assumption about which group is placed in the first +slot of +.Fa gidset +other than it being the supplementary group with smallest GID. +.Pp +The effective GID is present in the supplementary groups set if and only if it +was explicitly set as a supplementary group. +The function +.Fn initgroups +enforces that, while the +.Fn setgroups +system call does not. +Please consult the +.Xr initgroups 3 +manual page for the rationale. diff --git a/lib/libsys/jail.2 b/lib/libsys/jail.2 index 8f8b9925c712..ee4e5b03d38e 100644 --- a/lib/libsys/jail.2 +++ b/lib/libsys/jail.2 @@ -23,7 +23,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 29, 2023 +.Dd September 15, 2025 .Dt JAIL 2 .Os .Sh NAME @@ -31,7 +31,9 @@ .Nm jail_get , .Nm jail_set , .Nm jail_remove , -.Nm jail_attach +.Nm jail_attach , +.Nm jail_remove_jd , +.Nm jail_attach_jd .Nd create and manage system jails .Sh LIBRARY .Lb libc @@ -44,6 +46,10 @@ .Fn jail_attach "int jid" .Ft int .Fn jail_remove "int jid" +.Ft int +.Fn jail_attach_jd "int fd" +.Ft int +.Fn jail_remove_jd "int fd" .In sys/uio.h .Ft int .Fn jail_get "struct iovec *iov" "u_int niov" "int flags" @@ -188,6 +194,29 @@ system call. This is deprecated in .Fn jail_set and has no effect. +.It Dv JAIL_USE_DESC +Identify the jail by a descriptor in the +.Va desc +parameter. +.It Dv JAIL_AT_DESC +Operate in the context of the jail described by the +.Va desc +parameter, instead of the current jail. +Only one of +.Dv JAIL_USE_DESC +or +.Dv JAIL_AT_DESC +may be specified. +.It Dv JAIL_GET_DESC +Return a new jail descriptor for the jail in the +.Va desc +parameter. +.It Dv JAIL_OWN_DESC +Return an +.Dq owning +jail descriptor in the +.Va desc +parameter. .El .Pp The @@ -221,6 +250,9 @@ arguments consists of one or more following flags: .Bl -tag -width indent .It Dv JAIL_DYING Allow getting a jail that is in the process of being removed. +.It Dv JAIL_USE_DESC , Dv JAIL_AT_DESC , Dv JAIL_GET_DESC , Dv JAIL_OWN_DESC +These have the same meaning as they do in +.Fn jail_set . .El .Pp The @@ -238,6 +270,76 @@ system call removes the jail identified by .Fa jid . It will kill all processes belonging to the jail, and remove any children of that jail. +.Pp +The +.Fn jail_attach_fd +and +.Fn jail_remove_fd +system calls work the same as +.Fn jail_attach +and +.Fn jail_remove , +except that they operate on the jail identified by jail descriptor +.Fa fd . +.Ss Jail Descriptors +In addition to the jail ID, +jails can be referred to using a jail descriptor, +a type of file descriptor tied to a particular jail. +Jail descriptors are created by calling +.Fn jail_set +or +.Fn jail_get +with the special parameter +.Va desc , +and either the +.Dv JAIL_GET_DESC +or +.Dv JAIL_OWN_DESC +flags set. +The difference between the two flags is that descriptors created with +.Dv JAIL_OWN_DESC +.Po +called +.Dq owning +descriptors +.Pc +will automatically remove the jail when the descriptor is closed. +.Pp +Jail descriptors can be passed back to +.Fn jail_set +or +.Fm jail_get +with the +.Va desc +parameter, +and either the +.Dv JAIL_USE_DESC +or +.Dv JAIL_AT_DESC +flags set. +With +.Dv JAIL_USE_DESC , +the descriptor identifies the jail to operate on, +instead of the +.Va jid +or +.Va name +parameter. +With +.Dv JAIL_AT_DESC , +the descriptor is used in place of the current jail, +allowing accessing or creating jails that are children of the +descriptor jail. +.Pp +The system calls +.Fn jail_attach_jd +and +.Fn jail_aremove_jd +work the same as +.Fn jail_attach +and +.Fn jail_remove , +except that they operate on the jail referred to by the passed descriptor. .Sh RETURN VALUES If successful, .Fn jail , @@ -249,7 +351,7 @@ They return \-1 on failure, and set .Va errno to indicate the error. .Pp -.Rv -std jail_attach jail_remove +.Rv -std jail_attach jail_remove jail_attach_jd jail_remove_jd .Sh ERRORS The .Fn jail @@ -281,6 +383,13 @@ the super-user, or because it would exceed the jail's .Va children.max limit. .It Bq Er EPERM +The jail descriptor in the +.Va desc +parameter was created by a user other than the super-user, +and the +.Dv JAIL_USE_DESC +flag was set. +.It Bq Er EPERM A jail parameter was set to a less restrictive value then the current environment. .It Bq Er EFAULT @@ -298,8 +407,12 @@ flag is not set. .It Bq Er ENOENT The jail referred to by a .Va jid -is not accessible by the process, because the process is in a different -jail. +parameter is not accessible by the process, because the process is in a +different jail. +.It Bq Er ENOENT +The jail referred to by a +.Va desc +parameter has been removed. .It Bq Er EEXIST The jail referred to by a .Va jid @@ -326,6 +439,24 @@ flags is not set. A supplied string parameter is longer than allowed. .It Bq Er EAGAIN There are no jail IDs left. +.It Bq Er EMFILE +A jail descriptor could not be created for the +.Va desc +parameter with either the +.Dv JAIL_GET_DESC +or +.Dv JAIL_OWN_DESC +flag set, +because the process has already reached its limit for open file descriptors. +.It Bq Er ENFILE +A jail descriptor could not be created for the +.Va desc +parameter with either the +.Dv JAIL_GET_DESC +or +.Dv JAIL_OWN_DESC +flag set, +because the system file table is full. .El .Pp The @@ -333,10 +464,6 @@ The system call will fail if: .Bl -tag -width Er -.It Bq Er EFAULT -.Fa Iov , -or one of the addresses contained within it, -points to an address outside the allocated address space of the process. .It Bq Er ENOENT The jail referred to by a .Va jid @@ -352,10 +479,37 @@ jail. The .Va lastjid parameter is greater than the highest current jail ID. +.It Bq Er ENOENT +The jail referred to by a +.Va desc +parameter has been removed +.Pq even if the Dv JAIL_CREATE flag has been set . .It Bq Er EINVAL A supplied parameter is the wrong size. .It Bq Er EINVAL +A supplied parameter is out of range. +.It Bq Er EINVAL +A supplied string parameter is not null-terminated. +.It Bq Er EINVAL A supplied parameter name does not match any known parameters. +.It Bq Er EMFILE +A jail descriptor could not be created for the +.Va desc +parameter with either the +.Dv JAIL_GET_DESC +or +.Dv JAIL_OWN_DESC +flag set, +because the process has already reached its limit for open file descriptors. +.It Bq Er ENFILE +A jail descriptor could not be created for the +.Va desc +parameter with either the +.Dv JAIL_GET_DESC +or +.Dv JAIL_OWN_DESC +flag set, +because the system file table is full. .El .Pp The @@ -373,14 +527,37 @@ The jail specified by does not exist. .El .Pp +The +.Fn jail_attach_jd +and +.Fn jail_remove_jd +system calls +will fail if: +.Bl -tag -width Er +.It Bq Er EINVAL +The +.Fa fd +argument is not a valid jail descriptor. +.It Bq Er EPERM +The jail descriptor was created by a user other than the super-user. +.It Bq Er EINVAL +The jail specified by +.Fa jid +has been removed. +.El +.Pp Further .Fn jail , .Fn jail_set , +.Fn jail_attach , and -.Fn jail_attach +.Fn jail_attach_jd call .Xr chroot 2 internally, so they can fail for all the same reasons. +In particular, they return the +.Bq Er EPERM +error when the process to join a jail has open directories. Please consult the .Xr chroot 2 manual page for details. diff --git a/lib/libsys/kqueue.2 b/lib/libsys/kqueue.2 index d6e949baa24c..96c9b0222a37 100644 --- a/lib/libsys/kqueue.2 +++ b/lib/libsys/kqueue.2 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 26, 2023 +.Dd September 12, 2025 .Dt KQUEUE 2 .Os .Sh NAME @@ -593,6 +593,64 @@ returns the number of times the signal has occurred since the last call to This filter automatically sets the .Dv EV_CLEAR flag internally. +.It Dv EVFILT_JAIL +Takes the jail ID to monitor as the identifier and the events to watch for +in +.Va fflags , +and returns when the jail performs one or more of the requested events. +If a process can normally see a jail, it can attach an event to it. +An identifier of zero will watch the process's own jail. +The events to monitor are: +.Bl -tag -width "Dv NOTE_JAIL_ATTACH" +.It Dv NOTE_JAIL_SET +The jail has been changed via +.Xr jail_set 2 . +.It Dv NOTE_JAIL_ATTACH +A process has attached to the jail via +.Xr jail_attach 2 +or a similar call. +The process ID will be stored in +.Va data . +If more than one process has attached since the last call to +.Fn kevent , +.Va data +will be zero. +.It Dv NOTE_JAIL_REMOVE +The jail has been removed. +.It Dv NOTE_JAIL_CHILD +A child of the watched jail has been created. +Its jail ID will be stored in +.Va data . +If more than one jail has been created since the last call to +.Fn kevent , +.Va data +will be zero. +.El +.Pp +On return, +.Va fflags +contains the events which triggered the filter. +It will also contain +.Dv NOTE_JAIL_MULTI +if more than one +.Dv NOTE_JAIL_ATTACH +or +.Dv NOTE_JAIL_CHILD +event has been received since the last call to +.Fn kevent . +.It Dv EVFILT_JAILDESC +Takes a jail descriptor returned by +.Xr jail_set 2 +or +.Xr jail_get 2 +as the identifier and the events to watch for in +.Va fflags , +and returns when the jail performs one or more of the requested events. +The events to monitor and the resulting +.Va fflags +are the same as those listed in +.Dv EVFILT_JAIL , +above. .It Dv EVFILT_TIMER Establishes an arbitrary timer identified by .Va ident . diff --git a/lib/libsys/setcred.2 b/lib/libsys/setcred.2 index 86f61ddfdb30..f5d1f15b631b 100644 --- a/lib/libsys/setcred.2 +++ b/lib/libsys/setcred.2 @@ -6,7 +6,7 @@ .\" This documentation was written by Olivier Certner <olce.freebsd@certner.fr> .\" at Kumacom SARL under sponsorship from the FreeBSD Foundation. .\" -.Dd December 19, 2024 +.Dd August 29, 2025 .Dt SETCRED 2 .Os .Sh NAME @@ -119,11 +119,6 @@ It must be less than or equal to An array of IDs to set the supplementary groups to, if flag .Dv SETCREDF_SUPP_GROUPS is specified. -Note that all groups in this array will be set as supplementary groups only, in -contrast to -.Xr setgroups 2 -which treats the first element specially as the new effective group, not adding -it to supplementary groups. .It Fa sc_label A pointer to a valid MAC label structure, e.g., built with the .Xr mac_from_text 3 diff --git a/lib/libsys/setgroups.2 b/lib/libsys/setgroups.2 index a226aeafea96..0ec99507cfb0 100644 --- a/lib/libsys/setgroups.2 +++ b/lib/libsys/setgroups.2 @@ -1,5 +1,13 @@ +.\"- +.\" SPDX-License-Identifier: BSD-3-Clause +.\" .\" Copyright (c) 1983, 1991, 1993, 1994 .\" The Regents of the University of California. All rights reserved. +.\" Copyright (c) 2025 The FreeBSD Foundation +.\" +.\" Portions of this documentation were written by Olivier Certner +.\" <olce@FreeBSD.org> at Kumacom SARL under sponsorship from the FreeBSD +.\" Foundation. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -25,12 +33,12 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd January 19, 2018 +.Dd September 17, 2025 .Dt SETGROUPS 2 .Os .Sh NAME .Nm setgroups -.Nd set group access list +.Nd set the calling process' supplementary groups .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -41,35 +49,21 @@ .Sh DESCRIPTION The .Fn setgroups -system call -sets the group access list of the current user process -according to the array -.Fa gidset . +system call sets the calling process' supplementary groups according to the +.Fa gidset +array. The .Fa ngroups -argument -indicates the number of entries in the array and must be no -more than -.Dv {NGROUPS_MAX}+1 . +argument indicates the number of entries in the array and must be no more than +.Dv {NGROUPS_MAX} . .Pp -Only the super-user may set a new group list. +The +.Fa ngroups +argument may be set to zero to clear all supplementary groups, in which case +.Fa gidset +is ignored. .Pp -The first entry of the group array -.Pq Va gidset[0] -is used as the effective group-ID for the process. -This entry is over-written when a setgid program is run. -To avoid losing access to the privileges of the -.Va gidset[0] -entry, it should be duplicated later in the group array. -By convention, -this happens because the group value indicated -in the password file also appears in -.Pa /etc/group . -The group value in the password file is placed in -.Va gidset[0] -and that value then gets added a second time when the -.Pa /etc/group -file is scanned to create the group set. +Only the super-user may install a new supplementary groups set. .Sh RETURN VALUES .Rv -std setgroups .Sh ERRORS @@ -83,19 +77,86 @@ The caller is not the super-user. The number specified in the .Fa ngroups argument is larger than the -.Dv {NGROUPS_MAX}+1 +.Dv {NGROUPS_MAX} limit. .It Bq Er EFAULT -The address specified for +Part of the groups array starting at .Fa gidset -is outside the process -address space. +is outside the process address space. .El .Sh SEE ALSO .Xr getgroups 2 , +.Xr setcred 2 , .Xr initgroups 3 .Sh HISTORY The .Fn setgroups system call appeared in .Bx 4.2 . +.Pp +Before +.Fx 15.0 , +the +.Fn setgroups +system call would set the effective group ID for the process to the first +element of +.Fa gidset , +and only the other elements as supplementary groups. +Despite treating the first element as the effective group ID to set, it accepted +an empty +.Fa gidset +.Po +.Fa ngroups +being zero +.Pc +as a stance requiring to drop all supplementary groups, leaving the effective +group ID unchanged. +.Sh SECURITY CONSIDERATIONS +The +.Fn setgroups +system call sets the process' supplementary groups to those contained in the +.Fa gidset +array. +In particular, as evoked in +.Sx HISTORY , +it does not anymore treat the first element of +.Fa gidset +separately. +Formerly, it would set it as the effective group ID while only the others were +used as supplementary groups. +.Pp +Programs solely relying on +.Fn setgroups +to change the effective group ID must be modified, e.g., to also call +.Xr setegid 2 +or to instead use +.Xr setcred 2 , +else they will unwillingly keep their effective group ID. +.Pp +Programs using +.Fn setgroups +with the effective group ID as the first element of array +.Fa gidset +and not duplicating it in the rest of the array, which includes those using +.Fn initgroups , +now insert this group ID in the supplementary groups set. +This is in general desirable, as explained in the +.Xr initgroups 3 +manual page, and has the consequence that subsequent process' effective group +ID's changes do not remove membership of the original effective group ID, since +these changes do not affect the supplementary groups. +Applications that expressly do not want that must be modified to stop passing +the effective group ID as the first element to +.Fn setgroups . +.Pp +To clear all the calling process' supplementary groups, always use the statement +.Bd -literal -offset indent +setgroups(0, NULL); +.Ed +.Pp +which works also on older FreeBSD version +.Po +see the +.Sx HISTORY +section +.Pc . diff --git a/lib/libsys/stat.2 b/lib/libsys/stat.2 index bd9005710147..8107740bd901 100644 --- a/lib/libsys/stat.2 +++ b/lib/libsys/stat.2 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd March 30, 2021 +.Dd August 17, 2025 .Dt STAT 2 .Os .Sh NAME @@ -169,6 +169,9 @@ Flags enabled for the file. See .Xr chflags 2 for the list of flags and their description. +.It Va st_rdev +Numeric ID of the device referenced by the file, if the file is a +character or block special; otherwise unspecified. .El .Pp The diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map index dbb011343c8f..b5400b9849b3 100644 --- a/lib/libsys/syscalls.map +++ b/lib/libsys/syscalls.map @@ -117,10 +117,6 @@ FBSDprivate_1.0 { __sys_madvise; _mincore; __sys_mincore; - _getgroups; - __sys_getgroups; - _setgroups; - __sys_setgroups; _getpgrp; __sys_getpgrp; _setpgid; @@ -813,4 +809,12 @@ FBSDprivate_1.0 { __sys_inotify_add_watch_at; _inotify_rm_watch; __sys_inotify_rm_watch; + _getgroups; + __sys_getgroups; + _setgroups; + __sys_setgroups; + _jail_attach_jd; + __sys_jail_attach_jd; + _jail_remove_jd; + __sys_jail_remove_jd; }; diff --git a/lib/libsysdecode/Makefile b/lib/libsysdecode/Makefile index ca020552a6e9..11f45355b8e2 100644 --- a/lib/libsysdecode/Makefile +++ b/lib/libsysdecode/Makefile @@ -27,7 +27,7 @@ MAN= sysdecode.3 \ sysdecode_sigcode.3 \ sysdecode_sockopt_name.3 \ sysdecode_socket_protocol.3 \ - sysdecode_syscallnames.3 \ + sysdecode_syscallname.3 \ sysdecode_utrace.3 MLINKS= sysdecode_abi_to_freebsd_errno.3 sysdecode_freebsd_to_abi_errno.3 MLINKS+=sysdecode_enum.3 sysdecode_acltype.3 \ diff --git a/lib/libsysdecode/sysdecode.3 b/lib/libsysdecode/sysdecode.3 index 0aa4155c004b..32f7fad4e6c5 100644 --- a/lib/libsysdecode/sysdecode.3 +++ b/lib/libsysdecode/sysdecode.3 @@ -73,7 +73,7 @@ A placeholder for use when the ABI is not known. .Xr sysdecode_sigcode 3 , .Xr sysdecode_socket_protocol 3 , .Xr sysdecode_sockopt_name 3 , -.Xr sysdecode_syscallnames 3 , +.Xr sysdecode_syscallname 3 , .Xr sysdecode_utrace 3 .Sh HISTORY The diff --git a/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3 b/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3 index 8f710d1e3756..51955f062393 100644 --- a/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3 +++ b/lib/libsysdecode/sysdecode_abi_to_freebsd_errno.3 @@ -89,4 +89,4 @@ see .Xr sysdecode 3 . .Sh SEE ALSO .Xr sysdecode 3 , -.Xr sysdecode_syscallnames 3 +.Xr sysdecode_syscallname 3 diff --git a/lib/libsysdecode/sysdecode_syscallnames.3 b/lib/libsysdecode/sysdecode_syscallname.3 index 610cbc9b2115..8ba88fd3c43e 100644 --- a/lib/libsysdecode/sysdecode_syscallnames.3 +++ b/lib/libsysdecode/sysdecode_syscallname.3 @@ -23,17 +23,17 @@ .\" SUCH DAMAGE. .\" .Dd October 17, 2016 -.Dt sysdecode_syscallnames 3 +.Dt sysdecode_syscallname 3 .Os .Sh NAME -.Nm sysdecode_syscallnames +.Nm sysdecode_syscallname .Nd lookup name of system calls .Sh LIBRARY .Lb libsysdecode .Sh SYNOPSIS .In sysdecode.h .Ft const char * -.Fn sysdecode_syscallnames "enum sysdecode_abi abi" "unsigned int code" +.Fn sysdecode_syscallname "enum sysdecode_abi abi" "unsigned int code" .Sh DESCRIPTION This function returns a pointer to the name of a system call identified by .Fa code diff --git a/lib/libtelnet/Makefile b/lib/libtelnet/Makefile index 6bc2f5a51de0..2eeac2d44f98 100644 --- a/lib/libtelnet/Makefile +++ b/lib/libtelnet/Makefile @@ -1,6 +1,5 @@ .include <src.opts.mk> -PACKAGE=lib${LIB} TELNETDIR= ${SRCTOP}/contrib/telnet .PATH: ${TELNETDIR}/libtelnet diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile index ab913f834bb3..3b1911d7a5cd 100644 --- a/lib/libufs/Makefile +++ b/lib/libufs/Makefile @@ -1,4 +1,6 @@ -PACKAGE= libufs +PACKAGE= ufs +LIB_PACKAGE= + LIB= ufs SHLIBDIR?= /lib SHLIB_MAJOR= 8 diff --git a/lib/libunbound/Makefile b/lib/libunbound/Makefile index cdc965c20763..e2cd25ea8b34 100644 --- a/lib/libunbound/Makefile +++ b/lib/libunbound/Makefile @@ -13,23 +13,20 @@ PACKAGE= unbound CFLAGS+= -I${UNBOUNDDIR} -I${LDNSDIR} -I${.OBJDIR} -I${.CURDIR} CFLAGS+= -DOPENSSL_API_COMPAT=0x10100000L -SRCS= alloc.c as112.c authzone.c autotrust.c cachedb.c config_file.c \ - configlexer.l configparser.y context.c dname.c dns.c dns64.c \ - dnstree.c edns.c fptr_wlist.c infra.c iter_delegpt.c iter_donotq.c \ - iter_fwd.c iter_hints.c iter_priv.c iter_resptype.c iter_scrub.c \ - iter_utils.c iterator.c keyraw.c libunbound.c libworker.c \ - listen_dnsport.c localzone.c locks.c log.c lookup3.c lruhash.c \ - mesh.c mini_event.c modstack.c module.c msgencode.c msgparse.c \ - msgreply.c net_help.c netevent.c outbound_list.c outside_network.c \ - packed_rrset.c parse.c parseutil.c proxy_protocol.c \ - random.c rbtree.c redis.c \ - regional.c respip.c rfc_1982.c rpz.c rrdef.c rrset.c rtt.c sbuffer.c \ - siphash.c slabhash.c \ - str2wire.c tcp_conn_limit.c timehist.c timeval_func.c \ - tube.c ub_event_pluggable.c \ - val_anchor.c val_kcache.c val_kentry.c val_neg.c val_nsec.c \ - val_nsec3.c val_secalgo.c val_sigcrypt.c val_utils.c validator.c \ - view.c winsock_event.c wire2str.c +SRCS= alloc.c as112.c authzone.c autotrust.c config_file.c configlexer.l \ + configparser.y context.c dname.c dns.c dns64.c dnstree.c edns.c \ + fptr_wlist.c infra.c iter_delegpt.c iter_donotq.c iter_fwd.c \ + iter_hints.c iter_priv.c iter_resptype.c iter_scrub.c iter_utils.c \ + iterator.c keyraw.c libunbound.c libworker.c listen_dnsport.c \ + localzone.c locks.c log.c lookup3.c lruhash.c mesh.c mini_event.c \ + modstack.c module.c msgencode.c msgparse.c msgreply.c net_help.c \ + netevent.c outbound_list.c outside_network.c packed_rrset.c parse.c \ + parseutil.c proxy_protocol.c random.c rbtree.c regional.c respip.c \ + rfc_1982.c rpz.c rrdef.c rrset.c rtt.c sbuffer.c siphash.c \ + slabhash.c str2wire.c tcp_conn_limit.c timehist.c timeval_func.c \ + tube.c ub_event_pluggable.c val_anchor.c val_kcache.c val_kentry.c \ + val_neg.c val_nsec.c val_nsec3.c val_secalgo.c val_sigcrypt.c \ + val_utils.c validator.c view.c winsock_event.c wire2str.c WARNS?= 2 NO_WTHREAD_SAFETY= true diff --git a/lib/libunbound/config.h b/lib/libunbound/config.h index a986bfc869a3..51105977b20a 100644 --- a/lib/libunbound/config.h +++ b/lib/libunbound/config.h @@ -20,7 +20,7 @@ /* #undef COMPAT_SHA512 */ /* Command line arguments used with configure */ -#define CONFCMDLINE "--with-ssl=/usr --with-libexpat=/usr --disable-dnscrypt --disable-dnstap --enable-ecdsa --disable-event-api --enable-gost --with-libevent --disable-subnet --disable-tfo-client --disable-tfo-server --with-pthreads--prefix=/usr --localstatedir=/var/unbound --mandir=/usr/share/man --build=freebsd" +#define CONFCMDLINE "--prefix= --exec-prefix=/usr --with-conf-file=/var/unbound/unbound.conf --with-run-dir=/var/unbound --with-username=unbound" /* Pathname to the Unbound configuration file */ #define CONFIGFILE "/var/unbound/unbound.conf" @@ -49,13 +49,13 @@ internal symbols */ /* #undef EXPORT_ALL_SYMBOLS */ -/* Define to 1 if you have the `accept4' function. */ +/* Define to 1 if you have the 'accept4' function. */ #define HAVE_ACCEPT4 1 -/* Define to 1 if you have the `arc4random' function. */ +/* Define to 1 if you have the 'arc4random' function. */ #define HAVE_ARC4RANDOM 1 -/* Define to 1 if you have the `arc4random_uniform' function. */ +/* Define to 1 if you have the 'arc4random_uniform' function. */ #define HAVE_ARC4RANDOM_UNIFORM 1 /* Define to 1 if you have the <arpa/inet.h> header file. */ @@ -77,13 +77,10 @@ #define HAVE_ATTR_WEAK 1 /* If we have be64toh */ -/* #undef HAVE_BE64TOH */ +#define HAVE_BE64TOH 1 -/* Define to 1 if you have the `BIO_set_callback_ex' function. */ -/* #undef HAVE_BIO_SET_CALLBACK_EX */ - -/* Define to 1 if you have the `BIO_set_callback_ex' function. */ -/* #undef HAVE_BIO_SET_CALLBACK_EX */ +/* Define to 1 if you have the 'BIO_set_callback_ex' function. */ +#define HAVE_BIO_SET_CALLBACK_EX 1 /* Define to 1 if you have the <bsd/stdlib.h> header file. */ /* #undef HAVE_BSD_STDLIB_H */ @@ -91,241 +88,241 @@ /* Define to 1 if you have the <bsd/string.h> header file. */ /* #undef HAVE_BSD_STRING_H */ -/* Define to 1 if you have the `chown' function. */ +/* Define to 1 if you have the 'chown' function. */ #define HAVE_CHOWN 1 -/* Define to 1 if you have the `chroot' function. */ +/* Define to 1 if you have the 'chroot' function. */ #define HAVE_CHROOT 1 -/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* Define to 1 if you have the 'CRYPTO_cleanup_all_ex_data' function. */ /* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ -/* Define to 1 if you have the `CRYPTO_THREADID_set_callback' function. */ +/* Define to 1 if you have the 'CRYPTO_THREADID_set_callback' function. */ /* #undef HAVE_CRYPTO_THREADID_SET_CALLBACK */ -/* Define to 1 if you have the `ctime_r' function. */ +/* Define to 1 if you have the 'ctime_r' function. */ #define HAVE_CTIME_R 1 -/* Define to 1 if you have the `daemon' function. */ +/* Define to 1 if you have the 'daemon' function. */ #define HAVE_DAEMON 1 -/* Define to 1 if you have the declaration of `arc4random', and to 0 if you +/* Define to 1 if you have the declaration of 'arc4random', and to 0 if you don't. */ /* #undef HAVE_DECL_ARC4RANDOM */ -/* Define to 1 if you have the declaration of `arc4random_uniform', and to 0 +/* Define to 1 if you have the declaration of 'arc4random_uniform', and to 0 if you don't. */ /* #undef HAVE_DECL_ARC4RANDOM_UNIFORM */ -/* Define to 1 if you have the declaration of `evsignal_assign', and to 0 if +/* Define to 1 if you have the declaration of 'evsignal_assign', and to 0 if you don't. */ /* #undef HAVE_DECL_EVSIGNAL_ASSIGN */ -/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you +/* Define to 1 if you have the declaration of 'inet_ntop', and to 0 if you don't. */ #define HAVE_DECL_INET_NTOP 1 -/* Define to 1 if you have the declaration of `inet_pton', and to 0 if you +/* Define to 1 if you have the declaration of 'inet_pton', and to 0 if you don't. */ #define HAVE_DECL_INET_PTON 1 -/* Define to 1 if you have the declaration of `nghttp2_session_server_new', +/* Define to 1 if you have the declaration of 'nghttp2_session_server_new', and to 0 if you don't. */ /* #undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW */ -/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you +/* Define to 1 if you have the declaration of 'ngtcp2_conn_server_new', and to + 0 if you don't. */ +/* #undef HAVE_DECL_NGTCP2_CONN_SERVER_NEW */ + +/* Define to 1 if you have the declaration of 'ngtcp2_crypto_encrypt_cb', and + to 0 if you don't. */ +/* #undef HAVE_DECL_NGTCP2_CRYPTO_ENCRYPT_CB */ + +/* Define to 1 if you have the declaration of 'NID_ED25519', and to 0 if you don't. */ #define HAVE_DECL_NID_ED25519 1 -/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you +/* Define to 1 if you have the declaration of 'NID_ED448', and to 0 if you don't. */ #define HAVE_DECL_NID_ED448 1 -/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you +/* Define to 1 if you have the declaration of 'NID_secp384r1', and to 0 if you don't. */ #define HAVE_DECL_NID_SECP384R1 1 -/* Define to 1 if you have the declaration of `NID_X9_62_prime256v1', and to 0 +/* Define to 1 if you have the declaration of 'NID_X9_62_prime256v1', and to 0 if you don't. */ #define HAVE_DECL_NID_X9_62_PRIME256V1 1 -/* Define to 1 if you have the declaration of `reallocarray', and to 0 if you +/* Define to 1 if you have the declaration of 'reallocarray', and to 0 if you don't. */ #define HAVE_DECL_REALLOCARRAY 1 -/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you +/* Define to 1 if you have the declaration of 'redisConnect', and to 0 if you don't. */ /* #undef HAVE_DECL_REDISCONNECT */ -/* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0 +/* Define to 1 if you have the declaration of 'sk_SSL_COMP_pop_free', and to 0 if you don't. */ #define HAVE_DECL_SK_SSL_COMP_POP_FREE 1 /* Define to 1 if you have the declaration of - `SSL_COMP_get_compression_methods', and to 0 if you don't. */ + 'SSL_COMP_get_compression_methods', and to 0 if you don't. */ #define HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS 1 -/* Define to 1 if you have the declaration of `SSL_CTX_set_ecdh_auto', and to +/* Define to 1 if you have the declaration of 'SSL_CTX_set_ecdh_auto', and to 0 if you don't. */ -/* #undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO */ +#define HAVE_DECL_SSL_CTX_SET_ECDH_AUTO 1 -/* Define to 1 if you have the declaration of `strlcat', and to 0 if you +/* Define to 1 if you have the declaration of 'strlcat', and to 0 if you don't. */ /* #undef HAVE_DECL_STRLCAT */ -/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you +/* Define to 1 if you have the declaration of 'strlcpy', and to 0 if you don't. */ /* #undef HAVE_DECL_STRLCPY */ -/* Define to 1 if you have the declaration of `XML_StopParser', and to 0 if +/* Define to 1 if you have the declaration of 'XML_StopParser', and to 0 if you don't. */ #define HAVE_DECL_XML_STOPPARSER 1 /* Define to 1 if you have the <dlfcn.h> header file. */ #define HAVE_DLFCN_H 1 -/* Define to 1 if you have the `DSA_SIG_set0' function. */ +/* Define to 1 if you have the 'DSA_SIG_set0' function. */ #define HAVE_DSA_SIG_SET0 1 /* Define to 1 if you have the <endian.h> header file. */ -/* #undef HAVE_ENDIAN_H */ +#define HAVE_ENDIAN_H 1 -/* Define to 1 if you have the `endprotoent' function. */ +/* Define to 1 if you have the 'endprotoent' function. */ #define HAVE_ENDPROTOENT 1 -/* Define to 1 if you have the `endpwent' function. */ +/* Define to 1 if you have the 'endpwent' function. */ #define HAVE_ENDPWENT 1 -/* Define to 1 if you have the `endservent' function. */ +/* Define to 1 if you have the 'endservent' function. */ #define HAVE_ENDSERVENT 1 -/* Define to 1 if you have the `ENGINE_cleanup' function. */ +/* Define to 1 if you have the 'ENGINE_cleanup' function. */ /* #undef HAVE_ENGINE_CLEANUP */ -/* Define to 1 if you have the `ERR_free_strings' function. */ +/* Define to 1 if you have the 'ERR_free_strings' function. */ /* #undef HAVE_ERR_FREE_STRINGS */ -/* Define to 1 if you have the `ERR_load_crypto_strings' function. */ +/* Define to 1 if you have the 'ERR_load_crypto_strings' function. */ /* #undef HAVE_ERR_LOAD_CRYPTO_STRINGS */ -/* Define to 1 if you have the `event_assign' function. */ +/* Define to 1 if you have the 'event_assign' function. */ /* #undef HAVE_EVENT_ASSIGN */ -/* Define to 1 if you have the `event_base_free' function. */ +/* Define to 1 if you have the 'event_base_free' function. */ /* #undef HAVE_EVENT_BASE_FREE */ -/* Define to 1 if you have the `event_base_get_method' function. */ +/* Define to 1 if you have the 'event_base_get_method' function. */ /* #undef HAVE_EVENT_BASE_GET_METHOD */ -/* Define to 1 if you have the `event_base_new' function. */ +/* Define to 1 if you have the 'event_base_new' function. */ /* #undef HAVE_EVENT_BASE_NEW */ -/* Define to 1 if you have the `event_base_once' function. */ +/* Define to 1 if you have the 'event_base_once' function. */ /* #undef HAVE_EVENT_BASE_ONCE */ /* Define to 1 if you have the <event.h> header file. */ /* #undef HAVE_EVENT_H */ -/* Define to 1 if you have the `EVP_aes_256_cbc' function. */ +/* Define to 1 if you have the 'EVP_aes_256_cbc' function. */ #define HAVE_EVP_AES_256_CBC 1 -/* Define to 1 if you have the `EVP_cleanup' function. */ +/* Define to 1 if you have the 'EVP_cleanup' function. */ /* #undef HAVE_EVP_CLEANUP */ -/* Define to 1 if you have the `EVP_default_properties_is_fips_enabled' +/* Define to 1 if you have the 'EVP_default_properties_is_fips_enabled' function. */ -/* #undef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED */ - +#define HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED 1 -/* Define to 1 if you have the `EVP_default_properties_is_fips_enabled' - function. */ -/* #undef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED */ - -/* Define to 1 if you have the `EVP_DigestVerify' function. */ +/* Define to 1 if you have the 'EVP_DigestVerify' function. */ #define HAVE_EVP_DIGESTVERIFY 1 -/* Define to 1 if you have the `EVP_dss1' function. */ +/* Define to 1 if you have the 'EVP_dss1' function. */ /* #undef HAVE_EVP_DSS1 */ -/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */ +/* Define to 1 if you have the 'EVP_EncryptInit_ex' function. */ #define HAVE_EVP_ENCRYPTINIT_EX 1 -/* Define to 1 if you have the `EVP_MAC_CTX_set_params' function. */ -/* #undef HAVE_EVP_MAC_CTX_SET_PARAMS */ +/* Define to 1 if you have the 'EVP_MAC_CTX_set_params' function. */ +#define HAVE_EVP_MAC_CTX_SET_PARAMS 1 -/* Define to 1 if you have the `EVP_MD_CTX_new' function. */ +/* Define to 1 if you have the 'EVP_MD_CTX_new' function. */ #define HAVE_EVP_MD_CTX_NEW 1 -/* Define to 1 if you have the `EVP_sha1' function. */ +/* Define to 1 if you have the 'EVP_sha1' function. */ #define HAVE_EVP_SHA1 1 -/* Define to 1 if you have the `EVP_sha256' function. */ +/* Define to 1 if you have the 'EVP_sha256' function. */ #define HAVE_EVP_SHA256 1 -/* Define to 1 if you have the `EVP_sha512' function. */ +/* Define to 1 if you have the 'EVP_sha512' function. */ #define HAVE_EVP_SHA512 1 -/* Define to 1 if you have the `ev_default_loop' function. */ +/* Define to 1 if you have the 'ev_default_loop' function. */ /* #undef HAVE_EV_DEFAULT_LOOP */ -/* Define to 1 if you have the `ev_loop' function. */ +/* Define to 1 if you have the 'ev_loop' function. */ /* #undef HAVE_EV_LOOP */ /* Define to 1 if you have the <expat.h> header file. */ #define HAVE_EXPAT_H 1 -/* Define to 1 if you have the `explicit_bzero' function. */ +/* Define to 1 if you have the 'explicit_bzero' function. */ #define HAVE_EXPLICIT_BZERO 1 -/* Define to 1 if you have the `fcntl' function. */ +/* Define to 1 if you have the 'fcntl' function. */ #define HAVE_FCNTL 1 -/* Define to 1 if you have the `FIPS_mode' function. */ -#define HAVE_FIPS_MODE 1 +/* Define to 1 if you have the 'FIPS_mode' function. */ +/* #undef HAVE_FIPS_MODE */ -/* Define to 1 if you have the `fork' function. */ +/* Define to 1 if you have the 'fork' function. */ #define HAVE_FORK 1 -/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +/* Define to 1 if fseeko (and ftello) are declared in stdio.h. */ #define HAVE_FSEEKO 1 -/* Define to 1 if you have the `fsync' function. */ +/* Define to 1 if you have the 'fsync' function. */ #define HAVE_FSYNC 1 /* Whether getaddrinfo is available */ #define HAVE_GETADDRINFO 1 -/* Define to 1 if you have the `getauxval' function. */ +/* Define to 1 if you have the 'getauxval' function. */ /* #undef HAVE_GETAUXVAL */ -/* Define to 1 if you have the `getentropy' function. */ +/* Define to 1 if you have the 'getentropy' function. */ /* #undef HAVE_GETENTROPY */ -/* Define to 1 if you have the `getifaddrs' function. */ +/* Define to 1 if you have the 'getifaddrs' function. */ #define HAVE_GETIFADDRS 1 /* Define to 1 if you have the <getopt.h> header file. */ #define HAVE_GETOPT_H 1 -/* Define to 1 if you have the `getpwnam' function. */ +/* Define to 1 if you have the 'getpwnam' function. */ #define HAVE_GETPWNAM 1 -/* Define to 1 if you have the `getrlimit' function. */ +/* Define to 1 if you have the 'getrlimit' function. */ #define HAVE_GETRLIMIT 1 -/* Define to 1 if you have the `gettid' function. */ -/* #undef HAVE_GETTID */ - -/* Define to 1 if you have the `gettid' function. */ +/* Define to 1 if you have the 'gettid' function. */ /* #undef HAVE_GETTID */ -/* Define to 1 if you have the `glob' function. */ +/* Define to 1 if you have the 'glob' function. */ #define HAVE_GLOB 1 /* Define to 1 if you have the <glob.h> header file. */ #define HAVE_GLOB_H 1 -/* Define to 1 if you have the `gmtime_r' function. */ +/* Define to 1 if you have the 'gmtime_r' function. */ #define HAVE_GMTIME_R 1 /* Define to 1 if you have the <grp.h> header file. */ @@ -334,31 +331,28 @@ /* Define to 1 if you have the <hiredis/hiredis.h> header file. */ /* #undef HAVE_HIREDIS_HIREDIS_H */ -/* Define to 1 if you have the `HMAC_Init_ex' function. */ +/* Define to 1 if you have the 'HMAC_Init_ex' function. */ #define HAVE_HMAC_INIT_EX 1 /* If we have htobe64 */ -/* #undef HAVE_HTOBE64 */ +#define HAVE_HTOBE64 1 /* Define to 1 if you have the <ifaddrs.h> header file. */ #define HAVE_IFADDRS_H 1 -/* Define to 1 if you have the `if_nametoindex' function. */ +/* Define to 1 if you have the 'if_nametoindex' function. */ #define HAVE_IF_NAMETOINDEX 1 -/* Define to 1 if you have the `if_nametoindex' function. */ -#define HAVE_IF_NAMETOINDEX 1 - -/* Define to 1 if you have the `inet_aton' function. */ +/* Define to 1 if you have the 'inet_aton' function. */ #define HAVE_INET_ATON 1 -/* Define to 1 if you have the `inet_ntop' function. */ +/* Define to 1 if you have the 'inet_ntop' function. */ #define HAVE_INET_NTOP 1 -/* Define to 1 if you have the `inet_pton' function. */ +/* Define to 1 if you have the 'inet_pton' function. */ #define HAVE_INET_PTON 1 -/* Define to 1 if you have the `initgroups' function. */ +/* Define to 1 if you have the 'initgroups' function. */ #define HAVE_INITGROUPS 1 /* Define to 1 if you have the <inttypes.h> header file. */ @@ -370,10 +364,10 @@ /* Define to 1 if you have the <iphlpapi.h> header file. */ /* #undef HAVE_IPHLPAPI_H */ -/* Define to 1 if you have the `isblank' function. */ +/* Define to 1 if you have the 'isblank' function. */ #define HAVE_ISBLANK 1 -/* Define to 1 if you have the `kill' function. */ +/* Define to 1 if you have the 'kill' function. */ #define HAVE_KILL 1 /* Use portable libbsd functions */ @@ -385,7 +379,13 @@ /* Define if we have LibreSSL */ /* #undef HAVE_LIBRESSL */ -/* Define to 1 if you have the `localtime_r' function. */ +/* If we have atomic_store */ +#define HAVE_LINK_ATOMIC_STORE 1 + +/* Define to 1 if you have the <linux/net_tstamp.h> header file. */ +/* #undef HAVE_LINUX_NET_TSTAMP_H */ + +/* Define to 1 if you have the 'localtime_r' function. */ #define HAVE_LOCALTIME_R 1 /* Define to 1 if you have the <login_cap.h> header file. */ @@ -394,7 +394,7 @@ /* If have GNU libc compatible malloc */ #define HAVE_MALLOC 1 -/* Define to 1 if you have the `memmove' function. */ +/* Define to 1 if you have the 'memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the <minix/config.h> header file. */ @@ -424,29 +424,91 @@ /* Define to 1 if you have the <net/if.h> header file. */ #define HAVE_NET_IF_H 1 +/* Define to 1 if you have the <net/pfvar.h> header file. */ +/* #undef HAVE_NET_PFVAR_H */ + /* Define this to use nghttp2 client. */ /* #undef HAVE_NGHTTP2 */ /* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */ /* #undef HAVE_NGHTTP2_NGHTTP2_H */ +/* Define this to use ngtcp2. */ +/* #undef HAVE_NGTCP2 */ + +/* Define to 1 if you have the 'ngtcp2_ccerr_default' function. */ +/* #undef HAVE_NGTCP2_CCERR_DEFAULT */ + +/* Define to 1 if you have the 'ngtcp2_conn_encode_0rtt_transport_params' + function. */ +/* #undef HAVE_NGTCP2_CONN_ENCODE_0RTT_TRANSPORT_PARAMS */ + +/* Define to 1 if you have the 'ngtcp2_conn_get_max_local_streams_uni' + function. */ +/* #undef HAVE_NGTCP2_CONN_GET_MAX_LOCAL_STREAMS_UNI */ + +/* Define to 1 if you have the 'ngtcp2_conn_get_num_scid' function. */ +/* #undef HAVE_NGTCP2_CONN_GET_NUM_SCID */ + +/* Define to 1 if you have the 'ngtcp2_conn_in_closing_period' function. */ +/* #undef HAVE_NGTCP2_CONN_IN_CLOSING_PERIOD */ + +/* Define to 1 if you have the 'ngtcp2_conn_in_draining_period' function. */ +/* #undef HAVE_NGTCP2_CONN_IN_DRAINING_PERIOD */ + +/* Define if ngtcp2_conn_shutdown_stream has 4 arguments. */ +/* #undef HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4 */ + +/* Define to 1 if you have the 'ngtcp2_conn_tls_early_data_rejected' function. + */ +/* #undef HAVE_NGTCP2_CONN_TLS_EARLY_DATA_REJECTED */ + +/* Define to 1 if you have the 'ngtcp2_crypto_encrypt_cb' function. */ +/* #undef HAVE_NGTCP2_CRYPTO_ENCRYPT_CB */ + +/* Define to 1 if you have the + 'ngtcp2_crypto_quictls_configure_client_context' function. */ +/* #undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_CLIENT_CONTEXT */ + +/* Define to 1 if you have the + 'ngtcp2_crypto_quictls_configure_server_context' function. */ +/* #undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT */ + +/* Define to 1 if you have the + 'ngtcp2_crypto_quictls_from_ossl_encryption_level' function. */ +/* #undef HAVE_NGTCP2_CRYPTO_QUICTLS_FROM_OSSL_ENCRYPTION_LEVEL */ + +/* Define to 1 if the system has the type 'ngtcp2_encryption_level'. */ +/* #undef HAVE_NGTCP2_ENCRYPTION_LEVEL */ + +/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_openssl.h> header file. + */ +/* #undef HAVE_NGTCP2_NGTCP2_CRYPTO_OPENSSL_H */ + +/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_quictls.h> header file. + */ +/* #undef HAVE_NGTCP2_NGTCP2_CRYPTO_QUICTLS_H */ + +/* Define to 1 if you have the <ngtcp2/ngtcp2.h> header file. */ +/* #undef HAVE_NGTCP2_NGTCP2_H */ + /* Use libnss for crypto */ /* #undef HAVE_NSS */ -/* Define to 1 if you have the `OpenSSL_add_all_digests' function. */ +/* Define to 1 if you have the 'OpenSSL_add_all_digests' function. */ /* #undef HAVE_OPENSSL_ADD_ALL_DIGESTS */ /* Define to 1 if you have the <openssl/bn.h> header file. */ #define HAVE_OPENSSL_BN_H 1 -/* Define to 1 if you have the `OPENSSL_config' function. */ +/* Define to 1 if you have the 'OPENSSL_config' function. */ #define HAVE_OPENSSL_CONFIG 1 /* Define to 1 if you have the <openssl/conf.h> header file. */ #define HAVE_OPENSSL_CONF_H 1 /* Define to 1 if you have the <openssl/core_names.h> header file. */ -/* #undef HAVE_OPENSSL_CORE_NAMES_H */ +#define HAVE_OPENSSL_CORE_NAMES_H 1 /* Define to 1 if you have the <openssl/dh.h> header file. */ #define HAVE_OPENSSL_DH_H 1 @@ -460,14 +522,14 @@ /* Define to 1 if you have the <openssl/err.h> header file. */ #define HAVE_OPENSSL_ERR_H 1 -/* Define to 1 if you have the `OPENSSL_init_crypto' function. */ +/* Define to 1 if you have the 'OPENSSL_init_crypto' function. */ #define HAVE_OPENSSL_INIT_CRYPTO 1 -/* Define to 1 if you have the `OPENSSL_init_ssl' function. */ +/* Define to 1 if you have the 'OPENSSL_init_ssl' function. */ #define HAVE_OPENSSL_INIT_SSL 1 /* Define to 1 if you have the <openssl/param_build.h> header file. */ -/* #undef HAVE_OPENSSL_PARAM_BUILD_H */ +#define HAVE_OPENSSL_PARAM_BUILD_H 1 /* Define to 1 if you have the <openssl/rand.h> header file. */ #define HAVE_OPENSSL_RAND_H 1 @@ -478,10 +540,10 @@ /* Define to 1 if you have the <openssl/ssl.h> header file. */ #define HAVE_OPENSSL_SSL_H 1 -/* Define to 1 if you have the `OSSL_PARAM_BLD_new' function. */ -/* #undef HAVE_OSSL_PARAM_BLD_NEW */ +/* Define to 1 if you have the 'OSSL_PARAM_BLD_new' function. */ +#define HAVE_OSSL_PARAM_BLD_NEW 1 -/* Define to 1 if you have the `poll' function. */ +/* Define to 1 if you have the 'poll' function. */ #define HAVE_POLL 1 /* Define to 1 if you have the <poll.h> header file. */ @@ -493,10 +555,10 @@ /* Have PTHREAD_PRIO_INHERIT. */ #define HAVE_PTHREAD_PRIO_INHERIT 1 -/* Define to 1 if the system has the type `pthread_rwlock_t'. */ +/* Define to 1 if the system has the type 'pthread_rwlock_t'. */ #define HAVE_PTHREAD_RWLOCK_T 1 -/* Define to 1 if the system has the type `pthread_spinlock_t'. */ +/* Define to 1 if the system has the type 'pthread_spinlock_t'. */ #define HAVE_PTHREAD_SPINLOCK_T 1 /* Define to 1 if you have the <pwd.h> header file. */ @@ -505,100 +567,109 @@ /* Define if you have Python libraries and header files. */ /* #undef HAVE_PYTHON */ -/* Define to 1 if you have the `random' function. */ +/* Define to 1 if you have the 'random' function. */ #define HAVE_RANDOM 1 -/* Define to 1 if you have the `RAND_cleanup' function. */ +/* Define to 1 if you have the 'RAND_cleanup' function. */ /* #undef HAVE_RAND_CLEANUP */ /* If we have reallocarray(3) */ #define HAVE_REALLOCARRAY 1 -/* Define to 1 if you have the `recvmsg' function. */ +/* Define to 1 if you have the 'recvmsg' function. */ #define HAVE_RECVMSG 1 -/* Define to 1 if you have the `sendmsg' function. */ +/* Define to 1 if you have the 'sendmsg' function. */ #define HAVE_SENDMSG 1 -/* Define to 1 if you have the `setregid' function. */ +/* Define to 1 if you have the 'setregid' function. */ /* #undef HAVE_SETREGID */ -/* Define to 1 if you have the `setresgid' function. */ +/* Define to 1 if you have the 'setresgid' function. */ #define HAVE_SETRESGID 1 -/* Define to 1 if you have the `setresuid' function. */ +/* Define to 1 if you have the 'setresuid' function. */ #define HAVE_SETRESUID 1 -/* Define to 1 if you have the `setreuid' function. */ +/* Define to 1 if you have the 'setreuid' function. */ /* #undef HAVE_SETREUID */ -/* Define to 1 if you have the `setrlimit' function. */ +/* Define to 1 if you have the 'setrlimit' function. */ #define HAVE_SETRLIMIT 1 -/* Define to 1 if you have the `setsid' function. */ +/* Define to 1 if you have the 'setsid' function. */ #define HAVE_SETSID 1 -/* Define to 1 if you have the `setusercontext' function. */ +/* Define to 1 if you have the 'setusercontext' function. */ #define HAVE_SETUSERCONTEXT 1 -/* Define to 1 if you have the `SHA512_Update' function. */ +/* Define to 1 if you have the 'SHA512_Update' function. */ /* #undef HAVE_SHA512_UPDATE */ -/* Define to 1 if you have the `shmget' function. */ +/* Define to 1 if you have the 'shmget' function. */ #define HAVE_SHMGET 1 -/* Define to 1 if you have the `sigprocmask' function. */ +/* Define to 1 if you have the 'sigprocmask' function. */ #define HAVE_SIGPROCMASK 1 -/* Define to 1 if you have the `sleep' function. */ +/* Define to 1 if you have the 'sleep' function. */ #define HAVE_SLEEP 1 -/* Define to 1 if you have the `snprintf' function. */ +/* Define to 1 if you have the 'snprintf' function. */ #define HAVE_SNPRINTF 1 -/* Define to 1 if you have the `socketpair' function. */ +/* Define to 1 if you have the 'socketpair' function. */ #define HAVE_SOCKETPAIR 1 /* Using Solaris threads */ /* #undef HAVE_SOLARIS_THREADS */ -/* Define to 1 if you have the `srandom' function. */ +/* Define to 1 if you have the 'srandom' function. */ #define HAVE_SRANDOM 1 /* Define if you have the SSL libraries installed. */ #define HAVE_SSL /**/ -/* Define to 1 if you have the `SSL_CTX_set_alpn_protos' function. */ +/* Define to 1 if you have the 'SSL_CTX_set_alpn_protos' function. */ #define HAVE_SSL_CTX_SET_ALPN_PROTOS 1 -/* Define to 1 if you have the `SSL_CTX_set_alpn_select_cb' function. */ +/* Define to 1 if you have the 'SSL_CTX_set_alpn_select_cb' function. */ #define HAVE_SSL_CTX_SET_ALPN_SELECT_CB 1 -/* Define to 1 if you have the `SSL_CTX_set_ciphersuites' function. */ +/* Define to 1 if you have the 'SSL_CTX_set_ciphersuites' function. */ #define HAVE_SSL_CTX_SET_CIPHERSUITES 1 -/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */ +/* Define to 1 if you have the 'SSL_CTX_set_security_level' function. */ #define HAVE_SSL_CTX_SET_SECURITY_LEVEL 1 -/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_evp_cb' +/* Define to 1 if you have the 'SSL_CTX_set_tlsext_ticket_key_evp_cb' function. */ -/* #undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB */ +#define HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB 1 + +/* Define to 1 if you have the 'SSL_CTX_set_tmp_ecdh' function. */ +/* #undef HAVE_SSL_CTX_SET_TMP_ECDH */ -/* Define to 1 if you have the `SSL_get0_alpn_selected' function. */ +/* Define to 1 if you have the 'SSL_get0_alpn_selected' function. */ #define HAVE_SSL_GET0_ALPN_SELECTED 1 -/* Define to 1 if you have the `SSL_get0_peername' function. */ +/* Define to 1 if you have the 'SSL_get0_peername' function. */ #define HAVE_SSL_GET0_PEERNAME 1 -/* Define to 1 if you have the `SSL_get1_peer_certificate' function. */ -/* #undef HAVE_SSL_GET1_PEER_CERTIFICATE */ +/* Define to 1 if you have the 'SSL_get1_peer_certificate' function. */ +#define HAVE_SSL_GET1_PEER_CERTIFICATE 1 -/* Define to 1 if you have the `SSL_set1_host' function. */ +/* Define to 1 if you have the 'SSL_is_quic' function. */ +/* #undef HAVE_SSL_IS_QUIC */ + +/* Define to 1 if you have the 'SSL_set1_host' function. */ #define HAVE_SSL_SET1_HOST 1 /* Define to 1 if you have the <stdarg.h> header file. */ #define HAVE_STDARG_H 1 +/* Define to 1 if you have the <stdatomic.h> header file. */ +#define HAVE_STDATOMIC_H 1 + /* Define to 1 if you have the <stdbool.h> header file. */ #define HAVE_STDBOOL_H 1 @@ -611,7 +682,7 @@ /* Define to 1 if you have the <stdlib.h> header file. */ #define HAVE_STDLIB_H 1 -/* Define to 1 if you have the `strftime' function. */ +/* Define to 1 if you have the 'strftime' function. */ #define HAVE_STRFTIME 1 /* Define to 1 if you have the <strings.h> header file. */ @@ -620,22 +691,39 @@ /* Define to 1 if you have the <string.h> header file. */ #define HAVE_STRING_H 1 -/* Define to 1 if you have the `strlcat' function. */ +/* Define to 1 if you have the 'strlcat' function. */ #define HAVE_STRLCAT 1 -/* Define to 1 if you have the `strlcpy' function. */ +/* Define to 1 if you have the 'strlcpy' function. */ #define HAVE_STRLCPY 1 -/* Define to 1 if you have the `strptime' function. */ +/* Define to 1 if you have the 'strptime' function. */ #define HAVE_STRPTIME 1 -/* Define to 1 if you have the `strsep' function. */ +/* Define to 1 if you have the 'strsep' function. */ #define HAVE_STRSEP 1 -/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */ +/* Define to 1 if 'ipi_spec_dst' is a member of 'struct in_pktinfo'. */ /* #undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST */ -/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */ +/* Define to 1 if 'tokenlen' is a member of 'struct ngtcp2_pkt_hd'. */ +/* #undef HAVE_STRUCT_NGTCP2_PKT_HD_TOKENLEN */ + +/* Define to 1 if 'max_tx_udp_payload_size' is a member of 'struct + ngtcp2_settings'. */ +/* #undef HAVE_STRUCT_NGTCP2_SETTINGS_MAX_TX_UDP_PAYLOAD_SIZE */ + +/* Define to 1 if 'tokenlen' is a member of 'struct ngtcp2_settings'. */ +/* #undef HAVE_STRUCT_NGTCP2_SETTINGS_TOKENLEN */ + +/* Define to 1 if 'original_dcid_present' is a member of 'struct + ngtcp2_transport_params'. */ +/* #undef HAVE_STRUCT_NGTCP2_TRANSPORT_PARAMS_ORIGINAL_DCID_PRESENT */ + +/* Define to 1 if the system has the type 'struct ngtcp2_version_cid'. */ +/* #undef HAVE_STRUCT_NGTCP2_VERSION_CID */ + +/* Define to 1 if 'sun_len' is a member of 'struct sockaddr_un'. */ #define HAVE_STRUCT_SOCKADDR_UN_SUN_LEN 1 /* Define if you have Swig libraries and header files. */ @@ -695,16 +783,16 @@ /* Define to 1 if you have the <time.h> header file. */ #define HAVE_TIME_H 1 -/* Define to 1 if you have the `tzset' function. */ +/* Define to 1 if you have the 'tzset' function. */ #define HAVE_TZSET 1 /* Define to 1 if you have the <unistd.h> header file. */ #define HAVE_UNISTD_H 1 -/* Define to 1 if you have the `usleep' function. */ +/* Define to 1 if you have the 'usleep' function. */ #define HAVE_USLEEP 1 -/* Define to 1 if you have the `vfork' function. */ +/* Define to 1 if you have the 'vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the <vfork.h> header file. */ @@ -722,22 +810,22 @@ /* Define to 1 if you have the <winsock2.h> header file. */ /* #undef HAVE_WINSOCK2_H */ -/* Define to 1 if `fork' works. */ +/* Define to 1 if 'fork' works. */ #define HAVE_WORKING_FORK 1 -/* Define to 1 if `vfork' works. */ +/* Define to 1 if 'vfork' works. */ #define HAVE_WORKING_VFORK 1 -/* Define to 1 if you have the `writev' function. */ +/* Define to 1 if you have the 'writev' function. */ #define HAVE_WRITEV 1 /* Define to 1 if you have the <ws2tcpip.h> header file. */ /* #undef HAVE_WS2TCPIP_H */ -/* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */ +/* Define to 1 if you have the 'X509_VERIFY_PARAM_set1_host' function. */ #define HAVE_X509_VERIFY_PARAM_SET1_HOST 1 -/* Define to 1 if you have the `_beginthreadex' function. */ +/* Define to 1 if you have the '_beginthreadex' function. */ /* #undef HAVE__BEGINTHREADEX */ /* If HMAC_Init_ex() returns void */ @@ -796,7 +884,7 @@ #define PACKAGE_NAME "unbound" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "unbound 1.23.0" +#define PACKAGE_STRING "unbound 1.23.1" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "unbound" @@ -805,7 +893,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "1.23.0" +#define PACKAGE_VERSION "1.23.1" /* default pidfile location */ #define PIDFILE "/var/unbound/unbound.pid" @@ -828,7 +916,7 @@ #define ROOT_CERT_FILE "/var/unbound/icannbundle.pem" /* version number for resource files */ -#define RSRC_PACKAGE_VERSION 1,23,0,0 +#define RSRC_PACKAGE_VERSION 1,23,1,0 /* Directory to chdir to */ #define RUN_DIR "/var/unbound" @@ -836,32 +924,17 @@ /* Shared data */ #define SHARE_DIR "/var/unbound" -#ifdef __LP64__ -/* The size of `size_t', as computed by sizeof. */ -#define SIZEOF_SIZE_T 8 -/* The size of `size_t'. */ -/* The size of `pthread_t', as computed by sizeof. */ +/* The size of 'pthread_t', as computed by sizeof. */ #define SIZEOF_PTHREAD_T 8 -#else -#define SIZEOF_SIZE_T 4 -/* The size of `size_t'. */ -/* The size of `pthread_t', as computed by sizeof. */ -#define SIZEOF_PTHREAD_T 4 -#endif -/* The size of `time_t', as computed by sizeof. */ -#ifdef __i386__ -#define SIZEOF_TIME_T 4 -#else +/* The size of 'size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of 'time_t', as computed by sizeof. */ #define SIZEOF_TIME_T 8 -#endif -/* The size of `unsigned long', as computed by sizeof. */ -#ifdef __LP64__ +/* The size of 'unsigned long', as computed by sizeof. */ #define SIZEOF_UNSIGNED_LONG 8 -#else -#define SIZEOF_UNSIGNED_LONG 4 -#endif /* define if (v)snprintf does not return length needed, (but length used) */ /* #undef SNPRINTF_RET_BROKEN */ @@ -869,7 +942,7 @@ /* Define to 1 if libsodium supports sodium_set_misuse_handler */ /* #undef SODIUM_MISUSE_HANDLER */ -/* Define to 1 if all of the C90 standard headers exist (not just the ones +/* Define to 1 if all of the C89 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #define STDC_HEADERS 1 @@ -911,7 +984,7 @@ /* #undef USE_DNSTAP */ /* Define this to enable DSA support. */ -#define USE_DSA 1 +/* #undef USE_DSA */ /* Define this to enable ECDSA support. */ #define USE_ECDSA 1 @@ -935,7 +1008,7 @@ /* #undef USE_IPSET */ /* Define if you enable libevent */ -#define USE_LIBEVENT 1 +/* #undef USE_LIBEVENT */ /* Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and @@ -963,7 +1036,7 @@ /* Define this to enable SHA256 and SHA512 support. */ #define USE_SHA2 1 -/* Enable extensions on AIX 3, Interix. */ +/* Enable extensions on AIX, Interix, z/OS. */ #ifndef _ALL_SOURCE # define _ALL_SOURCE 1 #endif @@ -1024,11 +1097,15 @@ #ifndef __STDC_WANT_IEC_60559_DFP_EXT__ # define __STDC_WANT_IEC_60559_DFP_EXT__ 1 #endif +/* Enable extensions specified by C23 Annex F. */ +#ifndef __STDC_WANT_IEC_60559_EXT__ +# define __STDC_WANT_IEC_60559_EXT__ 1 +#endif /* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ #ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ # define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1 #endif -/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ +/* Enable extensions specified by C23 Annex H and ISO/IEC TS 18661-3:2015. */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ # define __STDC_WANT_IEC_60559_TYPES_EXT__ 1 #endif @@ -1069,30 +1146,36 @@ /* Define if you want PyUnbound. */ /* #undef WITH_PYUNBOUND */ -/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a - `char[]'. */ +/* Define to 1 if 'lex' declares 'yytext' as a 'char *' by default, not a + 'char[]'. */ #define YYTEXT_POINTER 1 /* Number of bits in a file offset, on hosts where this is settable. */ /* #undef _FILE_OFFSET_BITS */ -/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +/* Define to 1 if necessary to make fseeko visible. */ /* #undef _LARGEFILE_SOURCE */ -/* Define for large files, on AIX-style hosts. */ +/* Define to 1 on platforms where this makes off_t a 64-bit type. */ /* #undef _LARGE_FILES */ /* Enable for compile on Minix */ #define _NETBSD_SOURCE 1 +/* Number of bits in time_t, on hosts where this is settable. */ +/* #undef _TIME_BITS */ + +/* Define to 1 on platforms where this makes time_t a 64-bit type. */ +/* #undef __MINGW_USE_VC2005_COMPAT */ + /* defined to use gcc ansi snprintf and sscanf that understands %lld when compiled for windows. */ /* #undef __USE_MINGW_ANSI_STDIO */ -/* Define to empty if `const' does not conform to ANSI C. */ +/* Define to empty if 'const' does not conform to ANSI C. */ /* #undef const */ -/* Define to `int' if <sys/types.h> doesn't define. */ +/* Define as 'int' if <sys/types.h> doesn't define. */ /* #undef gid_t */ /* in_addr_t */ @@ -1101,28 +1184,28 @@ /* in_port_t */ /* #undef in_port_t */ -/* Define to `__inline__' or `__inline' if that's what the C compiler +/* Define to '__inline__' or '__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif -/* Define to `short' if <sys/types.h> does not define. */ +/* Define to 'short' if <sys/types.h> does not define. */ /* #undef int16_t */ -/* Define to `int' if <sys/types.h> does not define. */ +/* Define to 'int' if <sys/types.h> does not define. */ /* #undef int32_t */ -/* Define to `long long' if <sys/types.h> does not define. */ +/* Define to 'long long' if <sys/types.h> does not define. */ /* #undef int64_t */ -/* Define to `signed char' if <sys/types.h> does not define. */ +/* Define to 'signed char' if <sys/types.h> does not define. */ /* #undef int8_t */ /* Define if replacement function should be used. */ /* #undef malloc */ -/* Define to `long int' if <sys/types.h> does not define. */ +/* Define to 'long int' if <sys/types.h> does not define. */ /* #undef off_t */ /* Define as a signed integer type capable of holding a process identifier. */ @@ -1131,71 +1214,71 @@ /* Define to 'int' if not defined */ /* #undef rlim_t */ -/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* Define as 'unsigned int' if <stddef.h> doesn't define. */ /* #undef size_t */ /* Define to 'int' if not defined */ /* #undef socklen_t */ -/* Define to `int' if <sys/types.h> does not define. */ +/* Define to 'int' if <sys/types.h> does not define. */ /* #undef ssize_t */ /* Define to 'unsigned char if not defined */ /* #undef u_char */ -/* Define to `int' if <sys/types.h> doesn't define. */ +/* Define as 'int' if <sys/types.h> doesn't define. */ /* #undef uid_t */ -/* Define to `unsigned short' if <sys/types.h> does not define. */ +/* Define to 'unsigned short' if <sys/types.h> does not define. */ /* #undef uint16_t */ -/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* Define to 'unsigned int' if <sys/types.h> does not define. */ /* #undef uint32_t */ -/* Define to `unsigned long long' if <sys/types.h> does not define. */ +/* Define to 'unsigned long long' if <sys/types.h> does not define. */ /* #undef uint64_t */ -/* Define to `unsigned char' if <sys/types.h> does not define. */ +/* Define to 'unsigned char' if <sys/types.h> does not define. */ /* #undef uint8_t */ -/* Define as `fork' if `vfork' does not work. */ +/* Define as 'fork' if 'vfork' does not work. */ /* #undef vfork */ #if defined(OMITTED__D_GNU_SOURCE) && !defined(_GNU_SOURCE) #define _GNU_SOURCE 1 -#endif +#endif #if defined(OMITTED__D_BSD_SOURCE) && !defined(_BSD_SOURCE) #define _BSD_SOURCE 1 -#endif +#endif #if defined(OMITTED__D_DEFAULT_SOURCE) && !defined(_DEFAULT_SOURCE) #define _DEFAULT_SOURCE 1 -#endif +#endif #if defined(OMITTED__D__EXTENSIONS__) && !defined(__EXTENSIONS__) #define __EXTENSIONS__ 1 -#endif +#endif #if defined(OMITTED__D_POSIX_C_SOURCE_200112) && !defined(_POSIX_C_SOURCE) #define _POSIX_C_SOURCE 200112 -#endif +#endif #if defined(OMITTED__D_XOPEN_SOURCE_600) && !defined(_XOPEN_SOURCE) #define _XOPEN_SOURCE 600 -#endif +#endif #if defined(OMITTED__D_XOPEN_SOURCE_EXTENDED_1) && !defined(_XOPEN_SOURCE_EXTENDED) #define _XOPEN_SOURCE_EXTENDED 1 -#endif +#endif #if defined(OMITTED__D_ALL_SOURCE) && !defined(_ALL_SOURCE) #define _ALL_SOURCE 1 -#endif +#endif #if defined(OMITTED__D_LARGEFILE_SOURCE_1) && !defined(_LARGEFILE_SOURCE) #define _LARGEFILE_SOURCE 1 -#endif +#endif @@ -1279,7 +1362,7 @@ #endif - + #ifdef HAVE_ATTR_FORMAT # define ATTR_FORMAT(archetype, string_index, first_to_check) \ __attribute__ ((format (archetype, string_index, first_to_check))) @@ -1389,7 +1472,7 @@ void* reallocarray(void *ptr, size_t nmemb, size_t size); #ifdef HAVE_WINSOCK2_H #define FD_SET_T (u_int) #else -#define FD_SET_T +#define FD_SET_T #endif @@ -1517,6 +1600,10 @@ struct sockaddr_storage; # define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__) # define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__) # define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__) +# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__) +#ifdef HAVE_REALLOCARRAY +# define reallocarray(p,n,s) unbound_stat_reallocarray_log(p, n, s, __FILE__, __LINE__, __func__) +#endif void *unbound_stat_malloc(size_t size); void *unbound_stat_calloc(size_t nmemb, size_t size); void unbound_stat_free(void *ptr); @@ -1529,6 +1616,10 @@ void unbound_stat_free_log(void *ptr, const char* file, int line, const char* func); void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file, int line, const char* func); +void *unbound_stat_reallocarray_log(void *ptr, size_t nmemb, size_t size, + const char* file, int line, const char* func); +char *unbound_stat_strdup_log(const char *s, const char* file, int line, + const char* func); #elif defined(UNBOUND_ALLOC_LITE) # include "util/alloc.h" #endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */ diff --git a/lib/libutil++/Makefile b/lib/libutil++/Makefile index 729a336ddb3a..2e7a614df800 100644 --- a/lib/libutil++/Makefile +++ b/lib/libutil++/Makefile @@ -1,4 +1,3 @@ -PACKAGE= clibs LIB_CXX= util++ INTERNALLIB= true SHLIB_MAJOR= 1 @@ -12,6 +11,10 @@ MAN+= freebsd::FILE_up.3 \ freebsd::pidfile.3 \ freebsd::stringf.3 +.for page in ${MAN} +MANSRC.${page}= ${page:S/:/_/g} +.endfor + .include <src.opts.mk> HAS_TESTS= diff --git a/lib/libutil++/freebsd::FILE_up.3 b/lib/libutil++/freebsd__FILE_up.3 index ea63b1233b43..ea63b1233b43 100644 --- a/lib/libutil++/freebsd::FILE_up.3 +++ b/lib/libutil++/freebsd__FILE_up.3 diff --git a/lib/libutil++/freebsd::addrinfo_up.3 b/lib/libutil++/freebsd__addrinfo_up.3 index 4845a76bfb61..4845a76bfb61 100644 --- a/lib/libutil++/freebsd::addrinfo_up.3 +++ b/lib/libutil++/freebsd__addrinfo_up.3 diff --git a/lib/libutil++/freebsd::fd_up.3 b/lib/libutil++/freebsd__fd_up.3 index 2ef2241a5c40..2ef2241a5c40 100644 --- a/lib/libutil++/freebsd::fd_up.3 +++ b/lib/libutil++/freebsd__fd_up.3 diff --git a/lib/libutil++/freebsd::malloc_up.3 b/lib/libutil++/freebsd__malloc_up.3 index b18e7854213a..b18e7854213a 100644 --- a/lib/libutil++/freebsd::malloc_up.3 +++ b/lib/libutil++/freebsd__malloc_up.3 diff --git a/lib/libutil++/freebsd::nvlist_up.3 b/lib/libutil++/freebsd__nvlist_up.3 index 43f76cf3ead3..43f76cf3ead3 100644 --- a/lib/libutil++/freebsd::nvlist_up.3 +++ b/lib/libutil++/freebsd__nvlist_up.3 diff --git a/lib/libutil++/freebsd::pidfile.3 b/lib/libutil++/freebsd__pidfile.3 index fb67253f5c02..fb67253f5c02 100644 --- a/lib/libutil++/freebsd::pidfile.3 +++ b/lib/libutil++/freebsd__pidfile.3 diff --git a/lib/libutil++/freebsd::stringf.3 b/lib/libutil++/freebsd__stringf.3 index 341fedef4343..341fedef4343 100644 --- a/lib/libutil++/freebsd::stringf.3 +++ b/lib/libutil++/freebsd__stringf.3 diff --git a/lib/libutil/login.conf.5 b/lib/libutil/login.conf.5 index 27f37fb5fc30..942f3ecd2661 100644 --- a/lib/libutil/login.conf.5 +++ b/lib/libutil/login.conf.5 @@ -17,7 +17,7 @@ .\" 5. Modifications may be freely made to this file providing the above .\" conditions are met. .\" -.Dd June 28, 2023 +.Dd September 25, 2025 .Dt LOGIN.CONF 5 .Os .Sh NAME @@ -496,7 +496,7 @@ lists. .Xr pam 3 , .Xr passwd 5 , .Xr ttys 5 , -.Xr ftpd 8 , +.Xr ftpd 8 Pq Pa ports/ftp/freebsd-ftpd , .Xr pam_passwdqc 8 .Sh HISTORY The file diff --git a/lib/libutil/mntopts.c b/lib/libutil/mntopts.c index 1d9347e3108a..07d3dd6d98a3 100644 --- a/lib/libutil/mntopts.c +++ b/lib/libutil/mntopts.c @@ -185,6 +185,7 @@ getmntpoint(const char *name) strncpy(statfsp->f_mntfromname, device, len); } if (stat(ddevname, &mntdevstat) == 0 && + S_ISCHR(mntdevstat.st_mode) && mntdevstat.st_rdev == devstat.st_rdev) return (statfsp); } diff --git a/lib/libxo/tests/encoder/Makefile b/lib/libxo/tests/encoder/Makefile index 7522328b0818..02634b971ace 100644 --- a/lib/libxo/tests/encoder/Makefile +++ b/lib/libxo/tests/encoder/Makefile @@ -1,4 +1,5 @@ PACKAGE= tests +NO_DEV_PACKAGE= LIBXOSRC= ${SRCTOP}/contrib/libxo diff --git a/lib/liby/Makefile b/lib/liby/Makefile index 93f72ee440f8..ace8f8457d22 100644 --- a/lib/liby/Makefile +++ b/lib/liby/Makefile @@ -1,4 +1,4 @@ -PACKAGE=lib${LIB} +PACKAGE=toolchain LIB= y SRCS= main.c yyerror.c NO_PIC= diff --git a/lib/msun/src/e_fmodf.c b/lib/msun/src/e_fmodf.c index a7d1a0c22acd..ada969db44c7 100644 --- a/lib/msun/src/e_fmodf.c +++ b/lib/msun/src/e_fmodf.c @@ -27,7 +27,7 @@ static const float one = 1.0, Zero[] = {0.0, -0.0,}; float fmodf(float x, float y) { - int32_t n,hx,hy,hz,ix,iy,sx,i; + int32_t hx, hy, hz, ix, iy, n, sx; GET_FLOAT_WORD(hx,x); GET_FLOAT_WORD(hy,y); @@ -44,14 +44,16 @@ fmodf(float x, float y) return Zero[(u_int32_t)sx>>31]; /* |x|=|y| return x*0*/ /* determine ix = ilogb(x) */ - if(hx<0x00800000) { /* subnormal x */ - for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1; - } else ix = (hx>>23)-127; + if(hx<0x00800000) + ix = subnormal_ilogbf(hx); + else + ix = (hx>>23)-127; /* determine iy = ilogb(y) */ - if(hy<0x00800000) { /* subnormal y */ - for (iy = -126,i=(hy<<8); i>=0; i<<=1) iy -=1; - } else iy = (hy>>23)-127; + if(hy<0x00800000) + iy = subnormal_ilogbf(hy); + else + iy = (hy>>23)-127; /* set up {hx,lx}, {hy,ly} and align y to x */ if(ix >= -126) diff --git a/lib/msun/src/math_private.h b/lib/msun/src/math_private.h index 0711f2f33c41..fbd84e246ca7 100644 --- a/lib/msun/src/math_private.h +++ b/lib/msun/src/math_private.h @@ -740,7 +740,7 @@ irintl(long double x) } while (0) /* - * For a double entity split into high and low parts, compute ilogb. + * For a subnormal double entity split into high and low parts, compute ilogb. */ static inline int32_t subnormal_ilogb(int32_t hi, int32_t lo) @@ -760,6 +760,20 @@ subnormal_ilogb(int32_t hi, int32_t lo) return (j); } +/* + * For a subnormal float entity represented as an int32_t, compute ilogb. + */ +static inline int32_t +subnormal_ilogbf(int32_t hx) +{ + int32_t j; + uint32_t i; + i = (uint32_t) hx << 8; + for (j = -126; i < 0x7fffffff; i <<= 1) j -=1; + + return (j); +} + #ifdef DEBUG #if defined(__amd64__) || defined(__i386__) #define breakpoint() asm("int $3") diff --git a/lib/msun/src/s_cpow.c b/lib/msun/src/s_cpow.c index b887db51aa2a..2c20a8f3b48b 100644 --- a/lib/msun/src/s_cpow.c +++ b/lib/msun/src/s_cpow.c @@ -58,7 +58,10 @@ cpow(double complex a, double complex z) y = cimag (z); absa = cabs (a); if (absa == 0.0) { - return (CMPLX(0.0, 0.0)); + if (x == 0 && y == 0) + return (CMPLX(1., 0.)); + else + return (CMPLX(0., 0.)); } arga = carg (a); r = pow (absa, x); diff --git a/lib/msun/src/s_cpowf.c b/lib/msun/src/s_cpowf.c index 144291079f97..b8bdbd9cb07b 100644 --- a/lib/msun/src/s_cpowf.c +++ b/lib/msun/src/s_cpowf.c @@ -57,7 +57,10 @@ cpowf(float complex a, float complex z) y = cimagf(z); absa = cabsf (a); if (absa == 0.0f) { - return (CMPLXF(0.0f, 0.0f)); + if (x == 0 && y == 0) + return (CMPLXF(1.f, 0.f)); + else + return (CMPLXF(0.f, 0.f)); } arga = cargf (a); r = powf (absa, x); diff --git a/lib/msun/src/s_cpowl.c b/lib/msun/src/s_cpowl.c index 39797cadcfcb..efbe4936895f 100644 --- a/lib/msun/src/s_cpowl.c +++ b/lib/msun/src/s_cpowl.c @@ -57,7 +57,10 @@ cpowl(long double complex a, long double complex z) y = cimagl(z); absa = cabsl(a); if (absa == 0.0L) { - return (CMPLXL(0.0L, 0.0L)); + if (x == 0 && y == 0) + return (CMPLXL(1.L, 0.L)); + else + return (CMPLXL(0.L, 0.L)); } arga = cargl(a); r = powl(absa, x); diff --git a/lib/msun/src/s_ilogbf.c b/lib/msun/src/s_ilogbf.c index e0f8fee26ac8..5195e2331af3 100644 --- a/lib/msun/src/s_ilogbf.c +++ b/lib/msun/src/s_ilogbf.c @@ -18,7 +18,8 @@ #include "math.h" #include "math_private.h" - int ilogbf(float x) +int +ilogbf(float x) { int32_t hx,ix; @@ -28,7 +29,7 @@ if(hx==0) return FP_ILOGB0; else /* subnormal x */ - for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1; + ix = subnormal_ilogbf(hx); return ix; } else if (hx<0x7f800000) return (hx>>23)-127; diff --git a/lib/msun/src/s_remquof.c b/lib/msun/src/s_remquof.c index 9cd148586796..e4adb8321559 100644 --- a/lib/msun/src/s_remquof.c +++ b/lib/msun/src/s_remquof.c @@ -25,7 +25,7 @@ static const float Zero[] = {0.0, -0.0,}; float remquof(float x, float y, int *quo) { - int32_t n,hx,hy,hz,ix,iy,sx,i; + int32_t hx, hy, hz, ix, iy, n, sx; u_int32_t q,sxy; GET_FLOAT_WORD(hx,x); @@ -47,14 +47,16 @@ remquof(float x, float y, int *quo) } /* determine ix = ilogb(x) */ - if(hx<0x00800000) { /* subnormal x */ - for (ix = -126,i=(hx<<8); i>0; i<<=1) ix -=1; - } else ix = (hx>>23)-127; + if(hx<0x00800000) + ix = subnormal_ilogbf(hx); + else + ix = (hx>>23)-127; /* determine iy = ilogb(y) */ - if(hy<0x00800000) { /* subnormal y */ - for (iy = -126,i=(hy<<8); i>0; i<<=1) iy -=1; - } else iy = (hy>>23)-127; + if(hy<0x00800000) + iy = subnormal_ilogbf(hy); + else + iy = (hy>>23)-127; /* set up {hx,lx}, {hy,ly} and align y to x */ if(ix >= -126) diff --git a/lib/ncurses/Makefile.inc b/lib/ncurses/Makefile.inc index f2ed84e2e38f..eea49908474c 100644 --- a/lib/ncurses/Makefile.inc +++ b/lib/ncurses/Makefile.inc @@ -1,5 +1,6 @@ # This is to include src/lib/Makefile.inc +PACKAGE?= ncurses WARNS?= 3 .include "../Makefile.inc" diff --git a/lib/ncurses/form/Makefile b/lib/ncurses/form/Makefile index d4774a5f51a8..7d8963b05ae8 100644 --- a/lib/ncurses/form/Makefile +++ b/lib/ncurses/form/Makefile @@ -3,7 +3,6 @@ SRCDIR= ${NCURSES_DIR}/form -PACKAGE= clibs LIB= formw SHLIB_MAJOR= 6 diff --git a/lib/ncurses/ncurses/Makefile b/lib/ncurses/ncurses/Makefile index 512a452ad6d0..b60760281b39 100644 --- a/lib/ncurses/ncurses/Makefile +++ b/lib/ncurses/ncurses/Makefile @@ -1,4 +1,3 @@ -PACKAGE= clibs SHLIBDIR?= /lib .include <src.opts.mk> diff --git a/lib/ncurses/panel/Makefile b/lib/ncurses/panel/Makefile index a51129df42e3..dfb478aa5f5b 100644 --- a/lib/ncurses/panel/Makefile +++ b/lib/ncurses/panel/Makefile @@ -3,7 +3,6 @@ SRCDIR= ${NCURSES_DIR}/panel -PACKAGE= clibs LIB= panelw SHLIB_MAJOR= 6 diff --git a/lib/ncurses/tinfo/Makefile b/lib/ncurses/tinfo/Makefile index 476df54bb72a..8f01557edaee 100644 --- a/lib/ncurses/tinfo/Makefile +++ b/lib/ncurses/tinfo/Makefile @@ -1,4 +1,3 @@ -PACKAGE= clibs SHLIBDIR?= /lib .include <src.opts.mk> diff --git a/lib/nss_tacplus/Makefile b/lib/nss_tacplus/Makefile index f39788cfbdea..c85297a7dbaa 100644 --- a/lib/nss_tacplus/Makefile +++ b/lib/nss_tacplus/Makefile @@ -1,9 +1,9 @@ LIB= nss_tacplus -SRCS= ${LIB}.8 +SRCS= ${LIB}.c SHLIB_MAJOR= 1 SHLIB_NAME= ${LIB}.so.${SHLIB_MAJOR} LIBADD= tacplus -MK_INSTALLIB= no +MK_INSTALLLIB= no MAN= ${LIB}.8 .include <bsd.lib.mk> diff --git a/lib/virtual_oss/Makefile b/lib/virtual_oss/Makefile new file mode 100644 index 000000000000..dc83edd4b980 --- /dev/null +++ b/lib/virtual_oss/Makefile @@ -0,0 +1,9 @@ +.include <src.opts.mk> + +SHLIBDIR?= ${LIBDIR}/virtual_oss + +SUBDIR+= null \ + oss + +.include "Makefile.inc" +.include <bsd.subdir.mk> diff --git a/lib/virtual_oss/Makefile.inc b/lib/virtual_oss/Makefile.inc new file mode 100644 index 000000000000..45c8e0b1fdfc --- /dev/null +++ b/lib/virtual_oss/Makefile.inc @@ -0,0 +1,3 @@ +.include "../Makefile.inc" + +LDFLAGS+= -L${.OBJDIR:H:H}/libsamplerate diff --git a/lib/virtual_oss/bt/Makefile b/lib/virtual_oss/bt/Makefile new file mode 100644 index 000000000000..15413b7a1f1e --- /dev/null +++ b/lib/virtual_oss/bt/Makefile @@ -0,0 +1,19 @@ +SHLIB_NAME= voss_bt.so +SHLIBDIR= ${LIBDIR}/virtual_oss + +SRCS= bt.c \ + avdtp.c \ + sbc_encode.c + +CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \ + -I${SRCTOP}/contrib/libsamplerate +LDFLAGS+= -lbluetooth -lsdp +LIBADD= samplerate + +.if defined(HAVE_LIBAV) +CFLAGS+= -I${LOCALBASE:U/usr/local}/include -DHAVE_LIBAV +LDFLAGS+= -L${LOCALBASE:U/usr/local}/lib \ + -lavdevice -lavutil -lavcodec -lavformat +.endif + +.include <bsd.lib.mk> diff --git a/lib/virtual_oss/bt/avdtp.c b/lib/virtual_oss/bt/avdtp.c new file mode 100644 index 000000000000..82ed0fb942b6 --- /dev/null +++ b/lib/virtual_oss/bt/avdtp.c @@ -0,0 +1,720 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2015-2016 Nathanial Sloss <nathanialsloss@yahoo.com.au> + * Copyright (c) 2016-2019 Hans Petter Selasky <hps@selasky.org> + * Copyright (c) 2019 Google LLC, written by Richard Kralovic <riso@google.com> + * + * This software is dedicated to the memory of - + * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012. + * + * Barry was a man who loved his music. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/uio.h> + +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "avdtp_signal.h" +#include "bt.h" + +#define DPRINTF(...) printf("backend_bt: " __VA_ARGS__) + +struct avdtpGetPacketInfo { + uint8_t buffer_data[512]; + uint16_t buffer_len; + uint8_t trans; + uint8_t signalID; +}; + +static int avdtpAutoConfig(struct bt_config *); + +/* Return received message type if success, < 0 if failure. */ +static int +avdtpGetPacket(int fd, struct avdtpGetPacketInfo *info) +{ + uint8_t *pos = info->buffer_data; + uint8_t *end = info->buffer_data + sizeof(info->buffer_data); + uint8_t message_type; + int len; + + memset(info, 0, sizeof(*info)); + + /* Handle fragmented packets */ + for (int remaining = 1; remaining > 0; --remaining) { + len = read(fd, pos, end - pos); + + if (len < AVDTP_LEN_SUCCESS) + return (-1); + if (len == (int)(end - pos)) + return (-1); /* buffer too small */ + + uint8_t trans = (pos[0] & TRANSACTIONLABEL) >> TRANSACTIONLABEL_S; + uint8_t packet_type = (pos[0] & PACKETTYPE) >> PACKETTYPE_S; + uint8_t current_message_type = (info->buffer_data[0] & MESSAGETYPE); + uint8_t shift; + if (pos == info->buffer_data) { + info->trans = trans; + message_type = current_message_type; + if (packet_type == singlePacket) { + info->signalID = (pos[1] & SIGNALID_MASK); + shift = 2; + } else { + if (packet_type != startPacket) + return (-1); + remaining = pos[1]; + info->signalID = (pos[2] & SIGNALID_MASK); + shift = 3; + } + } else { + if (info->trans != trans || + message_type != current_message_type || + (remaining == 1 && packet_type != endPacket) || + (remaining > 1 && packet_type != continuePacket)) { + return (-1); + } + shift = 1; + } + memmove(pos, pos + shift, len); + pos += len; + } + info->buffer_len = pos - info->buffer_data; + return (message_type); +} + +/* Returns 0 on success, < 0 on failure. */ +static int +avdtpSendPacket(int fd, uint8_t command, uint8_t trans, uint8_t type, + uint8_t * data0, int datasize0, uint8_t * data1, + int datasize1) +{ + struct iovec iov[3]; + uint8_t header[2]; + int retval; + + /* fill out command header */ + header[0] = (trans << 4) | (type & 3); + if (command != 0) + header[1] = command & 0x3f; + else + header[1] = 3; + + iov[0].iov_base = header; + iov[0].iov_len = 2; + iov[1].iov_base = data0; + iov[1].iov_len = datasize0; + iov[2].iov_base = data1; + iov[2].iov_len = datasize1; + + retval = writev(fd, iov, 3); + if (retval != (2 + datasize0 + datasize1)) + return (-EINVAL); + else + return (0); +} + +/* Returns 0 on success, < 0 on failure. */ +static int +avdtpSendSyncCommand(int fd, struct avdtpGetPacketInfo *info, + uint8_t command, uint8_t type, uint8_t * data0, + int datasize0, uint8_t * data1, int datasize1) +{ + static uint8_t transLabel; + uint8_t trans; + int retval; + + alarm(8); /* set timeout */ + + trans = (transLabel++) & 0xF; + + retval = avdtpSendPacket(fd, command, trans, type, + data0, datasize0, data1, datasize1); + if (retval) + goto done; +retry: + switch (avdtpGetPacket(fd, info)) { + case RESPONSEACCEPT: + if (info->trans != trans) + goto retry; + retval = 0; + break; + case RESPONSEREJECT: + if (info->trans != trans) + goto retry; + retval = -EINVAL; + break; + case COMMAND: + retval = avdtpSendReject(fd, info->trans, info->signalID); + if (retval == 0) + goto retry; + break; + default: + retval = -ENXIO; + break; + } +done: + alarm(0); /* clear timeout */ + + return (retval); +} + +/* + * Variant for acceptor role: We support any frequency, blocks, bands, and + * allocation. Returns 0 on success, < 0 on failure. + */ +static int +avdtpSendCapabilitiesResponseSBCForACP(int fd, int trans) +{ + uint8_t data[10]; + + data[0] = mediaTransport; + data[1] = 0; + data[2] = mediaCodec; + data[3] = 0x6; + data[4] = mediaTypeAudio; + data[5] = SBC_CODEC_ID; + data[6] = + (1 << (3 - MODE_STEREO)) | + (1 << (3 - MODE_JOINT)) | + (1 << (3 - MODE_DUAL)) | + (1 << (3 - MODE_MONO)) | + (1 << (7 - FREQ_44_1K)) | + (1 << (7 - FREQ_48K)) | + (1 << (7 - FREQ_32K)) | + (1 << (7 - FREQ_16K)); + data[7] = + (1 << (7 - BLOCKS_4)) | + (1 << (7 - BLOCKS_8)) | + (1 << (7 - BLOCKS_12)) | + (1 << (7 - BLOCKS_16)) | + (1 << (3 - BANDS_4)) | + (1 << (3 - BANDS_8)) | (1 << ALLOC_LOUDNESS) | (1 << ALLOC_SNR); + data[8] = MIN_BITPOOL; + data[9] = DEFAULT_MAXBPOOL; + + return (avdtpSendPacket(fd, AVDTP_GET_CAPABILITIES, trans, + RESPONSEACCEPT, data, sizeof(data), NULL, 0)); +} + +/* Returns 0 on success, < 0 on failure. */ +int +avdtpSendAccept(int fd, uint8_t trans, uint8_t myCommand) +{ + return (avdtpSendPacket(fd, myCommand, trans, RESPONSEACCEPT, + NULL, 0, NULL, 0)); +} + +/* Returns 0 on success, < 0 on failure. */ +int +avdtpSendReject(int fd, uint8_t trans, uint8_t myCommand) +{ + uint8_t value = 0; + + return (avdtpSendPacket(fd, myCommand, trans, RESPONSEREJECT, + &value, 1, NULL, 0)); +} + +/* Returns 0 on success, < 0 on failure. */ +int +avdtpSendDiscResponseAudio(int fd, uint8_t trans, + uint8_t mySep, uint8_t is_sink) +{ + uint8_t data[2]; + + data[0] = mySep << 2; + data[1] = mediaTypeAudio << 4 | (is_sink ? (1 << 3) : 0); + + return (avdtpSendPacket(fd, AVDTP_DISCOVER, trans, RESPONSEACCEPT, + data, 2, NULL, 0)); +} + +/* Returns 0 on success, < 0 on failure. */ +int +avdtpDiscoverAndConfig(struct bt_config *cfg, bool isSink) +{ + struct avdtpGetPacketInfo info; + uint16_t offset; + uint8_t chmode = cfg->chmode; + uint8_t aacMode1 = cfg->aacMode1; + uint8_t aacMode2 = cfg->aacMode2; + int retval; + + retval = avdtpSendSyncCommand(cfg->hc, &info, AVDTP_DISCOVER, 0, + NULL, 0, NULL, 0); + if (retval) + return (retval); + + retval = -EBUSY; + for (offset = 0; offset + 2 <= info.buffer_len; offset += 2) { + cfg->sep = info.buffer_data[offset] >> 2; + cfg->media_Type = info.buffer_data[offset + 1] >> 4; + cfg->chmode = chmode; + cfg->aacMode1 = aacMode1; + cfg->aacMode2 = aacMode2; + if (info.buffer_data[offset] & DISCOVER_SEP_IN_USE) + continue; + if (info.buffer_data[offset + 1] & DISCOVER_IS_SINK) { + if (!isSink) + continue; + } else { + if (isSink) + continue; + } + /* try to configure SBC */ + retval = avdtpAutoConfig(cfg); + if (retval == 0) + return (0); + } + return (retval); +} + +/* Returns 0 on success, < 0 on failure. */ +static int +avdtpGetCapabilities(int fd, uint8_t sep, struct avdtpGetPacketInfo *info) +{ + uint8_t address = (sep << 2); + + return (avdtpSendSyncCommand(fd, info, + AVDTP_GET_CAPABILITIES, 0, &address, 1, + NULL, 0)); +} + +/* Returns 0 on success, < 0 on failure. */ +int +avdtpSetConfiguration(int fd, uint8_t sep, uint8_t * data, int datasize) +{ + struct avdtpGetPacketInfo info; + uint8_t configAddresses[2]; + + configAddresses[0] = sep << 2; + configAddresses[1] = INTSEP << 2; + + return (avdtpSendSyncCommand(fd, &info, AVDTP_SET_CONFIGURATION, 0, + configAddresses, 2, data, datasize)); +} + +/* Returns 0 on success, < 0 on failure. */ +int +avdtpOpen(int fd, uint8_t sep) +{ + struct avdtpGetPacketInfo info; + uint8_t address = sep << 2; + + return (avdtpSendSyncCommand(fd, &info, AVDTP_OPEN, 0, + &address, 1, NULL, 0)); +} + +/* Returns 0 on success, < 0 on failure. */ +int +avdtpStart(int fd, uint8_t sep) +{ + struct avdtpGetPacketInfo info; + uint8_t address = sep << 2; + + return (avdtpSendSyncCommand(fd, &info, AVDTP_START, 0, + &address, 1, NULL, 0)); +} + +/* Returns 0 on success, < 0 on failure. */ +int +avdtpClose(int fd, uint8_t sep) +{ + struct avdtpGetPacketInfo info; + uint8_t address = sep << 2; + + return (avdtpSendSyncCommand(fd, &info, AVDTP_CLOSE, 0, + &address, 1, NULL, 0)); +} + +/* Returns 0 on success, < 0 on failure. */ +int +avdtpSuspend(int fd, uint8_t sep) +{ + struct avdtpGetPacketInfo info; + uint8_t address = sep << 2; + + return (avdtpSendSyncCommand(fd, &info, AVDTP_SUSPEND, 0, + &address, 1, NULL, 0)); +} + +/* Returns 0 on success, < 0 on failure. */ +int +avdtpAbort(int fd, uint8_t sep) +{ + struct avdtpGetPacketInfo info; + uint8_t address = sep << 2; + + return (avdtpSendSyncCommand(fd, &info, AVDTP_ABORT, 0, + &address, 1, NULL, 0)); +} + +static int +avdtpAutoConfig(struct bt_config *cfg) +{ + struct avdtpGetPacketInfo info; + uint8_t freqmode; + uint8_t blk_len_sb_alloc; + uint8_t availFreqMode = 0; + uint8_t availConfig = 0; + uint8_t supBitpoolMin = 0; + uint8_t supBitpoolMax = 0; + uint8_t aacMode1 = 0; + uint8_t aacMode2 = 0; +#ifdef HAVE_LIBAV + uint8_t aacBitrate3 = 0; + uint8_t aacBitrate4 = 0; + uint8_t aacBitrate5 = 0; +#endif + int retval; + int i; + + retval = avdtpGetCapabilities(cfg->hc, cfg->sep, &info); + if (retval) { + DPRINTF("Cannot get capabilities\n"); + return (retval); + } +retry: + for (i = 0; (i + 1) < info.buffer_len;) { +#if 0 + DPRINTF("0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + info.buffer_data[i + 0], + info.buffer_data[i + 1], + info.buffer_data[i + 2], + info.buffer_data[i + 3], + info.buffer_data[i + 4], info.buffer_data[i + 5]); +#endif + if (i + 2 + info.buffer_data[i + 1] > info.buffer_len) + break; + switch (info.buffer_data[i]) { + case mediaTransport: + break; + case mediaCodec: + if (info.buffer_data[i + 1] < 2) + break; + /* check codec */ + switch (info.buffer_data[i + 3]) { + case 0: /* SBC */ + if (info.buffer_data[i + 1] < 6) + break; + availFreqMode = info.buffer_data[i + 4]; + availConfig = info.buffer_data[i + 5]; + supBitpoolMin = info.buffer_data[i + 6]; + supBitpoolMax = info.buffer_data[i + 7]; + break; + case 2: /* MPEG2/4 AAC */ + if (info.buffer_data[i + 1] < 8) + break; + aacMode1 = info.buffer_data[i + 5]; + aacMode2 = info.buffer_data[i + 6]; +#ifdef HAVE_LIBAV + aacBitrate3 = info.buffer_data[i + 7]; + aacBitrate4 = info.buffer_data[i + 8]; + aacBitrate5 = info.buffer_data[i + 9]; +#endif + break; + default: + break; + } + } + /* jump to next information element */ + i += 2 + info.buffer_data[i + 1]; + } + aacMode1 &= cfg->aacMode1; + aacMode2 &= cfg->aacMode2; + + /* Try AAC first */ + if (aacMode1 == cfg->aacMode1 && aacMode2 == cfg->aacMode2) { +#ifdef HAVE_LIBAV + uint8_t config[12] = { mediaTransport, 0x0, mediaCodec, + 0x8, 0x0, 0x02, 0x80, aacMode1, aacMode2, aacBitrate3, + aacBitrate4, aacBitrate5 + }; + + if (avdtpSetConfiguration + (cfg->hc, cfg->sep, config, sizeof(config)) == 0) { + cfg->codec = CODEC_AAC; + return (0); + } +#endif + } + /* Try SBC second */ + if (cfg->freq == FREQ_UNDEFINED) + goto auto_config_failed; + + freqmode = (1 << (3 - cfg->freq + 4)) | (1 << (3 - cfg->chmode)); + + if ((availFreqMode & freqmode) != freqmode) { + DPRINTF("No frequency and mode match\n"); + goto auto_config_failed; + } + for (i = 0; i != 4; i++) { + blk_len_sb_alloc = (1 << (i + 4)) | + (1 << (1 - cfg->bands + 2)) | (1 << cfg->allocm); + + if ((availConfig & blk_len_sb_alloc) == blk_len_sb_alloc) + break; + } + if (i == 4) { + DPRINTF("No bands available\n"); + goto auto_config_failed; + } + cfg->blocks = (3 - i); + + if (cfg->allocm == ALLOC_SNR) + supBitpoolMax &= ~1; + + if (cfg->chmode == MODE_DUAL || cfg->chmode == MODE_MONO) + supBitpoolMax /= 2; + + if (cfg->bands == BANDS_4) + supBitpoolMax /= 2; + + if (supBitpoolMax > cfg->bitpool) + supBitpoolMax = cfg->bitpool; + else + cfg->bitpool = supBitpoolMax; + + do { + uint8_t config[10] = { mediaTransport, 0x0, mediaCodec, 0x6, + 0x0, 0x0, freqmode, blk_len_sb_alloc, supBitpoolMin, + supBitpoolMax + }; + + if (avdtpSetConfiguration + (cfg->hc, cfg->sep, config, sizeof(config)) == 0) { + cfg->codec = CODEC_SBC; + return (0); + } + } while (0); + +auto_config_failed: + if (cfg->chmode == MODE_STEREO) { + cfg->chmode = MODE_MONO; + cfg->aacMode2 ^= 0x0C; + goto retry; + } + return (-EINVAL); +} + +void +avdtpACPFree(struct bt_config *cfg) +{ + if (cfg->handle.sbc_enc) { + free(cfg->handle.sbc_enc); + cfg->handle.sbc_enc = NULL; + } +} + +/* Returns 0 on success, < 0 on failure. */ +static int +avdtpParseSBCConfig(uint8_t * data, struct bt_config *cfg) +{ + if (data[0] & (1 << (7 - FREQ_48K))) { + cfg->freq = FREQ_48K; + } else if (data[0] & (1 << (7 - FREQ_44_1K))) { + cfg->freq = FREQ_44_1K; + } else if (data[0] & (1 << (7 - FREQ_32K))) { + cfg->freq = FREQ_32K; + } else if (data[0] & (1 << (7 - FREQ_16K))) { + cfg->freq = FREQ_16K; + } else { + return -EINVAL; + } + + if (data[0] & (1 << (3 - MODE_STEREO))) { + cfg->chmode = MODE_STEREO; + } else if (data[0] & (1 << (3 - MODE_JOINT))) { + cfg->chmode = MODE_JOINT; + } else if (data[0] & (1 << (3 - MODE_DUAL))) { + cfg->chmode = MODE_DUAL; + } else if (data[0] & (1 << (3 - MODE_MONO))) { + cfg->chmode = MODE_MONO; + } else { + return -EINVAL; + } + + if (data[1] & (1 << (7 - BLOCKS_16))) { + cfg->blocks = BLOCKS_16; + } else if (data[1] & (1 << (7 - BLOCKS_12))) { + cfg->blocks = BLOCKS_12; + } else if (data[1] & (1 << (7 - BLOCKS_8))) { + cfg->blocks = BLOCKS_8; + } else if (data[1] & (1 << (7 - BLOCKS_4))) { + cfg->blocks = BLOCKS_4; + } else { + return -EINVAL; + } + + if (data[1] & (1 << (3 - BANDS_8))) { + cfg->bands = BANDS_8; + } else if (data[1] & (1 << (3 - BANDS_4))) { + cfg->bands = BANDS_4; + } else { + return -EINVAL; + } + + if (data[1] & (1 << ALLOC_LOUDNESS)) { + cfg->allocm = ALLOC_LOUDNESS; + } else if (data[1] & (1 << ALLOC_SNR)) { + cfg->allocm = ALLOC_SNR; + } else { + return -EINVAL; + } + cfg->bitpool = data[3]; + return 0; +} + +int +avdtpACPHandlePacket(struct bt_config *cfg) +{ + struct avdtpGetPacketInfo info; + int retval; + + if (avdtpGetPacket(cfg->hc, &info) != COMMAND) + return (-ENXIO); + + switch (info.signalID) { + case AVDTP_DISCOVER: + retval = + avdtpSendDiscResponseAudio(cfg->hc, info.trans, ACPSEP, 1); + if (!retval) + retval = AVDTP_DISCOVER; + break; + case AVDTP_GET_CAPABILITIES: + retval = + avdtpSendCapabilitiesResponseSBCForACP(cfg->hc, info.trans); + if (!retval) + retval = AVDTP_GET_CAPABILITIES; + break; + case AVDTP_SET_CONFIGURATION: + if (cfg->acceptor_state != acpInitial) + goto err; + cfg->sep = info.buffer_data[1] >> 2; + int is_configured = 0; + for (int i = 2; (i + 1) < info.buffer_len;) { + if (i + 2 + info.buffer_data[i + 1] > info.buffer_len) + break; + switch (info.buffer_data[i]) { + case mediaTransport: + break; + case mediaCodec: + if (info.buffer_data[i + 1] < 2) + break; + /* check codec */ + switch (info.buffer_data[i + 3]) { + case 0: /* SBC */ + if (info.buffer_data[i + 1] < 6) + break; + retval = + avdtpParseSBCConfig(info.buffer_data + i + 4, cfg); + if (retval) + return retval; + is_configured = 1; + break; + case 2: /* MPEG2/4 AAC */ + /* TODO: Add support */ + default: + break; + } + } + /* jump to next information element */ + i += 2 + info.buffer_data[i + 1]; + } + if (!is_configured) + goto err; + + retval = + avdtpSendAccept(cfg->hc, info.trans, AVDTP_SET_CONFIGURATION); + if (retval) + return (retval); + + /* TODO: Handle other codecs */ + if (cfg->handle.sbc_enc == NULL) { + cfg->handle.sbc_enc = malloc(sizeof(*cfg->handle.sbc_enc)); + if (cfg->handle.sbc_enc == NULL) + return (-ENOMEM); + } + memset(cfg->handle.sbc_enc, 0, sizeof(*cfg->handle.sbc_enc)); + + retval = AVDTP_SET_CONFIGURATION; + cfg->acceptor_state = acpConfigurationSet; + break; + case AVDTP_OPEN: + if (cfg->acceptor_state != acpConfigurationSet) + goto err; + retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID); + if (retval) + return (retval); + retval = info.signalID; + cfg->acceptor_state = acpStreamOpened; + break; + case AVDTP_START: + if (cfg->acceptor_state != acpStreamOpened && + cfg->acceptor_state != acpStreamSuspended) { + goto err; + } + retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID); + if (retval) + return retval; + retval = info.signalID; + cfg->acceptor_state = acpStreamStarted; + break; + case AVDTP_CLOSE: + if (cfg->acceptor_state != acpStreamOpened && + cfg->acceptor_state != acpStreamStarted && + cfg->acceptor_state != acpStreamSuspended) { + goto err; + } + retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID); + if (retval) + return (retval); + retval = info.signalID; + cfg->acceptor_state = acpStreamClosed; + break; + case AVDTP_SUSPEND: + if (cfg->acceptor_state != acpStreamOpened && + cfg->acceptor_state != acpStreamStarted) { + goto err; + } + retval = avdtpSendAccept(cfg->hc, info.trans, info.signalID); + if (retval) + return (retval); + retval = info.signalID; + cfg->acceptor_state = acpStreamSuspended; + break; + case AVDTP_GET_CONFIGURATION: + case AVDTP_RECONFIGURE: + case AVDTP_ABORT: + /* TODO: Implement this. */ + default: +err: + avdtpSendReject(cfg->hc, info.trans, info.signalID); + return (-ENXIO); + } + return (retval); +} diff --git a/lib/virtual_oss/bt/avdtp_signal.h b/lib/virtual_oss/bt/avdtp_signal.h new file mode 100644 index 000000000000..a46cc6dd9dcf --- /dev/null +++ b/lib/virtual_oss/bt/avdtp_signal.h @@ -0,0 +1,139 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au> + * + * This software is dedicated to the memory of - + * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012. + * + * Barry was a man who loved his music. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _AVDTP_SIGNAL_H_ +#define _AVDTP_SIGNAL_H_ + +#include <stdint.h> +#include <stdbool.h> + +/* Our endpoint. */ +#define INTSEP 8 +#define ACPSEP 8 + +/* AVDTP signals. */ + +#define AVDTP_DISCOVER 0x01 +#define AVDTP_GET_CAPABILITIES 0x02 +#define AVDTP_SET_CONFIGURATION 0x03 +#define AVDTP_GET_CONFIGURATION 0x04 +#define AVDTP_RECONFIGURE 0x05 +#define AVDTP_OPEN 0x06 +#define AVDTP_START 0x07 +#define AVDTP_CLOSE 0x08 +#define AVDTP_SUSPEND 0x09 +#define AVDTP_ABORT 0x0a +#define AVDTP_SECUURITY_CONTROL 0x0b + +/* Signal Command & Response Header Masks. */ + +#define TRANSACTIONLABEL 0xf0 +#define TRANSACTIONLABEL_S 4 +#define SIGNALID_MASK 0x3f +#define PACKETTYPE 0x0c +#define PACKETTYPE_S 0x02 +#define MESSAGETYPE 0x03 +#define SIGNALIDENTIFIER 0x3f +#define DISCOVER_SEP_IN_USE 0x02 +#define DISCOVER_IS_SINK 0x08 + +/* Packet Types */ +#define singlePacket 0x0 +#define startPacket 0x1 +#define continuePacket 0x2 +#define endPacket 0x3 + +/* Message Types */ +#define COMMAND 0x0 +#define RESPONSEACCEPT 0x2 +#define RESPONSEREJECT 0x3 + +/* Response general error/success lengths */ +#define AVDTP_LEN_SUCCESS 2 +#define AVDTP_LEN_ERROR 3 + +/* Error codes */ +#define BAD_HEADER_FORMAT 0x01 +#define BAD_LENGTH 0x11 +#define BAD_ACP_SEID 0x12 +#define SEP_IN_USE 0x13 +#define SEP_NOT_IN_USE 0x14 +#define BAD_SERV_CATAGORY 0x17 +#define BAD_PAYLOAD_FORMAT 0x18 +#define NOT_SUPPORTED_COMMAND 0x19 +#define INVALID_CAPABILITIES 0x1a + +#define BAD_RECOVERY_TYPE 0x22 +#define BAD_MEDIA_TRANSPORT_FORMAT 0x23 +#define BAD_RECOVERY_FORMAT 0x25 +#define BAD_ROHC_FORMAT 0x26 +#define BAD_CP_FORMAT 0x27 +#define BAD_MULTIPLEXING_FORMAT 0x28 +#define UNSUPPORTED_CONFIGURATION 0x29 +#define BAD_STATE 0x31 + +/* Service Capabilities Field. */ +#define mediaTransport 0x1 +#define reporting 0x2 +#define recovery 0x3 +#define contentProtection 0x4 +#define headerCompression 0x5 +#define multiplexing 0x6 +#define mediaCodec 0x7 + +/* Media Codec Capabilities */ +#define mediaCodecSbc 0x00 +#define mediaCodecMpeg1 0x01 +#define mediaCodecMpeg2 0x02 + +#define SBC_CODEC_ID 0x0 +#define mediaTypeAudio 0x0 + +struct bt_config; + +int avdtpSendAccept(int, uint8_t, uint8_t); +int avdtpSendReject(int, uint8_t, uint8_t); +int avdtpSendDiscResponseAudio(int, uint8_t, uint8_t, uint8_t); +int avdtpDiscoverAndConfig(struct bt_config *, bool); +int avdtpSetConfiguration(int, uint8_t, uint8_t *, int); +int avdtpOpen(int, uint8_t); +int avdtpStart(int, uint8_t); +int avdtpClose(int, uint8_t); +int avdtpSuspend(int, uint8_t); +int avdtpAbort(int, uint8_t); + +/* Return < 0 if error, processed signal otherwise. */ +int avdtpACPHandlePacket(struct bt_config *cfg); +/* Free state allocated in avdtpACPHandlePacket(), if any. */ +void avdtpACPFree(struct bt_config *cfg); + +#endif /* _AVDTP_SIGNAL_H_ */ diff --git a/lib/virtual_oss/bt/bt.c b/lib/virtual_oss/bt/bt.c new file mode 100644 index 000000000000..57f000b067d5 --- /dev/null +++ b/lib/virtual_oss/bt/bt.c @@ -0,0 +1,1061 @@ +/*- + * Copyright (c) 2015-2019 Hans Petter Selasky + * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au> + * Copyright (c) 2006 Itronix Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/queue.h> +#include <sys/filio.h> +#include <sys/soundcard.h> + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <err.h> +#define L2CAP_SOCKET_CHECKED +#include <bluetooth.h> +#include <sdp.h> + +#include "backend.h" +#include "int.h" + +#include "avdtp_signal.h" +#include "bt.h" + +#define DPRINTF(...) printf("backend_bt: " __VA_ARGS__) + +struct l2cap_info { + bdaddr_t laddr; + bdaddr_t raddr; +}; + +static struct bt_config bt_play_cfg; +static struct bt_config bt_rec_cfg; + +int +bt_receive(struct bt_config *cfg, void *ptr, int len, int use_delay) +{ + struct sbc_header *phdr = (struct sbc_header *)cfg->mtu_data; + struct sbc_encode *sbc = cfg->handle.sbc_enc; + uint8_t *tmp = ptr; + int old_len = len; + int delta; + int err; + + /* wait for service interval, if any */ + if (use_delay) + virtual_oss_wait(); + + switch (cfg->blocks) { + case BLOCKS_4: + sbc->blocks = 4; + break; + case BLOCKS_8: + sbc->blocks = 8; + break; + case BLOCKS_12: + sbc->blocks = 12; + break; + default: + sbc->blocks = 16; + break; + } + + switch (cfg->bands) { + case BANDS_4: + sbc->bands = 4; + break; + default: + sbc->bands = 8; + break; + } + + if (cfg->chmode != MODE_MONO) { + sbc->channels = 2; + } else { + sbc->channels = 1; + } + + while (1) { + delta = len & ~1; + if (delta > (int)(2 * sbc->rem_len)) + delta = (2 * sbc->rem_len); + + /* copy out samples, if any */ + memcpy(tmp, (char *)sbc->music_data + sbc->rem_off, delta); + tmp += delta; + len -= delta; + sbc->rem_off += delta / 2; + sbc->rem_len -= delta / 2; + if (len == 0) + break; + + if (sbc->rem_len == 0 && + sbc->rem_data_frames != 0) { + err = sbc_decode_frame(cfg, sbc->rem_data_len * 8); + sbc->rem_data_frames--; + sbc->rem_data_ptr += err; + sbc->rem_data_len -= err; + continue; + } + /* TODO: Support fragmented SBC frames */ + err = read(cfg->fd, cfg->mtu_data, cfg->mtu); + + if (err == 0) { + break; + } else if (err < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + break; + else + return (-1); /* disconnected */ + } + + /* verify RTP header */ + if (err < (int)sizeof(*phdr) || phdr->id != 0x80) + continue; + + sbc->rem_data_frames = phdr->numFrames; + sbc->rem_data_ptr = (uint8_t *)(phdr + 1); + sbc->rem_data_len = err - sizeof(*phdr); + } + return (old_len - len); +} + +static int +bt_set_format(int *format) +{ + int value; + + value = *format & AFMT_S16_NE; + if (value != 0) { + *format = value; + return (0); + } + return (-1); +} + +static void +bt_close(struct voss_backend *pbe) +{ + struct bt_config *cfg = pbe->arg; + + if (cfg->hc > 0) { + avdtpAbort(cfg->hc, cfg->sep); + avdtpClose(cfg->hc, cfg->sep); + close(cfg->hc); + cfg->hc = -1; + } + if (cfg->fd > 0) { + close(cfg->fd); + cfg->fd = -1; + } +} + +static void +bt_play_close(struct voss_backend *pbe) +{ + struct bt_config *cfg = pbe->arg; + + switch (cfg->codec) { + case CODEC_SBC: + if (cfg->handle.sbc_enc == NULL) + break; + free(cfg->handle.sbc_enc); + cfg->handle.sbc_enc = NULL; + break; +#ifdef HAVE_LIBAV + case CODEC_AAC: + if (cfg->handle.av.context == NULL) + break; + av_free(cfg->rem_in_data); + av_frame_free(&cfg->handle.av.frame); + avcodec_close(cfg->handle.av.context); + avformat_free_context(cfg->handle.av.format); + cfg->handle.av.context = NULL; + break; +#endif + default: + break; + } + return (bt_close(pbe)); +} + +static void +bt_rec_close(struct voss_backend *pbe) +{ + struct bt_config *cfg = pbe->arg; + + switch (cfg->codec) { + case CODEC_SBC: + break; +#ifdef HAVE_LIBAV + case CODEC_AAC: + break; +#endif + + default: + break; + } + return (bt_close(pbe)); +} + +static const uint32_t bt_attrs[] = { + SDP_ATTR_RANGE(SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, + SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), +}; + +#define BT_NUM_VALUES 32 +#define BT_BUF_SIZE 32 + +static int +bt_find_psm(const uint8_t *start, const uint8_t *end) +{ + uint32_t type; + uint32_t len; + int protover = 0; + int psm = -1; + + if ((end - start) < 2) + return (-1); + + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + return (-1); + } + + while (start < end) { + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + return (-1); + } + /* check range */ + if (len > (uint32_t)(end - start)) + break; + + if (len >= 6) { + const uint8_t *ptr = start; + + SDP_GET8(type, ptr); + if (type == SDP_DATA_UUID16) { + uint16_t temp; + + SDP_GET16(temp, ptr); + switch (temp) { + case SDP_UUID_PROTOCOL_L2CAP: + SDP_GET8(type, ptr); + SDP_GET16(psm, ptr); + break; + case SDP_UUID_PROTOCOL_AVDTP: + SDP_GET8(type, ptr); + SDP_GET16(protover, ptr); + break; + default: + break; + } + } + } + start += len; + + if (protover >= 0x0100 && psm > -1) + return (htole16(psm)); + } + return (-1); +} + +static int +bt_query(struct l2cap_info *info, uint16_t service_class) +{ + sdp_attr_t values[BT_NUM_VALUES]; + uint8_t buffer[BT_NUM_VALUES][BT_BUF_SIZE]; + void *ss; + int psm = -1; + int n; + + memset(buffer, 0, sizeof(buffer)); + memset(values, 0, sizeof(values)); + + ss = sdp_open(&info->laddr, &info->raddr); + if (ss == NULL || sdp_error(ss) != 0) { + DPRINTF("Could not open SDP\n"); + sdp_close(ss); + return (psm); + } + /* Initialize attribute values array */ + for (n = 0; n != BT_NUM_VALUES; n++) { + values[n].flags = SDP_ATTR_INVALID; + values[n].vlen = BT_BUF_SIZE; + values[n].value = buffer[n]; + } + + /* Do SDP Service Search Attribute Request */ + n = sdp_search(ss, 1, &service_class, 1, bt_attrs, BT_NUM_VALUES, values); + if (n != 0) { + DPRINTF("SDP search failed\n"); + goto done; + } + /* Print attributes values */ + for (n = 0; n != BT_NUM_VALUES; n++) { + if (values[n].flags != SDP_ATTR_OK) + break; + if (values[n].attr != SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST) + continue; + psm = bt_find_psm(values[n].value, values[n].value + values[n].vlen); + if (psm > -1) + break; + } +done: + sdp_close(ss); + return (psm); +} + +static int +bt_open(struct voss_backend *pbe __unused, const char *devname, int samplerate, + int bufsize __unused, int *pchannels, int *pformat, struct bt_config *cfg, + int service_class, int isSink) +{ + struct sockaddr_l2cap addr; + struct l2cap_info info; + socklen_t mtusize = sizeof(uint16_t); + int tmpbitpool; + int l2cap_psm; + int temp; + + memset(&info, 0, sizeof(info)); + + if (strstr(devname, "/dev/bluetooth/") != devname) { + printf("Invalid device name '%s'", devname); + goto error; + } + /* skip prefix */ + devname += sizeof("/dev/bluetooth/") - 1; + + if (!bt_aton(devname, &info.raddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(devname)) == NULL) { + DPRINTF("Could not get host by name\n"); + goto error; + } + bdaddr_copy(&info.raddr, (bdaddr_t *)he->h_addr); + } + switch (samplerate) { + case 8000: + cfg->freq = FREQ_UNDEFINED; + cfg->aacMode1 = 0x80; + cfg->aacMode2 = 0x0C; + break; + case 11025: + cfg->freq = FREQ_UNDEFINED; + cfg->aacMode1 = 0x40; + cfg->aacMode2 = 0x0C; + break; + case 12000: + cfg->freq = FREQ_UNDEFINED; + cfg->aacMode1 = 0x20; + cfg->aacMode2 = 0x0C; + break; + case 16000: + cfg->freq = FREQ_16K; + cfg->aacMode1 = 0x10; + cfg->aacMode2 = 0x0C; + break; + case 22050: + cfg->freq = FREQ_UNDEFINED; + cfg->aacMode1 = 0x08; + cfg->aacMode2 = 0x0C; + break; + case 24000: + cfg->freq = FREQ_UNDEFINED; + cfg->aacMode1 = 0x04; + cfg->aacMode2 = 0x0C; + break; + case 32000: + cfg->freq = FREQ_32K; + cfg->aacMode1 = 0x02; + cfg->aacMode2 = 0x0C; + break; + case 44100: + cfg->freq = FREQ_44_1K; + cfg->aacMode1 = 0x01; + cfg->aacMode2 = 0x0C; + break; + case 48000: + cfg->freq = FREQ_48K; + cfg->aacMode1 = 0; + cfg->aacMode2 = 0x8C; + break; + case 64000: + cfg->freq = FREQ_UNDEFINED; + cfg->aacMode1 = 0; + cfg->aacMode2 = 0x4C; + break; + case 88200: + cfg->freq = FREQ_UNDEFINED; + cfg->aacMode1 = 0; + cfg->aacMode2 = 0x2C; + break; + case 96000: + cfg->freq = FREQ_UNDEFINED; + cfg->aacMode1 = 0; + cfg->aacMode2 = 0x1C; + break; + default: + DPRINTF("Invalid samplerate %d", samplerate); + goto error; + } + cfg->bands = BANDS_8; + cfg->bitpool = 0; + + switch (*pchannels) { + case 1: + cfg->aacMode2 &= 0xF8; + cfg->chmode = MODE_MONO; + break; + default: + cfg->aacMode2 &= 0xF4; + cfg->chmode = MODE_STEREO; + break; + } + + cfg->allocm = ALLOC_LOUDNESS; + + if (cfg->chmode == MODE_MONO || cfg->chmode == MODE_DUAL) + tmpbitpool = 16; + else + tmpbitpool = 32; + + if (cfg->bands == BANDS_8) + tmpbitpool *= 8; + else + tmpbitpool *= 4; + + if (tmpbitpool > DEFAULT_MAXBPOOL) + tmpbitpool = DEFAULT_MAXBPOOL; + + cfg->bitpool = tmpbitpool; + + if (bt_set_format(pformat)) { + DPRINTF("Unsupported sample format\n"); + goto error; + } + l2cap_psm = bt_query(&info, service_class); + DPRINTF("PSM=0x%02x\n", l2cap_psm); + if (l2cap_psm < 0) { + DPRINTF("PSM not found\n"); + goto error; + } + cfg->hc = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); + if (cfg->hc < 0) { + DPRINTF("Could not create BT socket\n"); + goto error; + } + memset(&addr, 0, sizeof(addr)); + addr.l2cap_len = sizeof(addr); + addr.l2cap_family = AF_BLUETOOTH; + bdaddr_copy(&addr.l2cap_bdaddr, &info.laddr); + + if (bind(cfg->hc, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + DPRINTF("Could not bind to HC\n"); + goto error; + } + bdaddr_copy(&addr.l2cap_bdaddr, &info.raddr); + addr.l2cap_psm = l2cap_psm; + if (connect(cfg->hc, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + DPRINTF("Could not connect to HC: %d\n", errno); + goto error; + } + if (avdtpDiscoverAndConfig(cfg, isSink)) { + DPRINTF("DISCOVER FAILED\n"); + goto error; + } + if (avdtpOpen(cfg->hc, cfg->sep)) { + DPRINTF("OPEN FAILED\n"); + goto error; + } + cfg->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); + if (cfg->fd < 0) { + DPRINTF("Could not create BT socket\n"); + goto error; + } + memset(&addr, 0, sizeof(addr)); + + addr.l2cap_len = sizeof(addr); + addr.l2cap_family = AF_BLUETOOTH; + bdaddr_copy(&addr.l2cap_bdaddr, &info.laddr); + + if (bind(cfg->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + DPRINTF("Could not bind\n"); + goto error; + } + bdaddr_copy(&addr.l2cap_bdaddr, &info.raddr); + addr.l2cap_psm = l2cap_psm; + if (connect(cfg->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + DPRINTF("Could not connect: %d\n", errno); + goto error; + } + if (isSink) { + if (getsockopt(cfg->fd, SOL_L2CAP, SO_L2CAP_OMTU, &cfg->mtu, &mtusize) == -1) { + DPRINTF("Could not get MTU\n"); + goto error; + } + temp = cfg->mtu * 16; + if (setsockopt(cfg->fd, SOL_SOCKET, SO_SNDBUF, &temp, sizeof(temp)) == -1) { + DPRINTF("Could not set send buffer size\n"); + goto error; + } + temp = cfg->mtu; + if (setsockopt(cfg->fd, SOL_SOCKET, SO_SNDLOWAT, &temp, sizeof(temp)) == -1) { + DPRINTF("Could not set low water mark\n"); + goto error; + } + } else { + if (getsockopt(cfg->fd, SOL_L2CAP, SO_L2CAP_IMTU, &cfg->mtu, &mtusize) == -1) { + DPRINTF("Could not get MTU\n"); + goto error; + } + temp = cfg->mtu * 16; + if (setsockopt(cfg->fd, SOL_SOCKET, SO_RCVBUF, &temp, sizeof(temp)) == -1) { + DPRINTF("Could not set receive buffer size\n"); + goto error; + } + temp = 1; + if (setsockopt(cfg->fd, SOL_SOCKET, SO_RCVLOWAT, &temp, sizeof(temp)) == -1) { + DPRINTF("Could not set low water mark\n"); + goto error; + } + temp = 1; + if (ioctl(cfg->fd, FIONBIO, &temp) == -1) { + DPRINTF("Could not set non-blocking I/O for receive direction\n"); + goto error; + } + } + + if (avdtpStart(cfg->hc, cfg->sep)) { + DPRINTF("START FAILED\n"); + goto error; + } + switch (cfg->chmode) { + case MODE_MONO: + *pchannels = 1; + break; + default: + *pchannels = 2; + break; + } + return (0); + +error: + if (cfg->hc > 0) { + close(cfg->hc); + cfg->hc = -1; + } + if (cfg->fd > 0) { + close(cfg->fd); + cfg->fd = -1; + } + return (-1); +} + +static void +bt_init_cfg(struct bt_config *cfg) +{ + memset(cfg, 0, sizeof(*cfg)); +} + +static int +bt_rec_open(struct voss_backend *pbe, const char *devname, int samplerate, + int bufsize, int *pchannels, int *pformat) +{ + struct bt_config *cfg = pbe->arg; + int retval; + + bt_init_cfg(cfg); + + retval = bt_open(pbe, devname, samplerate, bufsize, pchannels, pformat, + cfg, SDP_SERVICE_CLASS_AUDIO_SOURCE, 0); + if (retval != 0) + return (retval); + return (0); +} + +static int +bt_play_open(struct voss_backend *pbe, const char *devname, int samplerate, + int bufsize, int *pchannels, int *pformat) +{ + struct bt_config *cfg = pbe->arg; + int retval; + + bt_init_cfg(cfg); + + retval = bt_open(pbe, devname, samplerate, bufsize, pchannels, pformat, + cfg, SDP_SERVICE_CLASS_AUDIO_SINK, 1); + if (retval != 0) + return (retval); + + /* setup codec */ + switch (cfg->codec) { + case CODEC_SBC: + cfg->handle.sbc_enc = + malloc(sizeof(*cfg->handle.sbc_enc)); + if (cfg->handle.sbc_enc == NULL) + return (-1); + memset(cfg->handle.sbc_enc, 0, sizeof(*cfg->handle.sbc_enc)); + break; +#ifdef HAVE_LIBAV + case CODEC_AAC: + cfg->handle.av.codec = __DECONST(AVCodec *, + avcodec_find_encoder_by_name("aac")); + if (cfg->handle.av.codec == NULL) { + DPRINTF("Codec AAC encoder not found\n"); + goto av_error_0; + } + cfg->handle.av.format = avformat_alloc_context(); + if (cfg->handle.av.format == NULL) { + DPRINTF("Could not allocate format context\n"); + goto av_error_0; + } + cfg->handle.av.format->oformat = + av_guess_format("latm", NULL, NULL); + if (cfg->handle.av.format->oformat == NULL) { + DPRINTF("Could not guess output format\n"); + goto av_error_1; + } + cfg->handle.av.stream = avformat_new_stream( + cfg->handle.av.format, cfg->handle.av.codec); + + if (cfg->handle.av.stream == NULL) { + DPRINTF("Could not create new stream\n"); + goto av_error_1; + } + cfg->handle.av.context = avcodec_alloc_context3(cfg->handle.av.codec); + if (cfg->handle.av.context == NULL) { + DPRINTF("Could not allocate audio context\n"); + goto av_error_1; + } + /*avcodec_get_context_defaults3(cfg->handle.av.context,*/ + /*cfg->handle.av.codec);*/ + + cfg->handle.av.context->bit_rate = 128000; + cfg->handle.av.context->sample_fmt = AV_SAMPLE_FMT_FLTP; + cfg->handle.av.context->sample_rate = samplerate; + switch (*pchannels) { + case 1: + cfg->handle.av.context->ch_layout = *(AVChannelLayout *)AV_CH_LAYOUT_MONO; + break; + default: + cfg->handle.av.context->ch_layout = *(AVChannelLayout *)AV_CH_LAYOUT_STEREO; + break; + } + + cfg->handle.av.context->profile = FF_PROFILE_AAC_LOW; + if (1) { + AVDictionary *opts = NULL; + + av_dict_set(&opts, "strict", "-2", 0); + av_dict_set_int(&opts, "latm", 1, 0); + + if (avcodec_open2(cfg->handle.av.context, + cfg->handle.av.codec, &opts) < 0) { + av_dict_free(&opts); + + DPRINTF("Could not open codec\n"); + goto av_error_1; + } + av_dict_free(&opts); + } + cfg->handle.av.frame = av_frame_alloc(); + if (cfg->handle.av.frame == NULL) { + DPRINTF("Could not allocate audio frame\n"); + goto av_error_2; + } + cfg->handle.av.frame->nb_samples = cfg->handle.av.context->frame_size; + cfg->handle.av.frame->format = cfg->handle.av.context->sample_fmt; + cfg->handle.av.frame->ch_layout = cfg->handle.av.context->ch_layout; + cfg->rem_in_size = av_samples_get_buffer_size(NULL, + cfg->handle.av.context->ch_layout.nb_channels, + cfg->handle.av.context->frame_size, + cfg->handle.av.context->sample_fmt, 0); + + cfg->rem_in_data = av_malloc(cfg->rem_in_size); + if (cfg->rem_in_data == NULL) { + DPRINTF("Could not allocate %u bytes sample buffer\n", + (unsigned)cfg->rem_in_size); + goto av_error_3; + } + retval = avcodec_fill_audio_frame(cfg->handle.av.frame, + cfg->handle.av.context->ch_layout.nb_channels, + cfg->handle.av.context->sample_fmt, + cfg->rem_in_data, cfg->rem_in_size, 0); + if (retval < 0) { + DPRINTF("Could not setup audio frame\n"); + goto av_error_4; + } + break; +av_error_4: + av_free(cfg->rem_in_data); +av_error_3: + av_frame_free(&cfg->handle.av.frame); +av_error_2: + avcodec_close(cfg->handle.av.context); +av_error_1: + avformat_free_context(cfg->handle.av.format); + cfg->handle.av.context = NULL; +av_error_0: + bt_close(pbe); + return (-1); +#endif + default: + bt_close(pbe); + return (-1); + } + return (0); +} + +static int +bt_rec_transfer(struct voss_backend *pbe, void *ptr, int len) +{ + return (bt_receive(pbe->arg, ptr, len, 1)); +} + +static int +bt_play_sbc_transfer(struct voss_backend *pbe, void *ptr, int len) +{ + struct bt_config *cfg = pbe->arg; + struct sbc_encode *sbc = cfg->handle.sbc_enc; + int rem_size = 1; + int old_len = len; + int err = 0; + + switch (cfg->blocks) { + case BLOCKS_4: + sbc->blocks = 4; + rem_size *= 4; + break; + case BLOCKS_8: + sbc->blocks = 8; + rem_size *= 8; + break; + case BLOCKS_12: + sbc->blocks = 12; + rem_size *= 12; + break; + default: + sbc->blocks = 16; + rem_size *= 16; + break; + } + + switch (cfg->bands) { + case BANDS_4: + rem_size *= 4; + sbc->bands = 4; + break; + default: + rem_size *= 8; + sbc->bands = 8; + break; + } + + /* store number of samples per frame */ + sbc->framesamples = rem_size; + + if (cfg->chmode != MODE_MONO) { + rem_size *= 2; + sbc->channels = 2; + } else { + sbc->channels = 1; + } + + rem_size *= 2; /* 16-bit samples */ + + while (len > 0) { + int delta = len; + + if (delta > (int)(rem_size - sbc->rem_len)) + delta = (int)(rem_size - sbc->rem_len); + + /* copy in samples */ + memcpy((char *)sbc->music_data + sbc->rem_len, ptr, delta); + + ptr = (char *)ptr + delta; + len -= delta; + sbc->rem_len += delta; + + /* check if buffer is full */ + if ((int)sbc->rem_len == rem_size) { + struct sbc_header *phdr = (struct sbc_header *)cfg->mtu_data; + uint32_t pkt_len; + uint32_t rem; + + if (cfg->chmode == MODE_MONO) + sbc->channels = 1; + else + sbc->channels = 2; + + pkt_len = sbc_encode_frame(cfg); + + retry: + if (cfg->mtu_offset == 0) { + phdr->id = 0x80; /* RTP v2 */ + phdr->id2 = 0x60; /* payload type 96. */ + phdr->seqnumMSB = (uint8_t)(cfg->mtu_seqnumber >> 8); + phdr->seqnumLSB = (uint8_t)(cfg->mtu_seqnumber); + phdr->ts3 = (uint8_t)(cfg->mtu_timestamp >> 24); + phdr->ts2 = (uint8_t)(cfg->mtu_timestamp >> 16); + phdr->ts1 = (uint8_t)(cfg->mtu_timestamp >> 8); + phdr->ts0 = (uint8_t)(cfg->mtu_timestamp); + phdr->reserved0 = 0x01; + phdr->numFrames = 0; + + cfg->mtu_seqnumber++; + cfg->mtu_offset += sizeof(*phdr); + } + /* compute bytes left */ + rem = cfg->mtu - cfg->mtu_offset; + + if (phdr->numFrames == 255 || rem < pkt_len) { + int xlen; + + if (phdr->numFrames == 0) + return (-1); + do { + xlen = write(cfg->fd, cfg->mtu_data, cfg->mtu_offset); + } while (xlen < 0 && errno == EAGAIN); + + if (xlen < 0) + return (-1); + + cfg->mtu_offset = 0; + goto retry; + } + memcpy(cfg->mtu_data + cfg->mtu_offset, sbc->data, pkt_len); + memset(sbc->data, 0, pkt_len); + cfg->mtu_offset += pkt_len; + cfg->mtu_timestamp += sbc->framesamples; + phdr->numFrames++; + + sbc->rem_len = 0; + } + } + if (err == 0) + return (old_len); + return (err); +} + +#ifdef HAVE_LIBAV +static int +bt_play_aac_transfer(struct voss_backend *pbe, void *ptr, int len) +{ + struct bt_config *cfg = pbe->arg; + struct aac_header { + uint8_t id; + uint8_t id2; + uint8_t seqnumMSB; + uint8_t seqnumLSB; + uint8_t ts3; + uint8_t ts2; + uint8_t ts1; + uint8_t ts0; + uint8_t sync3; + uint8_t sync2; + uint8_t sync1; + uint8_t sync0; + uint8_t fixed[8]; + }; + int old_len = len; + int err = 0; + + while (len > 0) { + int delta = len; + int rem; + + if (delta > (int)(cfg->rem_in_size - cfg->rem_in_len)) + delta = (int)(cfg->rem_in_size - cfg->rem_in_len); + + memcpy(cfg->rem_in_data + cfg->rem_in_len, ptr, delta); + + ptr = (char *)ptr + delta; + len -= delta; + cfg->rem_in_len += delta; + + /* check if buffer is full */ + if (cfg->rem_in_len == cfg->rem_in_size) { + struct aac_header *phdr = (struct aac_header *)cfg->mtu_data; + AVPacket *pkt; + uint8_t *pkt_buf; + int pkt_len; + + pkt = av_packet_alloc(); + err = avcodec_send_frame(cfg->handle.av.context, + cfg->handle.av.frame); + if (err < 0) { + DPRINTF("Error encoding audio frame\n"); + return (-1); + } + phdr->id = 0x80;/* RTP v2 */ + phdr->id2 = 0x60; /* payload type 96. */ + phdr->seqnumMSB = (uint8_t)(cfg->mtu_seqnumber >> 8); + phdr->seqnumLSB = (uint8_t)(cfg->mtu_seqnumber); + phdr->ts3 = (uint8_t)(cfg->mtu_timestamp >> 24); + phdr->ts2 = (uint8_t)(cfg->mtu_timestamp >> 16); + phdr->ts1 = (uint8_t)(cfg->mtu_timestamp >> 8); + phdr->ts0 = (uint8_t)(cfg->mtu_timestamp); + phdr->sync3 = 0; + phdr->sync2 = 0; + phdr->sync1 = 0; + phdr->sync0 = 0; + phdr->fixed[0] = 0xfc; + phdr->fixed[1] = 0x00; + phdr->fixed[2] = 0x00; + phdr->fixed[3] = 0xb0; + phdr->fixed[4] = 0x90; + phdr->fixed[5] = 0x80; + phdr->fixed[6] = 0x03; + phdr->fixed[7] = 0x00; + + cfg->mtu_seqnumber++; + cfg->mtu_offset = sizeof(*phdr); + + /* compute bytes left */ + rem = cfg->mtu - cfg->mtu_offset; + + if (avio_open_dyn_buf(&cfg->handle.av.format->pb) == 0) { + static int once = 0; + + if (!once++) + (void)avformat_write_header(cfg->handle.av.format, NULL); + av_write_frame(cfg->handle.av.format, pkt); + av_packet_unref(pkt); + pkt_len = avio_close_dyn_buf(cfg->handle.av.format->pb, &pkt_buf); + if (rem < pkt_len) + DPRINTF("Out of buffer space\n"); + if (pkt_len >= 3 && rem >= pkt_len) { + int xlen; + + memcpy(cfg->mtu_data + cfg->mtu_offset, pkt_buf + 3, pkt_len - 3); + + av_free(pkt_buf); + + cfg->mtu_offset += pkt_len - 3; + if (cfg->chmode != MODE_MONO) + cfg->mtu_timestamp += cfg->rem_in_size / 4; + else + cfg->mtu_timestamp += cfg->rem_in_size / 2; + do { + xlen = write(cfg->fd, cfg->mtu_data, cfg->mtu_offset); + } while (xlen < 0 && errno == EAGAIN); + + if (xlen < 0) + return (-1); + } else { + av_free(pkt_buf); + } + } else { + av_packet_unref(pkt); + } + /* reset remaining length */ + cfg->rem_in_len = 0; + } + } + if (err == 0) + return (old_len); + return (err); +} + +#endif + +static int +bt_play_transfer(struct voss_backend *pbe, void *ptr, int len) +{ + struct bt_config *cfg = pbe->arg; + + switch (cfg->codec) { + case CODEC_SBC: + return (bt_play_sbc_transfer(pbe, ptr, len)); +#ifdef HAVE_LIBAV + case CODEC_AAC: + return (bt_play_aac_transfer(pbe, ptr, len)); +#endif + default: + return (-1); + } +} + +static void +bt_rec_delay(struct voss_backend *pbe __unused, int *pdelay) +{ + *pdelay = -1; +} + +static void +bt_play_delay(struct voss_backend *pbe __unused, int *pdelay) +{ + /* TODO */ + *pdelay = -1; +} + +struct voss_backend voss_backend_bt_rec = { + .open = bt_rec_open, + .close = bt_rec_close, + .transfer = bt_rec_transfer, + .delay = bt_rec_delay, + .arg = &bt_rec_cfg, +}; + +struct voss_backend voss_backend_bt_play = { + .open = bt_play_open, + .close = bt_play_close, + .transfer = bt_play_transfer, + .delay = bt_play_delay, + .arg = &bt_play_cfg, +}; diff --git a/lib/virtual_oss/bt/bt.h b/lib/virtual_oss/bt/bt.h new file mode 100644 index 000000000000..2abdb9eb021a --- /dev/null +++ b/lib/virtual_oss/bt/bt.h @@ -0,0 +1,116 @@ +/*- + * Copyright (c) 2015 Hans Petter Selasky + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _BACKEND_BT_H_ +#define _BACKEND_BT_H_ + +#ifdef HAVE_LIBAV +#include <libavformat/avformat.h> +#include <libavcodec/avcodec.h> +#include <libavutil/opt.h> +#endif + +#include "sbc_encode.h" + +struct bt_config { + uint8_t sep; /* SEID of the peer */ + uint8_t media_Type; + uint8_t chmode; +#define MODE_STEREO 2 +#define MODE_JOINT 3 +#define MODE_DUAL 1 +#define MODE_MONO 0 + uint8_t allocm; +#define ALLOC_LOUDNESS 0 +#define ALLOC_SNR 1 + uint8_t bitpool; + uint8_t bands; +#define BANDS_4 0 +#define BANDS_8 1 + uint8_t blocks; +#define BLOCKS_4 0 +#define BLOCKS_8 1 +#define BLOCKS_12 2 +#define BLOCKS_16 3 + uint8_t freq; +#define FREQ_UNDEFINED 255 +#define FREQ_16K 0 +#define FREQ_32K 1 +#define FREQ_44_1K 2 +#define FREQ_48K 3 + uint16_t mtu; + uint8_t codec; +#define CODEC_SBC 0x00 +#define CODEC_AAC 0x02 + uint8_t aacMode1; + uint8_t aacMode2; + + /* transcoding handle(s) */ + union { +#ifdef HAVE_LIBAV + struct { + AVCodec *codec; + AVCodecContext *context; + AVFormatContext *format; + AVFrame *frame; + AVStream *stream; + } av; +#endif + struct sbc_encode *sbc_enc; + } handle; + + /* audio input buffer */ + uint32_t rem_in_len; + uint32_t rem_in_size; + uint8_t *rem_in_data; + + /* data transport */ + uint32_t mtu_seqnumber; + uint32_t mtu_timestamp; + uint32_t mtu_offset; + + /* bluetooth file handles */ + int fd; + int hc; + + /* scratch buffer */ + uint8_t mtu_data[65536]; + + /* acceptor state */ + int8_t acceptor_state; +#define acpInitial 1 +#define acpConfigurationSet 2 +#define acpStreamOpened 3 +#define acpStreamStarted 4 +#define acpStreamSuspended 5 +#define acpStreamClosed 6 +}; + +size_t sbc_encode_frame(struct bt_config *); +size_t sbc_decode_frame(struct bt_config *, int); + +int bt_receive(struct bt_config *cfg, void *ptr, int len, int use_delay); + +#endif /* _BACKEND_BT_H_ */ diff --git a/lib/virtual_oss/bt/cosdata-gen/Makefile b/lib/virtual_oss/bt/cosdata-gen/Makefile new file mode 100644 index 000000000000..d08e263f32b5 --- /dev/null +++ b/lib/virtual_oss/bt/cosdata-gen/Makefile @@ -0,0 +1,12 @@ +# $NetBSD$ + +WARNS?= 3 + +PROG= cosdata +SRCS= cosdata.c +MAN= + +DPADD+= ${LIBMATH} +LDADD+= -lm + +.include <bsd.prog.mk> diff --git a/lib/virtual_oss/bt/cosdata-gen/cosdata.c b/lib/virtual_oss/bt/cosdata-gen/cosdata.c new file mode 100644 index 000000000000..b8409cbd0216 --- /dev/null +++ b/lib/virtual_oss/bt/cosdata-gen/cosdata.c @@ -0,0 +1,177 @@ +/*- + * Copyright (c) 2015 - 2016 Nathanial Sloss <nathanialsloss@yahoo.com.au> + * All rights reserved. + * + * This software is dedicated to the memory of - + * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012. + * + * Barry was a man who loved his music. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <math.h> +#include <stdio.h> +#include <stdint.h> + +static const double sbc8_coeffs[] = { + 0.00000000e+00, 1.56575398e-04, 3.43256425e-04, 5.54620202e-04, + 8.23919506e-04, 1.13992507e-03, 1.47640169e-03, 1.78371725e-03, + 2.01182542e-03, 2.10371989e-03, 1.99454554e-03, 1.61656283e-03, + 9.02154502e-04, -1.78805361e-04, -1.64973098e-03, -3.49717454e-03, + 5.65949473e-03, 8.02941163e-03, 1.04584443e-02, 1.27472335e-02, + 1.46525263e-02, 1.59045603e-02, 1.62208471e-02, 1.53184106e-02, + 1.29371806e-02, 8.85757540e-03, 2.92408442e-03, -4.91578024e-03, + -1.46404076e-02, -2.61098752e-02, -3.90751381e-02, -5.31873032e-02, + 6.79989431e-02, 8.29847578e-02, 9.75753918e-02, 1.11196689e-01, + 1.23264548e-01, 1.33264415e-01, 1.40753505e-01, 1.45389847e-01, + 1.46955068e-01, 1.45389847e-01, 1.40753505e-01, 1.33264415e-01, + 1.23264548e-01, 1.11196689e-01, 9.75753918e-02, 8.29847578e-02, + -6.79989431e-02, -5.31873032e-02, -3.90751381e-02, -2.61098752e-02, + -1.46404076e-02, -4.91578024e-03, 2.92408442e-03, 8.85757540e-03, + 1.29371806e-02, 1.53184106e-02, 1.62208471e-02, 1.59045603e-02, + 1.46525263e-02, 1.27472335e-02, 1.04584443e-02, 8.02941163e-03, + -5.65949473e-03, -3.49717454e-03, -1.64973098e-03, -1.78805361e-04, + 9.02154502e-04, 1.61656283e-03, 1.99454554e-03, 2.10371989e-03, + 2.01182542e-03, 1.78371725e-03, 1.47640169e-03, 1.13992507e-03, + 8.23919506e-04, 5.54620202e-04, 3.43256425e-04, 1.56575398e-04, +}; + +static const double sbc4_coeffs[] = { + 0.00000000e+00, 5.36548976e-04, 1.49188357e-03, 2.73370904e-03, + 3.83720193e-03, 3.89205149e-03, 1.86581691e-03, -3.06012286e-03, + 1.09137620e-02, 2.04385087e-02, 2.88757392e-02, 3.21939290e-02, + 2.58767811e-02, 6.13245186e-03, -2.88217274e-02, -7.76463494e-02, + 1.35593274e-01, 1.94987841e-01, 2.46636662e-01, 2.81828203e-01, + 2.94315332e-01, 2.81828203e-01, 2.46636662e-01, 1.94987841e-01, + -1.35593274e-01, -7.76463494e-02, -2.88217274e-02, 6.13245186e-03, + 2.58767811e-02, 3.21939290e-02, 2.88757392e-02, 2.04385087e-02, + -1.09137620e-02, -3.06012286e-03, 1.86581691e-03, 3.89205149e-03, + 3.83720193e-03, 2.73370904e-03, 1.49188357e-03, 5.36548976e-04, +}; + +#define AC(x) (int)(sizeof(x) / sizeof((x)[0])) + +int +main(int argc, char **argv) +{ + float S[8][16]; + int i; + int k; + int count = 0; + + printf("/* sbc_coeffs.h - Automatically generated by cosdata.c. */\n" + "\n"); + + printf("static const float sbc_coeffs8[] = {\n "); + for (k = 0; k < AC(sbc8_coeffs); k++) { + if ((count % 8) == 0 && count != 0) + printf("\n "); + printf("%0.12ff, ", (float)sbc8_coeffs[k]); + count++; + } + printf("\n};\n"); + + count = 0; + printf("static const float sbc_coeffs4[] = {\n "); + for (k = 0; k < AC(sbc4_coeffs); k++) { + if ((count % 8) == 0 && count != 0) + printf("\n "); + printf("%0.12ff, ", (float)sbc4_coeffs[k]); + count++; + } + printf("\n};\n"); + + count = 0; + printf("static const float cosdata8[8][16] = {\n "); + for (i = 0; i < 8; i++) { + for (k = 0; k < 16; k++) { + S[i][k] = cosf((float)((i + 0.5) * (k - 4) * (M_PI / 8.0))); + + if ((count % 8) == 0 && count != 0) + printf("\n "); + if (k == 0) + printf("{ "); + printf("%0.12ff, ", S[i][k]); + if (k == 15) + printf("},"); + count++; + } + } + printf("\n};\n"); + + count = 0; + printf("static const float cosdata4[4][8] = {\n "); + for (i = 0; i < 4; i++) { + for (k = 0; k < 8; k++) { + S[i][k] = cosf((float)((i + 0.5) * (k - 2) * (M_PI / 4.0))); + + if ((count % 8) == 0 && count != 0) + printf("\n "); + if (k == 0) + printf("{ "); + printf("%0.12ff, ", S[i][k]); + if (k == 7) + printf("},"); + count++; + } + } + printf("\n};\n"); + + count = 0; + printf("static const float cosdecdata8[8][16] = {\n "); + for (i = 0; i < 8; i++) { + for (k = 0; k < 16; k++) { + S[i][k] = cosf((float)((i + 0.5) * (k + 4) * (M_PI / 8.0))); + + if ((count % 8) == 0 && count != 0) + printf("\n "); + if (k == 0) + printf("{ "); + printf("%0.12ff, ", S[i][k]); + if (k == 15) + printf("},"); + count++; + } + } + printf("\n};\n"); + + count = 0; + printf("static const float cosdecdata4[4][8] = {\n "); + for (i = 0; i < 4; i++) { + for (k = 0; k < 8; k++) { + S[i][k] = cosf((float)((i + 0.5) * (k + 2) * (M_PI / 4.0))); + + if ((count % 8) == 0 && count != 0) + printf("\n "); + if (k == 0) + printf("{ "); + printf("%0.12ff, ", S[i][k]); + if (k == 7) + printf("},"); + count++; + } + } + printf("\n};\n"); + + return (0); +} diff --git a/lib/virtual_oss/bt/sbc_coeffs.h b/lib/virtual_oss/bt/sbc_coeffs.h new file mode 100644 index 000000000000..b9428033d50b --- /dev/null +++ b/lib/virtual_oss/bt/sbc_coeffs.h @@ -0,0 +1,69 @@ +/* sbc_coeffs.h - Automatically generated by cosdata.c. */ + +static const float sbc_coeffs8[] = { + 0.000000000000f, 0.000156575392f, 0.000343256426f, 0.000554620230f, 0.000823919487f, 0.001139925094f, 0.001476401696f, 0.001783717307f, + 0.002011825331f, 0.002103719860f, 0.001994545572f, 0.001616562833f, 0.000902154483f, -0.000178805363f, -0.001649730955f, -0.003497174475f, + 0.005659494549f, 0.008029411547f, 0.010458444245f, 0.012747233734f, 0.014652526006f, 0.015904560685f, 0.016220847145f, 0.015318410471f, + 0.012937180698f, 0.008857575245f, 0.002924084431f, -0.004915780388f, -0.014640407637f, -0.026109876111f, -0.039075139910f, -0.053187303245f, + 0.067998945713f, 0.082984760404f, 0.097575388849f, 0.111196689308f, 0.123264551163f, 0.133264422417f, 0.140753507614f, 0.145389840007f, + 0.146955072880f, 0.145389840007f, 0.140753507614f, 0.133264422417f, 0.123264551163f, 0.111196689308f, 0.097575388849f, 0.082984760404f, + -0.067998945713f, -0.053187303245f, -0.039075139910f, -0.026109876111f, -0.014640407637f, -0.004915780388f, 0.002924084431f, 0.008857575245f, + 0.012937180698f, 0.015318410471f, 0.016220847145f, 0.015904560685f, 0.014652526006f, 0.012747233734f, 0.010458444245f, 0.008029411547f, + -0.005659494549f, -0.003497174475f, -0.001649730955f, -0.000178805363f, 0.000902154483f, 0.001616562833f, 0.001994545572f, 0.002103719860f, + 0.002011825331f, 0.001783717307f, 0.001476401696f, 0.001139925094f, 0.000823919487f, 0.000554620230f, 0.000343256426f, 0.000156575392f, +}; +static const float sbc_coeffs4[] = { + 0.000000000000f, 0.000536548963f, 0.001491883537f, 0.002733709058f, 0.003837201977f, 0.003892051522f, 0.001865816885f, -0.003060122952f, + 0.010913762264f, 0.020438509062f, 0.028875738382f, 0.032193928957f, 0.025876780972f, 0.006132451817f, -0.028821727261f, -0.077646352351f, + 0.135593280196f, 0.194987848401f, 0.246636658907f, 0.281828194857f, 0.294315338135f, 0.281828194857f, 0.246636658907f, 0.194987848401f, + -0.135593280196f, -0.077646352351f, -0.028821727261f, 0.006132451817f, 0.025876780972f, 0.032193928957f, 0.028875738382f, 0.020438509062f, + -0.010913762264f, -0.003060122952f, 0.001865816885f, 0.003892051522f, 0.003837201977f, 0.002733709058f, 0.001491883537f, 0.000536548963f, +}; +static const float cosdata8[8][16] = { + { 0.707106769085f, 0.831469595432f, 0.923879504204f, 0.980785250664f, 1.000000000000f, 0.980785250664f, 0.923879504204f, 0.831469595432f, + 0.707106769085f, 0.555570244789f, 0.382683426142f, 0.195090353489f, -0.000000043711f, -0.195090323687f, -0.382683396339f, -0.555570185184f, }, + { -0.707106769085f, -0.195090323687f, 0.382683426142f, 0.831469595432f, 1.000000000000f, 0.831469595432f, 0.382683426142f, -0.195090323687f, + -0.707106769085f, -0.980785310268f, -0.923879504204f, -0.555570423603f, 0.000000011925f, 0.555570065975f, 0.923879563808f, 0.980785310268f, }, + { -0.707106828690f, -0.980785310268f, -0.382683396339f, 0.555570244789f, 1.000000000000f, 0.555570244789f, -0.382683396339f, -0.980785310268f, + -0.707106828690f, 0.195090413094f, 0.923879563808f, 0.831469655037f, 0.000000139071f, -0.831469774246f, -0.923879444599f, -0.195090219378f, }, + { 0.707106649876f, -0.555570423603f, -0.923879504204f, 0.195090353489f, 1.000000000000f, 0.195090353489f, -0.923879504204f, -0.555570423603f, + 0.707106649876f, 0.831469655037f, -0.382683008909f, -0.980785369873f, -0.000000290067f, 0.980785250664f, 0.382683545351f, -0.831469595432f, }, + { 0.707106769085f, 0.555570065975f, -0.923879504204f, -0.195090323687f, 1.000000000000f, -0.195090323687f, -0.923879504204f, 0.555570065975f, + 0.707106769085f, -0.831469774246f, -0.382683843374f, 0.980785250664f, -0.000000035775f, -0.980785250664f, 0.382683902979f, 0.831469714642f, }, + { -0.707106590271f, 0.980785310268f, -0.382683575153f, -0.555570185184f, 1.000000000000f, -0.555570185184f, -0.382683575153f, 0.980785310268f, + -0.707106590271f, -0.195090219378f, 0.923879683018f, -0.831469595432f, -0.000000592058f, 0.831469714642f, -0.923879623413f, 0.195090919733f, }, + { -0.707106530666f, 0.195090532303f, 0.382683604956f, -0.831469655037f, 1.000000000000f, -0.831469655037f, 0.382683604956f, 0.195090532303f, + -0.707106530666f, 0.980785310268f, -0.923879384995f, 0.555569529533f, -0.000000687457f, -0.555570006371f, 0.923879563808f, -0.980785191059f, }, + { 0.707106828690f, -0.831469774246f, 0.923879563808f, -0.980785310268f, 1.000000000000f, -0.980785310268f, 0.923879563808f, -0.831469774246f, + 0.707106828690f, -0.555570065975f, 0.382683902979f, -0.195089668036f, 0.000000059624f, 0.195089548826f, -0.382683813572f, 0.555569946766f, }, +}; +static const float cosdata4[4][8] = { + { 0.707106769085f, 0.923879504204f, 1.000000000000f, 0.923879504204f, 0.707106769085f, 0.382683426142f, -0.000000043711f, -0.382683396339f, }, + { -0.707106769085f, 0.382683426142f, 1.000000000000f, 0.382683426142f, -0.707106769085f, -0.923879504204f, 0.000000011925f, 0.923879563808f, }, + { -0.707106828690f, -0.382683396339f, 1.000000000000f, -0.382683396339f, -0.707106828690f, 0.923879563808f, 0.000000139071f, -0.923879444599f, }, + { 0.707106649876f, -0.923879504204f, 1.000000000000f, -0.923879504204f, 0.707106649876f, -0.382683008909f, -0.000000290067f, 0.382683545351f, }, +}; +static const float cosdecdata8[8][16] = { + { 0.707106769085f, 0.555570244789f, 0.382683426142f, 0.195090353489f, -0.000000043711f, -0.195090323687f, -0.382683396339f, -0.555570185184f, + -0.707106769085f, -0.831469655037f, -0.923879504204f, -0.980785310268f, -1.000000000000f, -0.980785310268f, -0.923879504204f, -0.831469535828f, }, + { -0.707106769085f, -0.980785310268f, -0.923879504204f, -0.555570423603f, 0.000000011925f, 0.555570065975f, 0.923879563808f, 0.980785310268f, + 0.707106769085f, 0.195090532303f, -0.382683008909f, -0.831469774246f, -1.000000000000f, -0.831469714642f, -0.382683843374f, 0.195090577006f, }, + { -0.707106828690f, 0.195090413094f, 0.923879563808f, 0.831469655037f, 0.000000139071f, -0.831469774246f, -0.923879444599f, -0.195090219378f, + 0.707106828690f, 0.980785310268f, 0.382683545351f, -0.555570065975f, -1.000000000000f, -0.555570542812f, 0.382683902979f, 0.980785191059f, }, + { 0.707106649876f, 0.831469655037f, -0.382683008909f, -0.980785369873f, -0.000000290067f, 0.980785250664f, 0.382683545351f, -0.831469595432f, + -0.707107424736f, 0.555569529533f, 0.923879802227f, -0.195089668036f, -1.000000000000f, -0.195090815425f, 0.923879384995f, 0.555570483208f, }, + { 0.707106769085f, -0.831469774246f, -0.382683843374f, 0.980785250664f, -0.000000035775f, -0.980785250664f, 0.382683902979f, 0.831469714642f, + -0.707106173038f, -0.555570006371f, 0.923879384995f, 0.195089548826f, -1.000000000000f, 0.195089697838f, 0.923879325390f, -0.555570125580f, }, + { -0.707106590271f, -0.195090219378f, 0.923879683018f, -0.831469595432f, -0.000000592058f, 0.831469714642f, -0.923879623413f, 0.195090919733f, + 0.707107424736f, -0.980785191059f, 0.382683366537f, 0.555569946766f, -1.000000000000f, 0.555571198463f, 0.382683783770f, -0.980785667896f, }, + { -0.707106530666f, 0.980785310268f, -0.923879384995f, 0.555569529533f, -0.000000687457f, -0.555570006371f, 0.923879563808f, -0.980785191059f, + 0.707106173038f, -0.195089071989f, -0.382684975863f, 0.831468641758f, -1.000000000000f, 0.831470131874f, -0.382683992386f, -0.195090129972f, }, + { 0.707106828690f, -0.555570065975f, 0.382683902979f, -0.195089668036f, 0.000000059624f, 0.195089548826f, -0.382683813572f, 0.555569946766f, + -0.707106053829f, 0.831468641758f, -0.923880040646f, 0.980785369873f, -1.000000000000f, 0.980785429478f, -0.923880159855f, 0.831468760967f, }, +}; +static const float cosdecdata4[4][8] = { + { 0.707106769085f, 0.382683426142f, -0.000000043711f, -0.382683396339f, -0.707106769085f, -0.923879504204f, -1.000000000000f, -0.923879504204f, }, + { -0.707106769085f, -0.923879504204f, 0.000000011925f, 0.923879563808f, 0.707106769085f, -0.382683008909f, -1.000000000000f, -0.382683843374f, }, + { -0.707106828690f, 0.923879563808f, 0.000000139071f, -0.923879444599f, 0.707106828690f, 0.382683545351f, -1.000000000000f, 0.382683902979f, }, + { 0.707106649876f, -0.382683008909f, -0.000000290067f, 0.382683545351f, -0.707107424736f, 0.923879802227f, -1.000000000000f, 0.923879384995f, }, +}; diff --git a/lib/virtual_oss/bt/sbc_encode.c b/lib/virtual_oss/bt/sbc_encode.c new file mode 100644 index 000000000000..153f2e69e76e --- /dev/null +++ b/lib/virtual_oss/bt/sbc_encode.c @@ -0,0 +1,701 @@ +/*- + * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au> + * + * This software is dedicated to the memory of - + * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012. + * + * Barry was a man who loved his music. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/endian.h> +#include <sys/uio.h> + +#include <stdio.h> +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <math.h> + +#include "sbc_coeffs.h" +#include "bt.h" + +#define SYNCWORD 0x9c +#define ABS(x) (((x) < 0) ? -(x) : (x)) +#define BIT30 (1U << 30) +#define BM(x) ((1LL << (x)) - 1LL) + +/* Loudness offset allocations. */ +static const int loudnessoffset8[4][8] = { + {-2, 0, 0, 0, 0, 0, 0, 1}, + {-3, 0, 0, 0, 0, 0, 1, 2}, + {-4, 0, 0, 0, 0, 0, 1, 2}, + {-4, 0, 0, 0, 0, 0, 1, 2}, +}; + +static const int loudnessoffset4[4][4] = { + {-1, 0, 0, 0}, + {-2, 0, 0, 1}, + {-2, 0, 0, 1}, + {-2, 0, 0, 1}, +}; + +static uint8_t +calc_scalefactors_joint(struct sbc_encode *sbc) +{ + float sb_j[16][2]; + uint32_t x; + uint32_t y; + uint8_t block; + uint8_t joint; + uint8_t sb; + uint8_t lz; + + joint = 0; + for (sb = 0; sb != sbc->bands - 1; sb++) { + for (block = 0; block < sbc->blocks; block++) { + sb_j[block][0] = (sbc->samples[block][0][sb] + + sbc->samples[block][1][sb]) / 2.0f; + sb_j[block][1] = (sbc->samples[block][0][sb] - + sbc->samples[block][1][sb]) / 2.0f; + } + + x = 1 << 15; + y = 1 << 15; + for (block = 0; block < sbc->blocks; block++) { + x |= (uint32_t)ABS(sb_j[block][0]); + y |= (uint32_t)ABS(sb_j[block][1]); + } + + lz = 1; + while (!(x & BIT30)) { + lz++; + x <<= 1; + } + x = 16 - lz; + + lz = 1; + while (!(y & BIT30)) { + lz++; + y <<= 1; + } + y = 16 - lz; + + if ((sbc->scalefactor[0][sb] + sbc->scalefactor[1][sb]) > x + y) { + joint |= 1 << (sbc->bands - sb - 1); + sbc->scalefactor[0][sb] = x; + sbc->scalefactor[1][sb] = y; + for (block = 0; block < sbc->blocks; block++) { + sbc->samples[block][0][sb] = sb_j[block][0]; + sbc->samples[block][1][sb] = sb_j[block][1]; + } + } + } + return (joint); +} + +static void +calc_scalefactors(struct sbc_encode *sbc) +{ + uint8_t block; + uint8_t ch; + uint8_t sb; + + for (ch = 0; ch != sbc->channels; ch++) { + for (sb = 0; sb != sbc->bands; sb++) { + uint32_t x = 1 << 15; + uint8_t lx = 1; + + for (block = 0; block != sbc->blocks; block++) + x |= (uint32_t)ABS(sbc->samples[block][ch][sb]); + + while (!(x & BIT30)) { + lx++; + x <<= 1; + } + sbc->scalefactor[ch][sb] = 16 - lx; + } + } +} + +static void +calc_bitneed(struct bt_config *cfg) +{ + struct sbc_encode *sbc = cfg->handle.sbc_enc; + int32_t bitneed[2][8]; + int32_t max_bitneed, bitcount; + int32_t slicecount, bitslice; + int32_t loudness; + int ch, sb, start_chan = 0; + + if (cfg->chmode == MODE_DUAL) + sbc->channels = 1; + +next_chan: + max_bitneed = 0; + bitcount = 0; + slicecount = 0; + + if (cfg->allocm == ALLOC_SNR) { + for (ch = start_chan; ch < sbc->channels; ch++) { + for (sb = 0; sb < sbc->bands; sb++) { + bitneed[ch][sb] = sbc->scalefactor[ch][sb]; + + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } + } else { + for (ch = start_chan; ch < sbc->channels; ch++) { + for (sb = 0; sb < sbc->bands; sb++) { + if (sbc->scalefactor[ch][sb] == 0) { + bitneed[ch][sb] = -5; + } else { + if (sbc->bands == 8) { + loudness = sbc->scalefactor[ch][sb] - + loudnessoffset8[cfg->freq][sb]; + } else { + loudness = sbc->scalefactor[ch][sb] - + loudnessoffset4[cfg->freq][sb]; + } + if (loudness > 0) + bitneed[ch][sb] = loudness / 2; + else + bitneed[ch][sb] = loudness; + } + if (bitneed[ch][sb] > max_bitneed) + max_bitneed = bitneed[ch][sb]; + } + } + } + + slicecount = bitcount = 0; + bitslice = max_bitneed + 1; + do { + bitslice--; + bitcount += slicecount; + slicecount = 0; + for (ch = start_chan; ch < sbc->channels; ch++) { + for (sb = 0; sb < sbc->bands; sb++) { + if ((bitneed[ch][sb] > bitslice + 1) && + (bitneed[ch][sb] < bitslice + 16)) + slicecount++; + else if (bitneed[ch][sb] == bitslice + 1) + slicecount += 2; + } + } + } while (bitcount + slicecount < cfg->bitpool); + + /* check if exactly one more fits */ + if (bitcount + slicecount == cfg->bitpool) { + bitcount += slicecount; + bitslice--; + } + for (ch = start_chan; ch < sbc->channels; ch++) { + for (sb = 0; sb < sbc->bands; sb++) { + if (bitneed[ch][sb] < bitslice + 2) { + sbc->bits[ch][sb] = 0; + } else { + sbc->bits[ch][sb] = bitneed[ch][sb] - bitslice; + if (sbc->bits[ch][sb] > 16) + sbc->bits[ch][sb] = 16; + } + } + } + + if (cfg->chmode == MODE_DUAL) + ch = start_chan; + else + ch = 0; + sb = 0; + while (bitcount < cfg->bitpool && sb < sbc->bands) { + if ((sbc->bits[ch][sb] >= 2) && (sbc->bits[ch][sb] < 16)) { + sbc->bits[ch][sb]++; + bitcount++; + } else if ((bitneed[ch][sb] == bitslice + 1) && + (cfg->bitpool > bitcount + 1)) { + sbc->bits[ch][sb] = 2; + bitcount += 2; + } + if (sbc->channels == 1 || start_chan == 1) + sb++; + else if (ch == 1) { + ch = 0; + sb++; + } else + ch = 1; + } + + if (cfg->chmode == MODE_DUAL) + ch = start_chan; + else + ch = 0; + sb = 0; + while (bitcount < cfg->bitpool && sb < sbc->bands) { + if (sbc->bits[ch][sb] < 16) { + sbc->bits[ch][sb]++; + bitcount++; + } + if (sbc->channels == 1 || start_chan == 1) + sb++; + else if (ch == 1) { + ch = 0; + sb++; + } else + ch = 1; + } + + if (cfg->chmode == MODE_DUAL && start_chan == 0) { + start_chan = 1; + sbc->channels = 2; + goto next_chan; + } +} + +static void +sbc_store_bits_crc(struct sbc_encode *sbc, uint32_t numbits, uint32_t value) +{ + uint32_t off = sbc->bitoffset; + + while (numbits-- && off != sbc->maxoffset) { + if (value & (1 << numbits)) { + sbc->data[off / 8] |= 1 << ((7 - off) & 7); + sbc->crc ^= 0x80; + } + sbc->crc *= 2; + if (sbc->crc & 0x100) + sbc->crc ^= 0x11d; /* CRC-8 polynomial */ + + off++; + } + sbc->bitoffset = off; +} + +static int +sbc_encode(struct bt_config *cfg) +{ + struct sbc_encode *sbc = cfg->handle.sbc_enc; + const int16_t *input = sbc->music_data; + float delta[2][8]; + float levels[2][8]; + float mask[2][8]; + float S; + float *X; + float Z[80]; + float Y[80]; + float audioout; + int16_t left[8]; + int16_t right[8]; + int16_t *data; + int numsamples; + int i; + int k; + int block; + int chan; + int sb; + + for (block = 0; block < sbc->blocks; block++) { + + for (i = 0; i < sbc->bands; i++) { + left[i] = *input++; + if (sbc->channels == 2) + right[i] = *input++; + } + + for (chan = 0; chan < sbc->channels; chan++) { + + /* select right or left channel */ + if (chan == 0) { + X = sbc->left; + data = left; + } else { + X = sbc->right; + data = right; + } + + /* shift up old data */ + for (i = (sbc->bands * 10) - 1; i > sbc->bands - 1; i--) + X[i] = X[i - sbc->bands]; + k = 0; + for (i = sbc->bands - 1; i >= 0; i--) + X[i] = data[k++]; + for (i = 0; i < sbc->bands * 10; i++) { + if (sbc->bands == 8) + Z[i] = sbc_coeffs8[i] * X[i]; + else + Z[i] = sbc_coeffs4[i] * X[i]; + } + for (i = 0; i < sbc->bands * 2; i++) { + Y[i] = 0; + for (k = 0; k < 5; k++) + Y[i] += Z[i + k * sbc->bands * 2]; + } + for (i = 0; i < sbc->bands; i++) { + S = 0; + for (k = 0; k < sbc->bands * 2; k++) { + if (sbc->bands == 8) { + S += cosdata8[i][k] * Y[k]; + } else { + S += cosdata4[i][k] * Y[k]; + } + } + sbc->samples[block][chan][i] = S * (1 << 15); + } + } + } + + calc_scalefactors(sbc); + + if (cfg->chmode == MODE_JOINT) + sbc->join = calc_scalefactors_joint(sbc); + else + sbc->join = 0; + + calc_bitneed(cfg); + + for (chan = 0; chan < sbc->channels; chan++) { + for (sb = 0; sb < sbc->bands; sb++) { + if (sbc->bits[chan][sb] == 0) + continue; + mask[chan][sb] = BM(sbc->bits[chan][sb]); + levels[chan][sb] = mask[chan][sb] * + (1LL << (15 - sbc->scalefactor[chan][sb])); + delta[chan][sb] = + (1LL << (sbc->scalefactor[chan][sb] + 16)); + } + } + + numsamples = 0; + for (block = 0; block < sbc->blocks; block++) { + for (chan = 0; chan < sbc->channels; chan++) { + for (sb = 0; sb < sbc->bands; sb++) { + if (sbc->bits[chan][sb] == 0) + continue; + audioout = (levels[chan][sb] * + (delta[chan][sb] + sbc->samples[block][chan][sb])); + audioout /= (1LL << 32); + + audioout = roundf(audioout); + + /* range check */ + if (audioout > mask[chan][sb]) + audioout = mask[chan][sb]; + + sbc->output[numsamples++] = audioout; + } + } + } + return (numsamples); +} + +static void +sbc_decode(struct bt_config *cfg) +{ + struct sbc_encode *sbc = cfg->handle.sbc_enc; + float delta[2][8]; + float levels[2][8]; + float audioout; + float *X; + float *V; + float left[160]; + float right[160]; + float U[160]; + float W[160]; + float S[8]; + int position; + int block; + int chan; + int sb; + int i; + int k; + + for (chan = 0; chan < sbc->channels; chan++) { + for (sb = 0; sb < sbc->bands; sb++) { + levels[chan][sb] = (1 << sbc->bits[chan][sb]) - 1; + delta[chan][sb] = (1 << sbc->scalefactor[chan][sb]); + } + } + + i = 0; + for (block = 0; block < sbc->blocks; block++) { + for (chan = 0; chan < sbc->channels; chan++) { + for (sb = 0; sb < sbc->bands; sb++) { + if (sbc->bits[chan][sb] == 0) { + audioout = 0; + } else { + audioout = + ((((sbc->output[i] * 2.0f) + 1.0f) * delta[chan][sb]) / + levels[chan][sb]) - delta[chan][sb]; + } + sbc->output[i++] = audioout; + } + } + } + + if (cfg->chmode == MODE_JOINT) { + i = 0; + while (i < (sbc->blocks * sbc->bands * sbc->channels)) { + for (sb = 0; sb < sbc->bands; sb++) { + if (sbc->join & (1 << (sbc->bands - sb - 1))) { + audioout = sbc->output[i]; + sbc->output[i] = (2.0f * sbc->output[i]) + + (2.0f * sbc->output[i + sbc->bands]); + sbc->output[i + sbc->bands] = + (2.0f * audioout) - + (2.0f * sbc->output[i + sbc->bands]); + sbc->output[i] /= 2.0f; + sbc->output[i + sbc->bands] /= 2.0f; + } + i++; + } + i += sbc->bands; + } + } + position = 0; + for (block = 0; block < sbc->blocks; block++) { + for (chan = 0; chan < sbc->channels; chan++) { + /* select right or left channel */ + if (chan == 0) { + X = left; + V = sbc->left; + } else { + X = right; + V = sbc->right; + } + for (i = 0; i < sbc->bands; i++) + S[i] = sbc->output[position++]; + + for (i = (sbc->bands * 20) - 1; i >= (sbc->bands * 2); i--) + V[i] = V[i - (sbc->bands * 2)]; + for (k = 0; k < sbc->bands * 2; k++) { + float vk = 0; + for (i = 0; i < sbc->bands; i++) { + if (sbc->bands == 8) { + vk += cosdecdata8[i][k] * S[i]; + } else { + vk += cosdecdata4[i][k] * S[i]; + } + } + V[k] = vk; + } + for (i = 0; i <= 4; i++) { + for (k = 0; k < sbc->bands; k++) { + U[(i * sbc->bands * 2) + k] = + V[(i * sbc->bands * 4) + k]; + U[(i * sbc->bands + * 2) + sbc->bands + k] = + V[(i * sbc->bands * 4) + + (sbc->bands * 3) + k]; + } + } + for (i = 0; i < sbc->bands * 10; i++) { + if (sbc->bands == 4) { + W[i] = U[i] * (sbc_coeffs4[i] * -4.0f); + } else if (sbc->bands == 8) { + W[i] = U[i] * (sbc_coeffs8[i] * -8.0f); + } else { + W[i] = 0; + } + } + + for (k = 0; k < sbc->bands; k++) { + unsigned int offset = k + (block * sbc->bands); + + X[offset] = 0; + for (i = 0; i < 10; i++) { + X[offset] += W[k + (i * sbc->bands)]; + } + + if (X[offset] > 32767.0) + X[offset] = 32767.0; + else if (X[offset] < -32767.0) + X[offset] = -32767.0; + } + } + } + + for (i = 0, k = 0; k != (sbc->blocks * sbc->bands); k++) { + sbc->music_data[i++] = left[k]; + if (sbc->channels == 2) + sbc->music_data[i++] = right[k]; + } +} + +size_t +sbc_encode_frame(struct bt_config *cfg) +{ + struct sbc_encode *sbc = cfg->handle.sbc_enc; + uint8_t config; + uint8_t block; + uint8_t chan; + uint8_t sb; + uint8_t j; + uint8_t i; + + config = (cfg->freq << 6) | (cfg->blocks << 4) | + (cfg->chmode << 2) | (cfg->allocm << 1) | cfg->bands; + + sbc_encode(cfg); + + /* set initial CRC */ + sbc->crc = 0x5e; + + /* reset data position and size */ + sbc->bitoffset = 0; + sbc->maxoffset = sizeof(sbc->data) * 8; + + sbc_store_bits_crc(sbc, 8, SYNCWORD); + sbc_store_bits_crc(sbc, 8, config); + sbc_store_bits_crc(sbc, 8, cfg->bitpool); + + /* skip 8-bit CRC */ + sbc->bitoffset += 8; + + if (cfg->chmode == MODE_JOINT) { + if (sbc->bands == 8) + sbc_store_bits_crc(sbc, 8, sbc->join); + else if (sbc->bands == 4) + sbc_store_bits_crc(sbc, 4, sbc->join); + } + for (i = 0; i < sbc->channels; i++) { + for (j = 0; j < sbc->bands; j++) + sbc_store_bits_crc(sbc, 4, sbc->scalefactor[i][j]); + } + + /* store 8-bit CRC */ + sbc->data[3] = (sbc->crc & 0xFF); + + i = 0; + for (block = 0; block < sbc->blocks; block++) { + for (chan = 0; chan < sbc->channels; chan++) { + for (sb = 0; sb < sbc->bands; sb++) { + if (sbc->bits[chan][sb] == 0) + continue; + + sbc_store_bits_crc(sbc, sbc->bits[chan][sb], sbc->output[i++]); + } + } + } + return ((sbc->bitoffset + 7) / 8); +} + +static uint32_t +sbc_load_bits_crc(struct sbc_encode *sbc, uint32_t numbits) +{ + uint32_t off = sbc->bitoffset; + uint32_t value = 0; + + while (numbits-- && off != sbc->maxoffset) { + if (sbc->rem_data_ptr[off / 8] & (1 << ((7 - off) & 7))) { + value |= (1 << numbits); + sbc->crc ^= 0x80; + } + sbc->crc *= 2; + if (sbc->crc & 0x100) + sbc->crc ^= 0x11d; /* CRC-8 polynomial */ + + off++; + } + sbc->bitoffset = off; + return (value); +} + +size_t +sbc_decode_frame(struct bt_config *cfg, int bits) +{ + struct sbc_encode *sbc = cfg->handle.sbc_enc; + uint8_t config; + uint8_t block; + uint8_t chan; + uint8_t sb; + uint8_t j; + uint8_t i; + + sbc->rem_off = 0; + sbc->rem_len = 0; + + config = (cfg->freq << 6) | (cfg->blocks << 4) | + (cfg->chmode << 2) | (cfg->allocm << 1) | cfg->bands; + + /* set initial CRC */ + sbc->crc = 0x5e; + + /* reset data position and size */ + sbc->bitoffset = 0; + sbc->maxoffset = bits; + + /* verify SBC header */ + if (sbc->maxoffset < (8 * 4)) + return (0); + if (sbc_load_bits_crc(sbc, 8) != SYNCWORD) + return (0); + if (sbc_load_bits_crc(sbc, 8) != config) + return (0); + cfg->bitpool = sbc_load_bits_crc(sbc, 8); + + (void)sbc_load_bits_crc(sbc, 8);/* CRC */ + + if (cfg->chmode == MODE_JOINT) { + if (sbc->bands == 8) + sbc->join = sbc_load_bits_crc(sbc, 8); + else if (sbc->bands == 4) + sbc->join = sbc_load_bits_crc(sbc, 4); + else + sbc->join = 0; + } else { + sbc->join = 0; + } + + for (i = 0; i < sbc->channels; i++) { + for (j = 0; j < sbc->bands; j++) + sbc->scalefactor[i][j] = sbc_load_bits_crc(sbc, 4); + } + + calc_bitneed(cfg); + + i = 0; + for (block = 0; block < sbc->blocks; block++) { + for (chan = 0; chan < sbc->channels; chan++) { + for (sb = 0; sb < sbc->bands; sb++) { + if (sbc->bits[chan][sb] == 0) { + i++; + continue; + } + sbc->output[i++] = + sbc_load_bits_crc(sbc, sbc->bits[chan][sb]); + } + } + } + + sbc_decode(cfg); + + sbc->rem_off = 0; + sbc->rem_len = sbc->blocks * sbc->channels * sbc->bands; + + return ((sbc->bitoffset + 7) / 8); +} diff --git a/lib/virtual_oss/bt/sbc_encode.h b/lib/virtual_oss/bt/sbc_encode.h new file mode 100644 index 000000000000..71f8460a242e --- /dev/null +++ b/lib/virtual_oss/bt/sbc_encode.h @@ -0,0 +1,82 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2015 Nathanial Sloss <nathanialsloss@yahoo.com.au> + * + * This software is dedicated to the memory of - + * Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012. + * + * Barry was a man who loved his music. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SBC_ENCODE_H_ +#define _SBC_ENCODE_H_ + +#define MIN_BITPOOL 2 +#define DEFAULT_MAXBPOOL 250 + +/* + * SBC header format + */ +struct sbc_header { + uint8_t id; + uint8_t id2; + uint8_t seqnumMSB; + uint8_t seqnumLSB; + uint8_t ts3; + uint8_t ts2; + uint8_t ts1; + uint8_t ts0; + uint8_t reserved3; + uint8_t reserved2; + uint8_t reserved1; + uint8_t reserved0; + uint8_t numFrames; +}; + +struct sbc_encode { + int16_t music_data[256]; + uint8_t data[1024]; + uint8_t *rem_data_ptr; + int rem_data_len; + int rem_data_frames; + int bits[2][8]; + float output[256]; + float left[160]; + float right[160]; + float samples[16][2][8]; + uint32_t rem_len; + uint32_t rem_off; + uint32_t bitoffset; + uint32_t maxoffset; + uint32_t crc; + uint16_t framesamples; + uint8_t scalefactor[2][8]; + uint8_t channels; + uint8_t bands; + uint8_t blocks; + uint8_t join; +}; + +#endif /* _SBC_ENCODE_H_ */ diff --git a/lib/virtual_oss/null/Makefile b/lib/virtual_oss/null/Makefile new file mode 100644 index 000000000000..ec5c2d40f665 --- /dev/null +++ b/lib/virtual_oss/null/Makefile @@ -0,0 +1,10 @@ +SHLIB_NAME= voss_null.so +SHLIBDIR= ${LIBDIR}/virtual_oss + +SRCS= null.c + +CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \ + -I${SRCTOP}/contrib/libsamplerate +LIBADD= samplerate + +.include <bsd.lib.mk> diff --git a/lib/virtual_oss/null/null.c b/lib/virtual_oss/null/null.c new file mode 100644 index 000000000000..149c6e3e8c6a --- /dev/null +++ b/lib/virtual_oss/null/null.c @@ -0,0 +1,102 @@ +/*- + * Copyright (c) 2015-2022 Hans Petter Selasky + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/queue.h> +#include <sys/filio.h> +#include <sys/soundcard.h> + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <err.h> +#include <time.h> + +#include "backend.h" +#include "int.h" + +static void +null_close(struct voss_backend *pbe __unused) +{ +} + +static int +null_open(struct voss_backend *pbe __unused, const char *devname __unused, + int samplerate __unused, int bufsize __unused, int *pchannels __unused, + int *pformat) +{ + int value[3]; + int i; + + value[0] = *pformat & VPREFERRED_SNE_AFMT; + value[1] = *pformat & VPREFERRED_SLE_AFMT; + value[2] = *pformat & VPREFERRED_SBE_AFMT; + + for (i = 0; i != 3; i++) { + if (value[i] == 0) + continue; + *pformat = value[i]; + return (0); + } + return (-1); +} + +static int +null_rec_transfer(struct voss_backend *pbe __unused, void *ptr, int len) +{ + + if (voss_has_synchronization == 0) + virtual_oss_wait(); + memset(ptr, 0, len); + return (len); +} + +static int +null_play_transfer(struct voss_backend *pbe __unused, void *ptr __unused, + int len) +{ + return (len); +} + +static void +null_delay(struct voss_backend *pbe __unused, int *pdelay) +{ + *pdelay = -1; +} + +struct voss_backend voss_backend_null_rec = { + .open = null_open, + .close = null_close, + .transfer = null_rec_transfer, + .delay = null_delay, +}; + +struct voss_backend voss_backend_null_play = { + .open = null_open, + .close = null_close, + .transfer = null_play_transfer, + .delay = null_delay, +}; diff --git a/lib/virtual_oss/oss/Makefile b/lib/virtual_oss/oss/Makefile new file mode 100644 index 000000000000..257d7f0c0bae --- /dev/null +++ b/lib/virtual_oss/oss/Makefile @@ -0,0 +1,10 @@ +SHLIB_NAME= voss_oss.so +SHLIBDIR= ${LIBDIR}/virtual_oss + +SRCS= oss.c + +CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \ + -I${SRCTOP}/contrib/libsamplerate +LIBADD= samplerate + +.include <bsd.lib.mk> diff --git a/lib/virtual_oss/oss/oss.c b/lib/virtual_oss/oss/oss.c new file mode 100644 index 000000000000..b4779f9108d9 --- /dev/null +++ b/lib/virtual_oss/oss/oss.c @@ -0,0 +1,197 @@ +/*- + * Copyright (c) 2015-2019 Hans Petter Selasky + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/queue.h> +#include <sys/filio.h> +#include <sys/soundcard.h> + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <err.h> +#include <poll.h> + +#include "backend.h" +#include "int.h" + +static int +oss_set_format(int fd, int *format) +{ + int value[6]; + int error; + int fmt; + int i; + + value[0] = *format & VPREFERRED_SNE_AFMT; + value[1] = *format & VPREFERRED_UNE_AFMT; + value[2] = *format & VPREFERRED_SLE_AFMT; + value[3] = *format & VPREFERRED_SBE_AFMT; + value[4] = *format & VPREFERRED_ULE_AFMT; + value[5] = *format & VPREFERRED_UBE_AFMT; + + for (i = 0; i != 6; i++) { + fmt = value[i]; + if (fmt == 0) + continue; + error = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt); + /* make sure we got the format we asked for */ + if (error == 0 && fmt == value[i]) { + *format = fmt; + return (0); + } + } + return (-1); +} + +static void +oss_close(struct voss_backend *pbe) +{ + if (pbe->fd > -1) { + close(pbe->fd); + pbe->fd = -1; + } +} + +static int +oss_open(struct voss_backend *pbe, const char *devname, int samplerate, + int bufsize, int *pchannels, int *pformat, int attr, int fionbio) +{ + int temp; + int err; + + pbe->fd = open(devname, attr); + if (pbe->fd < 0) { + warn("Could not open DSP device '%s'", devname); + return (-1); + } + err = ioctl(pbe->fd, FIONBIO, &fionbio); + if (err < 0) { + warn("Could not set blocking mode on DSP"); + goto error; + } + err = oss_set_format(pbe->fd, pformat); + if (err < 0) { + warn("Could not set sample format 0x%08x", *pformat); + goto error; + } + temp = *pchannels; + bufsize /= temp; /* get buffer size per channel */ + do { + err = ioctl(pbe->fd, SOUND_PCM_WRITE_CHANNELS, &temp); + } while (err < 0 && --temp > 0); + + err = ioctl(pbe->fd, SOUND_PCM_READ_CHANNELS, &temp); + if (err < 0 || temp <= 0 || temp > *pchannels) { + warn("Could not set DSP channels: %d / %d", temp, *pchannels); + goto error; + } + *pchannels = temp; + + temp = samplerate; + err = ioctl(pbe->fd, SNDCTL_DSP_SPEED, &temp); + if (err < 0 || temp != samplerate) { + warn("Could not set sample rate to %d / %d Hz", temp, samplerate); + goto error; + } + + temp = bufsize * (*pchannels); + err = ioctl(pbe->fd, SNDCTL_DSP_SETBLKSIZE, &temp); + if (err < 0) { + warn("Could not set block size to %d", temp); + goto error; + } + return (0); +error: + close(pbe->fd); + pbe->fd = -1; + return (-1); +} + +static int +oss_rec_open(struct voss_backend *pbe, const char *devname, int samplerate, + int bufsize, int *pchannels, int *pformat) +{ + return (oss_open(pbe, devname, samplerate, bufsize, pchannels, pformat, O_RDONLY, 0)); +} + +static int +oss_play_open(struct voss_backend *pbe, const char *devname, int samplerate, + int bufsize, int *pchannels, int *pformat) +{ + bufsize *= 4; /* XXX allow extra space for jitter */ + return (oss_open(pbe, devname, samplerate, bufsize, pchannels, pformat, O_WRONLY, 0)); +} + +static int +oss_rec_transfer(struct voss_backend *pbe, void *ptr, int len) +{ + struct pollfd fds = { .fd = pbe->fd, .events = POLLIN | POLLRDNORM }; + int err; + + /* wait at maximum 2 seconds for data, else something is wrong */ + err = poll(&fds, 1, 2000); + if (err < 1) + return (-1); + return (read(pbe->fd, ptr, len)); +} + +static int +oss_play_transfer(struct voss_backend *pbe, void *ptr, int len) +{ + return (write(pbe->fd, ptr, len)); +} + +static void +oss_rec_delay(struct voss_backend *pbe, int *pdelay) +{ + if (ioctl(pbe->fd, FIONREAD, pdelay) != 0) + *pdelay = -1; +} + +static void +oss_play_delay(struct voss_backend *pbe, int *pdelay) +{ + if (voss_has_synchronization != 0 || + ioctl(pbe->fd, SNDCTL_DSP_GETODELAY, pdelay) != 0) + *pdelay = -1; +} + +struct voss_backend voss_backend_oss_rec = { + .open = oss_rec_open, + .close = oss_close, + .transfer = oss_rec_transfer, + .delay = oss_rec_delay, + .fd = -1, +}; + +struct voss_backend voss_backend_oss_play = { + .open = oss_play_open, + .close = oss_close, + .transfer = oss_play_transfer, + .delay = oss_play_delay, + .fd = -1, +}; diff --git a/lib/virtual_oss/sndio/Makefile b/lib/virtual_oss/sndio/Makefile new file mode 100644 index 000000000000..9b5af63a3246 --- /dev/null +++ b/lib/virtual_oss/sndio/Makefile @@ -0,0 +1,12 @@ +SHLIB_NAME= voss_sndio.so +SHLIBDIR= ${LIBDIR}/virtual_oss + +SRCS= sndio.c + +CFLAGS+= -I${SRCTOP}/usr.sbin/virtual_oss/virtual_oss \ + -I${SRCTOP}/contrib/libsamplerate \ + -I${LOCALBASE:U/usr/local}/include +LDFLAGS+= -L${LOCALBASE:U/usr/local}/lib -lsndio +LIBADD= samplerate + +.include <bsd.lib.mk> diff --git a/lib/virtual_oss/sndio/sndio.c b/lib/virtual_oss/sndio/sndio.c new file mode 100644 index 000000000000..2d1a3411049b --- /dev/null +++ b/lib/virtual_oss/sndio/sndio.c @@ -0,0 +1,203 @@ +/*- + * Copyright (c) 2021 Tim Creech <tcreech@tcreech.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/queue.h> +#include <sys/soundcard.h> + +#include <err.h> +#include <stdlib.h> +#include <string.h> + +#include <sndio.h> + +#include "backend.h" +#include "int.h" + +static struct sio_hdl * +get_sio_hdl(struct voss_backend *pbe) +{ + if (pbe) + return (pbe->arg); + + return (NULL); +} + +static void +sndio_close(struct voss_backend *pbe) +{ + if (!pbe) + return; + + if (get_sio_hdl(pbe)) + sio_close(get_sio_hdl(pbe)); +} + +static int +sndio_get_signedness(int *fmt) +{ + int s_fmt = *fmt & (VPREFERRED_SLE_AFMT | VPREFERRED_SBE_AFMT); + + if (s_fmt) { + *fmt = s_fmt; + return (1); + } + *fmt = *fmt & (VPREFERRED_ULE_AFMT | VPREFERRED_UBE_AFMT); + return (0); +} + +static int +sndio_get_endianness_is_le(int *fmt) +{ + int le_fmt = *fmt & (VPREFERRED_SLE_AFMT | VPREFERRED_ULE_AFMT); + + if (le_fmt) { + *fmt = le_fmt; + return (1); + } + *fmt = *fmt & (VPREFERRED_SBE_AFMT | VPREFERRED_UBE_AFMT); + return (0); +} + +static int +sndio_get_bits(int *fmt) +{ + if (*fmt & AFMT_16BIT) + return (16); + if (*fmt & AFMT_24BIT) + return (24); + if (*fmt & AFMT_32BIT) + return (32); + if (*fmt & AFMT_8BIT) + return (8); + return (-1); + /* TODO AFMT_BIT */ +} + +static int +sndio_open(struct voss_backend *pbe, const char *devname, + int samplerate, int bufsize, int *pchannels, int *pformat, int direction) +{ + const char *sndio_name = devname + strlen("/dev/sndio/"); + + int sig = sndio_get_signedness(pformat); + int le = sndio_get_endianness_is_le(pformat); + int bits = sndio_get_bits(pformat); + + if (bits == -1) { + warn("unsupported format precision"); + return (-1); + } + + struct sio_hdl *hdl = sio_open(sndio_name, direction, 0); + + if (hdl == 0) { + warn("sndio: failed to open device"); + return (-1); + } + + struct sio_par par; + + sio_initpar(&par); + par.pchan = *pchannels; + par.sig = sig; + par.bits = bits; + par.bps = SIO_BPS(bits); + par.le = le; + par.rate = samplerate; + par.appbufsz = bufsize; + par.xrun = SIO_SYNC; + if (!sio_setpar(hdl, &par)) + errx(1, "internal error, sio_setpar() failed"); + if (!sio_getpar(hdl, &par)) + errx(1, "internal error, sio_getpar() failed"); + if ((int)par.pchan != *pchannels) + errx(1, "couldn't set number of channels"); + if ((int)par.sig != sig || (int)par.bits != bits || (int)par.le != le) + errx(1, "couldn't set format"); + if ((int)par.bits != bits) + errx(1, "couldn't set precision"); + if ((int)par.rate < samplerate * 995 / 1000 || + (int)par.rate > samplerate * 1005 / 1000) + errx(1, "couldn't set rate"); + if (par.xrun != SIO_SYNC) + errx(1, "couldn't set xun policy"); + + /* Save the device handle with the backend */ + pbe->arg = hdl; + + /* Start the device. */ + if (!sio_start(hdl)) + errx(1, "couldn't start device"); + + return (0); +} + +static int +sndio_open_play(struct voss_backend *pbe, const char *devname, + int samplerate, int bufsize, int *pchannels, int *pformat) +{ + return (sndio_open(pbe, devname, samplerate, bufsize, pchannels, pformat, SIO_PLAY)); +} + +static int +sndio_open_rec(struct voss_backend *pbe, const char *devname, + int samplerate, int bufsize, int *pchannels, int *pformat) +{ + return (sndio_open(pbe, devname, samplerate, bufsize, pchannels, pformat, SIO_REC)); +} + +static int +sndio_play_transfer(struct voss_backend *pbe, void *ptr, int len) +{ + return (sio_write(get_sio_hdl(pbe), ptr, len)); +} + +static int +sndio_rec_transfer(struct voss_backend *pbe, void *ptr, int len) +{ + return (sio_read(get_sio_hdl(pbe), ptr, len)); +} + +static void +sndio_delay(struct voss_backend *pbe __unused, int *pdelay) +{ + *pdelay = -1; +} + +struct voss_backend voss_backend_sndio_rec = { + .open = sndio_open_rec, + .close = sndio_close, + .transfer = sndio_rec_transfer, + .delay = sndio_delay, + .fd = -1, +}; + +struct voss_backend voss_backend_sndio_play = { + .open = sndio_open_play, + .close = sndio_close, + .transfer = sndio_play_transfer, + .delay = sndio_delay, + .fd = -1, +}; |