sync with OpenBSD -current

This commit is contained in:
purplerain 2024-09-06 01:21:03 +00:00
parent 9b453b8087
commit d592c28c93
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
298 changed files with 9365 additions and 4443 deletions

View file

@ -30,6 +30,60 @@
!! THANK YOU! Sebastian Pipping -- Berlin, 2024-03-09 !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Release 2.6.3 Wed September 4 2024
Security fixes:
#887 #890 CVE-2024-45490 -- Calling function XML_ParseBuffer with
len < 0 without noticing and then calling XML_GetBuffer
will have XML_ParseBuffer fail to recognize the problem
and XML_GetBuffer corrupt memory.
With the fix, XML_ParseBuffer now complains with error
XML_ERROR_INVALID_ARGUMENT just like sibling XML_Parse
has been doing since Expat 2.2.1, and now documented.
Impact is denial of service to potentially artitrary code
execution.
#888 #891 CVE-2024-45491 -- Internal function dtdCopy can have an
integer overflow for nDefaultAtts on 32-bit platforms
(where UINT_MAX equals SIZE_MAX).
Impact is denial of service to potentially artitrary code
execution.
#889 #892 CVE-2024-45492 -- Internal function nextScaffoldPart can
have an integer overflow for m_groupSize on 32-bit
platforms (where UINT_MAX equals SIZE_MAX).
Impact is denial of service to potentially artitrary code
execution.
Other changes:
#851 #879 Autotools: Sync CMake templates with CMake 3.28
#853 Autotools: Always provide path to find(1) for portability
#861 Autotools: Ensure that the m4 directory always exists.
#870 Autotools: Simplify handling of SIZEOF_VOID_P
#869 Autotools: Support non-GNU sed
#856 Autotools|CMake: Fix main() to main(void)
#865 Autotools|CMake: Fix compile tests for HAVE_SYSCALL_GETRANDOM
#863 Autotools|CMake: Stop requiring dos2unix
#854 #855 CMake: Fix check for symbols size_t and off_t
#864 docs|tests: Convert README to Markdown and update
#741 Windows: Drop support for Visual Studio <=15.0/2017
#886 Drop needless XML_DTD guards around is_param access
#885 Fix typo in a code comment
#894 #896 Version info bumped from 10:2:9 (libexpat*.so.1.9.2)
to 10:3:9 (libexpat*.so.1.9.3); see https://verbump.de/
for what these numbers do
Infrastructure:
#880 Readme: Promote the call for help
#868 CI: Fix various issues
#849 CI: Allow triggering GitHub Actions workflows manually
#851 #872 ..
#873 #879 CI: Adapt to breaking changes in GitHub Actions
Special thanks to:
Alexander Bluhm
Berkay Eren Ürün
Dag-Erling Smørgrav
Ferenc Géczi
TaiYou
Release 2.6.2 Wed March 13 2024
Security fixes:
#839 #842 CVE-2024-28757 -- Prevent billion laughs attacks with

View file

@ -4,8 +4,14 @@
[![Downloads SourceForge](https://img.shields.io/sourceforge/dt/expat?label=Downloads%20SourceForge)](https://sourceforge.net/projects/expat/files/)
[![Downloads GitHub](https://img.shields.io/github/downloads/libexpat/libexpat/total?label=Downloads%20GitHub)](https://github.com/libexpat/libexpat/releases)
> [!CAUTION]
>
> Expat is **understaffed** and without funding.
> There is a [call for help with details](https://github.com/libexpat/libexpat/blob/master/expat/Changes)
> at the top of the `Changes` file.
# Expat, Release 2.6.2
# Expat, Release 2.6.3
This is Expat, a C99 library for parsing
[XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by
@ -20,7 +26,7 @@ Expat supports the following compilers:
- GNU GCC >=4.5
- LLVM Clang >=3.5
- Microsoft Visual Studio >=15.0/2017 (rolling `${today} minus 5 years`)
- Microsoft Visual Studio >=16.0/2019 (rolling `${today} minus 5 years`)
Windows users can use the
[`expat-win32bin-*.*.*.{exe,zip}` download](https://github.com/libexpat/libexpat/releases),
@ -158,10 +164,10 @@ support this mode of compilation (yet):
1. Mass-patch `Makefile.am` files to use `libexpatw.la` for a library name:
<br/>
`find -name Makefile.am -exec sed
`find . -name Makefile.am -exec sed
-e 's,libexpat\.la,libexpatw.la,'
-e 's,libexpat_la,libexpatw_la,'
-i {} +`
-i.bak {} +`
1. Run `automake` to re-write `Makefile.in` files:<br/>
`automake`

View file

@ -52,7 +52,7 @@
<div>
<h1>
The Expat XML Parser
<small>Release 2.6.2</small>
<small>Release 2.6.3</small>
</h1>
</div>
<div class="content">
@ -319,7 +319,7 @@ directions in the next section. Otherwise if you have Microsoft's
Developer Studio installed,
you can use CMake to generate a <code>.sln</code> file, e.g.
<code>
cmake -G"Visual Studio 15 2017" -DCMAKE_BUILD_TYPE=RelWithDebInfo .
cmake -G"Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=RelWithDebInfo .
</code>, and build Expat using <code>msbuild /m expat.sln</code> after.</p>
<p>Alternatively, you may download the Win32 binary package that
@ -1135,7 +1135,9 @@ containing part (or perhaps all) of the document. The number of bytes of s
that are part of the document is indicated by <code>len</code>. This means
that <code>s</code> doesn't have to be null-terminated. It also means that
if <code>len</code> is larger than the number of bytes in the block of
memory that <code>s</code> points at, then a memory fault is likely. The
memory that <code>s</code> points at, then a memory fault is likely.
Negative values for <code>len</code> are rejected since Expat 2.2.1.
The
<code>isFinal</code> parameter informs the parser that this is the last
piece of the document. Frequently, the last piece is empty (i.e.
<code>len</code> is zero.)
@ -1183,11 +1185,17 @@ XML_ParseBuffer(XML_Parser p,
int isFinal);
</pre>
<div class="fcndef">
<p>
This is just like <code><a href= "#XML_Parse" >XML_Parse</a></code>,
except in this case Expat provides the buffer. By obtaining the
buffer from Expat with the <code><a href= "#XML_GetBuffer"
>XML_GetBuffer</a></code> function, the application can avoid double
copying of the input.
</p>
<p>
Negative values for <code>len</code> are rejected since Expat 2.6.3.
</p>
</div>
<h4 id="XML_GetBuffer">XML_GetBuffer</h4>

View file

@ -1066,7 +1066,7 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
*/
#define XML_MAJOR_VERSION 2
#define XML_MINOR_VERSION 6
#define XML_MICRO_VERSION 2
#define XML_MICRO_VERSION 3
#ifdef __cplusplus
}

View file

@ -126,8 +126,7 @@
| ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) \
| ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
#define SIPHASH_INITIALIZER \
{ 0, 0, 0, 0, {0}, 0, 0 }
#define SIPHASH_INITIALIZER {0, 0, 0, 0, {0}, 0, 0}
struct siphash {
uint64_t v0, v1, v2, v3;

View file

@ -1,4 +1,4 @@
/* 2a14271ad4d35e82bde8ba210b4edb7998794bcbae54deab114046a300f9639a (2.6.2+)
/* ba4cdf9bdb534f355a9def4c9e25d20ee8e72f95b0a4d930be52e563f5080196 (2.6.3+)
__ __ _
___\ \/ /_ __ __ _| |_
/ _ \\ /| '_ \ / _` | __|
@ -39,6 +39,7 @@
Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
Copyright (c) 2023 Owain Davies <owaind@bath.edu>
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
Copyright (c) 2024 Berkay Eren Ürün <berkay.ueruen@siemens.com>
Licensed under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining
@ -294,7 +295,7 @@ typedef struct {
The name of the element is stored in both the document and API
encodings. The memory buffer 'buf' is a separately-allocated
memory area which stores the name. During the XML_Parse()/
XMLParseBuffer() when the element is open, the memory for the 'raw'
XML_ParseBuffer() when the element is open, the memory for the 'raw'
version of the name (in the document encoding) is shared with the
document buffer. If the element is open across calls to
XML_Parse()/XML_ParseBuffer(), the buffer is re-allocated to
@ -2038,6 +2039,12 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal) {
if (parser == NULL)
return XML_STATUS_ERROR;
if (len < 0) {
parser->m_errorCode = XML_ERROR_INVALID_ARGUMENT;
return XML_STATUS_ERROR;
}
switch (parser->m_parsingStatus.parsing) {
case XML_SUSPENDED:
parser->m_errorCode = XML_ERROR_SUSPENDED;
@ -5846,18 +5853,17 @@ processInternalEntity(XML_Parser parser, ENTITY *entity, XML_Bool betweenDecl) {
/* Set a safe default value in case 'next' does not get set */
next = textStart;
#ifdef XML_DTD
if (entity->is_param) {
int tok
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
tok, next, &next, XML_FALSE, XML_FALSE,
XML_ACCOUNT_ENTITY_EXPANSION);
} else
#endif /* XML_DTD */
} else {
result = doContent(parser, parser->m_tagLevel, parser->m_internalEncoding,
textStart, textEnd, &next, XML_FALSE,
XML_ACCOUNT_ENTITY_EXPANSION);
}
if (result == XML_ERROR_NONE) {
if (textEnd != next && parser->m_parsingStatus.parsing == XML_SUSPENDED) {
@ -5894,18 +5900,17 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
/* Set a safe default value in case 'next' does not get set */
next = textStart;
#ifdef XML_DTD
if (entity->is_param) {
int tok
= XmlPrologTok(parser->m_internalEncoding, textStart, textEnd, &next);
result = doProlog(parser, parser->m_internalEncoding, textStart, textEnd,
tok, next, &next, XML_FALSE, XML_TRUE,
XML_ACCOUNT_ENTITY_EXPANSION);
} else
#endif /* XML_DTD */
} else {
result = doContent(parser, openEntity->startTagLevel,
parser->m_internalEncoding, textStart, textEnd, &next,
XML_FALSE, XML_ACCOUNT_ENTITY_EXPANSION);
}
if (result != XML_ERROR_NONE)
return result;
@ -5932,7 +5937,6 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
return XML_ERROR_NONE;
}
#ifdef XML_DTD
if (entity->is_param) {
int tok;
parser->m_processor = prologProcessor;
@ -5940,9 +5944,7 @@ internalEntityProcessor(XML_Parser parser, const char *s, const char *end,
return doProlog(parser, parser->m_encoding, s, end, tok, next, nextPtr,
(XML_Bool)! parser->m_parsingStatus.finalBuffer, XML_TRUE,
XML_ACCOUNT_DIRECT);
} else
#endif /* XML_DTD */
{
} else {
parser->m_processor = contentProcessor;
/* see externalEntityContentProcessor vs contentProcessor */
result = doContent(parser, parser->m_parentParser ? 1 : 0,
@ -7016,6 +7018,16 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd,
if (! newE)
return 0;
if (oldE->nDefaultAtts) {
/* Detect and prevent integer overflow.
* The preprocessor guard addresses the "always false" warning
* from -Wtype-limits on platforms where
* sizeof(int) < sizeof(size_t), e.g. on x86_64. */
#if UINT_MAX >= SIZE_MAX
if ((size_t)oldE->nDefaultAtts
> ((size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE))) {
return 0;
}
#endif
newE->defaultAtts
= ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
if (! newE->defaultAtts) {
@ -7558,6 +7570,15 @@ nextScaffoldPart(XML_Parser parser) {
int next;
if (! dtd->scaffIndex) {
/* Detect and prevent integer overflow.
* The preprocessor guard addresses the "always false" warning
* from -Wtype-limits on platforms where
* sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
#if UINT_MAX >= SIZE_MAX
if (parser->m_groupSize > ((size_t)(-1) / sizeof(int))) {
return -1;
}
#endif
dtd->scaffIndex = (int *)MALLOC(parser, parser->m_groupSize * sizeof(int));
if (! dtd->scaffIndex)
return -1;

View file

@ -2804,6 +2804,61 @@ START_TEST(test_empty_parse) {
}
END_TEST
/* Test XML_Parse for len < 0 */
START_TEST(test_negative_len_parse) {
const char *const doc = "<root/>";
for (int isFinal = 0; isFinal < 2; isFinal++) {
set_subtest("isFinal=%d", isFinal);
XML_Parser parser = XML_ParserCreate(NULL);
if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
fail("There was not supposed to be any initial parse error.");
const enum XML_Status status = XML_Parse(parser, doc, -1, isFinal);
if (status != XML_STATUS_ERROR)
fail("Negative len was expected to fail the parse but did not.");
if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT)
fail("Parse error does not match XML_ERROR_INVALID_ARGUMENT.");
XML_ParserFree(parser);
}
}
END_TEST
/* Test XML_ParseBuffer for len < 0 */
START_TEST(test_negative_len_parse_buffer) {
const char *const doc = "<root/>";
for (int isFinal = 0; isFinal < 2; isFinal++) {
set_subtest("isFinal=%d", isFinal);
XML_Parser parser = XML_ParserCreate(NULL);
if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
fail("There was not supposed to be any initial parse error.");
void *const buffer = XML_GetBuffer(parser, (int)strlen(doc));
if (buffer == NULL)
fail("XML_GetBuffer failed.");
memcpy(buffer, doc, strlen(doc));
const enum XML_Status status = XML_ParseBuffer(parser, -1, isFinal);
if (status != XML_STATUS_ERROR)
fail("Negative len was expected to fail the parse but did not.");
if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT)
fail("Parse error does not match XML_ERROR_INVALID_ARGUMENT.");
XML_ParserFree(parser);
}
}
END_TEST
/* Test odd corners of the XML_GetBuffer interface */
static enum XML_Status
get_feature(enum XML_FeatureEnum feature_id, long *presult) {
@ -5959,6 +6014,8 @@ make_basic_test_case(Suite *s) {
tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
tcase_add_test(tc_basic, test_empty_parse);
tcase_add_test(tc_basic, test_negative_len_parse);
tcase_add_test(tc_basic, test_negative_len_parse_buffer);
tcase_add_test(tc_basic, test_get_buffer_1);
tcase_add_test(tc_basic, test_get_buffer_2);
#if XML_CONTEXT_BYTES > 0

View file

@ -208,7 +208,7 @@ START_TEST(test_misc_version) {
if (! versions_equal(&read_version, &parsed_version))
fail("Version mismatch");
if (xcstrcmp(version_text, XCS("expat_2.6.2"))) /* needs bump on releases */
if (xcstrcmp(version_text, XCS("expat_2.6.3"))) /* needs bump on releases */
fail("XML_*_VERSION in expat.h out of sync?\n");
}
END_TEST

View file

@ -960,7 +960,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) {
while (state->have < 19)
state->lens[order[state->have++]] = 0;
state->next = state->codes;
state->lencode = (const code FAR *)(state->next);
state->lencode = state->distcode = (const code FAR *)(state->next);
state->lenbits = 7;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);

View file

@ -1,12 +1,8 @@
# $OpenBSD: Makefile,v 1.12 2022/10/14 17:09:43 tb Exp $
# $OpenBSD: Makefile,v 1.14 2024/09/04 04:35:30 tb Exp $
SUBDIR += libressl
.if exists(/usr/local/bin/eopenssl11)
SUBDIR += openssl11
.else
.END:
@echo 'Run "pkg_add openssl--%1.1" to run tests against OpenSSL 1.1'
@echo SKIPPED
.if exists(/usr/local/bin/eopenssl32)
SUBDIR += openssl
.endif
.include <bsd.subdir.mk>

View file

@ -0,0 +1,10 @@
# $OpenBSD: Makefile,v 1.1 2024/09/04 04:34:14 tb Exp $
EOPENSSL = eopenssl32
LDADD += -Wl,-rpath,/usr/local/lib/${EOPENSSL} -L/usr/local/lib/${EOPENSSL}
CFLAGS += -I${.CURDIR}/ -I/usr/local/include/${EOPENSSL}/
.PATH: ${.CURDIR}/..
.include <bsd.regress.mk>

View file

@ -0,0 +1,29 @@
/* $OpenBSD: unistd.h,v 1.2 2024/09/04 07:52:45 tb Exp $ */
/*
* Public domain
* compatibility shim for OpenSSL 3
* overloading unistd.h is a ugly guly hack for this issue but works here
*/
#include_next <unistd.h>
#include <openssl/cms.h>
#include <openssl/stack.h>
#ifndef DECLARE_STACK_OF
#define DECLARE_STACK_OF DEFINE_STACK_OF
#endif
static inline int
CMS_get_version(CMS_ContentInfo *cms, long *version)
{
*version = 3;
return 1;
}
static inline int
CMS_SignerInfo_get_version(CMS_SignerInfo *si, long *version)
{
*version = 3;
return 1;
}

View file

@ -1,8 +0,0 @@
# $OpenBSD: Makefile,v 1.18 2023/05/22 15:20:16 tb Exp $
LDADD += -Wl,-rpath,/usr/local/lib/eopenssl11 -L/usr/local/lib/eopenssl11
CFLAGS += -I${.CURDIR}/ -I/usr/local/include/eopenssl11/
.PATH: ${.CURDIR}/..
.include <bsd.regress.mk>

View file

@ -1,16 +0,0 @@
/*
* Public domain
* compatibility shim for openssl11
* overloading unistd.h is a ugly guly hack for this issue but works here
*/
#include_next <unistd.h>
#include <openssl/stack.h>
#define CMS_get_version(cms, version) (*(version) = 3, 1)
#define CMS_SignerInfo_get_version(si, version) (*(version) = 3, 1)
#ifndef DECLARE_STACK_OF
#define DECLARE_STACK_OF DEFINE_STACK_OF
#endif

View file

@ -1,4 +1,4 @@
/* $OpenBSD: frontend.c,v 1.82 2024/08/09 19:43:26 florian Exp $ */
/* $OpenBSD: frontend.c,v 1.83 2024/09/05 08:22:46 florian Exp $ */
/*
* Copyright (c) 2018 Florian Obser <florian@openbsd.org>
@ -773,7 +773,7 @@ handle_query(struct pending_query *pq)
}
rcode = parse_edns_from_query_pkt(pq->qbuf, &pq->edns, NULL, NULL,
NULL, 0, pq->region);
NULL, 0, pq->region, NULL);
if (rcode != LDNS_RCODE_NOERROR) {
error_answer(pq, rcode);
goto send_answer;
@ -1059,7 +1059,7 @@ resend_dns64_query(struct pending_query *opq)
}
rcode = parse_edns_from_query_pkt(pq->qbuf, &pq->edns, NULL, NULL,
NULL, 0, pq->region);
NULL, 0, pq->region, NULL);
if (rcode != LDNS_RCODE_NOERROR) {
error_answer(pq, rcode);
goto send_answer;

View file

@ -1,6 +1,9 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* apply the fallthrough attribute. */
#define ATTR_FALLTHROUGH __attribute__((fallthrough));
/* apply the noreturn attribute to a function that exits the program */
#define ATTR_NORETURN __attribute__((__noreturn__))
@ -58,6 +61,9 @@
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Whether the C compiler accepts the "fallthrough" attribute */
#define HAVE_ATTR_FALLTHROUGH 1
/* Whether the C compiler accepts the "format" attribute */
#define HAVE_ATTR_FORMAT 1
@ -407,6 +413,9 @@
/* 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 */
@ -567,6 +576,9 @@
function. */
/* #undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB */
/* 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 HAVE_SSL_GET0_ALPN_SELECTED 1
@ -779,7 +791,7 @@
#define PACKAGE_NAME "unbound"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "unbound 1.20.0"
#define PACKAGE_STRING "unbound 1.21.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unbound"
@ -788,7 +800,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.20.0"
#define PACKAGE_VERSION "1.21.0"
/* default pidfile location */
#define PIDFILE ""
@ -811,7 +823,7 @@
#define ROOT_CERT_FILE "/var/unbound/etc/icannbundle.pem"
/* version number for resource files */
#define RSRC_PACKAGE_VERSION 1,20,0,0
#define RSRC_PACKAGE_VERSION 1,21,0,0
/* Directory to chdir to */
#define RUN_DIR "/var/unbound/etc"
@ -1485,6 +1497,7 @@ 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__)
void *unbound_stat_malloc(size_t size);
void *unbound_stat_calloc(size_t nmemb, size_t size);
void unbound_stat_free(void *ptr);
@ -1497,6 +1510,8 @@ 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);
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 */

View file

@ -701,6 +701,7 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
iq->state = DNS64_NEW_QUERY;
iq->started_no_cache_store = qstate->no_cache_store;
qstate->no_cache_store = 1;
ATTR_FALLTHROUGH
/* fallthrough */
case module_event_pass:
qstate->ext_state[id] = handle_event_pass(qstate, id);
@ -1044,8 +1045,8 @@ dns64_get_mem(struct module_env* env, int id)
*/
static struct module_func_block dns64_block = {
"dns64",
&dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super,
&dns64_clear, &dns64_get_mem
NULL, NULL, &dns64_init, &dns64_deinit, &dns64_operate,
&dns64_inform_super, &dns64_clear, &dns64_get_mem
};
/**

View file

@ -39,6 +39,7 @@
#ifdef USE_DNSTAP
#include "util/locks.h"
struct config_file;
struct sldns_buffer;
struct dt_msg_queue;
@ -75,6 +76,13 @@ struct dt_env {
unsigned log_forwarder_query_messages : 1;
/** whether to log Message/FORWARDER_RESPONSE */
unsigned log_forwarder_response_messages : 1;
/** lock on sample count */
lock_basic_type sample_lock;
/** rate limit value from config, samples 1/N messages */
unsigned int sample_rate;
/** rate limit counter */
unsigned int sample_rate_count;
};
/**

View file

@ -367,6 +367,47 @@ type_allowed_in_additional_section(uint16_t tp)
return 0;
}
/** Shorten RRset */
static void
shorten_rrset(sldns_buffer* pkt, struct rrset_parse* rrset, int count)
{
/* The too large NS RRset is shortened. This is so that too large
* content does not overwhelm the cache. It may make the rrset
* bogus if it was signed, and then the domain is not resolved any
* more, that is okay, the NS RRset was too large. During a referral
* it can be shortened and then the first part of the list could
* be used to resolve. The scrub continues to disallow glue for the
* removed nameserver RRs and removes that too. Because the glue
* is not marked as okay, since the RRs have been removed here. */
int i;
struct rr_parse* rr = rrset->rr_first, *prev = NULL;
if(!rr)
return;
for(i=0; i<count; i++) {
prev = rr;
rr = rr->next;
if(!rr)
return; /* The RRset is already short. */
}
if(verbosity >= VERB_QUERY
&& rrset->dname_len <= LDNS_MAX_DOMAINLEN) {
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
dname_pkt_copy(pkt, buf, rrset->dname);
log_nametypeclass(VERB_QUERY, "normalize: shorten RRset:", buf,
rrset->type, ntohs(rrset->rrset_class));
}
/* remove further rrs */
rrset->rr_last = prev;
rrset->rr_count = count;
while(rr) {
rrset->size -= rr->size;
rr = rr->next;
}
if(rrset->rr_last)
rrset->rr_last->next = NULL;
else rrset->rr_first = NULL;
}
/**
* This routine normalizes a response. This includes removing "irrelevant"
* records from the answer and additional sections and (re)synthesizing
@ -387,6 +428,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
uint8_t* sname = qinfo->qname;
size_t snamelen = qinfo->qname_len;
struct rrset_parse* rrset, *prev, *nsset=NULL;
int cname_length = 0; /* number of CNAMEs, or DNAMEs */
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR &&
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN)
@ -401,6 +443,16 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
prev = NULL;
rrset = msg->rrset_first;
while(rrset && rrset->section == LDNS_SECTION_ANSWER) {
if(cname_length > 11 /* env->cfg.iter_scrub_cname */) {
/* Too many CNAMEs, or DNAMEs, from the authority
* server, scrub down the length to something
* shorter. This deletes everything after the limit
* is reached. The iterator is going to look up
* the content one by one anyway. */
remove_rrset("normalize: removing because too many cnames:",
pkt, msg, prev, &rrset);
continue;
}
if(rrset->type == LDNS_RR_TYPE_DNAME &&
pkt_strict_sub(pkt, sname, rrset->dname)) {
/* check if next rrset is correct CNAME. else,
@ -420,6 +472,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"too long");
return 0;
}
cname_length++;
if(nx && nx->type == LDNS_RR_TYPE_CNAME &&
dname_pkt_compare(pkt, sname, nx->dname) == 0) {
/* check next cname */
@ -460,6 +513,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
if(rrset->type == LDNS_RR_TYPE_CNAME) {
struct rrset_parse* nx = rrset->rrset_all_next;
uint8_t* oldsname = sname;
cname_length++;
/* see if the next one is a DNAME, if so, swap them */
if(nx && nx->section == LDNS_SECTION_ANSWER &&
nx->type == LDNS_RR_TYPE_DNAME &&
@ -507,6 +561,10 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
LDNS_SECTION_ANSWER &&
dname_pkt_compare(pkt, oldsname,
rrset->dname) == 0) {
if(rrset->type == LDNS_RR_TYPE_NS &&
rrset->rr_count > 20 /* env->cfg->iter_scrub_ns */) {
shorten_rrset(pkt, rrset, 20 /* env->cfg->iter_scrub_ns */);
}
prev = rrset;
rrset = rrset->rrset_all_next;
}
@ -522,6 +580,11 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
continue;
}
if(rrset->type == LDNS_RR_TYPE_NS &&
rrset->rr_count > 20 /* env->cfg->iter_scrub_ns */) {
shorten_rrset(pkt, rrset, 20 /* env->cfg->iter_scrub_ns */);
}
/* Mark the additional names from relevant rrset as OK. */
/* only for RRsets that match the query name, other ones
* will be removed by sanitize, so no additional for them */
@ -578,6 +641,25 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
if(rrset->rr_count > 20 /* env->cfg->iter_scrub_ns */) {
/* If this is not a referral, and the NS RRset
* is signed, then remove it entirely, so
* that when it becomes bogus it does not
* make the message that is otherwise fine
* into a bogus message. */
if(!(msg->an_rrsets == 0 &&
FLAGS_GET_RCODE(msg->flags) ==
LDNS_RCODE_NOERROR &&
!soa_in_auth(msg) &&
!(msg->flags & BIT_AA)) &&
rrset->rrsig_count != 0) {
remove_rrset("normalize: removing too large NS "
"RRset:", pkt, msg, prev, &rrset);
continue;
} else {
shorten_rrset(pkt, rrset, 20 /* env->cfg->iter_scrub_ns */);
}
}
}
/* if this is type DS and we query for type DS we just got
* a referral answer for our type DS query, fix packet */

View file

@ -279,9 +279,10 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
name, namelen, qtype, &lame, &dnsseclame, &reclame,
&rtt, now)) {
log_addr(VERB_ALGO, "servselect", &a->addr, a->addrlen);
verbose(VERB_ALGO, " rtt=%d%s%s%s%s", rtt,
verbose(VERB_ALGO, " rtt=%d%s%s%s%s%s", rtt,
lame?" LAME":"",
dnsseclame?" DNSSEC_LAME":"",
a->dnsseclame?" ADDR_DNSSEC_LAME":"",
reclame?" REC_LAME":"",
a->lame?" ADDR_LAME":"");
if(lame)

View file

@ -760,6 +760,14 @@ target_count_increase_nx(struct iter_qstate* iq, int num)
iq->target_count[TARGET_COUNT_NX] += num;
}
static void
target_count_increase_global_quota(struct iter_qstate* iq, int num)
{
target_count_create(iq);
if(iq->target_count)
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA] += num;
}
/**
* Generate a subrequest.
* Generate a local request event. Local events are tied to this module, and
@ -1378,7 +1386,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
"restarts (eg. indirections)");
if(iq->qchase.qname)
errinf_dname(qstate, "stop at", iq->qchase.qname);
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
/* We enforce a maximum recursion/dependency depth -- in general,
@ -1560,6 +1568,11 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
errinf(qstate, "malloc failure for forward zone");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
if(!cache_fill_missing(qstate->env, iq->qchase.qclass,
qstate->region, iq->dp)) {
errinf(qstate, "malloc failure, copy extra info into delegation point");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
if((qstate->query_flags&BIT_RD)==0) {
/* If the server accepts RD=0 queries and forwards
* with RD=1, then if the server is listed as an NS
@ -1654,7 +1667,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
if(!iq->dp) {
log_err("internal error: no hints dp");
errinf(qstate, "no hints for this class");
return error_response(qstate, id,
return error_response_cache(qstate, id,
LDNS_RCODE_SERVFAIL);
}
iq->dp = delegpt_copy(iq->dp, qstate->region);
@ -1974,7 +1987,8 @@ generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq,
* if it is negative, there is no maximum number of targets.
* @param num: returns the number of queries generated and processed,
* which may be zero if there were no missing targets.
* @return false on error.
* @return 0 on success, nonzero on error. 1 means temporary failure and
* 2 means the failure can be cached.
*/
static int
query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
@ -1997,13 +2011,13 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
else toget = maxtargets;
if(toget == 0) {
*num = 0;
return 1;
return 0;
}
/* now that we are sure that a target query is going to be made,
* check the limits. */
if(iq->depth == ie->max_dependency_depth)
return 0;
return 1;
if(iq->depth > 0 && iq->target_count &&
iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) {
char s[LDNS_MAX_DOMAINLEN+1];
@ -2011,7 +2025,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"number of glue fetches %d", s,
iq->target_count[TARGET_COUNT_QUERIES]);
return 0;
return 2;
}
if(iq->dp_target_count > MAX_DP_TARGET_COUNT) {
char s[LDNS_MAX_DOMAINLEN+1];
@ -2019,7 +2033,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"number of glue fetches %d to a single delegation point",
s, iq->dp_target_count);
return 0;
return 2;
}
/* select 'toget' items from the total of 'missing' items */
@ -2048,7 +2062,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
*num = query_count;
if(query_count > 0)
qstate->ext_state[id] = module_wait_subquery;
return 0;
return 1;
}
query_count++;
/* If the mesh query list is full, exit the loop here.
@ -2057,9 +2071,17 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
* increase, because the spawned state uses cpu and a
* socket while this state waits for that spawned
* state. Next time we can look up further targets */
if(mesh_jostle_exceeded(qstate->env->mesh))
if(mesh_jostle_exceeded(qstate->env->mesh)) {
/* If no ip4 query is possible, that makes
* this ns resolved. */
if(!((ie->supports_ipv4 || ie->use_nat64) &&
((ns->lame && !ns->done_pside4) ||
(!ns->lame && !ns->got4)))) {
ns->resolved = 1;
}
break;
}
}
/* Send the A request. */
if((ie->supports_ipv4 || ie->use_nat64) &&
((ns->lame && !ns->done_pside4) ||
@ -2070,13 +2092,18 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
*num = query_count;
if(query_count > 0)
qstate->ext_state[id] = module_wait_subquery;
return 0;
return 1;
}
query_count++;
/* If the mesh query list is full, exit the loop. */
if(mesh_jostle_exceeded(qstate->env->mesh))
if(mesh_jostle_exceeded(qstate->env->mesh)) {
/* With the ip6 query already checked for,
* this makes the ns resolved. It is no longer
* a missing target. */
ns->resolved = 1;
break;
}
}
/* mark this target as in progress. */
ns->resolved = 1;
@ -2089,7 +2116,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
if(query_count > 0)
qstate->ext_state[id] = module_wait_subquery;
return 1;
return 0;
}
/**
@ -2180,12 +2207,14 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
}
/* query for an extra name added by the parent-NS record */
if(delegpt_count_missing_targets(iq->dp, NULL) > 0) {
int qs = 0;
int qs = 0, ret;
verbose(VERB_ALGO, "try parent-side target name");
if(!query_for_targets(qstate, iq, ie, id, 1, &qs)) {
if((ret=query_for_targets(qstate, iq, ie, id, 1, &qs))!=0) {
errinf(qstate, "could not fetch nameserver");
errinf_dname(qstate, "at zone", iq->dp->name);
if(ret == 1)
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
iq->num_target_queries += qs;
target_count_increase(iq, qs);
@ -2414,13 +2443,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
verbose(VERB_QUERY, "request has exceeded the maximum "
"number of referrrals with %d", iq->referral_count);
errinf(qstate, "exceeded the maximum of referrals");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
if(iq->sent_count > ie->max_sent_count) {
verbose(VERB_QUERY, "request has exceeded the maximum "
"number of sends with %d", iq->sent_count);
errinf(qstate, "exceeded the maximum number of sends");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
/* Check if we reached MAX_TARGET_NX limit without a fallback activation. */
@ -2450,7 +2479,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
"already present for the delegation point, no "
"fallback possible");
errinf(qstate, "exceeded the maximum nameserver nxdomains");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
verbose(VERB_ALGO, "initiating parent-side fallback for "
"nxdomain nameserver lookups");
@ -2493,7 +2522,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
"lookups (%d) with %d", MAX_TARGET_NX_FALLBACK,
iq->target_count[TARGET_COUNT_NX]);
errinf(qstate, "exceeded the maximum nameserver nxdomains");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
if(!iq->dp->has_parent_side_NS) {
@ -2707,7 +2736,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
verbose(VERB_ALGO, "auth zone lookup failed, no fallback,"
" servfail");
errinf(qstate, "auth zone lookup failed, fallback is off");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
if(iq->dp->auth_dp) {
/* we wanted to fallback, but had no delegpt, only the
@ -2736,11 +2765,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
/* if in 0x20 fallback get as many targets as possible */
if(iq->caps_fallback) {
int extra = 0;
int extra = 0, ret;
size_t naddr, nres, navail;
if(!query_for_targets(qstate, iq, ie, id, -1, &extra)) {
if((ret=query_for_targets(qstate, iq, ie, id, -1, &extra))!=0) {
errinf(qstate, "could not fetch nameservers for 0x20 fallback");
if(ret == 1)
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
iq->num_target_queries += extra;
target_count_increase(iq, extra);
@ -2883,15 +2914,18 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
* to distinguish between generating (a) new target
* query, or failing. */
if(delegpt_count_missing_targets(iq->dp, NULL) > 0) {
int qs = 0;
int qs = 0, ret;
verbose(VERB_ALGO, "querying for next "
"missing target");
if(!query_for_targets(qstate, iq, ie, id,
1, &qs)) {
if((ret=query_for_targets(qstate, iq, ie, id,
1, &qs))!=0) {
errinf(qstate, "could not fetch nameserver");
errinf_dname(qstate, "at zone", iq->dp->name);
if(ret == 1)
return error_response(qstate, id,
LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id,
LDNS_RCODE_SERVFAIL);
}
if(qs == 0 &&
delegpt_count_missing_targets(iq->dp, NULL) == 0){
@ -2902,6 +2936,17 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
* so this is not a loop. */
return 1;
}
if(qs == 0) {
/* There should be targets now, and
* if there are not, it should not
* wait for no targets. Stop it from
* waiting forever, or looping to
* here, as a safeguard. */
errinf(qstate, "could not generate nameserver lookups");
errinf_dname(qstate, "at zone", iq->dp->name);
return error_response(qstate, id,
LDNS_RCODE_SERVFAIL);
}
iq->num_target_queries += qs;
target_count_increase(iq, qs);
}
@ -2976,6 +3021,17 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
}
target_count_increase_global_quota(iq, 1);
if(iq->target_count && iq->target_count[TARGET_COUNT_GLOBAL_QUOTA]
> MAX_GLOBAL_QUOTA) {
char s[LDNS_MAX_DOMAINLEN+1];
dname_str(qstate->qinfo.qname, s);
verbose(VERB_QUERY, "request %s has exceeded the maximum "
"global quota on number of upstream queries %d", s,
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA]);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
/* Do not check ratelimit for forwarding queries or if we already got a
* pass. */
sq_check_ratelimit = (!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok);
@ -3025,7 +3081,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
qstate->was_ratelimited = 1;
errinf_dname(qstate, "exceeded ratelimit for zone",
iq->dp->name);
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
log_addr(VERB_QUERY, "error sending query to auth server",
&real_addr, real_addrlen);
@ -3247,7 +3303,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iter_scrub_nxdomain(iq->response);
return final_state(iq);
}
return error_response(qstate, id,
return error_response_cache(qstate, id,
LDNS_RCODE_SERVFAIL);
}
/* Best effort qname-minimisation.
@ -3582,7 +3638,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
" fallback possible, servfail");
errinf_dname(qstate, "response is bad, no fallback, "
"for auth zone", iq->dp->name);
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
verbose(VERB_ALGO, "auth zone response was bad, "
"fallback enabled");
@ -3990,7 +4046,7 @@ processCollectClass(struct module_qstate* qstate, int id)
if(iq->num_current_queries == 0) {
verbose(VERB_ALGO, "No root hints or fwds, giving up "
"on qclass ANY");
return error_response(qstate, id, LDNS_RCODE_REFUSED);
return error_response_cache(qstate, id, LDNS_RCODE_REFUSED);
}
/* return false, wait for queries to return */
}
@ -4357,7 +4413,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
"getting different replies, failed");
outbound_list_remove(&iq->outlist, outbound);
errinf(qstate, "0x20 failed, then got different replies in fallback");
(void)error_response(qstate, id,
(void)error_response_cache(qstate, id,
LDNS_RCODE_SERVFAIL);
return;
}
@ -4457,8 +4513,8 @@ iter_get_mem(struct module_env* env, int id)
*/
static struct module_func_block iter_block = {
"iterator",
&iter_init, &iter_deinit, &iter_operate, &iter_inform_super,
&iter_clear, &iter_get_mem
NULL, NULL, &iter_init, &iter_deinit, &iter_operate,
&iter_inform_super, &iter_clear, &iter_get_mem
};
struct module_func_block*

View file

@ -55,6 +55,9 @@ struct rbtree_type;
/** max number of targets spawned for a query and its subqueries */
#define MAX_TARGET_COUNT 64
/** max number of upstream queries for a query and its subqueries, it is
* never reset. */
#define MAX_GLOBAL_QUOTA 128
/** max number of target lookups per qstate, per delegation point */
#define MAX_DP_TARGET_COUNT 16
/** max number of nxdomains allowed for target lookups for a query and
@ -248,6 +251,9 @@ enum target_count_variables {
TARGET_COUNT_QUERIES,
/** Number of nxdomain responses encountered. */
TARGET_COUNT_NX,
/** Global quota on number of queries to upstream servers per
* client request, that is never reset. */
TARGET_COUNT_GLOBAL_QUOTA,
/** This should stay last here, it is used for the allocation */
TARGET_COUNT_MAX,

View file

@ -75,7 +75,9 @@ context_finalize(struct ub_ctx* ctx)
ctx->pipe_pid = getpid();
cfg_apply_local_port_policy(cfg, 65536);
config_apply(cfg);
if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
if(!modstack_call_startup(&ctx->mods, cfg->module_conf, ctx->env))
return UB_INITFAIL;
if(!modstack_call_init(&ctx->mods, cfg->module_conf, ctx->env))
return UB_INITFAIL;
listen_setup_locks();
log_edns_known_options(VERB_ALGO, ctx->env);

View file

@ -188,7 +188,9 @@ ub_ctx_create(void)
int e = errno;
ub_randfree(ctx->seed_rnd);
config_delete(ctx->env->cfg);
modstack_desetup(&ctx->mods, ctx->env);
modstack_call_deinit(&ctx->mods, ctx->env);
modstack_call_destartup(&ctx->mods, ctx->env);
modstack_free(&ctx->mods);
listen_desetup_locks();
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
@ -202,7 +204,9 @@ ub_ctx_create(void)
tube_delete(ctx->qq_pipe);
ub_randfree(ctx->seed_rnd);
config_delete(ctx->env->cfg);
modstack_desetup(&ctx->mods, ctx->env);
modstack_call_deinit(&ctx->mods, ctx->env);
modstack_call_destartup(&ctx->mods, ctx->env);
modstack_free(&ctx->mods);
listen_desetup_locks();
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
@ -360,7 +364,9 @@ ub_ctx_delete(struct ub_ctx* ctx)
}
libworker_delete_event(ctx->event_worker);
modstack_desetup(&ctx->mods, ctx->env);
modstack_call_deinit(&ctx->mods, ctx->env);
modstack_call_destartup(&ctx->mods, ctx->env);
modstack_free(&ctx->mods);
a = ctx->alloc_list;
while(a) {
na = a->super;
@ -981,7 +987,8 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
if(!addr) {
/* disable fwd mode - the root stub should be first. */
if(ctx->env->cfg->forwards &&
strcmp(ctx->env->cfg->forwards->name, ".") == 0) {
(ctx->env->cfg->forwards->name &&
strcmp(ctx->env->cfg->forwards->name, ".") == 0)) {
s = ctx->env->cfg->forwards;
ctx->env->cfg->forwards = s->next;
s->next = NULL;
@ -1001,7 +1008,8 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
/* it parses, add root stub in front of list */
lock_basic_lock(&ctx->cfglock);
if(!ctx->env->cfg->forwards ||
strcmp(ctx->env->cfg->forwards->name, ".") != 0) {
(ctx->env->cfg->forwards->name &&
strcmp(ctx->env->cfg->forwards->name, ".") != 0)) {
s = calloc(1, sizeof(*s));
if(!s) {
lock_basic_unlock(&ctx->cfglock);
@ -1019,6 +1027,7 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
ctx->env->cfg->forwards = s;
} else {
log_assert(ctx->env->cfg->forwards);
log_assert(ctx->env->cfg->forwards->name);
s = ctx->env->cfg->forwards;
}
dupl = strdup(addr);

View file

@ -292,6 +292,7 @@ libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len)
log_err("unknown command for bg worker %d",
(int)context_serial_getcmd(msg, len));
/* and fall through to quit */
ATTR_FALLTHROUGH
/* fallthrough */
case UB_LIBCMD_QUIT:
free(msg);

View file

@ -1259,8 +1259,8 @@ respip_get_mem(struct module_env* env, int id)
*/
static struct module_func_block respip_block = {
"respip",
&respip_init, &respip_deinit, &respip_operate, &respip_inform_super,
&respip_clear, &respip_get_mem
NULL, NULL, &respip_init, &respip_deinit, &respip_operate,
&respip_inform_super, &respip_clear, &respip_get_mem
};
struct module_func_block*

View file

@ -7778,7 +7778,8 @@ static void auth_zone_log(uint8_t* name, enum verbosity_value level,
static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
struct module_env* env, struct module_stack* mods,
struct ub_packed_rrset_key* dnskey, struct auth_data* node,
struct auth_rrset* rrset, char** why_bogus, uint8_t* sigalg)
struct auth_rrset* rrset, char** why_bogus, uint8_t* sigalg,
char* reasonbuf, size_t reasonlen)
{
struct ub_packed_rrset_key pk;
enum sec_status sec;
@ -7808,7 +7809,7 @@ static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
"zonemd: verify %s RRset with DNSKEY", typestr);
}
sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus, NULL,
LDNS_SECTION_ANSWER, NULL, &verified);
LDNS_SECTION_ANSWER, NULL, &verified, reasonbuf, reasonlen);
if(sec == sec_status_secure) {
return 1;
}
@ -7851,7 +7852,8 @@ static int nsec3_of_param_has_type(struct auth_rrset* nsec3, int algo,
static int zonemd_check_dnssec_absence(struct auth_zone* z,
struct module_env* env, struct module_stack* mods,
struct ub_packed_rrset_key* dnskey, struct auth_data* apex,
char** reason, char** why_bogus, uint8_t* sigalg)
char** reason, char** why_bogus, uint8_t* sigalg, char* reasonbuf,
size_t reasonlen)
{
struct auth_rrset* nsec = NULL;
if(!apex) {
@ -7863,7 +7865,7 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z,
struct ub_packed_rrset_key pk;
/* dnssec verify the NSEC */
if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex,
nsec, why_bogus, sigalg)) {
nsec, why_bogus, sigalg, reasonbuf, reasonlen)) {
*reason = "DNSSEC verify failed for NSEC RRset";
return 0;
}
@ -7906,7 +7908,7 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z,
}
/* dnssec verify the NSEC3 */
if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, match,
nsec3, why_bogus, sigalg)) {
nsec3, why_bogus, sigalg, reasonbuf, reasonlen)) {
*reason = "DNSSEC verify failed for NSEC3 RRset";
return 0;
}
@ -7928,7 +7930,7 @@ static int zonemd_check_dnssec_soazonemd(struct auth_zone* z,
struct module_env* env, struct module_stack* mods,
struct ub_packed_rrset_key* dnskey, struct auth_data* apex,
struct auth_rrset* zonemd_rrset, char** reason, char** why_bogus,
uint8_t* sigalg)
uint8_t* sigalg, char* reasonbuf, size_t reasonlen)
{
struct auth_rrset* soa;
if(!apex) {
@ -7941,12 +7943,12 @@ static int zonemd_check_dnssec_soazonemd(struct auth_zone* z,
return 0;
}
if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex, soa,
why_bogus, sigalg)) {
why_bogus, sigalg, reasonbuf, reasonlen)) {
*reason = "DNSSEC verify failed for SOA RRset";
return 0;
}
if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex,
zonemd_rrset, why_bogus, sigalg)) {
zonemd_rrset, why_bogus, sigalg, reasonbuf, reasonlen)) {
*reason = "DNSSEC verify failed for ZONEMD RRset";
return 0;
}
@ -8014,6 +8016,7 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
struct module_stack* mods, struct ub_packed_rrset_key* dnskey,
int is_insecure, char** result, uint8_t* sigalg)
{
char reasonbuf[256];
char* reason = NULL, *why_bogus = NULL;
struct auth_data* apex = NULL;
struct auth_rrset* zonemd_rrset = NULL;
@ -8042,7 +8045,8 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
} else if(!zonemd_rrset && dnskey && !is_insecure) {
/* fetch, DNSSEC verify, and check NSEC/NSEC3 */
if(!zonemd_check_dnssec_absence(z, env, mods, dnskey, apex,
&reason, &why_bogus, sigalg)) {
&reason, &why_bogus, sigalg, reasonbuf,
sizeof(reasonbuf))) {
auth_zone_zonemd_fail(z, env, reason, why_bogus, result);
return;
}
@ -8050,7 +8054,8 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
} else if(zonemd_rrset && dnskey && !is_insecure) {
/* check DNSSEC verify of SOA and ZONEMD */
if(!zonemd_check_dnssec_soazonemd(z, env, mods, dnskey, apex,
zonemd_rrset, &reason, &why_bogus, sigalg)) {
zonemd_rrset, &reason, &why_bogus, sigalg, reasonbuf,
sizeof(reasonbuf))) {
auth_zone_zonemd_fail(z, env, reason, why_bogus, result);
return;
}
@ -8107,6 +8112,8 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
* @param why_bogus: if the routine fails, returns the failure reason.
* @param keystorage: where to store the ub_packed_rrset_key that is created
* on success. A pointer to it is returned on success.
* @param reasonbuf: buffer to use for fail reason string print.
* @param reasonlen: length of reasonbuf.
* @return the dnskey RRset, reference to zone data and keystorage, or
* NULL on failure.
*/
@ -8114,7 +8121,8 @@ static struct ub_packed_rrset_key*
zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env,
struct module_stack* mods, struct trust_anchor* anchor,
int* is_insecure, char** why_bogus,
struct ub_packed_rrset_key* keystorage)
struct ub_packed_rrset_key* keystorage, char* reasonbuf,
size_t reasonlen)
{
struct auth_data* apex;
struct auth_rrset* dnskey_rrset;
@ -8150,7 +8158,8 @@ zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env,
auth_zone_log(z->name, VERB_QUERY,
"zonemd: verify DNSKEY RRset with trust anchor");
sec = val_verify_DNSKEY_with_TA(env, ve, keystorage, anchor->ds_rrset,
anchor->dnskey_rrset, NULL, why_bogus, NULL, NULL);
anchor->dnskey_rrset, NULL, why_bogus, NULL, NULL, reasonbuf,
reasonlen);
regional_free_all(env->scratch);
if(sec == sec_status_secure) {
/* success */
@ -8173,7 +8182,8 @@ static struct ub_packed_rrset_key*
auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z,
struct module_env* env, struct module_stack* mods,
struct ub_packed_rrset_key* ds, int* is_insecure, char** why_bogus,
struct ub_packed_rrset_key* keystorage, uint8_t* sigalg)
struct ub_packed_rrset_key* keystorage, uint8_t* sigalg,
char* reasonbuf, size_t reasonlen)
{
struct auth_data* apex;
struct auth_rrset* dnskey_rrset;
@ -8209,7 +8219,7 @@ auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z,
keystorage->rk.rrset_class = htons(z->dclass);
auth_zone_log(z->name, VERB_QUERY, "zonemd: verify zone DNSKEY with DS");
sec = val_verify_DNSKEY_with_DS(env, ve, keystorage, ds, sigalg,
why_bogus, NULL, NULL);
why_bogus, NULL, NULL, reasonbuf, reasonlen);
regional_free_all(env->scratch);
if(sec == sec_status_secure) {
/* success */
@ -8235,6 +8245,7 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
{
struct auth_zone* z = (struct auth_zone*)arg;
struct module_env* env;
char reasonbuf[256];
char* reason = NULL, *ds_bogus = NULL, *typestr="DNSKEY";
struct ub_packed_rrset_key* dnskey = NULL, *ds = NULL;
int is_insecure = 0, downprot;
@ -8346,7 +8357,8 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
if(!reason && !is_insecure && !dnskey && ds) {
dnskey = auth_zone_verify_zonemd_key_with_ds(z, env,
&env->mesh->mods, ds, &is_insecure, &ds_bogus,
&keystorage, downprot?sigalg:NULL);
&keystorage, downprot?sigalg:NULL, reasonbuf,
sizeof(reasonbuf));
if(!dnskey && !is_insecure && !reason)
reason = "DNSKEY verify with DS failed";
}
@ -8354,6 +8366,7 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
if(reason) {
auth_zone_zonemd_fail(z, env, reason, ds_bogus, NULL);
lock_rw_unlock(&z->lock);
regional_free_all(env->scratch);
return;
}
@ -8438,6 +8451,7 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
struct module_stack* mods, char** result, int offline, int only_online)
{
char reasonbuf[256];
char* reason = NULL, *why_bogus = NULL;
struct trust_anchor* anchor = NULL;
struct ub_packed_rrset_key* dnskey = NULL;
@ -8472,7 +8486,8 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
}
/* equal to trustanchor, no need for online lookups */
dnskey = zonemd_get_dnskey_from_anchor(z, env, mods, anchor,
&is_insecure, &why_bogus, &keystorage);
&is_insecure, &why_bogus, &keystorage, reasonbuf,
sizeof(reasonbuf));
lock_basic_unlock(&anchor->lock);
if(!dnskey && !reason && !is_insecure) {
reason = "verify DNSKEY RRset with trust anchor failed";
@ -8498,6 +8513,7 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
if(reason) {
auth_zone_zonemd_fail(z, env, reason, why_bogus, result);
regional_free_all(env->scratch);
return;
}

View file

@ -96,7 +96,8 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
struct ub_packed_rrset_key* ck;
lock_rw_rdlock(&rep->ref[i].key->entry.lock);
/* if deleted rrset, do not copy it */
if(rep->ref[i].key->id == 0)
if(rep->ref[i].key->id == 0 ||
rep->ref[i].id != rep->ref[i].key->id)
ck = NULL;
else ck = packed_rrset_copy_region(
rep->ref[i].key, region, now);
@ -109,14 +110,22 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
/* no break: also copy key item */
/* the line below is matched by gcc regex and silences
* the fallthrough warning */
ATTR_FALLTHROUGH
/* fallthrough */
case 1: /* ref updated, item inserted */
rep->rrsets[i] = rep->ref[i].key;
}
/* if ref was updated make sure the message ttl is updated to
* the minimum of the current rrsets. */
ttl = ((struct packed_rrset_data*)rep->rrsets[i]->entry.data)->ttl;
/* ref was updated; make sure the message ttl is
* updated to the minimum of the current rrsets. */
lock_rw_rdlock(&rep->ref[i].key->entry.lock);
/* if deleted, skip ttl update. */
if(rep->ref[i].key->id != 0 &&
rep->ref[i].id == rep->ref[i].key->id) {
ttl = ((struct packed_rrset_data*)
rep->rrsets[i]->entry.data)->ttl;
if(ttl < min_ttl) min_ttl = ttl;
}
lock_rw_unlock(&rep->ref[i].key->entry.lock);
}
}
if(min_ttl < rep->ttl) {
rep->ttl = min_ttl;
@ -337,6 +346,13 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
* not use dns64 translation */
neg = msg_cache_lookup(env, ns->name, ns->namelen,
LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
/* Because recursion for lookup uses BIT_CD, check
* for that so it stops the recursion lookup, if a
* negative answer is cached. Because the cache uses
* the CD flag for type AAAA. */
if(!neg)
neg = msg_cache_lookup(env, ns->name, ns->namelen,
LDNS_RR_TYPE_AAAA, qclass, BIT_CD, now, 0);
if(neg) {
delegpt_add_neg_msg(dp, neg);
lock_rw_unlock(&neg->entry.lock);
@ -396,6 +412,13 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
* not use dns64 translation */
neg = msg_cache_lookup(env, ns->name, ns->namelen,
LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
/* Because recursion for lookup uses BIT_CD, check
* for that so it stops the recursion lookup, if a
* negative answer is cached. Because the cache uses
* the CD flag for type AAAA. */
if(!neg)
neg = msg_cache_lookup(env, ns->name, ns->namelen,
LDNS_RR_TYPE_AAAA, qclass, BIT_CD, now, 0);
if(neg) {
delegpt_add_neg_msg(dp, neg);
lock_rw_unlock(&neg->entry.lock);

View file

@ -60,6 +60,16 @@
* can do this number of packets (until those all timeout too) */
#define TIMEOUT_COUNT_MAX 3
/** Minus 1000 because that is outside of the RTTBAND, so
* blacklisted servers stay blacklisted if this is chosen.
* If USEFUL_SERVER_TOP_TIMEOUT is below 1000 (configured via RTT_MAX_TIMEOUT,
* infra-cache-max-rtt) change it to just above the RTT_BAND. */
#define STILL_USEFUL_TIMEOUT ( \
USEFUL_SERVER_TOP_TIMEOUT < 1000 || \
USEFUL_SERVER_TOP_TIMEOUT - 1000 <= RTT_BAND \
?RTT_BAND + 1 \
:USEFUL_SERVER_TOP_TIMEOUT - 1000)
/** ratelimit value for delegation point */
int infra_dp_ratelimit = 0;
@ -347,6 +357,7 @@ infra_create(struct config_file* cfg)
return NULL;
}
infra_ip_ratelimit = cfg->ip_ratelimit;
infra_ip_ratelimit_cookie = cfg->ip_ratelimit_cookie;
infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
&ip_rate_compfunc, &ip_rate_delkeyfunc, &ip_rate_deldatafunc, NULL);
@ -398,6 +409,7 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
infra->infra_keep_probing = cfg->infra_keep_probing;
infra_dp_ratelimit = cfg->ratelimit;
infra_ip_ratelimit = cfg->ip_ratelimit;
infra_ip_ratelimit_cookie = cfg->ip_ratelimit_cookie;
maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
sizeof(struct infra_data)+INFRA_BYTES_NAME);
/* divide cachesize by slabs and multiply by slabs, because if the
@ -656,7 +668,7 @@ infra_update_tcp_works(struct infra_cache* infra,
if(data->rtt.rto >= RTT_MAX_TIMEOUT)
/* do not disqualify this server altogether, it is better
* than nothing */
data->rtt.rto = RTT_MAX_TIMEOUT-1000;
data->rtt.rto = STILL_USEFUL_TIMEOUT;
lock_rw_unlock(&e->lock);
}
@ -796,7 +808,7 @@ infra_get_lame_rtt(struct infra_cache* infra,
&& infra->infra_keep_probing) {
/* single probe, keep probing */
if(*rtt >= USEFUL_SERVER_TOP_TIMEOUT)
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
*rtt = STILL_USEFUL_TIMEOUT;
} else if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) {
/* single probe for this domain, and we are not probing */
@ -804,26 +816,23 @@ infra_get_lame_rtt(struct infra_cache* infra,
if(qtype == LDNS_RR_TYPE_A) {
if(host->timeout_A >= TIMEOUT_COUNT_MAX)
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
else *rtt = STILL_USEFUL_TIMEOUT;
} else if(qtype == LDNS_RR_TYPE_AAAA) {
if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX)
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
else *rtt = STILL_USEFUL_TIMEOUT;
} else {
if(host->timeout_other >= TIMEOUT_COUNT_MAX)
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
else *rtt = STILL_USEFUL_TIMEOUT;
}
}
/* expired entry */
if(timenow > host->ttl) {
/* see if this can be a re-probe of an unresponsive server */
/* minus 1000 because that is outside of the RTTBAND, so
* blacklisted servers stay blacklisted if this is chosen */
if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
lock_rw_unlock(&e->lock);
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
*rtt = STILL_USEFUL_TIMEOUT;
*lame = 0;
*dnsseclame = 0;
*reclame = 0;

View file

@ -234,7 +234,7 @@ struct infra_cache* infra_adjust(struct infra_cache* infra,
struct config_file* cfg);
/**
* Plain find infra data function (used by the the other functions)
* Plain find infra data function (used by the other functions)
* @param infra: infrastructure cache.
* @param addr: host address.
* @param addrlen: length of addr.

View file

@ -675,7 +675,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
int* reuseport, int transparent, int mss, int nodelay, int freebind,
int use_systemd, int dscp)
{
int s;
int s = -1;
char* err;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined(SO_BINDANY)
int on = 1;

View file

@ -242,7 +242,7 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
}
/** enter a new zone */
static struct local_zone*
struct local_zone*
lz_enter_zone(struct local_zones* zones, const char* name, const char* type,
uint16_t dclass)
{
@ -983,36 +983,39 @@ lz_enter_overrides(struct local_zones* zones, struct config_file* cfg)
return 1;
}
/** setup parent pointers, so that a lookup can be done for closest match */
static void
init_parents(struct local_zones* zones)
/* return closest parent in the tree, NULL if none */
static struct local_zone* find_closest_parent(struct local_zone* curr,
struct local_zone* prev)
{
struct local_zone* node, *prev = NULL, *p;
struct local_zone* p;
int m;
lock_rw_wrlock(&zones->lock);
RBTREE_FOR(node, struct local_zone*, &zones->ztree) {
lock_rw_wrlock(&node->lock);
node->parent = NULL;
if(!prev || prev->dclass != node->dclass) {
prev = node;
lock_rw_unlock(&node->lock);
continue;
}
(void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
node->namelabs, &m); /* we know prev is smaller */
if(!prev || prev->dclass != curr->dclass) return NULL;
(void)dname_lab_cmp(prev->name, prev->namelabs, curr->name,
curr->namelabs, &m); /* we know prev is smaller */
/* sort order like: . com. bla.com. zwb.com. net. */
/* find the previous, or parent-parent-parent */
for(p = prev; p; p = p->parent)
for(p = prev; p; p = p->parent) {
/* looking for name with few labels, a parent */
if(p->namelabs <= m) {
/* ==: since prev matched m, this is closest*/
/* <: prev matches more, but is not a parent,
* this one is a (grand)parent */
node->parent = p;
break;
return p;
}
}
return NULL;
}
prev = node;
/** setup parent pointers, so that a lookup can be done for closest match */
void
lz_init_parents(struct local_zones* zones)
{
struct local_zone* node, *prev = NULL;
lock_rw_wrlock(&zones->lock);
RBTREE_FOR(node, struct local_zone*, &zones->ztree) {
lock_rw_wrlock(&node->lock);
node->parent = find_closest_parent(node, prev);
prev = node;
if(node->override_tree)
addr_tree_init_parents(node->override_tree);
lock_rw_unlock(&node->lock);
@ -1036,7 +1039,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
int nmlabs = 0;
int match = 0; /* number of labels match count */
init_parents(zones); /* to enable local_zones_lookup() */
lz_init_parents(zones); /* to enable local_zones_lookup() */
for(p = cfg->local_data; p; p = p->next) {
uint8_t* rr_name;
uint16_t rr_class, rr_type;
@ -1202,7 +1205,7 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
}
/* setup parent ptrs for lookup during data entry */
init_parents(zones);
lz_init_parents(zones);
/* insert local zone tags */
if(!lz_enter_zone_tags(zones, cfg)) {
return 0;
@ -2028,7 +2031,9 @@ struct local_zone* local_zones_add_zone(struct local_zones* zones,
uint8_t* name, size_t len, int labs, uint16_t dclass,
enum localzone_type tp)
{
int exact;
/* create */
struct local_zone *prev;
struct local_zone* z = local_zone_create(name, len, labs, tp, dclass);
if(!z) {
free(name);
@ -2037,10 +2042,12 @@ struct local_zone* local_zones_add_zone(struct local_zones* zones,
lock_rw_wrlock(&z->lock);
/* find the closest parent */
z->parent = local_zones_find(zones, name, len, labs, dclass);
prev = local_zones_find_le(zones, name, len, labs, dclass, &exact);
if(!exact)
z->parent = find_closest_parent(z, prev);
/* insert into the tree */
if(!rbtree_insert(&zones->ztree, &z->node)) {
if(exact||!rbtree_insert(&zones->ztree, &z->node)) {
/* duplicate entry! */
lock_rw_unlock(&z->lock);
local_zone_delete(z);

View file

@ -641,4 +641,23 @@ local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen,
*/
struct local_data*
local_zone_find_data(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs);
/** Enter a new zone; returns with WRlock
* Made public for unit testing
* @param zones: the local zones tree
* @param name: name of the zone
* @param type: type of the zone
* @param dclass: class of the zone
* @return local_zone (or duplicate), NULL on parse and malloc failures
*/
struct local_zone*
lz_enter_zone(struct local_zones* zones, const char* name, const char* type,
uint16_t dclass);
/** Setup parent pointers, so that a lookup can be done for closest match
* Made public for unit testing
* @param zones: the local zones tree
*/
void
lz_init_parents(struct local_zones* zones);
#endif /* SERVICES_LOCALZONE_H */

View file

@ -413,6 +413,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
int timeout = mesh->env->cfg->serve_expired?
mesh->env->cfg->serve_expired_client_timeout:0;
struct sldns_buffer* r_buffer = rep->c->buffer;
uint16_t mesh_flags = qflags&(BIT_RD|BIT_CD);
if(rep->c->tcp_req_info) {
r_buffer = rep->c->tcp_req_info->spool_buffer;
}
@ -425,7 +426,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
return;
}
if(!unique)
s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
s = mesh_area_find(mesh, cinfo, qinfo, mesh_flags, 0, 0);
/* does this create a new reply state? */
if(!s || s->list_select == mesh_no_list) {
if(!mesh_make_new_space(mesh, rep->c->buffer)) {
@ -453,7 +454,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
struct rbnode_type* n;
#endif
s = mesh_state_create(mesh->env, qinfo, cinfo,
qflags&(BIT_RD|BIT_CD), 0, 0);
mesh_flags, 0, 0);
if(!s) {
log_err("mesh_state_create: out of memory; SERVFAIL");
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
@ -565,6 +566,8 @@ servfail_mem:
edns->opt_list_inplace_cb_out = NULL;
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
if(rep->c->use_h2)
http2_stream_remove_mesh_state(rep->c->h2_stream);
comm_point_send_reply(rep);
if(added)
mesh_state_delete(&s->s);
@ -583,8 +586,9 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
int was_detached = 0;
int was_noreply = 0;
int added = 0;
uint16_t mesh_flags = qflags&(BIT_RD|BIT_CD);
if(!unique)
s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
s = mesh_area_find(mesh, NULL, qinfo, mesh_flags, 0, 0);
/* there are no limits on the number of callbacks */
@ -594,7 +598,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
struct rbnode_type* n;
#endif
s = mesh_state_create(mesh->env, qinfo, NULL,
qflags&(BIT_RD|BIT_CD), 0, 0);
mesh_flags, 0, 0);
if(!s) {
return 0;
}
@ -673,8 +677,12 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
struct query_info* qinfo, uint16_t qflags, time_t leeway, int run,
int rpz_passthru)
{
/* Explicitly set the BIT_RD regardless of the client's flags. This is
* for a prefetch query (no client attached) but it needs to be treated
* as a recursion query. */
uint16_t mesh_flags = BIT_RD|(qflags&BIT_CD);
struct mesh_state* s = mesh_area_find(mesh, NULL, qinfo,
qflags&(BIT_RD|BIT_CD), 0, 0);
mesh_flags, 0, 0);
#ifdef UNBOUND_DEBUG
struct rbnode_type* n;
#endif
@ -694,8 +702,7 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
return;
}
s = mesh_state_create(mesh->env, qinfo, NULL,
qflags&(BIT_RD|BIT_CD), 0, 0);
s = mesh_state_create(mesh->env, qinfo, NULL, mesh_flags, 0, 0);
if(!s) {
log_err("prefetch mesh_state_create: out of memory");
return;
@ -756,14 +763,17 @@ static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
#ifdef UNBOUND_DEBUG
struct rbnode_type* n;
#endif
/* Explicitly set the BIT_RD regardless of the client's flags. This is
* for a prefetch query (no client attached) but it needs to be treated
* as a recursion query. */
uint16_t mesh_flags = BIT_RD|(qflags&BIT_CD);
if(!mesh_make_new_space(mesh, NULL)) {
verbose(VERB_ALGO, "Too many queries. dropped prefetch.");
mesh->stats_dropped ++;
return;
}
s = mesh_state_create(mesh->env, qinfo, NULL,
qflags&(BIT_RD|BIT_CD), 0, 0);
s = mesh_state_create(mesh->env, qinfo, NULL, mesh_flags, 0, 0);
if(!s) {
log_err("prefetch_subnet mesh_state_create: out of memory");
return;
@ -966,6 +976,8 @@ mesh_state_cleanup(struct mesh_state* mstate)
for(; rep; rep=rep->next) {
infra_wait_limit_dec(mesh->env->infra_cache,
&rep->query_reply, mesh->env->cfg);
if(rep->query_reply.c->use_h2)
http2_stream_remove_mesh_state(rep->h2_stream);
comm_point_drop_reply(&rep->query_reply);
log_assert(mesh->num_reply_addrs > 0);
mesh->num_reply_addrs--;
@ -1522,6 +1534,8 @@ void mesh_query_done(struct mesh_state* mstate)
infra_wait_limit_dec(mstate->s.env->infra_cache,
&r->query_reply, mstate->s.env->cfg);
mstate->reply_list = NULL;
if(r->query_reply.c->use_h2)
http2_stream_remove_mesh_state(r->h2_stream);
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
mstate->s.env->mesh->stats_dropped++;
@ -1554,6 +1568,9 @@ void mesh_query_done(struct mesh_state* mstate)
infra_wait_limit_dec(mstate->s.env->infra_cache,
&r->query_reply, mstate->s.env->cfg);
mstate->reply_list = NULL;
if(r->query_reply.c->use_h2) {
http2_stream_remove_mesh_state(r->h2_stream);
}
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
} else {
@ -1568,6 +1585,8 @@ void mesh_query_done(struct mesh_state* mstate)
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
r_buffer = NULL;
}
/* mesh_send_reply removed mesh state from
* http2_stream. */
prev = r;
prev_buffer = r_buffer;
}
@ -1720,6 +1739,7 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
return 0;
if(rep->c->use_h2)
r->h2_stream = rep->c->h2_stream;
else r->h2_stream = NULL;
/* Data related to local alias stored in 'qinfo' (if any) is ephemeral
* and can be different for different original queries (even if the
@ -2243,6 +2263,8 @@ mesh_serve_expired_callback(void* arg)
infra_wait_limit_dec(mstate->s.env->infra_cache,
&r->query_reply, mstate->s.env->cfg);
mstate->reply_list = NULL;
if(r->query_reply.c->use_h2)
http2_stream_remove_mesh_state(r->h2_stream);
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
mstate->s.env->mesh->stats_dropped++;
@ -2276,6 +2298,7 @@ mesh_serve_expired_callback(void* arg)
r, r_buffer, prev, prev_buffer);
if(r->query_reply.c->tcp_req_info)
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
/* mesh_send_reply removed mesh state from http2_stream. */
infra_wait_limit_dec(mstate->s.env->infra_cache,
&r->query_reply, mstate->s.env->cfg);
prev = r;

View file

@ -95,6 +95,16 @@ modstack_init(struct module_stack* stack)
stack->mod = NULL;
}
void
modstack_free(struct module_stack* stack)
{
if(!stack)
return;
stack->num = 0;
free(stack->mod);
stack->mod = NULL;
}
int
modstack_config(struct module_stack* stack, const char* module_conf)
{
@ -223,17 +233,58 @@ module_func_block* module_factory(const char** str)
}
int
modstack_setup(struct module_stack* stack, const char* module_conf,
modstack_call_startup(struct module_stack* stack, const char* module_conf,
struct module_env* env)
{
int i;
if(stack->num != 0)
modstack_desetup(stack, env);
fatal_exit("unexpected already initialised modules");
/* fixed setup of the modules */
if(!modstack_config(stack, module_conf)) {
return 0;
}
for(i=0; i<stack->num; i++) {
if(stack->mod[i]->startup == NULL)
continue;
verbose(VERB_OPS, "startup module %d: %s",
i, stack->mod[i]->name);
fptr_ok(fptr_whitelist_mod_startup(stack->mod[i]->startup));
if(!(*stack->mod[i]->startup)(env, i)) {
log_err("module startup for module %s failed",
stack->mod[i]->name);
return 0;
}
}
return 1;
}
int
modstack_call_init(struct module_stack* stack, const char* module_conf,
struct module_env* env)
{
int i, changed = 0;
env->need_to_validate = 0; /* set by module init below */
for(i=0; i<stack->num; i++) {
while(*module_conf && isspace(*module_conf))
module_conf++;
if(strncmp(stack->mod[i]->name, module_conf,
strlen(stack->mod[i]->name))) {
if(stack->mod[i]->startup || stack->mod[i]->destartup) {
log_err("changed module ordering during reload not supported, for module that needs startup");
return 0;
} else {
changed = 1;
}
}
module_conf += strlen(stack->mod[i]->name);
}
if(changed) {
modstack_free(stack);
if(!modstack_config(stack, module_conf)) {
return 0;
}
}
for(i=0; i<stack->num; i++) {
verbose(VERB_OPS, "init module %d: %s",
i, stack->mod[i]->name);
@ -248,16 +299,25 @@ modstack_setup(struct module_stack* stack, const char* module_conf,
}
void
modstack_desetup(struct module_stack* stack, struct module_env* env)
modstack_call_deinit(struct module_stack* stack, struct module_env* env)
{
int i;
for(i=0; i<stack->num; i++) {
fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
(*stack->mod[i]->deinit)(env, i);
}
stack->num = 0;
free(stack->mod);
stack->mod = NULL;
}
void
modstack_call_destartup(struct module_stack* stack, struct module_env* env)
{
int i;
for(i=0; i<stack->num; i++) {
if(stack->mod[i]->destartup == NULL)
continue;
fptr_ok(fptr_whitelist_mod_destartup(stack->mod[i]->destartup));
(*stack->mod[i]->destartup)(env, i);
}
}
int

View file

@ -60,6 +60,23 @@ struct module_stack {
*/
void modstack_init(struct module_stack* stack);
/**
* Free the stack of modules
* @param stack: stack that frees up memory.
*/
void modstack_free(struct module_stack* stack);
/**
* Initialises modules and assignes ids. Calls module_startup().
* @param stack: Expected empty, filled according to module_conf
* @param module_conf: string what modules to initialize
* @param env: module environment which is inited by the modules.
* environment should have a superalloc, cfg,
* @return on false a module init failed.
*/
int modstack_call_startup(struct module_stack* stack, const char* module_conf,
struct module_env* env);
/**
* Read config file module settings and set up the modfunc block
* @param stack: the stack of modules (empty before call).
@ -83,24 +100,31 @@ struct module_func_block* module_factory(const char** str);
const char** module_list_avail(void);
/**
* Setup modules. Assigns ids and calls module_init.
* @param stack: if not empty beforehand, it will be desetup()ed.
* It is then modstack_configged().
* @param module_conf: string what modules to insert.
* Init modules. Calls module_init().
* @param stack: It is modstack_setupped().
* @param module_conf: module ordering to check against the ordering in stack.
* fails on changed ordering.
* @param env: module environment which is inited by the modules.
* environment should have a superalloc, cfg,
* env.need_to_validate is set by the modules.
* @return on false a module init failed.
*/
int modstack_setup(struct module_stack* stack, const char* module_conf,
int modstack_call_init(struct module_stack* stack, const char* module_conf,
struct module_env* env);
/**
* Desetup the modules, deinit, delete.
* Deinit the modules.
* @param stack: made empty.
* @param env: module env for module deinit() calls.
*/
void modstack_desetup(struct module_stack* stack, struct module_env* env);
void modstack_call_deinit(struct module_stack* stack, struct module_env* env);
/**
* Destartup the modules, close, delete.
* @param stack: made empty.
* @param env: module env for module destartup() calls.
*/
void modstack_call_destartup(struct module_stack* stack, struct module_env* env);
/**
* Find index of module by name.

View file

@ -2051,7 +2051,8 @@ select_id(struct outside_network* outnet, struct pending* pend,
}
/** return true is UDP connect error needs to be logged */
static int udp_connect_needs_log(int err)
static int udp_connect_needs_log(int err, struct sockaddr_storage* addr,
socklen_t addrlen)
{
switch(err) {
case ECONNREFUSED:
@ -2075,6 +2076,15 @@ static int udp_connect_needs_log(int err)
if(verbosity >= VERB_ALGO)
return 1;
return 0;
case EINVAL:
/* Stop 'Invalid argument for fe80::/10' addresses appearing
* in the logs, at low verbosity. They cannot be sent to. */
if(addr_is_ip6linklocal(addr, addrlen)) {
if(verbosity >= VERB_ALGO)
return 1;
return 0;
}
break;
default:
break;
}
@ -2141,7 +2151,8 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
/* connect() to the destination */
if(connect(fd, (struct sockaddr*)&pend->addr,
pend->addrlen) < 0) {
if(udp_connect_needs_log(errno)) {
if(udp_connect_needs_log(errno,
&pend->addr, pend->addrlen)) {
log_err_addr("udp connect failed",
strerror(errno), &pend->addr,
pend->addrlen);
@ -3455,7 +3466,10 @@ outnet_serviced_query(struct outside_network* outnet,
timenow = *env->now;
if(!infra_ratelimit_inc(env->infra_cache, zone,
zonelen, timenow, env->cfg->ratelimit_backoff,
&qstate->qinfo, qstate->reply)) {
&qstate->qinfo,
qstate->mesh_info->reply_list
?&qstate->mesh_info->reply_list->query_reply
:NULL)) {
/* Can we pass through with slip factor? */
if(env->cfg->ratelimit_factor == 0 ||
ub_random_max(env->rnd,

View file

@ -242,10 +242,14 @@ rpz_action_to_localzone_type(enum rpz_action a)
case RPZ_NODATA_ACTION: return local_zone_always_nodata;
case RPZ_DROP_ACTION: return local_zone_always_deny;
case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent;
case RPZ_LOCAL_DATA_ACTION: /* fallthrough */
case RPZ_LOCAL_DATA_ACTION:
ATTR_FALLTHROUGH
/* fallthrough */
case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect;
case RPZ_TCP_ONLY_ACTION: return local_zone_truncate;
case RPZ_INVALID_ACTION: /* fallthrough */
case RPZ_INVALID_ACTION:
ATTR_FALLTHROUGH
/* fallthrough */
default: return local_zone_invalid;
}
}
@ -258,10 +262,14 @@ rpz_action_to_respip_action(enum rpz_action a)
case RPZ_NODATA_ACTION: return respip_always_nodata;
case RPZ_DROP_ACTION: return respip_always_deny;
case RPZ_PASSTHRU_ACTION: return respip_always_transparent;
case RPZ_LOCAL_DATA_ACTION: /* fallthrough */
case RPZ_LOCAL_DATA_ACTION:
ATTR_FALLTHROUGH
/* fallthrough */
case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect;
case RPZ_TCP_ONLY_ACTION: return respip_truncate;
case RPZ_INVALID_ACTION: /* fallthrough */
case RPZ_INVALID_ACTION:
ATTR_FALLTHROUGH
/* fallthrough */
default: return respip_invalid;
}
}
@ -276,7 +284,9 @@ localzone_type_to_rpz_action(enum localzone_type lzt)
case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION;
case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION;
case local_zone_truncate: return RPZ_TCP_ONLY_ACTION;
case local_zone_invalid: /* fallthrough */
case local_zone_invalid:
ATTR_FALLTHROUGH
/* fallthrough */
default: return RPZ_INVALID_ACTION;
}
}
@ -291,7 +301,9 @@ respip_action_to_rpz_action(enum respip_action a)
case respip_always_transparent: return RPZ_PASSTHRU_ACTION;
case respip_redirect: return RPZ_LOCAL_DATA_ACTION;
case respip_truncate: return RPZ_TCP_ONLY_ACTION;
case respip_invalid: /* fallthrough */
case respip_invalid:
ATTR_FALLTHROUGH
/* fallthrough */
default: return RPZ_INVALID_ACTION;
}
}
@ -2435,11 +2447,10 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
az = ms->env->auth_zones;
lock_rw_rdlock(&az->rpz_lock);
verbose(VERB_ALGO, "rpz: iterator module callback: have_rpz=%d", az->rpz_first != NULL);
lock_rw_rdlock(&az->rpz_lock);
/* precedence of RPZ works, loosely, like this:
* CNAMEs in order of the CNAME chain. rpzs in the order they are
* configured. In an RPZ: first client-IP addr, then QNAME, then
@ -2454,6 +2465,13 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
lock_rw_unlock(&a->lock);
continue;
}
if(r->taglist && (!ms->client_info ||
!taglist_intersect(r->taglist, r->taglistlen,
ms->client_info->taglist,
ms->client_info->taglen))) {
lock_rw_unlock(&a->lock);
continue;
}
/* the nsdname has precedence over the nsip triggers */
z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
@ -2512,6 +2530,13 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
lock_rw_unlock(&a->lock);
continue;
}
if(r->taglist && (!ms->client_info ||
!taglist_intersect(r->taglist, r->taglistlen,
ms->client_info->taglist,
ms->client_info->taglen))) {
lock_rw_unlock(&a->lock);
continue;
}
z = rpz_find_zone(r->local_zones, is->qchase.qname,
is->qchase.qname_len, is->qchase.qclass, 0, 0, 0);
if(z && r->action_override == RPZ_DISABLED_ACTION) {

View file

@ -106,7 +106,7 @@ ssize_t sldns_bget_token(struct sldns_buffer *b, char *token, const char *delim,
* \param[in] k_del keyword delimiter
* \param[out] data the data found
* \param[in] d_del the data delimiter
* \param[in] data_limit maximum size the the data buffer
* \param[in] data_limit maximum size the data buffer
* \return the number of character read
*/
ssize_t sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
@ -119,7 +119,7 @@ ssize_t sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del,
* \param[in] k_del keyword delimiter
* \param[out] data the data found
* \param[in] d_del the data delimiter
* \param[in] data_limit maximum size the the data buffer
* \param[in] data_limit maximum size the data buffer
* \param[in] line_nr pointer to an integer containing the current line number (for
debugging purposes)
* \return the number of character read
@ -134,7 +134,7 @@ ssize_t sldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_de
* \param[in] k_del keyword delimiter
* \param[out] data the data found
* \param[in] d_del the data delimiter
* \param[in] data_limit maximum size the the data buffer
* \param[in] data_limit maximum size the data buffer
* \return the number of character read
*/
ssize_t sldns_bget_keyword_data(struct sldns_buffer *b, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);

View file

@ -436,11 +436,13 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
/* ........ ........ ....4444 4....... ........ */
c = src[3] >> 7 ;
ATTR_FALLTHROUGH
/* fallthrough */
case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c];
/* ........ .......3 3333.... ........ ........ */
c = src[2] >> 4 ;
ATTR_FALLTHROUGH
/* fallthrough */
case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c];
@ -449,6 +451,7 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
/* .....111 11...... ........ ........ ........ */
c = src[1] >> 6 ;
ATTR_FALLTHROUGH
/* fallthrough */
case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c];
@ -460,11 +463,14 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
switch (src_sz) {
case 1: dst[2] = '=';
dst[3] = '=';
ATTR_FALLTHROUGH
/* fallthrough */
case 2: dst[4] = '=';
ATTR_FALLTHROUGH
/* fallthrough */
case 3: dst[5] = '=';
dst[6] = '=';
ATTR_FALLTHROUGH
/* fallthrough */
case 4: dst[7] = '=';
}
@ -577,17 +583,20 @@ sldns_b32_pton_base(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz,
/* ........ ........ ........ .55555.. ........ */
/* ........ ........ ....4444 4....... ........ */
dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
ATTR_FALLTHROUGH
/* fallthrough */
case 5: /* ........ ........ ....4444 4....... ........ */
/* ........ .......3 3333.... ........ ........ */
dst[2] = buf[3] << 4 | buf[4] >> 1;
ATTR_FALLTHROUGH
/* fallthrough */
case 4: /* ........ .......3 3333.... ........ ........ */
/* ........ ..22222. ........ ........ ........ */
/* .....111 11...... ........ ........ ........ */
dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
ATTR_FALLTHROUGH
/* fallthrough */
case 2: /* .....111 11...... ........ ........ ........ */

View file

@ -470,6 +470,11 @@ enum sldns_enum_ede_code
LDNS_EDE_NO_REACHABLE_AUTHORITY = 22,
LDNS_EDE_NETWORK_ERROR = 23,
LDNS_EDE_INVALID_DATA = 24,
LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID = 25,
LDNS_EDE_TOO_EARLY = 26,
LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS = 27,
LDNS_EDE_BADPROXYPOLICY = 28,
LDNS_EDE_SYNTHESIZED = 29
};
typedef enum sldns_enum_ede_code sldns_ede_code;

View file

@ -228,6 +228,11 @@ static sldns_lookup_table sldns_edns_ede_codes_data[] = {
{ LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" },
{ LDNS_EDE_NETWORK_ERROR, "Network Error" },
{ LDNS_EDE_INVALID_DATA, "Invalid Data" },
{ LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID, "Signature Expired Before Valid" },
{ LDNS_EDE_TOO_EARLY, "Non-Replayable Transactions Received in 0-RTT Data" },
{ LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS, "Unsupported NSEC3 Iterations Value" },
{ LDNS_EDE_BADPROXYPOLICY, "Unable to Conform to Policy" },
{ LDNS_EDE_SYNTHESIZED, "Synthesized Answer" },
{ 0, NULL}
};
sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data;
@ -1236,6 +1241,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d);
break;
case SVCB_KEY_DOHPATH:
ATTR_FALLTHROUGH
/* fallthrough */
default:
r = sldns_str_print(s, slen, "=\"");

View file

@ -466,6 +466,18 @@ void *unbound_stat_realloc(void *ptr, size_t size)
memcpy(res+8, &mem_special, sizeof(mem_special));
return res+16;
}
/** strdup with stats */
char *unbound_stat_strdup(const char* s)
{
size_t len;
char* res;
if(!s) return NULL;
len = strlen(s);
res = unbound_stat_malloc(len+1);
if(!res) return NULL;
memmove(res, s, len+1);
return res;
}
/** log to file where alloc was done */
void *unbound_stat_malloc_log(size_t size, const char* file, int line,
@ -507,6 +519,15 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
return unbound_stat_realloc(ptr, size);
}
/** log to file where strdup was done */
char *unbound_stat_strdup_log(const char *s, const char* file, int line,
const char* func)
{
log_info("%s:%d %s strdup size %u", file, line, func,
(s?(unsigned)strlen(s)+1:0));
return unbound_stat_strdup(s);
}
#endif /* UNBOUND_ALLOC_STATS */
#ifdef UNBOUND_ALLOC_LITE
#undef malloc

View file

@ -42,6 +42,7 @@
#include "config.h"
#include <ctype.h>
#include <stdarg.h>
#include <errno.h>
#ifdef HAVE_TIME_H
#include <time.h>
#endif
@ -386,6 +387,7 @@ config_create(void)
memset(cfg->cookie_secret, 0, sizeof(cfg->cookie_secret));
cfg->cookie_secret_len = 16;
init_cookie_secret(cfg->cookie_secret, cfg->cookie_secret_len);
cfg->cookie_secret_file = NULL;
#ifdef USE_CACHEDB
if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
@ -769,6 +771,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("dnstap-send-version:", dnstap_send_version)
else S_STR("dnstap-identity:", dnstap_identity)
else S_STR("dnstap-version:", dnstap_version)
else S_NUMBER_OR_ZERO("dnstap-sample-rate:", dnstap_sample_rate)
else S_YNO("dnstap-log-resolver-query-messages:",
dnstap_log_resolver_query_messages)
else S_YNO("dnstap-log-resolver-response-messages:",
@ -837,6 +840,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
{ IS_NUMBER_OR_ZERO; cfg->ipsecmod_max_ttl = atoi(val); }
else S_YNO("ipsecmod-strict:", ipsecmod_strict)
#endif
else S_YNO("answer-cookie:", do_answer_cookie)
else S_STR("cookie-secret-file:", cookie_secret_file)
#ifdef USE_CACHEDB
else S_YNO("cachedb-no-store:", cachedb_no_store)
else S_YNO("cachedb-check-when-serve-expired:", cachedb_check_when_serve_expired)
@ -1248,6 +1253,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "dnstap-send-version", dnstap_send_version)
else O_STR(opt, "dnstap-identity", dnstap_identity)
else O_STR(opt, "dnstap-version", dnstap_version)
else O_UNS(opt, "dnstap-sample-rate", dnstap_sample_rate)
else O_YNO(opt, "dnstap-log-resolver-query-messages",
dnstap_log_resolver_query_messages)
else O_YNO(opt, "dnstap-log-resolver-response-messages",
@ -1333,6 +1339,8 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_LST(opt, "ipsecmod-whitelist", ipsecmod_whitelist)
else O_YNO(opt, "ipsecmod-strict", ipsecmod_strict)
#endif
else O_YNO(opt, "answer-cookie", do_answer_cookie)
else O_STR(opt, "cookie-secret-file", cookie_secret_file)
#ifdef USE_CACHEDB
else O_STR(opt, "backend", cachedb_backend)
else O_STR(opt, "secret-seed", cachedb_secret)
@ -1718,6 +1726,7 @@ config_delete(struct config_file* cfg)
free(cfg->ipsecmod_hook);
config_delstrlist(cfg->ipsecmod_whitelist);
#endif
free(cfg->cookie_secret_file);
#ifdef USE_CACHEDB
free(cfg->cachedb_backend);
free(cfg->cachedb_secret);
@ -1772,6 +1781,39 @@ init_outgoing_availports(int* a, int num)
}
}
static int
extract_port_from_str(const char* str, int max_port) {
char* endptr;
long int value;
if (str == NULL || *str == '\0') {
log_err("str: '%s' is invalid", (str?str:"NULL"));
return -1;
}
value = strtol(str, &endptr, 10);
if ((endptr == str) || (*endptr != '\0')) {
log_err("cannot parse port number '%s'", str);
return -1;
}
if (errno == ERANGE) {
log_err("overflow occurred when parsing '%s'", str);
return -1;
}
if (value == 0 && strcmp(str, "0") != 0) {
log_err("cannot parse port number '%s'", str);
return -1;
}
if (value < 0 || value >= max_port) {
log_err(" '%s' is out of bounds [0, %d)", str, max_port);
return -1;
}
return (int)value;
}
int
cfg_mark_ports(const char* str, int allow, int* avail, int num)
{
@ -1782,53 +1824,45 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num)
"options");
#endif
if(!mid) {
int port = atoi(str);
int port = extract_port_from_str(str, num);
if(port < 0) {
log_err("port number is negative: %d", port);
return 0;
}
if(port == 0 && strcmp(str, "0") != 0) {
log_err("cannot parse port number '%s'", str);
log_err("Failed to parse the port number");
return 0;
}
if(port < num)
avail[port] = (allow?port:0);
} else {
int i, low, high = atoi(mid+1);
char buf[16];
int i, low;
int high = extract_port_from_str(mid+1, num);
if(high < 0) {
log_err("port number is negative: %d", high);
return 0;
}
if(high == 0 && strcmp(mid+1, "0") != 0) {
log_err("cannot parse port number '%s'", mid+1);
log_err("Failed to parse the port number");
return 0;
}
if( (int)(mid-str)+1 >= (int)sizeof(buf) ) {
log_err("cannot parse port number '%s'", str);
return 0;
}
if(mid > str)
memcpy(buf, str, (size_t)(mid-str));
buf[mid-str] = 0;
low = atoi(buf);
low = extract_port_from_str(buf, num);
if(low < 0) {
log_err("port number is negative: %d", low);
log_err("Failed to parse the port number");
return 0;
}
if(low == 0 && strcmp(buf, "0") != 0) {
log_err("cannot parse port number '%s'", buf);
if (low > high) {
log_err("Low value is greater than high value");
return 0;
}
if(high > num) {
/* Stop very high values from taking a long time. */
high = num;
}
for(i=low; i<=high; i++) {
if(i < num)
avail[i] = (allow?i:0);
}
return 1;
}
return 1;
}

View file

@ -592,6 +592,8 @@ struct config_file {
char* dnstap_identity;
/** dnstap "version", package version is used if "". */
char* dnstap_version;
/** dnstap sample rate */
int dnstap_sample_rate;
/** true to log dnstap RESOLVER_QUERY message events */
int dnstap_log_resolver_query_messages;
@ -748,6 +750,8 @@ struct config_file {
uint8_t cookie_secret[40];
/** cookie secret length */
size_t cookie_secret_len;
/** path to cookie secret store */
char* cookie_secret_file;
/* ipset module */
#ifdef USE_IPSET

File diff suppressed because it is too large Load diff

View file

@ -513,6 +513,7 @@ dnstap-log-forwarder-query-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) }
dnstap-log-forwarder-response-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
dnstap-sample-rate { YDVAR(1, VAR_DNSTAP_SAMPLE_RATE) }
disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) }
ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) }
ip-ratelimit-cookie{COLON} { YDVAR(1, VAR_IP_RATELIMIT_COOKIE) }
@ -581,6 +582,7 @@ udp-upstream-without-downstream{COLON} { YDVAR(1, VAR_UDP_UPSTREAM_WITHOUT_DOWNS
tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
answer-cookie{COLON} { YDVAR(1, VAR_ANSWER_COOKIE ) }
cookie-secret{COLON} { YDVAR(1, VAR_COOKIE_SECRET) }
cookie-secret-file{COLON} { YDVAR(1, VAR_COOKIE_SECRET_FILE) }
edns-client-string{COLON} { YDVAR(2, VAR_EDNS_CLIENT_STRING) }
edns-client-string-opcode{COLON} { YDVAR(1, VAR_EDNS_CLIENT_STRING_OPCODE) }
nsid{COLON} { YDVAR(1, VAR_NSID ) }

View file

@ -187,171 +187,173 @@
#define VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES 443
#define VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES 444
#define VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES 445
#define VAR_RESPONSE_IP_TAG 446
#define VAR_RESPONSE_IP 447
#define VAR_RESPONSE_IP_DATA 448
#define VAR_HARDEN_ALGO_DOWNGRADE 449
#define VAR_IP_TRANSPARENT 450
#define VAR_IP_DSCP 451
#define VAR_DISABLE_DNSSEC_LAME_CHECK 452
#define VAR_IP_RATELIMIT 453
#define VAR_IP_RATELIMIT_SLABS 454
#define VAR_IP_RATELIMIT_SIZE 455
#define VAR_RATELIMIT 456
#define VAR_RATELIMIT_SLABS 457
#define VAR_RATELIMIT_SIZE 458
#define VAR_OUTBOUND_MSG_RETRY 459
#define VAR_MAX_SENT_COUNT 460
#define VAR_MAX_QUERY_RESTARTS 461
#define VAR_RATELIMIT_FOR_DOMAIN 462
#define VAR_RATELIMIT_BELOW_DOMAIN 463
#define VAR_IP_RATELIMIT_FACTOR 464
#define VAR_RATELIMIT_FACTOR 465
#define VAR_IP_RATELIMIT_BACKOFF 466
#define VAR_RATELIMIT_BACKOFF 467
#define VAR_SEND_CLIENT_SUBNET 468
#define VAR_CLIENT_SUBNET_ZONE 469
#define VAR_CLIENT_SUBNET_ALWAYS_FORWARD 470
#define VAR_CLIENT_SUBNET_OPCODE 471
#define VAR_MAX_CLIENT_SUBNET_IPV4 472
#define VAR_MAX_CLIENT_SUBNET_IPV6 473
#define VAR_MIN_CLIENT_SUBNET_IPV4 474
#define VAR_MIN_CLIENT_SUBNET_IPV6 475
#define VAR_MAX_ECS_TREE_SIZE_IPV4 476
#define VAR_MAX_ECS_TREE_SIZE_IPV6 477
#define VAR_CAPS_WHITELIST 478
#define VAR_CACHE_MAX_NEGATIVE_TTL 479
#define VAR_PERMIT_SMALL_HOLDDOWN 480
#define VAR_CACHE_MIN_NEGATIVE_TTL 481
#define VAR_QNAME_MINIMISATION 482
#define VAR_QNAME_MINIMISATION_STRICT 483
#define VAR_IP_FREEBIND 484
#define VAR_DEFINE_TAG 485
#define VAR_LOCAL_ZONE_TAG 486
#define VAR_ACCESS_CONTROL_TAG 487
#define VAR_LOCAL_ZONE_OVERRIDE 488
#define VAR_ACCESS_CONTROL_TAG_ACTION 489
#define VAR_ACCESS_CONTROL_TAG_DATA 490
#define VAR_VIEW 491
#define VAR_ACCESS_CONTROL_VIEW 492
#define VAR_VIEW_FIRST 493
#define VAR_SERVE_EXPIRED 494
#define VAR_SERVE_EXPIRED_TTL 495
#define VAR_SERVE_EXPIRED_TTL_RESET 496
#define VAR_SERVE_EXPIRED_REPLY_TTL 497
#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 498
#define VAR_EDE_SERVE_EXPIRED 499
#define VAR_SERVE_ORIGINAL_TTL 500
#define VAR_FAKE_DSA 501
#define VAR_FAKE_SHA1 502
#define VAR_LOG_IDENTITY 503
#define VAR_HIDE_TRUSTANCHOR 504
#define VAR_HIDE_HTTP_USER_AGENT 505
#define VAR_HTTP_USER_AGENT 506
#define VAR_TRUST_ANCHOR_SIGNALING 507
#define VAR_AGGRESSIVE_NSEC 508
#define VAR_USE_SYSTEMD 509
#define VAR_SHM_ENABLE 510
#define VAR_SHM_KEY 511
#define VAR_ROOT_KEY_SENTINEL 512
#define VAR_DNSCRYPT 513
#define VAR_DNSCRYPT_ENABLE 514
#define VAR_DNSCRYPT_PORT 515
#define VAR_DNSCRYPT_PROVIDER 516
#define VAR_DNSCRYPT_SECRET_KEY 517
#define VAR_DNSCRYPT_PROVIDER_CERT 518
#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 519
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 520
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 521
#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 522
#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 523
#define VAR_PAD_RESPONSES 524
#define VAR_PAD_RESPONSES_BLOCK_SIZE 525
#define VAR_PAD_QUERIES 526
#define VAR_PAD_QUERIES_BLOCK_SIZE 527
#define VAR_IPSECMOD_ENABLED 528
#define VAR_IPSECMOD_HOOK 529
#define VAR_IPSECMOD_IGNORE_BOGUS 530
#define VAR_IPSECMOD_MAX_TTL 531
#define VAR_IPSECMOD_WHITELIST 532
#define VAR_IPSECMOD_STRICT 533
#define VAR_CACHEDB 534
#define VAR_CACHEDB_BACKEND 535
#define VAR_CACHEDB_SECRETSEED 536
#define VAR_CACHEDB_REDISHOST 537
#define VAR_CACHEDB_REDISPORT 538
#define VAR_CACHEDB_REDISTIMEOUT 539
#define VAR_CACHEDB_REDISEXPIRERECORDS 540
#define VAR_CACHEDB_REDISPATH 541
#define VAR_CACHEDB_REDISPASSWORD 542
#define VAR_CACHEDB_REDISLOGICALDB 543
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 544
#define VAR_FOR_UPSTREAM 545
#define VAR_AUTH_ZONE 546
#define VAR_ZONEFILE 547
#define VAR_MASTER 548
#define VAR_URL 549
#define VAR_FOR_DOWNSTREAM 550
#define VAR_FALLBACK_ENABLED 551
#define VAR_TLS_ADDITIONAL_PORT 552
#define VAR_LOW_RTT 553
#define VAR_LOW_RTT_PERMIL 554
#define VAR_FAST_SERVER_PERMIL 555
#define VAR_FAST_SERVER_NUM 556
#define VAR_ALLOW_NOTIFY 557
#define VAR_TLS_WIN_CERT 558
#define VAR_TCP_CONNECTION_LIMIT 559
#define VAR_ANSWER_COOKIE 560
#define VAR_COOKIE_SECRET 561
#define VAR_IP_RATELIMIT_COOKIE 562
#define VAR_FORWARD_NO_CACHE 563
#define VAR_STUB_NO_CACHE 564
#define VAR_LOG_SERVFAIL 565
#define VAR_DENY_ANY 566
#define VAR_UNKNOWN_SERVER_TIME_LIMIT 567
#define VAR_LOG_TAG_QUERYREPLY 568
#define VAR_DISCARD_TIMEOUT 569
#define VAR_WAIT_LIMIT 570
#define VAR_WAIT_LIMIT_COOKIE 571
#define VAR_WAIT_LIMIT_NETBLOCK 572
#define VAR_WAIT_LIMIT_COOKIE_NETBLOCK 573
#define VAR_STREAM_WAIT_SIZE 574
#define VAR_TLS_CIPHERS 575
#define VAR_TLS_CIPHERSUITES 576
#define VAR_TLS_USE_SNI 577
#define VAR_IPSET 578
#define VAR_IPSET_NAME_V4 579
#define VAR_IPSET_NAME_V6 580
#define VAR_TLS_SESSION_TICKET_KEYS 581
#define VAR_RPZ 582
#define VAR_TAGS 583
#define VAR_RPZ_ACTION_OVERRIDE 584
#define VAR_RPZ_CNAME_OVERRIDE 585
#define VAR_RPZ_LOG 586
#define VAR_RPZ_LOG_NAME 587
#define VAR_DYNLIB 588
#define VAR_DYNLIB_FILE 589
#define VAR_EDNS_CLIENT_STRING 590
#define VAR_EDNS_CLIENT_STRING_OPCODE 591
#define VAR_NSID 592
#define VAR_ZONEMD_PERMISSIVE_MODE 593
#define VAR_ZONEMD_CHECK 594
#define VAR_ZONEMD_REJECT_ABSENCE 595
#define VAR_RPZ_SIGNAL_NXDOMAIN_RA 596
#define VAR_INTERFACE_AUTOMATIC_PORTS 597
#define VAR_EDE 598
#define VAR_INTERFACE_ACTION 599
#define VAR_INTERFACE_VIEW 600
#define VAR_INTERFACE_TAG 601
#define VAR_INTERFACE_TAG_ACTION 602
#define VAR_INTERFACE_TAG_DATA 603
#define VAR_PROXY_PROTOCOL_PORT 604
#define VAR_STATISTICS_INHIBIT_ZERO 605
#define VAR_HARDEN_UNKNOWN_ADDITIONAL 606
#define VAR_DISABLE_EDNS_DO 607
#define VAR_CACHEDB_NO_STORE 608
#define VAR_LOG_DESTADDR 609
#define VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED 610
#define VAR_DNSTAP_SAMPLE_RATE 446
#define VAR_RESPONSE_IP_TAG 447
#define VAR_RESPONSE_IP 448
#define VAR_RESPONSE_IP_DATA 449
#define VAR_HARDEN_ALGO_DOWNGRADE 450
#define VAR_IP_TRANSPARENT 451
#define VAR_IP_DSCP 452
#define VAR_DISABLE_DNSSEC_LAME_CHECK 453
#define VAR_IP_RATELIMIT 454
#define VAR_IP_RATELIMIT_SLABS 455
#define VAR_IP_RATELIMIT_SIZE 456
#define VAR_RATELIMIT 457
#define VAR_RATELIMIT_SLABS 458
#define VAR_RATELIMIT_SIZE 459
#define VAR_OUTBOUND_MSG_RETRY 460
#define VAR_MAX_SENT_COUNT 461
#define VAR_MAX_QUERY_RESTARTS 462
#define VAR_RATELIMIT_FOR_DOMAIN 463
#define VAR_RATELIMIT_BELOW_DOMAIN 464
#define VAR_IP_RATELIMIT_FACTOR 465
#define VAR_RATELIMIT_FACTOR 466
#define VAR_IP_RATELIMIT_BACKOFF 467
#define VAR_RATELIMIT_BACKOFF 468
#define VAR_SEND_CLIENT_SUBNET 469
#define VAR_CLIENT_SUBNET_ZONE 470
#define VAR_CLIENT_SUBNET_ALWAYS_FORWARD 471
#define VAR_CLIENT_SUBNET_OPCODE 472
#define VAR_MAX_CLIENT_SUBNET_IPV4 473
#define VAR_MAX_CLIENT_SUBNET_IPV6 474
#define VAR_MIN_CLIENT_SUBNET_IPV4 475
#define VAR_MIN_CLIENT_SUBNET_IPV6 476
#define VAR_MAX_ECS_TREE_SIZE_IPV4 477
#define VAR_MAX_ECS_TREE_SIZE_IPV6 478
#define VAR_CAPS_WHITELIST 479
#define VAR_CACHE_MAX_NEGATIVE_TTL 480
#define VAR_PERMIT_SMALL_HOLDDOWN 481
#define VAR_CACHE_MIN_NEGATIVE_TTL 482
#define VAR_QNAME_MINIMISATION 483
#define VAR_QNAME_MINIMISATION_STRICT 484
#define VAR_IP_FREEBIND 485
#define VAR_DEFINE_TAG 486
#define VAR_LOCAL_ZONE_TAG 487
#define VAR_ACCESS_CONTROL_TAG 488
#define VAR_LOCAL_ZONE_OVERRIDE 489
#define VAR_ACCESS_CONTROL_TAG_ACTION 490
#define VAR_ACCESS_CONTROL_TAG_DATA 491
#define VAR_VIEW 492
#define VAR_ACCESS_CONTROL_VIEW 493
#define VAR_VIEW_FIRST 494
#define VAR_SERVE_EXPIRED 495
#define VAR_SERVE_EXPIRED_TTL 496
#define VAR_SERVE_EXPIRED_TTL_RESET 497
#define VAR_SERVE_EXPIRED_REPLY_TTL 498
#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 499
#define VAR_EDE_SERVE_EXPIRED 500
#define VAR_SERVE_ORIGINAL_TTL 501
#define VAR_FAKE_DSA 502
#define VAR_FAKE_SHA1 503
#define VAR_LOG_IDENTITY 504
#define VAR_HIDE_TRUSTANCHOR 505
#define VAR_HIDE_HTTP_USER_AGENT 506
#define VAR_HTTP_USER_AGENT 507
#define VAR_TRUST_ANCHOR_SIGNALING 508
#define VAR_AGGRESSIVE_NSEC 509
#define VAR_USE_SYSTEMD 510
#define VAR_SHM_ENABLE 511
#define VAR_SHM_KEY 512
#define VAR_ROOT_KEY_SENTINEL 513
#define VAR_DNSCRYPT 514
#define VAR_DNSCRYPT_ENABLE 515
#define VAR_DNSCRYPT_PORT 516
#define VAR_DNSCRYPT_PROVIDER 517
#define VAR_DNSCRYPT_SECRET_KEY 518
#define VAR_DNSCRYPT_PROVIDER_CERT 519
#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 520
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 521
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 522
#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 523
#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 524
#define VAR_PAD_RESPONSES 525
#define VAR_PAD_RESPONSES_BLOCK_SIZE 526
#define VAR_PAD_QUERIES 527
#define VAR_PAD_QUERIES_BLOCK_SIZE 528
#define VAR_IPSECMOD_ENABLED 529
#define VAR_IPSECMOD_HOOK 530
#define VAR_IPSECMOD_IGNORE_BOGUS 531
#define VAR_IPSECMOD_MAX_TTL 532
#define VAR_IPSECMOD_WHITELIST 533
#define VAR_IPSECMOD_STRICT 534
#define VAR_CACHEDB 535
#define VAR_CACHEDB_BACKEND 536
#define VAR_CACHEDB_SECRETSEED 537
#define VAR_CACHEDB_REDISHOST 538
#define VAR_CACHEDB_REDISPORT 539
#define VAR_CACHEDB_REDISTIMEOUT 540
#define VAR_CACHEDB_REDISEXPIRERECORDS 541
#define VAR_CACHEDB_REDISPATH 542
#define VAR_CACHEDB_REDISPASSWORD 543
#define VAR_CACHEDB_REDISLOGICALDB 544
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 545
#define VAR_FOR_UPSTREAM 546
#define VAR_AUTH_ZONE 547
#define VAR_ZONEFILE 548
#define VAR_MASTER 549
#define VAR_URL 550
#define VAR_FOR_DOWNSTREAM 551
#define VAR_FALLBACK_ENABLED 552
#define VAR_TLS_ADDITIONAL_PORT 553
#define VAR_LOW_RTT 554
#define VAR_LOW_RTT_PERMIL 555
#define VAR_FAST_SERVER_PERMIL 556
#define VAR_FAST_SERVER_NUM 557
#define VAR_ALLOW_NOTIFY 558
#define VAR_TLS_WIN_CERT 559
#define VAR_TCP_CONNECTION_LIMIT 560
#define VAR_ANSWER_COOKIE 561
#define VAR_COOKIE_SECRET 562
#define VAR_IP_RATELIMIT_COOKIE 563
#define VAR_FORWARD_NO_CACHE 564
#define VAR_STUB_NO_CACHE 565
#define VAR_LOG_SERVFAIL 566
#define VAR_DENY_ANY 567
#define VAR_UNKNOWN_SERVER_TIME_LIMIT 568
#define VAR_LOG_TAG_QUERYREPLY 569
#define VAR_DISCARD_TIMEOUT 570
#define VAR_WAIT_LIMIT 571
#define VAR_WAIT_LIMIT_COOKIE 572
#define VAR_WAIT_LIMIT_NETBLOCK 573
#define VAR_WAIT_LIMIT_COOKIE_NETBLOCK 574
#define VAR_STREAM_WAIT_SIZE 575
#define VAR_TLS_CIPHERS 576
#define VAR_TLS_CIPHERSUITES 577
#define VAR_TLS_USE_SNI 578
#define VAR_IPSET 579
#define VAR_IPSET_NAME_V4 580
#define VAR_IPSET_NAME_V6 581
#define VAR_TLS_SESSION_TICKET_KEYS 582
#define VAR_RPZ 583
#define VAR_TAGS 584
#define VAR_RPZ_ACTION_OVERRIDE 585
#define VAR_RPZ_CNAME_OVERRIDE 586
#define VAR_RPZ_LOG 587
#define VAR_RPZ_LOG_NAME 588
#define VAR_DYNLIB 589
#define VAR_DYNLIB_FILE 590
#define VAR_EDNS_CLIENT_STRING 591
#define VAR_EDNS_CLIENT_STRING_OPCODE 592
#define VAR_NSID 593
#define VAR_ZONEMD_PERMISSIVE_MODE 594
#define VAR_ZONEMD_CHECK 595
#define VAR_ZONEMD_REJECT_ABSENCE 596
#define VAR_RPZ_SIGNAL_NXDOMAIN_RA 597
#define VAR_INTERFACE_AUTOMATIC_PORTS 598
#define VAR_EDE 599
#define VAR_INTERFACE_ACTION 600
#define VAR_INTERFACE_VIEW 601
#define VAR_INTERFACE_TAG 602
#define VAR_INTERFACE_TAG_ACTION 603
#define VAR_INTERFACE_TAG_DATA 604
#define VAR_PROXY_PROTOCOL_PORT 605
#define VAR_STATISTICS_INHIBIT_ZERO 606
#define VAR_HARDEN_UNKNOWN_ADDITIONAL 607
#define VAR_DISABLE_EDNS_DO 608
#define VAR_CACHEDB_NO_STORE 609
#define VAR_LOG_DESTADDR 610
#define VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED 611
#define VAR_COOKIE_SECRET_FILE 612
#ifndef YYSTYPE_DEFINED
#define YYSTYPE_DEFINED
typedef union {

View file

@ -137,6 +137,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
%token VAR_DNSTAP_SAMPLE_RATE
%token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
%token VAR_IP_DSCP
@ -204,6 +205,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO
%token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO VAR_CACHEDB_NO_STORE
%token VAR_LOG_DESTADDR VAR_CACHEDB_CHECK_WHEN_SERVE_EXPIRED
%token VAR_COOKIE_SECRET_FILE
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -341,7 +343,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_interface_automatic_ports | server_ede |
server_proxy_protocol_port | server_statistics_inhibit_zero |
server_harden_unknown_additional | server_disable_edns_do |
server_log_destaddr
server_log_destaddr | server_cookie_secret_file
;
stubstart: VAR_STUB_ZONE
{
@ -357,8 +359,14 @@ stubstart: VAR_STUB_ZONE
}
}
;
contents_stub: contents_stub content_stub
| ;
contents_stub: content_stub contents_stub
|
{
/* stub end */
if(cfg_parser->cfg->stubs &&
!cfg_parser->cfg->stubs->name)
yyerror("stub-zone without name");
};
content_stub: stub_name | stub_host | stub_addr | stub_prime | stub_first |
stub_no_cache | stub_ssl_upstream | stub_tcp_upstream
;
@ -376,8 +384,14 @@ forwardstart: VAR_FORWARD_ZONE
}
}
;
contents_forward: contents_forward content_forward
| ;
contents_forward: content_forward contents_forward
|
{
/* forward end */
if(cfg_parser->cfg->forwards &&
!cfg_parser->cfg->forwards->name)
yyerror("forward-zone without name");
};
content_forward: forward_name | forward_host | forward_addr | forward_first |
forward_no_cache | forward_ssl_upstream | forward_tcp_upstream
;
@ -389,16 +403,20 @@ viewstart: VAR_VIEW
s = (struct config_view*)calloc(1, sizeof(struct config_view));
if(s) {
s->next = cfg_parser->cfg->views;
if(s->next && !s->next->name)
yyerror("view without name");
cfg_parser->cfg->views = s;
} else {
yyerror("out of memory");
}
}
;
contents_view: contents_view content_view
| ;
contents_view: content_view contents_view
|
{
/* view end */
if(cfg_parser->cfg->views &&
!cfg_parser->cfg->views->name)
yyerror("view without name");
};
content_view: view_name | view_local_zone | view_local_data | view_first |
view_response_ip | view_response_ip_data | view_local_data_ptr
;
@ -3437,7 +3455,8 @@ content_dt: dt_dnstap_enable | dt_dnstap_socket_path | dt_dnstap_bidirectional |
dt_dnstap_log_client_query_messages |
dt_dnstap_log_client_response_messages |
dt_dnstap_log_forwarder_query_messages |
dt_dnstap_log_forwarder_response_messages
dt_dnstap_log_forwarder_response_messages |
dt_dnstap_sample_rate
;
dt_dnstap_enable: VAR_DNSTAP_ENABLE STRING_ARG
{
@ -3601,6 +3620,17 @@ dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MES
free($2);
}
;
dt_dnstap_sample_rate: VAR_DNSTAP_SAMPLE_RATE STRING_ARG
{
OUTYY(("P(dt_dnstap_sample_rate:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else if(atoi($2) < 0)
yyerror("dnstap sample rate too small");
else cfg_parser->cfg->dnstap_sample_rate = atoi($2);
free($2);
}
;
pythonstart: VAR_PYTHON
{
OUTYY(("\nP(python:)\n"));
@ -3969,6 +3999,13 @@ server_cookie_secret: VAR_COOKIE_SECRET STRING_ARG
free($2);
}
;
server_cookie_secret_file: VAR_COOKIE_SECRET_FILE STRING_ARG
{
OUTYY(("P(cookie_secret_file:%s)\n", $2));
free(cfg_parser->cfg->cookie_secret_file);
cfg_parser->cfg->cookie_secret_file = $2;
}
;
ipsetstart: VAR_IPSET
{
OUTYY(("\nP(ipset:)\n"));

View file

@ -225,7 +225,7 @@ int dname_strict_subdomain(uint8_t* d1, int labs1, uint8_t* d2, int labs2);
int dname_strict_subdomain_c(uint8_t* d1, uint8_t* d2);
/**
* Counts labels. Tests is d1 is a subdomain of d2.
* Counts labels. Tests if d1 is a subdomain of d2.
* @param d1: domain name, uncompressed wireformat
* @param d2: domain name, uncompressed wireformat
* @return true if d1 is a subdomain of d2.

View file

@ -947,7 +947,8 @@ parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region)
static int
parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
struct edns_data* edns, struct config_file* cfg, struct comm_point* c,
struct comm_reply* repinfo, uint32_t now, struct regional* region)
struct comm_reply* repinfo, uint32_t now, struct regional* region,
struct cookie_secrets* cookie_secrets)
{
/* To respond with a Keepalive option, the client connection must have
* received one message with a TCP Keepalive EDNS option, and that
@ -1070,13 +1071,24 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
&((struct sockaddr_in6*)&repinfo->remote_addr)->sin6_addr, 16);
}
if(cfg->cookie_secret_file &&
cfg->cookie_secret_file[0]) {
/* Loop over the active and staging cookies. */
cookie_val_status =
cookie_secrets_server_validate(
rdata_ptr, opt_len, cookie_secrets,
cookie_is_v4, server_cookie, now);
} else {
/* Use the cookie option value to validate. */
cookie_val_status = edns_cookie_server_validate(
rdata_ptr, opt_len, cfg->cookie_secret,
cfg->cookie_secret_len, cookie_is_v4,
server_cookie, now);
}
if(cookie_val_status == COOKIE_STATUS_VALID_RENEW)
edns->cookie_valid = 1;
switch(cookie_val_status) {
case COOKIE_STATUS_VALID:
case COOKIE_STATUS_VALID_RENEW:
edns->cookie_valid = 1;
/* Reuse cookie */
if(!edns_opt_list_append(
@ -1091,13 +1103,30 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
break;
case COOKIE_STATUS_CLIENT_ONLY:
edns->cookie_client = 1;
ATTR_FALLTHROUGH
/* fallthrough */
case COOKIE_STATUS_VALID_RENEW:
case COOKIE_STATUS_FUTURE:
case COOKIE_STATUS_EXPIRED:
case COOKIE_STATUS_INVALID:
default:
if(cfg->cookie_secret_file &&
cfg->cookie_secret_file[0]) {
if(!cookie_secrets)
break;
lock_basic_lock(&cookie_secrets->lock);
if(cookie_secrets->cookie_count < 1) {
lock_basic_unlock(&cookie_secrets->lock);
break;
}
edns_cookie_server_write(server_cookie,
cookie_secrets->cookie_secrets[0].cookie_secret,
cookie_is_v4, now);
lock_basic_unlock(&cookie_secrets->lock);
} else {
edns_cookie_server_write(server_cookie,
cfg->cookie_secret, cookie_is_v4, now);
}
if(!edns_opt_list_append(&edns->opt_list_out,
LDNS_EDNS_COOKIE, 24, server_cookie,
region)) {
@ -1239,7 +1268,8 @@ skip_pkt_rrs(sldns_buffer* pkt, int num)
int
parse_edns_from_query_pkt(sldns_buffer* pkt, struct edns_data* edns,
struct config_file* cfg, struct comm_point* c,
struct comm_reply* repinfo, time_t now, struct regional* region)
struct comm_reply* repinfo, time_t now, struct regional* region,
struct cookie_secrets* cookie_secrets)
{
size_t rdata_len;
uint8_t* rdata_ptr;
@ -1285,7 +1315,7 @@ parse_edns_from_query_pkt(sldns_buffer* pkt, struct edns_data* edns,
rdata_ptr = sldns_buffer_current(pkt);
/* ignore rrsigs */
return parse_edns_options_from_query(rdata_ptr, rdata_len, edns, cfg,
c, repinfo, now, region);
c, repinfo, now, region, cookie_secrets);
}
void

View file

@ -73,6 +73,7 @@ struct edns_option;
struct config_file;
struct comm_point;
struct comm_reply;
struct cookie_secrets;
/** number of buckets in parse rrset hash table. Must be power of 2. */
#define PARSE_TABLE_SIZE 32
@ -322,12 +323,14 @@ int skip_pkt_rrs(struct sldns_buffer* pkt, int num);
* @param repinfo: commreply to determine the client address
* @param now: current time
* @param region: region to alloc results in (edns option contents)
* @param cookie_secrets: the cookie secrets for EDNS COOKIE validation.
* @return: 0 on success, or an RCODE on error.
* RCODE formerr if OPT is badly formatted and so on.
*/
int parse_edns_from_query_pkt(struct sldns_buffer* pkt, struct edns_data* edns,
struct config_file* cfg, struct comm_point* c,
struct comm_reply* repinfo, time_t now, struct regional* region);
struct comm_reply* repinfo, time_t now, struct regional* region,
struct cookie_secrets* cookie_secrets);
/**
* Calculate hash value for rrset in packet.

View file

@ -187,3 +187,189 @@ edns_cookie_server_validate(const uint8_t* cookie, size_t cookie_len,
return COOKIE_STATUS_VALID_RENEW;
return COOKIE_STATUS_VALID;
}
struct cookie_secrets*
cookie_secrets_create(void)
{
struct cookie_secrets* cookie_secrets = calloc(1,
sizeof(*cookie_secrets));
if(!cookie_secrets)
return NULL;
lock_basic_init(&cookie_secrets->lock);
lock_protect(&cookie_secrets->lock, &cookie_secrets->cookie_count,
sizeof(cookie_secrets->cookie_count));
lock_protect(&cookie_secrets->lock, cookie_secrets->cookie_secrets,
sizeof(cookie_secret_type)*UNBOUND_COOKIE_HISTORY_SIZE);
return cookie_secrets;
}
void
cookie_secrets_delete(struct cookie_secrets* cookie_secrets)
{
if(!cookie_secrets)
return;
lock_basic_destroy(&cookie_secrets->lock);
explicit_bzero(cookie_secrets->cookie_secrets,
sizeof(cookie_secret_type)*UNBOUND_COOKIE_HISTORY_SIZE);
free(cookie_secrets);
}
/** Read the cookie secret file */
static int
cookie_secret_file_read(struct cookie_secrets* cookie_secrets,
char* cookie_secret_file)
{
char secret[UNBOUND_COOKIE_SECRET_SIZE * 2 + 2/*'\n' and '\0'*/];
FILE* f;
int corrupt = 0;
size_t count;
log_assert(cookie_secret_file != NULL);
cookie_secrets->cookie_count = 0;
f = fopen(cookie_secret_file, "r");
/* a non-existing cookie file is not an error */
if( f == NULL ) {
if(errno != EPERM) {
log_err("Could not read cookie-secret-file '%s': %s",
cookie_secret_file, strerror(errno));
return 0;
}
return 1;
}
/* cookie secret file exists and is readable */
for( count = 0; count < UNBOUND_COOKIE_HISTORY_SIZE; count++ ) {
size_t secret_len = 0;
ssize_t decoded_len = 0;
if( fgets(secret, sizeof(secret), f) == NULL ) { break; }
secret_len = strlen(secret);
if( secret_len == 0 ) { break; }
log_assert( secret_len <= sizeof(secret) );
secret_len = secret[secret_len - 1] == '\n' ? secret_len - 1 : secret_len;
if( secret_len != UNBOUND_COOKIE_SECRET_SIZE * 2 ) { corrupt++; break; }
/* needed for `hex_pton`; stripping potential `\n` */
secret[secret_len] = '\0';
decoded_len = hex_pton(secret, cookie_secrets->cookie_secrets[count].cookie_secret,
UNBOUND_COOKIE_SECRET_SIZE);
if( decoded_len != UNBOUND_COOKIE_SECRET_SIZE ) { corrupt++; break; }
cookie_secrets->cookie_count++;
}
fclose(f);
return corrupt == 0;
}
int
cookie_secrets_apply_cfg(struct cookie_secrets* cookie_secrets,
char* cookie_secret_file)
{
if(!cookie_secrets) {
if(!cookie_secret_file || !cookie_secret_file[0])
return 1; /* There is nothing to read anyway */
log_err("Could not read cookie secrets, no structure alloced");
return 0;
}
if(!cookie_secret_file_read(cookie_secrets, cookie_secret_file))
return 0;
return 1;
}
enum edns_cookie_val_status
cookie_secrets_server_validate(const uint8_t* cookie, size_t cookie_len,
struct cookie_secrets* cookie_secrets, int v4,
const uint8_t* hash_input, uint32_t now)
{
size_t i;
enum edns_cookie_val_status cookie_val_status,
last = COOKIE_STATUS_INVALID;
if(!cookie_secrets)
return COOKIE_STATUS_INVALID; /* There are no cookie secrets.*/
lock_basic_lock(&cookie_secrets->lock);
if(cookie_secrets->cookie_count == 0) {
lock_basic_unlock(&cookie_secrets->lock);
return COOKIE_STATUS_INVALID; /* There are no cookie secrets.*/
}
for(i=0; i<cookie_secrets->cookie_count; i++) {
cookie_val_status = edns_cookie_server_validate(cookie,
cookie_len,
cookie_secrets->cookie_secrets[i].cookie_secret,
UNBOUND_COOKIE_SECRET_SIZE, v4, hash_input, now);
if(cookie_val_status == COOKIE_STATUS_VALID ||
cookie_val_status == COOKIE_STATUS_VALID_RENEW) {
lock_basic_unlock(&cookie_secrets->lock);
/* For staging cookies, write a fresh cookie. */
if(i != 0)
return COOKIE_STATUS_VALID_RENEW;
return cookie_val_status;
}
if(last == COOKIE_STATUS_INVALID)
last = cookie_val_status; /* Store more interesting
failure to return. */
}
lock_basic_unlock(&cookie_secrets->lock);
return last;
}
void add_cookie_secret(struct cookie_secrets* cookie_secrets,
uint8_t* secret, size_t secret_len)
{
log_assert(secret_len == UNBOUND_COOKIE_SECRET_SIZE);
(void)secret_len;
if(!cookie_secrets)
return;
/* New cookie secret becomes the staging secret (position 1)
* unless there is no active cookie yet, then it becomes the active
* secret. If the UNBOUND_COOKIE_HISTORY_SIZE > 2 then all staging cookies
* are moved one position down.
*/
if(cookie_secrets->cookie_count == 0) {
memcpy( cookie_secrets->cookie_secrets->cookie_secret
, secret, UNBOUND_COOKIE_SECRET_SIZE);
cookie_secrets->cookie_count = 1;
explicit_bzero(secret, UNBOUND_COOKIE_SECRET_SIZE);
return;
}
#if UNBOUND_COOKIE_HISTORY_SIZE > 2
memmove( &cookie_secrets->cookie_secrets[2], &cookie_secrets->cookie_secrets[1]
, sizeof(struct cookie_secret) * (UNBOUND_COOKIE_HISTORY_SIZE - 2));
#endif
memcpy( cookie_secrets->cookie_secrets[1].cookie_secret
, secret, UNBOUND_COOKIE_SECRET_SIZE);
cookie_secrets->cookie_count = cookie_secrets->cookie_count < UNBOUND_COOKIE_HISTORY_SIZE
? cookie_secrets->cookie_count + 1 : UNBOUND_COOKIE_HISTORY_SIZE;
explicit_bzero(secret, UNBOUND_COOKIE_SECRET_SIZE);
}
void activate_cookie_secret(struct cookie_secrets* cookie_secrets)
{
uint8_t active_secret[UNBOUND_COOKIE_SECRET_SIZE];
if(!cookie_secrets)
return;
/* The staging secret becomes the active secret.
* The active secret becomes a staging secret.
* If the UNBOUND_COOKIE_HISTORY_SIZE > 2 then all staging secrets are moved
* one position up and the previously active secret becomes the last
* staging secret.
*/
if(cookie_secrets->cookie_count < 2)
return;
memcpy( active_secret, cookie_secrets->cookie_secrets[0].cookie_secret
, UNBOUND_COOKIE_SECRET_SIZE);
memmove( &cookie_secrets->cookie_secrets[0], &cookie_secrets->cookie_secrets[1]
, sizeof(struct cookie_secret) * (UNBOUND_COOKIE_HISTORY_SIZE - 1));
memcpy( cookie_secrets->cookie_secrets[cookie_secrets->cookie_count - 1].cookie_secret
, active_secret, UNBOUND_COOKIE_SECRET_SIZE);
explicit_bzero(active_secret, UNBOUND_COOKIE_SECRET_SIZE);
}
void drop_cookie_secret(struct cookie_secrets* cookie_secrets)
{
if(!cookie_secrets)
return;
/* Drops a staging cookie secret. If there are more than one, it will
* drop the last staging secret. */
if(cookie_secrets->cookie_count < 2)
return;
explicit_bzero( cookie_secrets->cookie_secrets[cookie_secrets->cookie_count - 1].cookie_secret
, UNBOUND_COOKIE_SECRET_SIZE);
cookie_secrets->cookie_count -= 1;
}

View file

@ -43,6 +43,7 @@
#define UTIL_EDNS_H
#include "util/storage/dnstree.h"
#include "util/locks.h"
struct edns_data;
struct config_file;
@ -75,6 +76,31 @@ struct edns_string_addr {
size_t string_len;
};
#define UNBOUND_COOKIE_HISTORY_SIZE 2
#define UNBOUND_COOKIE_SECRET_SIZE 16
typedef struct cookie_secret cookie_secret_type;
struct cookie_secret {
/** cookie secret */
uint8_t cookie_secret[UNBOUND_COOKIE_SECRET_SIZE];
};
/**
* The cookie secrets from the cookie-secret-file.
*/
struct cookie_secrets {
/** lock on the structure, in case there are modifications
* from remote control, this avoids race conditions. */
lock_basic_type lock;
/** how many cookies are there in the cookies array */
size_t cookie_count;
/* keep track of the last `UNBOUND_COOKIE_HISTORY_SIZE`
* cookies as per rfc requirement .*/
cookie_secret_type cookie_secrets[UNBOUND_COOKIE_HISTORY_SIZE];
};
enum edns_cookie_val_status {
COOKIE_STATUS_CLIENT_ONLY = -3,
COOKIE_STATUS_FUTURE = -2,
@ -165,4 +191,63 @@ enum edns_cookie_val_status edns_cookie_server_validate(const uint8_t* cookie,
size_t cookie_len, const uint8_t* secret, size_t secret_len, int v4,
const uint8_t* hash_input, uint32_t now);
/**
* Create the cookie secrets structure.
* @return the structure or NULL on failure.
*/
struct cookie_secrets* cookie_secrets_create(void);
/**
* Delete the cookie secrets.
* @param cookie_secrets: the cookie secrets.
*/
void cookie_secrets_delete(struct cookie_secrets* cookie_secrets);
/**
* Apply configuration to cookie secrets, read them from file.
* @param cookie_secrets: the cookie secrets structure.
* @param cookie_secret_file: the file name, it is read.
* @return false on failure.
*/
int cookie_secrets_apply_cfg(struct cookie_secrets* cookie_secrets,
char* cookie_secret_file);
/**
* Validate the cookie secrets, try all of them.
* @param cookie: pointer to the cookie data.
* @param cookie_len: the length of the cookie data.
* @param cookie_secrets: struct of cookie secrets.
* @param v4: if the client IP is v4 or v6.
* @param hash_input: pointer to the hash input for validation. It needs to be:
* Client Cookie | Version | Reserved | Timestamp | Client-IP
* @param now: the current time.
* return edns_cookie_val_status with the cookie validation status i.e.,
* <=0 for invalid, else valid.
*/
enum edns_cookie_val_status cookie_secrets_server_validate(
const uint8_t* cookie, size_t cookie_len,
struct cookie_secrets* cookie_secrets, int v4,
const uint8_t* hash_input, uint32_t now);
/**
* Add a cookie secret. If there are no secrets yet, the secret will become
* the active secret. Otherwise it will become the staging secret.
* Active secrets are used to both verify and create new DNS Cookies.
* Staging secrets are only used to verify DNS Cookies. Caller has to lock.
*/
void add_cookie_secret(struct cookie_secrets* cookie_secrets, uint8_t* secret,
size_t secret_len);
/**
* Makes the staging cookie secret active and the active secret staging.
* Caller has to lock.
*/
void activate_cookie_secret(struct cookie_secrets* cookie_secrets);
/**
* Drop a cookie secret. Drops the staging secret. An active secret will not
* be dropped. Caller has to lock.
*/
void drop_cookie_secret(struct cookie_secrets* cookie_secrets);
#endif

View file

@ -448,6 +448,28 @@ fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
return 0;
}
int
fptr_whitelist_mod_startup(int (*fptr)(struct module_env* env, int id))
{
#ifdef USE_IPSET
if(fptr == &ipset_startup) return 1;
#else
(void)fptr;
#endif
return 0;
}
int
fptr_whitelist_mod_destartup(void (*fptr)(struct module_env* env, int id))
{
#ifdef USE_IPSET
if(fptr == &ipset_destartup) return 1;
#else
(void)fptr;
#endif
return 0;
}
int
fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate,
enum module_ev event, int id, struct outbound_entry* outbound))

View file

@ -278,6 +278,22 @@ int fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id));
*/
int fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id));
/**
* Check function pointer whitelist for module startup call values.
*
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_mod_startup(int (*fptr)(struct module_env* env, int id));
/**
* Check function pointer whitelist for module destartup call values.
*
* @param fptr: function pointer to check.
* @return false if not in whitelist.
*/
int fptr_whitelist_mod_destartup(void (*fptr)(struct module_env* env, int id));
/**
* Check function pointer whitelist for module operate call values.
*

View file

@ -143,7 +143,7 @@
* also contain an rcode that is nonzero, but in this case additional
* information (query, additional) can be passed along.
*
* The rcode and dns_msg are used to pass the result from the the rightmost
* The rcode and dns_msg are used to pass the result from the rightmost
* module towards the leftmost modules and then towards the user.
*
* If you want to avoid recursion-cycles where queries need other queries
@ -713,7 +713,28 @@ struct module_func_block {
const char* name;
/**
* init the module. Called once for the global state.
* Set up the module for start. This is called only once at startup.
* Privileged operations like opening device files may be done here.
* The function ptr can be NULL, if it is not used.
* @param env: module environment.
* @param id: module id number.
* return: 0 on error
*/
int (*startup)(struct module_env* env, int id);
/**
* Close down the module for stop. This is called only once before
* shutdown to free resources allocated during startup().
* Closing privileged ports or files must be done here.
* The function ptr can be NULL, if it is not used.
* @param env: module environment.
* @param id: module id number.
*/
void (*destartup)(struct module_env* env, int id);
/**
* Initialise the module. Called when restarting or reloading the
* daemon.
* This is the place to apply settings from the config file.
* @param env: module environment.
* @param id: module id number.
@ -722,7 +743,8 @@ struct module_func_block {
int (*init)(struct module_env* env, int id);
/**
* de-init, delete, the module. Called once for the global state.
* Deinitialise the module, undo stuff done during init().
* Called before reloading the daemon.
* @param env: module environment.
* @param id: module id number.
*/

View file

@ -47,6 +47,7 @@
#ifdef HAVE_NETIOAPI_H
#include <netioapi.h>
#endif
#include <ctype.h>
#include "util/net_help.h"
#include "util/log.h"
#include "util/data/dname.h"
@ -862,6 +863,20 @@ addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen)
return (memcmp(s, map_prefix, 12) == 0);
}
int addr_is_ip6linklocal(struct sockaddr_storage* addr, socklen_t addrlen)
{
const uint8_t prefix[2] = {0xfe, 0x80};
int af = (int)((struct sockaddr_in6*)addr)->sin6_family;
void* sin6addr = &((struct sockaddr_in6*)addr)->sin6_addr;
uint8_t start[2];
if(af != AF_INET6 || addrlen<(socklen_t)sizeof(struct sockaddr_in6))
return 0;
/* Put the first 10 bits of sin6addr in start, match fe80::/10. */
memmove(start, sin6addr, 2);
start[1] &= 0xc0;
return memcmp(start, prefix, 2) == 0;
}
int addr_is_broadcast(struct sockaddr_storage* addr, socklen_t addrlen)
{
int af = (int)((struct sockaddr_in*)addr)->sin_family;
@ -1206,7 +1221,7 @@ listen_sslctx_setup_2(void* ctxt)
if(!SSL_CTX_set_ecdh_auto(ctx,1)) {
log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE");
}
#elif defined(USE_ECDSA)
#elif defined(USE_ECDSA) && defined(HAVE_SSL_CTX_SET_TMP_ECDH)
if(1) {
EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
if (!ecdh) {
@ -1857,3 +1872,42 @@ sock_close(int socket)
closesocket(socket);
}
# endif /* USE_WINSOCK */
ssize_t
hex_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize)
{
static char hexdigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
size_t i;
if (targsize < srclength * 2 + 1) {
return -1;
}
for (i = 0; i < srclength; ++i) {
*target++ = hexdigits[src[i] >> 4U];
*target++ = hexdigits[src[i] & 0xfU];
}
*target = '\0';
return 2 * srclength;
}
ssize_t
hex_pton(const char* src, uint8_t* target, size_t targsize)
{
uint8_t *t = target;
if(strlen(src) % 2 != 0 || strlen(src)/2 > targsize) {
return -1;
}
while(*src) {
if(!isxdigit((unsigned char)src[0]) ||
!isxdigit((unsigned char)src[1]))
return -1;
*t++ = sldns_hexdigit_to_int(src[0]) * 16 +
sldns_hexdigit_to_int(src[1]) ;
src += 2;
}
return t-target;
}

View file

@ -362,6 +362,14 @@ void addr_to_nat64(const struct sockaddr_storage* addr,
*/
int addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen);
/**
* See if sockaddr is an ipv6 fe80::/10 link local address.
* @param addr: address
* @param addrlen: length of address
* @return true if so
*/
int addr_is_ip6linklocal(struct sockaddr_storage* addr, socklen_t addrlen);
/**
* See if sockaddr is 255.255.255.255.
* @param addr: address
@ -564,4 +572,13 @@ char* sock_strerror(int errn);
/** close the socket with close, or wsa closesocket */
void sock_close(int socket);
/**
* Convert binary data to a string of hexadecimal characters.
*/
ssize_t hex_ntop(uint8_t const *src, size_t srclength, char *target,
size_t targsize);
/** Convert hexadecimal data to binary. */
ssize_t hex_pton(const char* src, uint8_t* target, size_t targsize);
#endif /* NET_HELP_H */

View file

@ -329,6 +329,7 @@ udp_send_errno_needs_log(struct sockaddr* addr, socklen_t addrlen)
case EACCES:
if(verbosity < VERB_ALGO)
return 0;
break;
default:
break;
}
@ -2365,11 +2366,11 @@ recv_error:
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return 1;
if(recv_initial) {
#ifdef ECONNRESET
if(errno == ECONNRESET && verbosity < 2)
return 0; /* silence reset by peer */
#endif
if(recv_initial) {
#ifdef ECONNREFUSED
if(errno == ECONNREFUSED && verbosity < 2)
return 0; /* silence reset by peer */
@ -2396,7 +2397,7 @@ recv_error:
#endif
#ifdef ENOTCONN
if(errno == ENOTCONN) {
log_err_addr("read (in tcp s) failed and this "
log_err_addr("read (in tcp initial) failed and this "
"could be because TCP Fast Open is "
"enabled [--disable-tfo-client "
"--disable-tfo-server] but does not "
@ -2430,8 +2431,9 @@ recv_error:
return 1;
}
#endif
log_err_addr("read (in tcp s)", sock_strerror(errno),
&c->repinfo.remote_addr, c->repinfo.remote_addrlen);
log_err_addr((recv_initial?"read (in tcp initial)":"read (in tcp)"),
sock_strerror(errno), &c->repinfo.remote_addr,
c->repinfo.remote_addrlen);
return 0;
}
@ -3306,6 +3308,13 @@ void http2_stream_add_meshstate(struct http2_stream* h2_stream,
h2_stream->mesh_state = m;
}
void http2_stream_remove_mesh_state(struct http2_stream* h2_stream)
{
if(!h2_stream)
return;
h2_stream->mesh_state = NULL;
}
/** delete http2 session server. After closing connection. */
static void http2_session_server_delete(struct http2_session* h2_session)
{

View file

@ -955,6 +955,9 @@ void http2_session_add_stream(struct http2_session* h2_session,
void http2_stream_add_meshstate(struct http2_stream* h2_stream,
struct mesh_area* mesh, struct mesh_state* m);
/** Remove mesh state from stream. When the mesh state has been removed. */
void http2_stream_remove_mesh_state(struct http2_stream* h2_stream);
/**
* This routine is published for checks and tests, and is only used internally.
* handle libevent callback for timer comm.

View file

@ -153,6 +153,7 @@ pp2_write_to_buf(uint8_t* buf, size_t buflen,
break;
#endif /* INET6 */
case AF_UNIX:
ATTR_FALLTHROUGH
/* fallthrough */
default:
return 0;

View file

@ -128,26 +128,32 @@ int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
case 7:
b |= ((uint64_t)in[6]) << 48;
/** EDIT annotate case statement fallthrough for gcc */
ATTR_FALLTHROUGH
/* fallthrough */
case 6:
b |= ((uint64_t)in[5]) << 40;
/** EDIT annotate case statement fallthrough for gcc */
ATTR_FALLTHROUGH
/* fallthrough */
case 5:
b |= ((uint64_t)in[4]) << 32;
/** EDIT annotate case statement fallthrough for gcc */
ATTR_FALLTHROUGH
/* fallthrough */
case 4:
b |= ((uint64_t)in[3]) << 24;
/** EDIT annotate case statement fallthrough for gcc */
ATTR_FALLTHROUGH
/* fallthrough */
case 3:
b |= ((uint64_t)in[2]) << 16;
/** EDIT annotate case statement fallthrough for gcc */
ATTR_FALLTHROUGH
/* fallthrough */
case 2:
b |= ((uint64_t)in[1]) << 8;
/** EDIT annotate case statement fallthrough for gcc */
ATTR_FALLTHROUGH
/* fallthrough */
case 1:
b |= ((uint64_t)in[0]);

View file

@ -254,11 +254,15 @@ uint32_t initval) /* the previous hash, or an arbitrary value */
switch(length) /* all the case statements fall through */
{
case 3 : c+=k[2];
ATTR_FALLTHROUGH
/* fallthrough */
case 2 : b+=k[1];
ATTR_FALLTHROUGH
/* fallthrough */
case 1 : a+=k[0];
final(a,b,c);
ATTR_FALLTHROUGH
/* fallthrough */
case 0: /* case 0: nothing left to add */
break;
}
@ -304,9 +308,15 @@ uint32_t *pb) /* IN: more seed OUT: secondary hash value */
switch(length) /* all the case statements fall through */
{
case 3 : c+=k[2];
ATTR_FALLTHROUGH
/* fallthrough */
case 2 : b+=k[1];
ATTR_FALLTHROUGH
/* fallthrough */
case 1 : a+=k[0];
final(a,b,c);
ATTR_FALLTHROUGH
/* fallthrough */
case 0: /* case 0: nothing left to add */
break;
}
@ -404,16 +414,32 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
switch(length)
{
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
case 9 : c+=k8[8]; /* fall through */
case 11: c+=((uint32_t)k8[10])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 10: c+=((uint32_t)k8[9])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 9 : c+=k8[8];
ATTR_FALLTHROUGH
/* fallthrough */
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
case 5 : b+=k8[4]; /* fall through */
case 7 : b+=((uint32_t)k8[6])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 6 : b+=((uint32_t)k8[5])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 5 : b+=k8[4];
ATTR_FALLTHROUGH
/* fallthrough */
case 4 : a+=k[0]; break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
case 3 : a+=((uint32_t)k8[2])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 2 : a+=((uint32_t)k8[1])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 1 : a+=k8[0]; break;
case 0 : return c;
}
@ -443,23 +469,33 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 11: c+=((uint32_t)k8[10])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 10: c+=k[4];
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 9 : c+=k8[8]; /* fall through */
case 9 : c+=k8[8];
ATTR_FALLTHROUGH
/* fallthrough */
case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 7 : b+=((uint32_t)k8[6])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 6 : b+=k[2];
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 5 : b+=k8[4]; /* fall through */
case 5 : b+=k8[4];
ATTR_FALLTHROUGH
/* fallthrough */
case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 3 : a+=((uint32_t)k8[2])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 2 : a+=k[0];
break;
case 1 : a+=k8[0];
@ -494,26 +530,37 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
switch(length) /* all the case statements fall through */
{
case 12: c+=((uint32_t)k[11])<<24;
ATTR_FALLTHROUGH
/* fallthrough */
case 11: c+=((uint32_t)k[10])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 10: c+=((uint32_t)k[9])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 9 : c+=k[8];
ATTR_FALLTHROUGH
/* fallthrough */
case 8 : b+=((uint32_t)k[7])<<24;
ATTR_FALLTHROUGH
/* fallthrough */
case 7 : b+=((uint32_t)k[6])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 6 : b+=((uint32_t)k[5])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 5 : b+=k[4];
ATTR_FALLTHROUGH
/* fallthrough */
case 4 : a+=((uint32_t)k[3])<<24;
ATTR_FALLTHROUGH
/* fallthrough */
case 3 : a+=((uint32_t)k[2])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 2 : a+=((uint32_t)k[1])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 1 : a+=k[0];
break;
@ -603,16 +650,32 @@ void hashlittle2(
switch(length)
{
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
case 9 : c+=k8[8]; /* fall through */
case 11: c+=((uint32_t)k8[10])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 10: c+=((uint32_t)k8[9])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 9 : c+=k8[8];
ATTR_FALLTHROUGH
/* fallthrough */
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
case 5 : b+=k8[4]; /* fall through */
case 7 : b+=((uint32_t)k8[6])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 6 : b+=((uint32_t)k8[5])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 5 : b+=k8[4];
ATTR_FALLTHROUGH
/* fallthrough */
case 4 : a+=k[0]; break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
case 3 : a+=((uint32_t)k8[2])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 2 : a+=((uint32_t)k8[1])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 1 : a+=k8[0]; break;
case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
}
@ -642,23 +705,33 @@ void hashlittle2(
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
case 11: c+=((uint32_t)k8[10])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 10: c+=k[4];
b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 9 : c+=k8[8]; /* fall through */
case 9 : c+=k8[8];
ATTR_FALLTHROUGH
/* fallthrough */
case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
case 7 : b+=((uint32_t)k8[6])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 6 : b+=k[2];
a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 5 : b+=k8[4]; /* fall through */
case 5 : b+=k8[4];
ATTR_FALLTHROUGH
/* fallthrough */
case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
break;
case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
case 3 : a+=((uint32_t)k8[2])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 2 : a+=k[0];
break;
case 1 : a+=k8[0];
@ -693,16 +766,38 @@ void hashlittle2(
switch(length) /* all the case statements fall through */
{
case 12: c+=((uint32_t)k[11])<<24;
ATTR_FALLTHROUGH
/* fallthrough */
case 11: c+=((uint32_t)k[10])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 10: c+=((uint32_t)k[9])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 9 : c+=k[8];
ATTR_FALLTHROUGH
/* fallthrough */
case 8 : b+=((uint32_t)k[7])<<24;
ATTR_FALLTHROUGH
/* fallthrough */
case 7 : b+=((uint32_t)k[6])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 6 : b+=((uint32_t)k[5])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 5 : b+=k[4];
ATTR_FALLTHROUGH
/* fallthrough */
case 4 : a+=((uint32_t)k[3])<<24;
ATTR_FALLTHROUGH
/* fallthrough */
case 3 : a+=((uint32_t)k[2])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 2 : a+=((uint32_t)k[1])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 1 : a+=k[0];
break;
case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */
@ -784,16 +879,32 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval)
switch(length) /* all the case statements fall through */
{
case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
case 11: c+=((uint32_t)k8[10])<<8; /* fall through */
case 10: c+=((uint32_t)k8[9])<<16; /* fall through */
case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */
case 11: c+=((uint32_t)k8[10])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 10: c+=((uint32_t)k8[9])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 9 : c+=((uint32_t)k8[8])<<24;
ATTR_FALLTHROUGH
/* fallthrough */
case 8 : b+=k[1]; a+=k[0]; break;
case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */
case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */
case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */
case 7 : b+=((uint32_t)k8[6])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 6 : b+=((uint32_t)k8[5])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 5 : b+=((uint32_t)k8[4])<<24;
ATTR_FALLTHROUGH
/* fallthrough */
case 4 : a+=k[0]; break;
case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */
case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */
case 3 : a+=((uint32_t)k8[2])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 2 : a+=((uint32_t)k8[1])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 1 : a+=((uint32_t)k8[0])<<24; break;
case 0 : return c;
}
@ -827,16 +938,38 @@ uint32_t hashbig( const void *key, size_t length, uint32_t initval)
switch(length) /* all the case statements fall through */
{
case 12: c+=k[11];
ATTR_FALLTHROUGH
/* fallthrough */
case 11: c+=((uint32_t)k[10])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 10: c+=((uint32_t)k[9])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 9 : c+=((uint32_t)k[8])<<24;
ATTR_FALLTHROUGH
/* fallthrough */
case 8 : b+=k[7];
ATTR_FALLTHROUGH
/* fallthrough */
case 7 : b+=((uint32_t)k[6])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 6 : b+=((uint32_t)k[5])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 5 : b+=((uint32_t)k[4])<<24;
ATTR_FALLTHROUGH
/* fallthrough */
case 4 : a+=k[3];
ATTR_FALLTHROUGH
/* fallthrough */
case 3 : a+=((uint32_t)k[2])<<8;
ATTR_FALLTHROUGH
/* fallthrough */
case 2 : a+=((uint32_t)k[1])<<16;
ATTR_FALLTHROUGH
/* fallthrough */
case 1 : a+=((uint32_t)k[0])<<24;
break;
case 0 : return c;

View file

@ -1266,12 +1266,13 @@ verify_dnskey(struct module_env* env, struct val_env* ve,
struct trust_anchor* tp, struct ub_packed_rrset_key* rrset,
struct module_qstate* qstate)
{
char reasonbuf[256];
char* reason = NULL;
uint8_t sigalg[ALGO_NEEDS_MAX+1];
int downprot = env->cfg->harden_algo_downgrade;
enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve, rrset,
tp->ds_rrset, tp->dnskey_rrset, downprot?sigalg:NULL, &reason,
NULL, qstate);
NULL, qstate, reasonbuf, sizeof(reasonbuf));
/* sigalg is ignored, it returns algorithms signalled to exist, but
* in 5011 there are no other rrsets to check. if downprot is
* enabled, then it checks that the DNSKEY is signed with all

View file

@ -177,7 +177,7 @@ static int
nsec_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* nsec, struct key_entry_key* kkey,
char** reason, sldns_ede_code* reason_bogus,
struct module_qstate* qstate)
struct module_qstate* qstate, char* reasonbuf, size_t reasonlen)
{
struct packed_rrset_data* d = (struct packed_rrset_data*)
nsec->entry.data;
@ -189,7 +189,8 @@ nsec_verify_rrset(struct module_env* env, struct val_env* ve,
if(d->security == sec_status_secure)
return 1;
d->security = val_verify_rrset_entry(env, ve, nsec, kkey, reason,
reason_bogus, LDNS_SECTION_AUTHORITY, qstate, &verified);
reason_bogus, LDNS_SECTION_AUTHORITY, qstate, &verified,
reasonbuf, reasonlen);
if(d->security == sec_status_secure) {
rrset_update_sec_status(env->rrset_cache, nsec, *env->now);
return 1;
@ -201,7 +202,8 @@ enum sec_status
val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
struct query_info* qinfo, struct reply_info* rep,
struct key_entry_key* kkey, time_t* proof_ttl, char** reason,
sldns_ede_code* reason_bogus, struct module_qstate* qstate)
sldns_ede_code* reason_bogus, struct module_qstate* qstate,
char* reasonbuf, size_t reasonlen)
{
struct ub_packed_rrset_key* nsec = reply_find_rrset_section_ns(
rep, qinfo->qname, qinfo->qname_len, LDNS_RR_TYPE_NSEC,
@ -219,7 +221,7 @@ val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
* 2) this is not a delegation point */
if(nsec) {
if(!nsec_verify_rrset(env, ve, nsec, kkey, reason,
reason_bogus, qstate)) {
reason_bogus, qstate, reasonbuf, reasonlen)) {
verbose(VERB_ALGO, "NSEC RRset for the "
"referral did not verify.");
return sec_status_bogus;
@ -250,7 +252,7 @@ val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
if(rep->rrsets[i]->rk.type != htons(LDNS_RR_TYPE_NSEC))
continue;
if(!nsec_verify_rrset(env, ve, rep->rrsets[i], kkey, reason,
reason_bogus, qstate)) {
reason_bogus, qstate, reasonbuf, reasonlen)) {
verbose(VERB_ALGO, "NSEC for empty non-terminal "
"did not verify.");
*reason = "NSEC for empty non-terminal "

View file

@ -68,6 +68,8 @@ struct key_entry_key;
* @param reason: string explaining why bogus.
* @param reason_bogus: relevant EDE code for validation failure.
* @param qstate: qstate with region.
* @param reasonbuf: buffer to use for fail reason string print.
* @param reasonlen: length of reasonbuf.
* @return security status.
* SECURE: proved absence of DS.
* INSECURE: proved that this was not a delegation point.
@ -78,7 +80,7 @@ enum sec_status val_nsec_prove_nodata_dsreply(struct module_env* env,
struct val_env* ve, struct query_info* qinfo,
struct reply_info* rep, struct key_entry_key* kkey,
time_t* proof_ttl, char** reason, sldns_ede_code* reason_bogus,
struct module_qstate* qstate);
struct module_qstate* qstate, char* reasonbuf, size_t reasonlen);
/**
* nsec typemap check, takes an NSEC-type bitmap as argument, checks for type.

View file

@ -1445,7 +1445,7 @@ static int
list_is_secure(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num,
struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus,
struct module_qstate* qstate)
struct module_qstate* qstate, char* reasonbuf, size_t reasonlen)
{
struct packed_rrset_data* d;
size_t i;
@ -1461,7 +1461,7 @@ list_is_secure(struct module_env* env, struct val_env* ve,
continue;
d->security = val_verify_rrset_entry(env, ve, list[i], kkey,
reason, reason_bogus, LDNS_SECTION_AUTHORITY, qstate,
&verified);
&verified, reasonbuf, reasonlen);
if(d->security != sec_status_secure) {
verbose(VERB_ALGO, "NSEC3 did not verify");
return 0;
@ -1476,7 +1476,7 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num,
struct query_info* qinfo, struct key_entry_key* kkey, char** reason,
sldns_ede_code* reason_bogus, struct module_qstate* qstate,
struct nsec3_cache_table* ct)
struct nsec3_cache_table* ct, char* reasonbuf, size_t reasonlen)
{
struct nsec3_filter flt;
struct ce_response ce;
@ -1491,7 +1491,8 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
*reason = "no valid NSEC3s";
return sec_status_bogus; /* no valid NSEC3s, bogus */
}
if(!list_is_secure(env, ve, list, num, kkey, reason, reason_bogus, qstate)) {
if(!list_is_secure(env, ve, list, num, kkey, reason, reason_bogus,
qstate, reasonbuf, reasonlen)) {
*reason = "not all NSEC3 records secure";
return sec_status_bogus; /* not all NSEC3 records secure */
}

View file

@ -210,6 +210,8 @@ nsec3_prove_wildcard(struct module_env* env, struct val_env* ve,
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region.
* @param ct: cached hashes table.
* @param reasonbuf: buffer to use for fail reason string print.
* @param reasonlen: length of reasonbuf.
* @return:
* sec_status SECURE of the proposition is proven by the NSEC3 RRs,
* BOGUS if not, INSECURE if all of the NSEC3s could be validly ignored.
@ -222,7 +224,7 @@ nsec3_prove_nods(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key** list, size_t num,
struct query_info* qinfo, struct key_entry_key* kkey, char** reason,
sldns_ede_code* reason_bogus, struct module_qstate* qstate,
struct nsec3_cache_table* ct);
struct nsec3_cache_table* ct, char* reasonbuf, size_t reasonlen);
/**
* Prove NXDOMAIN or NODATA.

View file

@ -423,7 +423,10 @@ setup_dsa_sig(unsigned char** sig, unsigned int* len)
if(!dsasig) return 0;
#ifdef HAVE_DSA_SIG_SET0
if(!DSA_SIG_set0(dsasig, R, S)) return 0;
if(!DSA_SIG_set0(dsasig, R, S)) {
DSA_SIG_free(dsasig);
return 0;
}
#else
# ifndef S_SPLINT_S
dsasig->r = R;
@ -2057,11 +2060,13 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
digest_size = (digest_size ? digest_size : SHA1_DIGEST_SIZE);
#endif
/* double fallthrough annotation to please gcc parser */
ATTR_FALLTHROUGH
/* fallthrough */
#ifdef USE_SHA2
/* fallthrough */
case LDNS_RSASHA256:
digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
ATTR_FALLTHROUGH
/* fallthrough */
case LDNS_RSASHA512:
digest_size = (digest_size ? digest_size : SHA512_DIGEST_SIZE);
@ -2077,6 +2082,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
#ifdef USE_ECDSA
case LDNS_ECDSAP256SHA256:
digest_size = (digest_size ? digest_size : SHA256_DIGEST_SIZE);
ATTR_FALLTHROUGH
/* fallthrough */
case LDNS_ECDSAP384SHA384:
digest_size = (digest_size ? digest_size : SHA384_DIGEST_SIZE);

View file

@ -623,7 +623,8 @@ enum sec_status
dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate, int* verified)
sldns_pkt_section section, struct module_qstate* qstate, int* verified,
char* reasonbuf, size_t reasonlen)
{
enum sec_status sec;
size_t i, num;
@ -680,7 +681,8 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
verbose(VERB_ALGO, "rrset failed to verify: "
"no valid signatures for %d algorithms",
(int)algo_needs_num_missing(&needs));
algo_needs_reason(env, alg, reason, "no signatures");
algo_needs_reason(alg, reason, "no signatures", reasonbuf,
reasonlen);
} else {
verbose(VERB_ALGO, "rrset failed to verify: "
"no valid signatures");
@ -688,17 +690,16 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
return sec_status_bogus;
}
void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s)
void algo_needs_reason(int alg, char** reason, char* s, char* reasonbuf,
size_t reasonlen)
{
char buf[256];
sldns_lookup_table *t = sldns_lookup_by_id(sldns_algorithms, alg);
if(t&&t->name)
snprintf(buf, sizeof(buf), "%s with algorithm %s", s, t->name);
else snprintf(buf, sizeof(buf), "%s with algorithm ALG%u", s,
snprintf(reasonbuf, reasonlen, "%s with algorithm %s", s,
t->name);
else snprintf(reasonbuf, reasonlen, "%s with algorithm ALG%u", s,
(unsigned)alg);
*reason = regional_strdup(env->scratch, buf);
if(!*reason)
*reason = s;
*reason = reasonbuf;
}
enum sec_status

View file

@ -134,12 +134,14 @@ int algo_needs_missing(struct algo_needs* n);
/**
* Format error reason for algorithm missing.
* @param env: module env with scratch for temp storage of string.
* @param alg: DNSKEY-algorithm missing.
* @param reason: destination.
* @param s: string, appended with 'with algorithm ..'.
* @param reasonbuf: buffer to use for fail reason string print.
* @param reasonlen: length of reasonbuf.
*/
void algo_needs_reason(struct module_env* env, int alg, char** reason, char* s);
void algo_needs_reason(int alg, char** reason, char* s, char* reasonbuf,
size_t reasonlen);
/**
* Check if dnskey matches a DS digest
@ -261,6 +263,8 @@ uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx);
* @param section: section of packet where this rrset comes from.
* @param qstate: qstate with region.
* @param verified: if not NULL the number of RRSIG validations is returned.
* @param reasonbuf: buffer to use for fail reason string print.
* @param reasonlen: length of reasonbuf.
* @return SECURE if one key in the set verifies one rrsig.
* UNCHECKED on allocation errors, unsupported algorithms, malformed data,
* and BOGUS on verification failures (no keys match any signatures).
@ -269,8 +273,8 @@ enum sec_status dnskeyset_verify_rrset(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, uint8_t* sigalg,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate, int* verified);
sldns_pkt_section section, struct module_qstate* qstate, int* verified,
char* reasonbuf, size_t reasonlen);
/**
* verify rrset against one specific dnskey (from rrset)

View file

@ -240,6 +240,26 @@ val_find_best_signer(struct ub_packed_rrset_key* rrset,
}
}
/** Detect if the, unsigned, CNAME is under a previous DNAME RR in the
* message, and thus it was generated from that previous DNAME.
*/
static int
cname_under_previous_dname(struct reply_info* rep, size_t cname_idx,
size_t* ret)
{
size_t i;
for(i=0; i<cname_idx; i++) {
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNAME &&
dname_strict_subdomain_c(rep->rrsets[cname_idx]->
rk.dname, rep->rrsets[i]->rk.dname)) {
*ret = i;
return 1;
}
}
*ret = 0;
return 0;
}
void
val_find_signer(enum val_classification subtype, struct query_info* qinf,
struct reply_info* rep, size_t skip, uint8_t** signer_name,
@ -275,12 +295,19 @@ val_find_signer(enum val_classification subtype, struct query_info* qinf,
*signer_name = NULL;
*signer_len = 0;
} else if(subtype == VAL_CLASS_CNAME) {
size_t j;
/* check for the first signed cname/dname rrset */
for(i=skip; i<rep->an_numrrsets; i++) {
val_find_rrset_signer(rep->rrsets[i],
signer_name, signer_len);
if(*signer_name)
return;
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME
&& cname_under_previous_dname(rep, i, &j)) {
val_find_rrset_signer(rep->rrsets[j],
signer_name, signer_len);
return;
}
if(ntohs(rep->rrsets[i]->rk.type) != LDNS_RR_TYPE_DNAME)
break; /* only check CNAME after a DNAME */
}
@ -379,7 +406,7 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
uint8_t* sigalg, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate,
int *verified)
int *verified, char* reasonbuf, size_t reasonlen)
{
enum sec_status sec;
struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
@ -404,7 +431,7 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname,
ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
sec = dnskeyset_verify_rrset(env, ve, rrset, keys, sigalg, reason,
reason_bogus, section, qstate, verified);
reason_bogus, section, qstate, verified, reasonbuf, reasonlen);
verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
regional_free_all(env->scratch);
@ -439,7 +466,7 @@ val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey,
char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate,
int* verified)
int* verified, char* reasonbuf, size_t reasonlen)
{
/* temporary dnskey rrset-key */
struct ub_packed_rrset_key dnskey;
@ -453,7 +480,7 @@ val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
dnskey.entry.key = &dnskey;
dnskey.entry.data = kd->rrset_data;
sec = val_verify_rrset(env, ve, rrset, &dnskey, kd->algo, reason,
reason_bogus, section, qstate, verified);
reason_bogus, section, qstate, verified, reasonbuf, reasonlen);
return sec;
}
@ -463,7 +490,7 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason,
sldns_ede_code *reason_bogus, struct module_qstate* qstate,
int *nonechecked)
int *nonechecked, char* reasonbuf, size_t reasonlen)
{
enum sec_status sec = sec_status_bogus;
size_t i, num, numchecked = 0, numhashok = 0, numsizesupp = 0;
@ -517,8 +544,8 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
return sec_status_insecure;
}
if(numchecked == 0) {
algo_needs_reason(env, ds_get_key_algo(ds_rrset, ds_idx),
reason, "no keys have a DS");
algo_needs_reason(ds_get_key_algo(ds_rrset, ds_idx),
reason, "no keys have a DS", reasonbuf, reasonlen);
*nonechecked = 1;
} else if(numhashok == 0) {
*reason = "DS hash mismatches key";
@ -549,7 +576,8 @@ enum sec_status
val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason,
sldns_ede_code *reason_bogus, struct module_qstate* qstate)
sldns_ede_code *reason_bogus, struct module_qstate* qstate,
char* reasonbuf, size_t reasonlen)
{
/* as long as this is false, we can consider this DS rrset to be
* equivalent to no DS rrset. */
@ -588,7 +616,7 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
ds_rrset, i, reason, reason_bogus, qstate,
&nonechecked);
&nonechecked, reasonbuf, reasonlen);
if(sec == sec_status_insecure) {
/* DNSKEY too large unsupported or algo refused by
* crypto lib. */
@ -639,8 +667,8 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
/* If any were understandable, then it is bad. */
verbose(VERB_QUERY, "Failed to match any usable DS to a DNSKEY.");
if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
algo_needs_reason(env, alg, reason, "missing verification of "
"DNSKEY signature");
algo_needs_reason(alg, reason, "missing verification of "
"DNSKEY signature", reasonbuf, reasonlen);
}
return sec_status_bogus;
}
@ -649,12 +677,13 @@ struct key_entry_key*
val_verify_new_DNSKEYs(struct regional* region, struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
sldns_ede_code *reason_bogus, struct module_qstate* qstate)
sldns_ede_code *reason_bogus, struct module_qstate* qstate,
char* reasonbuf, size_t reasonlen)
{
uint8_t sigalg[ALGO_NEEDS_MAX+1];
enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve,
dnskey_rrset, ds_rrset, downprot?sigalg:NULL, reason,
reason_bogus, qstate);
reason_bogus, qstate, reasonbuf, reasonlen);
if(sec == sec_status_secure) {
return key_entry_create_rrset(region,
@ -679,7 +708,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ta_ds,
struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
sldns_ede_code *reason_bogus, struct module_qstate* qstate)
sldns_ede_code *reason_bogus, struct module_qstate* qstate,
char* reasonbuf, size_t reasonlen)
{
/* as long as this is false, we can consider this anchor to be
* equivalent to no anchor. */
@ -730,7 +760,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
continue;
sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
ta_ds, i, reason, reason_bogus, qstate, &nonechecked);
ta_ds, i, reason, reason_bogus, qstate, &nonechecked,
reasonbuf, reasonlen);
if(sec == sec_status_insecure) {
has_algo_refusal = 1;
continue;
@ -810,8 +841,8 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
/* If any were understandable, then it is bad. */
verbose(VERB_QUERY, "Failed to match any usable anchor to a DNSKEY.");
if(sigalg && (alg=algo_needs_missing(&needs)) != 0) {
algo_needs_reason(env, alg, reason, "missing verification of "
"DNSKEY signature");
algo_needs_reason(alg, reason, "missing verification of "
"DNSKEY signature", reasonbuf, reasonlen);
}
return sec_status_bogus;
}
@ -821,12 +852,14 @@ val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ta_ds_rrset,
struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate)
char** reason, sldns_ede_code *reason_bogus,
struct module_qstate* qstate, char* reasonbuf, size_t reasonlen)
{
uint8_t sigalg[ALGO_NEEDS_MAX+1];
enum sec_status sec = val_verify_DNSKEY_with_TA(env, ve,
dnskey_rrset, ta_ds_rrset, ta_dnskey_rrset,
downprot?sigalg:NULL, reason, reason_bogus, qstate);
downprot?sigalg:NULL, reason, reason_bogus, qstate,
reasonbuf, reasonlen);
if(sec == sec_status_secure) {
return key_entry_create_rrset(region,
@ -979,7 +1012,7 @@ void
val_fill_reply(struct reply_info* chase, struct reply_info* orig,
size_t skip, uint8_t* name, size_t len, uint8_t* signer)
{
size_t i;
size_t i, j;
int seen_dname = 0;
chase->rrset_count = 0;
chase->an_numrrsets = 0;
@ -1002,6 +1035,13 @@ val_fill_reply(struct reply_info* chase, struct reply_info* orig,
LDNS_RR_TYPE_DNAME) {
seen_dname = 1;
}
} else if(ntohs(orig->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME
&& ((struct packed_rrset_data*)orig->rrsets[i]->
entry.data)->rrsig_count == 0 &&
cname_under_previous_dname(orig, i, &j) &&
rrset_has_signer(orig->rrsets[j], name, len)) {
chase->rrsets[chase->an_numrrsets++] = orig->rrsets[j];
chase->rrsets[chase->an_numrrsets++] = orig->rrsets[i];
}
}
/* AUTHORITY section */

View file

@ -125,13 +125,15 @@ void val_find_signer(enum val_classification subtype,
* @param section: section of packet where this rrset comes from.
* @param qstate: qstate with region.
* @param verified: if not NULL, the number of RRSIG validations is returned.
* @param reasonbuf: buffer to use for fail reason string print.
* @param reasonlen: length of reasonbuf.
* @return security status of verification.
*/
enum sec_status val_verify_rrset_entry(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
struct key_entry_key* kkey, char** reason, sldns_ede_code *reason_bogus,
sldns_pkt_section section, struct module_qstate* qstate,
int* verified);
int* verified, char* reasonbuf, size_t reasonlen);
/**
* Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but
@ -146,6 +148,8 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
* @param reason: reason of failure. Fixed string or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region.
* @param reasonbuf: buffer to use for fail reason string print.
* @param reasonlen: length of reasonbuf.
* @return: sec_status_secure if a DS matches.
* sec_status_insecure if end of trust (i.e., unknown algorithms).
* sec_status_bogus if it fails.
@ -153,7 +157,8 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, uint8_t* sigalg, char** reason,
sldns_ede_code *reason_bogus, struct module_qstate* qstate);
sldns_ede_code *reason_bogus, struct module_qstate* qstate,
char* reasonbuf, size_t reasonlen);
/**
* Verify DNSKEYs with DS and DNSKEY rrset. Like val_verify_DNSKEY_with_DS
@ -169,6 +174,8 @@ enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
* @param reason: reason of failure. Fixed string or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region.
* @param reasonbuf: buffer to use for fail reason string print.
* @param reasonlen: length of reasonbuf.
* @return: sec_status_secure if a DS matches.
* sec_status_insecure if end of trust (i.e., unknown algorithms).
* sec_status_bogus if it fails.
@ -177,7 +184,8 @@ enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ta_ds,
struct ub_packed_rrset_key* ta_dnskey, uint8_t* sigalg, char** reason,
sldns_ede_code *reason_bogus, struct module_qstate* qstate);
sldns_ede_code *reason_bogus, struct module_qstate* qstate,
char* reasonbuf, size_t reasonlen);
/**
* Verify new DNSKEYs with DS rrset. The DS contains hash values that should
@ -194,6 +202,8 @@ enum sec_status val_verify_DNSKEY_with_TA(struct module_env* env,
* @param reason: reason of failure. Fixed string or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region.
* @param reasonbuf: buffer to use for fail reason string print.
* @param reasonlen: length of reasonbuf.
* @return a KeyEntry. This will either contain the now trusted
* dnskey_rrset, a "null" key entry indicating that this DS
* rrset/DNSKEY pair indicate an secure end to the island of trust
@ -208,7 +218,8 @@ struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ds_rrset, int downprot, char** reason,
sldns_ede_code *reason_bogus, struct module_qstate* qstate);
sldns_ede_code *reason_bogus, struct module_qstate* qstate,
char* reasonbuf, size_t reasonlen);
/**
* Verify rrset with trust anchor: DS and DNSKEY rrset.
@ -224,6 +235,8 @@ struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
* @param reason: reason of failure. Fixed string or alloced in scratch.
* @param reason_bogus: EDE (RFC8914) code paired with the reason of failure.
* @param qstate: qstate with region.
* @param reasonbuf: buffer to use for fail reason string print.
* @param reasonlen: length of reasonbuf.
* @return a KeyEntry. This will either contain the now trusted
* dnskey_rrset, a "null" key entry indicating that this DS
* rrset/DNSKEY pair indicate an secure end to the island of trust
@ -239,7 +252,8 @@ struct key_entry_key* val_verify_new_DNSKEYs_with_ta(struct regional* region,
struct ub_packed_rrset_key* dnskey_rrset,
struct ub_packed_rrset_key* ta_ds_rrset,
struct ub_packed_rrset_key* ta_dnskey_rrset, int downprot,
char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate);
char** reason, sldns_ede_code *reason_bogus, struct module_qstate* qstate,
char* reasonbuf, size_t reasonlen);
/**
* Determine if DS rrset is usable for validator or not.

View file

@ -72,7 +72,8 @@
/* forward decl for cache response and normal super inform calls of a DS */
static void process_ds_response(struct module_qstate* qstate,
struct val_qstate* vq, int id, int rcode, struct dns_msg* msg,
struct query_info* qinfo, struct sock_list* origin, int* suspend);
struct query_info* qinfo, struct sock_list* origin, int* suspend,
struct module_qstate* sub_qstate);
/* Updates the suplied EDE (RFC8914) code selectively so we don't lose
@ -273,11 +274,17 @@ val_new_getmsg(struct module_qstate* qstate, struct val_qstate* vq)
return NULL;
if(vq->orig_msg->rep->rrset_count > RR_COUNT_MAX)
return NULL; /* protect against integer overflow */
vq->chase_reply->rrsets = regional_alloc_init(qstate->region,
vq->orig_msg->rep->rrsets, sizeof(struct ub_packed_rrset_key*)
* vq->orig_msg->rep->rrset_count);
/* Over allocate (+an_numrrsets) in case we need to put extra DNAME
* records for unsigned CNAME repetitions */
vq->chase_reply->rrsets = regional_alloc(qstate->region,
sizeof(struct ub_packed_rrset_key*) *
(vq->orig_msg->rep->rrset_count
+ vq->orig_msg->rep->an_numrrsets));
if(!vq->chase_reply->rrsets)
return NULL;
memmove(vq->chase_reply->rrsets, vq->orig_msg->rep->rrsets,
sizeof(struct ub_packed_rrset_key*) *
vq->orig_msg->rep->rrset_count);
vq->rrset_skip = 0;
return vq;
}
@ -640,6 +647,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
struct ub_packed_rrset_key* s;
enum sec_status sec;
int num_verifies = 0, verified, have_state = 0;
char reasonbuf[256];
char* reason = NULL;
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
*suspend = 0;
@ -675,7 +683,8 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
/* Verify the answer rrset */
sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason,
&reason_bogus, LDNS_SECTION_ANSWER, qstate, &verified);
&reason_bogus, LDNS_SECTION_ANSWER, qstate, &verified,
reasonbuf, sizeof(reasonbuf));
/* If the (answer) rrset failed to validate, then this
* message is BAD. */
if(sec != sec_status_secure) {
@ -720,7 +729,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
s = chase_reply->rrsets[i];
sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason,
&reason_bogus, LDNS_SECTION_AUTHORITY, qstate,
&verified);
&verified, reasonbuf, sizeof(reasonbuf));
/* If anything in the authority section fails to be secure,
* we have a bad message. */
if(sec != sec_status_secure) {
@ -766,7 +775,7 @@ validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
if(sname && query_dname_compare(sname, key_entry->name)==0)
(void)val_verify_rrset_entry(env, ve, s, key_entry,
&reason, NULL, LDNS_SECTION_ADDITIONAL, qstate,
&verified);
&verified, reasonbuf, sizeof(reasonbuf));
/* the additional section can fail to be secure,
* it is optional, check signature in case we need
* to clean the additional section later. */
@ -1462,9 +1471,9 @@ validate_any_response(struct module_env* env, struct val_env* ve,
* DNAME+CNAME. Possible wildcard proof.
* Difference with positive proof is that this routine refuses
* wildcarded DNAMEs.
*
*
* The answer and authority rrsets must already be verified as secure.
*
*
* @param env: module env for verify.
* @param ve: validator env for verify.
* @param qchase: query that was made.
@ -2060,7 +2069,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
verbose(VERB_ALGO, "Process suspended sub DS response");
msg = vq->sub_ds_msg;
process_ds_response(qstate, vq, id, LDNS_RCODE_NOERROR,
msg, &msg->qinfo, NULL, &suspend);
msg, &msg->qinfo, NULL, &suspend, NULL);
if(suspend) {
/* we'll come back here later to continue */
if(!validate_suspend_setup_timer(qstate, vq,
@ -2076,7 +2085,7 @@ processFindKey(struct module_qstate* qstate, struct val_qstate* vq, int id)
vq->key_entry->name)) ) {
verbose(VERB_ALGO, "Process cached DS response");
process_ds_response(qstate, vq, id, LDNS_RCODE_NOERROR,
msg, &msg->qinfo, NULL, &suspend);
msg, &msg->qinfo, NULL, &suspend, NULL);
if(suspend) {
/* we'll come back here later to continue */
if(!validate_suspend_setup_timer(qstate, vq,
@ -2658,6 +2667,8 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
* @param ta: trust anchor.
* @param qstate: qstate that needs key.
* @param id: module id.
* @param sub_qstate: the sub query state, that is the lookup that fetched
* the trust anchor data, it contains error information for the answer.
* @return new key entry or NULL on allocation failure.
* The key entry will either contain a validated DNSKEY rrset, or
* represent a Null key (query failed, but validation did not), or a
@ -2665,31 +2676,38 @@ val_operate(struct module_qstate* qstate, enum module_ev event, int id,
*/
static struct key_entry_key*
primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
struct trust_anchor* ta, struct module_qstate* qstate, int id)
struct trust_anchor* ta, struct module_qstate* qstate, int id,
struct module_qstate* sub_qstate)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
struct key_entry_key* kkey = NULL;
enum sec_status sec = sec_status_unchecked;
char reasonbuf[256];
char* reason = NULL;
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
int downprot = qstate->env->cfg->harden_algo_downgrade;
if(!dnskey_rrset) {
char* err = errinf_to_str_misc(sub_qstate);
char rstr[1024];
log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "
"could not fetch DNSKEY rrset",
ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass);
reason_bogus = LDNS_EDE_DNSKEY_MISSING;
reason = "no DNSKEY rrset";
if(!err) {
snprintf(rstr, sizeof(rstr), "no DNSKEY rrset");
} else {
snprintf(rstr, sizeof(rstr), "no DNSKEY rrset "
"[%s]", err);
}
if(qstate->env->cfg->harden_dnssec_stripped) {
errinf_ede(qstate, reason, reason_bogus);
errinf_ede(qstate, rstr, reason_bogus);
kkey = key_entry_create_bad(qstate->region, ta->name,
ta->namelen, ta->dclass, BOGUS_KEY_TTL,
reason_bogus, reason,
*qstate->env->now);
reason_bogus, rstr, *qstate->env->now);
} else kkey = key_entry_create_null(qstate->region, ta->name,
ta->namelen, ta->dclass, NULL_KEY_TTL,
reason_bogus, reason,
*qstate->env->now);
reason_bogus, rstr, *qstate->env->now);
if(!kkey) {
log_err("out of memory: allocate fail prime key");
return NULL;
@ -2699,7 +2717,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
/* attempt to verify with trust anchor DS and DNSKEY */
kkey = val_verify_new_DNSKEYs_with_ta(qstate->region, qstate->env, ve,
dnskey_rrset, ta->ds_rrset, ta->dnskey_rrset, downprot,
&reason, &reason_bogus, qstate);
&reason, &reason_bogus, qstate, reasonbuf, sizeof(reasonbuf));
if(!kkey) {
log_err("out of memory: verifying prime TA");
return NULL;
@ -2754,6 +2772,9 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
* DS response indicated an end to secure space, is_good if the DS
* validated. It returns ke=NULL if the DS response indicated that the
* request wasn't a delegation point.
* @param sub_qstate: the sub query state, that is the lookup that fetched
* the trust anchor data, it contains error information for the answer.
* Can be NULL.
* @return
* 0 on success,
* 1 on servfail error (malloc failure),
@ -2762,9 +2783,10 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
static int
ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
int id, int rcode, struct dns_msg* msg, struct query_info* qinfo,
struct key_entry_key** ke)
struct key_entry_key** ke, struct module_qstate* sub_qstate)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
char reasonbuf[256];
char* reason = NULL;
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
enum val_classification subtype;
@ -2777,6 +2799,14 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
verbose(VERB_DETAIL, "DS response was error, thus bogus");
errinf(qstate, rc);
reason = "no DS";
if(sub_qstate) {
char* err = errinf_to_str_misc(sub_qstate);
if(err) {
char buf[1024];
snprintf(buf, sizeof(buf), "[%s]", err);
errinf(qstate, buf);
}
}
reason_bogus = LDNS_EDE_NETWORK_ERROR;
errinf_ede(qstate, reason, reason_bogus);
goto return_bogus;
@ -2799,7 +2829,9 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
/* Verify only returns BOGUS or SECURE. If the rrset is
* bogus, then we are done. */
sec = val_verify_rrset_entry(qstate->env, ve, ds,
vq->key_entry, &reason, &reason_bogus, LDNS_SECTION_ANSWER, qstate, &verified);
vq->key_entry, &reason, &reason_bogus,
LDNS_SECTION_ANSWER, qstate, &verified, reasonbuf,
sizeof(reasonbuf));
if(sec != sec_status_secure) {
verbose(VERB_DETAIL, "DS rrset in DS response did "
"not verify");
@ -2849,7 +2881,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
/* Try to prove absence of the DS with NSEC */
sec = val_nsec_prove_nodata_dsreply(
qstate->env, ve, qinfo, msg->rep, vq->key_entry,
&proof_ttl, &reason, &reason_bogus, qstate);
&proof_ttl, &reason, &reason_bogus, qstate,
reasonbuf, sizeof(reasonbuf));
switch(sec) {
case sec_status_secure:
verbose(VERB_DETAIL, "NSEC RRset for the "
@ -2886,7 +2919,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
sec = nsec3_prove_nods(qstate->env, ve,
msg->rep->rrsets + msg->rep->an_numrrsets,
msg->rep->ns_numrrsets, qinfo, vq->key_entry, &reason,
&reason_bogus, qstate, &vq->nsec3_cache_table);
&reason_bogus, qstate, &vq->nsec3_cache_table,
reasonbuf, sizeof(reasonbuf));
switch(sec) {
case sec_status_insecure:
/* case insecure also continues to unsigned
@ -2953,7 +2987,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
}
sec = val_verify_rrset_entry(qstate->env, ve, cname,
vq->key_entry, &reason, &reason_bogus,
LDNS_SECTION_ANSWER, qstate, &verified);
LDNS_SECTION_ANSWER, qstate, &verified, reasonbuf,
sizeof(reasonbuf));
if(sec == sec_status_secure) {
verbose(VERB_ALGO, "CNAME validated, "
"proof that DS does not exist");
@ -3002,11 +3037,15 @@ return_bogus:
* @param origin: the origin of msg.
* @param suspend: returned true if the task takes too long and needs to
* suspend to continue the effort later.
* @param sub_qstate: the sub query state, that is the lookup that fetched
* the trust anchor data, it contains error information for the answer.
* Can be NULL.
*/
static void
process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
int id, int rcode, struct dns_msg* msg, struct query_info* qinfo,
struct sock_list* origin, int* suspend)
struct sock_list* origin, int* suspend,
struct module_qstate* sub_qstate)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
struct key_entry_key* dske = NULL;
@ -3014,7 +3053,8 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
int ret;
*suspend = 0;
vq->empty_DS_name = NULL;
ret = ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske);
ret = ds_response_to_ke(qstate, vq, id, rcode, msg, qinfo, &dske,
sub_qstate);
if(ret != 0) {
switch(ret) {
case 1:
@ -3090,16 +3130,19 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
* @param msg: result message (if rcode is OK).
* @param qinfo: from the sub query state, query info.
* @param origin: the origin of msg.
* @param sub_qstate: the sub query state, that is the lookup that fetched
* the trust anchor data, it contains error information for the answer.
*/
static void
process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
int id, int rcode, struct dns_msg* msg, struct query_info* qinfo,
struct sock_list* origin)
struct sock_list* origin, struct module_qstate* sub_qstate)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
struct key_entry_key* old = vq->key_entry;
struct ub_packed_rrset_key* dnskey = NULL;
int downprot;
char reasonbuf[256];
char* reason = NULL;
sldns_ede_code reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
@ -3107,6 +3150,8 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
dnskey = reply_find_answer_rrset(qinfo, msg->rep);
if(dnskey == NULL) {
char* err;
char rstr[1024];
/* bad response */
verbose(VERB_DETAIL, "Missing DNSKEY RRset in response to "
"DNSKEY query.");
@ -3118,17 +3163,22 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
vq->restart_count++;
return;
}
reason = "No DNSKEY record";
err = errinf_to_str_misc(sub_qstate);
if(!err) {
snprintf(rstr, sizeof(rstr), "No DNSKEY record");
} else {
snprintf(rstr, sizeof(rstr), "No DNSKEY record "
"[%s]", err);
}
reason_bogus = LDNS_EDE_DNSKEY_MISSING;
vq->key_entry = key_entry_create_bad(qstate->region,
qinfo->qname, qinfo->qname_len, qinfo->qclass,
BOGUS_KEY_TTL, reason_bogus, reason,
*qstate->env->now);
BOGUS_KEY_TTL, reason_bogus, rstr, *qstate->env->now);
if(!vq->key_entry) {
log_err("alloc failure in missing dnskey response");
/* key_entry is NULL for failure in Validate */
}
errinf_ede(qstate, reason, reason_bogus);
errinf_ede(qstate, rstr, reason_bogus);
errinf_origin(qstate, origin);
errinf_dname(qstate, "for key", qinfo->qname);
vq->state = VAL_VALIDATE_STATE;
@ -3142,7 +3192,8 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
}
downprot = qstate->env->cfg->harden_algo_downgrade;
vq->key_entry = val_verify_new_DNSKEYs(qstate->region, qstate->env,
ve, dnskey, vq->ds_rrset, downprot, &reason, &reason_bogus, qstate);
ve, dnskey, vq->ds_rrset, downprot, &reason, &reason_bogus,
qstate, reasonbuf, sizeof(reasonbuf));
if(!vq->key_entry) {
log_err("out of memory in verify new DNSKEYs");
@ -3192,10 +3243,13 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
* @param rcode: rcode result value.
* @param msg: result message (if rcode is OK).
* @param origin: the origin of msg.
* @param sub_qstate: the sub query state, that is the lookup that fetched
* the trust anchor data, it contains error information for the answer.
*/
static void
process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
int id, int rcode, struct dns_msg* msg, struct sock_list* origin)
int id, int rcode, struct dns_msg* msg, struct sock_list* origin,
struct module_qstate* sub_qstate)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
struct ub_packed_rrset_key* dnskey_rrset = NULL;
@ -3227,7 +3281,8 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
return;
}
}
vq->key_entry = primeResponseToKE(dnskey_rrset, ta, qstate, id);
vq->key_entry = primeResponseToKE(dnskey_rrset, ta, qstate, id,
sub_qstate);
lock_basic_unlock(&ta->lock);
if(vq->key_entry) {
if(key_entry_isbad(vq->key_entry)
@ -3278,14 +3333,14 @@ val_inform_super(struct module_qstate* qstate, int id,
if(vq->wait_prime_ta) {
vq->wait_prime_ta = 0;
process_prime_response(super, vq, id, qstate->return_rcode,
qstate->return_msg, qstate->reply_origin);
qstate->return_msg, qstate->reply_origin, qstate);
return;
}
if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS) {
int suspend;
process_ds_response(super, vq, id, qstate->return_rcode,
qstate->return_msg, &qstate->qinfo,
qstate->reply_origin, &suspend);
qstate->reply_origin, &suspend, qstate);
/* If NSEC3 was needed during validation, NULL the NSEC3 cache;
* it will be re-initiated if needed later on.
* Validation (and the cache table) are happening/allocated in
@ -3306,7 +3361,7 @@ val_inform_super(struct module_qstate* qstate, int id,
} else if(qstate->qinfo.qtype == LDNS_RR_TYPE_DNSKEY) {
process_dnskey_response(super, vq, id, qstate->return_rcode,
qstate->return_msg, &qstate->qinfo,
qstate->reply_origin);
qstate->reply_origin, qstate);
return;
}
log_err("internal error in validator: no inform_supers possible");
@ -3344,8 +3399,8 @@ val_get_mem(struct module_env* env, int id)
*/
static struct module_func_block val_block = {
"validator",
&val_init, &val_deinit, &val_operate, &val_inform_super, &val_clear,
&val_get_mem
NULL, NULL, &val_init, &val_deinit, &val_operate, &val_inform_super,
&val_clear, &val_get_mem
};
struct module_func_block*

View file

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.850 2024/08/31 04:21:45 dlg Exp $
# $OpenBSD: Makefile,v 1.851 2024/09/04 11:12:53 jsg Exp $
MAN= aac.4 abcrtc.4 abl.4 ac97.4 acphy.4 acrtc.4 \
acpi.4 acpiac.4 acpials.4 acpiasus.4 acpibat.4 \
@ -72,7 +72,7 @@ MAN= aac.4 abcrtc.4 abl.4 ac97.4 acphy.4 acrtc.4 \
pcmcia.4 pcn.4 pcppi.4 pcscp.4 pcxrtc.4 pcyrtc.4 \
pf.4 pflog.4 pflow.4 pfsync.4 \
pgt.4 piixpm.4 pijuice.4 pinctrl.4 pipex.4 plgpio.4 plrtc.4 pluart.4 \
pms.4 ppb.4 ppp.4 pppoe.4 pppx.4 psci.4 pty.4 puc.4 pvbus.4 \
pms.4 ppb.4 ppp.4 pppoe.4 pppx.4 psci.4 psp.4 pty.4 puc.4 pvbus.4 \
pvclock.4 pwdog.4 pwmbl.4 pwmfan.4 pwmleds.4 pwmreg.4 \
qccpu.4 qcdwusb.4 qcgpio.4 qciic.4 qcpdc.4 qcpmic.4 qcpmicgpio.4 \
qcpon.4 qcpwm.4 qcrng.4 qcrtc.4 qcspmi.4 \

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: ccp.4,v 1.5 2024/09/01 19:32:48 bluhm Exp $
.\" $OpenBSD: ccp.4,v 1.6 2024/09/04 11:12:53 jsg Exp $
.\"
.\" Copyright (c) 2018 David Gwynne <dlg@openbsd.org>
.\"
@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 1 2024 $
.Dd $Mdocdate: September 4 2024 $
.Dt CCP 4
.Os
.Sh NAME
@ -33,14 +33,9 @@ The
.Nm
driver supports feeding output of the random number generator into
the kernel entropy pool.
.Pp
On amd64
.Nm
provides
.Xr ioctl 2
access to the platform security processor (PSP).
.Sh SEE ALSO
.Xr intro 4 ,
.Xr psp 4 ,
.Xr random 4 ,
.Xr arc4random 9
.Sh HISTORY
@ -54,5 +49,3 @@ The
.Nm
driver was written by
.An David Gwynne Aq Mt dlg@openbsd.org .
PSP support was implemented by
.An Hans-Joerg Hoexer Aq Mt hshoexer@genua.de .

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: ddb.4,v 1.107 2024/02/05 21:33:00 jmc Exp $
.\" $OpenBSD: ddb.4,v 1.108 2024/09/05 08:52:27 bluhm Exp $
.\" $NetBSD: ddb.4,v 1.5 1994/11/30 16:22:09 jtc Exp $
.\"
.\" Mach Operating System
@ -25,7 +25,7 @@
.\" any improvements or extensions that they make and grant Carnegie Mellon
.\" the rights to redistribute these changes.
.\"
.Dd $Mdocdate: February 5 2024 $
.Dd $Mdocdate: September 5 2024 $
.Dt DDB 4
.Os
.Sh NAME
@ -658,7 +658,11 @@ If the
.Cm /f
modifier is specified, the complete map is printed.
.\" --------------------
.It Ic show mbuf Ar addr
.It Xo
.Ic show mbuf
.Op Cm /cp
.Ar addr
.Xc
Prints the
.Vt struct mbuf
header at
@ -668,6 +672,13 @@ Depending on the mbuf flags
and
.Vt struct m_ext
are printed as well.
If the
.Cm /c
modifier is specified, print the mbuf chain linked with the m_next
pointer.
.Cm /p
does the same using m_nextpkt.
Both can be combined.
.\" --------------------
.It Xo
.Ic show mount

54
share/man/man4/psp.4 Normal file
View file

@ -0,0 +1,54 @@
.\" $OpenBSD: psp.4,v 1.2 2024/09/04 14:24:10 jsg Exp $
.\"
.\" Copyright (c) 2024 Jonathan Gray <jsg@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 4 2024 $
.Dt PSP 4
.Os
.Sh NAME
.Nm psp
.Nd AMD Platform Security Processor
.Sh SYNOPSIS
.Cd "psp* at ccp?"
.Sh DESCRIPTION
The
.Nm
driver provides an interface to the AMD Platform Security Processor.
.Sh FILES
.Bl -tag -width /dev/psp
.It Pa /dev/psp
.El
.Sh SEE ALSO
.Xr ccp 4 ,
.Xr vmd 8
.Rs
.%T Secure Encrypted Virtualization API
.%O Publication #55766
.Re
.Rs
.%T SEV Secure Nested Paging Firmware ABI Specification
.%O Publication #56860
.Re
.Sh HISTORY
The
.Nm
device driver first appeared in
.Ox 7.6 .
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Hans-Joerg Hoexer Aq Mt hshoexer@genua.de .

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: bsd.port.mk.5,v 1.646 2024/08/15 09:46:39 tb Exp $
.\" $OpenBSD: bsd.port.mk.5,v 1.647 2024/09/04 09:07:03 sthen Exp $
.\"
.\" Copyright (c) 2000-2008 Marc Espie
.\"
@ -24,7 +24,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: August 15 2024 $
.Dd $Mdocdate: September 4 2024 $
.Dt BSD.PORT.MK 5
.Os
.Sh NAME
@ -1731,12 +1731,7 @@ checksummed and extracted (see
.Cm checksum ,
.Cm extract ) .
.Ev DISTFILES
normally holds a list of files, possibly with
.Sq :0
to
.Sq :9
appended to select a different
.Ev SITES .
normally holds a list of files.
.Pp
Preferably, adding a suffix to
.Ev DISTFILES ,

View file

@ -1,65 +0,0 @@
.\" $OpenBSD: forward.5,v 1.11 2015/12/28 23:30:59 mmcc Exp $
.\"
.\" Copyright (c) 2001 Marco S. Hyman
.\"
.\" Permission to copy all or part of this material with or without
.\" modification for any purpose is granted provided that the above
.\" copyright notice and this paragraph are duplicated in all copies.
.\"
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.Dd $Mdocdate: December 28 2015 $
.Dt FORWARD 5
.Os
.Sh NAME
.Nm forward
.Nd email forwarding information file
.Sh DESCRIPTION
Users may put a file named
.Pa .forward
in their home directory.
If this file exists,
.Xr sendmail 8
(and sendmail-like mailers) will redirect mail for the user to the list of
addresses found in the
.Pa .forward
file.
.Pp
A
.Pa .forward
file contains one or more lines where each line is an email address
or the name of a private incoming mailer where incoming mail will be
forwarded.
Multiple entries may be specified on one line, comma separated.
Additionally, a copy of all mail may be retained
on the local machine using a
.Dq \euser
entry.
.Pp
.Pa .forward
files must not be group or world writable.
The user's home directory should not be group writable.
The
.Pa .forward
file must be owned by and readable by the indicated user.
.Sh FILES
.Bl -tag -width $HOME/.forward -compact
.It Pa $HOME/.forward
email forwarding information
.El
.Sh EXAMPLES
.Bd -literal -offset indent
# lines with # in the first column are ignored
# empty lines are ignored
# #@# with whitespace on both sides may be used to start a comment
foo@bar.baz.com, \euser #@# is a comment anywhere
"| /usr/local/libexec/slocal -user foo"
.Ed
.Sh SEE ALSO
.Xr aliases 5 ,
.Xr sendmail 8
.Pp
.Lk http://www.sendmail.org/

View file

@ -1,10 +1,10 @@
.\" $OpenBSD: MAKEDEV.8,v 1.97 2023/01/14 12:19:11 kettenis Exp $
.\" $OpenBSD: MAKEDEV.8,v 1.98 2024/09/04 13:45:25 jsg Exp $
.\"
.\" THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
.\" generated from:
.\"
.\" OpenBSD: etc.amd64/MAKEDEV.md,v 1.82 2023/01/14 12:15:12 kettenis Exp
.\" OpenBSD: MAKEDEV.common,v 1.119 2023/01/14 12:15:12 kettenis Exp
.\" OpenBSD: etc.amd64/MAKEDEV.md,v 1.83 2024/09/03 09:35:46 bluhm Exp
.\" OpenBSD: MAKEDEV.common,v 1.121 2024/09/03 09:35:46 bluhm Exp
.\" OpenBSD: MAKEDEV.man,v 1.9 2017/06/06 08:11:23 tb Exp
.\" OpenBSD: MAKEDEV.mansub,v 1.2 2004/02/20 19:13:01 miod Exp
.\"
@ -23,7 +23,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: January 14 2023 $
.Dd $Mdocdate: September 4 2024 $
.Dt MAKEDEV 8 amd64
.Os
.Sh NAME
@ -299,6 +299,9 @@ paravirtual device tree root, see
.It Ar kstat
Kernel Statistics, see
.Xr kstat 4 .
.It Ar psp
Platform Security Processor, see
.Xr psp 4 .
.El
.Sh FILES
.Bl -tag -width /dev -compact

View file

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.6 2024/08/23 15:13:58 nicm Exp $
# $OpenBSD: Makefile,v 1.7 2024/09/04 14:18:36 deraadt Exp $
# from: @(#)Makefile 5.3 (Berkeley) 10/22/90
FILES= std stdcrt vt100 vt300
@ -7,7 +7,7 @@ CLEANFILES+= ${FILES}
all: ${FILES}
${FILES}:
sh ${.CURDIR}/gentabset.sh ${.CURDIR}/obj
sh ${.CURDIR}/gentabset.sh ${.OBJDIR}
realinstall: ${FILES}
install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${FILES} \

View file

@ -1,4 +1,4 @@
/* $OpenBSD: conf.c,v 1.81 2024/06/12 12:54:54 bluhm Exp $ */
/* $OpenBSD: conf.c,v 1.82 2024/09/04 07:45:08 jsg Exp $ */
/*
* Copyright (c) 1994, 1995 Charles M. Hannum. All rights reserved.
@ -152,8 +152,6 @@ cdev_decl(nvram);
#include "drm.h"
#include "viocon.h"
cdev_decl(viocon);
#include "ccp.h"
cdev_decl(psp);
#include "wsdisplay.h"
#include "wskbd.h"
@ -292,7 +290,7 @@ struct cdevsw cdevsw[] =
cdev_fido_init(NFIDO,fido), /* 98: FIDO/U2F security keys */
cdev_pppx_init(NPPPX,pppac), /* 99: PPP Access Concentrator */
cdev_ujoy_init(NUJOY,ujoy), /* 100: USB joystick/gamecontroller */
cdev_psp_init(NCCP,psp), /* 101: PSP */
cdev_psp_init(NPSP,psp), /* 101: PSP */
};
int nchrdev = nitems(cdevsw);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: trap.c,v 1.105 2024/02/21 15:53:07 deraadt Exp $ */
/* $OpenBSD: trap.c,v 1.106 2024/09/04 07:54:51 mglocker Exp $ */
/* $NetBSD: trap.c,v 1.2 2003/05/04 23:51:56 fvdl Exp $ */
/*-
@ -182,7 +182,7 @@ upageflttrap(struct trapframe *frame, uint64_t cr2)
int signal, sicode, error;
/*
* If NX is not enabled, we cant distinguish between PROT_READ
* If NX is not enabled, we can't distinguish between PROT_READ
* and PROT_EXEC access, so try both.
*/
error = uvm_fault(&p->p_vmspace->vm_map, va, 0, access_type);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: vmm_machdep.c,v 1.34 2024/09/03 13:36:19 dv Exp $ */
/* $OpenBSD: vmm_machdep.c,v 1.36 2024/09/04 16:12:40 dv Exp $ */
/*
* Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
*
@ -4181,7 +4181,8 @@ vcpu_run_vmx(struct vcpu *vcpu, struct vm_run_params *vrp)
break;
}
if (!(exitinfo & VMX_EXIT_INFO_HAVE_REASON)) {
printf("%s: cant read exit reason\n", __func__);
printf("%s: can't read exit reason\n",
__func__);
ret = EINVAL;
break;
}
@ -6281,7 +6282,8 @@ vmm_handle_cpuid(struct vcpu *vcpu)
*rdx = 0;
break;
case 0x80000000: /* Extended function level */
*rax = 0x8000001f; /* curcpu()->ci_pnfeatset */
/* We don't emulate past 0x8000001f currently. */
*rax = min(curcpu()->ci_pnfeatset, 0x8000001f);
*rbx = 0;
*rcx = 0;
*rdx = 0;

View file

@ -1,4 +1,4 @@
# $OpenBSD: GENERIC,v 1.525 2024/08/14 14:40:45 patrick Exp $
# $OpenBSD: GENERIC,v 1.526 2024/09/04 07:45:08 jsg Exp $
#
# For further information on compiling SecBSD kernels, see the config(8)
# man page.
@ -123,6 +123,7 @@ ksmn* at pci? # AMD K17 temperature sensor
amas* at pci? disable # AMD memory configuration
pchtemp* at pci? # Intel C610 temperature sensor
ccp* at pci? # AMD Cryptographic Co-processor
psp* at ccp? # AMD Platform Security Processor
# National Semiconductor LM7[89] and compatible hardware monitors
lm0 at isa? port 0x290

View file

@ -1,4 +1,4 @@
# $OpenBSD: files.amd64,v 1.110 2024/09/03 00:23:05 jsg Exp $
# $OpenBSD: files.amd64,v 1.111 2024/09/04 07:45:08 jsg Exp $
maxpartitions 16
maxusers 2 16 128
@ -65,8 +65,6 @@ file arch/amd64/amd64/powernow-k8.c !small_kernel
file arch/amd64/amd64/est.c !small_kernel
file arch/amd64/amd64/k1x-pstate.c !small_kernel
file dev/ic/psp.c ccp
include "dev/rasops/files.rasops"
include "dev/wsfont/files.wsfont"

View file

@ -1,4 +1,4 @@
/* $OpenBSD: conf.h,v 1.10 2024/09/01 17:13:46 bluhm Exp $ */
/* $OpenBSD: conf.h,v 1.11 2024/09/04 07:45:08 jsg Exp $ */
/* $NetBSD: conf.h,v 1.2 1996/05/05 19:28:34 christos Exp $ */
/*
@ -55,5 +55,5 @@ cdev_decl(pctr);
#include "vmm.h"
cdev_decl(vmm);
#include "ccp.h"
#include "psp.h"
cdev_decl(psp);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: trap.c,v 1.164 2023/12/13 15:57:22 miod Exp $ */
/* $OpenBSD: trap.c,v 1.165 2024/09/04 07:54:51 mglocker Exp $ */
/* $NetBSD: trap.c,v 1.95 1996/05/05 06:50:02 mycroft Exp $ */
/*-
@ -121,7 +121,7 @@ upageflttrap(struct trapframe *frame, uint32_t cr2)
/*
* cpu_pae is true if system has PAE + NX.
* If NX is not enabled, we cant distinguish between PROT_READ
* If NX is not enabled, we can't distinguish between PROT_READ
* and PROT_EXEC access, so try both.
*/
error = uvm_fault(&p->p_vmspace->vm_map, va, 0, access_type);

View file

@ -1,4 +1,4 @@
# $OpenBSD: files,v 1.736 2024/08/31 04:17:14 dlg Exp $
# $OpenBSD: files,v 1.737 2024/09/04 07:45:08 jsg Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@ -470,9 +470,14 @@ device xhci: usbus
file dev/usb/xhci.c xhci needs-flag
# AMD Cryptographic Co-processor
device ccp
device ccp {}
file dev/ic/ccp.c ccp needs-flag
# AMD Platform Security Processor
device psp
attach psp at ccp
file dev/ic/psp.c psp needs-flag
# SDHC SD/MMC controller
define sdhc
device sdhc: sdmmcbus

View file

@ -1,4 +1,4 @@
/* $OpenBSD: siphash.h,v 1.5 2015/02/20 11:51:03 tedu Exp $ */
/* $OpenBSD: siphash.h,v 1.6 2024/09/04 07:54:52 mglocker Exp $ */
/*-
* Copyright (c) 2013 Andre Oppermann <andre@FreeBSD.org>
* All rights reserved.
@ -35,7 +35,7 @@
* optimized for speed on short messages returning a 64bit hash/digest value.
*
* The number of rounds is defined during the initialization:
* SipHash24_Init() for the fast and resonable strong version
* SipHash24_Init() for the fast and reasonably strong version
* SipHash48_Init() for the strong version (half as fast)
*
* struct SIPHASH_CTX ctx;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: db_command.c,v 1.101 2024/05/13 01:15:50 jsg Exp $ */
/* $OpenBSD: db_command.c,v 1.102 2024/09/05 08:52:27 bluhm Exp $ */
/* $NetBSD: db_command.c,v 1.20 1996/03/30 22:30:05 christos Exp $ */
/*
@ -340,7 +340,15 @@ db_malloc_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
void
db_mbuf_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
{
m_print((void *)addr, db_printf);
if ((modif[0] == 'c' && modif[1] == 'p') ||
(modif[0] == 'p' && modif[1] == 'c'))
m_print_packet((void *)addr, 1, db_printf);
else if (modif[0] == 'c')
m_print_chain((void *)addr, 0, db_printf);
else if (modif[0] == 'p')
m_print_packet((void *)addr, 0, db_printf);
else
m_print((void *)addr, db_printf);
}
void

View file

@ -1,4 +1,4 @@
/* $OpenBSD: db_elf.c,v 1.32 2021/03/12 10:22:46 jsg Exp $ */
/* $OpenBSD: db_elf.c,v 1.33 2024/09/04 07:54:52 mglocker Exp $ */
/* $NetBSD: db_elf.c,v 1.13 2000/07/07 21:55:18 jhawk Exp $ */
/*-
@ -280,7 +280,7 @@ db_elf_sym_search(vaddr_t off, db_strategy_t strategy, db_expr_t *diffp)
if (symp->st_name == 0)
continue;
#if 0
/* This prevents me from seeing anythin in locore.s -- eeh */
/* This prevents me from seeing anything in locore.s -- eeh */
if (ELF_SYM_TYPE(symp->st_info) != Elf_estt_object &&
ELF_SYM_TYPE(symp->st_info) != Elf_estt_func)
continue;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: db_interface.h,v 1.27 2024/02/03 18:51:58 beck Exp $ */
/* $OpenBSD: db_interface.h,v 1.28 2024/09/05 08:52:27 bluhm Exp $ */
/* $NetBSD: db_interface.h,v 1.1 1996/02/05 01:57:03 christos Exp $ */
/*
@ -61,6 +61,8 @@ void db_show_all_pools(db_expr_t, int, db_expr_t, char *);
/* kern/uipc_mbuf.c */
void m_print(void *, int (*)(const char *, ...));
void m_print_chain(void *, int, int (*)(const char *, ...));
void m_print_packet(void *, int, int (*)(const char *, ...));
/* kern/uipc_socket.c */
void so_print(void *, int (*)(const char *, ...));

View file

@ -1,4 +1,4 @@
/* $OpenBSD: acpi.c,v 1.438 2024/08/18 02:53:08 deraadt Exp $ */
/* $OpenBSD: acpi.c,v 1.439 2024/09/04 21:39:18 hastings Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@ -3249,7 +3249,6 @@ acpi_foundhid(struct aml_node *node, void *arg)
aaa.aaa_node = node->parent;
aaa.aaa_dev = dev;
aaa.aaa_cdev = cdev;
acpi_parse_crs(sc, &aaa);
#ifndef SMALL_KERNEL
if (!strcmp(cdev, ACPI_DEV_MOUSE)) {
@ -3266,6 +3265,8 @@ acpi_foundhid(struct aml_node *node, void *arg)
acpi_matchhids(&aaa, acpi_isa_hids, "none"))
return (0);
acpi_parse_crs(sc, &aaa);
aaa.aaa_dmat = acpi_iommu_device_map(node->parent, aaa.aaa_dmat);
if (!node->parent->attached) {

View file

@ -1,4 +1,4 @@
/* $OpenBSD: atk0110.c,v 1.19 2022/04/06 18:59:27 naddy Exp $ */
/* $OpenBSD: atk0110.c,v 1.20 2024/09/04 07:54:52 mglocker Exp $ */
/*
* Copyright (c) 2009 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru>
@ -215,7 +215,7 @@ aibs_attach_sif(struct aibs_softc *sc, enum sensor_type st)
aml_freevalue(&res);
return;
} else if (res.length - 1 > n) {
printf("%s: %s: misformed package: %i/%i",
printf("%s: %s: malformed package: %i/%i",
DEVNAME(sc), name, n, res.length - 1);
#ifdef AIBS_MORE_SENSORS
n = res.length - 1;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: atascsi.c,v 1.155 2024/05/26 10:01:01 jsg Exp $ */
/* $OpenBSD: atascsi.c,v 1.156 2024/09/04 07:54:52 mglocker Exp $ */
/*
* Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
@ -418,7 +418,7 @@ atascsi_probe(struct scsi_link *link)
xa->pmp_port = ap->ap_pmp_port;
xa->atascsi_private = &ahp->ahp_iopool;
ata_exec(as, xa);
ata_polled(xa); /* we dont care if it doesnt work */
ata_polled(xa); /* we don't care if it doesn't work */
return (0);
error:
@ -1797,7 +1797,7 @@ ata_polled(struct ata_xfer *xa)
int rv;
if (!ISSET(xa->flags, ATA_F_DONE))
panic("ata_polled: xa isnt complete");
panic("ata_polled: xa isn't complete");
switch (xa->state) {
case ATA_S_COMPLETE:

View file

@ -1,4 +1,4 @@
/* $OpenBSD: com_cardbus.c,v 1.45 2024/05/24 06:26:47 jsg Exp $ */
/* $OpenBSD: com_cardbus.c,v 1.46 2024/09/04 07:54:52 mglocker Exp $ */
/* $NetBSD: com_cardbus.c,v 1.4 2000/04/17 09:21:59 joda Exp $ */
/*
@ -36,7 +36,7 @@
/* This is a driver for CardBus based serial devices. It is less
generic than it could be, but it keeps the complexity down. So far
it assumes that anything that reports itself as a `serial' device
is infact a 16x50 or 8250, which is not necessarily true (in
is in fact a 16x50 or 8250, which is not necessarily true (in
practice this shouldn't be a problem). It also does not handle
devices in the `multiport serial' or `modem' sub-classes, I've
never seen any of these, so I don't know what they might look like.

View file

@ -1,4 +1,4 @@
/* $OpenBSD: i2c_scan.c,v 1.146 2019/12/16 19:17:04 claudio Exp $ */
/* $OpenBSD: i2c_scan.c,v 1.147 2024/09/04 07:54:52 mglocker Exp $ */
/*
* Copyright (c) 2005 Theo de Raadt <deraadt@openbsd.org>
@ -657,7 +657,7 @@ iic_probe_sensor(struct device *self, u_int8_t addr)
(iicprobe(0x03) & 0x3f) == 0x00 && iicprobe(0x04) <= 0x08)
/*
* Genesys Logic doesn't make the datasheet
* for the GL523SM publically available, so
* for the GL523SM publicly available, so
* the checks above are nothing more than a
* (conservative) educated guess.
*/

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