sync code with last improvements from OpenBSD

This commit is contained in:
purplerain 2023-09-06 22:21:59 +00:00
parent 30d14db1d3
commit 0c904fa153
Signed by: purplerain
GPG Key ID: F42C07F07E2E35B7
235 changed files with 12410 additions and 6193 deletions

View File

@ -1,10 +1,10 @@
.\" $OpenBSD: ASN1_OBJECT_new.3,v 1.15 2021/12/15 20:07:51 schwarze Exp $
.\" $OpenBSD: ASN1_OBJECT_new.3,v 1.16 2023/09/05 15:01:39 schwarze Exp $
.\" full merge up to: OpenSSL 99d63d4 Mar 19 12:28:58 2016 -0400
.\"
.\" This file is a derived work.
.\" The changes are covered by the following Copyright and license:
.\"
.\" Copyright (c) 2017, 2021 Ingo Schwarze <schwarze@openbsd.org>
.\" Copyright (c) 2017, 2021, 2023 Ingo Schwarze <schwarze@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
@ -65,7 +65,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: December 15 2021 $
.Dd $Mdocdate: September 5 2023 $
.Dt ASN1_OBJECT_NEW 3
.Os
.Sh NAME
@ -207,3 +207,22 @@ first appeared in SSLeay 0.5.1 and
in SSLeay 0.8.0.
These functions have been available since
.Ox 2.4 .
.Sh BUGS
The function
.Fn ASN1_OBJECT_new
is not useful for any practical purpose because the library does not
provide any function capable of adding data to an existing object.
Consequently, if the application program creates an object with
.Fn ASN1_OBJECT_new ,
that object will always remain empty.
.Pp
Similarly, if an
.Fa nid
of
.Dv NID_undef
is passed to
.Fn ASN1_OBJECT_create ,
or if
.Dv NULL
is passed for any of its pointer arguments, the returned object
will permanently remain incomplete.

View File

@ -1,6 +1,23 @@
.\" $OpenBSD: EVP_CIPHER_meth_new.3,v 1.2 2023/08/26 15:14:28 schwarze Exp $
.\" $OpenBSD: EVP_CIPHER_meth_new.3,v 1.4 2023/09/05 14:37:00 schwarze Exp $
.\" selective merge up to: OpenSSL b0edda11 Mar 20 13:00:17 2018 +0000
.\"
.\" This file is a derived work.
.\" The changes are covered by the following Copyright and license:
.\"
.\" Copyright (c) 2023 Ingo Schwarze <schwarze@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.
.\"
.\" The original file was written by Richard Levitte <levitte@openssl.org>
.\" Copyright (c) 2015 The OpenSSL Project.
.\" All rights reserved.
@ -49,7 +66,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: August 26 2023 $
.Dd $Mdocdate: September 5 2023 $
.Dt EVP_CIPHER_METH_NEW 3
.Os
.Sh NAME
@ -184,75 +201,116 @@ Zero or more of the following flags can be OR'ed into the
.Fa flags
argument:
.Bl -tag -width Ds
.It EVP_CIPH_VARIABLE_LENGTH
This cipher is of variable length.
.It EVP_CIPH_CUSTOM_IV
Storing and initialising the IV is left entirely to the implementation.
.It EVP_CIPH_ALWAYS_CALL_INIT
Set this if the implementation's
.Fn init
function should be called even if
.Fa key
is
.Dv NULL .
.It EVP_CIPH_CTRL_INIT
Set this to have the implementation's
.Fn ctrl
function called with command code
.Dv EVP_CTRL_INIT
early in its setup.
.It EVP_CIPH_CUSTOM_KEY_LENGTH
Checking and setting the key length after creating the
.Vt EVP_CIPHER
is left to the implementation.
Whenever someone uses
.It Dv EVP_CIPH_VARIABLE_LENGTH
This cipher has a variable key length, and the function
.Xr EVP_CIPHER_CTX_set_key_length 3
on a
.Vt EVP_CIPHER
with this flag set, the implementation's
.Fn ctrl
function will be called with the control code
can be used with it.
.It Dv EVP_CIPH_CUSTOM_IV
Instruct
.Xr EVP_CipherInit_ex 3
and similar initialization functions to leave storing and initialising
the IV entirely to the implementation.
If this flag is set,
the implementation is typically expected to do that in its
.Fa init
function.
.It Dv EVP_CIPH_ALWAYS_CALL_INIT
Instruct
.Xr EVP_CipherInit_ex 3
and similar initialization functions to call the implementation's
.Fa init
function even if the
.Fa key
argument is
.Dv NULL .
.It Dv EVP_CIPH_CTRL_INIT
Instruct
.Xr EVP_CipherInit_ex 3
and similar initialization functions to call the implementation's
.Fa ctrl
function with a command
.Fa type
of
.Dv EVP_CTRL_INIT
early during the setup.
.It Dv EVP_CIPH_CUSTOM_KEY_LENGTH
Instruct
.Xr EVP_CIPHER_CTX_set_key_length 3
to not check and set the key length itself,
but to leave that to the implementation by instead calling its
.Fa ctrl
function with a command
.Fa type
of
.Dv EVP_CTRL_SET_KEY_LENGTH
and the key length in
.Fa arg .
.It EVP_CIPH_NO_PADDING
Don't use standard block padding.
.It EVP_CIPH_RAND_KEY
Making a key with random content is left to the implementation.
This is done by calling the implementation's
.Fn ctrl
function with the control code
.It Dv EVP_CIPH_NO_PADDING
Instruct
.Xr EVP_CipherFinal_ex 3
and similar finalization functions to not use standard block padding
but instead report an error if the total amount of data
to be encrypted or decrypted is not a multiple of the block size.
.It Dv EVP_CIPH_RAND_KEY
Instruct
.Xr EVP_CIPHER_CTX_rand_key 3
to not generate a random key using
.Xr arc4random_buf 3
but instead leave that to the implementation by calling the
.Fa ctrl
function with a command
.Fa type
of
.Dv EVP_CTRL_RAND_KEY
and the pointer to the key memory storage in
.Fa ptr .
.It EVP_CIPH_CUSTOM_COPY
Set this to have the implementation's
.Fn ctrl
function called with command code
.It Dv EVP_CIPH_CUSTOM_COPY
Instruct
.Xr EVP_CIPHER_CTX_copy 3
to call the implementation's
.Fa ctrl
function with a command
.Fa type
of
.Dv EVP_CTRL_COPY
at the end of
.Xr EVP_CIPHER_CTX_copy 3 .
and the destination
.Fa "EVP_CIPHER_CTX *out"
in the
.Fa ptr
argument immediately before returning successfully.
The intended use is for further things to deal with after the
implementation specific data block has been copied.
The destination
.Vt EVP_CIPHER_CTX
object is passed to the control with the
.Fa ptr
parameter.
The implementation-specific data block is reached with
.Xr EVP_CIPHER_CTX_get_cipher_data 3 .
.It EVP_CIPH_FLAG_DEFAULT_ASN1
Use the default EVP routines to pass IV to and from ASN.1.
.It EVP_CIPH_FLAG_LENGTH_BITS
.It Dv EVP_CIPH_FLAG_DEFAULT_ASN1
Instruct
.Xr EVP_CIPHER_param_to_asn1 3
to use
.Xr ASN1_TYPE_set_octetstring 3
if no
.Fa set_asn1_parameters
function is installed, and instruct
.Xr EVP_CIPHER_asn1_to_param 3
to use
.Xr ASN1_TYPE_get_octetstring 3
if no
.Fa get_asn1_parameters
function is installed.
.It Dv EVP_CIPH_FLAG_LENGTH_BITS
Signals that the length of the input buffer for encryption / decryption
is to be understood as the number of bits instead of bytes for this
implementation.
This is only useful for CFB1 ciphers.
.It EVP_CIPH_FLAG_CUSTOM_CIPHER
This indicates that the implementation takes care of everything,
.It Dv EVP_CIPH_FLAG_CUSTOM_CIPHER
Instruct
.Xr EVP_CipherUpdate 3 ,
.Xr EVP_CipherFinal_ex 3 ,
and similar encryption, decryption, and finalization functions
that the implementation's
.Fa do_cipher
function takes care of everything,
including padding, buffering and finalization.
The EVP routines will simply give them control and do nothing more.
.It EVP_CIPH_FLAG_AEAD_CIPHER
.It Dv EVP_CIPH_FLAG_AEAD_CIPHER
This indicates that this is an AEAD cipher implementation.
.El
.Pp
@ -261,7 +319,9 @@ sets the size of the EVP_CIPHER's implementation context so that it can
be automatically allocated.
.Pp
.Fn EVP_CIPHER_meth_set_init
sets the cipher init function for
sets the
.Fa init
function for
.Fa cipher .
The cipher init function is called by
.Xr EVP_CipherInit 3 ,
@ -269,6 +329,7 @@ The cipher init function is called by
.Xr EVP_EncryptInit 3 ,
.Xr EVP_EncryptInit_ex 3 ,
.Xr EVP_DecryptInit 3 ,
and
.Xr EVP_DecryptInit_ex 3 .
.Pp
.Fn EVP_CIPHER_meth_set_do_cipher

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: EVP_CIPHER_nid.3,v 1.2 2023/09/01 17:28:21 schwarze Exp $
.\" $OpenBSD: EVP_CIPHER_nid.3,v 1.3 2023/09/05 14:54:21 schwarze Exp $
.\" full merge up to: OpenSSL man3/EVP_EncryptInit.pod
.\" 0874d7f2 Oct 11 13:13:47 2022 +0100
.\"
@ -66,12 +66,13 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: September 1 2023 $
.Dd $Mdocdate: September 5 2023 $
.Dt EVP_CIPHER_NID 3
.Os
.Sh NAME
.Nm EVP_CIPHER_nid ,
.Nm EVP_CIPHER_CTX_nid ,
.Nm EVP_CIPHER_name ,
.Nm EVP_CIPHER_type ,
.Nm EVP_CIPHER_CTX_type ,
.Nm EVP_CIPHER_block_size ,
@ -91,6 +92,10 @@
.Fo EVP_CIPHER_CTX_nid
.Fa "const EVP_CIPHER_CTX *ctx"
.Fc
.Ft const char *
.Fo EVP_CIPHER_name
.Fa "const EVP_CIPHER *cipher"
.Fc
.Ft int
.Fo EVP_CIPHER_type
.Fa "const EVP_CIPHER *ctx"
@ -137,6 +142,12 @@ returns the NID of the cipher that
.Fa ctx
is configured to use.
.Pp
.Fn EVP_CIPHER_name
converts the NID of the
.Fa cipher
to its short name with
.Xr OBJ_nid2sn 3 .
.Pp
.Fn EVP_CIPHER_type
returns the NID associated with the ASN.1 OBJECT IDENTIFIER of the
.Fa cipher ,
@ -196,12 +207,27 @@ and the return value of
returns the cipher mode of the cipher that
.Fa ctx
is configured to use.
.Pp
.Fn EVP_CIPHER_name ,
.Fn EVP_CIPHER_CTX_type ,
.Fn EVP_CIPHER_mode ,
and
.Fn EVP_CIPHER_CTX_mode
are implemented as macros.
.Sh RETURN VALUES
.Fn EVP_CIPHER_nid
and
.Fn EVP_CIPHER_CTX_nid
return an NID.
.Pp
.Fn EVP_CIPHER_name
returns a pointer to a string that is owned by an internal library object or
.Dv NULL
if the NID is neither built into the library nor added to the global
object table by one of the functions documented in the manual page
.Xr OBJ_create 3 ,
of if the object does not contain a short name.
.Pp
.Fn EVP_CIPHER_type
and
.Fn EVP_CIPHER_CTX_type
@ -264,6 +290,10 @@ and
.Fn EVP_CIPHER_CTX_mode
first appeared in OpenSSL 0.9.6 and have been available since
.Ox 2.9 .
.Pp
.Fn EVP_CIPHER_name
first appeared in OpenSSL 0.9.7 and has been available since
.Ox 3.2 .
.Sh CAVEATS
The behaviour of the functions taking an
.Vt EVP_CIPHER_CTX

View File

@ -1,11 +1,11 @@
.\" $OpenBSD: OBJ_nid2obj.3,v 1.20 2023/07/21 05:02:53 tb Exp $
.\" $OpenBSD: OBJ_nid2obj.3,v 1.21 2023/09/05 13:50:22 schwarze Exp $
.\" full merge up to: OpenSSL c264592d May 14 11:28:00 2006 +0000
.\" selective merge up to: OpenSSL 35fd9953 May 28 14:49:38 2019 +0200
.\"
.\" This file is a derived work.
.\" The changes are covered by the following Copyright and license:
.\"
.\" Copyright (c) 2017, 2021 Ingo Schwarze <schwarze@openbsd.org>
.\" Copyright (c) 2017, 2021, 2023 Ingo Schwarze <schwarze@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
@ -67,7 +67,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: July 21 2023 $
.Dd $Mdocdate: September 5 2023 $
.Dt OBJ_NID2OBJ 3
.Os
.Sh NAME
@ -89,19 +89,19 @@
.In openssl/objects.h
.Ft ASN1_OBJECT *
.Fo OBJ_nid2obj
.Fa "int n"
.Fa "int nid"
.Fc
.Ft const char *
.Fo OBJ_nid2ln
.Fa "int n"
.Fa "int nid"
.Fc
.Ft const char *
.Fo OBJ_nid2sn
.Fa "int n"
.Fa "int nid"
.Fc
.Ft int
.Fo OBJ_obj2nid
.Fa "const ASN1_OBJECT *o"
.Fa "const ASN1_OBJECT *object"
.Fc
.Ft int
.Fo OBJ_ln2nid
@ -124,7 +124,7 @@
.Fo OBJ_obj2txt
.Fa "char *buf"
.Fa "int buf_len"
.Fa "const ASN1_OBJECT *a"
.Fa "const ASN1_OBJECT *object"
.Fa "int no_name"
.Fc
.Ft int
@ -134,86 +134,102 @@
.Fc
.Ft ASN1_OBJECT *
.Fo OBJ_dup
.Fa "const ASN1_OBJECT *o"
.Fa "const ASN1_OBJECT *object"
.Fc
.In openssl/asn1.h
.Ft int
.Fo i2t_ASN1_OBJECT
.Fa "char *buf"
.Fa "int buf_len"
.Fa "const ASN1_OBJECT *a"
.Fa "const ASN1_OBJECT *object"
.Fc
.Ft int
.Fo i2a_ASN1_OBJECT
.Fa "BIO *out_bio"
.Fa "const ASN1_OBJECT *a"
.Fa "const ASN1_OBJECT *object"
.Fc
.Sh DESCRIPTION
The ASN.1 object utility functions process
.Vt ASN1_OBJECT
structures which are a representation of the ASN.1 OBJECT IDENTIFIER
(OID) type.
For convenience, OIDs are usually represented in source code as
numeric identifiers, or NIDs.
OpenSSL has an internal table of OIDs that are generated when the
library is built, and their corresponding NIDs are available as
defined constants.
For the functions below, application code should treat all returned
values \(em OIDs, NIDs, or names \(em as constants.
structures, in the following called
.Dq objects .
An object represents an ASN.1
.Vt OBJECT IDENTIFIER
.Pq OID .
The library maintains an internal global table of objects.
Many of these objects are built into the library
and contained in the global table by default.
The application program can add additional objects to the global table
by using functions documented in the
.Xr OBJ_create 3
manual page.
Consequently, there are three classes of objects:
built-in table objects, user-defined table objects, and non-table objects.
.Pp
.Fn OBJ_nid2obj ,
.Fn OBJ_nid2ln ,
In addition to the OID, each object can hold
a long name, a short name, and a numerical identifier (NID).
Even though the concept of NIDs is specific to the library
and not standardized, using the NID is often the most convenient way
for source code to refer to a specific OID.
The NIDs of the built-in objects are available as defined constants.
.Pp
Built-in table objects have certain advantages
over objects that are not in the global table:
for example, their NIDs can be used in C language switch statements.
They are also shared:
there is only a single static constant structure for each built-on OID.
.Pp
Some functions operate on table objects only:
.Pp
.Fn OBJ_nid2obj
retrieves the table object associated with the
.Fa nid .
.Fn OBJ_nid2ln
and
.Fn OBJ_nid2sn
convert the NID
.Fa n
to an
.Vt ASN1_OBJECT
structure, its long name, and its short name, respectively, or return
.Dv NULL
if an error occurred.
retrieve its long and short name, respectively.
.Pp
.Fn OBJ_obj2nid ,
.Fn OBJ_ln2nid ,
.Fn OBJ_obj2nid
retrieves the NID associated with the given
.Fa object ,
which is either the NID stored in the
.Fa object
itself, if any, or otherwise the NID stored in a table object
containing the same OID.
.Pp
.Fn OBJ_ln2nid
and
.Fn OBJ_sn2nid
return the corresponding NID for the object
.Fa o ,
the long name
.Fa ln ,
retrieve the NID from the table object with the long name
.Fa ln
or the short name
.Fa sn ,
respectively, or
.Dv NID_undef
if an error occurred.
respectively.
.Pp
.Fn OBJ_txt2nid
returns the NID corresponding to text string
.Fa s .
.Fa s
can be a long name, a short name, or the numerical representation
of an object.
retrieves the NID from the table object described by the text string
.Fa s ,
which can be a long name, a short name,
or the numerical representation of an OID.
.Pp
The remaining functions can be used both on table objects
and on objects that are not in the global table:
.Pp
.Fn OBJ_txt2obj
converts the text string
.Fa s
into an
.Vt ASN1_OBJECT
structure.
retrieves or creates an object matching the text string
.Fa s .
If
.Fa no_name
is 0 then long names and short names will be interpreted as well as
numerical forms.
is 1, only the numerical representation of an OID is accepted.
If
.Fa no_name
is 1, only the numerical form is acceptable.
is 0, long names and short names are accepted as well.
.Pp
.Fn OBJ_obj2txt
converts the
.Vt ASN1_OBJECT
.Fa a
into a textual representation.
The representation is written as a NUL terminated string to
writes a NUL terminated textual representation
of the OID contained in the given
.Fa object
into
.Fa buf .
At most
.Fa buf_len
@ -221,8 +237,13 @@ bytes are written, truncating the result if necessary.
The total amount of space required is returned.
If
.Fa no_name
is 0 and the object has a long or short name, then that will be used,
otherwise the numerical form will be used.
is 0 and the table object containing the same OID
contains a long name, the long name is written.
Otherwise, if
.Fa no_name
is 0 and the table object containing the same OID
contains a short name, the short name is written.
Otherwise, the numerical representation of the OID is written.
.Pp
.Fn i2t_ASN1_OBJECT
is the same as
@ -232,18 +253,18 @@ with
set to 0.
.Pp
.Fn i2a_ASN1_OBJECT
writes a textual representation of
.Fa a
writes a textual representation of the OID contained in the given
.Fa object
to
.Fa out_bio
using
.Xr BIO_write 3 .
It does not write a terminating NUL byte.
If
.Fa a
is
If the
.Fa object
argument is
.Dv NULL
or contains no data, it writes the 4-byte string
or contains no OID, it writes the 4-byte string
.Qq NULL .
If
.Fn i2t_ASN1_OBJECT
@ -255,103 +276,128 @@ Otherwise, it writes the string constructed with
.Fn i2t_ASN1_OBJECT .
.Pp
.Fn OBJ_cmp
compares
tests whether
.Fa a
to
.Fa b .
If the two are identical, 0 is returned.
and
.Fa b
represent the same ASN.1
.Vt OBJECT IDENTIFIER .
Any names and NIDs contained in the two objects are ignored,
even if they differ between both objects.
.Pp
.Fn OBJ_dup
returns a deep copy of
.Fa o
if
.Fa o
is marked as dynamically allocated.
The new object and all data contained in it is marked as dynamically
returns a deep copy of the given
.Fa object
if it is marked as dynamically allocated.
The new object and all data contained in it are marked as dynamically
allocated.
If
.Fa o
If the given
.Fa object
is not marked as dynamically allocated,
.Fn OBJ_dup
just returns
.Fa o
just returns a pointer to the
.Fa object
itself.
.Pp
Objects can have a short name, a long name, and a numerical
identifier (NID) associated with them.
A standard set of objects is represented in an internal table.
The appropriate values are defined in the header file
.In openssl/objects.h .
.Pp
For example, the OID for commonName has the following definitions:
.Bd -literal
#define SN_commonName "CN"
#define LN_commonName "commonName"
#define NID_commonName 13
.Ed
.Pp
New objects can be added by calling
.Xr OBJ_create 3 .
.Pp
Table objects have certain advantages over other objects: for example
their NIDs can be used in a C language switch statement.
They are also static constant structures which are shared: that is there
is only a single constant structure for each table object.
.Pp
Objects which are not in the table have the NID value
.Dv NID_undef .
.Pp
Objects do not need to be in the internal tables to be processed:
the functions
.Fn OBJ_txt2obj
and
.Fn OBJ_obj2txt
can process the numerical form of an OID.
.Sh RETURN VALUES
.Fn OBJ_nid2obj ,
.Fn OBJ_txt2obj ,
and
.Fn OBJ_dup
return an
.Vt ASN1_OBJECT
object or
Application code should treat all returned values \(em
objects, names, and NIDs \(em as constants.
.Pp
.Fn OBJ_nid2obj
returns a pointer to a table object owned by the library or
.Dv NULL
if an error occurs.
if no matching table object is found.
.Pp
.Fn OBJ_nid2ln
and
.Fn OBJ_nid2sn
return a valid string or
return a pointer to a string owned by a table object or
.Dv NULL
on error.
.Pp
.Fn OBJ_obj2nid ,
.Fn OBJ_ln2nid ,
.Fn OBJ_sn2nid ,
if no matching table object is found.
For
.Dv NID_undef ,
they return the constant static strings
.Qq undefined
and
.Fn OBJ_txt2nid
return a NID or
.Qq UNDEF ,
respectively.
.Pp
.Fn OBJ_obj2nid
returns an NID on success, or
.Dv NID_undef
on error.
if
.Fa object
is
.Dv NULL ,
does not contain an OID,
if no table object matching the OID is found,
or if the matching object does not contain an NID.
.Pp
.Fn OBJ_ln2nid
and
.Fn OBJ_sn2nid
return an NID on success or
.Dv NID_undef
if no matching table object is found
or if the matching object does not contain an NID.
.Pp
.Fn OBJ_txt2nid
returns an NID on success or
.Dv NID_undef
if parsing of
.Fa s
or memory allocation fails, if no matching table object is found,
or if the matching object does not contain an NID.
.Pp
.Fn OBJ_txt2obj
returns a pointer to a table object owned by the library if lookup of
.Fa s
as a long or short name succeeds.
Otherwise, it returns a newly created object,
transferring ownership to the caller, or
.Dv NULL
if parsing of
.Fa s
or memory allocation fails.
.Pp
.Fn OBJ_obj2txt
and
.Fn i2t_ASN1_OBJECT
return the amount of space required in bytes,
including the terminating NUL byte.
.Pp
.Fn i2a_ASN1_OBJECT
returns the number of bytes written, even if
.Fa a
is invalid or contains invalid data,
but a negative value if memory allocation or a write operation fails.
including the terminating NUL byte,
or zero if an error occurs before the required space can be calculated,
in particular if
.Fa buf_len
is negative,
.Fa object
is
.Dv NULL
or does not contain an OID,
or if memory allocation fails.
.Pp
.Fn OBJ_cmp
returns 0 if the contents of
.Fa a
and
.Fa b
are identical, or non-zero otherwise.
returns 0 if both objects refer to the same OID
or neither of them are associated with any OID,
or a non-zero value if at least one of them refers to an OID
but the other one does not refer to the same OID.
.Pp
.Fn OBJ_dup
returns the pointer to the original
.Fa object
if it is not marked as dynamically allocated.
Otherwise, it returns a newly created object,
transferring ownership to the caller, or
.Dv NULL
if
.Fa object
is
.Dv NULL
or memory allocation fails.
.Pp
.Fn i2a_ASN1_OBJECT
returns the number of bytes written, even if the given
.Fa object
is invalid or contains invalid data,
but a negative value if memory allocation or a write operation fails.
.Pp
In some cases of failure of
.Fn OBJ_nid2obj ,
@ -367,23 +413,23 @@ and
the reason can be determined with
.Xr ERR_get_error 3 .
.Sh EXAMPLES
Create an object for
Retrieve the object for
.Sy commonName :
.Bd -literal -offset indent
ASN1_OBJECT *o;
o = OBJ_nid2obj(NID_commonName);
ASN1_OBJECT *object;
object = OBJ_nid2obj(NID_commonName);
.Ed
.Pp
Check if an object is
Check whether an object contains the OID for
.Sy commonName :
.Bd -literal -offset indent
if (OBJ_obj2nid(obj) == NID_commonName)
if (OBJ_obj2nid(object) == NID_commonName)
/* Do something */
.Ed
.Pp
Create a new object directly:
.Bd -literal -offset indent
obj = OBJ_txt2obj("1.2.3.4", 1);
object = OBJ_txt2obj("1.2.3.4", 1);
.Ed
.Sh SEE ALSO
.Xr ASN1_OBJECT_new 3 ,
@ -416,7 +462,52 @@ first appeared in OpenSSL 0.9.2b.
first appeared in OpenSSL 0.9.4.
Both functions have been available since
.Ox 2.6 .
.Sh CAVEATS
The API contract of
.Fn OBJ_txt2obj
when called with a
.Fa no_name
argument of 0 and of
.Fn OBJ_dup
is scary in so far as the caller cannot find out from the returned
object whether it is owned by the library or whether ownership was
transferred to the caller.
Consequently, it is best practice to assume that ownership of the object
may have been transferred and call
.Xr ASN1_OBJECT_free 3
on the returned object when the caller no longer needs it.
In case the library retained ownership of the returned object,
.Xr ASN1_OBJECT_free 3
has no effect and is harmless.
.Pp
Objects returned from
.Fn OBJ_txt2obj
with a
.Fa no_name
argument of 1 always require
.Xr ASN1_OBJECT_free 3
to prevent memory leaks.
.Pp
Objects returned from
.Fn OBJ_nid2obj
never require
.Xr ASN1_OBJECT_free 3 ,
but calling it anyway has no effect and is harmless.
.Sh BUGS
Usually, an object is expected to contain an NID other than
.Dv NID_undef
if and only if it is a table object.
However, this is not an invariant guaranteed by the API.
In particular,
.Xr ASN1_OBJECT_create 3
allows the creation of non-table objects containing bogus NIDs.
.Fn OBJ_obj2nid
returns such bogus NIDs even though
.Fn OBJ_nid2obj
cannot use them for retrieval.
On top of that, the global table contains one built-in object with an NID of
.Dv NID_undef .
.Pp
.Fn OBJ_obj2txt
is awkward and messy to use: it doesn't follow the convention of other
OpenSSL functions where the buffer can be set to

View File

@ -1,4 +1,4 @@
/* $OpenBSD: obj_dat.c,v 1.60 2023/08/17 09:28:43 tb Exp $ */
/* $OpenBSD: obj_dat.c,v 1.61 2023/09/05 14:59:00 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -208,15 +208,6 @@ added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb)
}
static IMPLEMENT_LHASH_COMP_FN(added_obj, ADDED_OBJ)
static int
init_added(void)
{
if (added != NULL)
return (1);
added = lh_ADDED_OBJ_new();
return (added != NULL);
}
static void
cleanup1_doall(ADDED_OBJ *a)
{
@ -289,13 +280,16 @@ LCRYPTO_ALIAS(OBJ_new_nid);
int
OBJ_add_object(const ASN1_OBJECT *obj)
{
ASN1_OBJECT *o;
ASN1_OBJECT *o = NULL;
ADDED_OBJ *ao[4] = {NULL, NULL, NULL, NULL}, *aop;
int i;
if (added == NULL)
if (!init_added())
return (0);
added = lh_ADDED_OBJ_new();
if (added == NULL)
goto err;
if (obj == NULL || obj->nid == NID_undef)
goto err;
if ((o = OBJ_dup(obj)) == NULL)
goto err;
if (!(ao[ADDED_NID] = malloc(sizeof(ADDED_OBJ))))

View File

@ -1,4 +1,4 @@
/* $OpenBSD: pfctl_radix.c,v 1.37 2020/01/15 22:31:51 kn Exp $ */
/* $OpenBSD: pfctl_radix.c,v 1.38 2023/09/05 15:37:07 robert Exp $ */
/*
* Copyright (c) 2002 Cedric Berger
@ -53,7 +53,7 @@
extern int dev;
static int pfr_next_token(char buf[], FILE *);
static int pfr_next_token(char buf[BUF_SIZE], FILE *);
int

View File

@ -1,4 +1,4 @@
/* $OpenBSD: frontend.c,v 1.78 2023/04/30 23:46:52 jsg Exp $ */
/* $OpenBSD: frontend.c,v 1.79 2023/09/05 15:44:39 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,
pq->region);
NULL, 0, pq->region);
if (rcode != LDNS_RCODE_NOERROR) {
error_answer(pq, rcode);
goto send_answer;
@ -927,7 +927,7 @@ synthesize_dns64_answer(struct pending_query *pq)
rinfo->qdcount, rinfo->ttl, rinfo->prefetch_ttl,
rinfo->serve_expired_ttl, rinfo->an_numrrsets,
rinfo->ns_numrrsets, rinfo->ar_numrrsets, rinfo->rrset_count,
rinfo->security);
rinfo->security, rinfo->reason_bogus);
if (!synth_rinfo)
goto srvfail;
@ -1059,7 +1059,7 @@ resend_dns64_query(struct pending_query *opq)
}
rcode = parse_edns_from_query_pkt(pq->qbuf, &pq->edns, NULL, NULL,
pq->region);
NULL, 0, pq->region);
if (rcode != LDNS_RCODE_NOERROR) {
error_answer(pq, rcode);
goto send_answer;

View File

@ -368,6 +368,9 @@
/* Define if we have LibreSSL */
#define HAVE_LIBRESSL 1
/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
/* #undef HAVE_LINUX_NET_TSTAMP_H */
/* Define to 1 if you have the `localtime_r' function. */
#define HAVE_LOCALTIME_R 1
@ -773,7 +776,7 @@
#define PACKAGE_NAME "unbound"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "unbound 1.17.0"
#define PACKAGE_STRING "unbound 1.18.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "unbound"
@ -782,7 +785,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.17.0"
#define PACKAGE_VERSION "1.18.0"
/* default pidfile location */
#define PIDFILE ""
@ -805,7 +808,7 @@
#define ROOT_CERT_FILE "/var/unbound/etc/icannbundle.pem"
/* version number for resource files */
#define RSRC_PACKAGE_VERSION 1,17,0,0
#define RSRC_PACKAGE_VERSION 1,18,0,0
/* Directory to chdir to */
#define RUN_DIR "/var/unbound/etc"

View File

@ -64,8 +64,12 @@ enum acl_access {
acl_allow,
/** allow full access for all queries, recursion and cache snooping */
acl_allow_snoop,
/** allow full access for recursion queries and set RD flag regardless of request */
acl_allow_setrd
/** allow full access for recursion queries and set RD flag regardless
* of request */
acl_allow_setrd,
/** allow full access for recursion (+RD) queries if valid cookie
* present or stateful transport */
acl_allow_cookie
};
/**

View File

@ -126,4 +126,11 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
*/
void server_stats_insrcode(struct ub_server_stats* stats, struct sldns_buffer* buf);
/**
* Add DNS Cookie stats for this query
* @param stats: the stats
* @param edns: edns record
*/
void server_stats_downstream_cookie(struct ub_server_stats* stats,
struct edns_data* edns);
#endif /* DAEMON_STATS_H */

View File

@ -118,7 +118,7 @@ struct worker {
/** do we need to restart or quit (on signal) */
int need_to_exit;
/** allocation cache for this thread */
struct alloc_cache alloc;
struct alloc_cache *alloc;
/** per thread statistics */
struct ub_server_stats stats;
/** thread scratch regional */
@ -131,6 +131,8 @@ struct worker {
/** dnstap environment, changed for this thread */
struct dt_env dtenv;
#endif
/** reuse existing cache on reload if other conditions allow it. */
int reuse_cache;
};
/**

View File

@ -59,7 +59,7 @@
******************************************************************************/
/**
* This is the default DNS64 prefix that is used whent he dns64 module is listed
* This is the default DNS64 prefix that is used when the dns64 module is listed
* in module-config but when the dns64-prefix variable is not present.
*/
static const char DEFAULT_DNS64_PREFIX[] = "64:ff9b::/96";
@ -841,7 +841,7 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
rep->rrset_count, rep->security);
rep->rrset_count, rep->security, LDNS_EDE_NONE);
if(!cp)
return;

View File

@ -126,13 +126,15 @@ dt_delete(struct dt_env *env);
* @param rsock: local (service) address/port.
* @param cptype: comm_udp or comm_tcp.
* @param qmsg: query message.
* @param tstamp: timestamp or NULL if none provided.
*/
void
dt_msg_send_client_query(struct dt_env *env,
struct sockaddr_storage *qsock,
struct sockaddr_storage *rsock,
enum comm_point_type cptype,
struct sldns_buffer *qmsg);
struct sldns_buffer *qmsg,
struct timeval* tstamp);
/**
* Create and send a new dnstap "Message" event of type CLIENT_RESPONSE.

View File

@ -321,6 +321,45 @@ void delegpt_log(enum verbosity_value v, struct delegpt* dp)
}
}
int
delegpt_addr_on_result_list(struct delegpt* dp, struct delegpt_addr* find)
{
struct delegpt_addr* a = dp->result_list;
while(a) {
if(a == find)
return 1;
a = a->next_result;
}
return 0;
}
void
delegpt_usable_list_remove_addr(struct delegpt* dp, struct delegpt_addr* del)
{
struct delegpt_addr* usa = dp->usable_list, *prev = NULL;
while(usa) {
if(usa == del) {
/* snip off the usable list */
if(prev)
prev->next_usable = usa->next_usable;
else dp->usable_list = usa->next_usable;
return;
}
prev = usa;
usa = usa->next_usable;
}
}
void
delegpt_add_to_result_list(struct delegpt* dp, struct delegpt_addr* a)
{
if(delegpt_addr_on_result_list(dp, a))
return;
delegpt_usable_list_remove_addr(dp, a);
a->next_result = dp->result_list;
dp->result_list = a;
}
void
delegpt_add_unused_targets(struct delegpt* dp)
{

View File

@ -457,4 +457,29 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
/** get memory in use by dp */
size_t delegpt_get_mem(struct delegpt* dp);
/**
* See if the addr is on the result list.
* @param dp: delegation point.
* @param find: the pointer is searched for on the result list.
* @return 1 if found, 0 if not found.
*/
int delegpt_addr_on_result_list(struct delegpt* dp, struct delegpt_addr* find);
/**
* Remove the addr from the usable list.
* @param dp: the delegation point.
* @param del: the addr to remove from the list, the pointer is searched for.
*/
void delegpt_usable_list_remove_addr(struct delegpt* dp,
struct delegpt_addr* del);
/**
* Add the delegpt_addr back to the result list, if it is not already on
* the result list. Also removes it from the usable list.
* @param dp: delegation point.
* @param a: addr to add, nothing happens if it is already on the result list.
* It is removed from the usable list.
*/
void delegpt_add_to_result_list(struct delegpt* dp, struct delegpt_addr* a);
#endif /* ITERATOR_ITER_DELEGPT_H */

View File

@ -284,6 +284,13 @@ response_type_from_server(int rdset,
/* If we've gotten this far, this is NOERROR/NODATA (which could
* be an entirely empty message) */
/* but ignore entirely empty messages, noerror/nodata has a soa
* negative ttl value in the authority section, this makes it try
* again at another authority. And turns it from a 5 second empty
* message into a 5 second servfail response. */
if(msg->rep->an_numrrsets == 0 && msg->rep->ns_numrrsets == 0 &&
msg->rep->ar_numrrsets == 0)
return RESPONSE_TYPE_THROWAWAY;
/* check if recursive answer; saying it has empty cache */
if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset)
return RESPONSE_TYPE_REC_LAME;

View File

@ -346,6 +346,26 @@ soa_in_auth(struct msg_parse* msg)
return 0;
}
/** Check if type is allowed in the authority section */
static int
type_allowed_in_authority_section(uint16_t tp)
{
if(tp == LDNS_RR_TYPE_SOA || tp == LDNS_RR_TYPE_NS ||
tp == LDNS_RR_TYPE_DS || tp == LDNS_RR_TYPE_NSEC ||
tp == LDNS_RR_TYPE_NSEC3)
return 1;
return 0;
}
/** Check if type is allowed in the additional section */
static int
type_allowed_in_additional_section(uint16_t tp)
{
if(tp == LDNS_RR_TYPE_A || tp == LDNS_RR_TYPE_AAAA)
return 1;
return 0;
}
/**
* This routine normalizes a response. This includes removing "irrelevant"
* records from the answer and additional sections and (re)synthesizing
@ -355,11 +375,13 @@ soa_in_auth(struct msg_parse* msg)
* @param msg: msg to normalize.
* @param qinfo: original query.
* @param region: where to allocate synthesized CNAMEs.
* @param env: module env with config options.
* @return 0 on error.
*/
static int
scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, struct regional* region)
struct query_info* qinfo, struct regional* region,
struct module_env* env)
{
uint8_t* sname = qinfo->qname;
size_t snamelen = qinfo->qname_len;
@ -511,6 +533,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
/* Mark additional names from AUTHORITY */
while(rrset && rrset->section == LDNS_SECTION_AUTHORITY) {
/* protect internals of recursor by making sure to del these */
if(rrset->type==LDNS_RR_TYPE_DNAME ||
rrset->type==LDNS_RR_TYPE_CNAME ||
rrset->type==LDNS_RR_TYPE_A ||
@ -519,6 +542,13 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
/* Allowed list of types in the authority section */
if(env->cfg->harden_unknown_additional &&
!type_allowed_in_authority_section(rrset->type)) {
remove_rrset("normalize: removing irrelevant "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
/* only one NS set allowed in authority section */
if(rrset->type==LDNS_RR_TYPE_NS) {
/* NS set must be pertinent to the query */
@ -576,7 +606,6 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
* found in ANSWER and AUTHORITY. */
/* These records have not been marked OK previously */
while(rrset && rrset->section == LDNS_SECTION_ADDITIONAL) {
/* FIXME: what about other types? */
if(rrset->type==LDNS_RR_TYPE_A ||
rrset->type==LDNS_RR_TYPE_AAAA)
{
@ -589,6 +618,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
continue;
}
}
/* protect internals of recursor by making sure to del these */
if(rrset->type==LDNS_RR_TYPE_DNAME ||
rrset->type==LDNS_RR_TYPE_CNAME ||
rrset->type==LDNS_RR_TYPE_NS) {
@ -596,6 +626,13 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
/* Allowed list of types in the additional section */
if(env->cfg->harden_unknown_additional &&
!type_allowed_in_additional_section(rrset->type)) {
remove_rrset("normalize: removing irrelevant "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
prev = rrset;
rrset = rrset->rrset_all_next;
}
@ -846,7 +883,7 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
}
/* normalize the response, this cleans up the additional. */
if(!scrub_normalize(pkt, msg, qinfo, region))
if(!scrub_normalize(pkt, msg, qinfo, region, env))
return 0;
/* delete all out-of-zone information */
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie))

View File

@ -71,6 +71,11 @@
/** time when nameserver glue is said to be 'recent' */
#define SUSPICION_RECENT_EXPIRY 86400
/** if NAT64 is enabled and no NAT64 prefix is configured, first fall back to
* DNS64 prefix. If that is not configured, fall back to this default value.
*/
static const char DEFAULT_NAT64_PREFIX[] = "64:ff9b::/96";
/** fillup fetch policy array */
static void
fetch_fill(struct iter_env* ie, const char* str)
@ -142,6 +147,7 @@ caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg)
int
iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
{
const char *nat64_prefix;
int i;
/* target fetch policy */
if(!read_fetch_policy(iter_env, cfg->target_fetch_policy))
@ -172,9 +178,35 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
}
}
nat64_prefix = cfg->nat64_prefix;
if(!nat64_prefix)
nat64_prefix = cfg->dns64_prefix;
if(!nat64_prefix)
nat64_prefix = DEFAULT_NAT64_PREFIX;
if(!netblockstrtoaddr(nat64_prefix, 0, &iter_env->nat64_prefix_addr,
&iter_env->nat64_prefix_addrlen,
&iter_env->nat64_prefix_net)) {
log_err("cannot parse nat64-prefix netblock: %s", nat64_prefix);
return 0;
}
if(!addr_is_ip6(&iter_env->nat64_prefix_addr,
iter_env->nat64_prefix_addrlen)) {
log_err("nat64-prefix is not IPv6: %s", cfg->nat64_prefix);
return 0;
}
if(!prefixnet_is_nat64(iter_env->nat64_prefix_net)) {
log_err("nat64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
nat64_prefix);
return 0;
}
iter_env->supports_ipv6 = cfg->do_ip6;
iter_env->supports_ipv4 = cfg->do_ip4;
iter_env->use_nat64 = cfg->do_nat64;
iter_env->outbound_msg_retry = cfg->outbound_msg_retry;
iter_env->max_sent_count = cfg->max_sent_count;
iter_env->max_query_restarts = cfg->max_query_restarts;
return 1;
}
@ -238,7 +270,8 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) {
return -1; /* there is no ip6 available */
}
if(!iter_env->supports_ipv4 && !addr_is_ip6(&a->addr, a->addrlen)) {
if(!iter_env->supports_ipv4 && !iter_env->use_nat64 &&
!addr_is_ip6(&a->addr, a->addrlen)) {
return -1; /* there is no ip4 available */
}
/* check lameness - need zone , class info */
@ -745,10 +778,15 @@ iter_mark_pside_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
int
iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp, int supports_ipv4, int supports_ipv6)
struct delegpt* dp, int supports_ipv4, int supports_ipv6,
int use_nat64)
{
struct delegpt_ns* ns;
struct delegpt_addr* a;
if(supports_ipv6 && use_nat64)
supports_ipv4 = 1;
/* check:
* o RD qflag is on.
* o no addresses are provided.
@ -1308,8 +1346,7 @@ void iter_dec_attempts(struct delegpt* dp, int d, int outbound_msg_retry)
for(a=dp->target_list; a; a = a->next_target) {
if(a->attempts >= outbound_msg_retry) {
/* add back to result list */
a->next_result = dp->result_list;
dp->result_list = a;
delegpt_add_to_result_list(dp, a);
}
if(a->attempts > d)
a->attempts -= d;

View File

@ -189,10 +189,13 @@ void iter_mark_pside_cycle_targets(struct module_qstate* qstate,
* if not, then the IPv4 addresses are useless.
* @param supports_ipv6: if we support ipv6 for lookups to the target.
* if not, then the IPv6 addresses are useless.
* @param use_nat64: if we support NAT64 for lookups to the target.
* if yes, IPv4 addresses are useful even if we don't support IPv4.
* @return true if dp is useless.
*/
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp, int supports_ipv4, int supports_ipv6);
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp, int supports_ipv4, int supports_ipv6,
int use_nat64);
/**
* See if qname has DNSSEC needs. This is true if there is a trust anchor above

View File

@ -255,7 +255,7 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
log_err("out of memory adding missing");
}
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) &&
(dpns->got6 == 2 || !ie->supports_ipv6)) {
dpns->resolved = 1; /* mark as failed */
target_count_increase_nx(super_iq, 1);
@ -302,81 +302,65 @@ error_response(struct module_qstate* qstate, int id, int rcode)
static int
error_response_cache(struct module_qstate* qstate, int id, int rcode)
{
if(!qstate->no_cache_store) {
/* store in cache */
struct reply_info err;
if(qstate->prefetch_leeway > NORR_TTL) {
verbose(VERB_ALGO, "error response for prefetch in cache");
/* attempt to adjust the cache entry prefetch */
if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo,
NORR_TTL, qstate->query_flags))
return error_response(qstate, id, rcode);
/* if that fails (not in cache), fall through to store err */
}
if(qstate->env->cfg->serve_expired) {
/* if serving expired contents, and such content is
* already available, don't overwrite this servfail */
struct msgreply_entry* msg;
if((msg=msg_cache_lookup(qstate->env,
qstate->qinfo.qname, qstate->qinfo.qname_len,
qstate->qinfo.qtype, qstate->qinfo.qclass,
qstate->query_flags, 0,
qstate->env->cfg->serve_expired_ttl_reset))
!= NULL) {
if(qstate->env->cfg->serve_expired_ttl_reset) {
struct reply_info* rep =
(struct reply_info*)msg->entry.data;
if(rep && *qstate->env->now +
qstate->env->cfg->serve_expired_ttl >
rep->serve_expired_ttl) {
rep->serve_expired_ttl =
*qstate->env->now +
qstate->env->cfg->serve_expired_ttl;
}
}
lock_rw_unlock(&msg->entry.lock);
return error_response(qstate, id, rcode);
}
/* serving expired contents, but nothing is cached
* at all, so the servfail cache entry is useful
* (stops waste of time on this servfail NORR_TTL) */
} else {
/* don't overwrite existing (non-expired) data in
* cache with a servfail */
struct msgreply_entry* msg;
if((msg=msg_cache_lookup(qstate->env,
qstate->qinfo.qname, qstate->qinfo.qname_len,
qstate->qinfo.qtype, qstate->qinfo.qclass,
qstate->query_flags, *qstate->env->now, 0))
!= NULL) {
struct reply_info* rep = (struct reply_info*)
msg->entry.data;
if(FLAGS_GET_RCODE(rep->flags) ==
LDNS_RCODE_NOERROR ||
FLAGS_GET_RCODE(rep->flags) ==
LDNS_RCODE_NXDOMAIN) {
/* we have a good entry,
* don't overwrite */
lock_rw_unlock(&msg->entry.lock);
return error_response(qstate, id, rcode);
}
lock_rw_unlock(&msg->entry.lock);
}
}
memset(&err, 0, sizeof(err));
err.flags = (uint16_t)(BIT_QR | BIT_RA);
FLAGS_SET_RCODE(err.flags, rcode);
err.qdcount = 1;
err.ttl = NORR_TTL;
err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl);
err.serve_expired_ttl = NORR_TTL;
/* do not waste time trying to validate this servfail */
err.security = sec_status_indeterminate;
verbose(VERB_ALGO, "store error response in message cache");
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
qstate->query_flags, qstate->qstarttime);
struct reply_info err;
struct msgreply_entry* msg;
if(qstate->no_cache_store) {
return error_response(qstate, id, rcode);
}
if(qstate->prefetch_leeway > NORR_TTL) {
verbose(VERB_ALGO, "error response for prefetch in cache");
/* attempt to adjust the cache entry prefetch */
if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo,
NORR_TTL, qstate->query_flags))
return error_response(qstate, id, rcode);
/* if that fails (not in cache), fall through to store err */
}
if((msg=msg_cache_lookup(qstate->env,
qstate->qinfo.qname, qstate->qinfo.qname_len,
qstate->qinfo.qtype, qstate->qinfo.qclass,
qstate->query_flags, 0,
qstate->env->cfg->serve_expired_ttl_reset)) != NULL) {
struct reply_info* rep = (struct reply_info*)msg->entry.data;
if(qstate->env->cfg->serve_expired &&
qstate->env->cfg->serve_expired_ttl_reset && rep &&
*qstate->env->now + qstate->env->cfg->serve_expired_ttl
> rep->serve_expired_ttl) {
verbose(VERB_ALGO, "reset serve-expired-ttl for "
"response in cache");
rep->serve_expired_ttl = *qstate->env->now +
qstate->env->cfg->serve_expired_ttl;
}
if(rep && (FLAGS_GET_RCODE(rep->flags) ==
LDNS_RCODE_NOERROR ||
FLAGS_GET_RCODE(rep->flags) ==
LDNS_RCODE_NXDOMAIN ||
FLAGS_GET_RCODE(rep->flags) ==
LDNS_RCODE_YXDOMAIN) &&
(qstate->env->cfg->serve_expired ||
*qstate->env->now <= rep->ttl)) {
/* we have a good entry, don't overwrite */
lock_rw_unlock(&msg->entry.lock);
return error_response(qstate, id, rcode);
}
lock_rw_unlock(&msg->entry.lock);
/* nothing interesting is cached (already error response or
* expired good record when we don't serve expired), so this
* servfail cache entry is useful (stops waste of time on this
* servfail NORR_TTL) */
}
/* store in cache */
memset(&err, 0, sizeof(err));
err.flags = (uint16_t)(BIT_QR | BIT_RA);
FLAGS_SET_RCODE(err.flags, rcode);
err.qdcount = 1;
err.ttl = NORR_TTL;
err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl);
err.serve_expired_ttl = NORR_TTL;
/* do not waste time trying to validate this servfail */
err.security = sec_status_indeterminate;
verbose(VERB_ALGO, "store error response in message cache");
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
qstate->query_flags, qstate->qstarttime);
return error_response(qstate, id, rcode);
}
@ -590,6 +574,54 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
return 1;
}
/** fill fail address for later recovery */
static void
fill_fail_addr(struct iter_qstate* iq, struct sockaddr_storage* addr,
socklen_t addrlen)
{
if(addrlen == 0) {
iq->fail_addr_type = 0;
return;
}
if(((struct sockaddr_in*)addr)->sin_family == AF_INET) {
iq->fail_addr_type = 4;
memcpy(&iq->fail_addr.in,
&((struct sockaddr_in*)addr)->sin_addr,
sizeof(iq->fail_addr.in));
}
#ifdef AF_INET6
else if(((struct sockaddr_in*)addr)->sin_family == AF_INET6) {
iq->fail_addr_type = 6;
memcpy(&iq->fail_addr.in6,
&((struct sockaddr_in6*)addr)->sin6_addr,
sizeof(iq->fail_addr.in6));
}
#endif
else {
iq->fail_addr_type = 0;
}
}
/** print fail addr to string */
static void
print_fail_addr(struct iter_qstate* iq, char* buf, size_t len)
{
if(iq->fail_addr_type == 4) {
if(inet_ntop(AF_INET, &iq->fail_addr.in, buf,
(socklen_t)len) == 0)
(void)strlcpy(buf, "(inet_ntop error)", len);
}
#ifdef AF_INET6
else if(iq->fail_addr_type == 6) {
if(inet_ntop(AF_INET6, &iq->fail_addr.in6, buf,
(socklen_t)len) == 0)
(void)strlcpy(buf, "(inet_ntop error)", len);
}
#endif
else
(void)strlcpy(buf, "", len);
}
/** add response specific error information for log servfail */
static void
errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq)
@ -597,16 +629,14 @@ errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq)
if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
return;
if((qstate->reply && qstate->reply->remote_addrlen != 0) ||
(iq->fail_reply && iq->fail_reply->remote_addrlen != 0)) {
(iq->fail_addr_type != 0)) {
char from[256], frm[512];
if(qstate->reply && qstate->reply->remote_addrlen != 0)
addr_to_str(&qstate->reply->remote_addr,
qstate->reply->remote_addrlen, from,
sizeof(from));
else
addr_to_str(&iq->fail_reply->remote_addr,
iq->fail_reply->remote_addrlen, from,
sizeof(from));
print_fail_addr(iq, from, sizeof(from));
snprintf(frm, sizeof(frm), "from %s", from);
errinf(qstate, frm);
}
@ -1137,7 +1167,7 @@ generate_a_aaaa_check(struct module_qstate* qstate, struct iter_qstate* iq,
* Generate a NS check request to obtain authoritative information
* on an NS rrset.
*
* @param qstate: the qtstate that triggered the need to prime.
* @param qstate: the qstate that triggered the need to prime.
* @param iq: iterator query state.
* @param id: module id.
*/
@ -1314,7 +1344,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
/* We enforce a maximum number of query restarts. This is primarily a
* cheap way to prevent CNAME loops. */
if(iq->query_restart_count > MAX_RESTART_COUNT) {
if(iq->query_restart_count > ie->max_query_restarts) {
verbose(VERB_QUERY, "request has exceeded the maximum number"
" of query restarts with %d", iq->query_restart_count);
errinf(qstate, "request has exceeded the maximum number "
@ -1451,6 +1481,19 @@ 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((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
* entry, it starts query loops. Stop that loop by
* disallowing the query. The RD=0 was previously used
* to check the cache with allow_snoop. For stubs,
* the iterator pass would have primed the stub and
* then cached information can be used for further
* queries. */
verbose(VERB_ALGO, "cannot forward RD=0 query, to stop query loops");
errinf(qstate, "cannot forward RD=0 query");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
iq->refetch_glue = 0;
iq->minimisation_state = DONOT_MINIMISE_STATE;
/* the request has been forwarded.
@ -1560,18 +1603,19 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
/* see if this dp not useless.
* It is useless if:
* o all NS items are required glue.
* o all NS items are required glue.
* or the query is for NS item that is required glue.
* o no addresses are provided.
* o RD qflag is on.
* Instead, go up one level, and try to get even further
* If the root was useless, use safety belt information.
* If the root was useless, use safety belt information.
* Only check cache returns, because replies for servers
* could be useless but lead to loops (bumping into the
* same server reply) if useless-checked.
*/
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp, ie->supports_ipv4, ie->supports_ipv6)) {
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp, ie->supports_ipv4, ie->supports_ipv6,
ie->use_nat64)) {
struct delegpt* retdp = NULL;
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
if(retdp) {
@ -1932,7 +1976,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
break;
}
/* Send the A request. */
if(ie->supports_ipv4 &&
if((ie->supports_ipv4 || ie->use_nat64) &&
((ns->lame && !ns->done_pside4) ||
(!ns->lame && !ns->got4))) {
if(!generate_target_query(qstate, iq, id,
@ -2085,14 +2129,14 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
/* if this nameserver is at a delegation point, but that
* delegation point is a stub and we cannot go higher, skip*/
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
(ie->supports_ipv4 && !ns->done_pside4)) &&
((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) &&
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
iq->qchase.qclass, NULL)) {
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
"because it is also a stub/forward,",
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
if(ie->supports_ipv6) ns->done_pside6 = 1;
if(ie->supports_ipv4) ns->done_pside4 = 1;
if(ie->supports_ipv4 || ie->use_nat64) ns->done_pside4 = 1;
continue;
}
/* query for parent-side A and AAAA for nameservers */
@ -2117,7 +2161,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
return 0;
}
}
if(ie->supports_ipv4 && !ns->done_pside4) {
if((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4) {
/* Send the A request. */
if(!generate_parentside_target_query(qstate, iq, id,
ns->name, ns->namelen,
@ -2259,6 +2303,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
int tf_policy;
struct delegpt_addr* target;
struct outbound_entry* outq;
struct sockaddr_storage real_addr;
socklen_t real_addrlen;
int auth_fallback = 0;
uint8_t* qout_orig = NULL;
size_t qout_orig_len = 0;
@ -2276,14 +2322,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->num_current_queries, iq->sent_count);
/* Make sure that we haven't run away */
/* FIXME: is this check even necessary? */
if(iq->referral_count > MAX_REFERRAL_COUNT) {
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);
}
if(iq->sent_count > MAX_SENT_COUNT) {
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");
@ -2385,7 +2430,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(!ie->supports_ipv6)
delegpt_no_ipv6(iq->dp);
if(!ie->supports_ipv4)
if(!ie->supports_ipv4 && !ie->use_nat64)
delegpt_no_ipv4(iq->dp);
delegpt_log(VERB_ALGO, iq->dp);
@ -2630,7 +2675,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
* the original query is one that matched too, so we have
* caps_server+1 number of matching queries now */
if(iq->caps_server+1 >= naddr*3 ||
iq->caps_server*2+2 >= MAX_SENT_COUNT) {
iq->caps_server*2+2 >= (size_t)ie->max_sent_count) {
/* *2 on sentcount check because ipv6 may fail */
/* we're done, process the response */
verbose(VERB_ALGO, "0x20 fallback had %d responses "
@ -2806,12 +2851,24 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
/* We have a valid target. */
if(verbosity >= VERB_QUERY) {
log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out);
log_name_addr(VERB_QUERY, "sending to target:", iq->dp->name,
log_name_addr(VERB_QUERY, "sending to target:", iq->dp->name,
&target->addr, target->addrlen);
verbose(VERB_ALGO, "dnssec status: %s%s",
iq->dnssec_expected?"expected": "not expected",
iq->dnssec_lame_query?" but lame_query anyway": "");
}
real_addr = target->addr;
real_addrlen = target->addrlen;
if(ie->use_nat64 && target->addr.ss_family == AF_INET) {
addr_to_nat64(&target->addr, &ie->nat64_prefix_addr,
ie->nat64_prefix_addrlen, ie->nat64_prefix_net,
&real_addr, &real_addrlen);
log_name_addr(VERB_QUERY, "applied NAT64:",
iq->dp->name, &real_addr, real_addrlen);
}
fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query));
outq = (*qstate->env->send_query)(&iq->qinfo_out,
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
@ -2822,7 +2879,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
!qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env,
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
ie, iq), sq_check_ratelimit, &target->addr, target->addrlen,
ie, iq), sq_check_ratelimit, &real_addr, real_addrlen,
iq->dp->name, iq->dp->namelen,
(iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream),
(iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
@ -2839,7 +2896,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
log_addr(VERB_QUERY, "error sending query to auth server",
&target->addr, target->addrlen);
&real_addr, real_addrlen);
if(qstate->env->cfg->qname_minimisation)
iq->minimisation_state = SKIP_MINIMISE_STATE;
return next_state(iq, QUERYTARGETS_STATE);
@ -2883,7 +2940,7 @@ static int
processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
struct iter_env* ie, int id)
{
int dnsseclame = 0;
int dnsseclame = 0, origtypecname = 0;
enum response_type type;
iq->num_current_queries--;
@ -2966,6 +3023,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* YXDOMAIN is a permanent error, no need to retry */
type = RESPONSE_TYPE_ANSWER;
}
if(type == RESPONSE_TYPE_CNAME)
origtypecname = 1;
if(type == RESPONSE_TYPE_CNAME && iq->response->rep->an_numrrsets >= 1
&& ntohs(iq->response->rep->rrsets[0]->rk.type) == LDNS_RR_TYPE_DNAME) {
uint8_t* sname = NULL;
@ -3051,11 +3110,14 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iq->minimisation_state = DONOT_MINIMISE_STATE;
}
if(FLAGS_GET_RCODE(iq->response->rep->flags) ==
LDNS_RCODE_NXDOMAIN) {
LDNS_RCODE_NXDOMAIN && !origtypecname) {
/* Stop resolving when NXDOMAIN is DNSSEC
* signed. Based on assumption that nameservers
* serving signed zones do not return NXDOMAIN
* for empty-non-terminals. */
/* If this response is actually a CNAME type,
* the nxdomain rcode may not be for the qname,
* and so it is not the final response. */
if(iq->dnssec_expected)
return final_state(iq);
/* Make subrequest to validate intermediate
@ -3183,7 +3245,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
iq->response = NULL;
iq->fail_reply = NULL;
iq->fail_addr_type = 0;
verbose(VERB_ALGO, "cleared outbound list for next round");
return next_state(iq, QUERYTARGETS_STATE);
} else if(type == RESPONSE_TYPE_CNAME) {
@ -3565,7 +3627,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
} else {
verbose(VERB_ALGO, "iterator TargetResponse failed");
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) &&
(dpns->got6 == 2 || !ie->supports_ipv6)) {
dpns->resolved = 1; /* fail the target */
/* do not count cached answers */
@ -3810,6 +3872,9 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
/* make sure QR flag is on */
iq->response->rep->flags |= BIT_QR;
/* explicitly set the EDE string to NULL */
iq->response->rep->reason_bogus_str = NULL;
/* we have finished processing this query */
qstate->ext_state[id] = module_finished;
@ -3988,7 +4053,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
}
/* parse message */
iq->fail_reply = qstate->reply;
fill_fail_addr(iq, &qstate->reply->remote_addr,
qstate->reply->remote_addrlen);
prs = (struct msg_parse*)regional_alloc(qstate->env->scratch,
sizeof(struct msg_parse));
if(!prs) {

View File

@ -63,12 +63,8 @@ struct rbtree_type;
/** max number of nxdomains allowed for target lookups for a query and
* its subqueries when fallback has kicked in */
#define MAX_TARGET_NX_FALLBACK (MAX_TARGET_NX*2)
/** max number of query restarts. Determines max number of CNAME chain. */
#define MAX_RESTART_COUNT 11
/** max number of referrals. Makes sure resolver does not run away */
#define MAX_REFERRAL_COUNT 130
/** max number of queries-sent-out. Make sure large NS set does not loop */
#define MAX_SENT_COUNT 32
/** max number of queries for which to perform dnsseclameness detection,
* (rrsigs missing detection) after that, just pick up that response */
#define DNSSEC_LAME_DETECT_COUNT 4
@ -107,7 +103,7 @@ extern int BLACKLIST_PENALTY;
#define RTT_BAND 400
/**
* Global state for the iterator.
* Global state for the iterator.
*/
struct iter_env {
/** A flag to indicate whether or not we have an IPv6 route */
@ -116,6 +112,18 @@ struct iter_env {
/** A flag to indicate whether or not we have an IPv4 route */
int supports_ipv4;
/** A flag to locally apply NAT64 to make IPv4 addrs into IPv6 */
int use_nat64;
/** NAT64 prefix address, cf. dns64_env->prefix_addr */
struct sockaddr_storage nat64_prefix_addr;
/** sizeof(sockaddr_in6) */
socklen_t nat64_prefix_addrlen;
/** CIDR mask length of NAT64 prefix */
int nat64_prefix_net;
/** A set of inetaddrs that should never be queried. */
struct iter_donotq* donotq;
@ -145,6 +153,12 @@ struct iter_env {
/** number of retries on outgoing queries */
int outbound_msg_retry;
/** number of queries_sent */
int max_sent_count;
/** max number of query restarts to limit length of CNAME chain */
int max_query_restarts;
};
/**
@ -437,7 +451,14 @@ struct iter_qstate {
/** true if there have been parse failures of reply packets */
int parse_failures;
/** a failure printout address for last received answer */
struct comm_reply* fail_reply;
union {
struct in_addr in;
#ifdef AF_INET6
struct in6_addr in6;
#endif
} fail_addr;
/** which fail_addr, 0 is nothing, 4 or 6 */
int fail_addr_type;
};
/**

View File

@ -70,6 +70,7 @@ context_finalize(struct ub_ctx* ctx)
} else {
log_init(cfg->logfile, cfg->use_syslog, NULL);
}
ctx->pipe_pid = getpid();
cfg_apply_local_port_policy(cfg, 65536);
config_apply(cfg);
if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))

View File

@ -89,6 +89,12 @@ struct ub_ctx {
pid_t bg_pid;
/** tid of bg worker thread */
ub_thread_type bg_tid;
/** pid when pipes are created. This was the process when the
* setup was called. Helps with clean up, so we can tell after a fork
* which side of the fork the delete is on. */
pid_t pipe_pid;
/** when threaded, the worker that exists in the created thread. */
struct libworker* thread_worker;
/** do threading (instead of forking) for async resolution */
int dothread;

View File

@ -305,11 +305,31 @@ ub_ctx_delete(struct ub_ctx* ctx)
int do_stop = 1;
if(!ctx) return;
/* if the delete is called but it has forked, and before the fork
* the context was finalized, then the bg worker is not stopped
* from here. There is one worker, but two contexts that refer to
* it and only one should clean up, the one with getpid == pipe_pid.*/
if(ctx->created_bg && ctx->pipe_pid != getpid()) {
do_stop = 0;
#ifndef USE_WINSOCK
/* Stop events from getting deregistered, if the backend is
* epoll, the epoll fd is the same as the other process.
* That process should deregister them. */
if(ctx->qq_pipe->listen_com)
ctx->qq_pipe->listen_com->event_added = 0;
if(ctx->qq_pipe->res_com)
ctx->qq_pipe->res_com->event_added = 0;
if(ctx->rr_pipe->listen_com)
ctx->rr_pipe->listen_com->event_added = 0;
if(ctx->rr_pipe->res_com)
ctx->rr_pipe->res_com->event_added = 0;
#endif
}
/* see if bg thread is created and if threads have been killed */
/* no locks, because those may be held by terminated threads */
/* for processes the read pipe is closed and we see that on read */
#ifdef HAVE_PTHREAD
if(ctx->created_bg && ctx->dothread) {
if(ctx->created_bg && ctx->dothread && do_stop) {
if(pthread_kill(ctx->bg_tid, 0) == ESRCH) {
/* thread has been killed */
do_stop = 0;
@ -318,6 +338,23 @@ ub_ctx_delete(struct ub_ctx* ctx)
#endif /* HAVE_PTHREAD */
if(do_stop)
ub_stop_bg(ctx);
if(ctx->created_bg && ctx->pipe_pid != getpid() && ctx->thread_worker) {
/* This delete is happening from a different process. Delete
* the thread worker from this process memory space. The
* thread is not there to do so, so it is freed here. */
struct ub_event_base* evbase = comm_base_internal(
ctx->thread_worker->base);
libworker_delete_event(ctx->thread_worker);
ctx->thread_worker = NULL;
#ifdef USE_MINI_EVENT
ub_event_base_free(evbase);
#else
/* cannot event_base_free, because the epoll_fd cleanup
* in libevent could stop the original event_base in the
* other process from working. */
free(evbase);
#endif
}
libworker_delete_event(ctx->event_worker);
modstack_desetup(&ctx->mods, ctx->env);

View File

@ -168,14 +168,12 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
hints_delete(w->env->hints);
w->env->hints = NULL;
}
if(cfg->ssl_upstream || (cfg->tls_cert_bundle && cfg->tls_cert_bundle[0]) || cfg->tls_win_cert) {
w->sslctx = connect_sslctx_create(NULL, NULL,
cfg->tls_cert_bundle, cfg->tls_win_cert);
if(!w->sslctx) {
/* to make the setup fail after unlock */
hints_delete(w->env->hints);
w->env->hints = NULL;
}
w->sslctx = connect_sslctx_create(NULL, NULL,
cfg->tls_cert_bundle, cfg->tls_win_cert);
if(!w->sslctx) {
/* to make the setup fail after unlock */
hints_delete(w->env->hints);
w->env->hints = NULL;
}
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
@ -395,6 +393,7 @@ int libworker_bg(struct ub_ctx* ctx)
w = libworker_setup(ctx, 1, NULL);
if(!w) return UB_NOMEM;
w->is_bg_thread = 1;
ctx->thread_worker = w;
#ifdef ENABLE_LOCK_CHECKS
w->thread_num = 1; /* for nicer DEBUG checklocks */
#endif
@ -604,6 +603,8 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
edns->opt_list_out = NULL;
edns->opt_list_inplace_cb_out = NULL;
edns->padding_block_size = 0;
edns->cookie_present = 0;
edns->cookie_valid = 0;
if(sldns_buffer_capacity(w->back->udp_buff) < 65535)
edns->udp_size = (uint16_t)sldns_buffer_capacity(
w->back->udp_buff);

View File

@ -52,8 +52,8 @@
* unbound was compiled with, otherwise it wouldn't work, the event and
* event_base structures would be different.
*/
#ifndef _UB_UNBOUND_EVENT_H
#define _UB_UNBOUND_EVENT_H
#ifndef UB_UNBOUND_EVENT_H
#define UB_UNBOUND_EVENT_H
#ifdef __cplusplus
extern "C" {
@ -230,7 +230,7 @@ int ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base);
* @param callback: this is called on completion of the resolution.
* It is called as:
* void callback(void* mydata, int rcode, void* packet, int packet_len,
* int sec, char* why_bogus)
* int sec, char* why_bogus, int was_ratelimited)
* with mydata: the same as passed here, you may pass NULL,
* with rcode: 0 on no error, nonzero for mostly SERVFAIL situations,
* this is a DNS rcode.
@ -241,6 +241,7 @@ int ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base);
* with packet_len: length in bytes of the packet buffer.
* with sec: 0 if insecure, 1 if bogus, 2 if DNSSEC secure.
* with why_bogus: text string explaining why it is bogus (or NULL).
* with was_ratelimited: if the query was ratelimited.
* These point to buffers inside unbound; do not deallocate the packet or
* error string.
*
@ -261,4 +262,4 @@ int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
}
#endif
#endif /* _UB_UNBOUND_H */
#endif /* UB_UNBOUND_EVENT_H */

View File

@ -4,22 +4,22 @@
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -36,7 +36,7 @@
/**
* \file
*
* This file contains functions to resolve DNS queries and
* This file contains functions to resolve DNS queries and
* validate the answers. Synchronously and asynchronously.
*
* Several ways to use this interface from an application wishing
@ -65,7 +65,7 @@
* ... or process() calls my_callback() with results.
*
* ... if the application has nothing more to do, wait for answer
* ub_wait(ctx);
* ub_wait(ctx);
*
* Application threaded. Blocking.
* Blocking, same as above. The current thread does the work.
@ -83,7 +83,7 @@
* CRYPTO_set_id_callback and CRYPTO_set_locking_callback.
*
* If no threading is compiled in, the above async example uses fork(2) to
* create a process to perform the work. The forked process exits when the
* create a process to perform the work. The forked process exits when the
* calling process exits, or ctx_delete() is called.
* Otherwise, for asynchronous with threading, a worker thread is created.
*
@ -94,8 +94,8 @@
* The second calls another worker thread (or process) to perform the work.
* And no buffers need to be set up, but a context-switch happens.
*/
#ifndef _UB_UNBOUND_H
#define _UB_UNBOUND_H
#ifndef UB_UNBOUND_H
#define UB_UNBOUND_H
#ifdef __cplusplus
extern "C" {
@ -128,10 +128,10 @@ struct ub_result {
/** the class asked for */
int qclass;
/**
* a list of network order DNS rdata items, terminated with a
/**
* a list of network order DNS rdata items, terminated with a
* NULL pointer, so that data[0] is the first result entry,
* data[1] the second, and the last entry is NULL.
* data[1] the second, and the last entry is NULL.
* If there was no data, data[0] is NULL.
*/
char** data;
@ -139,8 +139,8 @@ struct ub_result {
/** the length in bytes of the data items, len[i] for data[i] */
int* len;
/**
* canonical name for the result (the final cname).
/**
* canonical name for the result (the final cname).
* zero terminated string.
* May be NULL if no canonical name exists.
*/
@ -165,9 +165,9 @@ struct ub_result {
*/
int havedata;
/**
/**
* If there was no data, and the domain did not exist, this is true.
* If it is false, and there was no data, then the domain name
* If it is false, and there was no data, then the domain name
* is purported to exist, but the requested data type is not available.
*/
int nxdomain;
@ -182,19 +182,19 @@ struct ub_result {
*/
int secure;
/**
* If the result was not secure (secure==0), and this result is due
/**
* If the result was not secure (secure==0), and this result is due
* to a security failure, bogus is true.
* This means the data has been actively tampered with, signatures
* failed, expected signatures were not present, timestamps on
* failed, expected signatures were not present, timestamps on
* signatures were out of date and so on.
*
* If !secure and !bogus, this can happen if the data is not secure
* because security is disabled for that domain name.
* If !secure and !bogus, this can happen if the data is not secure
* because security is disabled for that domain name.
* This means the data is from a domain where data is not signed.
*/
int bogus;
/**
* If the result is bogus this contains a string (zero terminated)
* that describes the failure. There may be other errors as well
@ -222,7 +222,7 @@ struct ub_result {
* The readable function definition looks like:
* void my_callback(void* my_arg, int err, struct ub_result* result);
* It is called with
* void* my_arg: your pointer to a (struct of) data of your choice,
* void* my_arg: your pointer to a (struct of) data of your choice,
* or NULL.
* int err: if 0 all is OK, otherwise an error occurred and no results
* are forthcoming.
@ -301,8 +301,8 @@ int ub_ctx_set_option(struct ub_ctx* ctx, const char* opt, const char* val);
* This is a power-users interface that lets you specify all sorts
* of options.
* @param str: the string is malloced and returned here. NULL on error.
* The caller must free() the string. In cases with multiple
* entries (auto-trust-anchor-file), a newline delimited list is
* The caller must free() the string. In cases with multiple
* entries (auto-trust-anchor-file), a newline delimited list is
* returned in the string.
* @return 0 if OK else an error code (malloc failure, syntax error).
*/
@ -321,10 +321,10 @@ int ub_ctx_get_option(struct ub_ctx* ctx, const char* opt, char** str);
int ub_ctx_config(struct ub_ctx* ctx, const char* fname);
/**
* Set machine to forward DNS queries to, the caching resolver to use.
* IP4 or IP6 address. Forwards all DNS requests to that machine, which
* is expected to run a recursive resolver. If the proxy is not
* DNSSEC-capable, validation may fail. Can be called several times, in
* Set machine to forward DNS queries to, the caching resolver to use.
* IP4 or IP6 address. Forwards all DNS requests to that machine, which
* is expected to run a recursive resolver. If the proxy is not
* DNSSEC-capable, validation may fail. Can be called several times, in
* that case the addresses are used as backup servers.
*
* To read the list of nameservers from /etc/resolv.conf (from DHCP or so),
@ -389,7 +389,7 @@ int ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname);
/**
* Read list of hosts from the filename given.
* Usually "/etc/hosts".
* Usually "/etc/hosts".
* These addresses are not flagged as DNSSEC secure when queried for.
*
* @param ctx: context.
@ -403,7 +403,7 @@ int ub_ctx_hosts(struct ub_ctx* ctx, const char* fname);
/**
* Add a trust anchor to the given context.
* The trust anchor is a string, on one line, that holds a valid DNSKEY or
* DS RR.
* DS RR.
* @param ctx: context.
* At this time it is only possible to add trusted keys before the
* first resolve is done.
@ -465,7 +465,7 @@ int ub_ctx_debugout(struct ub_ctx* ctx, void* out);
* Set debug verbosity for the context
* Output is directed to stderr.
* @param ctx: context.
* @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed,
* @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed,
* and 3 is lots.
* @return 0 if OK, else error.
*/
@ -474,10 +474,10 @@ int ub_ctx_debuglevel(struct ub_ctx* ctx, int d);
/**
* Set a context behaviour for asynchronous action.
* @param ctx: context.
* @param dothread: if true, enables threading and a call to resolve_async()
* @param dothread: if true, enables threading and a call to resolve_async()
* creates a thread to handle work in the background.
* If false, a process is forked to handle work in the background.
* Changes to this setting after async() calls have been made have
* Changes to this setting after async() calls have been made have
* no effect (delete and re-create the context to change).
* @return 0 if OK, else error.
*/
@ -495,7 +495,7 @@ int ub_poll(struct ub_ctx* ctx);
/**
* Wait for a context to finish with results. Calls ub_process() after
* the wait for you. After the wait, there are no more outstanding
* the wait for you. After the wait, there are no more outstanding
* asynchronous queries.
* @param ctx: context.
* @return: 0 if OK, else error.
@ -530,11 +530,11 @@ int ub_process(struct ub_ctx* ctx);
* @param rrtype: type of RR in host order, 1 is A (address).
* @param rrclass: class of RR in host order, 1 is IN (for internet).
* @param result: the result data is returned in a newly allocated result
* structure. May be NULL on return, return value is set to an error
* structure. May be NULL on return, return value is set to an error
* in that case (out of memory).
* @return 0 if OK, else error.
*/
int ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
int ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
int rrclass, struct ub_result** result);
/**
@ -561,11 +561,11 @@ int ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
* If an error happens during processing, your callback will be called
* with error set to a nonzero value (and result==NULL).
* @param async_id: if you pass a non-NULL value, an identifier number is
* returned for the query as it is in progress. It can be used to
* returned for the query as it is in progress. It can be used to
* cancel the query.
* @return 0 if OK, else error.
*/
int ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
int ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
int rrclass, void* mydata, ub_callback_type callback, int* async_id);
/**
@ -589,7 +589,7 @@ int ub_cancel(struct ub_ctx* ctx, int async_id);
*/
void ub_resolve_free(struct ub_result* result);
/**
/**
* Convert error value to a human readable string.
* @param err: error code from one of the libunbound functions.
* The error codes are from the type enum ub_ctx_err.
@ -605,7 +605,7 @@ const char* ub_strerror(int err);
int ub_ctx_print_local_zones(struct ub_ctx* ctx);
/**
* Add a new zone with the zonetype to the local authority info of the
* Add a new zone with the zonetype to the local authority info of the
* library.
* @param ctx: context. Is finalized by the routine.
* @param zone_name: name of the zone in text, "example.com"
@ -613,7 +613,7 @@ int ub_ctx_print_local_zones(struct ub_ctx* ctx);
* @param zone_type: type of the zone (like for unbound.conf) in text.
* @return 0 if OK, else error.
*/
int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name,
int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name,
const char *zone_type);
/**
@ -649,7 +649,7 @@ int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data);
*/
const char* ub_version(void);
/**
/**
* Some global statistics that are not in struct stats_info,
* this struct is shared on a shm segment (shm-key in unbound.conf)
*/
@ -695,13 +695,22 @@ struct ub_server_stats {
long long num_queries;
/** number of queries that have been dropped/ratelimited by ip. */
long long num_queries_ip_ratelimited;
/** number of queries with a valid DNS Cookie. */
long long num_queries_cookie_valid;
/** number of queries with only the client part of the DNS Cookie. */
long long num_queries_cookie_client;
/** number of queries with invalid DNS Cookie. */
long long num_queries_cookie_invalid;
/** number of queries that had a cache-miss. */
long long num_queries_missed_cache;
/** number of prefetch queries - cachehits with prefetch */
long long num_queries_prefetch;
/** number of queries which are too late to process */
long long num_queries_timed_out;
/** the longest wait time in the queue */
long long max_query_time_us;
/**
* Sum of the querylistsize of the worker for
* Sum of the querylistsize of the worker for
* every query that missed cache. To calculate average.
*/
long long sum_query_list_size;
@ -773,12 +782,12 @@ struct ub_server_stats {
long long tcp_accept_usage;
/** expired answers served from cache */
long long ans_expired;
/** histogram data exported to array
/** histogram data exported to array
* if the array is the same size, no data is lost, and
* if all histograms are same size (is so by default) then
* adding up works well. */
long long hist[UB_STATS_BUCKET_NUM];
/** number of message cache entries */
long long msg_cache_count;
/** number of rrset cache entries */
@ -788,6 +797,11 @@ struct ub_server_stats {
/** number of key cache entries */
long long key_cache_count;
/** maximum number of collisions in the msg cache */
long long msg_cache_max_collisions;
/** maximum number of collisions in the rrset cache */
long long rrset_cache_max_collisions;
/** number of queries that used dnscrypt */
long long num_query_dnscrypt_crypted;
/** number of queries that queried dnscrypt certificates */
@ -819,6 +833,8 @@ struct ub_server_stats {
/** number of queries answered from edns-subnet specific data, and
* the answer was from the edns-subnet cache. */
long long num_query_subnet_cache;
/** number of queries served from cachedb */
long long num_query_cachedb;
/** number of bytes in the stream wait buffers */
long long mem_stream_wait;
/** number of bytes in the HTTP2 query buffers */
@ -831,7 +847,7 @@ struct ub_server_stats {
long long rpz_action[UB_STATS_RPZ_ACTION_NUM];
};
/**
/**
* Statistics to send over the control pipe when asked
* This struct is made to be memcopied, sent in binary.
* shm mapped with (number+1) at num_threads+1, with first as total
@ -860,4 +876,4 @@ struct ub_stats_info {
}
#endif
#endif /* _UB_UNBOUND_H */
#endif /* UB_UNBOUND_H */

View File

@ -1306,8 +1306,8 @@ az_remove_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len,
auth_data_delete(node);
}
if(z->rpz) {
rpz_remove_rr(z->rpz, z->namelen, dname, dname_len, rr_type,
rr_class, rdata, rdatalen);
rpz_remove_rr(z->rpz, z->name, z->namelen, dname, dname_len,
rr_type, rr_class, rdata, rdatalen);
}
return 1;
}
@ -2756,6 +2756,7 @@ az_change_dnames(struct dns_msg* msg, uint8_t* oldname, uint8_t* newname,
== 0) {
msg->rep->rrsets[i]->rk.dname = newname;
msg->rep->rrsets[i]->rk.dname_len = newlen;
msg->rep->rrsets[i]->entry.hash = rrset_key_hash(&msg->rep->rrsets[i]->rk);
}
}
}
@ -5419,6 +5420,8 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
edns.opt_list_out = NULL;
edns.opt_list_inplace_cb_out = NULL;
edns.padding_block_size = 0;
edns.cookie_present = 0;
edns.cookie_valid = 0;
if(sldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
else edns.udp_size = 65535;
@ -6612,6 +6615,8 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
edns.opt_list_out = NULL;
edns.opt_list_inplace_cb_out = NULL;
edns.padding_block_size = 0;
edns.cookie_present = 0;
edns.cookie_valid = 0;
if(sldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
else edns.udp_size = 65535;
@ -7509,7 +7514,7 @@ static void add_rrlist_rrsigs_into_data(struct packed_rrset_data* data,
size_t j;
if(!rrlist[i])
continue;
if(rrlist[i] && rrlist[i]->type == LDNS_RR_TYPE_ZONEMD &&
if(rrlist[i]->type == LDNS_RR_TYPE_ZONEMD &&
query_dname_compare(z->name, node->name)==0) {
/* omit RRSIGs over type ZONEMD at apex */
continue;

View File

@ -132,31 +132,6 @@ msg_cache_remove(struct module_env* env, uint8_t* qname, size_t qnamelen,
slabhash_remove(env->msg_cache, h, &k);
}
/** remove servfail msg cache entry */
static void
msg_del_servfail(struct module_env* env, struct query_info* qinfo,
uint32_t flags)
{
struct msgreply_entry* e;
/* see if the entry is servfail, and then remove it, so that
* lookups move from the cacheresponse stage to the recursionresponse
* stage */
e = msg_cache_lookup(env, qinfo->qname, qinfo->qname_len,
qinfo->qtype, qinfo->qclass, flags, 0, 0);
if(!e) return;
/* we don't check for the ttl here, also expired servfail entries
* are removed. If the user uses serve-expired, they would still be
* used to answer from cache */
if(FLAGS_GET_RCODE(((struct reply_info*)e->entry.data)->flags)
!= LDNS_RCODE_SERVFAIL) {
lock_rw_unlock(&e->entry.lock);
return;
}
lock_rw_unlock(&e->entry.lock);
msg_cache_remove(env, qinfo->qname, qinfo->qname_len, qinfo->qtype,
qinfo->qclass, flags);
}
void
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
@ -182,13 +157,20 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
/* we do not store the message, but we did store the RRs,
* which could be useful for delegation information */
verbose(VERB_ALGO, "TTL 0: dropped msg from cache");
free(rep);
/* if the message is SERVFAIL in cache, remove that SERVFAIL,
reply_info_delete(rep, NULL);
/* if the message is in the cache, remove that msg,
* so that the TTL 0 response can be returned for future
* responses (i.e. don't get answered by the servfail from
* responses (i.e. don't get answered from
* cache, but instead go to recursion to get this TTL0
* response). */
msg_del_servfail(env, qinfo, flags);
* response).
* Possible messages that could be in the cache:
* - SERVFAIL
* - NXDOMAIN
* - NODATA
* - an older record that is expired
* - an older record that did not yet expire */
msg_cache_remove(env, qinfo->qname, qinfo->qname_len,
qinfo->qtype, qinfo->qclass, flags);
return;
}
@ -610,6 +592,7 @@ gen_dns_msg(struct regional* region, struct query_info* q, size_t num)
if(!msg->rep)
return NULL;
msg->rep->reason_bogus = LDNS_EDE_NONE;
msg->rep->reason_bogus_str = NULL;
if(num > RR_COUNT_MAX)
return NULL; /* integer overflow protection */
msg->rep->rrsets = (struct ub_packed_rrset_key**)
@ -636,6 +619,14 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
r->serve_expired_ttl < now) {
return NULL;
}
/* Ignore expired failure answers */
if(FLAGS_GET_RCODE(r->flags) !=
LDNS_RCODE_NOERROR &&
FLAGS_GET_RCODE(r->flags) !=
LDNS_RCODE_NXDOMAIN &&
FLAGS_GET_RCODE(r->flags) !=
LDNS_RCODE_YXDOMAIN)
return 0;
} else {
return NULL;
}
@ -664,6 +655,10 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
msg->rep->rrset_count = r->rrset_count;
msg->rep->authoritative = r->authoritative;
msg->rep->reason_bogus = r->reason_bogus;
if(r->reason_bogus_str) {
msg->rep->reason_bogus_str = regional_strdup(region, r->reason_bogus_str);
}
if(!rrset_array_lock(r->ref, r->rrset_count, now_control)) {
return NULL;
}
@ -1067,7 +1062,6 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
/* ttl must be relative ;i.e. 0..86400 not time(0)+86400.
* the env->now is added to message and RRsets in this routine. */
/* the leeway is used to invalidate other rrsets earlier */
if(is_referral) {
/* store rrsets */
struct rrset_ref ref;
@ -1084,7 +1078,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
&& !pside) ? qstarttime:*env->now + leeway));
}
free(rep);
reply_info_delete(rep, NULL);
return 1;
} else {
/* store msg, and rrsets */

View File

@ -67,6 +67,11 @@ int infra_dp_ratelimit = 0;
* in queries per second. */
int infra_ip_ratelimit = 0;
/** ratelimit value for client ip addresses,
* in queries per second.
* For clients with a valid DNS Cookie. */
int infra_ip_ratelimit_cookie = 0;
size_t
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
{
@ -1051,9 +1056,50 @@ infra_get_mem(struct infra_cache* infra)
return s;
}
/* Returns 1 if the limit has not been exceeded, 0 otherwise. */
static int
check_ip_ratelimit(struct sockaddr_storage* addr, socklen_t addrlen,
struct sldns_buffer* buffer, int premax, int max, int has_cookie)
{
int limit;
if(has_cookie) limit = infra_ip_ratelimit_cookie;
else limit = infra_ip_ratelimit;
/* Disabled */
if(limit == 0) return 1;
if(premax <= limit && max > limit) {
char client_ip[128], qnm[LDNS_MAX_DOMAINLEN+1+12+12];
addr_to_str(addr, addrlen, client_ip, sizeof(client_ip));
qnm[0]=0;
if(sldns_buffer_limit(buffer)>LDNS_HEADER_SIZE &&
LDNS_QDCOUNT(sldns_buffer_begin(buffer))!=0) {
(void)sldns_wire2str_rrquestion_buf(
sldns_buffer_at(buffer, LDNS_HEADER_SIZE),
sldns_buffer_limit(buffer)-LDNS_HEADER_SIZE,
qnm, sizeof(qnm));
if(strlen(qnm)>0 && qnm[strlen(qnm)-1]=='\n')
qnm[strlen(qnm)-1] = 0; /*remove newline*/
if(strchr(qnm, '\t'))
*strchr(qnm, '\t') = ' ';
if(strchr(qnm, '\t'))
*strchr(qnm, '\t') = ' ';
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d%s %s",
client_ip, limit,
has_cookie?"(cookie)":"", qnm);
} else {
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d%s (no query name)",
client_ip, limit,
has_cookie?"(cookie)":"");
}
}
return (max <= limit);
}
int infra_ip_ratelimit_inc(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
int backoff, struct sldns_buffer* buffer)
int has_cookie, int backoff, struct sldns_buffer* buffer)
{
int max;
struct lruhash_entry* entry;
@ -1070,31 +1116,8 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
(*cur)++;
max = infra_rate_max(entry->data, timenow, backoff);
lock_rw_unlock(&entry->lock);
if(premax <= infra_ip_ratelimit && max > infra_ip_ratelimit) {
char client_ip[128], qnm[LDNS_MAX_DOMAINLEN+1+12+12];
addr_to_str(addr, addrlen, client_ip, sizeof(client_ip));
qnm[0]=0;
if(sldns_buffer_limit(buffer)>LDNS_HEADER_SIZE &&
LDNS_QDCOUNT(sldns_buffer_begin(buffer))!=0) {
(void)sldns_wire2str_rrquestion_buf(
sldns_buffer_at(buffer, LDNS_HEADER_SIZE),
sldns_buffer_limit(buffer)-LDNS_HEADER_SIZE,
qnm, sizeof(qnm));
if(strlen(qnm)>0 && qnm[strlen(qnm)-1]=='\n')
qnm[strlen(qnm)-1] = 0; /*remove newline*/
if(strchr(qnm, '\t'))
*strchr(qnm, '\t') = ' ';
if(strchr(qnm, '\t'))
*strchr(qnm, '\t') = ' ';
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d %s",
client_ip, infra_ip_ratelimit, qnm);
} else {
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d (no query name)",
client_ip, infra_ip_ratelimit);
}
}
return (max <= infra_ip_ratelimit);
return check_ip_ratelimit(addr, addrlen, buffer, premax, max,
has_cookie);
}
/* create */

View File

@ -153,6 +153,8 @@ struct rate_key {
/** ip ratelimit, 0 is off */
extern int infra_ip_ratelimit;
/** ip ratelimit for DNS Cookie clients, 0 is off */
extern int infra_ip_ratelimit_cookie;
/**
* key for ip_ratelimit lookups, a source IP.
@ -419,13 +421,14 @@ int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
* @param addr: client address
* @param addrlen: client address length
* @param timenow: what time it is now.
* @param has_cookie: if the request came with a DNS Cookie.
* @param backoff: if backoff is enabled.
* @param buffer: with query for logging.
* @return 1 if it could be incremented. 0 if the increment overshot the
* ratelimit and the query should be dropped. */
int infra_ip_ratelimit_inc(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
int backoff, struct sldns_buffer* buffer);
int has_cookie, int backoff, struct sldns_buffer* buffer);
/**
* Get memory used by the infra cache.

View File

@ -4,22 +4,22 @@
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -79,9 +79,11 @@
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#ifdef HAVE_LINUX_NET_TSTAMP_H
#include <linux/net_tstamp.h>
#endif
/** number of queued TCP connections for listen() */
#define TCP_BACKLOG 256
#define TCP_BACKLOG 256
#ifndef THREADS_DISABLED
/** lock on the counter of stream buffer memory */
@ -187,7 +189,7 @@ systemd_get_activated(int family, int socktype, int listen,
log_err("systemd sd_listen_fds(): %s", strerror(-r));
return -1;
}
for(i = 0; i < r; i++) {
if(sd_is_socket(SD_LISTEN_FDS_START + i, family, socktype, listen)) {
s = SD_LISTEN_FDS_START + i;
@ -253,7 +255,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
return -1;
}
#else
if(WSAGetLastError() == WSAEAFNOSUPPORT ||
if(WSAGetLastError() == WSAEAFNOSUPPORT ||
WSAGetLastError() == WSAEPROTONOSUPPORT) {
*noproto = 1;
return -1;
@ -270,7 +272,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
#endif
if(listen) {
#ifdef SO_REUSEADDR
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
sock_strerror(errno));
@ -368,9 +370,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t slen = (socklen_t)sizeof(got);
# ifdef SO_RCVBUFFORCE
/* Linux specific: try to use root permission to override
* system limits on rcvbuf. The limit is stored in
* system limits on rcvbuf. The limit is stored in
* /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */
if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
(socklen_t)sizeof(rcv)) < 0) {
if(errno != EPERM) {
log_err("setsockopt(..., SO_RCVBUFFORCE, "
@ -381,7 +383,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
return -1;
}
# endif /* SO_RCVBUFFORCE */
if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
(socklen_t)sizeof(rcv)) < 0) {
log_err("setsockopt(..., SO_RCVBUF, "
"...) failed: %s", sock_strerror(errno));
@ -392,7 +394,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
}
/* check if we got the right thing or if system
* reduced to some system max. Warn if so */
if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got,
if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got,
&slen) >= 0 && got < rcv/2) {
log_warn("so-rcvbuf %u was not granted. "
"Got %u. To fix: start with "
@ -413,9 +415,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t slen = (socklen_t)sizeof(got);
# ifdef SO_SNDBUFFORCE
/* Linux specific: try to use root permission to override
* system limits on sndbuf. The limit is stored in
* system limits on sndbuf. The limit is stored in
* /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */
if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
(socklen_t)sizeof(snd)) < 0) {
if(errno != EPERM) {
log_err("setsockopt(..., SO_SNDBUFFORCE, "
@ -426,7 +428,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
return -1;
}
# endif /* SO_SNDBUFFORCE */
if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
(socklen_t)sizeof(snd)) < 0) {
log_err("setsockopt(..., SO_SNDBUF, "
"...) failed: %s", sock_strerror(errno));
@ -437,7 +439,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
}
/* check if we got the right thing or if system
* reduced to some system max. Warn if so */
if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got,
if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got,
&slen) >= 0 && got < snd/2) {
log_warn("so-sndbuf %u was not granted. "
"Got %u. To fix: start with "
@ -469,7 +471,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
# endif
) {
int val=(v6only==2)?0:1;
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(void*)&val, (socklen_t)sizeof(val)) < 0) {
log_err("setsockopt(..., IPV6_V6ONLY"
", ...) failed: %s", sock_strerror(errno));
@ -576,7 +578,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
int action;
# if defined(IP_PMTUDISC_OMIT)
action = IP_PMTUDISC_OMIT;
if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
&action, (socklen_t)sizeof(action)) < 0) {
if (errno != EINVAL) {
@ -609,7 +611,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
/* the IP_DONTFRAG option if defined in the 11.0 OSX headers,
* but does not work on that version, so we exclude it */
int off = 0;
if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
&off, (socklen_t)sizeof(off)) < 0) {
log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
strerror(errno));
@ -647,7 +649,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
if(WSAGetLastError() != WSAEADDRINUSE &&
WSAGetLastError() != WSAEADDRNOTAVAIL &&
!(WSAGetLastError() == WSAEACCES && verbosity < 4 && !listen)) {
log_err_addr("can't bind socket",
log_err_addr("can't bind socket",
wsa_strerror(WSAGetLastError()),
(struct sockaddr_storage*)addr, addrlen);
}
@ -749,7 +751,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
}
#endif
#ifdef SO_REUSEADDR
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
(socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
sock_strerror(errno));
@ -793,7 +795,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
&& !got_fd_from_systemd
# endif
) {
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
(void*)&on, (socklen_t)sizeof(on)) < 0) {
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
sock_strerror(errno));
@ -845,7 +847,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
addr->ai_addrlen);
}
#else
log_err_addr("can't bind socket",
log_err_addr("can't bind socket",
wsa_strerror(WSAGetLastError()),
(struct sockaddr_storage*)addr->ai_addr,
addr->ai_addrlen);
@ -873,7 +875,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
/* 5 is recommended on linux */
qlen = 5;
#endif
if ((setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &qlen,
if ((setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &qlen,
sizeof(qlen))) == -1 ) {
#ifdef ENOPROTOOPT
/* squelch ENOPROTOOPT: freebsd server mode with kernel support
@ -999,7 +1001,7 @@ err:
* Create socket from getaddrinfo results
*/
static int
make_sock(int stype, const char* ifname, const char* port,
make_sock(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind,
int use_systemd, int dscp, struct unbound_socket* ub_sock)
@ -1015,10 +1017,10 @@ make_sock(int stype, const char* ifname, const char* port,
return -1;
}
#endif
log_err("node %s:%s getaddrinfo: %s %s",
log_err("node %s:%s getaddrinfo: %s %s",
ifname?ifname:"default", port, gai_strerror(r),
#ifdef EAI_SYSTEM
r==EAI_SYSTEM?(char*)strerror(errno):""
(r==EAI_SYSTEM?(char*)strerror(errno):"")
#else
""
#endif
@ -1055,7 +1057,7 @@ make_sock(int stype, const char* ifname, const char* port,
/** make socket and first see if ifname contains port override info */
static int
make_sock_port(int stype, const char* ifname, const char* port,
make_sock_port(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
int* reuseport, int transparent, int tcp_mss, int nodelay, int freebind,
int use_systemd, int dscp, struct unbound_socket* ub_sock)
@ -1114,9 +1116,28 @@ port_insert(struct listen_port** list, int s, enum listen_type ftype,
return 1;
}
/** set fd to receive software timestamps */
static int
set_recvtimestamp(int s)
{
#ifdef HAVE_LINUX_NET_TSTAMP_H
int opt = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMPNS, (void*)&opt, (socklen_t)sizeof(opt)) < 0) {
log_err("setsockopt(..., SO_TIMESTAMPNS, ...) failed: %s",
strerror(errno));
return 0;
}
return 1;
#else
log_err("packets timestamping is not supported on this platform");
(void)s;
return 0;
#endif
}
/** set fd to receive source address packet info */
static int
set_recvpktinfo(int s, int family)
set_recvpktinfo(int s, int family)
{
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO)
int on = 1;
@ -1214,6 +1235,9 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param use_systemd: if true, fetch sockets from systemd.
* @param dnscrypt_port: dnscrypt service port number
* @param dscp: DSCP to use.
* @param sock_queue_timeout: the sock_queue_timeout from config. Seconds to
* wait to discard if UDP packets have waited for long in the socket
* buffer.
* @return: returns false on error.
*/
static int
@ -1223,7 +1247,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
struct config_strlist* tls_additional_port, int https_port,
struct config_strlist* proxy_protocol_port,
int* reuseport, int transparent, int tcp_mss, int freebind,
int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp)
int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp,
int sock_queue_timeout)
{
int s, noip6=0;
int is_https = if_is_https(ifname, port, https_port);
@ -1252,7 +1277,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
freeaddrinfo(ub_sock->addr);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock);
if(noip6) {
log_warn("IPv6 protocol not available");
@ -1263,15 +1289,20 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
/* getting source addr packet info is highly non-portable */
if(!set_recvpktinfo(s, hints->ai_family)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
if (sock_queue_timeout && !set_recvtimestamp(s)) {
log_warn("socket timestamping is not available");
}
if(!port_insert(list, s, is_dnscrypt
?listen_type_udpancil_dnscrypt:listen_type_udpancil,
is_pp2, ub_sock)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
@ -1283,7 +1314,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
freeaddrinfo(ub_sock->addr);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock);
if(noip6) {
log_warn("IPv6 protocol not available");
@ -1291,11 +1323,15 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
}
return 0;
}
if (sock_queue_timeout && !set_recvtimestamp(s)) {
log_warn("socket timestamping is not available");
}
if(!port_insert(list, s, is_dnscrypt
?listen_type_udp_dnscrypt:listen_type_udp,
is_pp2, ub_sock)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
@ -1318,7 +1354,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
&noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay,
freebind, use_systemd, dscp, ub_sock)) == -1) {
freeaddrinfo(ub_sock->addr);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock);
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
@ -1330,7 +1367,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
verbose(VERB_ALGO, "setup TCP for SSL service");
if(!port_insert(list, s, port_type, is_pp2, ub_sock)) {
sock_close(s);
freeaddrinfo(ub_sock->addr);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock);
return 0;
}
@ -1338,7 +1376,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
return 1;
}
/**
/**
* Add items to commpoint list in front.
* @param c: commpoint to add.
* @param front: listen struct.
@ -1389,7 +1427,7 @@ void listen_desetup_locks(void)
}
}
struct listen_dnsport*
struct listen_dnsport*
listen_create(struct comm_base* base, struct listen_port* ports,
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
int harden_large_queries, uint32_t http_max_streams,
@ -1525,10 +1563,10 @@ listen_list_delete(struct listen_list* list)
}
}
void
void
listen_delete(struct listen_dnsport* front)
{
if(!front)
if(!front)
return;
listen_list_delete(front->cps);
#ifdef USE_DNSCRYPT
@ -1802,7 +1840,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@ -1819,7 +1857,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@ -1838,7 +1876,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@ -1854,7 +1892,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@ -1872,7 +1910,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@ -1888,7 +1926,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind,
cfg->http_nodelay, cfg->use_systemd,
cfg->dnscrypt_port, cfg->ip_dscp)) {
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
listening_ports_free(list);
return NULL;
}
@ -1908,7 +1946,8 @@ void listening_ports_free(struct listen_port* list)
}
/* rc_ports don't have ub_socket */
if(list->socket) {
freeaddrinfo(list->socket->addr);
if(list->socket->addr)
freeaddrinfo(list->socket->addr);
free(list->socket);
}
free(list);
@ -1919,8 +1958,8 @@ void listening_ports_free(struct listen_port* list)
size_t listen_get_mem(struct listen_dnsport* listen)
{
struct listen_list* p;
size_t s = sizeof(*listen) + sizeof(*listen->base) +
sizeof(*listen->udp_buff) +
size_t s = sizeof(*listen) + sizeof(*listen->base) +
sizeof(*listen->udp_buff) +
sldns_buffer_capacity(listen->udp_buff);
#ifdef USE_DNSCRYPT
s += sizeof(*listen->dnscrypt_udp_buff);
@ -2001,7 +2040,7 @@ void tcp_req_info_clear(struct tcp_req_info* req)
}
req->open_req_list = NULL;
req->num_open_req = 0;
/* free pending writable result packets */
item = req->done_req_list;
while(item) {
@ -2060,7 +2099,7 @@ tcp_req_info_setup_listen(struct tcp_req_info* req)
wr = 1;
if(!req->read_is_closed)
rd = 1;
if(wr) {
req->cp->tcp_is_reading = 0;
comm_point_stop_listening(req->cp);
@ -2196,7 +2235,7 @@ tcp_req_info_handle_readdone(struct tcp_req_info* req)
}
req->in_worker_handle = 0;
/* it should be waiting in the mesh for recursion.
* If mesh failed to add a new entry and called commpoint_drop_reply.
* If mesh failed to add a new entry and called commpoint_drop_reply.
* Then the mesh state has been cleared. */
if(req->is_drop) {
/* the reply has been dropped, stream has been closed. */
@ -2256,7 +2295,7 @@ tcp_req_info_add_result(struct tcp_req_info* req, uint8_t* buf, size_t len)
last = req->done_req_list;
while(last && last->next)
last = last->next;
/* create new element */
item = (struct tcp_req_done_item*)malloc(sizeof(*item));
if(!item) {
@ -2615,7 +2654,7 @@ static int http2_query_read_done(struct http2_session* h2_session,
"buffer already assigned to stream");
return -1;
}
/* the c->buffer might be used by mesh_send_reply and no be cleard
* need to be cleared before use */
sldns_buffer_clear(h2_session->c->buffer);

View File

@ -1308,6 +1308,7 @@ local_encode(struct query_info* qinfo, struct module_env* env,
else rep.ns_numrrsets = 1;
rep.rrset_count = 1;
rep.rrsets = &rrset;
rep.reason_bogus = LDNS_EDE_NONE;
udpsize = edns->udp_size;
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
@ -1603,7 +1604,7 @@ local_zone_does_not_cover(struct local_zone* z, struct query_info* qinfo,
struct local_data key;
struct local_data* ld = NULL;
struct local_rrset* lr = NULL;
if(z->type == local_zone_always_transparent)
if(z->type == local_zone_always_transparent || z->type == local_zone_block_a)
return 1;
if(z->type != local_zone_transparent
&& z->type != local_zone_typetransparent
@ -1679,6 +1680,16 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
} else if(lz_type == local_zone_typetransparent
|| lz_type == local_zone_always_transparent) {
/* no NODATA or NXDOMAINS for this zone type */
return 0;
} else if(lz_type == local_zone_block_a) {
/* Return NODATA for all A queries */
if(qinfo->qtype == LDNS_RR_TYPE_A) {
local_error_encode(qinfo, env, edns, repinfo, buf, temp,
LDNS_RCODE_NOERROR, (LDNS_RCODE_NOERROR|BIT_AA),
LDNS_EDE_NONE, NULL);
return 1;
}
return 0;
} else if(lz_type == local_zone_always_null) {
/* 0.0.0.0 or ::0 or noerror/nodata for this zone type,
@ -1846,7 +1857,8 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
if(z && (lzt == local_zone_transparent ||
lzt == local_zone_typetransparent ||
lzt == local_zone_inform ||
lzt == local_zone_always_transparent) &&
lzt == local_zone_always_transparent ||
lzt == local_zone_block_a) &&
local_zone_does_not_cover(z, qinfo, labs)) {
lock_rw_unlock(&z->lock);
z = NULL;
@ -1894,6 +1906,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
if(lzt != local_zone_always_refuse
&& lzt != local_zone_always_transparent
&& lzt != local_zone_block_a
&& lzt != local_zone_always_nxdomain
&& lzt != local_zone_always_nodata
&& lzt != local_zone_always_deny
@ -1924,6 +1937,7 @@ const char* local_zone_type2str(enum localzone_type t)
case local_zone_inform_deny: return "inform_deny";
case local_zone_inform_redirect: return "inform_redirect";
case local_zone_always_transparent: return "always_transparent";
case local_zone_block_a: return "block_a";
case local_zone_always_refuse: return "always_refuse";
case local_zone_always_nxdomain: return "always_nxdomain";
case local_zone_always_nodata: return "always_nodata";
@ -1958,6 +1972,8 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
*t = local_zone_inform_redirect;
else if(strcmp(type, "always_transparent") == 0)
*t = local_zone_always_transparent;
else if(strcmp(type, "block_a") == 0)
*t = local_zone_block_a;
else if(strcmp(type, "always_refuse") == 0)
*t = local_zone_always_refuse;
else if(strcmp(type, "always_nxdomain") == 0)

View File

@ -88,6 +88,8 @@ enum localzone_type {
local_zone_inform_redirect,
/** resolve normally, even when there is local data */
local_zone_always_transparent,
/** resolve normally, even when there is local data but return NODATA for A queries */
local_zone_block_a,
/** answer with error, even when there is local data */
local_zone_always_refuse,
/** answer with nxdomain, even when there is local data */

View File

@ -4,22 +4,22 @@
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -63,82 +63,13 @@
#include "util/data/dname.h"
#include "respip/respip.h"
#include "services/listen_dnsport.h"
#include "util/timeval_func.h"
#ifdef CLIENT_SUBNET
#include "edns-subnet/subnetmod.h"
#include "edns-subnet/edns-subnet.h"
#endif
/** subtract timers and the values do not overflow or become negative */
static void
timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start)
{
#ifndef S_SPLINT_S
time_t end_usec = end->tv_usec;
d->tv_sec = end->tv_sec - start->tv_sec;
if(end_usec < start->tv_usec) {
end_usec += 1000000;
d->tv_sec--;
}
d->tv_usec = end_usec - start->tv_usec;
#endif
}
/** add timers and the values do not overflow or become negative */
static void
timeval_add(struct timeval* d, const struct timeval* add)
{
#ifndef S_SPLINT_S
d->tv_sec += add->tv_sec;
d->tv_usec += add->tv_usec;
if(d->tv_usec >= 1000000 ) {
d->tv_usec -= 1000000;
d->tv_sec++;
}
#endif
}
/** divide sum of timers to get average */
static void
timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
{
#ifndef S_SPLINT_S
size_t leftover;
if(d <= 0) {
avg->tv_sec = 0;
avg->tv_usec = 0;
return;
}
avg->tv_sec = sum->tv_sec / d;
avg->tv_usec = sum->tv_usec / d;
/* handle fraction from seconds divide */
leftover = sum->tv_sec - avg->tv_sec*d;
if(leftover <= 0)
leftover = 0;
avg->tv_usec += (((long long)leftover)*((long long)1000000))/d;
if(avg->tv_sec < 0)
avg->tv_sec = 0;
if(avg->tv_usec < 0)
avg->tv_usec = 0;
#endif
}
/** histogram compare of time values */
static int
timeval_smaller(const struct timeval* x, const struct timeval* y)
{
#ifndef S_SPLINT_S
if(x->tv_sec < y->tv_sec)
return 1;
else if(x->tv_sec == y->tv_sec) {
if(x->tv_usec <= y->tv_usec)
return 1;
else return 0;
}
else return 0;
#endif
}
/**
* Compare two response-ip client info entries for the purpose of mesh state
* compare. It returns 0 if ci_a and ci_b are considered equal; otherwise
@ -249,7 +180,7 @@ mesh_state_ref_compare(const void* ap, const void* bp)
return mesh_state_compare(a->s, b->s);
}
struct mesh_area*
struct mesh_area*
mesh_create(struct module_stack* stack, struct module_env* env)
{
struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area));
@ -275,6 +206,7 @@ mesh_create(struct module_stack* stack, struct module_env* env)
mesh->stats_jostled = 0;
mesh->stats_dropped = 0;
mesh->ans_expired = 0;
mesh->ans_cachedb = 0;
mesh->max_reply_states = env->cfg->num_queries_per_thread;
mesh->max_forever_states = (mesh->max_reply_states+1)/2;
#ifndef S_SPLINT_S
@ -298,7 +230,7 @@ mesh_delete_helper(rbnode_type* n)
* traversal and rbtree rebalancing do not work together */
}
void
void
mesh_delete(struct mesh_area* mesh)
{
if(!mesh)
@ -341,7 +273,7 @@ int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf)
if(m && m->reply_list && m->list_select == mesh_jostle_list) {
/* how old is it? */
struct timeval age;
timeval_subtract(&age, mesh->env->now_tv,
timeval_subtract(&age, mesh->env->now_tv,
&m->reply_list->start_time);
if(timeval_smaller(&mesh->jostle_max, &age)) {
/* its a goner */
@ -517,6 +449,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
comm_point_send_reply(rep);
return;
}
/* set detached (it is now) */
mesh->num_detached_states++;
if(unique)
mesh_state_make_unique(s);
s->s.rpz_passthru = rpz_passthru;
@ -525,13 +459,14 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
s->s.region);
if(!s->s.edns_opts_front_in) {
log_err("mesh_state_create: out of memory; SERVFAIL");
log_err("edns_opt_copy_region: out of memory; SERVFAIL");
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL,
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv))
edns->opt_list_inplace_cb_out = NULL;
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
mesh_state_delete(&s->s);
return;
}
}
@ -543,8 +478,6 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
#endif
rbtree_insert(&mesh->all, &s->node);
log_assert(n != NULL);
/* set detached (it is now) */
mesh->num_detached_states++;
added = 1;
}
if(!s->reply_list && !s->cb_list) {
@ -585,11 +518,11 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
/* move to either the forever or the jostle_list */
if(mesh->num_forever_states < mesh->max_forever_states) {
mesh->num_forever_states ++;
mesh_list_insert(s, &mesh->forever_first,
mesh_list_insert(s, &mesh->forever_first,
&mesh->forever_last);
s->list_select = mesh_forever_list;
} else {
mesh_list_insert(s, &mesh->jostle_first,
mesh_list_insert(s, &mesh->jostle_first,
&mesh->jostle_last);
s->list_select = mesh_jostle_list;
}
@ -610,9 +543,9 @@ servfail_mem:
return;
}
int
int
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru)
{
struct mesh_state* s = NULL;
@ -637,6 +570,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
if(!s) {
return 0;
}
/* set detached (it is now) */
mesh->num_detached_states++;
if(unique)
mesh_state_make_unique(s);
s->s.rpz_passthru = rpz_passthru;
@ -644,6 +579,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
s->s.region);
if(!s->s.edns_opts_front_in) {
mesh_state_delete(&s->s);
return 0;
}
}
@ -654,8 +590,6 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
#endif
rbtree_insert(&mesh->all, &s->node);
log_assert(n != NULL);
/* set detached (it is now) */
mesh->num_detached_states++;
added = 1;
}
if(!s->reply_list && !s->cb_list) {
@ -672,6 +606,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
}
/* add serve expired timer if not already there */
if(timeout && !mesh_serve_expired_init(s, timeout)) {
if(added)
mesh_state_delete(&s->s);
return 0;
}
/* update statistics */
@ -773,7 +709,7 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
* attached its own ECS data. */
static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
struct query_info* qinfo, uint16_t qflags, time_t leeway, int run,
int rpz_passthru, struct comm_reply* rep, struct edns_option* edns_list)
int rpz_passthru, struct sockaddr_storage* addr, struct edns_option* edns_list)
{
struct mesh_state* s = NULL;
struct edns_option* opt = NULL;
@ -803,20 +739,10 @@ static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
return;
}
} else {
/* Fake the ECS data from the client's IP */
struct ecs_data ecs;
memset(&ecs, 0, sizeof(ecs));
subnet_option_from_ss(&rep->client_addr, &ecs, mesh->env->cfg);
if(ecs.subnet_validdata == 0) {
log_err("prefetch_subnet subnet_option_from_ss: invalid data");
return;
}
subnet_ecs_opt_list_append(&ecs, &s->s.edns_opts_front_in,
&s->s, s->s.region);
if(!s->s.edns_opts_front_in) {
log_err("prefetch_subnet subnet_ecs_opt_list_append: out of memory");
return;
}
/* Store the client's address. Later in the subnet module,
* it is decided whether to include an ECS option or not.
*/
s->s.client_addr = *addr;
}
#ifdef UNBOUND_DEBUG
n =
@ -863,14 +789,14 @@ static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, time_t leeway, int rpz_passthru,
struct comm_reply* rep, struct edns_option* opt_list)
struct sockaddr_storage* addr, struct edns_option* opt_list)
{
(void)addr;
(void)opt_list;
(void)rep;
#ifdef CLIENT_SUBNET
if(rep)
if(addr)
mesh_schedule_prefetch_subnet(mesh, qinfo, qflags, leeway, 1,
rpz_passthru, rep, opt_list);
rpz_passthru, addr, opt_list);
else
#endif
mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1,
@ -900,7 +826,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
int i;
if(!region)
return NULL;
mstate = (struct mesh_state*)regional_alloc(region,
mstate = (struct mesh_state*)regional_alloc(region,
sizeof(struct mesh_state));
if(!mstate) {
alloc_reg_release(env->alloc, region);
@ -970,19 +896,13 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
return mstate;
}
int
mesh_state_is_unique(struct mesh_state* mstate)
{
return mstate->unique != NULL;
}
void
mesh_state_make_unique(struct mesh_state* mstate)
{
mstate->unique = mstate;
}
void
void
mesh_state_cleanup(struct mesh_state* mstate)
{
struct mesh_area* mesh;
@ -1028,7 +948,7 @@ mesh_state_cleanup(struct mesh_state* mstate)
alloc_reg_release(mstate->s.env->alloc, mstate->s.region);
}
void
void
mesh_state_delete(struct module_qstate* qstate)
{
struct mesh_area* mesh;
@ -1041,10 +961,10 @@ mesh_state_delete(struct module_qstate* qstate)
mesh_detach_subs(&mstate->s);
if(mstate->list_select == mesh_forever_list) {
mesh->num_forever_states --;
mesh_list_remove(mstate, &mesh->forever_first,
mesh_list_remove(mstate, &mesh->forever_first,
&mesh->forever_last);
} else if(mstate->list_select == mesh_jostle_list) {
mesh_list_remove(mstate, &mesh->jostle_first,
mesh_list_remove(mstate, &mesh->jostle_first,
&mesh->jostle_last);
}
if(!mstate->reply_list && !mstate->cb_list
@ -1116,7 +1036,7 @@ void mesh_detach_subs(struct module_qstate* qstate)
if(!ref->s->reply_list && !ref->s->cb_list
&& ref->s->super_set.count == 0) {
mesh->num_detached_states++;
log_assert(mesh->num_detached_states +
log_assert(mesh->num_detached_states +
mesh->num_reply_states <= mesh->all.count);
}
}
@ -1181,7 +1101,7 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
if(!mesh_state_attachment(qstate->mesh_info, sub))
return 0;
/* if it was a duplicate attachment, the count was not zero before */
if(!sub->reply_list && !sub->cb_list && was_detached &&
if(!sub->reply_list && !sub->cb_list && was_detached &&
sub->super_set.count == 1) {
/* it used to be detached, before this one got added */
log_assert(mesh->num_detached_states > 0);
@ -1251,7 +1171,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
else secure = 0;
if(!rep && rcode == LDNS_RCODE_NOERROR)
rcode = LDNS_RCODE_SERVFAIL;
if(!rcode && (rep->security == sec_status_bogus ||
if(!rcode && rep && (rep->security == sec_status_bogus ||
rep->security == sec_status_secure_sentinel_fail)) {
if(!(reason = errinf_to_str_bogus(&m->s)))
rcode = LDNS_RCODE_SERVFAIL;
@ -1280,10 +1200,10 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region, start_time) ||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->buf, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
(int)(r->edns.bits & EDNS_DO), secure))
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r->buf, 0, 1,
m->s.env->scratch, udp_size, &r->edns,
(int)(r->edns.bits & EDNS_DO), secure))
{
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
(*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf,
@ -1291,7 +1211,8 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
} else {
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
(*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf,
rep->security, reason, was_ratelimited);
(rep?rep->security:sec_status_unchecked),
reason, was_ratelimited);
}
}
free(reason);
@ -1311,10 +1232,36 @@ mesh_is_rpz_respip_tcponly_action(struct mesh_state const* m)
}
static inline int
mesh_is_udp(struct mesh_reply const* r) {
mesh_is_udp(struct mesh_reply const* r)
{
return r->query_reply.c->type == comm_udp;
}
static inline void
mesh_find_and_attach_ede_and_reason(struct mesh_state* m,
struct reply_info* rep, struct mesh_reply* r)
{
/* OLD note:
* During validation the EDE code can be received via two
* code paths. One code path fills the reply_info EDE, and
* the other fills it in the errinf_strlist. These paths
* intersect at some points, but where is opaque due to
* the complexity of the validator. At the time of writing
* we make the choice to prefer the EDE from errinf_strlist
* but a compelling reason to do otherwise is just as valid
* NEW note:
* The compelling reason is that with caching support, the value
* in the reply_info is cached.
* The reason members of the reply_info struct should be
* updated as they are already cached. No reason to
* try and find the EDE information in errinf anymore.
*/
if(rep->reason_bogus != LDNS_EDE_NONE) {
edns_opt_list_append_ede(&r->edns.opt_list_out,
m->s.region, rep->reason_bogus, rep->reason_bogus_str);
}
}
/**
* Send reply to mesh reply entry
* @param m: mesh state to send it for.
@ -1346,7 +1293,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
/* examine security status */
if(m->s.env->need_to_validate && (!(r->qflags&BIT_CD) ||
m->s.env->cfg->ignore_cd) && rep &&
m->s.env->cfg->ignore_cd) && rep &&
(rep->security <= sec_status_bogus ||
rep->security == sec_status_secure_sentinel_fail)) {
rcode = LDNS_RCODE_SERVFAIL;
@ -1401,40 +1348,17 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
rep, rcode, &r->edns, &r->query_reply, m->s.region, &r->start_time))
r->edns.opt_list_inplace_cb_out = NULL;
} else {
} else {
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
&r->edns, &r->query_reply, m->s.region, &r->start_time))
r->edns.opt_list_inplace_cb_out = NULL;
}
/* Send along EDE BOGUS EDNS0 option when answer is bogus */
if(m->s.env->cfg->ede && rcode == LDNS_RCODE_SERVFAIL &&
m->s.env->need_to_validate && (!(r->qflags&BIT_CD) ||
m->s.env->cfg->ignore_cd) && rep &&
(rep->security <= sec_status_bogus ||
rep->security == sec_status_secure_sentinel_fail)) {
char *reason = m->s.env->cfg->val_log_level >= 2
? errinf_to_str_bogus(&m->s) : NULL;
/* During validation the EDE code can be received via two
* code paths. One code path fills the reply_info EDE, and
* the other fills it in the errinf_strlist. These paths
* intersect at some points, but where is opaque due to
* the complexity of the validator. At the time of writing
* we make the choice to prefer the EDE from errinf_strlist
* but a compelling reason to do otherwise is just as valid
*/
sldns_ede_code reason_bogus = errinf_to_reason_bogus(&m->s);
if ((reason_bogus == LDNS_EDE_DNSSEC_BOGUS &&
rep->reason_bogus != LDNS_EDE_NONE) ||
reason_bogus == LDNS_EDE_NONE) {
reason_bogus = rep->reason_bogus;
}
if(reason_bogus != LDNS_EDE_NONE) {
edns_opt_list_append_ede(&r->edns.opt_list_out,
m->s.region, reason_bogus, reason);
}
free(reason);
/* Send along EDE EDNS0 option when SERVFAILing; usually
* DNSSEC validation failures */
/* Since we are SERVFAILing here, CD bit and rep->security
* is already handled. */
if(m->s.env->cfg->ede && rep) {
mesh_find_and_attach_ede_and_reason(m, rep, r);
}
error_encode(r_buffer, rcode, &m->s.qinfo, r->qid,
r->qflags, &r->edns);
@ -1449,12 +1373,22 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
r->edns.bits &= EDNS_DO;
m->s.qinfo.qname = r->qname;
m->s.qinfo.local_alias = r->local_alias;
/* Attach EDE without SERVFAIL if the validation failed.
* Need to explicitly check for rep->security otherwise failed
* validation paths may attach to a secure answer. */
if(m->s.env->cfg->ede && rep &&
(rep->security <= sec_status_bogus ||
rep->security == sec_status_secure_sentinel_fail)) {
mesh_find_and_attach_ede_and_reason(m, rep, r);
}
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
LDNS_RCODE_NOERROR, &r->edns, &r->query_reply, m->s.region, &r->start_time) ||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
r->qflags, r_buffer, 0, 1, m->s.env->scratch,
udp_size, &r->edns, (int)(r->edns.bits & EDNS_DO),
secure))
secure))
{
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time))
@ -1503,6 +1437,7 @@ void mesh_query_done(struct mesh_state* mstate)
struct reply_info* rep = (mstate->s.return_msg?
mstate->s.return_msg->rep:NULL);
struct timeval tv = {0, 0};
int i = 0;
/* No need for the serve expired timer anymore; we are going to reply. */
if(mstate->s.serve_expired_data) {
comm_timer_delete(mstate->s.serve_expired_data->timer);
@ -1522,6 +1457,7 @@ void mesh_query_done(struct mesh_state* mstate)
}
}
for(r = mstate->reply_list; r; r = r->next) {
i++;
tv = r->start_time;
/* if a response-ip address block has been stored the
@ -1533,16 +1469,6 @@ void mesh_query_done(struct mesh_state* mstate)
mstate->s.qinfo.qclass, r->local_alias,
&r->query_reply.client_addr,
r->query_reply.client_addrlen);
if(mstate->s.env->cfg->stat_extended &&
mstate->s.respip_action_info->rpz_used) {
if(mstate->s.respip_action_info->rpz_disabled)
mstate->s.env->mesh->rpz_action[RPZ_DISABLED_ACTION]++;
if(mstate->s.respip_action_info->rpz_cname_override)
mstate->s.env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
else
mstate->s.env->mesh->rpz_action[respip_action_to_rpz_action(
mstate->s.respip_action_info->action)]++;
}
}
/* if this query is determined to be dropped during the
@ -1573,6 +1499,27 @@ void mesh_query_done(struct mesh_state* mstate)
prev_buffer = r_buffer;
}
}
/* Account for each reply sent. */
if(i > 0 && mstate->s.respip_action_info &&
mstate->s.respip_action_info->addrinfo &&
mstate->s.env->cfg->stat_extended &&
mstate->s.respip_action_info->rpz_used) {
if(mstate->s.respip_action_info->rpz_disabled)
mstate->s.env->mesh->rpz_action[RPZ_DISABLED_ACTION] += i;
if(mstate->s.respip_action_info->rpz_cname_override)
mstate->s.env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION] += i;
else
mstate->s.env->mesh->rpz_action[respip_action_to_rpz_action(
mstate->s.respip_action_info->action)] += i;
}
if(!mstate->s.is_drop && i > 0) {
if(mstate->s.env->cfg->stat_extended
&& mstate->s.is_cachedb_answer) {
mstate->s.env->mesh->ans_cachedb += i;
}
}
/* Mesh area accounting */
if(mstate->reply_list) {
mstate->reply_list = NULL;
if(!mstate->reply_list && !mstate->cb_list) {
@ -1585,6 +1532,7 @@ void mesh_query_done(struct mesh_state* mstate)
mstate->s.env->mesh->num_detached_states++;
}
mstate->replies_sent = 1;
while((c = mstate->cb_list) != NULL) {
/* take this cb off the list; so that the list can be
* changed, eg. by adds from the callback routine */
@ -1611,7 +1559,7 @@ void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
/* callback the function to inform super of result */
fptr_ok(fptr_whitelist_mod_inform_super(
mesh->mods.mod[ref->s->s.curmod]->inform_super));
(*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
(*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
ref->s->s.curmod, &ref->s->s);
/* copy state that is always relevant to super */
copy_state_to_super(&mstate->s, ref->s->s.curmod, &ref->s->s);
@ -1635,7 +1583,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
* desire aggregation).*/
key.unique = NULL;
key.s.client_info = cinfo;
result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
return result;
}
@ -1644,7 +1592,7 @@ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
sldns_buffer* buf, mesh_cb_func_type cb, void* cb_arg,
uint16_t qid, uint16_t qflags)
{
struct mesh_cb* r = regional_alloc(s->s.region,
struct mesh_cb* r = regional_alloc(s->s.region,
sizeof(struct mesh_cb));
if(!r)
return 0;
@ -1776,7 +1724,7 @@ mesh_copy_qinfo(struct mesh_state* mstate, struct query_info** qinfop,
* Handles module finished.
* @param mesh: the mesh area.
* @param mstate: currently active mesh state.
* Deleted if finished, calls _done and _supers to
* Deleted if finished, calls _done and _supers to
* send replies to clients and inform other mesh states.
* This in turn may create additional runnable mesh states.
* @param s: state at which the current module exited.
@ -1810,7 +1758,7 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
}
if(s == module_restart_next) {
int curmod = mstate->s.curmod;
for(; mstate->s.curmod < mesh->mods.num;
for(; mstate->s.curmod < mesh->mods.num;
mstate->s.curmod++) {
fptr_ok(fptr_whitelist_mod_clear(
mesh->mods.mod[mstate->s.curmod]->clear));
@ -1842,9 +1790,21 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
if(s == module_finished) {
if(mstate->s.curmod == 0) {
struct query_info* qinfo = NULL;
struct edns_option* opt_list = NULL;
struct sockaddr_storage addr;
uint16_t qflags;
int rpz_p = 0;
#ifdef CLIENT_SUBNET
struct edns_option* ecs;
if(mstate->s.need_refetch && mstate->reply_list &&
modstack_find(&mesh->mods, "subnetcache") != -1 &&
mstate->s.env->unique_mesh) {
addr = mstate->reply_list->query_reply.client_addr;
} else
#endif
memset(&addr, 0, sizeof(addr));
mesh_query_done(mstate);
mesh_walk_supers(mesh, mstate);
@ -1854,13 +1814,28 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
* we need to make a copy of the query info here. */
if(mstate->s.need_refetch) {
mesh_copy_qinfo(mstate, &qinfo, &qflags);
#ifdef CLIENT_SUBNET
/* Make also a copy of the ecs option if any */
if((ecs = edns_opt_list_find(
mstate->s.edns_opts_front_in,
mstate->s.env->cfg->client_subnet_opcode)) != NULL) {
(void)edns_opt_list_append(&opt_list,
ecs->opt_code, ecs->opt_len,
ecs->opt_data,
mstate->s.env->scratch);
}
#endif
rpz_p = mstate->s.rpz_passthru;
}
mesh_state_delete(&mstate->s);
if(qinfo) {
mesh_schedule_prefetch(mesh, qinfo, qflags,
0, 1, rpz_p);
mesh_state_delete(&mstate->s);
mesh_new_prefetch(mesh, qinfo, qflags, 0,
rpz_p,
addr.ss_family!=AF_UNSPEC?&addr:NULL,
opt_list);
} else {
mesh_state_delete(&mstate->s);
}
return 0;
}
@ -1888,7 +1863,7 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
mstate->s.reply = NULL;
regional_free_all(mstate->s.env->scratch);
s = mstate->s.ext_state[mstate->s.curmod];
verbose(VERB_ALGO, "mesh_run: %s module exit state is %s",
verbose(VERB_ALGO, "mesh_run: %s module exit state is %s",
mesh->mods.mod[mstate->s.curmod]->name, strextstate(s));
e = NULL;
if(mesh_continue(mesh, mstate, s, &ev))
@ -1908,14 +1883,14 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
}
}
void
void
mesh_log_list(struct mesh_area* mesh)
{
char buf[30];
struct mesh_state* m;
int num = 0;
RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
snprintf(buf, sizeof(buf), "%d%s%s%s%s%s%s mod%d %s%s",
snprintf(buf, sizeof(buf), "%d%s%s%s%s%s%s mod%d %s%s",
num++, (m->s.is_priming)?"p":"", /* prime */
(m->s.is_valrec)?"v":"", /* prime */
(m->s.query_flags&BIT_RD)?"RD":"",
@ -1924,18 +1899,18 @@ mesh_log_list(struct mesh_area* mesh)
(m->sub_set.count!=0)?"c":"", /* children */
m->s.curmod, (m->reply_list)?"rep":"", /*hasreply*/
(m->cb_list)?"cb":"" /* callbacks */
);
);
log_query_info(VERB_ALGO, buf, &m->s.qinfo);
}
}
void
void
mesh_stats(struct mesh_area* mesh, const char* str)
{
verbose(VERB_DETAIL, "%s %u recursion states (%u with reply, "
"%u detached), %u waiting replies, %u recursion replies "
"sent, %d replies dropped, %d states jostled out",
str, (unsigned)mesh->all.count,
"sent, %d replies dropped, %d states jostled out",
str, (unsigned)mesh->all.count,
(unsigned)mesh->num_reply_states,
(unsigned)mesh->num_detached_states,
(unsigned)mesh->num_reply_addrs,
@ -1944,7 +1919,7 @@ mesh_stats(struct mesh_area* mesh, const char* str)
(unsigned)mesh->stats_jostled);
if(mesh->replies_sent > 0) {
struct timeval avg;
timeval_divide(&avg, &mesh->replies_sum_wait,
timeval_divide(&avg, &mesh->replies_sum_wait,
mesh->replies_sent);
log_info("average recursion processing time "
ARG_LL "d.%6.6d sec",
@ -1954,7 +1929,7 @@ mesh_stats(struct mesh_area* mesh, const char* str)
}
}
void
void
mesh_stats_clear(struct mesh_area* mesh)
{
if(!mesh)
@ -1968,12 +1943,13 @@ mesh_stats_clear(struct mesh_area* mesh)
mesh->ans_secure = 0;
mesh->ans_bogus = 0;
mesh->ans_expired = 0;
mesh->ans_cachedb = 0;
memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM);
memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM);
mesh->ans_nodata = 0;
}
size_t
size_t
mesh_get_mem(struct mesh_area* mesh)
{
struct mesh_state* m;
@ -1987,7 +1963,7 @@ mesh_get_mem(struct mesh_area* mesh)
return s;
}
int
int
mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
uint16_t flags, int prime, int valrec)
{
@ -2104,6 +2080,7 @@ mesh_serve_expired_callback(void* arg)
struct timeval tv = {0, 0};
int must_validate = (!(qstate->query_flags&BIT_CD)
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
int i = 0;
if(!qstate->serve_expired_data) return;
verbose(VERB_ALGO, "Serve expired: Trying to reply with expired data");
comm_timer_delete(qstate->serve_expired_data->timer);
@ -2175,6 +2152,7 @@ mesh_serve_expired_callback(void* arg)
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
for(r = mstate->reply_list; r; r = r->next) {
i++;
tv = r->start_time;
/* If address info is returned, it means the action should be an
@ -2184,16 +2162,6 @@ mesh_serve_expired_callback(void* arg)
qstate->qinfo.qtype, qstate->qinfo.qclass,
r->local_alias, &r->query_reply.client_addr,
r->query_reply.client_addrlen);
if(qstate->env->cfg->stat_extended && actinfo.rpz_used) {
if(actinfo.rpz_disabled)
qstate->env->mesh->rpz_action[RPZ_DISABLED_ACTION]++;
if(actinfo.rpz_cname_override)
qstate->env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
else
qstate->env->mesh->rpz_action[
respip_action_to_rpz_action(actinfo.action)]++;
}
}
/* Add EDE Stale Answer (RCF8914). Ignore global ede as this is
@ -2213,11 +2181,23 @@ mesh_serve_expired_callback(void* arg)
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
prev = r;
prev_buffer = r_buffer;
/* Account for each reply sent. */
mesh->ans_expired++;
}
/* Account for each reply sent. */
if(i > 0) {
mesh->ans_expired += i;
if(actinfo.addrinfo && qstate->env->cfg->stat_extended &&
actinfo.rpz_used) {
if(actinfo.rpz_disabled)
qstate->env->mesh->rpz_action[RPZ_DISABLED_ACTION] += i;
if(actinfo.rpz_cname_override)
qstate->env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION] += i;
else
qstate->env->mesh->rpz_action[
respip_action_to_rpz_action(actinfo.action)] += i;
}
}
/* Mesh area accounting */
if(mstate->reply_list) {
mstate->reply_list = NULL;
if(!mstate->reply_list && !mstate->cb_list) {
@ -2228,6 +2208,7 @@ mesh_serve_expired_callback(void* arg)
}
}
}
while((c = mstate->cb_list) != NULL) {
/* take this cb off the list; so that the list can be
* changed, eg. by adds from the callback routine */

View File

@ -114,6 +114,8 @@ struct mesh_area {
size_t stats_dropped;
/** stats, number of expired replies sent */
size_t ans_expired;
/** stats, number of cached replies from cachedb */
size_t ans_cachedb;
/** number of replies sent */
size_t replies_sent;
/** sum of waiting times for the replies */
@ -335,13 +337,13 @@ int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
* @param leeway: TTL leeway what to expire earlier for this update.
* @param rpz_passthru: if true, the rpz passthru was previously found and
* further rpz processing is stopped.
* @param rep: comm_reply for the client; to be used when subnet is enabled.
* @param addr: sockaddr_storage for the client; to be used with subnet.
* @param opt_list: edns opt_list from the client; to be used when subnet is
* enabled.
*/
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, time_t leeway, int rpz_passthru,
struct comm_reply* rep, struct edns_option* opt_list);
struct sockaddr_storage* addr, struct edns_option* opt_list);
/**
* Handle new event from the wire. A serviced query has returned.
@ -478,14 +480,6 @@ struct mesh_state* mesh_state_create(struct module_env* env,
struct query_info* qinfo, struct respip_client_info* cinfo,
uint16_t qflags, int prime, int valrec);
/**
* Check if the mesh state is unique.
* A unique mesh state uses it's unique member to point to itself, else NULL.
* @param mstate: mesh state to check.
* @return true if the mesh state is unique, false otherwise.
*/
int mesh_state_is_unique(struct mesh_state* mstate);
/**
* Make a mesh state unique.
* A unique mesh state uses it's unique member to point to itself.

View File

@ -120,12 +120,16 @@ modstack_config(struct module_stack* stack, const char* module_conf)
stack->mod[i] = module_factory(&module_conf);
if(!stack->mod[i]) {
char md[256];
char * s = md;
snprintf(md, sizeof(md), "%s", module_conf);
if(strchr(md, ' ')) *(strchr(md, ' ')) = 0;
if(strchr(md, '\t')) *(strchr(md, '\t')) = 0;
/* Leading spaces are present on errors. */
while (*s && isspace((unsigned char)*s))
s++;
if(strchr(s, ' ')) *(strchr(s, ' ')) = 0;
if(strchr(s, '\t')) *(strchr(s, '\t')) = 0;
log_err("Unknown value in module-config, module: '%s'."
" This module is not present (not compiled in),"
" See the list of linked modules with unbound -V", md);
" See the list of linked modules with unbound -V", s);
return 0;
}
}

View File

@ -551,8 +551,27 @@ reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr,
log_assert(&key_p != ((struct reuse_tcp*)result)->pending);
}
/* not found, return null */
/* It is possible that we search for something before the first element
* in the tree. Replace a null pointer with the first element.
*/
if (!result) {
verbose(VERB_CLIENT, "reuse_tcp_find: taking first");
result = rbtree_first(&outnet->tcp_reuse);
}
if(!result || result == RBTREE_NULL)
return NULL;
/* It is possible that we got the previous address, but that the
* address we are looking for is in the tree. If the address we got
* is less than the address we are looking, then take the next entry.
*/
if (reuse_cmp_addrportssl(result->key, &key_p.reuse) < 0) {
verbose(VERB_CLIENT, "reuse_tcp_find: key too low");
result = rbtree_next(result);
}
verbose(VERB_CLIENT, "reuse_tcp_find check inexact match");
/* inexact match, find one of possibly several connections to the
* same destination address, with the correct port, ssl, and
@ -620,6 +639,15 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
log_assert(w->addrlen > 0);
pend->c->tcp_do_toggle_rw = 0;
pend->c->tcp_do_close = 0;
/* Consistency check, if we have ssl_upstream but no sslctx, then
* log an error and return failure.
*/
if (w->ssl_upstream && !w->outnet->sslctx) {
log_err("SSL upstream requested but no SSL context");
return 0;
}
/* open socket */
s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss, w->outnet->ip_dscp);

View File

@ -1188,6 +1188,22 @@ rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint1
return z;
}
/** Find entry for RR type in the list of rrsets for the clientip. */
static struct local_rrset*
rpz_find_synthesized_rrset(uint16_t qtype,
struct clientip_synthesized_rr* data)
{
struct local_rrset* cursor = data->data;
while( cursor != NULL) {
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
if(htons(qtype) == packed_rrset->type) {
return cursor;
}
cursor = cursor->next;
}
return NULL;
}
/**
* Remove RR from RPZ's local-data
* @param z: local-zone for RPZ, holding write lock
@ -1270,15 +1286,15 @@ rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata,
}
/** Remove RR from RPZ's local-zone */
/** Remove RR from rpz localzones structure */
static void
rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
uint8_t* rdatawl, size_t rdatalen)
rpz_remove_local_zones_trigger(struct local_zones* zones, uint8_t* dname,
size_t dnamelen, enum rpz_action a, uint16_t rr_type,
uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
{
struct local_zone* z;
int delete_zone = 1;
z = rpz_find_zone(r->local_zones, dname, dnamelen, rr_class,
z = rpz_find_zone(zones, dname, dnamelen, rr_class,
1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/);
if(!z) {
verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
@ -1290,15 +1306,24 @@ rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
dnamelen, rr_type, rdatawl, rdatalen);
else if(a != localzone_type_to_rpz_action(z->type)) {
lock_rw_unlock(&z->lock);
lock_rw_unlock(&r->local_zones->lock);
lock_rw_unlock(&zones->lock);
return;
}
lock_rw_unlock(&z->lock);
if(delete_zone) {
local_zones_del_zone(r->local_zones, z);
local_zones_del_zone(zones, z);
}
lock_rw_unlock(&r->local_zones->lock);
return;
lock_rw_unlock(&zones->lock);
}
/** Remove RR from RPZ's local-zone */
static void
rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
uint8_t* rdatawl, size_t rdatalen)
{
rpz_remove_local_zones_trigger(r->local_zones, dname, dnamelen,
a, rr_type, rr_class, rdatawl, rdatalen);
}
static void
@ -1335,15 +1360,159 @@ rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
lock_rw_unlock(&r->respip_set->lock);
}
/** find and remove type from list of local_rrset entries*/
static void
del_local_rrset_from_list(struct local_rrset** list_head, uint16_t dtype)
{
struct local_rrset* prev=NULL, *p=*list_head;
while(p && ntohs(p->rrset->rk.type) != dtype) {
prev = p;
p = p->next;
}
if(!p)
return; /* rrset type not found */
/* unlink it */
if(prev) prev->next = p->next;
else *list_head = p->next;
/* no memory recycling for zone deletions ... */
}
/** Delete client-ip trigger RR from its RRset and perhaps also the rrset
* from the linked list. Returns if the local data is empty and the node can
* be deleted too, or not. */
static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node,
uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
{
struct local_rrset* rrset;
struct packed_rrset_data* d;
size_t index;
rrset = rpz_find_synthesized_rrset(rr_type, node);
if(rrset == NULL)
return 0; /* type not found, ignore */
d = (struct packed_rrset_data*)rrset->rrset->entry.data;
if(!packed_rrset_find_rr(d, rdatawl, rdatalen, &index))
return 0; /* RR not found, ignore */
if(d->count == 1) {
/* regional alloc'd */
/* delete the type entry from the list */
del_local_rrset_from_list(&node->data, rr_type);
/* if the list is empty, the node can be removed too */
if(node->data == NULL)
return 1;
} else if (d->count > 1) {
if(!local_rrset_remove_rr(d, index))
return 0;
}
return 0;
}
/** remove trigger RR from clientip_syntheized set tree. */
static void
rpz_clientip_remove_trigger_rr(struct clientip_synthesized_rrset* set,
struct sockaddr_storage* addr, socklen_t addrlen, int net,
enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
{
struct clientip_synthesized_rr* node;
int delete_node = 1;
lock_rw_wrlock(&set->lock);
node = (struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
addr, addrlen, net);
if(node == NULL) {
/* netblock not found */
verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
"RPZ address, netblock not found");
lock_rw_unlock(&set->lock);
return;
}
lock_rw_wrlock(&node->lock);
if(a == RPZ_LOCAL_DATA_ACTION) {
/* remove RR, signal whether entry can be removed */
delete_node = rpz_remove_clientip_rr(node, rr_type, rdatawl,
rdatalen);
} else if(a != node->action) {
/* ignore the RR with different action specification */
delete_node = 0;
}
if(delete_node) {
rbtree_delete(&set->entries, node->node.node.key);
}
lock_rw_unlock(&set->lock);
lock_rw_unlock(&node->lock);
if(delete_node) {
lock_rw_destroy(&node->lock);
}
}
/** Remove clientip trigger RR from RPZ. */
static void
rpz_remove_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
{
struct sockaddr_storage addr;
socklen_t addrlen;
int net, af;
if(a == RPZ_INVALID_ACTION)
return;
if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
return;
rpz_clientip_remove_trigger_rr(r->client_set, &addr, addrlen, net,
a, rr_type, rdatawl, rdatalen);
}
/** Remove nsip trigger RR from RPZ. */
static void
rpz_remove_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
{
struct sockaddr_storage addr;
socklen_t addrlen;
int net, af;
if(a == RPZ_INVALID_ACTION)
return;
if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
return;
rpz_clientip_remove_trigger_rr(r->ns_set, &addr, addrlen, net,
a, rr_type, rdatawl, rdatalen);
}
/** Remove nsdname trigger RR from RPZ. */
static void
rpz_remove_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
uint8_t* rdatawl, size_t rdatalen)
{
uint8_t* dname_stripped = NULL;
size_t dnamelen_stripped = 0;
if(a == RPZ_INVALID_ACTION)
return;
if(!rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
&dnamelen_stripped))
return;
rpz_remove_local_zones_trigger(r->nsdname_zones, dname_stripped,
dnamelen_stripped, a, rr_type, rr_class, rdatawl, rdatalen);
free(dname_stripped);
}
void
rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, size_t dnamelen,
uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl,
size_t rdatalen)
{
size_t policydnamelen;
enum rpz_trigger t;
enum rpz_action a;
uint8_t* policydname;
if(rpz_type_ignored(rr_type)) {
/* this rpz action is not valid, eg. this is the SOA or NS RR */
return;
}
if(!dname_subdomain_c(dname, azname)) {
/* not subdomain of the RPZ zone. */
return;
}
if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1)))
return;
@ -1358,13 +1527,28 @@ rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, size_t dnamelen,
return;
}
t = rpz_dname_to_trigger(policydname, policydnamelen);
if(t == RPZ_INVALID_TRIGGER) {
/* skipping invalid trigger */
free(policydname);
return;
}
if(t == RPZ_QNAME_TRIGGER) {
rpz_remove_qname_trigger(r, policydname, policydnamelen, a,
rr_type, rr_class, rdatawl, rdatalen);
} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
rpz_remove_response_ip_trigger(r, policydname, policydnamelen,
a, rr_type, rdatawl, rdatalen);
} else if(t == RPZ_CLIENT_IP_TRIGGER) {
rpz_remove_clientip_trigger(r, policydname, policydnamelen, a,
rr_type, rdatawl, rdatalen);
} else if(t == RPZ_NSIP_TRIGGER) {
rpz_remove_nsip_trigger(r, policydname, policydnamelen, a,
rr_type, rdatawl, rdatalen);
} else if(t == RPZ_NSDNAME_TRIGGER) {
rpz_remove_nsdname_trigger(r, policydname, policydnamelen, a,
rr_type, rr_class, rdatawl, rdatalen);
}
/* else it was an unsupported trigger, also skipped. */
free(policydname);
}
@ -1563,21 +1747,6 @@ rpz_local_encode(struct module_env* env, struct query_info* qinfo,
return 1;
}
static struct local_rrset*
rpz_find_synthesized_rrset(uint16_t qtype,
struct clientip_synthesized_rr* data)
{
struct local_rrset* cursor = data->data;
while( cursor != NULL) {
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
if(htons(qtype) == packed_rrset->type) {
return cursor;
}
cursor = cursor->next;
}
return NULL;
}
/** allocate SOA record ubrrsetkey in region */
static struct ub_packed_rrset_key*
make_soa_ubrrset(struct auth_zone* auth_zone, struct auth_rrset* soa,
@ -1713,7 +1882,8 @@ rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
0, /* ns */
0, /* ar */
0, /* total */
sec_status_insecure);
sec_status_insecure,
LDNS_EDE_NONE);
if(msg->rep)
msg->rep->authoritative = 1;
if(!rpz_add_soa(msg->rep, ms, az))
@ -1742,7 +1912,8 @@ rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms,
0, /* ns */
0, /* ar */
0, /* total */
sec_status_insecure);
sec_status_insecure,
LDNS_EDE_NONE);
if(msg->rep)
msg->rep->authoritative = 1;
if(!rpz_add_soa(msg->rep, ms, az))
@ -1772,7 +1943,8 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
0, /* ns */
0, /* ar */
1, /* total */
sec_status_insecure);
sec_status_insecure,
LDNS_EDE_NONE);
if(new_reply_info == NULL) {
log_err("out of memory");
return NULL;

View File

@ -84,10 +84,11 @@ enum rpz_action {
RPZ_CNAME_OVERRIDE_ACTION, /* RPZ CNAME action override*/
};
struct clientip_synthesized_rrset{
struct clientip_synthesized_rrset {
struct regional* region;
struct rbtree_type entries;
lock_rw_type lock; /* lock on the respip tree */
/** lock on the entries tree */
lock_rw_type lock;
};
struct clientip_synthesized_rr {
@ -95,10 +96,6 @@ struct clientip_synthesized_rr {
struct addr_tree_node node;
/** lock on the node item */
lock_rw_type lock;
/** tag bitlist */
uint8_t* taglist;
/** length of the taglist (in bytes) */
size_t taglen;
/** action for this address span */
enum rpz_action action;
/** "local data" for this node */
@ -152,6 +149,7 @@ int rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dna
/**
* Delete policy matching RR, used for IXFR.
* @param r: the rpz to add the policy to.
* @param azname: dname of the auth-zone
* @param aznamelen: the length of the auth-zone name
* @param dname: dname of the RR
* @param dnamelen: length of the dname
@ -160,9 +158,9 @@ int rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dna
* @param rdatawl: rdata of the RR, prepended with the rdata size
* @param rdatalen: length if the RR, including the prepended rdata size
*/
void rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl,
size_t rdatalen);
void rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen,
uint8_t* dname, size_t dnamelen, uint16_t rr_type, uint16_t rr_class,
uint8_t* rdatawl, size_t rdatalen);
/**
* Walk over the RPZ zones to find and apply a QNAME trigger policy.

View File

@ -702,7 +702,11 @@ sldns_get_rr_type_by_name(const char *name)
/* TYPEXX representation */
if (strlen(name) > 4 && strncasecmp(name, "TYPE", 4) == 0) {
return atoi(name + 4);
unsigned int a = atoi(name + 4);
if (a > LDNS_RR_TYPE_LAST) {
return (enum sldns_enum_rr_type)0;
}
return a;
}
/* Normal types */
@ -740,7 +744,11 @@ sldns_get_rr_class_by_name(const char *name)
/* CLASSXX representation */
if (strlen(name) > 5 && strncasecmp(name, "CLASS", 5) == 0) {
return atoi(name + 5);
unsigned int a = atoi(name + 5);
if (a > LDNS_RR_CLASS_LAST) {
return (enum sldns_enum_rr_class)0;
}
return a;
}
/* Normal types */

View File

@ -433,10 +433,12 @@ enum sldns_enum_edns_option
LDNS_EDNS_DHU = 6, /* RFC6975 */
LDNS_EDNS_N3U = 7, /* RFC6975 */
LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
LDNS_EDNS_COOKIE = 10, /* RFC7873 */
LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
LDNS_EDNS_PADDING = 12, /* RFC7830 */
LDNS_EDNS_EDE = 15, /* RFC8914 */
LDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */
LDNS_EDNS_CLIENT_TAG = 16, /* draft-bellis-dnsop-edns-tags-01 */
LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST = 65534
};
typedef enum sldns_enum_edns_option sldns_edns_option;
@ -482,6 +484,9 @@ typedef enum sldns_enum_ede_code sldns_ede_code;
#define LDNS_TSIG_ERROR_BADNAME 20
#define LDNS_TSIG_ERROR_BADALG 21
/** DNS Cookie extended rcode */
#define LDNS_EXT_RCODE_BADCOOKIE 23
/**
* Contains all information about resource record types.
*

View File

@ -357,7 +357,7 @@ rrinternal_get_delims(sldns_rdf_type rdftype, size_t r_cnt, size_t r_max)
break;
default : break;
}
return "\n\t ";
return "\n\t ";
}
/* Syntactic sugar for sldns_rr_new_frm_str_internal */
@ -448,7 +448,7 @@ rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len,
sldns_buffer_position(strbuf));
}
hex_data_size = (size_t)atoi(token);
if(hex_data_size > LDNS_MAX_RDFLEN ||
if(hex_data_size > LDNS_MAX_RDFLEN ||
*rr_cur_len + hex_data_size > *rr_len) {
return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
sldns_buffer_position(strbuf));
@ -567,7 +567,7 @@ sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len,
/* check if not quoted yet, and we have encountered quotes */
if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) &&
slen >= 2 &&
(token[0] == '"' || token[0] == '\'') &&
(token[0] == '"' || token[0] == '\'') &&
(token[slen-1] == '"' || token[slen-1] == '\'')) {
/* move token two smaller (quotes) with endnull */
memmove(token, token+1, slen-2);
@ -698,7 +698,7 @@ static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len)
mandatory = svcparams[i];
}
/* 4. verify that all the SvcParamKeys in mandatory are present */
/* Verify that all the SvcParamKeys in mandatory are present */
if(mandatory) {
/* Divide by sizeof(uint16_t)*/
uint16_t mandatory_nkeys = sldns_read_uint16(mandatory + 2) / sizeof(uint16_t);
@ -785,7 +785,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
token[2]=='\t')) {
was_unknown_rr_format = 1;
if((status=rrinternal_parse_unknown(strbuf, token,
token_len, rr, rr_len, &rr_cur_len,
token_len, rr, rr_len, &rr_cur_len,
pre_data_pos)) != 0)
return status;
} else if(token_strlen > 0 || quoted) {
@ -844,7 +844,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
if (rr_type == LDNS_RR_TYPE_SVCB || rr_type == LDNS_RR_TYPE_HTTPS) {
size_t rdata_len = rr_cur_len - dname_len - 10;
uint8_t *rdata = rr+dname_len + 10;
/* skip 1st rdata field SvcPriority (uint16_t) */
if (rdata_len < sizeof(uint16_t))
return LDNS_WIREPARSE_ERR_OK;
@ -1123,36 +1123,40 @@ sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len)
return key_value;
} else switch (key_len) {
case sizeof("mandatory")-1:
if (!strncmp(key, "mandatory", sizeof("mandatory")-1))
return SVCB_KEY_MANDATORY;
if (!strncmp(key, "echconfig", sizeof("echconfig")-1))
return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */
case 3:
if (!strncmp(key, "ech", key_len))
return SVCB_KEY_ECH;
break;
case sizeof("alpn")-1:
if (!strncmp(key, "alpn", sizeof("alpn")-1))
case 4:
if (!strncmp(key, "alpn", key_len))
return SVCB_KEY_ALPN;
if (!strncmp(key, "port", sizeof("port")-1))
if (!strncmp(key, "port", key_len))
return SVCB_KEY_PORT;
break;
case sizeof("no-default-alpn")-1:
if (!strncmp( key , "no-default-alpn"
, sizeof("no-default-alpn")-1))
return SVCB_KEY_NO_DEFAULT_ALPN;
case 7:
if (!strncmp(key, "dohpath", key_len))
return SVCB_KEY_DOHPATH;
break;
case sizeof("ipv4hint")-1:
if (!strncmp(key, "ipv4hint", sizeof("ipv4hint")-1))
case 8:
if (!strncmp(key, "ipv4hint", key_len))
return SVCB_KEY_IPV4HINT;
if (!strncmp(key, "ipv6hint", sizeof("ipv6hint")-1))
if (!strncmp(key, "ipv6hint", key_len))
return SVCB_KEY_IPV6HINT;
break;
case sizeof("ech")-1:
if (!strncmp(key, "ech", sizeof("ech")-1))
return SVCB_KEY_ECH;
case 9:
if (!strncmp(key, "mandatory", key_len))
return SVCB_KEY_MANDATORY;
if (!strncmp(key, "echconfig", key_len))
return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */
break;
case 15:
if (!strncmp(key, "no-default-alpn", key_len))
return SVCB_KEY_NO_DEFAULT_ALPN;
break;
default:
@ -1477,7 +1481,7 @@ sldns_str2wire_svcbparam_alpn_value(const char* val,
size_t str_len;
size_t dst_len;
size_t val_len;
val_len = strlen(val);
if (val_len > sizeof(unescaped_dst)) {
@ -1511,7 +1515,34 @@ sldns_str2wire_svcbparam_alpn_value(const char* val,
sldns_write_uint16(rd + 2, dst_len);
memcpy(rd + 4, unescaped_dst, dst_len);
*rd_len = 4 + dst_len;
return LDNS_WIREPARSE_ERR_OK;
}
static int
sldns_str2wire_svcbparam_dohpath_value(const char* val,
uint8_t* rd, size_t* rd_len)
{
size_t val_len;
/* RFC6570#section-2.1
* "The characters outside of expressions in a URI Template string are
* intended to be copied literally"
* Practically this means we do not have to look for "double escapes"
* like in the alpn value list.
*/
val_len = strlen(val);
if (*rd_len < 4 + val_len) {
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
}
sldns_write_uint16(rd, SVCB_KEY_DOHPATH);
sldns_write_uint16(rd + 2, val_len);
memcpy(rd + 4, val, val_len);
*rd_len = 4 + val_len;
return LDNS_WIREPARSE_ERR_OK;
}
@ -1535,6 +1566,7 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len,
case SVCB_KEY_PORT:
case SVCB_KEY_IPV4HINT:
case SVCB_KEY_IPV6HINT:
case SVCB_KEY_DOHPATH:
return LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM;
#endif
default:
@ -1566,6 +1598,8 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len,
return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len);
case SVCB_KEY_ALPN:
return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len);
case SVCB_KEY_DOHPATH:
return sldns_str2wire_svcbparam_dohpath_value(val, rd, rd_len);
default:
str_len = strlen(val);
if (*rd_len < 4 + str_len)
@ -1593,7 +1627,7 @@ static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_
/* case: key=value */
if (eq_pos != NULL && eq_pos[1]) {
val_in = eq_pos + 1;
/* unescape characters and "" blocks */
if (*val_in == '"') {
val_in++;
@ -1610,11 +1644,11 @@ static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_
}
*val_out = 0;
return sldns_str2wire_svcparam_value(str, eq_pos - str,
unescaped_val[0] ? unescaped_val : NULL, rd, rd_len);
return sldns_str2wire_svcparam_value(str, eq_pos - str,
unescaped_val[0] ? unescaped_val : NULL, rd, rd_len);
}
/* case: key= */
else if (eq_pos != NULL && !(eq_pos[1])) {
else if (eq_pos != NULL && !(eq_pos[1])) {
return sldns_str2wire_svcparam_value(str, eq_pos - str, NULL, rd, rd_len);
}
/* case: key */

View File

@ -38,7 +38,8 @@ struct sldns_struct_lookup_table;
#define SVCB_KEY_IPV4HINT 4
#define SVCB_KEY_ECH 5
#define SVCB_KEY_IPV6HINT 6
#define SVCPARAMKEY_COUNT 7
#define SVCB_KEY_DOHPATH 7
#define SVCPARAMKEY_COUNT 8
#define MAX_NUMBER_OF_SVCPARAMS 64
@ -236,6 +237,7 @@ uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len);
#define LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE 385
#define LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA 386
/**
* Get reference to a constant string for the (parse) error.
* @param e: error return value

View File

@ -159,7 +159,7 @@ static sldns_lookup_table sldns_wireparse_errors_data[] = {
"Mandatory SvcParamKey is missing"},
{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY,
"Keys in SvcParam mandatory MUST be unique" },
{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY,
{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY,
"mandatory MUST not be included as mandatory parameter" },
{ LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX,
"Could not parse port SvcParamValue" },
@ -224,7 +224,7 @@ sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data;
/* draft-ietf-dnsop-svcb-https-06: 6. Initial SvcParamKeys */
const char *svcparamkey_strs[] = {
"mandatory", "alpn", "no-default-alpn", "port",
"ipv4hint", "ech", "ipv6hint"
"ipv4hint", "ech", "ipv6hint", "dohpath"
};
char* sldns_wire2str_pkt(uint8_t* data, size_t len)
@ -487,7 +487,7 @@ int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
uint8_t* rr = *d;
size_t rrlen = *dlen, dname_off, rdlen, ordlen;
uint16_t rrtype = 0;
if(*dlen >= 3 && (*d)[0]==0 &&
sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) {
/* perform EDNS OPT processing */
@ -1119,7 +1119,7 @@ static int sldns_wire2str_svcparam_alpn2str(char** s,
w += sldns_str_print(s, slen, "%s", ",");
}
w += sldns_str_print(s, slen, "\"");
return w;
}
@ -1139,7 +1139,7 @@ static int sldns_wire2str_svcparam_ech2str(char** s,
(*s) += size;
(*slen) -= size;
w += sldns_str_print(s, slen, "\"");
w += sldns_str_print(s, slen, "\"");
return w + size;
}
@ -1162,7 +1162,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
/* verify that we have data_len data */
if (data_len > *dlen)
return -1;
return -1;
written_chars += sldns_print_svcparamkey(s, slen, svcparamkey);
if (!data_len) {
@ -1174,6 +1174,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
case SVCB_KEY_IPV4HINT:
case SVCB_KEY_IPV6HINT:
case SVCB_KEY_MANDATORY:
case SVCB_KEY_DOHPATH:
return -1;
default:
return written_chars;
@ -1201,6 +1202,8 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
case SVCB_KEY_ECH:
r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d);
break;
case SVCB_KEY_DOHPATH:
/* fallthrough */
default:
r = sldns_str_print(s, slen, "=\"");
@ -1222,7 +1225,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
}
if (r <= 0)
return -1; /* wireformat error */
written_chars += r;
*d += data_len;
*dlen -= data_len;
@ -1551,7 +1554,7 @@ int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
unsigned i, bit, window, block_len;
uint16_t t;
int w = 0;
/* check for errors */
while(pl) {
if(pl < 2) return -1;

View File

@ -1,11 +1,12 @@
# $OpenBSD: Makefile.inc,v 1.5 2022/10/22 16:37:57 florian Exp $
# $OpenBSD: Makefile.inc,v 1.6 2023/09/05 15:44:02 florian Exp $
.PATH: ${.CURDIR}/libunbound/util
SRCS+= alloc.c as112.c config_file.c configlexer.c configparser.y edns.c \
fptr_wlist.c locks.c mini_event.c module.c net_help.c netevent.c \
proxy_protocol.c random.c rbtree.c regional.c rtt.c tcp_conn_limit.c \
timehist.c tube.c ub_event_pluggable.c util_log.c winsock_event.c
proxy_protocol.c random.c rbtree.c regional.c rfc_1982.c rtt.c siphash.c \
tcp_conn_limit.c timehist.c timeval_func.c tube.c ub_event_pluggable.c \
util_log.c winsock_event.c
util_log.c:
ln -s ${.CURDIR}/libunbound/util/log.c $@

View File

@ -4,22 +4,22 @@
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -55,6 +55,7 @@
#include "util/regional.h"
#include "util/fptr_wlist.h"
#include "util/data/dname.h"
#include "util/random.h"
#include "util/rtt.h"
#include "services/cache/infra.h"
#include "sldns/wire2str.h"
@ -87,7 +88,10 @@ struct config_parser_state* cfg_parser = 0;
/** init ports possible for use */
static void init_outgoing_availports(int* array, int num);
struct config_file*
/** init cookie with random data */
static void init_cookie_secret(uint8_t* cookie_secret, size_t cookie_secret_len);
struct config_file*
config_create(void)
{
struct config_file* cfg;
@ -99,6 +103,7 @@ config_create(void)
cfg->stat_interval = 0;
cfg->stat_cumulative = 0;
cfg->stat_extended = 0;
cfg->stat_inhibit_zero = 1;
cfg->num_threads = 1;
cfg->port = UNBOUND_DNS_PORT;
cfg->do_ip4 = 1;
@ -115,6 +120,7 @@ config_create(void)
cfg->tcp_auth_query_timeout = 3 * 1000; /* 3s in millisecs */
cfg->do_tcp_keepalive = 0;
cfg->tcp_keepalive_timeout = 120 * 1000; /* 120s in millisecs */
cfg->sock_queue_timeout = 0; /* do not check timeout */
cfg->ssl_service_key = NULL;
cfg->ssl_service_pem = NULL;
cfg->ssl_port = UNBOUND_DNS_OVER_TLS_PORT;
@ -152,7 +158,7 @@ config_create(void)
cfg->outgoing_num_ports = 48; /* windows is limited in num fds */
cfg->num_queries_per_thread = 24;
cfg->outgoing_num_tcp = 2; /* leaves 64-52=12 for: 4if,1stop,thread4 */
cfg->incoming_num_tcp = 2;
cfg->incoming_num_tcp = 2;
#endif
cfg->stream_wait_size = 4 * 1024 * 1024;
cfg->edns_buffer_size = 1232; /* from DNS flagday recommendation */
@ -232,6 +238,7 @@ config_create(void)
cfg->harden_below_nxdomain = 1;
cfg->harden_referral_path = 0;
cfg->harden_algo_downgrade = 0;
cfg->harden_unknown_additional = 0;
cfg->use_caps_bits_for_id = 0;
cfg->caps_whitelist = NULL;
cfg->private_address = NULL;
@ -299,14 +306,14 @@ config_create(void)
cfg->minimal_responses = 1;
cfg->rrset_roundrobin = 1;
cfg->unknown_server_time_limit = 376;
cfg->max_udp_size = 4096;
if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key")))
cfg->max_udp_size = 1232; /* value taken from edns_buffer_size */
if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key")))
goto error_exit;
if(!(cfg->server_cert_file = strdup(RUN_DIR"/unbound_server.pem")))
if(!(cfg->server_cert_file = strdup(RUN_DIR"/unbound_server.pem")))
goto error_exit;
if(!(cfg->control_key_file = strdup(RUN_DIR"/unbound_control.key")))
if(!(cfg->control_key_file = strdup(RUN_DIR"/unbound_control.key")))
goto error_exit;
if(!(cfg->control_cert_file = strdup(RUN_DIR"/unbound_control.pem")))
if(!(cfg->control_cert_file = strdup(RUN_DIR"/unbound_control.pem")))
goto error_exit;
#ifdef CLIENT_SUBNET
@ -314,7 +321,7 @@ config_create(void)
#else
if(!(cfg->module_conf = strdup("validator iterator"))) goto error_exit;
#endif
if(!(cfg->val_nsec3_key_iterations =
if(!(cfg->val_nsec3_key_iterations =
strdup("1024 150 2048 150 4096 150"))) goto error_exit;
#if defined(DNSTAP_SOCKET_PATH)
if(!(cfg->dnstap_socket_path = strdup(DNSTAP_SOCKET_PATH)))
@ -323,6 +330,7 @@ config_create(void)
cfg->dnstap_bidirectional = 1;
cfg->dnstap_tls = 1;
cfg->disable_dnssec_lame_check = 0;
cfg->ip_ratelimit_cookie = 0;
cfg->ip_ratelimit = 0;
cfg->ratelimit = 0;
cfg->ip_ratelimit_slabs = 4;
@ -336,6 +344,8 @@ config_create(void)
cfg->ip_ratelimit_backoff = 0;
cfg->ratelimit_backoff = 0;
cfg->outbound_msg_retry = 5;
cfg->max_sent_count = 32;
cfg->max_query_restarts = 11;
cfg->qname_minimisation = 1;
cfg->qname_minimisation_strict = 0;
cfg->shm_enable = 0;
@ -364,11 +374,17 @@ config_create(void)
cfg->ipsecmod_whitelist = NULL;
cfg->ipsecmod_strict = 0;
#endif
cfg->do_answer_cookie = 0;
memset(cfg->cookie_secret, 0, sizeof(cfg->cookie_secret));
cfg->cookie_secret_len = 16;
init_cookie_secret(cfg->cookie_secret, cfg->cookie_secret_len);
#ifdef USE_CACHEDB
if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
#ifdef USE_REDIS
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
cfg->redis_server_path = NULL;
cfg->redis_server_password = NULL;
cfg->redis_timeout = 100;
cfg->redis_server_port = 6379;
cfg->redis_expire_records = 0;
@ -484,10 +500,10 @@ int config_set_option(struct config_file* cfg, const char* opt,
/* not supported, library must have 1 thread in bgworker */
return 0;
} else if(strcmp(opt, "outgoing-port-permit:") == 0) {
return cfg_mark_ports(val, 1,
return cfg_mark_ports(val, 1,
cfg->outgoing_avail_ports, 65536);
} else if(strcmp(opt, "outgoing-port-avoid:") == 0) {
return cfg_mark_ports(val, 0,
return cfg_mark_ports(val, 0,
cfg->outgoing_avail_ports, 65536);
} else if(strcmp(opt, "local-zone:") == 0) {
return cfg_parse_local_zone(cfg, val);
@ -501,7 +517,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
if(atoi(val) == 0) return 0;
cfg->val_date_override = (uint32_t)atoi(val);
}
} else if(strcmp(opt, "local-data-ptr:") == 0) {
} else if(strcmp(opt, "local-data-ptr:") == 0) {
char* ptr = cfg_ptr_reverse((char*)opt);
return cfg_strlist_insert(&cfg->local_data, ptr);
} else if(strcmp(opt, "logfile:") == 0) {
@ -516,6 +532,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("use-syslog:", use_syslog)
else S_STR("log-identity:", log_identity)
else S_YNO("extended-statistics:", stat_extended)
else S_YNO("statistics-inhibit-zero:", stat_inhibit_zero)
else S_YNO("statistics-cumulative:", stat_cumulative)
else S_YNO("shm-enable:", shm_enable)
else S_NUMBER_OR_ZERO("shm-key:", shm_key)
@ -536,6 +553,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_NUMBER_NONZERO("tcp-reuse-timeout:", tcp_reuse_timeout)
else S_YNO("edns-tcp-keepalive:", do_tcp_keepalive)
else S_NUMBER_NONZERO("edns-tcp-keepalive-timeout:", tcp_keepalive_timeout)
else S_NUMBER_OR_ZERO("sock-queue-timeout:", sock_queue_timeout)
else S_YNO("ssl-upstream:", ssl_upstream)
else S_YNO("tls-upstream:", ssl_upstream)
else S_STR("ssl-service-key:", ssl_service_key)
@ -645,6 +663,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("harden-below-nxdomain:", harden_below_nxdomain)
else S_YNO("harden-referral-path:", harden_referral_path)
else S_YNO("harden-algo-downgrade:", harden_algo_downgrade)
else S_YNO("harden-unknown-additional:", harden_unknown_additional)
else S_YNO("use-caps-for-id:", use_caps_bits_for_id)
else S_STRLIST("caps-whitelist:", caps_whitelist)
else S_SIZET_OR_ZERO("unwanted-reply-threshold:", unwanted_threshold)
@ -680,7 +699,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else if(strcmp(opt, "serve-expired-reply-ttl:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->serve_expired_reply_ttl = atoi(val); SERVE_EXPIRED_REPLY_TTL=(time_t)cfg->serve_expired_reply_ttl;}
else S_NUMBER_OR_ZERO("serve-expired-client-timeout:", serve_expired_client_timeout)
else S_YNO("ede:", ede)
else S_YNO("ede:", ede)
else S_YNO("ede-serve-expired:", ede_serve_expired)
else S_YNO("serve-original-ttl:", serve_original_ttl)
else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations)
@ -761,6 +780,10 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_POW2("dnscrypt-nonce-cache-slabs:",
dnscrypt_nonce_cache_slabs)
#endif
else if(strcmp(opt, "ip-ratelimit-cookie:") == 0) {
IS_NUMBER_OR_ZERO; cfg->ip_ratelimit_cookie = atoi(val);
infra_ip_ratelimit_cookie=cfg->ip_ratelimit_cookie;
}
else if(strcmp(opt, "ip-ratelimit:") == 0) {
IS_NUMBER_OR_ZERO; cfg->ip_ratelimit = atoi(val);
infra_ip_ratelimit=cfg->ip_ratelimit;
@ -778,6 +801,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("ip-ratelimit-backoff:", ip_ratelimit_backoff)
else S_YNO("ratelimit-backoff:", ratelimit_backoff)
else S_NUMBER_NONZERO("outbound-msg-retry:", outbound_msg_retry)
else S_NUMBER_NONZERO("max-sent-count:", max_sent_count)
else S_NUMBER_NONZERO("max-query-restarts:", max_query_restarts)
else S_SIZET_NONZERO("fast-server-num:", fast_server_num)
else S_NUMBER_OR_ZERO("fast-server-permil:", fast_server_permil)
else S_YNO("qname-minimisation:", qname_minimisation)
@ -806,7 +831,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
{ IS_NUMBER_OR_ZERO; cfg->val_max_restart = (int32_t)atoi(val); }
else if (strcmp(opt, "outgoing-interface:") == 0) {
char* d = strdup(val);
char** oi =
char** oi =
(char**)reallocarray(NULL, (size_t)cfg->num_out_ifs+1, sizeof(char*));
if(!d || !oi) { free(d); free(oi); return -1; }
if(cfg->out_ifs && cfg->num_out_ifs) {
@ -901,7 +926,7 @@ config_collate_cat(struct config_strlist* list)
for(s=list; s; s=s->next)
total += strlen(s->str) + 1; /* len + newline */
left = total+1; /* one extra for nul at end */
r = malloc(left);
r = malloc(left);
if(!r)
return NULL;
w = r;
@ -980,7 +1005,7 @@ config_collate_cat(struct config_strlist* list)
}
int
config_get_option(struct config_file* cfg, const char* opt,
config_get_option(struct config_file* cfg, const char* opt,
void (*func)(char*,void*), void* arg)
{
char buf[1024], nopt[64];
@ -996,6 +1021,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "statistics-interval", stat_interval)
else O_YNO(opt, "statistics-cumulative", stat_cumulative)
else O_YNO(opt, "extended-statistics", stat_extended)
else O_YNO(opt, "statistics-inhibit-zero", stat_inhibit_zero)
else O_YNO(opt, "shm-enable", shm_enable)
else O_DEC(opt, "shm-key", shm_key)
else O_YNO(opt, "use-syslog", use_syslog)
@ -1055,6 +1081,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "tcp-reuse-timeout", tcp_reuse_timeout)
else O_YNO(opt, "edns-tcp-keepalive", do_tcp_keepalive)
else O_DEC(opt, "edns-tcp-keepalive-timeout", tcp_keepalive_timeout)
else O_DEC(opt, "sock-queue-timeout", sock_queue_timeout)
else O_YNO(opt, "ssl-upstream", ssl_upstream)
else O_YNO(opt, "tls-upstream", ssl_upstream)
else O_STR(opt, "ssl-service-key", ssl_service_key)
@ -1110,6 +1137,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "harden-below-nxdomain", harden_below_nxdomain)
else O_YNO(opt, "harden-referral-path", harden_referral_path)
else O_YNO(opt, "harden-algo-downgrade", harden_algo_downgrade)
else O_YNO(opt, "harden-unknown-additional", harden_unknown_additional)
else O_YNO(opt, "use-caps-for-id", use_caps_bits_for_id)
else O_LST(opt, "caps-whitelist", caps_whitelist)
else O_DEC(opt, "unwanted-reply-threshold", unwanted_threshold)
@ -1225,6 +1253,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_LST(opt, "python-script", python_script)
else O_LST(opt, "dynlib-file", dynlib_file)
else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
else O_DEC(opt, "ip-ratelimit-cookie", ip_ratelimit_cookie)
else O_DEC(opt, "ip-ratelimit", ip_ratelimit)
else O_DEC(opt, "ratelimit", ratelimit)
else O_MEM(opt, "ip-ratelimit-size", ip_ratelimit_size)
@ -1238,6 +1267,8 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "ip-ratelimit-backoff", ip_ratelimit_backoff)
else O_YNO(opt, "ratelimit-backoff", ratelimit_backoff)
else O_UNS(opt, "outbound-msg-retry", outbound_msg_retry)
else O_UNS(opt, "max-sent-count", max_sent_count)
else O_UNS(opt, "max-query-restarts", max_query_restarts)
else O_DEC(opt, "fast-server-num", fast_server_num)
else O_DEC(opt, "fast-server-permil", fast_server_permil)
else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min)
@ -1278,6 +1309,8 @@ config_get_option(struct config_file* cfg, const char* opt,
#ifdef USE_REDIS
else O_STR(opt, "redis-server-host", redis_server_host)
else O_DEC(opt, "redis-server-port", redis_server_port)
else O_STR(opt, "redis-server-path", redis_server_path)
else O_STR(opt, "redis-server-password", redis_server_password)
else O_DEC(opt, "redis-timeout", redis_timeout)
else O_YNO(opt, "redis-expire-records", redis_expire_records)
#endif /* USE_REDIS */
@ -1313,7 +1346,7 @@ create_cfg_parser(struct config_file* cfg, char* filename, const char* chroot)
init_cfg_parse();
}
int
int
config_read(struct config_file* cfg, const char* filename, const char* chroot)
{
FILE *in;
@ -1353,7 +1386,7 @@ config_read(struct config_file* cfg, const char* filename, const char* chroot)
if(r == GLOB_NOMATCH) {
verbose(VERB_QUERY, "include: "
"no matches for %s", fname);
return 1;
return 1;
} else if(r == GLOB_NOSPACE) {
log_err("include: %s: "
"fnametern out of memory", fname);
@ -1552,7 +1585,7 @@ config_del_strbytelist(struct config_strbytelist* p)
}
}
void
void
config_delete(struct config_file* cfg)
{
if(!cfg) return;
@ -1629,6 +1662,7 @@ config_delete(struct config_file* cfg)
free(cfg->server_cert_file);
free(cfg->control_key_file);
free(cfg->control_cert_file);
free(cfg->nat64_prefix);
free(cfg->dns64_prefix);
config_delstrlist(cfg->dns64_ignore_aaaa);
free(cfg->dnstap_socket_path);
@ -1654,6 +1688,8 @@ config_delete(struct config_file* cfg)
free(cfg->cachedb_secret);
#ifdef USE_REDIS
free(cfg->redis_server_host);
free(cfg->redis_server_path);
free(cfg->redis_server_password);
#endif /* USE_REDIS */
#endif /* USE_CACHEDB */
#ifdef USE_IPSET
@ -1663,7 +1699,21 @@ config_delete(struct config_file* cfg)
free(cfg);
}
static void
static void
init_cookie_secret(uint8_t* cookie_secret, size_t cookie_secret_len)
{
struct ub_randstate *rand = ub_initstate(NULL);
if (!rand)
fatal_exit("could not init random generator");
while (cookie_secret_len) {
*cookie_secret++ = (uint8_t)ub_random(rand);
cookie_secret_len--;
}
ub_randfree(rand);
}
static void
init_outgoing_availports(int* a, int num)
{
/* generated with make iana_update */
@ -1676,7 +1726,7 @@ init_outgoing_availports(int* a, int num)
for(i=1024; i<num; i++) {
a[i] = i;
}
/* create empty spot at 49152 to keep ephemeral ports available
/* create empty spot at 49152 to keep ephemeral ports available
* to other programs */
for(i=49152; i<49152+256; i++)
a[i] = 0;
@ -1687,7 +1737,7 @@ init_outgoing_availports(int* a, int num)
}
}
int
int
cfg_mark_ports(const char* str, int allow, int* avail, int num)
{
char* mid = strchr(str, '-');
@ -1732,7 +1782,7 @@ cfg_mark_ports(const char* str, int allow, int* avail, int num)
return 1;
}
int
int
cfg_scan_ports(int* avail, int num)
{
int i;
@ -1849,7 +1899,7 @@ int cfg_strlist_append(struct config_strlist_head* list, char* item)
return 1;
}
int
int
cfg_region_strlist_insert(struct regional* region,
struct config_strlist** head, char* item)
{
@ -1882,7 +1932,7 @@ cfg_strlist_find(struct config_strlist* head, const char *item)
return NULL;
}
int
int
cfg_strlist_insert(struct config_strlist** head, char* item)
{
struct config_strlist *s;
@ -1912,7 +1962,7 @@ cfg_strlist_append_ex(struct config_strlist** head, char* item)
return 0;
s->str = item;
s->next = NULL;
if (*head==NULL) {
*head = s;
} else {
@ -1922,11 +1972,11 @@ cfg_strlist_append_ex(struct config_strlist** head, char* item)
}
last->next = s;
}
return 1;
return 1;
}
int
int
cfg_str2list_insert(struct config_str2list** head, char* item, char* i2)
{
struct config_str2list *s;
@ -1948,7 +1998,7 @@ cfg_str2list_insert(struct config_str2list** head, char* item, char* i2)
return 1;
}
int
int
cfg_str3list_insert(struct config_str3list** head, char* item, char* i2,
char* i3)
{
@ -1984,7 +2034,7 @@ cfg_strbytelist_insert(struct config_strbytelist** head, char* item,
return 1;
}
time_t
time_t
cfg_convert_timeval(const char* str)
{
time_t t;
@ -1992,7 +2042,7 @@ cfg_convert_timeval(const char* str)
memset(&tm, 0, sizeof(tm));
if(strlen(str) < 14)
return 0;
if(sscanf(str, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon,
if(sscanf(str, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon,
&tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6)
return 0;
tm.tm_year -= 1900;
@ -2009,7 +2059,7 @@ cfg_convert_timeval(const char* str)
return t;
}
int
int
cfg_count_numbers(const char* s)
{
/* format ::= (sp num)+ sp */
@ -2044,7 +2094,7 @@ static int isalldigit(const char* str, size_t l)
return 1;
}
int
int
cfg_parse_memsize(const char* str, size_t* res)
{
size_t len;
@ -2060,11 +2110,11 @@ cfg_parse_memsize(const char* str, size_t* res)
/* check appended num */
while(len>0 && str[len-1]==' ')
len--;
if(len > 1 && str[len-1] == 'b')
if(len > 1 && str[len-1] == 'b')
len--;
else if(len > 1 && str[len-1] == 'B')
else if(len > 1 && str[len-1] == 'B')
len--;
if(len > 1 && tolower((unsigned char)str[len-1]) == 'g')
mult = 1024*1024*1024;
else if(len > 1 && tolower((unsigned char)str[len-1]) == 'm')
@ -2151,7 +2201,7 @@ uint8_t* config_parse_taglist(struct config_file* cfg, char* str,
log_err("out of memory");
return 0;
}
/* parse */
s = str;
while((p=strsep(&s, " \t\n")) != NULL) {
@ -2237,7 +2287,7 @@ int taglist_intersect(uint8_t* list1, size_t list1len, const uint8_t* list2,
return 0;
}
void
void
config_apply(struct config_file* config)
{
MAX_TTL = (time_t)config->max_ttl;
@ -2279,7 +2329,7 @@ void config_lookup_uid(struct config_file* cfg)
#endif
}
/**
/**
* Calculate string length of full pathname in original filesys
* @param fname: the path name to convert.
* Must not be null or empty.
@ -2293,7 +2343,7 @@ strlen_after_chroot(const char* fname, struct config_file* cfg, int use_chdir)
{
size_t len = 0;
int slashit = 0;
if(cfg->chrootdir && cfg->chrootdir[0] &&
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) {
/* already full pathname, return it */
return strlen(fname);
@ -2316,8 +2366,8 @@ strlen_after_chroot(const char* fname, struct config_file* cfg, int use_chdir)
/* prepend chdir */
if(slashit && cfg->directory[0] != '/')
len++;
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(cfg->chrootdir, cfg->directory,
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(cfg->chrootdir, cfg->directory,
strlen(cfg->chrootdir)) == 0)
len += strlen(cfg->directory)-strlen(cfg->chrootdir);
else len += strlen(cfg->directory);
@ -2340,7 +2390,7 @@ fname_after_chroot(const char* fname, struct config_file* cfg, int use_chdir)
return NULL;
buf[0] = 0;
/* is fname already in chroot ? */
if(cfg->chrootdir && cfg->chrootdir[0] &&
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(cfg->chrootdir, fname, strlen(cfg->chrootdir)) == 0) {
/* already full pathname, return it */
(void)strlcpy(buf, fname, len);
@ -2366,10 +2416,10 @@ fname_after_chroot(const char* fname, struct config_file* cfg, int use_chdir)
if(slashit && cfg->directory[0] != '/')
(void)strlcat(buf, "/", len);
/* is the directory already in the chroot? */
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(cfg->chrootdir, cfg->directory,
if(cfg->chrootdir && cfg->chrootdir[0] &&
strncmp(cfg->chrootdir, cfg->directory,
strlen(cfg->chrootdir)) == 0)
(void)strlcat(buf, cfg->directory+strlen(cfg->chrootdir),
(void)strlcat(buf, cfg->directory+strlen(cfg->chrootdir),
len);
else (void)strlcat(buf, cfg->directory, len);
slashit = 1;
@ -2406,7 +2456,7 @@ static char* last_space_pos(const char* str)
return (sp>tab)?sp:tab;
}
int
int
cfg_parse_local_zone(struct config_file* cfg, const char* val)
{
const char *type, *name_end, *name;
@ -2441,11 +2491,11 @@ cfg_parse_local_zone(struct config_file* cfg, const char* val)
}
if(strcmp(type, "nodefault")==0) {
return cfg_strlist_insert(&cfg->local_zones_nodefault,
return cfg_strlist_insert(&cfg->local_zones_nodefault,
strdup(name));
#ifdef USE_IPSET
} else if(strcmp(type, "ipset")==0) {
return cfg_strlist_insert(&cfg->local_zones_ipset,
return cfg_strlist_insert(&cfg->local_zones_ipset,
strdup(name));
#endif
} else {
@ -2500,7 +2550,7 @@ char* cfg_ptr_reverse(char* str)
const char* hex = "0123456789abcdef";
char *p = buf;
int i;
memmove(ad, &((struct sockaddr_in6*)&addr)->sin6_addr,
memmove(ad, &((struct sockaddr_in6*)&addr)->sin6_addr,
sizeof(ad));
for(i=15; i>=0; i--) {
uint8_t b = ad[i];
@ -2512,7 +2562,7 @@ char* cfg_ptr_reverse(char* str)
snprintf(buf+16*4, sizeof(buf)-16*4, "ip6.arpa. ");
} else {
uint8_t ad[4];
memmove(ad, &((struct sockaddr_in*)&addr)->sin_addr,
memmove(ad, &((struct sockaddr_in*)&addr)->sin_addr,
sizeof(ad));
snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa. ",
(unsigned)ad[3], (unsigned)ad[2],

View File

@ -4,22 +4,22 @@
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -76,6 +76,8 @@ struct config_file {
int stat_cumulative;
/** if true, the statistics are kept in greater detail */
int stat_extended;
/** if true, inhibits a lot of =0 lines from the extended stats output */
int stat_inhibit_zero;
/** number of threads to create */
int num_threads;
@ -86,6 +88,8 @@ struct config_file {
int do_ip4;
/** do ip6 query support. */
int do_ip6;
/** do nat64 on queries */
int do_nat64;
/** prefer ip4 upstream queries. */
int prefer_ip4;
/** prefer ip6 upstream queries. */
@ -114,6 +118,8 @@ struct config_file {
int do_tcp_keepalive;
/** tcp keepalive timeout, in msec */
int tcp_keepalive_timeout;
/** timeout of packets sitting in the socket queue */
int sock_queue_timeout;
/** proxy protocol ports */
struct config_strlist* proxy_protocol_port;
@ -230,7 +236,7 @@ struct config_file {
/** interface description strings (IP addresses) */
char **ifs;
/** number of outgoing interfaces to open.
/** number of outgoing interfaces to open.
* If 0 default all interfaces. */
int num_out_ifs;
/** outgoing interface description strings (IP addresses) */
@ -249,7 +255,7 @@ struct config_file {
/** list of donotquery addresses, linked list */
struct config_strlist* donotqueryaddrs;
#ifdef CLIENT_SUBNET
/** list of servers we send edns-client-subnet option to and
/** list of servers we send edns-client-subnet option to and
* accept option from, linked list */
struct config_strlist* client_subnet;
/** list of zones we send edns-client-subnet option for */
@ -290,6 +296,9 @@ struct config_file {
int harden_referral_path;
/** harden against algorithm downgrade */
int harden_algo_downgrade;
/** harden against unknown records in the authority section and in
* the additional section */
int harden_unknown_additional;
/** use 0x20 bits in query as random ID bits */
int use_caps_bits_for_id;
/** 0x20 whitelist, domains that do not use capsforid */
@ -362,7 +371,7 @@ struct config_file {
/** the module configuration string */
char* module_conf;
/** files with trusted DS and DNSKEYs in zonefile format, list */
struct config_strlist* trust_anchor_file_list;
/** list of trustanchor keys, linked list */
@ -387,7 +396,7 @@ struct config_file {
/** max number of query restarts, number of IPs to probe */
int32_t val_max_restart;
/** this value sets the number of seconds before revalidating bogus */
int bogus_ttl;
int bogus_ttl;
/** should validator clean additional section for secure msgs */
int val_clean_additional;
/** log bogus messages by the validator */
@ -533,6 +542,9 @@ struct config_file {
/** ignore AAAAs for these domain names and use A record anyway */
struct config_strlist* dns64_ignore_aaaa;
/* NAT64 prefix; if unset defaults to dns64_prefix */
char* nat64_prefix;
/** true to enable dnstap support */
int dnstap;
/** using bidirectional frame streams if true */
@ -578,6 +590,9 @@ struct config_file {
/** ratelimit for ip addresses. 0 is off, otherwise qps (unless overridden) */
int ip_ratelimit;
/** ratelimit for ip addresses with a valid DNS Cookie. 0 is off,
* otherwise qps (unless overridden) */
int ip_ratelimit_cookie;
/** number of slabs for ip_ratelimit cache */
size_t ip_ratelimit_slabs;
/** memory size in bytes for ip_ratelimit cache */
@ -608,6 +623,11 @@ struct config_file {
/** number of retries on outgoing queries */
int outbound_msg_retry;
/** max sent queries per qstate; resets on query restarts (e.g.,
* CNAMES) and referrals */
int max_sent_count;
/** max number of query restarts; determines max length of CNAME chain */
int max_query_restarts;
/** minimise outgoing QNAME and hide original QTYPE if possible */
int qname_minimisation;
/** minimise QNAME in strict mode, minimise according to RFC.
@ -684,12 +704,23 @@ struct config_file {
char* redis_server_host;
/** redis server's TCP port */
int redis_server_port;
/** redis server's unix path. Or "", NULL if unused */
char* redis_server_path;
/** redis server's AUTH password. Or "", NULL if unused */
char* redis_server_password;
/** timeout (in ms) for communication with the redis server */
int redis_timeout;
/** set timeout on redis records based on DNS response ttl */
int redis_expire_records;
#endif
#endif
/** Downstream DNS Cookies */
/** do answer with server cookie when request contained cookie option */
int do_answer_cookie;
/** cookie secret */
uint8_t cookie_secret[40];
/** cookie secret length */
size_t cookie_secret_len;
/* ipset module */
#ifdef USE_IPSET
@ -802,7 +833,7 @@ struct config_view {
struct config_strlist* local_zones_ipset;
#endif
/** Fallback to global local_zones when there is no match in the view
* view specific tree. 1 for yes, 0 for no */
* view specific tree. 1 for yes, 0 for no */
int isfirst;
/** predefined actions for particular IP address responses */
struct config_str2list* respip_actions;
@ -877,7 +908,7 @@ struct config_file* config_create_forlib(void);
* @param config: where options are stored into, must be freshly created.
* @param filename: name of configfile. If NULL nothing is done.
* @param chroot: if not NULL, the chroot dir currently in use (for include).
* @return: false on error. In that case errno is set, ENOENT means
* @return: false on error. In that case errno is set, ENOENT means
* file not found.
*/
int config_read(struct config_file* config, const char* filename,
@ -912,16 +943,16 @@ void config_lookup_uid(struct config_file* config);
int config_set_option(struct config_file* config, const char* option,
const char* value);
/**
/**
* Call print routine for the given option.
* @param cfg: config.
* @param opt: option name without trailing :.
* @param opt: option name without trailing :.
* This is different from config_set_option.
* @param func: print func, called as (str, arg) for every data element.
* @param arg: user argument for print func.
* @return false if the option name is not supported (syntax error).
*/
int config_get_option(struct config_file* cfg, const char* opt,
int config_get_option(struct config_file* cfg, const char* opt,
void (*func)(char*,void*), void* arg);
/**
@ -941,7 +972,7 @@ int config_get_option_list(struct config_file* cfg, const char* opt,
* @param str: string. malloced, caller must free it.
* @return 0=OK, 1=syntax error, 2=malloc failed.
*/
int config_get_option_collate(struct config_file* cfg, const char* opt,
int config_get_option_collate(struct config_file* cfg, const char* opt,
char** str);
/**
@ -1136,7 +1167,7 @@ int cfg_count_numbers(const char* str);
* k=1024, m=1024*1024, g=1024*1024*1024.
* @param str: string
* @param res: result is stored here, size in bytes.
* @return: true if parsed correctly, or 0 on a parse error (and an error
* @return: true if parsed correctly, or 0 on a parse error (and an error
* is logged).
*/
int cfg_parse_memsize(const char* str, size_t* res);
@ -1170,7 +1201,7 @@ int find_tag_id(struct config_file* cfg, const char* tag);
/**
* parse taglist from string into bytestring with bitlist.
* @param cfg: the config structure (with tagnames)
* @param str: the string to parse. Parse puts 0 bytes in string.
* @param str: the string to parse. Parse puts 0 bytes in string.
* @param listlen: returns length of in bytes.
* @return malloced bytes with a bitlist of the tags. or NULL on parse error
* or malloc failure.
@ -1213,7 +1244,7 @@ int cfg_parse_local_zone(struct config_file* cfg, const char* val);
* @param allow: give true if this range is permitted.
* @param avail: the array from cfg.
* @param num: size of the array (65536).
* @return: true if parsed correctly, or 0 on a parse error (and an error
* @return: true if parsed correctly, or 0 on a parse error (and an error
* is logged).
*/
int cfg_mark_ports(const char* str, int allow, int* avail, int num);
@ -1241,7 +1272,7 @@ void cfg_apply_local_port_policy(struct config_file* cfg, int num);
*/
int cfg_scan_ports(int* avail, int num);
/**
/**
* Convert a filename to full pathname in original filesys
* @param fname: the path name to convert.
* Must not be null or empty.
@ -1250,7 +1281,7 @@ int cfg_scan_ports(int* avail, int num);
* @return pointer to malloced buffer which is: [chroot][chdir]fname
* or NULL on malloc failure.
*/
char* fname_after_chroot(const char* fname, struct config_file* cfg,
char* fname_after_chroot(const char* fname, struct config_file* cfg,
int use_chdir);
/**
@ -1335,4 +1366,3 @@ int if_is_dnscrypt(const char* ifname, const char* port, int dnscrypt_port);
#endif
#endif /* UTIL_CONFIG_FILE_H */

File diff suppressed because it is too large Load Diff

View File

@ -209,9 +209,9 @@ SQANY [^\'\n\r\\]|\\.
%x quotedstring singlequotedstr include include_quoted val include_toplevel include_toplevel_quoted
%%
<INITIAL,val>{SPACE}* {
<INITIAL,val>{SPACE}* {
LEXOUT(("SP ")); /* ignore */ }
<INITIAL,val>{SPACE}*{COMMENT}.* {
<INITIAL,val>{SPACE}*{COMMENT}.* {
/* note that flex makes the longest match and '.' is any but not nl */
LEXOUT(("comment(%s) ", yytext)); /* ignore */ }
server{COLON} { YDVAR(0, VAR_SERVER) }
@ -227,6 +227,7 @@ outgoing-num-tcp{COLON} { YDVAR(1, VAR_OUTGOING_NUM_TCP) }
incoming-num-tcp{COLON} { YDVAR(1, VAR_INCOMING_NUM_TCP) }
do-ip4{COLON} { YDVAR(1, VAR_DO_IP4) }
do-ip6{COLON} { YDVAR(1, VAR_DO_IP6) }
do-nat64{COLON} { YDVAR(1, VAR_DO_NAT64) }
prefer-ip4{COLON} { YDVAR(1, VAR_PREFER_IP4) }
prefer-ip6{COLON} { YDVAR(1, VAR_PREFER_IP6) }
do-udp{COLON} { YDVAR(1, VAR_DO_UDP) }
@ -240,6 +241,7 @@ tcp-reuse-timeout{COLON} { YDVAR(1, VAR_TCP_REUSE_TIMEOUT) }
tcp-auth-query-timeout{COLON} { YDVAR(1, VAR_TCP_AUTH_QUERY_TIMEOUT) }
edns-tcp-keepalive{COLON} { YDVAR(1, VAR_EDNS_TCP_KEEPALIVE) }
edns-tcp-keepalive-timeout{COLON} { YDVAR(1, VAR_EDNS_TCP_KEEPALIVE_TIMEOUT) }
sock-queue-timeout{COLON} { YDVAR(1, VAR_SOCK_QUEUE_TIMEOUT) }
ssl-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) }
tls-upstream{COLON} { YDVAR(1, VAR_SSL_UPSTREAM) }
ssl-service-key{COLON} { YDVAR(1, VAR_SSL_SERVICE_KEY) }
@ -316,6 +318,7 @@ harden-dnssec-stripped{COLON} { YDVAR(1, VAR_HARDEN_DNSSEC_STRIPPED) }
harden-below-nxdomain{COLON} { YDVAR(1, VAR_HARDEN_BELOW_NXDOMAIN) }
harden-referral-path{COLON} { YDVAR(1, VAR_HARDEN_REFERRAL_PATH) }
harden-algo-downgrade{COLON} { YDVAR(1, VAR_HARDEN_ALGO_DOWNGRADE) }
harden-unknown-additional{COLON} { YDVAR(1, VAR_HARDEN_UNKNOWN_ADDITIONAL) }
use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
caps-exempt{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
@ -413,7 +416,7 @@ val-log-level{COLON} { YDVAR(1, VAR_VAL_LOG_LEVEL) }
key-cache-size{COLON} { YDVAR(1, VAR_KEY_CACHE_SIZE) }
key-cache-slabs{COLON} { YDVAR(1, VAR_KEY_CACHE_SLABS) }
neg-cache-size{COLON} { YDVAR(1, VAR_NEG_CACHE_SIZE) }
val-nsec3-keysize-iterations{COLON} {
val-nsec3-keysize-iterations{COLON} {
YDVAR(1, VAR_VAL_NSEC3_KEYSIZE_ITERATIONS) }
zonemd-permissive-mode{COLON} { YDVAR(1, VAR_ZONEMD_PERMISSIVE_MODE) }
zonemd-check{COLON} { YDVAR(1, VAR_ZONEMD_CHECK) }
@ -438,6 +441,7 @@ insecure-lan-zones{COLON} { YDVAR(1, VAR_INSECURE_LAN_ZONES) }
statistics-interval{COLON} { YDVAR(1, VAR_STATISTICS_INTERVAL) }
statistics-cumulative{COLON} { YDVAR(1, VAR_STATISTICS_CUMULATIVE) }
extended-statistics{COLON} { YDVAR(1, VAR_EXTENDED_STATISTICS) }
statistics-inhibit-zero{COLON} { YDVAR(1, VAR_STATISTICS_INHIBIT_ZERO) }
shm-enable{COLON} { YDVAR(1, VAR_SHM_ENABLE) }
shm-key{COLON} { YDVAR(1, VAR_SHM_KEY) }
remote-control{COLON} { YDVAR(0, VAR_REMOTE_CONTROL) }
@ -461,6 +465,7 @@ max-udp-size{COLON} { YDVAR(1, VAR_MAX_UDP_SIZE) }
dns64-prefix{COLON} { YDVAR(1, VAR_DNS64_PREFIX) }
dns64-synthall{COLON} { YDVAR(1, VAR_DNS64_SYNTHALL) }
dns64-ignore-aaaa{COLON} { YDVAR(1, VAR_DNS64_IGNORE_AAAA) }
nat64-prefix{COLON} { YDVAR(1, VAR_NAT64_PREFIX) }
define-tag{COLON} { YDVAR(1, VAR_DEFINE_TAG) }
local-zone-tag{COLON} { YDVAR(2, VAR_LOCAL_ZONE_TAG) }
access-control-tag{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_TAG) }
@ -502,6 +507,7 @@ dnstap-log-forwarder-response-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
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) }
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
ip-ratelimit-slabs{COLON} { YDVAR(1, VAR_IP_RATELIMIT_SLABS) }
ratelimit-slabs{COLON} { YDVAR(1, VAR_RATELIMIT_SLABS) }
@ -514,6 +520,8 @@ ratelimit-factor{COLON} { YDVAR(1, VAR_RATELIMIT_FACTOR) }
ip-ratelimit-backoff{COLON} { YDVAR(1, VAR_IP_RATELIMIT_BACKOFF) }
ratelimit-backoff{COLON} { YDVAR(1, VAR_RATELIMIT_BACKOFF) }
outbound-msg-retry{COLON} { YDVAR(1, VAR_OUTBOUND_MSG_RETRY) }
max-sent-count{COLON} { YDVAR(1, VAR_MAX_SENT_COUNT) }
max-query-restarts{COLON} { YDVAR(1, VAR_MAX_QUERY_RESTARTS) }
low-rtt{COLON} { YDVAR(1, VAR_LOW_RTT) }
fast-server-num{COLON} { YDVAR(1, VAR_FAST_SERVER_NUM) }
low-rtt-pct{COLON} { YDVAR(1, VAR_FAST_SERVER_PERMIL) }
@ -551,6 +559,8 @@ backend{COLON} { YDVAR(1, VAR_CACHEDB_BACKEND) }
secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
redis-server-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) }
redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) }
redis-server-path{COLON} { YDVAR(1, VAR_CACHEDB_REDISPATH) }
redis-server-password{COLON} { YDVAR(1, VAR_CACHEDB_REDISPASSWORD) }
redis-timeout{COLON} { YDVAR(1, VAR_CACHEDB_REDISTIMEOUT) }
redis-expire-records{COLON} { YDVAR(1, VAR_CACHEDB_REDISEXPIRERECORDS) }
ipset{COLON} { YDVAR(0, VAR_IPSET) }
@ -558,6 +568,8 @@ name-v4{COLON} { YDVAR(1, VAR_IPSET_NAME_V4) }
name-v6{COLON} { YDVAR(1, VAR_IPSET_NAME_V6) }
udp-upstream-without-downstream{COLON} { YDVAR(1, VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM) }
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) }
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 ) }
@ -573,7 +585,7 @@ proxy-protocol-port{COLON} { YDVAR(1, VAR_PROXY_PROTOCOL_PORT) }
else { BEGIN(val); }
}
<quotedstring>{DQANY}* { LEXOUT(("STR(%s) ", yytext)); yymore(); }
<quotedstring>{NEWLINE} { yyerror("newline inside quoted string, no end \"");
<quotedstring>{NEWLINE} { yyerror("newline inside quoted string, no end \"");
cfg_parser->line++; BEGIN(INITIAL); }
<quotedstring>\" {
LEXOUT(("QE "));
@ -594,7 +606,7 @@ proxy-protocol-port{COLON} { YDVAR(1, VAR_PROXY_PROTOCOL_PORT) }
else { BEGIN(val); }
}
<singlequotedstr>{SQANY}* { LEXOUT(("STR(%s) ", yytext)); yymore(); }
<singlequotedstr>{NEWLINE} { yyerror("newline inside quoted string, no end '");
<singlequotedstr>{NEWLINE} { yyerror("newline inside quoted string, no end '");
cfg_parser->line++; BEGIN(INITIAL); }
<singlequotedstr>\' {
LEXOUT(("SQE "));
@ -608,7 +620,7 @@ proxy-protocol-port{COLON} { YDVAR(1, VAR_PROXY_PROTOCOL_PORT) }
}
/* include: directive */
<INITIAL,val>include{COLON} {
<INITIAL,val>include{COLON} {
LEXOUT(("v(%s) ", yytext)); inc_prev = YYSTATE; BEGIN(include); }
<include><<EOF>> {
yyerror("EOF inside include directive");
@ -627,7 +639,7 @@ proxy-protocol-port{COLON} { YDVAR(1, VAR_PROXY_PROTOCOL_PORT) }
BEGIN(inc_prev);
}
<include_quoted>{DQANY}* { LEXOUT(("ISTR(%s) ", yytext)); yymore(); }
<include_quoted>{NEWLINE} { yyerror("newline before \" in include name");
<include_quoted>{NEWLINE} { yyerror("newline before \" in include name");
cfg_parser->line++; BEGIN(inc_prev); }
<include_quoted>\" {
LEXOUT(("IQE "));
@ -682,7 +694,7 @@ proxy-protocol-port{COLON} { YDVAR(1, VAR_PROXY_PROTOCOL_PORT) }
return (VAR_FORCE_TOPLEVEL);
}
<val>{UNQUOTEDLETTER}* { LEXOUT(("unquotedstr(%s) ", yytext));
<val>{UNQUOTEDLETTER}* { LEXOUT(("unquotedstr(%s) ", yytext));
if(--num_args == 0) { BEGIN(INITIAL); }
yylval.str = strdup(yytext); return STRING_ARG; }

View File

@ -16,319 +16,331 @@
#define VAR_PREFER_IP4 272
#define VAR_DO_IP4 273
#define VAR_DO_IP6 274
#define VAR_PREFER_IP6 275
#define VAR_DO_UDP 276
#define VAR_DO_TCP 277
#define VAR_TCP_MSS 278
#define VAR_OUTGOING_TCP_MSS 279
#define VAR_TCP_IDLE_TIMEOUT 280
#define VAR_EDNS_TCP_KEEPALIVE 281
#define VAR_EDNS_TCP_KEEPALIVE_TIMEOUT 282
#define VAR_CHROOT 283
#define VAR_USERNAME 284
#define VAR_DIRECTORY 285
#define VAR_LOGFILE 286
#define VAR_PIDFILE 287
#define VAR_MSG_CACHE_SIZE 288
#define VAR_MSG_CACHE_SLABS 289
#define VAR_NUM_QUERIES_PER_THREAD 290
#define VAR_RRSET_CACHE_SIZE 291
#define VAR_RRSET_CACHE_SLABS 292
#define VAR_OUTGOING_NUM_TCP 293
#define VAR_INFRA_HOST_TTL 294
#define VAR_INFRA_LAME_TTL 295
#define VAR_INFRA_CACHE_SLABS 296
#define VAR_INFRA_CACHE_NUMHOSTS 297
#define VAR_INFRA_CACHE_LAME_SIZE 298
#define VAR_NAME 299
#define VAR_STUB_ZONE 300
#define VAR_STUB_HOST 301
#define VAR_STUB_ADDR 302
#define VAR_TARGET_FETCH_POLICY 303
#define VAR_HARDEN_SHORT_BUFSIZE 304
#define VAR_HARDEN_LARGE_QUERIES 305
#define VAR_FORWARD_ZONE 306
#define VAR_FORWARD_HOST 307
#define VAR_FORWARD_ADDR 308
#define VAR_DO_NOT_QUERY_ADDRESS 309
#define VAR_HIDE_IDENTITY 310
#define VAR_HIDE_VERSION 311
#define VAR_IDENTITY 312
#define VAR_VERSION 313
#define VAR_HARDEN_GLUE 314
#define VAR_MODULE_CONF 315
#define VAR_TRUST_ANCHOR_FILE 316
#define VAR_TRUST_ANCHOR 317
#define VAR_VAL_OVERRIDE_DATE 318
#define VAR_BOGUS_TTL 319
#define VAR_VAL_CLEAN_ADDITIONAL 320
#define VAR_VAL_PERMISSIVE_MODE 321
#define VAR_INCOMING_NUM_TCP 322
#define VAR_MSG_BUFFER_SIZE 323
#define VAR_KEY_CACHE_SIZE 324
#define VAR_KEY_CACHE_SLABS 325
#define VAR_TRUSTED_KEYS_FILE 326
#define VAR_VAL_NSEC3_KEYSIZE_ITERATIONS 327
#define VAR_USE_SYSLOG 328
#define VAR_OUTGOING_INTERFACE 329
#define VAR_ROOT_HINTS 330
#define VAR_DO_NOT_QUERY_LOCALHOST 331
#define VAR_CACHE_MAX_TTL 332
#define VAR_HARDEN_DNSSEC_STRIPPED 333
#define VAR_ACCESS_CONTROL 334
#define VAR_LOCAL_ZONE 335
#define VAR_LOCAL_DATA 336
#define VAR_INTERFACE_AUTOMATIC 337
#define VAR_STATISTICS_INTERVAL 338
#define VAR_DO_DAEMONIZE 339
#define VAR_USE_CAPS_FOR_ID 340
#define VAR_STATISTICS_CUMULATIVE 341
#define VAR_OUTGOING_PORT_PERMIT 342
#define VAR_OUTGOING_PORT_AVOID 343
#define VAR_DLV_ANCHOR_FILE 344
#define VAR_DLV_ANCHOR 345
#define VAR_NEG_CACHE_SIZE 346
#define VAR_HARDEN_REFERRAL_PATH 347
#define VAR_PRIVATE_ADDRESS 348
#define VAR_PRIVATE_DOMAIN 349
#define VAR_REMOTE_CONTROL 350
#define VAR_CONTROL_ENABLE 351
#define VAR_CONTROL_INTERFACE 352
#define VAR_CONTROL_PORT 353
#define VAR_SERVER_KEY_FILE 354
#define VAR_SERVER_CERT_FILE 355
#define VAR_CONTROL_KEY_FILE 356
#define VAR_CONTROL_CERT_FILE 357
#define VAR_CONTROL_USE_CERT 358
#define VAR_TCP_REUSE_TIMEOUT 359
#define VAR_MAX_REUSE_TCP_QUERIES 360
#define VAR_EXTENDED_STATISTICS 361
#define VAR_LOCAL_DATA_PTR 362
#define VAR_JOSTLE_TIMEOUT 363
#define VAR_STUB_PRIME 364
#define VAR_UNWANTED_REPLY_THRESHOLD 365
#define VAR_LOG_TIME_ASCII 366
#define VAR_DOMAIN_INSECURE 367
#define VAR_PYTHON 368
#define VAR_PYTHON_SCRIPT 369
#define VAR_VAL_SIG_SKEW_MIN 370
#define VAR_VAL_SIG_SKEW_MAX 371
#define VAR_VAL_MAX_RESTART 372
#define VAR_CACHE_MIN_TTL 373
#define VAR_VAL_LOG_LEVEL 374
#define VAR_AUTO_TRUST_ANCHOR_FILE 375
#define VAR_KEEP_MISSING 376
#define VAR_ADD_HOLDDOWN 377
#define VAR_DEL_HOLDDOWN 378
#define VAR_SO_RCVBUF 379
#define VAR_EDNS_BUFFER_SIZE 380
#define VAR_PREFETCH 381
#define VAR_PREFETCH_KEY 382
#define VAR_SO_SNDBUF 383
#define VAR_SO_REUSEPORT 384
#define VAR_HARDEN_BELOW_NXDOMAIN 385
#define VAR_IGNORE_CD_FLAG 386
#define VAR_LOG_QUERIES 387
#define VAR_LOG_REPLIES 388
#define VAR_LOG_LOCAL_ACTIONS 389
#define VAR_TCP_UPSTREAM 390
#define VAR_SSL_UPSTREAM 391
#define VAR_TCP_AUTH_QUERY_TIMEOUT 392
#define VAR_SSL_SERVICE_KEY 393
#define VAR_SSL_SERVICE_PEM 394
#define VAR_SSL_PORT 395
#define VAR_FORWARD_FIRST 396
#define VAR_STUB_SSL_UPSTREAM 397
#define VAR_FORWARD_SSL_UPSTREAM 398
#define VAR_TLS_CERT_BUNDLE 399
#define VAR_STUB_TCP_UPSTREAM 400
#define VAR_FORWARD_TCP_UPSTREAM 401
#define VAR_HTTPS_PORT 402
#define VAR_HTTP_ENDPOINT 403
#define VAR_HTTP_MAX_STREAMS 404
#define VAR_HTTP_QUERY_BUFFER_SIZE 405
#define VAR_HTTP_RESPONSE_BUFFER_SIZE 406
#define VAR_HTTP_NODELAY 407
#define VAR_HTTP_NOTLS_DOWNSTREAM 408
#define VAR_STUB_FIRST 409
#define VAR_MINIMAL_RESPONSES 410
#define VAR_RRSET_ROUNDROBIN 411
#define VAR_MAX_UDP_SIZE 412
#define VAR_DELAY_CLOSE 413
#define VAR_UDP_CONNECT 414
#define VAR_UNBLOCK_LAN_ZONES 415
#define VAR_INSECURE_LAN_ZONES 416
#define VAR_INFRA_CACHE_MIN_RTT 417
#define VAR_INFRA_CACHE_MAX_RTT 418
#define VAR_INFRA_KEEP_PROBING 419
#define VAR_DNS64_PREFIX 420
#define VAR_DNS64_SYNTHALL 421
#define VAR_DNS64_IGNORE_AAAA 422
#define VAR_DNSTAP 423
#define VAR_DNSTAP_ENABLE 424
#define VAR_DNSTAP_SOCKET_PATH 425
#define VAR_DNSTAP_IP 426
#define VAR_DNSTAP_TLS 427
#define VAR_DNSTAP_TLS_SERVER_NAME 428
#define VAR_DNSTAP_TLS_CERT_BUNDLE 429
#define VAR_DNSTAP_TLS_CLIENT_KEY_FILE 430
#define VAR_DNSTAP_TLS_CLIENT_CERT_FILE 431
#define VAR_DNSTAP_SEND_IDENTITY 432
#define VAR_DNSTAP_SEND_VERSION 433
#define VAR_DNSTAP_BIDIRECTIONAL 434
#define VAR_DNSTAP_IDENTITY 435
#define VAR_DNSTAP_VERSION 436
#define VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES 437
#define VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES 438
#define VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES 439
#define VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES 440
#define VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES 441
#define VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES 442
#define VAR_RESPONSE_IP_TAG 443
#define VAR_RESPONSE_IP 444
#define VAR_RESPONSE_IP_DATA 445
#define VAR_HARDEN_ALGO_DOWNGRADE 446
#define VAR_IP_TRANSPARENT 447
#define VAR_IP_DSCP 448
#define VAR_DISABLE_DNSSEC_LAME_CHECK 449
#define VAR_IP_RATELIMIT 450
#define VAR_IP_RATELIMIT_SLABS 451
#define VAR_IP_RATELIMIT_SIZE 452
#define VAR_RATELIMIT 453
#define VAR_RATELIMIT_SLABS 454
#define VAR_RATELIMIT_SIZE 455
#define VAR_OUTBOUND_MSG_RETRY 456
#define VAR_RATELIMIT_FOR_DOMAIN 457
#define VAR_RATELIMIT_BELOW_DOMAIN 458
#define VAR_IP_RATELIMIT_FACTOR 459
#define VAR_RATELIMIT_FACTOR 460
#define VAR_IP_RATELIMIT_BACKOFF 461
#define VAR_RATELIMIT_BACKOFF 462
#define VAR_SEND_CLIENT_SUBNET 463
#define VAR_CLIENT_SUBNET_ZONE 464
#define VAR_CLIENT_SUBNET_ALWAYS_FORWARD 465
#define VAR_CLIENT_SUBNET_OPCODE 466
#define VAR_MAX_CLIENT_SUBNET_IPV4 467
#define VAR_MAX_CLIENT_SUBNET_IPV6 468
#define VAR_MIN_CLIENT_SUBNET_IPV4 469
#define VAR_MIN_CLIENT_SUBNET_IPV6 470
#define VAR_MAX_ECS_TREE_SIZE_IPV4 471
#define VAR_MAX_ECS_TREE_SIZE_IPV6 472
#define VAR_CAPS_WHITELIST 473
#define VAR_CACHE_MAX_NEGATIVE_TTL 474
#define VAR_PERMIT_SMALL_HOLDDOWN 475
#define VAR_QNAME_MINIMISATION 476
#define VAR_QNAME_MINIMISATION_STRICT 477
#define VAR_IP_FREEBIND 478
#define VAR_DEFINE_TAG 479
#define VAR_LOCAL_ZONE_TAG 480
#define VAR_ACCESS_CONTROL_TAG 481
#define VAR_LOCAL_ZONE_OVERRIDE 482
#define VAR_ACCESS_CONTROL_TAG_ACTION 483
#define VAR_ACCESS_CONTROL_TAG_DATA 484
#define VAR_VIEW 485
#define VAR_ACCESS_CONTROL_VIEW 486
#define VAR_VIEW_FIRST 487
#define VAR_SERVE_EXPIRED 488
#define VAR_SERVE_EXPIRED_TTL 489
#define VAR_SERVE_EXPIRED_TTL_RESET 490
#define VAR_SERVE_EXPIRED_REPLY_TTL 491
#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 492
#define VAR_EDE_SERVE_EXPIRED 493
#define VAR_SERVE_ORIGINAL_TTL 494
#define VAR_FAKE_DSA 495
#define VAR_FAKE_SHA1 496
#define VAR_LOG_IDENTITY 497
#define VAR_HIDE_TRUSTANCHOR 498
#define VAR_HIDE_HTTP_USER_AGENT 499
#define VAR_HTTP_USER_AGENT 500
#define VAR_TRUST_ANCHOR_SIGNALING 501
#define VAR_AGGRESSIVE_NSEC 502
#define VAR_USE_SYSTEMD 503
#define VAR_SHM_ENABLE 504
#define VAR_SHM_KEY 505
#define VAR_ROOT_KEY_SENTINEL 506
#define VAR_DNSCRYPT 507
#define VAR_DNSCRYPT_ENABLE 508
#define VAR_DNSCRYPT_PORT 509
#define VAR_DNSCRYPT_PROVIDER 510
#define VAR_DNSCRYPT_SECRET_KEY 511
#define VAR_DNSCRYPT_PROVIDER_CERT 512
#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 513
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 514
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 515
#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 516
#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 517
#define VAR_PAD_RESPONSES 518
#define VAR_PAD_RESPONSES_BLOCK_SIZE 519
#define VAR_PAD_QUERIES 520
#define VAR_PAD_QUERIES_BLOCK_SIZE 521
#define VAR_IPSECMOD_ENABLED 522
#define VAR_IPSECMOD_HOOK 523
#define VAR_IPSECMOD_IGNORE_BOGUS 524
#define VAR_IPSECMOD_MAX_TTL 525
#define VAR_IPSECMOD_WHITELIST 526
#define VAR_IPSECMOD_STRICT 527
#define VAR_CACHEDB 528
#define VAR_CACHEDB_BACKEND 529
#define VAR_CACHEDB_SECRETSEED 530
#define VAR_CACHEDB_REDISHOST 531
#define VAR_CACHEDB_REDISPORT 532
#define VAR_CACHEDB_REDISTIMEOUT 533
#define VAR_CACHEDB_REDISEXPIRERECORDS 534
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 535
#define VAR_FOR_UPSTREAM 536
#define VAR_AUTH_ZONE 537
#define VAR_ZONEFILE 538
#define VAR_MASTER 539
#define VAR_URL 540
#define VAR_FOR_DOWNSTREAM 541
#define VAR_FALLBACK_ENABLED 542
#define VAR_TLS_ADDITIONAL_PORT 543
#define VAR_LOW_RTT 544
#define VAR_LOW_RTT_PERMIL 545
#define VAR_FAST_SERVER_PERMIL 546
#define VAR_FAST_SERVER_NUM 547
#define VAR_ALLOW_NOTIFY 548
#define VAR_TLS_WIN_CERT 549
#define VAR_TCP_CONNECTION_LIMIT 550
#define VAR_FORWARD_NO_CACHE 551
#define VAR_STUB_NO_CACHE 552
#define VAR_LOG_SERVFAIL 553
#define VAR_DENY_ANY 554
#define VAR_UNKNOWN_SERVER_TIME_LIMIT 555
#define VAR_LOG_TAG_QUERYREPLY 556
#define VAR_STREAM_WAIT_SIZE 557
#define VAR_TLS_CIPHERS 558
#define VAR_TLS_CIPHERSUITES 559
#define VAR_TLS_USE_SNI 560
#define VAR_IPSET 561
#define VAR_IPSET_NAME_V4 562
#define VAR_IPSET_NAME_V6 563
#define VAR_TLS_SESSION_TICKET_KEYS 564
#define VAR_RPZ 565
#define VAR_TAGS 566
#define VAR_RPZ_ACTION_OVERRIDE 567
#define VAR_RPZ_CNAME_OVERRIDE 568
#define VAR_RPZ_LOG 569
#define VAR_RPZ_LOG_NAME 570
#define VAR_DYNLIB 571
#define VAR_DYNLIB_FILE 572
#define VAR_EDNS_CLIENT_STRING 573
#define VAR_EDNS_CLIENT_STRING_OPCODE 574
#define VAR_NSID 575
#define VAR_ZONEMD_PERMISSIVE_MODE 576
#define VAR_ZONEMD_CHECK 577
#define VAR_ZONEMD_REJECT_ABSENCE 578
#define VAR_RPZ_SIGNAL_NXDOMAIN_RA 579
#define VAR_INTERFACE_AUTOMATIC_PORTS 580
#define VAR_EDE 581
#define VAR_INTERFACE_ACTION 582
#define VAR_INTERFACE_VIEW 583
#define VAR_INTERFACE_TAG 584
#define VAR_INTERFACE_TAG_ACTION 585
#define VAR_INTERFACE_TAG_DATA 586
#define VAR_PROXY_PROTOCOL_PORT 587
#define VAR_DO_NAT64 275
#define VAR_PREFER_IP6 276
#define VAR_DO_UDP 277
#define VAR_DO_TCP 278
#define VAR_TCP_MSS 279
#define VAR_OUTGOING_TCP_MSS 280
#define VAR_TCP_IDLE_TIMEOUT 281
#define VAR_EDNS_TCP_KEEPALIVE 282
#define VAR_EDNS_TCP_KEEPALIVE_TIMEOUT 283
#define VAR_SOCK_QUEUE_TIMEOUT 284
#define VAR_CHROOT 285
#define VAR_USERNAME 286
#define VAR_DIRECTORY 287
#define VAR_LOGFILE 288
#define VAR_PIDFILE 289
#define VAR_MSG_CACHE_SIZE 290
#define VAR_MSG_CACHE_SLABS 291
#define VAR_NUM_QUERIES_PER_THREAD 292
#define VAR_RRSET_CACHE_SIZE 293
#define VAR_RRSET_CACHE_SLABS 294
#define VAR_OUTGOING_NUM_TCP 295
#define VAR_INFRA_HOST_TTL 296
#define VAR_INFRA_LAME_TTL 297
#define VAR_INFRA_CACHE_SLABS 298
#define VAR_INFRA_CACHE_NUMHOSTS 299
#define VAR_INFRA_CACHE_LAME_SIZE 300
#define VAR_NAME 301
#define VAR_STUB_ZONE 302
#define VAR_STUB_HOST 303
#define VAR_STUB_ADDR 304
#define VAR_TARGET_FETCH_POLICY 305
#define VAR_HARDEN_SHORT_BUFSIZE 306
#define VAR_HARDEN_LARGE_QUERIES 307
#define VAR_FORWARD_ZONE 308
#define VAR_FORWARD_HOST 309
#define VAR_FORWARD_ADDR 310
#define VAR_DO_NOT_QUERY_ADDRESS 311
#define VAR_HIDE_IDENTITY 312
#define VAR_HIDE_VERSION 313
#define VAR_IDENTITY 314
#define VAR_VERSION 315
#define VAR_HARDEN_GLUE 316
#define VAR_MODULE_CONF 317
#define VAR_TRUST_ANCHOR_FILE 318
#define VAR_TRUST_ANCHOR 319
#define VAR_VAL_OVERRIDE_DATE 320
#define VAR_BOGUS_TTL 321
#define VAR_VAL_CLEAN_ADDITIONAL 322
#define VAR_VAL_PERMISSIVE_MODE 323
#define VAR_INCOMING_NUM_TCP 324
#define VAR_MSG_BUFFER_SIZE 325
#define VAR_KEY_CACHE_SIZE 326
#define VAR_KEY_CACHE_SLABS 327
#define VAR_TRUSTED_KEYS_FILE 328
#define VAR_VAL_NSEC3_KEYSIZE_ITERATIONS 329
#define VAR_USE_SYSLOG 330
#define VAR_OUTGOING_INTERFACE 331
#define VAR_ROOT_HINTS 332
#define VAR_DO_NOT_QUERY_LOCALHOST 333
#define VAR_CACHE_MAX_TTL 334
#define VAR_HARDEN_DNSSEC_STRIPPED 335
#define VAR_ACCESS_CONTROL 336
#define VAR_LOCAL_ZONE 337
#define VAR_LOCAL_DATA 338
#define VAR_INTERFACE_AUTOMATIC 339
#define VAR_STATISTICS_INTERVAL 340
#define VAR_DO_DAEMONIZE 341
#define VAR_USE_CAPS_FOR_ID 342
#define VAR_STATISTICS_CUMULATIVE 343
#define VAR_OUTGOING_PORT_PERMIT 344
#define VAR_OUTGOING_PORT_AVOID 345
#define VAR_DLV_ANCHOR_FILE 346
#define VAR_DLV_ANCHOR 347
#define VAR_NEG_CACHE_SIZE 348
#define VAR_HARDEN_REFERRAL_PATH 349
#define VAR_PRIVATE_ADDRESS 350
#define VAR_PRIVATE_DOMAIN 351
#define VAR_REMOTE_CONTROL 352
#define VAR_CONTROL_ENABLE 353
#define VAR_CONTROL_INTERFACE 354
#define VAR_CONTROL_PORT 355
#define VAR_SERVER_KEY_FILE 356
#define VAR_SERVER_CERT_FILE 357
#define VAR_CONTROL_KEY_FILE 358
#define VAR_CONTROL_CERT_FILE 359
#define VAR_CONTROL_USE_CERT 360
#define VAR_TCP_REUSE_TIMEOUT 361
#define VAR_MAX_REUSE_TCP_QUERIES 362
#define VAR_EXTENDED_STATISTICS 363
#define VAR_LOCAL_DATA_PTR 364
#define VAR_JOSTLE_TIMEOUT 365
#define VAR_STUB_PRIME 366
#define VAR_UNWANTED_REPLY_THRESHOLD 367
#define VAR_LOG_TIME_ASCII 368
#define VAR_DOMAIN_INSECURE 369
#define VAR_PYTHON 370
#define VAR_PYTHON_SCRIPT 371
#define VAR_VAL_SIG_SKEW_MIN 372
#define VAR_VAL_SIG_SKEW_MAX 373
#define VAR_VAL_MAX_RESTART 374
#define VAR_CACHE_MIN_TTL 375
#define VAR_VAL_LOG_LEVEL 376
#define VAR_AUTO_TRUST_ANCHOR_FILE 377
#define VAR_KEEP_MISSING 378
#define VAR_ADD_HOLDDOWN 379
#define VAR_DEL_HOLDDOWN 380
#define VAR_SO_RCVBUF 381
#define VAR_EDNS_BUFFER_SIZE 382
#define VAR_PREFETCH 383
#define VAR_PREFETCH_KEY 384
#define VAR_SO_SNDBUF 385
#define VAR_SO_REUSEPORT 386
#define VAR_HARDEN_BELOW_NXDOMAIN 387
#define VAR_IGNORE_CD_FLAG 388
#define VAR_LOG_QUERIES 389
#define VAR_LOG_REPLIES 390
#define VAR_LOG_LOCAL_ACTIONS 391
#define VAR_TCP_UPSTREAM 392
#define VAR_SSL_UPSTREAM 393
#define VAR_TCP_AUTH_QUERY_TIMEOUT 394
#define VAR_SSL_SERVICE_KEY 395
#define VAR_SSL_SERVICE_PEM 396
#define VAR_SSL_PORT 397
#define VAR_FORWARD_FIRST 398
#define VAR_STUB_SSL_UPSTREAM 399
#define VAR_FORWARD_SSL_UPSTREAM 400
#define VAR_TLS_CERT_BUNDLE 401
#define VAR_STUB_TCP_UPSTREAM 402
#define VAR_FORWARD_TCP_UPSTREAM 403
#define VAR_HTTPS_PORT 404
#define VAR_HTTP_ENDPOINT 405
#define VAR_HTTP_MAX_STREAMS 406
#define VAR_HTTP_QUERY_BUFFER_SIZE 407
#define VAR_HTTP_RESPONSE_BUFFER_SIZE 408
#define VAR_HTTP_NODELAY 409
#define VAR_HTTP_NOTLS_DOWNSTREAM 410
#define VAR_STUB_FIRST 411
#define VAR_MINIMAL_RESPONSES 412
#define VAR_RRSET_ROUNDROBIN 413
#define VAR_MAX_UDP_SIZE 414
#define VAR_DELAY_CLOSE 415
#define VAR_UDP_CONNECT 416
#define VAR_UNBLOCK_LAN_ZONES 417
#define VAR_INSECURE_LAN_ZONES 418
#define VAR_INFRA_CACHE_MIN_RTT 419
#define VAR_INFRA_CACHE_MAX_RTT 420
#define VAR_INFRA_KEEP_PROBING 421
#define VAR_DNS64_PREFIX 422
#define VAR_DNS64_SYNTHALL 423
#define VAR_DNS64_IGNORE_AAAA 424
#define VAR_NAT64_PREFIX 425
#define VAR_DNSTAP 426
#define VAR_DNSTAP_ENABLE 427
#define VAR_DNSTAP_SOCKET_PATH 428
#define VAR_DNSTAP_IP 429
#define VAR_DNSTAP_TLS 430
#define VAR_DNSTAP_TLS_SERVER_NAME 431
#define VAR_DNSTAP_TLS_CERT_BUNDLE 432
#define VAR_DNSTAP_TLS_CLIENT_KEY_FILE 433
#define VAR_DNSTAP_TLS_CLIENT_CERT_FILE 434
#define VAR_DNSTAP_SEND_IDENTITY 435
#define VAR_DNSTAP_SEND_VERSION 436
#define VAR_DNSTAP_BIDIRECTIONAL 437
#define VAR_DNSTAP_IDENTITY 438
#define VAR_DNSTAP_VERSION 439
#define VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES 440
#define VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES 441
#define VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES 442
#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_QNAME_MINIMISATION 481
#define VAR_QNAME_MINIMISATION_STRICT 482
#define VAR_IP_FREEBIND 483
#define VAR_DEFINE_TAG 484
#define VAR_LOCAL_ZONE_TAG 485
#define VAR_ACCESS_CONTROL_TAG 486
#define VAR_LOCAL_ZONE_OVERRIDE 487
#define VAR_ACCESS_CONTROL_TAG_ACTION 488
#define VAR_ACCESS_CONTROL_TAG_DATA 489
#define VAR_VIEW 490
#define VAR_ACCESS_CONTROL_VIEW 491
#define VAR_VIEW_FIRST 492
#define VAR_SERVE_EXPIRED 493
#define VAR_SERVE_EXPIRED_TTL 494
#define VAR_SERVE_EXPIRED_TTL_RESET 495
#define VAR_SERVE_EXPIRED_REPLY_TTL 496
#define VAR_SERVE_EXPIRED_CLIENT_TIMEOUT 497
#define VAR_EDE_SERVE_EXPIRED 498
#define VAR_SERVE_ORIGINAL_TTL 499
#define VAR_FAKE_DSA 500
#define VAR_FAKE_SHA1 501
#define VAR_LOG_IDENTITY 502
#define VAR_HIDE_TRUSTANCHOR 503
#define VAR_HIDE_HTTP_USER_AGENT 504
#define VAR_HTTP_USER_AGENT 505
#define VAR_TRUST_ANCHOR_SIGNALING 506
#define VAR_AGGRESSIVE_NSEC 507
#define VAR_USE_SYSTEMD 508
#define VAR_SHM_ENABLE 509
#define VAR_SHM_KEY 510
#define VAR_ROOT_KEY_SENTINEL 511
#define VAR_DNSCRYPT 512
#define VAR_DNSCRYPT_ENABLE 513
#define VAR_DNSCRYPT_PORT 514
#define VAR_DNSCRYPT_PROVIDER 515
#define VAR_DNSCRYPT_SECRET_KEY 516
#define VAR_DNSCRYPT_PROVIDER_CERT 517
#define VAR_DNSCRYPT_PROVIDER_CERT_ROTATED 518
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE 519
#define VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS 520
#define VAR_DNSCRYPT_NONCE_CACHE_SIZE 521
#define VAR_DNSCRYPT_NONCE_CACHE_SLABS 522
#define VAR_PAD_RESPONSES 523
#define VAR_PAD_RESPONSES_BLOCK_SIZE 524
#define VAR_PAD_QUERIES 525
#define VAR_PAD_QUERIES_BLOCK_SIZE 526
#define VAR_IPSECMOD_ENABLED 527
#define VAR_IPSECMOD_HOOK 528
#define VAR_IPSECMOD_IGNORE_BOGUS 529
#define VAR_IPSECMOD_MAX_TTL 530
#define VAR_IPSECMOD_WHITELIST 531
#define VAR_IPSECMOD_STRICT 532
#define VAR_CACHEDB 533
#define VAR_CACHEDB_BACKEND 534
#define VAR_CACHEDB_SECRETSEED 535
#define VAR_CACHEDB_REDISHOST 536
#define VAR_CACHEDB_REDISPORT 537
#define VAR_CACHEDB_REDISTIMEOUT 538
#define VAR_CACHEDB_REDISEXPIRERECORDS 539
#define VAR_CACHEDB_REDISPATH 540
#define VAR_CACHEDB_REDISPASSWORD 541
#define VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM 542
#define VAR_FOR_UPSTREAM 543
#define VAR_AUTH_ZONE 544
#define VAR_ZONEFILE 545
#define VAR_MASTER 546
#define VAR_URL 547
#define VAR_FOR_DOWNSTREAM 548
#define VAR_FALLBACK_ENABLED 549
#define VAR_TLS_ADDITIONAL_PORT 550
#define VAR_LOW_RTT 551
#define VAR_LOW_RTT_PERMIL 552
#define VAR_FAST_SERVER_PERMIL 553
#define VAR_FAST_SERVER_NUM 554
#define VAR_ALLOW_NOTIFY 555
#define VAR_TLS_WIN_CERT 556
#define VAR_TCP_CONNECTION_LIMIT 557
#define VAR_ANSWER_COOKIE 558
#define VAR_COOKIE_SECRET 559
#define VAR_IP_RATELIMIT_COOKIE 560
#define VAR_FORWARD_NO_CACHE 561
#define VAR_STUB_NO_CACHE 562
#define VAR_LOG_SERVFAIL 563
#define VAR_DENY_ANY 564
#define VAR_UNKNOWN_SERVER_TIME_LIMIT 565
#define VAR_LOG_TAG_QUERYREPLY 566
#define VAR_STREAM_WAIT_SIZE 567
#define VAR_TLS_CIPHERS 568
#define VAR_TLS_CIPHERSUITES 569
#define VAR_TLS_USE_SNI 570
#define VAR_IPSET 571
#define VAR_IPSET_NAME_V4 572
#define VAR_IPSET_NAME_V6 573
#define VAR_TLS_SESSION_TICKET_KEYS 574
#define VAR_RPZ 575
#define VAR_TAGS 576
#define VAR_RPZ_ACTION_OVERRIDE 577
#define VAR_RPZ_CNAME_OVERRIDE 578
#define VAR_RPZ_LOG 579
#define VAR_RPZ_LOG_NAME 580
#define VAR_DYNLIB 581
#define VAR_DYNLIB_FILE 582
#define VAR_EDNS_CLIENT_STRING 583
#define VAR_EDNS_CLIENT_STRING_OPCODE 584
#define VAR_NSID 585
#define VAR_ZONEMD_PERMISSIVE_MODE 586
#define VAR_ZONEMD_CHECK 587
#define VAR_ZONEMD_REJECT_ABSENCE 588
#define VAR_RPZ_SIGNAL_NXDOMAIN_RA 589
#define VAR_INTERFACE_AUTOMATIC_PORTS 590
#define VAR_EDE 591
#define VAR_INTERFACE_ACTION 592
#define VAR_INTERFACE_VIEW 593
#define VAR_INTERFACE_TAG 594
#define VAR_INTERFACE_TAG_ACTION 595
#define VAR_INTERFACE_TAG_DATA 596
#define VAR_PROXY_PROTOCOL_PORT 597
#define VAR_STATISTICS_INHIBIT_ZERO 598
#define VAR_HARDEN_UNKNOWN_ADDITIONAL 599
#ifndef YYSTYPE_DEFINED
#define YYSTYPE_DEFINED
typedef union {

View File

@ -47,6 +47,7 @@
#include "util/configyyrename.h"
#include "util/config_file.h"
#include "util/net_help.h"
#include "sldns/str2wire.h"
int ub_c_lex(void);
void ub_c_error(const char *message);
@ -73,9 +74,10 @@ extern struct config_parser_state* cfg_parser;
%token VAR_FORCE_TOPLEVEL
%token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT
%token VAR_OUTGOING_RANGE VAR_INTERFACE VAR_PREFER_IP4
%token VAR_DO_IP4 VAR_DO_IP6 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP
%token VAR_DO_IP4 VAR_DO_IP6 VAR_DO_NAT64 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP
%token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS VAR_TCP_IDLE_TIMEOUT
%token VAR_EDNS_TCP_KEEPALIVE VAR_EDNS_TCP_KEEPALIVE_TIMEOUT
%token VAR_SOCK_QUEUE_TIMEOUT
%token VAR_CHROOT VAR_USERNAME VAR_DIRECTORY VAR_LOGFILE VAR_PIDFILE
%token VAR_MSG_CACHE_SIZE VAR_MSG_CACHE_SLABS VAR_NUM_QUERIES_PER_THREAD
%token VAR_RRSET_CACHE_SIZE VAR_RRSET_CACHE_SLABS VAR_OUTGOING_NUM_TCP
@ -123,6 +125,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES
%token VAR_INFRA_CACHE_MIN_RTT VAR_INFRA_CACHE_MAX_RTT VAR_INFRA_KEEP_PROBING
%token VAR_DNS64_PREFIX VAR_DNS64_SYNTHALL VAR_DNS64_IGNORE_AAAA
%token VAR_NAT64_PREFIX
%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH VAR_DNSTAP_IP
%token VAR_DNSTAP_TLS VAR_DNSTAP_TLS_SERVER_NAME VAR_DNSTAP_TLS_CERT_BUNDLE
%token VAR_DNSTAP_TLS_CLIENT_KEY_FILE VAR_DNSTAP_TLS_CLIENT_CERT_FILE
@ -140,7 +143,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DISABLE_DNSSEC_LAME_CHECK
%token VAR_IP_RATELIMIT VAR_IP_RATELIMIT_SLABS VAR_IP_RATELIMIT_SIZE
%token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE
%token VAR_OUTBOUND_MSG_RETRY
%token VAR_OUTBOUND_MSG_RETRY VAR_MAX_SENT_COUNT VAR_MAX_QUERY_RESTARTS
%token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN
%token VAR_IP_RATELIMIT_FACTOR VAR_RATELIMIT_FACTOR
%token VAR_IP_RATELIMIT_BACKOFF VAR_RATELIMIT_BACKOFF
@ -175,12 +178,13 @@ extern struct config_parser_state* cfg_parser;
%token VAR_IPSECMOD_MAX_TTL VAR_IPSECMOD_WHITELIST VAR_IPSECMOD_STRICT
%token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED
%token VAR_CACHEDB_REDISHOST VAR_CACHEDB_REDISPORT VAR_CACHEDB_REDISTIMEOUT
%token VAR_CACHEDB_REDISEXPIRERECORDS
%token VAR_CACHEDB_REDISEXPIRERECORDS VAR_CACHEDB_REDISPATH VAR_CACHEDB_REDISPASSWORD
%token VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM VAR_FOR_UPSTREAM
%token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM
%token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL
%token VAR_FAST_SERVER_PERMIL VAR_FAST_SERVER_NUM
%token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT VAR_TCP_CONNECTION_LIMIT
%token VAR_ANSWER_COOKIE VAR_COOKIE_SECRET VAR_IP_RATELIMIT_COOKIE
%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL VAR_DENY_ANY
%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY
%token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES VAR_TLS_USE_SNI
@ -193,7 +197,8 @@ extern struct config_parser_state* cfg_parser;
%token VAR_RPZ_SIGNAL_NXDOMAIN_RA VAR_INTERFACE_AUTOMATIC_PORTS VAR_EDE
%token VAR_INTERFACE_ACTION VAR_INTERFACE_VIEW VAR_INTERFACE_TAG
%token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA
%token VAR_PROXY_PROTOCOL_PORT
%token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO
%token VAR_HARDEN_UNKNOWN_ADDITIONAL
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@ -222,10 +227,11 @@ contents_server: contents_server content_server
| ;
content_server: server_num_threads | server_verbosity | server_port |
server_outgoing_range | server_do_ip4 |
server_do_ip6 | server_prefer_ip4 | server_prefer_ip6 |
server_do_udp | server_do_tcp |
server_do_ip6 | server_do_nat64 | server_prefer_ip4 |
server_prefer_ip6 | server_do_udp | server_do_tcp |
server_tcp_mss | server_outgoing_tcp_mss | server_tcp_idle_timeout |
server_tcp_keepalive | server_tcp_keepalive_timeout |
server_sock_queue_timeout |
server_interface | server_chroot | server_username |
server_directory | server_logfile | server_pidfile |
server_msg_cache_size | server_msg_cache_slabs |
@ -273,6 +279,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_so_reuseport | server_delay_close | server_udp_connect |
server_unblock_lan_zones | server_insecure_lan_zones |
server_dns64_prefix | server_dns64_synthall | server_dns64_ignore_aaaa |
server_nat64_prefix |
server_infra_cache_min_rtt | server_infra_cache_max_rtt | server_harden_algo_downgrade |
server_ip_transparent | server_ip_ratelimit | server_ratelimit |
server_ip_dscp | server_infra_keep_probing |
@ -282,6 +289,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_ratelimit_below_domain | server_ratelimit_factor |
server_ip_ratelimit_factor | server_ratelimit_backoff |
server_ip_ratelimit_backoff | server_outbound_msg_retry |
server_max_sent_count | server_max_query_restarts |
server_send_client_subnet | server_client_subnet_zone |
server_client_subnet_always_forward | server_client_subnet_opcode |
server_max_client_subnet_ipv4 | server_max_client_subnet_ipv6 |
@ -301,7 +309,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_serve_expired |
server_serve_expired_ttl | server_serve_expired_ttl_reset |
server_serve_expired_reply_ttl | server_serve_expired_client_timeout |
server_ede_serve_expired | server_serve_original_ttl | server_fake_dsa |
server_ede_serve_expired | server_serve_original_ttl | server_fake_dsa |
server_log_identity | server_use_systemd |
server_response_ip_tag | server_response_ip | server_response_ip_data |
server_shm_enable | server_shm_key | server_fake_sha1 |
@ -317,12 +325,14 @@ content_server: server_num_threads | server_verbosity | server_port |
server_unknown_server_time_limit | server_log_tag_queryreply |
server_stream_wait_size | server_tls_ciphers |
server_tls_ciphersuites | server_tls_session_ticket_keys |
server_answer_cookie | server_cookie_secret | server_ip_ratelimit_cookie |
server_tls_use_sni | server_edns_client_string |
server_edns_client_string_opcode | server_nsid |
server_zonemd_permissive_mode | server_max_reuse_tcp_queries |
server_tcp_reuse_timeout | server_tcp_auth_query_timeout |
server_interface_automatic_ports | server_ede |
server_proxy_protocol_port
server_proxy_protocol_port | server_statistics_inhibit_zero |
server_harden_unknown_additional
;
stubstart: VAR_STUB_ZONE
{
@ -485,7 +495,7 @@ rpz_signal_nxdomain_ra: VAR_RPZ_SIGNAL_NXDOMAIN_RA STRING_ARG
rpzstart: VAR_RPZ
{
struct config_auth* s;
OUTYY(("\nP(rpz:)\n"));
OUTYY(("\nP(rpz:)\n"));
cfg_parser->started_toplevel = 1;
s = (struct config_auth*)calloc(1, sizeof(struct config_auth));
if(s) {
@ -501,7 +511,7 @@ rpzstart: VAR_RPZ
}
}
;
contents_rpz: contents_rpz content_rpz
contents_rpz: contents_rpz content_rpz
| ;
content_rpz: auth_name | auth_zonefile | rpz_tag | auth_master | auth_url |
auth_allow_notify | rpz_action_override | rpz_cname_override |
@ -554,6 +564,15 @@ server_extended_statistics: VAR_EXTENDED_STATISTICS STRING_ARG
free($2);
}
;
server_statistics_inhibit_zero: VAR_STATISTICS_INHIBIT_ZERO STRING_ARG
{
OUTYY(("P(server_statistics_inhibit_zero:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->stat_inhibit_zero = (strcmp($2, "yes")==0);
free($2);
}
;
server_shm_enable: VAR_SHM_ENABLE STRING_ARG
{
OUTYY(("P(server_shm_enable:%s)\n", $2));
@ -840,6 +859,15 @@ server_do_ip6: VAR_DO_IP6 STRING_ARG
free($2);
}
;
server_do_nat64: VAR_DO_NAT64 STRING_ARG
{
OUTYY(("P(server_do_nat64:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->do_nat64 = (strcmp($2, "yes")==0);
free($2);
}
;
server_do_udp: VAR_DO_UDP STRING_ARG
{
OUTYY(("P(server_do_udp:%s)\n", $2));
@ -962,6 +990,19 @@ server_tcp_keepalive_timeout: VAR_EDNS_TCP_KEEPALIVE_TIMEOUT STRING_ARG
free($2);
}
;
server_sock_queue_timeout: VAR_SOCK_QUEUE_TIMEOUT STRING_ARG
{
OUTYY(("P(server_sock_queue_timeout:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else if (atoi($2) > 6553500)
cfg_parser->cfg->sock_queue_timeout = 6553500;
else if (atoi($2) < 1)
cfg_parser->cfg->sock_queue_timeout = 0;
else cfg_parser->cfg->sock_queue_timeout = atoi($2);
free($2);
}
;
server_tcp_upstream: VAR_TCP_UPSTREAM STRING_ARG
{
OUTYY(("P(server_tcp_upstream:%s)\n", $2));
@ -1122,7 +1163,7 @@ server_http_nodelay: VAR_HTTP_NODELAY STRING_ARG
yyerror("expected yes or no.");
else cfg_parser->cfg->http_nodelay = (strcmp($2, "yes")==0);
free($2);
}
};
server_http_notls_downstream: VAR_HTTP_NOTLS_DOWNSTREAM STRING_ARG
{
OUTYY(("P(server_http_notls_downstream:%s)\n", $2));
@ -1768,6 +1809,16 @@ server_harden_algo_downgrade: VAR_HARDEN_ALGO_DOWNGRADE STRING_ARG
free($2);
}
;
server_harden_unknown_additional: VAR_HARDEN_UNKNOWN_ADDITIONAL STRING_ARG
{
OUTYY(("P(server_harden_unknown_additional:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->harden_unknown_additional =
(strcmp($2, "yes")==0);
free($2);
}
;
server_use_caps_for_id: VAR_USE_CAPS_FOR_ID STRING_ARG
{
OUTYY(("P(server_use_caps_for_id:%s)\n", $2));
@ -2159,6 +2210,7 @@ server_permit_small_holddown: VAR_PERMIT_SMALL_HOLDDOWN STRING_ARG
(strcmp($2, "yes")==0);
free($2);
}
;
server_key_cache_size: VAR_KEY_CACHE_SIZE STRING_ARG
{
OUTYY(("P(server_key_cache_size:%s)\n", $2));
@ -2196,6 +2248,7 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
strcmp($3, "transparent")!=0 && strcmp($3, "nodefault")!=0
&& strcmp($3, "typetransparent")!=0
&& strcmp($3, "always_transparent")!=0
&& strcmp($3, "block_a")!=0
&& strcmp($3, "always_refuse")!=0
&& strcmp($3, "always_nxdomain")!=0
&& strcmp($3, "always_nodata")!=0
@ -2208,7 +2261,7 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG
yyerror("local-zone type: expected static, deny, "
"refuse, redirect, transparent, "
"typetransparent, inform, inform_deny, "
"inform_redirect, always_transparent, "
"inform_redirect, always_transparent, block_a,"
"always_refuse, always_nxdomain, "
"always_nodata, always_deny, always_null, "
"noview, nodefault or ipset");
@ -2323,6 +2376,13 @@ server_dns64_ignore_aaaa: VAR_DNS64_IGNORE_AAAA STRING_ARG
fatal_exit("out of memory adding dns64-ignore-aaaa");
}
;
server_nat64_prefix: VAR_NAT64_PREFIX STRING_ARG
{
OUTYY(("P(nat64_prefix:%s)\n", $2));
free(cfg_parser->cfg->nat64_prefix);
cfg_parser->cfg->nat64_prefix = $2;
}
;
server_define_tag: VAR_DEFINE_TAG STRING_ARG
{
char* p, *s = $2;
@ -2508,6 +2568,15 @@ server_ip_ratelimit: VAR_IP_RATELIMIT STRING_ARG
free($2);
}
;
server_ip_ratelimit_cookie: VAR_IP_RATELIMIT_COOKIE STRING_ARG
{
OUTYY(("P(server_ip_ratelimit_cookie:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else cfg_parser->cfg->ip_ratelimit_cookie = atoi($2);
free($2);
}
;
server_ratelimit: VAR_RATELIMIT STRING_ARG
{
OUTYY(("P(server_ratelimit:%s)\n", $2));
@ -2636,6 +2705,24 @@ server_outbound_msg_retry: VAR_OUTBOUND_MSG_RETRY STRING_ARG
free($2);
}
;
server_max_sent_count: VAR_MAX_SENT_COUNT STRING_ARG
{
OUTYY(("P(server_max_sent_count:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else cfg_parser->cfg->max_sent_count = atoi($2);
free($2);
}
;
server_max_query_restarts: VAR_MAX_QUERY_RESTARTS STRING_ARG
{
OUTYY(("P(server_max_query_restarts:%s)\n", $2));
if(atoi($2) == 0 && strcmp($2, "0") != 0)
yyerror("number expected");
else cfg_parser->cfg->max_query_restarts = atoi($2);
free($2);
}
;
server_low_rtt: VAR_LOW_RTT STRING_ARG
{
OUTYY(("P(low-rtt option is deprecated, use fast-server-num instead)\n"));
@ -2685,7 +2772,7 @@ server_pad_responses: VAR_PAD_RESPONSES STRING_ARG
OUTYY(("P(server_pad_responses:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->pad_responses =
else cfg_parser->cfg->pad_responses =
(strcmp($2, "yes")==0);
free($2);
}
@ -2704,7 +2791,7 @@ server_pad_queries: VAR_PAD_QUERIES STRING_ARG
OUTYY(("P(server_pad_queries:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->pad_queries =
else cfg_parser->cfg->pad_queries =
(strcmp($2, "yes")==0);
free($2);
}
@ -3443,9 +3530,10 @@ py_script: VAR_PYTHON_SCRIPT STRING_ARG
if(!cfg_strlist_append_ex(&cfg_parser->cfg->python_script, $2))
yyerror("out of memory");
}
;
dynlibstart: VAR_DYNLIB
{
OUTYY(("\nP(dynlib:)\n"));
{
OUTYY(("\nP(dynlib:)\n"));
cfg_parser->started_toplevel = 1;
}
;
@ -3459,6 +3547,7 @@ dl_file: VAR_DYNLIB_FILE STRING_ARG
if(!cfg_strlist_append_ex(&cfg_parser->cfg->dynlib_file, $2))
yyerror("out of memory");
}
;
server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
{
OUTYY(("P(disable_dnssec_lame_check:%s)\n", $2));
@ -3519,7 +3608,6 @@ dnsc_dnscrypt_enable: VAR_DNSCRYPT_ENABLE STRING_ARG
free($2);
}
;
dnsc_dnscrypt_port: VAR_DNSCRYPT_PORT STRING_ARG
{
OUTYY(("P(dnsc_dnscrypt_port:%s)\n", $2));
@ -3613,7 +3701,7 @@ contents_cachedb: contents_cachedb content_cachedb
| ;
content_cachedb: cachedb_backend_name | cachedb_secret_seed |
redis_server_host | redis_server_port | redis_timeout |
redis_expire_records
redis_expire_records | redis_server_path | redis_server_password
;
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
{
@ -3666,6 +3754,30 @@ redis_server_port: VAR_CACHEDB_REDISPORT STRING_ARG
free($2);
}
;
redis_server_path: VAR_CACHEDB_REDISPATH STRING_ARG
{
#if defined(USE_CACHEDB) && defined(USE_REDIS)
OUTYY(("P(redis_server_path:%s)\n", $2));
free(cfg_parser->cfg->redis_server_path);
cfg_parser->cfg->redis_server_path = $2;
#else
OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
free($2);
#endif
}
;
redis_server_password: VAR_CACHEDB_REDISPASSWORD STRING_ARG
{
#if defined(USE_CACHEDB) && defined(USE_REDIS)
OUTYY(("P(redis_server_password:%s)\n", $2));
free(cfg_parser->cfg->redis_server_password);
cfg_parser->cfg->redis_server_password = $2;
#else
OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
free($2);
#endif
}
;
redis_timeout: VAR_CACHEDB_REDISTIMEOUT STRING_ARG
{
#if defined(USE_CACHEDB) && defined(USE_REDIS)
@ -3703,6 +3815,31 @@ server_tcp_connection_limit: VAR_TCP_CONNECTION_LIMIT STRING_ARG STRING_ARG
}
}
;
server_answer_cookie: VAR_ANSWER_COOKIE STRING_ARG
{
OUTYY(("P(server_answer_cookie:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->do_answer_cookie = (strcmp($2, "yes")==0);
free($2);
}
;
server_cookie_secret: VAR_COOKIE_SECRET STRING_ARG
{
uint8_t secret[32];
size_t secret_len = sizeof(secret);
OUTYY(("P(server_cookie_secret:%s)\n", $2));
if(sldns_str2wire_hex_buf($2, secret, &secret_len)
|| (secret_len != 16))
yyerror("expected 128 bit hex string");
else {
cfg_parser->cfg->cookie_secret_len = secret_len;
memcpy(cfg_parser->cfg->cookie_secret, secret, sizeof(secret));
}
free($2);
}
;
ipsetstart: VAR_IPSET
{
OUTYY(("\nP(ipset:)\n"));
@ -3772,10 +3909,11 @@ validate_acl_action(const char* action)
strcmp(action, "refuse_non_local")!=0 &&
strcmp(action, "allow_setrd")!=0 &&
strcmp(action, "allow")!=0 &&
strcmp(action, "allow_snoop")!=0)
strcmp(action, "allow_snoop")!=0 &&
strcmp(action, "allow_cookie")!=0)
{
yyerror("expected deny, refuse, deny_non_local, "
"refuse_non_local, allow, allow_setrd or "
"allow_snoop as access control action");
"refuse_non_local, allow, allow_setrd, "
"allow_snoop or allow_cookie as access control action");
}
}

View File

@ -806,6 +806,95 @@ calc_edns_field_size(struct edns_data* edns)
return 1 + 2 + 2 + 4 + 2 + rdatalen;
}
uint16_t
calc_edns_option_size(struct edns_data* edns, uint16_t code)
{
size_t rdatalen = 0;
struct edns_option* opt;
if(!edns || !edns->edns_present)
return 0;
for(opt = edns->opt_list_inplace_cb_out; opt; opt = opt->next) {
if(opt->opt_code == code)
rdatalen += 4 + opt->opt_len;
}
for(opt = edns->opt_list_out; opt; opt = opt->next) {
if(opt->opt_code == code)
rdatalen += 4 + opt->opt_len;
}
return rdatalen;
}
uint16_t
calc_ede_option_size(struct edns_data* edns, uint16_t* txt_size)
{
size_t rdatalen = 0;
struct edns_option* opt;
*txt_size = 0;
if(!edns || !edns->edns_present)
return 0;
for(opt = edns->opt_list_inplace_cb_out; opt; opt = opt->next) {
if(opt->opt_code == LDNS_EDNS_EDE) {
rdatalen += 4 + opt->opt_len;
if(opt->opt_len > 2) *txt_size += opt->opt_len - 2;
if(opt->opt_len >= 2 && sldns_read_uint16(
opt->opt_data) == LDNS_EDE_OTHER) {
*txt_size += 4 + 2;
}
}
}
for(opt = edns->opt_list_out; opt; opt = opt->next) {
if(opt->opt_code == LDNS_EDNS_EDE) {
rdatalen += 4 + opt->opt_len;
if(opt->opt_len > 2) *txt_size += opt->opt_len - 2;
if(opt->opt_len >= 2 && sldns_read_uint16(
opt->opt_data) == LDNS_EDE_OTHER) {
*txt_size += 4 + 2;
}
}
}
return rdatalen;
}
/* Trims the EDE OPTION-DATA to not include any EXTRA-TEXT data.
* Also removes any LDNS_EDE_OTHER options from the list since they are useless
* without the extra text. */
static void
ede_trim_text(struct edns_option** list)
{
struct edns_option* curr, *prev = NULL;
if(!list || !(*list)) return;
/* Unlink and repoint if LDNS_EDE_OTHER are first in list */
while(list && *list && (*list)->opt_code == LDNS_EDNS_EDE
&& (*list)->opt_len >= 2
&& sldns_read_uint16((*list)->opt_data) == LDNS_EDE_OTHER ) {
*list = (*list)->next;
}
if(!list || !(*list)) return;
curr = *list;
while(curr) {
if(curr->opt_code == LDNS_EDNS_EDE) {
if(curr->opt_len >= 2 && sldns_read_uint16(
curr->opt_data) == LDNS_EDE_OTHER) {
/* LDNS_EDE_OTHER cannot be the first option in
* this while, so prev is always initialized at
* this point from the other branches;
* cut this option off */
prev->next = curr->next;
curr = curr->next;
} else if(curr->opt_len > 2) {
/* trim this option's EXTRA-TEXT */
curr->opt_len = 2;
prev = curr;
curr = curr->next;
}
} else {
/* continue */
prev = curr;
curr = curr->next;
}
}
}
static void
attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns,
uint16_t max_msg_sz)
@ -894,6 +983,7 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
{
uint16_t flags;
unsigned int attach_edns = 0;
uint16_t edns_field_size, ede_size, ede_txt_size;
if(!cached || rep->authoritative) {
/* original flags, copy RD and CD bits from query. */
@ -916,25 +1006,39 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
log_assert(flags & BIT_QR); /* QR bit must be on in our replies */
if(udpsize < LDNS_HEADER_SIZE)
return 0;
/* currently edns does not change during calculations;
* calculate sizes once here */
edns_field_size = calc_edns_field_size(edns);
ede_size = calc_ede_option_size(edns, &ede_txt_size);
if(sldns_buffer_capacity(pkt) < udpsize)
udpsize = sldns_buffer_capacity(pkt);
if(udpsize < LDNS_HEADER_SIZE + calc_edns_field_size(edns)) {
/* EDEs are optional, try to fit anything else before them */
if(udpsize < LDNS_HEADER_SIZE + edns_field_size - ede_size) {
/* packet too small to contain edns, omit it. */
attach_edns = 0;
} else {
/* reserve space for edns record */
attach_edns = (unsigned int)calc_edns_field_size(edns);
udpsize -= attach_edns;
attach_edns = (unsigned int)edns_field_size - ede_size;
}
if(!reply_info_encode(qinf, rep, id, flags, pkt, timenow, region,
udpsize, dnssec, MINIMAL_RESPONSES)) {
udpsize - attach_edns, dnssec, MINIMAL_RESPONSES)) {
log_err("reply encode: out of memory");
return 0;
}
if(attach_edns && sldns_buffer_capacity(pkt) >=
sldns_buffer_limit(pkt)+attach_edns)
attach_edns_record_max_msg_sz(pkt, edns, udpsize+attach_edns);
if(attach_edns) {
if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size)
attach_edns_record_max_msg_sz(pkt, edns, udpsize);
else if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_txt_size) {
ede_trim_text(&edns->opt_list_inplace_cb_out);
ede_trim_text(&edns->opt_list_out);
attach_edns_record_max_msg_sz(pkt, edns, udpsize);
} else if(udpsize >= sldns_buffer_limit(pkt) + edns_field_size - ede_size) {
edns_opt_list_remove(&edns->opt_list_inplace_cb_out, LDNS_EDNS_EDE);
edns_opt_list_remove(&edns->opt_list_out, LDNS_EDNS_EDE);
attach_edns_record_max_msg_sz(pkt, edns, udpsize);
}
}
return 1;
}
@ -958,15 +1062,17 @@ qinfo_query_encode(sldns_buffer* pkt, struct query_info* qinfo)
sldns_buffer_flip(pkt);
}
void
error_encode(sldns_buffer* buf, int r, struct query_info* qinfo,
uint16_t qid, uint16_t qflags, struct edns_data* edns)
void
extended_error_encode(sldns_buffer* buf, uint16_t rcode,
struct query_info* qinfo, uint16_t qid, uint16_t qflags,
uint16_t xflags, struct edns_data* edns)
{
uint16_t flags;
sldns_buffer_clear(buf);
sldns_buffer_write(buf, &qid, sizeof(uint16_t));
flags = (uint16_t)(BIT_QR | BIT_RA | r); /* QR and retcode*/
flags = (uint16_t)(BIT_QR | BIT_RA | (rcode & 0xF)); /* QR and retcode*/
flags |= xflags;
flags |= (qflags & (BIT_RD|BIT_CD)); /* copy RD and CD bit */
sldns_buffer_write_u16(buf, flags);
if(qinfo) flags = 1;
@ -993,11 +1099,25 @@ error_encode(sldns_buffer* buf, int r, struct query_info* qinfo,
struct edns_data es = *edns;
es.edns_version = EDNS_ADVERTISED_VERSION;
es.udp_size = EDNS_ADVERTISED_SIZE;
es.ext_rcode = 0;
es.ext_rcode = (uint8_t)(rcode >> 4);
es.bits &= EDNS_DO;
if(sldns_buffer_limit(buf) + calc_edns_field_size(&es) >
edns->udp_size)
return;
edns->udp_size) {
edns_opt_list_remove(&es.opt_list_inplace_cb_out, LDNS_EDNS_EDE);
edns_opt_list_remove(&es.opt_list_out, LDNS_EDNS_EDE);
if(sldns_buffer_limit(buf) + calc_edns_field_size(&es) >
edns->udp_size) {
return;
}
}
attach_edns_record(buf, &es);
}
}
void
error_encode(sldns_buffer* buf, int r, struct query_info* qinfo,
uint16_t qid, uint16_t qflags, struct edns_data* edns)
{
extended_error_encode(buf, (r & 0x000F), qinfo, qid, qflags,
(r & 0xFFF0), edns);
}

View File

@ -108,6 +108,27 @@ void qinfo_query_encode(struct sldns_buffer* pkt, struct query_info* qinfo);
*/
uint16_t calc_edns_field_size(struct edns_data* edns);
/**
* Calculate the size of a specific EDNS option in packet.
* @param edns: edns data or NULL.
* @param code: the opt code to get the size of.
* @return octets the option will take up.
*/
uint16_t calc_edns_option_size(struct edns_data* edns, uint16_t code);
/**
* Calculate the size of the EDE option(s) in packet. Also calculate seperately
* the size of the EXTRA-TEXT field(s) in case we can trim them to fit.
* In this case include any LDNS_EDE_OTHER options in their entirety since they
* are useless without extra text.
* @param edns: edns data or NULL.
* @param txt_size: the size of the EXTRA-TEXT field(s); this includes
* LDNS_EDE_OTHER in their entirety since they are useless without
* extra text.
* @return octets the option will take up.
*/
uint16_t calc_ede_option_size(struct edns_data* edns, uint16_t* txt_size);
/**
* Attach EDNS record to buffer. Buffer has complete packet. There must
* be enough room left for the EDNS record.
@ -116,11 +137,11 @@ uint16_t calc_edns_field_size(struct edns_data* edns);
*/
void attach_edns_record(struct sldns_buffer* pkt, struct edns_data* edns);
/**
/**
* Encode an error. With QR and RA set.
*
* @param pkt: where to store the packet.
* @param r: RCODE value to encode.
* @param r: RCODE value to encode (may contain extra flags).
* @param qinfo: if not NULL, the query is included.
* @param qid: query ID to set in packet. network order.
* @param qflags: original query flags (to copy RD and CD bits). host order.
@ -130,4 +151,21 @@ void attach_edns_record(struct sldns_buffer* pkt, struct edns_data* edns);
void error_encode(struct sldns_buffer* pkt, int r, struct query_info* qinfo,
uint16_t qid, uint16_t qflags, struct edns_data* edns);
/**
* Encode an extended error. With QR and RA set.
*
* @param pkt: where to store the packet.
* @param rcode: Extended RCODE value to encode.
* @param qinfo: if not NULL, the query is included.
* @param qid: query ID to set in packet. network order.
* @param qflags: original query flags (to copy RD and CD bits). host order.
* @param xflags: extra flags to set (such as for example BIT_AA and/or BIT_TC)
* @param edns: if not NULL, this is the query edns info,
* and an edns reply is attached. Only attached if EDNS record fits reply.
* Without edns extended errors (i.e. > 15) will not be conveyed.
*/
void extended_error_encode(struct sldns_buffer* pkt, uint16_t rcode,
struct query_info* qinfo, uint16_t qid, uint16_t qflags,
uint16_t xflags, struct edns_data* edns);
#endif /* UTIL_DATA_MSGENCODE_H */

View File

@ -45,6 +45,8 @@
#include "util/netevent.h"
#include "util/storage/lookup3.h"
#include "util/regional.h"
#include "util/rfc_1982.h"
#include "util/edns.h"
#include "sldns/rrdef.h"
#include "sldns/sbuffer.h"
#include "sldns/parseutil.h"
@ -940,22 +942,11 @@ parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region)
return 0;
}
static int
edns_opt_list_append_keepalive(struct edns_option** list, int msec,
struct regional* region)
{
uint8_t data[2]; /* For keepalive value */
data[0] = (uint8_t)((msec >> 8) & 0xff);
data[1] = (uint8_t)(msec & 0xff);
return edns_opt_list_append(list, LDNS_EDNS_KEEPALIVE, sizeof(data),
data, region);
}
/** parse EDNS options from EDNS wireformat rdata */
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 regional* region)
struct comm_reply* repinfo, uint32_t now, struct regional* region)
{
/* To respond with a Keepalive option, the client connection must have
* received one message with a TCP Keepalive EDNS option, and that
@ -979,6 +970,10 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
while(rdata_len >= 4) {
uint16_t opt_code = sldns_read_uint16(rdata_ptr);
uint16_t opt_len = sldns_read_uint16(rdata_ptr+2);
uint8_t server_cookie[40];
enum edns_cookie_val_status cookie_val_status;
int cookie_is_v4 = 1;
rdata_ptr += 4;
rdata_len -= 4;
if(opt_len > rdata_len)
@ -1041,6 +1036,76 @@ parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len,
edns->padding_block_size = cfg->pad_responses_block_size;
break;
case LDNS_EDNS_COOKIE:
if(!cfg || !cfg->do_answer_cookie || !repinfo)
break;
if(opt_len != 8 && (opt_len < 16 || opt_len > 40)) {
verbose(VERB_ALGO, "worker request: "
"badly formatted cookie");
return LDNS_RCODE_FORMERR;
}
edns->cookie_present = 1;
/* Copy client cookie, version and timestamp for
* validation and creation purposes.
*/
if(opt_len >= 16) {
memmove(server_cookie, rdata_ptr, 16);
} else {
memset(server_cookie, 0, 16);
memmove(server_cookie, rdata_ptr, opt_len);
}
/* Copy client ip for validation and creation
* purposes. It will be overwritten if (re)creation
* is needed.
*/
if(repinfo->remote_addr.ss_family == AF_INET) {
memcpy(server_cookie + 16,
&((struct sockaddr_in*)&repinfo->remote_addr)->sin_addr, 4);
} else {
cookie_is_v4 = 0;
memcpy(server_cookie + 16,
&((struct sockaddr_in6*)&repinfo->remote_addr)->sin6_addr, 16);
}
cookie_val_status = edns_cookie_server_validate(
rdata_ptr, opt_len, cfg->cookie_secret,
cfg->cookie_secret_len, cookie_is_v4,
server_cookie, now);
switch(cookie_val_status) {
case COOKIE_STATUS_VALID:
case COOKIE_STATUS_VALID_RENEW:
edns->cookie_valid = 1;
/* Reuse cookie */
if(!edns_opt_list_append(
&edns->opt_list_out, LDNS_EDNS_COOKIE,
opt_len, rdata_ptr, region)) {
log_err("out of memory");
return LDNS_RCODE_SERVFAIL;
}
/* Cookie to be reused added to outgoing
* options. Done!
*/
break;
case COOKIE_STATUS_CLIENT_ONLY:
edns->cookie_client = 1;
/* fallthrough */
case COOKIE_STATUS_FUTURE:
case COOKIE_STATUS_EXPIRED:
case COOKIE_STATUS_INVALID:
default:
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)) {
log_err("out of memory");
return LDNS_RCODE_SERVFAIL;
}
break;
}
break;
default:
break;
}
@ -1115,6 +1180,8 @@ parse_extract_edns_from_response_msg(struct msg_parse* msg,
edns->opt_list_out = NULL;
edns->opt_list_inplace_cb_out = NULL;
edns->padding_block_size = 0;
edns->cookie_present = 0;
edns->cookie_valid = 0;
/* take the options */
rdata_len = found->rr_first->size-2;
@ -1170,7 +1237,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 regional* region)
struct config_file* cfg, struct comm_point* c,
struct comm_reply* repinfo, time_t now, struct regional* region)
{
size_t rdata_len;
uint8_t* rdata_ptr;
@ -1206,6 +1274,8 @@ parse_edns_from_query_pkt(sldns_buffer* pkt, struct edns_data* edns,
edns->opt_list_out = NULL;
edns->opt_list_inplace_cb_out = NULL;
edns->padding_block_size = 0;
edns->cookie_present = 0;
edns->cookie_valid = 0;
/* take the options */
rdata_len = sldns_buffer_read_u16(pkt);
@ -1214,7 +1284,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, region);
c, repinfo, now, region);
}
void

View File

@ -72,6 +72,7 @@ struct regional;
struct edns_option;
struct config_file;
struct comm_point;
struct comm_reply;
/** number of buckets in parse rrset hash table. Must be power of 2. */
#define PARSE_TABLE_SIZE 32
@ -217,8 +218,6 @@ struct rr_parse {
* region.
*/
struct edns_data {
/** if EDNS OPT record was present */
int edns_present;
/** Extended RCODE */
uint8_t ext_rcode;
/** The EDNS version number */
@ -238,7 +237,15 @@ struct edns_data {
struct edns_option* opt_list_inplace_cb_out;
/** block size to pad */
uint16_t padding_block_size;
};
/** if EDNS OPT record was present */
unsigned int edns_present : 1;
/** if a cookie was present */
unsigned int cookie_present : 1;
/** if the cookie validated */
unsigned int cookie_valid : 1;
/** if the cookie holds only the client part */
unsigned int cookie_client : 1;
};
/**
* EDNS option
@ -310,12 +317,15 @@ int skip_pkt_rrs(struct sldns_buffer* pkt, int num);
* initialised.
* @param cfg: the configuration (with nsid value etc.)
* @param c: commpoint to determine transport (if needed)
* @param repinfo: commreply to determine the client address
* @param now: current time
* @param region: region to alloc results in (edns option contents)
* @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 regional* region);
struct config_file* cfg, struct comm_point* c,
struct comm_reply* repinfo, time_t now, struct regional* region);
/**
* Calculate hash value for rrset in packet.

View File

@ -94,7 +94,7 @@ parse_create_qinfo(sldns_buffer* pkt, struct msg_parse* msg,
struct reply_info*
construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd,
time_t ttl, time_t prettl, time_t expttl, size_t an, size_t ns,
size_t ar, size_t total, enum sec_status sec)
size_t ar, size_t total, enum sec_status sec, sldns_ede_code reason_bogus)
{
struct reply_info* rep;
/* rrset_count-1 because the first ref is part of the struct. */
@ -117,7 +117,9 @@ construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd,
rep->ar_numrrsets = ar;
rep->rrset_count = total;
rep->security = sec;
rep->reason_bogus = LDNS_EDE_NONE;
rep->reason_bogus = reason_bogus;
/* this is only allocated and used for caching on copy */
rep->reason_bogus_str = NULL;
rep->authoritative = 0;
/* array starts after the refs */
if(region)
@ -137,7 +139,7 @@ parse_create_repinfo(struct msg_parse* msg, struct reply_info** rep,
{
*rep = construct_reply_info_base(region, msg->flags, msg->qdcount, 0,
0, 0, msg->an_rrsets, msg->ns_rrsets, msg->ar_rrsets,
msg->rrset_count, sec_status_unchecked);
msg->rrset_count, sec_status_unchecked, LDNS_EDE_NONE);
if(!*rep)
return 0;
return 1;
@ -182,7 +184,7 @@ make_new_reply_info(const struct reply_info* rep, struct regional* region,
new_rep = construct_reply_info_base(region, rep->flags,
rep->qdcount, rep->ttl, rep->prefetch_ttl,
rep->serve_expired_ttl, an_numrrsets, 0, 0, an_numrrsets,
sec_status_insecure);
sec_status_insecure, LDNS_EDE_NONE);
if(!new_rep)
return NULL;
if(!reply_info_alloc_rrset_keys(new_rep, NULL, region))
@ -580,6 +582,10 @@ reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc)
for(i=0; i<rep->rrset_count; i++) {
ub_packed_rrset_parsedelete(rep->rrsets[i], alloc);
}
if(rep->reason_bogus_str) {
free(rep->reason_bogus_str);
rep->reason_bogus_str = NULL;
}
free(rep);
}
@ -661,6 +667,10 @@ void
reply_info_delete(void* d, void* ATTR_UNUSED(arg))
{
struct reply_info* r = (struct reply_info*)d;
if(r->reason_bogus_str) {
free(r->reason_bogus_str);
r->reason_bogus_str = NULL;
}
free(r);
}
@ -737,17 +747,36 @@ repinfo_copy_rrsets(struct reply_info* dest, struct reply_info* from,
return 1;
}
struct reply_info*
reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc,
struct reply_info*
reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc,
struct regional* region)
{
struct reply_info* cp;
cp = construct_reply_info_base(region, rep->flags, rep->qdcount,
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
cp = construct_reply_info_base(region, rep->flags, rep->qdcount,
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
rep->rrset_count, rep->security);
rep->rrset_count, rep->security, rep->reason_bogus);
if(!cp)
return NULL;
if(rep->reason_bogus_str && *rep->reason_bogus_str != 0) {
if(region) {
cp->reason_bogus_str = (char*)regional_alloc(region,
sizeof(char)
* (strlen(rep->reason_bogus_str)+1));
} else {
cp->reason_bogus_str = malloc(sizeof(char)
* (strlen(rep->reason_bogus_str)+1));
}
if(!cp->reason_bogus_str) {
if(!region)
reply_info_parsedelete(cp, alloc);
return NULL;
}
memcpy(cp->reason_bogus_str, rep->reason_bogus_str,
strlen(rep->reason_bogus_str)+1);
}
/* allocate ub_key structures special or not */
if(!reply_info_alloc_rrset_keys(cp, alloc, region)) {
if(!region)
@ -1020,6 +1049,16 @@ int edns_opt_list_append_ede(struct edns_option** list, struct regional* region,
return 1;
}
int edns_opt_list_append_keepalive(struct edns_option** list, int msec,
struct regional* region)
{
uint8_t data[2]; /* For keepalive value */
data[0] = (uint8_t)((msec >> 8) & 0xff);
data[1] = (uint8_t)(msec & 0xff);
return edns_opt_list_append(list, LDNS_EDNS_KEEPALIVE, sizeof(data),
data, region);
}
int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
uint8_t* data, struct regional* region)
{
@ -1195,7 +1234,7 @@ int inplace_cb_query_response_call(struct module_env* env,
}
struct edns_option* edns_opt_copy_region(struct edns_option* list,
struct regional* region)
struct regional* region)
{
struct edns_option* result = NULL, *cur = NULL, *s;
while(list) {
@ -1224,6 +1263,42 @@ struct edns_option* edns_opt_copy_region(struct edns_option* list,
return result;
}
struct edns_option* edns_opt_copy_filter_region(struct edns_option* list,
uint16_t* filter_list, size_t filter_list_len, struct regional* region)
{
struct edns_option* result = NULL, *cur = NULL, *s;
size_t i;
while(list) {
for(i=0; i<filter_list_len; i++)
if(filter_list[i] == list->opt_code) goto found;
if(i == filter_list_len) goto next;
found:
/* copy edns option structure */
s = regional_alloc_init(region, list, sizeof(*list));
if(!s) return NULL;
s->next = NULL;
/* copy option data */
if(s->opt_data) {
s->opt_data = regional_alloc_init(region, s->opt_data,
s->opt_len);
if(!s->opt_data)
return NULL;
}
/* link into list */
if(cur)
cur->next = s;
else result = s;
cur = s;
next:
/* examine next element */
list = list->next;
}
return result;
}
int edns_opt_compare(struct edns_option* p, struct edns_option* q)
{
if(!p && !q) return 0;

View File

@ -170,9 +170,17 @@ struct reply_info {
/**
* EDE (rfc8914) code with reason for DNSSEC bogus status.
* Used for caching the EDE.
*/
sldns_ede_code reason_bogus;
/**
* EDE (rfc8914) NULL-terminated string with human-readable reason
* for DNSSEC bogus status.
* Used for caching the EDE.
*/
char* reason_bogus_str;
/**
* Number of RRsets in each section.
* The answer section. Add up the RRs in every RRset to calculate
@ -240,13 +248,15 @@ struct msgreply_entry {
* @param ar: ar count
* @param total: total rrset count (presumably an+ns+ar).
* @param sec: security status of the reply info.
* @param reason_bogus: the Extended DNS Error for DNSSEC bogus status
* @return the reply_info base struct with the array for putting the rrsets
* in. The array has been zeroed. Returns NULL on malloc failure.
*/
struct reply_info*
construct_reply_info_base(struct regional* region, uint16_t flags, size_t qd,
time_t ttl, time_t prettl, time_t expttl, size_t an, size_t ns,
size_t ar, size_t total, enum sec_status sec);
time_t ttl, time_t prettl, time_t expttl, size_t an, size_t ns,
size_t ar, size_t total, enum sec_status sec,
sldns_ede_code reason_bogus);
/**
* Parse wire query into a queryinfo structure, return 0 on parse error.
@ -567,6 +577,16 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
int edns_opt_list_append_ede(struct edns_option** list, struct regional* region,
sldns_ede_code code, const char *txt);
/**
* Append edns keep alive option to edns options list
* @param list: the edns option list to append the edns option to.
* @param msec: the duration in msecs for the keep alive.
* @param region: region to allocate the new edns option.
* @return false on failure.
*/
int edns_opt_list_append_keepalive(struct edns_option** list, int msec,
struct regional* region);
/**
* Remove any option found on the edns option list that matches the code.
* @param list: the list of edns options.
@ -718,6 +738,12 @@ int inplace_cb_query_response_call(struct module_env* env,
struct edns_option* edns_opt_copy_region(struct edns_option* list,
struct regional* region);
/**
* Copy a filtered edns option list allocated to the new region
*/
struct edns_option* edns_opt_copy_filter_region(struct edns_option* list,
uint16_t* filter_list, size_t filter_list_len, struct regional* region);
/**
* Copy edns option list allocated with malloc
*/

View File

@ -45,8 +45,11 @@
#include "util/netevent.h"
#include "util/net_help.h"
#include "util/regional.h"
#include "util/rfc_1982.h"
#include "util/siphash.h"
#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
#include "sldns/sbuffer.h"
struct edns_strings* edns_strings_create(void)
{
@ -128,3 +131,59 @@ edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
return (struct edns_string_addr*)addr_tree_lookup(tree, addr, addrlen);
}
uint8_t*
edns_cookie_server_hash(const uint8_t* in, const uint8_t* secret, int v4,
uint8_t* hash)
{
v4?siphash(in, 20, secret, hash, 8):siphash(in, 32, secret, hash, 8);
return hash;
}
void
edns_cookie_server_write(uint8_t* buf, const uint8_t* secret, int v4,
uint32_t timestamp)
{
uint8_t hash[8];
buf[ 8] = 1; /* Version */
buf[ 9] = 0; /* Reserved */
buf[10] = 0; /* Reserved */
buf[11] = 0; /* Reserved */
sldns_write_uint32(buf + 12, timestamp);
(void)edns_cookie_server_hash(buf, secret, v4, hash);
memcpy(buf + 16, hash, 8);
}
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)
{
uint8_t hash[8];
uint32_t timestamp;
uint32_t subt_1982 = 0; /* Initialize for the compiler; unused value */
int comp_1982;
if(cookie_len != 24)
/* RFC9018 cookies are 24 bytes long */
return COOKIE_STATUS_CLIENT_ONLY;
if(secret_len != 16 || /* RFC9018 cookies have 16 byte secrets */
cookie[8] != 1) /* RFC9018 cookies are cookie version 1 */
return COOKIE_STATUS_INVALID;
timestamp = sldns_read_uint32(cookie + 12);
if((comp_1982 = compare_1982(now, timestamp)) > 0
&& (subt_1982 = subtract_1982(timestamp, now)) > 3600)
/* Cookie is older than 1 hour (see RFC9018 Section 4.3.) */
return COOKIE_STATUS_EXPIRED;
if(comp_1982 <= 0 && subtract_1982(now, timestamp) > 300)
/* Cookie time is more than 5 minutes in the future.
* (see RFC9018 Section 4.3.) */
return COOKIE_STATUS_FUTURE;
if(memcmp(edns_cookie_server_hash(hash_input, secret, v4, hash),
cookie + 16, 8) != 0)
/* Hashes do not match */
return COOKIE_STATUS_INVALID;
if(comp_1982 > 0 && subt_1982 > 1800)
/* Valid cookie but older than 30 minutes, so create a new one
* anyway */
return COOKIE_STATUS_VALID_RENEW;
return COOKIE_STATUS_VALID;
}

View File

@ -75,6 +75,15 @@ struct edns_string_addr {
size_t string_len;
};
enum edns_cookie_val_status {
COOKIE_STATUS_CLIENT_ONLY = -3,
COOKIE_STATUS_FUTURE = -2,
COOKIE_STATUS_EXPIRED = -1,
COOKIE_STATUS_INVALID = 0,
COOKIE_STATUS_VALID = 1,
COOKIE_STATUS_VALID_RENEW = 2,
};
/**
* Create structure to hold EDNS strings
* @return: newly created edns_strings, NULL on alloc failure.
@ -106,4 +115,54 @@ struct edns_string_addr*
edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr,
socklen_t addrlen);
/**
* Compute the interoperable DNS cookie (RFC9018) hash.
* @param in: buffer input for the hash generation. It needs to be:
* Client Cookie | Version | Reserved | Timestamp | Client-IP
* @param secret: the server secret; implicit length of 16 octets.
* @param v4: if the client IP is v4 or v6.
* @param hash: buffer to write the hash to.
* return a pointer to the hash.
*/
uint8_t* edns_cookie_server_hash(const uint8_t* in, const uint8_t* secret,
int v4, uint8_t* hash);
/**
* Write an interoperable DNS server cookie (RFC9018).
* @param buf: buffer to write to. It should have a size of at least 32 octets
* as it doubles as the output buffer and the hash input buffer.
* The first 8 octets are expected to be the Client Cookie and will be
* left untouched.
* The next 8 octets will be written with Version | Reserved | Timestamp.
* The next 4 or 16 octets are expected to be the IPv4 or the IPv6 address
* based on the v4 flag.
* Thus the first 20 or 32 octets, based on the v4 flag, will be used as
* the hash input.
* The server hash (8 octets) will be written after the first 16 octets;
* overwriting the address information.
* The caller expects a complete, 24 octet long cookie in the buffer.
* @param secret: the server secret; implicit length of 16 octets.
* @param v4: if the client IP is v4 or v6.
* @param timestamp: the timestamp to use.
*/
void edns_cookie_server_write(uint8_t* buf, const uint8_t* secret, int v4,
uint32_t timestamp);
/**
* Validate an interoperable DNS cookie (RFC9018).
* @param cookie: pointer to the cookie data.
* @param cookie_len: the length of the cookie data.
* @param secret: pointer to the server secret.
* @param secret_len: the length of the secret.
* @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 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);
#endif

View File

@ -659,6 +659,10 @@ int fptr_whitelist_inplace_cb_edns_back_parsed(
#else
(void)fptr;
#endif
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_edns_back_parsed_call)
return 1;
#endif
#ifdef WITH_DYNLIBMODULE
if(fptr == &dynlib_inplace_cb_edns_back_parsed)
return 1;
@ -675,6 +679,10 @@ int fptr_whitelist_inplace_cb_query_response(
#else
(void)fptr;
#endif
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_query_response)
return 1;
#endif
#ifdef WITH_DYNLIBMODULE
if(fptr == &dynlib_inplace_cb_query_response)
return 1;

View File

@ -674,6 +674,8 @@
911,
912,
913,
914,
915,
989,
990,
991,
@ -1901,6 +1903,7 @@
2256,
2257,
2258,
2259,
2260,
2261,
2262,
@ -2010,6 +2013,7 @@
2366,
2367,
2368,
2369,
2370,
2372,
2378,
@ -4840,6 +4844,7 @@
8403,
8416,
8417,
8433,
8442,
8443,
8444,

View File

@ -84,8 +84,10 @@ void errinf_ede(struct module_qstate* qstate,
const char* str, sldns_ede_code reason_bogus)
{
struct errinf_strlist* p;
if((qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail) || !str)
if(!str || (qstate->env->cfg->val_log_level < 2 &&
!qstate->env->cfg->log_servfail)) {
return;
}
p = (struct errinf_strlist*)regional_alloc(qstate->region, sizeof(*p));
if(!p) {
log_err("malloc failure in validator-error-info string");
@ -152,15 +154,19 @@ char* errinf_to_str_bogus(struct module_qstate* qstate)
return p;
}
/* Try to find the latest (most specific) dnssec failure */
sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate)
{
struct errinf_strlist* s;
sldns_ede_code ede = LDNS_EDE_NONE;
for(s=qstate->errinf; s; s=s->next) {
if (s->reason_bogus != LDNS_EDE_NONE) {
return s->reason_bogus;
}
if(s->reason_bogus == LDNS_EDE_NONE) continue;
if(ede != LDNS_EDE_NONE
&& ede != LDNS_EDE_DNSSEC_BOGUS
&& s->reason_bogus == LDNS_EDE_DNSSEC_BOGUS) continue;
ede = s->reason_bogus;
}
return LDNS_EDE_NONE;
return ede;
}
char* errinf_to_str_servfail(struct module_qstate* qstate)

View File

@ -619,6 +619,12 @@ struct module_qstate {
/** if this is a validation recursion query that does not get
* validation itself */
int is_valrec;
#ifdef CLIENT_SUBNET
/** the client network address is needed for the client-subnet option
* when prefetching, but we can't use reply_list in mesh_info, because
* we don't want to send a reply for the internal query. */
struct sockaddr_storage client_addr;
#endif
/** comm_reply contains server replies */
struct comm_reply* reply;
@ -671,6 +677,8 @@ struct module_qstate {
* those servers. By comparing expiry time with qstarttime for type NS.
*/
time_t qstarttime;
/** whether a message from cachedb will be used for the reply */
int is_cachedb_answer;
/**
* Attributes of clients that share the qstate that may affect IP-based
@ -818,11 +826,11 @@ void errinf_dname(struct module_qstate* qstate, const char* str,
* This string is malloced and has to be freed by caller.
*/
char* errinf_to_str_bogus(struct module_qstate* qstate);
/**
* Check the sldns_ede_code of the qstate.
* Check the sldns_ede_code of the qstate->errinf.
* @param qstate: query state.
* @return LDNS_EDE_DNSSEC_BOGUS by default, or the first explicitly set
* sldns_ede_code.
* @return the latest explicitly set sldns_ede_code or LDNS_EDE_NONE.
*/
sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate);

View File

@ -779,8 +779,8 @@ addr_in_common(struct sockaddr_storage* addr1, int net1,
return match;
}
void
addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen,
void
addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen,
char* buf, size_t len)
{
int af = (int)((struct sockaddr_in*)addr)->sin_family;
@ -792,7 +792,50 @@ addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen,
}
}
int
int
prefixnet_is_nat64(int prefixnet)
{
return (prefixnet == 32 || prefixnet == 40 ||
prefixnet == 48 || prefixnet == 56 ||
prefixnet == 64 || prefixnet == 96);
}
void
addr_to_nat64(const struct sockaddr_storage* addr,
const struct sockaddr_storage* nat64_prefix,
socklen_t nat64_prefixlen, int nat64_prefixnet,
struct sockaddr_storage* nat64_addr, socklen_t* nat64_addrlen)
{
struct sockaddr_in *sin = (struct sockaddr_in *)addr;
struct sockaddr_in6 *sin6;
uint8_t *v4_byte;
/* This needs to be checked by the caller */
log_assert(addr->ss_family == AF_INET);
/* Current usage is only from config values; prefix lengths enforced
* during config validation */
log_assert(prefixnet_is_nat64(nat64_prefixnet));
*nat64_addr = *nat64_prefix;
*nat64_addrlen = nat64_prefixlen;
sin6 = (struct sockaddr_in6 *)nat64_addr;
sin6->sin6_flowinfo = 0;
sin6->sin6_port = sin->sin_port;
nat64_prefixnet = nat64_prefixnet / 8;
v4_byte = (uint8_t *)&sin->sin_addr.s_addr;
for(int i = 0; i < 4; i++) {
if(nat64_prefixnet == 8) {
/* bits 64...71 are MBZ */
sin6->sin6_addr.s6_addr[nat64_prefixnet++] = 0;
}
sin6->sin6_addr.s6_addr[nat64_prefixnet++] = *v4_byte++;
}
}
int
addr_is_ip4mapped(struct sockaddr_storage* addr, socklen_t addrlen)
{
/* prefix for ipv4 into ipv6 mapping is ::ffff:x.x.x.x */
@ -1005,6 +1048,16 @@ listen_sslctx_setup(void* ctxt)
log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list");
}
#endif
#if defined(SSL_OP_IGNORE_UNEXPECTED_EOF)
/* ignore errors when peers do not send the mandatory close_notify
* alert on shutdown.
* Relevant for openssl >= 3 */
if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) &
SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) {
log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF");
return 0;
}
#endif
if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) &
SSL_OP_CIPHER_SERVER_PREFERENCE) !=
@ -1233,6 +1286,17 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
SSL_CTX_free(ctx);
return 0;
}
#endif
#if defined(SSL_OP_IGNORE_UNEXPECTED_EOF)
/* ignore errors when peers do not send the mandatory close_notify
* alert on shutdown.
* Relevant for openssl >= 3 */
if((SSL_CTX_set_options(ctx, SSL_OP_IGNORE_UNEXPECTED_EOF) &
SSL_OP_IGNORE_UNEXPECTED_EOF) != SSL_OP_IGNORE_UNEXPECTED_EOF) {
log_crypto_err("could not set SSL_OP_IGNORE_UNEXPECTED_EOF");
SSL_CTX_free(ctx);
return 0;
}
#endif
if(key && key[0]) {
if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {

View File

@ -331,6 +331,29 @@ int addr_in_common(struct sockaddr_storage* addr1, int net1,
void addr_to_str(struct sockaddr_storage* addr, socklen_t addrlen,
char* buf, size_t len);
/**
* Check if the prefix network length is one of the allowed 32, 40, 48, 56, 64,
* or 96.
* @param prefixnet: prefix network length to check.
* @return 1 on success, 0 on failure.
*/
int prefixnet_is_nat64(int prefixnet);
/**
* Create a NAT64 address from a given address (needs to be IPv4) and a given
* NAT64 prefix. The NAT64 prefix net needs to be one of 32, 40, 48, 56, 64, 96.
* @param addr: IPv4 address.
* @param nat64_prefix: NAT64 prefix.
* @param nat64_prefixlen: NAT64 prefix len.
* @param nat64_prefixnet: NAT64 prefix mask.
* @param nat64_addr: the resulting NAT64 address.
* @param nat64_addrlen: the resulting NAT64 address length.
*/
void addr_to_nat64(const struct sockaddr_storage* addr,
const struct sockaddr_storage* nat64_prefix,
socklen_t nat64_prefixlen, int nat64_prefixnet,
struct sockaddr_storage* nat64_addr, socklen_t* nat64_addrlen);
/**
* See if sockaddr is an ipv6 mapped ipv4 address, "::ffff:0.0.0.0"
* @param addr: address

View File

@ -4,22 +4,22 @@
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -46,6 +46,7 @@
#include "util/tcp_conn_limit.h"
#include "util/fptr_wlist.h"
#include "util/proxy_protocol.h"
#include "util/timeval_func.h"
#include "sldns/pkthdr.h"
#include "sldns/sbuffer.h"
#include "sldns/str2wire.h"
@ -71,7 +72,9 @@
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
#ifdef HAVE_LINUX_NET_TSTAMP_H
#include <linux/net_tstamp.h>
#endif
/* -------- Start of local definitions -------- */
/** if CMSG_ALIGN is not defined on this platform, a workaround */
#ifndef CMSG_ALIGN
@ -114,6 +117,16 @@
/** timeout in millisec to wait for write to unblock, packets dropped after.*/
#define SEND_BLOCKED_WAIT_TIMEOUT 200
/** Let's make timestamping code cleaner and redefine SO_TIMESTAMP* */
#ifndef SO_TIMESTAMP
#define SO_TIMESTAMP 29
#endif
#ifndef SO_TIMESTAMPNS
#define SO_TIMESTAMPNS 35
#endif
#ifndef SO_TIMESTAMPING
#define SO_TIMESTAMPING 37
#endif
/**
* The internal event structure for keeping ub_event info for the event.
* Possibly other structures (list, tree) this is part of.
@ -177,7 +190,7 @@ static struct comm_point* comm_point_create_tcp_handler(
/* -------- End of local definitions -------- */
struct comm_base*
struct comm_base*
comm_base_create(int sigs)
{
struct comm_base* b = (struct comm_base*)calloc(1,
@ -220,7 +233,7 @@ comm_base_create_event(struct ub_event_base* base)
return b;
}
void
void
comm_base_delete(struct comm_base* b)
{
if(!b)
@ -237,7 +250,7 @@ comm_base_delete(struct comm_base* b)
free(b);
}
void
void
comm_base_delete_no_base(struct comm_base* b)
{
if(!b)
@ -253,14 +266,14 @@ comm_base_delete_no_base(struct comm_base* b)
free(b);
}
void
void
comm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv)
{
*tt = &b->eb->secs;
*tv = &b->eb->now;
}
void
void
comm_base_dispatch(struct comm_base* b)
{
int retval;
@ -470,7 +483,7 @@ comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
(struct sockaddr_storage*)addr, addrlen);
return 0;
} else if((size_t)sent != sldns_buffer_remaining(packet)) {
log_err("sent %d in place of %d bytes",
log_err("sent %d in place of %d bytes",
(int)sent, (int)sldns_buffer_remaining(packet));
return 0;
}
@ -489,7 +502,7 @@ static void p_ancil(const char* str, struct comm_reply* r)
if(r->srctype == 6) {
#ifdef IPV6_PKTINFO
char buf[1024];
if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr,
if(inet_ntop(AF_INET6, &r->pktinfo.v6info.ipi6_addr,
buf, (socklen_t)sizeof(buf)) == 0) {
(void)strlcpy(buf, "(inet_ntop error)", sizeof(buf));
}
@ -499,13 +512,13 @@ static void p_ancil(const char* str, struct comm_reply* r)
} else if(r->srctype == 4) {
#ifdef IP_PKTINFO
char buf1[1024], buf2[1024];
if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr,
if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_addr,
buf1, (socklen_t)sizeof(buf1)) == 0) {
(void)strlcpy(buf1, "(inet_ntop error)", sizeof(buf1));
}
buf1[sizeof(buf1)-1]=0;
#ifdef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_spec_dst,
if(inet_ntop(AF_INET, &r->pktinfo.v4info.ipi_spec_dst,
buf2, (socklen_t)sizeof(buf2)) == 0) {
(void)strlcpy(buf2, "(inet_ntop error)", sizeof(buf2));
}
@ -517,7 +530,7 @@ static void p_ancil(const char* str, struct comm_reply* r)
buf1, buf2);
#elif defined(IP_RECVDSTADDR)
char buf1[1024];
if(inet_ntop(AF_INET, &r->pktinfo.v4addr,
if(inet_ntop(AF_INET, &r->pktinfo.v4addr,
buf1, (socklen_t)sizeof(buf1)) == 0) {
(void)strlcpy(buf1, "(inet_ntop error)", sizeof(buf1));
}
@ -531,7 +544,7 @@ static void p_ancil(const char* str, struct comm_reply* r)
/** send a UDP reply over specified interface*/
static int
comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
struct sockaddr* addr, socklen_t addrlen, struct comm_reply* r)
struct sockaddr* addr, socklen_t addrlen, struct comm_reply* r)
{
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_SENDMSG)
ssize_t sent;
@ -579,6 +592,11 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
cmsg_data = CMSG_DATA(cmsg);
((struct in_pktinfo *) cmsg_data)->ipi_ifindex = 0;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
/* zero the padding bytes inserted by the CMSG_LEN */
if(sizeof(struct in_pktinfo) < cmsg->cmsg_len)
memset(((uint8_t*)(CMSG_DATA(cmsg))) +
sizeof(struct in_pktinfo), 0, cmsg->cmsg_len
- sizeof(struct in_pktinfo));
#elif defined(IP_SENDSRCADDR)
msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
log_assert(msg.msg_controllen <= sizeof(control.buf));
@ -587,6 +605,11 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
memmove(CMSG_DATA(cmsg), &r->pktinfo.v4addr,
sizeof(struct in_addr));
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
/* zero the padding bytes inserted by the CMSG_LEN */
if(sizeof(struct in_addr) < cmsg->cmsg_len)
memset(((uint8_t*)(CMSG_DATA(cmsg))) +
sizeof(struct in_addr), 0, cmsg->cmsg_len
- sizeof(struct in_addr));
#else
verbose(VERB_ALGO, "no IP_PKTINFO or IP_SENDSRCADDR");
msg.msg_control = NULL;
@ -603,6 +626,11 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
cmsg_data = CMSG_DATA(cmsg);
((struct in6_pktinfo *) cmsg_data)->ipi6_ifindex = 0;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
/* zero the padding bytes inserted by the CMSG_LEN */
if(sizeof(struct in6_pktinfo) < cmsg->cmsg_len)
memset(((uint8_t*)(CMSG_DATA(cmsg))) +
sizeof(struct in6_pktinfo), 0, cmsg->cmsg_len
- sizeof(struct in6_pktinfo));
} else {
/* try to pass all 0 to use default route */
msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
@ -611,9 +639,14 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
cmsg->cmsg_type = IPV6_PKTINFO;
memset(CMSG_DATA(cmsg), 0, sizeof(struct in6_pktinfo));
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
/* zero the padding bytes inserted by the CMSG_LEN */
if(sizeof(struct in6_pktinfo) < cmsg->cmsg_len)
memset(((uint8_t*)(CMSG_DATA(cmsg))) +
sizeof(struct in6_pktinfo), 0, cmsg->cmsg_len
- sizeof(struct in6_pktinfo));
}
#endif /* S_SPLINT_S */
if(verbosity >= VERB_ALGO)
if(verbosity >= VERB_ALGO && r->srctype != 0)
p_ancil("send_udp over interface", r);
sent = sendmsg(c->fd, &msg, 0);
if(sent == -1) {
@ -695,7 +728,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
if(!udp_send_errno_needs_log(addr, addrlen))
return 0;
verbose(VERB_OPS, "sendmsg failed: %s", strerror(errno));
log_addr(VERB_OPS, "remote address is",
log_addr(VERB_OPS, "remote address is",
(struct sockaddr_storage*)addr, addrlen);
#ifdef __NetBSD__
/* netbsd 7 has IP_PKTINFO for recv but not send */
@ -705,7 +738,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
#endif
return 0;
} else if((size_t)sent != sldns_buffer_remaining(packet)) {
log_err("sent %d in place of %d bytes",
log_err("sent %d in place of %d bytes",
(int)sent, (int)sldns_buffer_remaining(packet));
return 0;
}
@ -817,7 +850,7 @@ done:
return 1;
}
void
void
comm_point_udp_ancil_callback(int fd, short event, void* arg)
{
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
@ -833,6 +866,9 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
#ifndef S_SPLINT_S
struct cmsghdr* cmsg;
#endif /* S_SPLINT_S */
#ifdef HAVE_LINUX_NET_TSTAMP_H
struct timespec *ts;
#endif /* HAVE_LINUX_NET_TSTAMP_H */
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
@ -843,6 +879,7 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
ub_comm_base_now(rep.c->ev->base);
for(i=0; i<NUM_UDP_PER_SELECT; i++) {
sldns_buffer_clear(rep.c->buffer);
timeval_clear(&rep.c->recv_tv);
rep.remote_addrlen = (socklen_t)sizeof(rep.remote_addr);
log_assert(fd != -1);
log_assert(sldns_buffer_remaining(rep.c->buffer) > 0);
@ -894,9 +931,23 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
sizeof(struct in_addr));
break;
#endif /* IP_PKTINFO or IP_RECVDSTADDR */
#ifdef HAVE_LINUX_NET_TSTAMP_H
} else if( cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SO_TIMESTAMPNS) {
ts = (struct timespec *)CMSG_DATA(cmsg);
TIMESPEC_TO_TIMEVAL(&rep.c->recv_tv, ts);
} else if( cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SO_TIMESTAMPING) {
ts = (struct timespec *)CMSG_DATA(cmsg);
TIMESPEC_TO_TIMEVAL(&rep.c->recv_tv, ts);
} else if( cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SO_TIMESTAMP) {
memmove(&rep.c->recv_tv, CMSG_DATA(cmsg), sizeof(struct timeval));
#endif /* HAVE_LINUX_NET_TSTAMP_H */
}
}
if(verbosity >= VERB_ALGO)
if(verbosity >= VERB_ALGO && rep.srctype != 0)
p_ancil("receive_udp on interface", &rep);
#endif /* S_SPLINT_S */
@ -930,7 +981,7 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */
}
void
void
comm_point_udp_callback(int fd, short event, void* arg)
{
struct comm_reply rep;
@ -950,14 +1001,14 @@ comm_point_udp_callback(int fd, short event, void* arg)
rep.remote_addrlen = (socklen_t)sizeof(rep.remote_addr);
log_assert(fd != -1);
log_assert(sldns_buffer_remaining(rep.c->buffer) > 0);
rcv = recvfrom(fd, (void*)sldns_buffer_begin(rep.c->buffer),
rcv = recvfrom(fd, (void*)sldns_buffer_begin(rep.c->buffer),
sldns_buffer_remaining(rep.c->buffer), MSG_DONTWAIT,
(struct sockaddr*)&rep.remote_addr, &rep.remote_addrlen);
if(rcv == -1) {
#ifndef USE_WINSOCK
if(errno != EAGAIN && errno != EINTR
&& udp_recv_needs_log(errno))
log_err("recvfrom %d failed: %s",
log_err("recvfrom %d failed: %s",
fd, strerror(errno));
#else
if(WSAGetLastError() != WSAEINPROGRESS &&
@ -1012,7 +1063,7 @@ int adjusted_tcp_timeout(struct comm_point* c)
/** Use a new tcp handler for new query fd, set to read query */
static void
setup_tcp_handler(struct comm_point* c, int fd, int cur, int max)
setup_tcp_handler(struct comm_point* c, int fd, int cur, int max)
{
int handler_usage;
log_assert(c->type == comm_tcp || c->type == comm_http);
@ -1076,10 +1127,10 @@ int comm_point_perform_accept(struct comm_point* c,
/* EINTR is signal interrupt. others are closed connection. */
if( errno == EINTR || errno == EAGAIN
#ifdef EWOULDBLOCK
|| errno == EWOULDBLOCK
|| errno == EWOULDBLOCK
#endif
#ifdef ECONNABORTED
|| errno == ECONNABORTED
|| errno == ECONNABORTED
#endif
#ifdef EPROTO
|| errno == EPROTO
@ -1253,7 +1304,7 @@ static int http2_submit_settings(struct http2_session* h2_session)
#endif /* HAVE_NGHTTP2 */
void
void
comm_point_tcp_accept_callback(int fd, short event, void* arg)
{
struct comm_point* c = (struct comm_point*)arg, *c_hdl;
@ -2161,7 +2212,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
log_err("in comm_point_tcp_handle_read buffer_remaining is "
"not > 0 as expected, continuing with (harmless) 0 "
"length recv");
r = recv(fd, (void*)sldns_buffer_current(c->buffer),
r = recv(fd, (void*)sldns_buffer_current(c->buffer),
sldns_buffer_remaining(c->buffer), MSG_DONTWAIT);
if(r == 0) {
if(c->tcp_req_info)
@ -2252,8 +2303,8 @@ recv_error:
return 0;
}
/**
* Handle tcp writing callback.
/**
* Handle tcp writing callback.
* @param fd: file descriptor of socket.
* @param c: comm point to write buffer out of.
* @return: 0 on error
@ -2277,7 +2328,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
/* from Stevens, unix network programming, vol1, 3rd ed, p450*/
int error = 0;
socklen_t len = (socklen_t)sizeof(error);
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error,
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error,
&len) < 0){
#ifndef USE_WINSOCK
error = errno; /* on solaris errno is error */
@ -2318,7 +2369,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
return ssl_handle_it(c, 1);
#ifdef USE_MSG_FASTOPEN
/* Only try this on first use of a connection that uses tfo,
/* Only try this on first use of a connection that uses tfo,
otherwise fall through to normal write */
/* Also, TFO support on WINDOWS not implemented at the moment */
if(c->tcp_do_fastopen == 1) {
@ -2473,7 +2524,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if(WSAGetLastError() == WSAEWOULDBLOCK) {
ub_winsock_tcp_wouldblock(c->ev->ev,
UB_EV_WRITE);
return 1;
return 1;
}
if(WSAGetLastError() == WSAECONNRESET && verbosity < 2)
return 0; /* silence reset by peer */
@ -2522,7 +2573,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
return 1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1;
return 1;
}
if(WSAGetLastError() == WSAECONNRESET && verbosity < 2)
return 0; /* silence reset by peer */
@ -2541,12 +2592,13 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
if((!c->tcp_write_and_read && sldns_buffer_remaining(buffer) == 0) || (c->tcp_write_and_read && c->tcp_write_byte_count == c->tcp_write_pkt_len + 2)) {
tcp_callback_writer(c);
}
return 1;
}
/** read again to drain buffers when there could be more to read */
static void
/** read again to drain buffers when there could be more to read, returns 0
* on failure which means the comm point is closed. */
static int
tcp_req_info_read_again(int fd, struct comm_point* c)
{
while(c->tcp_req_info->read_again) {
@ -2560,12 +2612,13 @@ tcp_req_info_read_again(int fd, struct comm_point* c)
if(!c->tcp_do_close) {
fptr_ok(fptr_whitelist_comm_point(
c->callback));
(void)(*c->callback)(c, c->cb_arg,
(void)(*c->callback)(c, c->cb_arg,
NETEVENT_CLOSED, NULL);
}
return;
return 0;
}
}
return 1;
}
/** read again to drain buffers when there could be more to read */
@ -2616,13 +2669,16 @@ tcp_more_write_again(int fd, struct comm_point* c)
}
}
void
void
comm_point_tcp_handle_callback(int fd, short event, void* arg)
{
struct comm_point* c = (struct comm_point*)arg;
log_assert(c->type == comm_tcp);
ub_comm_base_now(c->ev->base);
if(c->fd == -1 || c->fd != fd)
return; /* duplicate event, but commpoint closed. */
#ifdef USE_DNSCRYPT
/* Initialize if this is a dnscrypt socket */
if(c->tcp_parent) {
@ -2671,8 +2727,10 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
}
return;
}
if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again)
tcp_req_info_read_again(fd, c);
if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again) {
if(!tcp_req_info_read_again(fd, c))
return;
}
if(moreread && *moreread)
tcp_more_read_again(fd, c);
return;
@ -2690,8 +2748,10 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
}
return;
}
if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again)
tcp_req_info_read_again(fd, c);
if(has_tcpq && c->tcp_req_info && c->tcp_req_info->read_again) {
if(!tcp_req_info_read_again(fd, c))
return;
}
if(morewrite && *morewrite)
tcp_more_write_again(fd, c);
return;
@ -2774,7 +2834,7 @@ http_read_more(int fd, struct comm_point* c)
{
ssize_t r;
log_assert(sldns_buffer_remaining(c->buffer) > 0);
r = recv(fd, (void*)sldns_buffer_current(c->buffer),
r = recv(fd, (void*)sldns_buffer_current(c->buffer),
sldns_buffer_remaining(c->buffer), MSG_DONTWAIT);
if(r == 0) {
return 0;
@ -3043,7 +3103,7 @@ http_chunked_segment(struct comm_point* c)
/* return and wait to read more */
return 1;
}
/* callback of http reader for a new part of the data */
c->http_stored = 0;
sldns_buffer_set_position(c->buffer, 0);
@ -3393,7 +3453,7 @@ http_check_connect(int fd, struct comm_point* c)
/* from Stevens, unix network programming, vol1, 3rd ed, p450*/
int error = 0;
socklen_t len = (socklen_t)sizeof(error);
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error,
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&error,
&len) < 0){
#ifndef USE_WINSOCK
error = errno; /* on solaris errno is error */
@ -3478,7 +3538,7 @@ http_write_more(int fd, struct comm_point* c)
{
ssize_t r;
log_assert(sldns_buffer_remaining(c->buffer) > 0);
r = send(fd, (void*)sldns_buffer_current(c->buffer),
r = send(fd, (void*)sldns_buffer_current(c->buffer),
sldns_buffer_remaining(c->buffer), 0);
if(r == -1) {
#ifndef USE_WINSOCK
@ -3489,7 +3549,7 @@ http_write_more(int fd, struct comm_point* c)
return 1;
if(WSAGetLastError() == WSAEWOULDBLOCK) {
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1;
return 1;
}
#endif
log_err_addr("http send r", sock_strerror(errno),
@ -3610,8 +3670,8 @@ comm_point_http2_handle_write(int ATTR_UNUSED(fd), struct comm_point* c)
#endif
}
/**
* Handle http writing callback.
/**
* Handle http writing callback.
* @param fd: file descriptor of socket.
* @param c: comm point to write buffer out of.
* @return: 0 on error
@ -3677,7 +3737,7 @@ comm_point_http_handle_write(int fd, struct comm_point* c)
return 1;
}
void
void
comm_point_http_handle_callback(int fd, short event, void* arg)
{
struct comm_point* c = (struct comm_point*)arg;
@ -3730,7 +3790,7 @@ void comm_point_local_handle_callback(int fd, short event, void* arg)
if(event&UB_EV_READ) {
if(!comm_point_tcp_handle_read(fd, c, 1)) {
fptr_ok(fptr_whitelist_comm_point(c->callback));
(void)(*c->callback)(c, c->cb_arg, NETEVENT_CLOSED,
(void)(*c->callback)(c, c->cb_arg, NETEVENT_CLOSED,
NULL);
}
return;
@ -3738,21 +3798,21 @@ void comm_point_local_handle_callback(int fd, short event, void* arg)
log_err("Ignored event %d for localhdl.", event);
}
void comm_point_raw_handle_callback(int ATTR_UNUSED(fd),
void comm_point_raw_handle_callback(int ATTR_UNUSED(fd),
short event, void* arg)
{
struct comm_point* c = (struct comm_point*)arg;
int err = NETEVENT_NOERROR;
log_assert(c->type == comm_raw);
ub_comm_base_now(c->ev->base);
if(event&UB_EV_TIMEOUT)
err = NETEVENT_TIMEOUT;
fptr_ok(fptr_whitelist_comm_point_raw(c->callback));
(void)(*c->callback)(c, c->cb_arg, err, NULL);
}
struct comm_point*
struct comm_point*
comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
int pp2_enabled, comm_point_callback_type* callback,
void* callback_arg, struct unbound_socket* socket)
@ -3800,7 +3860,11 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
evbits = UB_EV_READ | UB_EV_PERSIST;
/* ub_event stuff */
c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits,
#ifdef USE_WINSOCK
comm_point_udp_callback, c);
#else
comm_point_udp_ancil_callback, c);
#endif
if(c->ev->ev == NULL) {
log_err("could not baseset udp event");
comm_point_delete(c);
@ -3815,7 +3879,7 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer,
return c;
}
struct comm_point*
struct comm_point*
comm_point_create_udp_ancil(struct comm_base *base, int fd,
sldns_buffer* buffer, int pp2_enabled,
comm_point_callback_type* callback, void* callback_arg, struct unbound_socket* socket)
@ -3878,8 +3942,8 @@ comm_point_create_udp_ancil(struct comm_base *base, int fd,
return c;
}
static struct comm_point*
comm_point_create_tcp_handler(struct comm_base *base,
static struct comm_point*
comm_point_create_tcp_handler(struct comm_base *base,
struct comm_point* parent, size_t bufsize,
struct sldns_buffer* spoolbuf, comm_point_callback_type* callback,
void* callback_arg, struct unbound_socket* socket)
@ -3976,8 +4040,8 @@ comm_point_create_tcp_handler(struct comm_base *base,
return c;
}
static struct comm_point*
comm_point_create_http_handler(struct comm_base *base,
static struct comm_point*
comm_point_create_http_handler(struct comm_base *base,
struct comm_point* parent, size_t bufsize, int harden_large_queries,
uint32_t http_max_streams, char* http_endpoint,
comm_point_callback_type* callback, void* callback_arg,
@ -4074,7 +4138,7 @@ comm_point_create_http_handler(struct comm_base *base,
return NULL;
}
#endif
/* add to parent free list */
c->tcp_free = parent->tcp_free;
parent->tcp_free = c;
@ -4096,7 +4160,7 @@ comm_point_create_http_handler(struct comm_base *base,
return c;
}
struct comm_point*
struct comm_point*
comm_point_create_tcp(struct comm_base *base, int fd, int num,
int idle_timeout, int harden_large_queries,
uint32_t http_max_streams, char* http_endpoint,
@ -4194,11 +4258,11 @@ comm_point_create_tcp(struct comm_base *base, int fd, int num,
return NULL;
}
}
return c;
}
struct comm_point*
struct comm_point*
comm_point_create_tcp_out(struct comm_base *base, size_t bufsize,
comm_point_callback_type* callback, void* callback_arg)
{
@ -4265,7 +4329,7 @@ comm_point_create_tcp_out(struct comm_base *base, size_t bufsize,
return c;
}
struct comm_point*
struct comm_point*
comm_point_create_http_out(struct comm_base *base, size_t bufsize,
comm_point_callback_type* callback, void* callback_arg,
sldns_buffer* temp)
@ -4336,7 +4400,7 @@ comm_point_create_http_out(struct comm_base *base, size_t bufsize,
return c;
}
struct comm_point*
struct comm_point*
comm_point_create_local(struct comm_base *base, int fd, size_t bufsize,
comm_point_callback_type* callback, void* callback_arg)
{
@ -4404,8 +4468,8 @@ comm_point_create_local(struct comm_base *base, int fd, size_t bufsize,
return c;
}
struct comm_point*
comm_point_create_raw(struct comm_base* base, int fd, int writing,
struct comm_point*
comm_point_create_raw(struct comm_base* base, int fd, int writing,
comm_point_callback_type* callback, void* callback_arg)
{
struct comm_point* c = (struct comm_point*)calloc(1,
@ -4469,7 +4533,7 @@ comm_point_create_raw(struct comm_base* base, int fd, int writing,
return c;
}
void
void
comm_point_close(struct comm_point* c)
{
if(!c)
@ -4488,6 +4552,11 @@ comm_point_close(struct comm_point* c)
tcp_req_info_clear(c->tcp_req_info);
if(c->h2_session)
http2_session_server_delete(c->h2_session);
/* stop the comm point from reading or writing after it is closed. */
if(c->tcp_more_read_again && *c->tcp_more_read_again)
*c->tcp_more_read_again = 0;
if(c->tcp_more_write_again && *c->tcp_more_write_again)
*c->tcp_more_write_again = 0;
/* close fd after removing from event lists, or epoll.. is messed up */
if(c->fd != -1 && !c->do_not_close) {
@ -4504,10 +4573,10 @@ comm_point_close(struct comm_point* c)
c->fd = -1;
}
void
void
comm_point_delete(struct comm_point* c)
{
if(!c)
if(!c)
return;
if((c->type == comm_tcp || c->type == comm_http) && c->ssl) {
#ifdef HAVE_SSL
@ -4546,7 +4615,7 @@ comm_point_delete(struct comm_point* c)
free(c);
}
void
void
comm_point_send_reply(struct comm_reply *repinfo)
{
struct sldns_buffer* buffer;
@ -4610,7 +4679,7 @@ comm_point_send_reply(struct comm_reply *repinfo)
}
}
void
void
comm_point_drop_reply(struct comm_reply* repinfo)
{
if(!repinfo)
@ -4634,7 +4703,7 @@ comm_point_drop_reply(struct comm_reply* repinfo)
reclaim_tcp_handler(repinfo->c);
}
void
void
comm_point_stop_listening(struct comm_point* c)
{
verbose(VERB_ALGO, "comm point stop listening %d", c->fd);
@ -4646,10 +4715,10 @@ comm_point_stop_listening(struct comm_point* c)
}
}
void
void
comm_point_start_listening(struct comm_point* c, int newfd, int msec)
{
verbose(VERB_ALGO, "comm point start listening %d (%d msec)",
verbose(VERB_ALGO, "comm point start listening %d (%d msec)",
c->fd==-1?newfd:c->fd, msec);
if(c->type == comm_tcp_accept && !c->tcp_free) {
/* no use to start listening no free slots. */
@ -4733,10 +4802,10 @@ void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr)
size_t comm_point_get_mem(struct comm_point* c)
{
size_t s;
if(!c)
if(!c)
return 0;
s = sizeof(*c) + sizeof(*c->ev);
if(c->timeout)
if(c->timeout)
s += sizeof(*c->timeout);
if(c->type == comm_tcp || c->type == comm_local) {
s += sizeof(*c->buffer) + sldns_buffer_capacity(c->buffer);
@ -4755,7 +4824,7 @@ size_t comm_point_get_mem(struct comm_point* c)
return s;
}
struct comm_timer*
struct comm_timer*
comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg)
{
struct internal_timer *tm = (struct internal_timer*)calloc(1,
@ -4768,7 +4837,7 @@ comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg)
tm->base = base;
tm->super.callback = cb;
tm->super.cb_arg = cb_arg;
tm->ev = ub_event_new(base->eb->base, -1, UB_EV_TIMEOUT,
tm->ev = ub_event_new(base->eb->base, -1, UB_EV_TIMEOUT,
comm_timer_callback, &tm->super);
if(tm->ev == NULL) {
log_err("timer_create: event_base_set failed.");
@ -4778,7 +4847,7 @@ comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg)
return &tm->super;
}
void
void
comm_timer_disable(struct comm_timer* timer)
{
if(!timer)
@ -4787,7 +4856,7 @@ comm_timer_disable(struct comm_timer* timer)
timer->ev_timer->enabled = 0;
}
void
void
comm_timer_set(struct comm_timer* timer, struct timeval* tv)
{
log_assert(tv);
@ -4799,7 +4868,7 @@ comm_timer_set(struct comm_timer* timer, struct timeval* tv)
timer->ev_timer->enabled = 1;
}
void
void
comm_timer_delete(struct comm_timer* timer)
{
if(!timer)
@ -4812,7 +4881,7 @@ comm_timer_delete(struct comm_timer* timer)
free(timer->ev_timer);
}
void
void
comm_timer_callback(int ATTR_UNUSED(fd), short event, void* arg)
{
struct comm_timer* tm = (struct comm_timer*)arg;
@ -4824,19 +4893,19 @@ comm_timer_callback(int ATTR_UNUSED(fd), short event, void* arg)
(*tm->callback)(tm->cb_arg);
}
int
int
comm_timer_is_set(struct comm_timer* timer)
{
return (int)timer->ev_timer->enabled;
}
size_t
size_t
comm_timer_get_mem(struct comm_timer* ATTR_UNUSED(timer))
{
return sizeof(struct internal_timer);
}
struct comm_signal*
struct comm_signal*
comm_signal_create(struct comm_base* base,
void (*callback)(int, void*), void* cb_arg)
{
@ -4853,7 +4922,7 @@ comm_signal_create(struct comm_base* base,
return com;
}
void
void
comm_signal_callback(int sig, short event, void* arg)
{
struct comm_signal* comsig = (struct comm_signal*)arg;
@ -4864,10 +4933,10 @@ comm_signal_callback(int sig, short event, void* arg)
(*comsig->callback)(sig, comsig->cb_arg);
}
int
int
comm_signal_bind(struct comm_signal* comsig, int sig)
{
struct internal_signal* entry = (struct internal_signal*)calloc(1,
struct internal_signal* entry = (struct internal_signal*)calloc(1,
sizeof(struct internal_signal));
if(!entry) {
log_err("malloc failed");
@ -4894,7 +4963,7 @@ comm_signal_bind(struct comm_signal* comsig, int sig)
return 1;
}
void
void
comm_signal_delete(struct comm_signal* comsig)
{
struct internal_signal* p, *np;

View File

@ -4,22 +4,22 @@
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -60,6 +60,7 @@
#ifndef NET_EVENT_H
#define NET_EVENT_H
#include <sys/time.h>
#include "dnscrypt/dnscrypt.h"
#ifdef HAVE_NGHTTP2_NGHTTP2_H
#include <nghttp2/nghttp2.h>
@ -83,7 +84,7 @@ struct internal_timer; /* A sub struct of the comm_timer super struct */
enum listen_type;
/** callback from communication point function type */
typedef int comm_point_callback_type(struct comm_point*, void*, int,
typedef int comm_point_callback_type(struct comm_point*, void*, int,
struct comm_reply*);
/** to pass no_error to callback function */
@ -91,7 +92,7 @@ typedef int comm_point_callback_type(struct comm_point*, void*, int,
/** to pass closed connection to callback function */
#define NETEVENT_CLOSED -1
/** to pass timeout happened to callback function */
#define NETEVENT_TIMEOUT -2
#define NETEVENT_TIMEOUT -2
/** to pass fallback from capsforID to callback function; 0x20 failed */
#define NETEVENT_CAPSFAIL -3
/** to pass done transfer to callback function; http file is complete */
@ -165,8 +166,8 @@ struct comm_reply {
socklen_t client_addrlen;
};
/**
* Communication point to the network
/**
* Communication point to the network
* These behaviours can be accomplished by setting the flags
* and passing return values from the callback.
* udp frontside: called after readdone. sendafter.
@ -206,7 +207,7 @@ struct comm_point {
int max_tcp_count;
/** current number of tcp handler in-use for this accept socket */
int cur_tcp_count;
/** malloced array of tcp handlers for a tcp-accept,
/** malloced array of tcp handlers for a tcp-accept,
of size max_tcp_count. */
struct comm_point** tcp_handlers;
/** linked list of free tcp_handlers to use for new queries.
@ -271,9 +272,9 @@ struct comm_point {
/** is this a UDP, TCP-accept or TCP socket. */
enum comm_point_type {
/** UDP socket - handle datagrams. */
comm_udp,
comm_udp,
/** TCP accept socket - only creates handlers if readable. */
comm_tcp_accept,
comm_tcp_accept,
/** TCP handler socket - handle byteperbyte readwrite. */
comm_tcp,
/** HTTP handler socket */
@ -282,7 +283,7 @@ struct comm_point {
comm_local,
/** raw - not DNS format - for pipe readers and writers */
comm_raw
}
}
/** variable with type of socket, UDP,TCP-accept,TCP,pipe */
type;
@ -303,7 +304,7 @@ struct comm_point {
/** if set the connection is NOT closed on delete. */
int do_not_close;
/** if set, the connection is closed on error, on timeout,
/** if set, the connection is closed on error, on timeout,
and after read/write completes. No callback is done. */
int tcp_do_close;
@ -383,15 +384,16 @@ struct comm_point {
/** number of queries outstanding on this socket, used by
* outside network for udp ports */
int inuse;
/** the timestamp when the packet was received by the kernel */
struct timeval recv_tv;
/** callback when done.
tcp_accept does not get called back, is NULL then.
If a timeout happens, callback with timeout=1 is called.
If an error happens, callback is called with error set
If an error happens, callback is called with error set
nonzero. If not NETEVENT_NOERROR, it is an errno value.
If the connection is closed (by remote end) then the
callback is called with error set to NETEVENT_CLOSED=-1.
If a timeout happens on the connection, the error is set to
If a timeout happens on the connection, the error is set to
NETEVENT_TIMEOUT=-2.
The reply_info can be copied if the reply needs to happen at a
later time. It consists of a struct with commpoint and address.
@ -399,7 +401,7 @@ struct comm_point {
Note the reply information is temporary and must be copied.
NULL is passed for_reply info, in cases where error happened.
declare as:
declare as:
int my_callback(struct comm_point* c, void* my_arg, int error,
struct comm_reply *reply_info);
@ -446,14 +448,14 @@ struct comm_signal {
/**
* Create a new comm base.
* @param sigs: if true it attempts to create a default loop for
* @param sigs: if true it attempts to create a default loop for
* signal handling.
* @return: the new comm base. NULL on error.
*/
struct comm_base* comm_base_create(int sigs);
/**
* Create comm base that uses the given ub_event_base (underlying pluggable
* Create comm base that uses the given ub_event_base (underlying pluggable
* event mechanism pointer).
* @param base: underlying pluggable event base.
* @return: the new comm base. NULL on error.
@ -619,7 +621,7 @@ struct comm_point* comm_point_create_http_out(struct comm_base* base,
* @return: the commpoint or NULL on error.
*/
struct comm_point* comm_point_create_local(struct comm_base* base,
int fd, size_t bufsize,
int fd, size_t bufsize,
comm_point_callback_type* callback, void* callback_arg);
/**
@ -632,7 +634,7 @@ struct comm_point* comm_point_create_local(struct comm_base* base,
* @return: the commpoint or NULL on error.
*/
struct comm_point* comm_point_create_raw(struct comm_base* base,
int fd, int writing,
int fd, int writing,
comm_point_callback_type* callback, void* callback_arg);
/**
@ -722,7 +724,7 @@ size_t comm_point_get_mem(struct comm_point* c);
* @param cb_arg: user callback argument.
* @return: the new timer or NULL on error.
*/
struct comm_timer* comm_timer_create(struct comm_base* base,
struct comm_timer* comm_timer_create(struct comm_base* base,
void (*cb)(void*), void* cb_arg);
/**
@ -792,7 +794,7 @@ void comm_signal_delete(struct comm_signal* comsig);
* if -1, error message has been printed if necessary, simply drop
* out of the reading handler.
*/
int comm_point_perform_accept(struct comm_point* c,
int comm_point_perform_accept(struct comm_point* c,
struct sockaddr_storage* addr, socklen_t* addrlen);
/**** internal routines ****/
@ -801,7 +803,7 @@ int comm_point_perform_accept(struct comm_point* c,
* This routine is published for checks and tests, and is only used internally.
* handle libevent callback for udp comm point.
* @param fd: file descriptor.
* @param event: event bits from libevent:
* @param event: event bits from libevent:
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
* @param arg: the comm_point structure.
*/
@ -811,7 +813,7 @@ void comm_point_udp_callback(int fd, short event, void* arg);
* This routine is published for checks and tests, and is only used internally.
* handle libevent callback for udp ancillary data comm point.
* @param fd: file descriptor.
* @param event: event bits from libevent:
* @param event: event bits from libevent:
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
* @param arg: the comm_point structure.
*/
@ -821,7 +823,7 @@ void comm_point_udp_ancil_callback(int fd, short event, void* arg);
* This routine is published for checks and tests, and is only used internally.
* handle libevent callback for tcp accept comm point
* @param fd: file descriptor.
* @param event: event bits from libevent:
* @param event: event bits from libevent:
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
* @param arg: the comm_point structure.
*/
@ -831,7 +833,7 @@ void comm_point_tcp_accept_callback(int fd, short event, void* arg);
* This routine is published for checks and tests, and is only used internally.
* handle libevent callback for tcp data comm point
* @param fd: file descriptor.
* @param event: event bits from libevent:
* @param event: event bits from libevent:
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
* @param arg: the comm_point structure.
*/
@ -841,7 +843,7 @@ void comm_point_tcp_handle_callback(int fd, short event, void* arg);
* This routine is published for checks and tests, and is only used internally.
* handle libevent callback for tcp data comm point
* @param fd: file descriptor.
* @param event: event bits from libevent:
* @param event: event bits from libevent:
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
* @param arg: the comm_point structure.
*/
@ -955,7 +957,7 @@ void http2_stream_add_meshstate(struct http2_stream* h2_stream,
* This routine is published for checks and tests, and is only used internally.
* handle libevent callback for timer comm.
* @param fd: file descriptor (always -1).
* @param event: event bits from libevent:
* @param event: event bits from libevent:
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
* @param arg: the comm_timer structure.
*/
@ -965,7 +967,7 @@ void comm_timer_callback(int fd, short event, void* arg);
* This routine is published for checks and tests, and is only used internally.
* handle libevent callback for signal comm.
* @param fd: file descriptor (used for the signal number).
* @param event: event bits from libevent:
* @param event: event bits from libevent:
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
* @param arg: the internal commsignal structure.
*/
@ -975,7 +977,7 @@ void comm_signal_callback(int fd, short event, void* arg);
* This routine is published for checks and tests, and is only used internally.
* libevent callback for AF_UNIX fds
* @param fd: file descriptor.
* @param event: event bits from libevent:
* @param event: event bits from libevent:
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
* @param arg: the comm_point structure.
*/
@ -985,7 +987,7 @@ void comm_point_local_handle_callback(int fd, short event, void* arg);
* This routine is published for checks and tests, and is only used internally.
* libevent callback for raw fd access.
* @param fd: file descriptor.
* @param event: event bits from libevent:
* @param event: event bits from libevent:
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
* @param arg: the comm_point structure.
*/
@ -995,7 +997,7 @@ void comm_point_raw_handle_callback(int fd, short event, void* arg);
* This routine is published for checks and tests, and is only used internally.
* libevent callback for timeout on slow accept.
* @param fd: file descriptor.
* @param event: event bits from libevent:
* @param event: event bits from libevent:
* EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT.
* @param arg: the comm_point structure.
*/

View File

@ -186,7 +186,7 @@ regional_alloc_init(struct regional* r, const void *init, size_t size)
{
void *s = regional_alloc(r, size);
if(!s) return NULL;
memcpy(s, init, size);
memmove(s, init, size);
return s;
}

View File

@ -0,0 +1,75 @@
/*
* util/rfc_1982.c - RFC 1982 Serial Number Arithmetic
*
* Copyright (c) 2023, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions for RFC 1982 serial number arithmetic.
*/
#include "config.h"
#include "util/rfc_1982.h"
int
compare_1982(uint32_t a, uint32_t b)
{
/* for 32 bit values */
const uint32_t cutoff = ((uint32_t) 1 << (32 - 1));
if (a == b) {
return 0;
} else if ((a < b && b - a < cutoff) || (a > b && a - b > cutoff)) {
return -1;
} else {
return 1;
}
}
uint32_t
subtract_1982(uint32_t a, uint32_t b)
{
/* for 32 bit values */
const uint32_t cutoff = ((uint32_t) 1 << (32 - 1));
if(a == b)
return 0;
if(a < b && b - a < cutoff) {
return b-a;
}
if(a > b && a - b > cutoff) {
return ((uint32_t)0xffffffff) - (a-b-1);
}
/* wrong case, b smaller than a */
return 0;
}

View File

@ -0,0 +1,63 @@
/*
* util/rfc_1982.h - RFC 1982 Serial Number Arithmetic
*
* Copyright (c) 2023, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains functions for RFC 1982 serial number arithmetic.
*/
#ifndef RFC_1982_H
#define RFC_1982_H
/**
* RFC 1982 comparison, uses unsigned integers, and tries to avoid
* compiler optimization (eg. by avoiding a-b<0 comparisons).
* @param a: value to compare.
* @param b: value to compare.
* @return 0 if equal, 1 if a > b, else -1.
*/
int compare_1982(uint32_t a, uint32_t b);
/**
* RFC 1982 subtraction, uses unsigned integers, and tries to avoid
* compiler optimization (eg. by avoiding a-b<0 comparisons).
* @param a: value to subtract from.
* @param b: value to subtract.
* @return the difference between them if we know that b is larger than a,
* that is the distance between them in serial number arithmetic.
*/
uint32_t subtract_1982(uint32_t a, uint32_t b);
#endif /* RFC_1982_H */

View File

@ -0,0 +1,192 @@
/*
SipHash reference C implementation
Copyright (c) 2012-2016 Jean-Philippe Aumasson
<jeanphilippe.aumasson@gmail.com>
Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with
this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
/**
* Edited slightly for integration in Unbound. Edits are noted with 'EDIT'.
*/
/** EDIT
* \#include <assert.h>
* \#include <stdint.h>
* \#include <stdio.h>
* \#include <string.h>
* Replaced the above includes with Unbound's config.h
*/
#include "config.h"
/** EDIT
* prevent warning from -Wmissing-prototypes
*/
#include "util/siphash.h"
/* default: SipHash-2-4 */
#define cROUNDS 2
#define dROUNDS 4
#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
#define U32TO8_LE(p, v) \
(p)[0] = (uint8_t)((v)); \
(p)[1] = (uint8_t)((v) >> 8); \
(p)[2] = (uint8_t)((v) >> 16); \
(p)[3] = (uint8_t)((v) >> 24);
#define U64TO8_LE(p, v) \
U32TO8_LE((p), (uint32_t)((v))); \
U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
#define U8TO64_LE(p) \
(((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
#define SIPROUND \
do { \
v0 += v1; \
v1 = ROTL(v1, 13); \
v1 ^= v0; \
v0 = ROTL(v0, 32); \
v2 += v3; \
v3 = ROTL(v3, 16); \
v3 ^= v2; \
v0 += v3; \
v3 = ROTL(v3, 21); \
v3 ^= v0; \
v2 += v1; \
v1 = ROTL(v1, 17); \
v1 ^= v2; \
v2 = ROTL(v2, 32); \
} while (0)
#ifdef DEBUG
#define TRACE \
do { \
printf("(%3d) v0 %08x %08x\n", (int)inlen, (uint32_t)(v0 >> 32), \
(uint32_t)v0); \
printf("(%3d) v1 %08x %08x\n", (int)inlen, (uint32_t)(v1 >> 32), \
(uint32_t)v1); \
printf("(%3d) v2 %08x %08x\n", (int)inlen, (uint32_t)(v2 >> 32), \
(uint32_t)v2); \
printf("(%3d) v3 %08x %08x\n", (int)inlen, (uint32_t)(v3 >> 32), \
(uint32_t)v3); \
} while (0)
#else
#define TRACE
#endif
int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
uint8_t *out, const size_t outlen) {
uint64_t v0 = 0x736f6d6570736575ULL;
uint64_t v1 = 0x646f72616e646f6dULL;
uint64_t v2 = 0x6c7967656e657261ULL;
uint64_t v3 = 0x7465646279746573ULL;
uint64_t k0 = U8TO64_LE(k);
uint64_t k1 = U8TO64_LE(k + 8);
uint64_t m;
int i;
const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
const int left = inlen & 7;
uint64_t b = ((uint64_t)inlen) << 56;
/** EDIT
* The following assert moved here from the top for C90 compliance.
*/
assert((outlen == 8) || (outlen == 16));
v3 ^= k1;
v2 ^= k0;
v1 ^= k1;
v0 ^= k0;
if (outlen == 16)
v1 ^= 0xee;
for (; in != end; in += 8) {
m = U8TO64_LE(in);
v3 ^= m;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= m;
}
switch (left) {
case 7:
b |= ((uint64_t)in[6]) << 48;
/** EDIT annotate case statement fallthrough for gcc */
/* fallthrough */
case 6:
b |= ((uint64_t)in[5]) << 40;
/** EDIT annotate case statement fallthrough for gcc */
/* fallthrough */
case 5:
b |= ((uint64_t)in[4]) << 32;
/** EDIT annotate case statement fallthrough for gcc */
/* fallthrough */
case 4:
b |= ((uint64_t)in[3]) << 24;
/** EDIT annotate case statement fallthrough for gcc */
/* fallthrough */
case 3:
b |= ((uint64_t)in[2]) << 16;
/** EDIT annotate case statement fallthrough for gcc */
/* fallthrough */
case 2:
b |= ((uint64_t)in[1]) << 8;
/** EDIT annotate case statement fallthrough for gcc */
/* fallthrough */
case 1:
b |= ((uint64_t)in[0]);
break;
case 0:
break;
}
v3 ^= b;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= b;
if (outlen == 16)
v2 ^= 0xee;
else
v2 ^= 0xff;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out, b);
if (outlen == 8)
return 0;
v1 ^= 0xdd;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out + 8, b);
return 0;
}

View File

@ -0,0 +1,43 @@
/*
* util/siphash.h - header for SipHash reference C implementation.
*
* Copyright (c) 2023, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
* Contains the SipHash reference C implementation.
*/
#ifndef UTIL_SIPHASH_H
#define UTIL_SIPHASH_H
int siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
uint8_t *out, const size_t outlen);
#endif /* UTIL_SIPHASH_H */

View File

@ -81,6 +81,7 @@ lruhash_create(size_t start_size, size_t maxmem,
table->num = 0;
table->space_used = 0;
table->space_max = maxmem;
table->max_collisions = 0;
table->array = calloc(table->size, sizeof(struct lruhash_bin));
if(!table->array) {
lock_quick_destroy(&table->lock);
@ -216,15 +217,19 @@ reclaim_space(struct lruhash* table, struct lruhash_entry** list)
struct lruhash_entry*
bin_find_entry(struct lruhash* table,
struct lruhash_bin* bin, hashvalue_type hash, void* key)
struct lruhash_bin* bin, hashvalue_type hash, void* key, size_t* collisions)
{
size_t c = 0;
struct lruhash_entry* p = bin->overflow_list;
while(p) {
if(p->hash == hash && table->compfunc(p->key, key) == 0)
return p;
break;
c++;
p = p->overflow_next;
}
return NULL;
if (collisions != NULL)
*collisions = c;
return p;
}
void
@ -303,6 +308,7 @@ lruhash_insert(struct lruhash* table, hashvalue_type hash,
struct lruhash_bin* bin;
struct lruhash_entry* found, *reclaimlist=NULL;
size_t need_size;
size_t collisions;
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
@ -317,12 +323,14 @@ lruhash_insert(struct lruhash* table, hashvalue_type hash,
lock_quick_lock(&bin->lock);
/* see if entry exists already */
if(!(found=bin_find_entry(table, bin, hash, entry->key))) {
if(!(found=bin_find_entry(table, bin, hash, entry->key, &collisions))) {
/* if not: add to bin */
entry->overflow_next = bin->overflow_list;
bin->overflow_list = entry;
lru_front(table, entry);
table->num++;
if (table->max_collisions < collisions)
table->max_collisions = collisions;
table->space_used += need_size;
} else {
/* if so: update data - needs a writelock */
@ -362,7 +370,7 @@ lruhash_lookup(struct lruhash* table, hashvalue_type hash, void* key, int wr)
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
if((entry=bin_find_entry(table, bin, hash, key)))
if((entry=bin_find_entry(table, bin, hash, key, NULL)))
lru_touch(table, entry);
lock_quick_unlock(&table->lock);
@ -389,7 +397,7 @@ lruhash_remove(struct lruhash* table, hashvalue_type hash, void* key)
lock_quick_lock(&table->lock);
bin = &table->array[hash & table->size_mask];
lock_quick_lock(&bin->lock);
if((entry=bin_find_entry(table, bin, hash, key))) {
if((entry=bin_find_entry(table, bin, hash, key, NULL))) {
bin_overflow_remove(bin, entry);
lru_remove(table, entry);
} else {
@ -579,6 +587,7 @@ lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
struct lruhash_bin* bin;
struct lruhash_entry* found, *reclaimlist = NULL;
size_t need_size;
size_t collisions;
fptr_ok(fptr_whitelist_hash_sizefunc(table->sizefunc));
fptr_ok(fptr_whitelist_hash_delkeyfunc(table->delkeyfunc));
fptr_ok(fptr_whitelist_hash_deldatafunc(table->deldatafunc));
@ -593,7 +602,7 @@ lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
lock_quick_lock(&bin->lock);
/* see if entry exists already */
if ((found = bin_find_entry(table, bin, hash, entry->key)) != NULL) {
if ((found = bin_find_entry(table, bin, hash, entry->key, &collisions)) != NULL) {
/* if so: keep the existing data - acquire a writelock */
lock_rw_wrlock(&found->lock);
}
@ -604,6 +613,8 @@ lruhash_insert_or_retrieve(struct lruhash* table, hashvalue_type hash,
bin->overflow_list = entry;
lru_front(table, entry);
table->num++;
if (table->max_collisions < collisions)
table->max_collisions = collisions;
table->space_used += need_size;
/* return the entry that was presented, and lock it */
found = entry;

View File

@ -178,6 +178,8 @@ struct lruhash {
size_t space_used;
/** the amount of space the hash table is maximally allowed to use. */
size_t space_max;
/** the maximum collisions were detected during the lruhash_insert operations. */
size_t max_collisions;
};
/**
@ -357,10 +359,11 @@ void bin_delete(struct lruhash* table, struct lruhash_bin* bin);
* @param bin: hash bin to look into.
* @param hash: hash value to look for.
* @param key: key to look for.
* @param collisions: how many collisions were found during the search.
* @return: the entry or NULL if not found.
*/
struct lruhash_entry* bin_find_entry(struct lruhash* table,
struct lruhash_bin* bin, hashvalue_type hash, void* key);
struct lruhash_bin* bin, hashvalue_type hash, void* key, size_t* collisions);
/**
* Remove entry from bin overflow chain.

View File

@ -242,3 +242,21 @@ size_t count_slabhash_entries(struct slabhash* sh)
}
return cnt;
}
void get_slabhash_stats(struct slabhash* sh, long long* num, long long* collisions)
{
size_t slab, cnt = 0, max_collisions = 0;
for(slab=0; slab<sh->size; slab++) {
lock_quick_lock(&sh->array[slab]->lock);
cnt += sh->array[slab]->num;
if (max_collisions < sh->array[slab]->max_collisions) {
max_collisions = sh->array[slab]->max_collisions;
}
lock_quick_unlock(&sh->array[slab]->lock);
}
if (num != NULL)
*num = cnt;
if (collisions != NULL)
*collisions = max_collisions;
}

View File

@ -200,6 +200,15 @@ void slabhash_traverse(struct slabhash* table, int wr,
*/
size_t count_slabhash_entries(struct slabhash* table);
/**
* Retrieves number of items in slabhash and the current max collision level
* @param table: slabbed hash table.
* @param entries_count: where to save the current number of elements.
* @param max_collisions: where to save the current max collisions level.
*/
void get_slabhash_stats(struct slabhash* table,
long long* entries_count, long long* max_collisions);
/* --- test representation --- */
/** test structure contains test key */
struct slabhash_testkey {

View File

@ -4,22 +4,22 @@
* Copyright (c) 2007, NLnet Labs. All rights reserved.
*
* This software is open source.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -46,6 +46,7 @@
#include <sys/types.h>
#include "util/timehist.h"
#include "util/log.h"
#include "util/timeval_func.h"
/** special timestwo operation for time values in histogram setup */
static void
@ -83,12 +84,12 @@ dosetup(struct timehist* hist)
struct timehist* timehist_setup(void)
{
struct timehist* hist = (struct timehist*)calloc(1,
struct timehist* hist = (struct timehist*)calloc(1,
sizeof(struct timehist));
if(!hist)
return NULL;
hist->num = NUM_BUCKETS_HIST;
hist->buckets = (struct th_buck*)calloc(hist->num,
hist->buckets = (struct th_buck*)calloc(hist->num,
sizeof(struct th_buck));
if(!hist->buckets) {
free(hist);
@ -114,23 +115,6 @@ void timehist_clear(struct timehist* hist)
hist->buckets[i].count = 0;
}
/** histogram compare of time values */
static int
timeval_smaller(const struct timeval* x, const struct timeval* y)
{
#ifndef S_SPLINT_S
if(x->tv_sec < y->tv_sec)
return 1;
else if(x->tv_sec == y->tv_sec) {
if(x->tv_usec <= y->tv_usec)
return 1;
else return 0;
}
else return 0;
#endif
}
void timehist_insert(struct timehist* hist, struct timeval* tv)
{
size_t i;
@ -194,7 +178,7 @@ timehist_count(struct timehist* hist)
return res;
}
double
double
timehist_quartile(struct timehist* hist, double q)
{
double lookfor, passed, res;
@ -209,22 +193,22 @@ timehist_quartile(struct timehist* hist, double q)
lookfor *= q;
passed = 0;
i = 0;
while(i+1 < hist->num &&
while(i+1 < hist->num &&
passed+(double)hist->buckets[i].count < lookfor) {
passed += (double)hist->buckets[i++].count;
}
/* got the right bucket */
#ifndef S_SPLINT_S
low = (double)hist->buckets[i].lower.tv_sec +
low = (double)hist->buckets[i].lower.tv_sec +
(double)hist->buckets[i].lower.tv_usec/1000000.;
up = (double)hist->buckets[i].upper.tv_sec +
up = (double)hist->buckets[i].upper.tv_sec +
(double)hist->buckets[i].upper.tv_usec/1000000.;
#endif
res = (lookfor - passed)*(up-low)/((double)hist->buckets[i].count);
return low+res;
}
void
void
timehist_export(struct timehist* hist, long long* array, size_t sz)
{
size_t i;
@ -235,7 +219,7 @@ timehist_export(struct timehist* hist, long long* array, size_t sz)
array[i] = (long long)hist->buckets[i].count;
}
void
void
timehist_import(struct timehist* hist, long long* array, size_t sz)
{
size_t i;

View File

@ -0,0 +1,113 @@
/*
* util/timeval_func.c - helpers to work with struct timeval values.
*
* Copyright (c) 2023, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains helpers to manipulate struct timeval values.
*/
#include "config.h"
#include "timeval_func.h"
/** subtract timers and the values do not overflow or become negative */
void
timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start)
{
#ifndef S_SPLINT_S
time_t end_usec = end->tv_usec;
d->tv_sec = end->tv_sec - start->tv_sec;
if(end_usec < start->tv_usec) {
end_usec += 1000000;
d->tv_sec--;
}
d->tv_usec = end_usec - start->tv_usec;
#endif
}
/** add timers and the values do not overflow or become negative */
void
timeval_add(struct timeval* d, const struct timeval* add)
{
#ifndef S_SPLINT_S
d->tv_sec += add->tv_sec;
d->tv_usec += add->tv_usec;
if(d->tv_usec >= 1000000 ) {
d->tv_usec -= 1000000;
d->tv_sec++;
}
#endif
}
/** divide sum of timers to get average */
void
timeval_divide(struct timeval* avg, const struct timeval* sum, long long d)
{
#ifndef S_SPLINT_S
long long leftover;
if(d <= 0) {
avg->tv_sec = 0;
avg->tv_usec = 0;
return;
}
avg->tv_sec = sum->tv_sec / d;
avg->tv_usec = sum->tv_usec / d;
/* handle fraction from seconds divide */
leftover = sum->tv_sec - avg->tv_sec*d;
if(leftover <= 0)
leftover = 0;
avg->tv_usec += (((long long)leftover)*((long long)1000000))/d;
if(avg->tv_sec < 0)
avg->tv_sec = 0;
if(avg->tv_usec < 0)
avg->tv_usec = 0;
#endif
}
/** histogram compare of time values */
int
timeval_smaller(const struct timeval* x, const struct timeval* y)
{
#ifndef S_SPLINT_S
if(x->tv_sec < y->tv_sec)
return 1;
else if(x->tv_sec == y->tv_sec) {
if(x->tv_usec <= y->tv_usec)
return 1;
else return 0;
}
else return 0;
#endif
}

View File

@ -0,0 +1,53 @@
/*
* util/timeval_func.h - definitions of helpers for struct timeval values.
*
* Copyright (c) 2023, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains definitions of helpers to manipulate struct timeval
* values, implemented in the corresponding C file.
*/
#include <sys/time.h>
#ifndef timeval_isset
#define timeval_isset(tv) ((tv)->tv_sec || (tv)->tv_usec)
#endif
#ifndef timeval_clear
#define timeval_clear(tv) ((tv)->tv_sec = (tv)->tv_usec = 0)
#endif
void timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start);
void timeval_add(struct timeval* d, const struct timeval* add);
void timeval_divide(struct timeval* avg, const struct timeval* sum, long long d);
int timeval_smaller(const struct timeval* x, const struct timeval* y);

View File

@ -45,6 +45,9 @@
#include "util/netevent.h"
#include "util/fptr_wlist.h"
#include "util/ub_event.h"
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifndef USE_WINSOCK
/* on unix */
@ -396,20 +399,28 @@ int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len,
return 1;
}
/** perform a select() on the fd */
/** perform poll() on the fd */
static int
pollit(int fd, struct timeval* t)
{
fd_set r;
struct pollfd fds;
int pret;
int msec = -1;
memset(&fds, 0, sizeof(fds));
fds.fd = fd;
fds.events = POLLIN | POLLERR | POLLHUP;
#ifndef S_SPLINT_S
FD_ZERO(&r);
FD_SET(FD_SET_T fd, &r);
if(t)
msec = t->tv_sec*1000 + t->tv_usec/1000;
#endif
if(select(fd+1, &r, NULL, NULL, t) == -1) {
pret = poll(&fds, 1, msec);
if(pret == -1)
return 0;
}
errno = 0;
return (int)(FD_ISSET(fd, &r));
if(pret != 0)
return 1;
return 0;
}
int tube_poll(struct tube* tube)
@ -426,24 +437,27 @@ int tube_wait(struct tube* tube)
int tube_wait_timeout(struct tube* tube, int msec)
{
struct timeval t;
int fd = tube->sr;
fd_set r;
t.tv_sec = msec/1000;
t.tv_usec = (msec%1000)*1000;
#ifndef S_SPLINT_S
FD_ZERO(&r);
FD_SET(FD_SET_T fd, &r);
#endif
int ret = 0;
while(1) {
if(select(fd+1, &r, NULL, NULL, &t) == -1) {
struct pollfd fds;
memset(&fds, 0, sizeof(fds));
fds.fd = tube->sr;
fds.events = POLLIN | POLLERR | POLLHUP;
ret = poll(&fds, 1, msec);
if(ret == -1) {
if(errno == EAGAIN || errno == EINTR)
continue;
return -1;
}
break;
}
return (int)(FD_ISSET(fd, &r));
if(ret != 0)
return 1;
return 0;
}
int tube_read_fd(struct tube* tube)
@ -529,6 +543,7 @@ struct tube* tube_create(void)
if(tube->event == WSA_INVALID_EVENT) {
free(tube);
log_err("WSACreateEvent: %s", wsa_strerror(WSAGetLastError()));
return NULL;
}
if(!WSAResetEvent(tube->event)) {
log_err("WSAResetEvent: %s", wsa_strerror(WSAGetLastError()));

View File

@ -2376,6 +2376,8 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp)
edns.opt_list_out = NULL;
edns.opt_list_inplace_cb_out = NULL;
edns.padding_block_size = 0;
edns.cookie_present = 0;
edns.cookie_valid = 0;
if(sldns_buffer_capacity(buf) < 65535)
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
else edns.udp_size = 65535;

View File

@ -81,17 +81,11 @@ key_cache_delete(struct key_cache* kcache)
void
key_cache_insert(struct key_cache* kcache, struct key_entry_key* kkey,
struct module_qstate* qstate)
int copy_reason)
{
struct key_entry_key* k = key_entry_copy(kkey);
struct key_entry_key* k = key_entry_copy(kkey, copy_reason);
if(!k)
return;
if(key_entry_isbad(k) && qstate->errinf &&
qstate->env->cfg->val_log_level >= 2) {
/* on malloc failure there is simply no reason string */
key_entry_set_reason(k, errinf_to_str_bogus(qstate));
key_entry_set_reason_bogus(k, errinf_to_reason_bogus(qstate));
}
key_entry_hash(k);
slabhash_insert(kcache->slab, k->entry.hash, &k->entry,
k->entry.data, NULL);

View File

@ -76,10 +76,10 @@ void key_cache_delete(struct key_cache* kcache);
* @param kcache: the key cache.
* @param kkey: key entry key, assumed malloced in a region, is copied
* to perform update or insertion. Its data pointer is also copied.
* @param qstate: store errinf reason in case its bad.
* @param copy_reason: if the reason string needs to be copied (allocated).
*/
void key_cache_insert(struct key_cache* kcache, struct key_entry_key* kkey,
struct module_qstate* qstate);
int copy_reason);
/**
* Remove an entry from the key cache.

View File

@ -152,7 +152,7 @@ key_entry_copy_toregion(struct key_entry_key* kkey, struct regional* region)
}
struct key_entry_key*
key_entry_copy(struct key_entry_key* kkey)
key_entry_copy(struct key_entry_key* kkey, int copy_reason)
{
struct key_entry_key* newk;
if(!kkey)
@ -190,7 +190,7 @@ key_entry_copy(struct key_entry_key* kkey)
}
packed_rrset_ptr_fixup(newd->rrset_data);
}
if(d->reason) {
if(copy_reason && d->reason && *d->reason != 0) {
newd->reason = strdup(d->reason);
if(!newd->reason) {
free(newd->rrset_data);
@ -199,6 +199,8 @@ key_entry_copy(struct key_entry_key* kkey)
free(newk);
return NULL;
}
} else {
newd->reason = NULL;
}
if(d->algo) {
newd->algo = (uint8_t*)strdup((char*)d->algo);
@ -237,22 +239,6 @@ key_entry_isbad(struct key_entry_key* kkey)
return (int)(d->isbad);
}
void
key_entry_set_reason(struct key_entry_key* kkey, char* reason)
{
struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
d->reason = reason;
}
void
key_entry_set_reason_bogus(struct key_entry_key* kkey, sldns_ede_code ede)
{
struct key_entry_data* d = (struct key_entry_data*)kkey->entry.data;
if (ede != LDNS_EDE_NONE) { /* reason_bogus init is LDNS_EDE_NONE already */
d->reason_bogus = ede;
}
}
char*
key_entry_get_reason(struct key_entry_key* kkey)
{
@ -294,6 +280,7 @@ key_entry_setup(struct regional* region,
struct key_entry_key*
key_entry_create_null(struct regional* region,
uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
sldns_ede_code reason_bogus, const char* reason,
time_t now)
{
struct key_entry_key* k;
@ -302,8 +289,10 @@ key_entry_create_null(struct regional* region,
return NULL;
d->ttl = now + ttl;
d->isbad = 0;
d->reason = NULL;
d->reason_bogus = LDNS_EDE_NONE;
d->reason = (!reason || *reason == 0)
?NULL :(char*)regional_strdup(region, reason);
/* On allocation error we don't store the reason string */
d->reason_bogus = reason_bogus;
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
d->rrset_data = NULL;
d->algo = NULL;
@ -313,7 +302,9 @@ key_entry_create_null(struct regional* region,
struct key_entry_key*
key_entry_create_rrset(struct regional* region,
uint8_t* name, size_t namelen, uint16_t dclass,
struct ub_packed_rrset_key* rrset, uint8_t* sigalg, time_t now)
struct ub_packed_rrset_key* rrset, uint8_t* sigalg,
sldns_ede_code reason_bogus, const char* reason,
time_t now)
{
struct key_entry_key* k;
struct key_entry_data* d;
@ -323,8 +314,10 @@ key_entry_create_rrset(struct regional* region,
return NULL;
d->ttl = rd->ttl + now;
d->isbad = 0;
d->reason = NULL;
d->reason_bogus = LDNS_EDE_NONE;
d->reason = (!reason || *reason == 0)
?NULL :(char*)regional_strdup(region, reason);
/* On allocation error we don't store the reason string */
d->reason_bogus = reason_bogus;
d->rrset_type = ntohs(rrset->rk.type);
d->rrset_data = (struct packed_rrset_data*)regional_alloc_init(region,
rd, packed_rrset_sizeof(rd));
@ -341,7 +334,8 @@ key_entry_create_rrset(struct regional* region,
struct key_entry_key*
key_entry_create_bad(struct regional* region,
uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
sldns_ede_code reason_bogus, const char* reason,
time_t now)
{
struct key_entry_key* k;
@ -350,8 +344,10 @@ key_entry_create_bad(struct regional* region,
return NULL;
d->ttl = now + ttl;
d->isbad = 1;
d->reason = NULL;
d->reason_bogus = LDNS_EDE_NONE;
d->reason = (!reason || *reason == 0)
?NULL :(char*)regional_strdup(region, reason);
/* On allocation error we don't store the reason string */
d->reason_bogus = reason_bogus;
d->rrset_type = LDNS_RR_TYPE_DNSKEY;
d->rrset_data = NULL;
d->algo = NULL;

View File

@ -120,9 +120,11 @@ struct key_entry_key* key_entry_copy_toregion(struct key_entry_key* kkey,
/**
* Copy a key entry, malloced.
* @param kkey: the key entry key (and data pointer) to copy.
* @param copy_reason: if the reason string needs to be copied (allocated).
* @return newly allocated entry or NULL on a failure to allocate memory.
*/
struct key_entry_key* key_entry_copy(struct key_entry_key* kkey);
struct key_entry_key* key_entry_copy(struct key_entry_key* kkey,
int copy_reason);
/**
* See if this is a null entry. Does not do locking.
@ -145,23 +147,6 @@ int key_entry_isgood(struct key_entry_key* kkey);
*/
int key_entry_isbad(struct key_entry_key* kkey);
/**
* Set reason why a key is bad.
* @param kkey: bad key.
* @param reason: string to attach, you must allocate it.
* Not safe to call twice unless you deallocate it yourself.
*/
void key_entry_set_reason(struct key_entry_key* kkey, char* reason);
/**
* Set the EDE (RFC8914) code why the key is bad, if it
* exists (so not LDNS_EDE_NONE).
* @param kkey: bad key.
* @param ede: EDE code to attach to this key.
*/
void key_entry_set_reason_bogus(struct key_entry_key* kkey, sldns_ede_code ede);
/**
* Get reason why a key is bad.
* @param kkey: bad key
@ -184,11 +169,14 @@ sldns_ede_code key_entry_get_reason_bogus(struct key_entry_key* kkey);
* @param namelen: length of name
* @param dclass: class of key entry. (host order);
* @param ttl: what ttl should the key have. relative.
* @param reason_bogus: accompanying EDE code.
* @param reason: accompanying NULL-terminated EDE string (or NULL).
* @param now: current time (added to ttl).
* @return new key entry or NULL on alloc failure
*/
struct key_entry_key* key_entry_create_null(struct regional* region,
uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
sldns_ede_code reason_bogus, const char* reason,
time_t now);
/**
@ -199,12 +187,16 @@ struct key_entry_key* key_entry_create_null(struct regional* region,
* @param dclass: class of key entry. (host order);
* @param rrset: data for key entry. This is copied to the region.
* @param sigalg: signalled algorithm list (or NULL).
* @param reason_bogus: accompanying EDE code (usually LDNS_EDE_NONE).
* @param reason: accompanying NULL-terminated EDE string (or NULL).
* @param now: current time (added to ttl of rrset)
* @return new key entry or NULL on alloc failure
*/
struct key_entry_key* key_entry_create_rrset(struct regional* region,
uint8_t* name, size_t namelen, uint16_t dclass,
struct ub_packed_rrset_key* rrset, uint8_t* sigalg, time_t now);
uint8_t* name, size_t namelen, uint16_t dclass,
struct ub_packed_rrset_key* rrset, uint8_t* sigalg,
sldns_ede_code reason_bogus, const char* reason,
time_t now);
/**
* Create a bad entry, in the given region.
@ -213,11 +205,14 @@ struct key_entry_key* key_entry_create_rrset(struct regional* region,
* @param namelen: length of name
* @param dclass: class of key entry. (host order);
* @param ttl: what ttl should the key have. relative.
* @param reason_bogus: accompanying EDE code.
* @param reason: accompanying NULL-terminated EDE string (or NULL).
* @param now: current time (added to ttl).
* @return new key entry or NULL on alloc failure
*/
struct key_entry_key* key_entry_create_bad(struct regional* region,
uint8_t* name, size_t namelen, uint16_t dclass, time_t ttl,
sldns_ede_code reason_bogus, const char* reason,
time_t now);
/**

View File

@ -43,7 +43,7 @@
*/
#include "config.h"
#ifdef HAVE_OPENSSL_SSL_H
#include "openssl/ssl.h"
#include <openssl/ssl.h>
#define NSEC3_SHA_LEN SHA_DIGEST_LENGTH
#else
#define NSEC3_SHA_LEN 20
@ -1407,6 +1407,11 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
/* Matching NSEC, use to generate No Data answer. Not creating answers
* yet for No Data proven using wildcard. */
if(nsec && nsec_proves_nodata(nsec, qinfo, &nodata_wc) && !nodata_wc) {
/* do not create nodata answers for qtype ANY, it is a query
* type, not an rrtype to disprove. Nameerrors are useful for
* qtype ANY, in the else branch. */
if(qinfo->qtype == LDNS_RR_TYPE_ANY)
return NULL;
if(!(msg = dns_msg_create(qinfo->qname, qinfo->qname_len,
qinfo->qtype, qinfo->qclass, region, 2)))
return NULL;

View File

@ -174,9 +174,10 @@ val_nsec_proves_no_ds(struct ub_packed_rrset_key* nsec,
/** check security status from cache or verify rrset, returns true if secure */
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, struct module_qstate* qstate)
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 packed_rrset_data* d = (struct packed_rrset_data*)
nsec->entry.data;
@ -187,7 +188,7 @@ 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,
NULL, LDNS_SECTION_AUTHORITY, qstate);
reason_bogus, LDNS_SECTION_AUTHORITY, qstate);
if(d->security == sec_status_secure) {
rrset_update_sec_status(env->rrset_cache, nsec, *env->now);
return 1;
@ -199,7 +200,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,
struct module_qstate* qstate)
sldns_ede_code* reason_bogus, struct module_qstate* qstate)
{
struct ub_packed_rrset_key* nsec = reply_find_rrset_section_ns(
rep, qinfo->qname, qinfo->qname_len, LDNS_RR_TYPE_NSEC,
@ -216,7 +217,8 @@ val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
* 1) this is a delegation point and there is no DS
* 2) this is not a delegation point */
if(nsec) {
if(!nsec_verify_rrset(env, ve, nsec, kkey, reason, qstate)) {
if(!nsec_verify_rrset(env, ve, nsec, kkey, reason,
reason_bogus, qstate)) {
verbose(VERB_ALGO, "NSEC RRset for the "
"referral did not verify.");
return sec_status_bogus;
@ -225,6 +227,7 @@ val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
if(sec == sec_status_bogus) {
/* something was wrong. */
*reason = "NSEC does not prove absence of DS";
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
return sec;
} else if(sec == sec_status_insecure) {
/* this wasn't a delegation point. */
@ -246,9 +249,11 @@ 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,
qstate)) {
reason_bogus, qstate)) {
verbose(VERB_ALGO, "NSEC for empty non-terminal "
"did not verify.");
*reason = "NSEC for empty non-terminal "
"did not verify.";
return sec_status_bogus;
}
if(nsec_proves_nodata(rep->rrsets[i], qinfo, &wc)) {

View File

@ -44,6 +44,7 @@
#ifndef VALIDATOR_VAL_NSEC_H
#define VALIDATOR_VAL_NSEC_H
#include "util/data/packed_rrset.h"
#include "sldns/rrdef.h"
struct val_env;
struct module_env;
struct module_qstate;
@ -65,6 +66,7 @@ struct key_entry_key;
* @param kkey: key entry to use for verification of signatures.
* @param proof_ttl: if secure, the TTL of how long this proof lasts.
* @param reason: string explaining why bogus.
* @param reason_bogus: relevant EDE code for validation failure.
* @param qstate: qstate with region.
* @return security status.
* SECURE: proved absence of DS.
@ -75,7 +77,8 @@ struct key_entry_key;
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, struct module_qstate* qstate);
time_t* proof_ttl, char** reason, sldns_ede_code* reason_bogus,
struct module_qstate* qstate);
/**
* nsec typemap check, takes an NSEC-type bitmap as argument, checks for type.

View File

@ -48,6 +48,7 @@
#include "util/data/msgparse.h"
#include "util/data/dname.h"
#include "util/rbtree.h"
#include "util/rfc_1982.h"
#include "util/module.h"
#include "util/net_help.h"
#include "util/regional.h"
@ -718,9 +719,9 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
}
verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus");
if(!numchecked) {
*reason = "signature missing";
*reason = "signature for expected key and algorithm missing";
if(reason_bogus)
*reason_bogus = LDNS_EDE_RRSIGS_MISSING;
*reason_bogus = LDNS_EDE_DNSSEC_BOGUS;
} else if(numchecked == numindeterminate) {
verbose(VERB_ALGO, "rrset failed to verify due to algorithm "
"refusal by cryptolib");
@ -1378,44 +1379,6 @@ sigdate_error(const char* str, int32_t expi, int32_t incep, int32_t now)
(unsigned)incep, (unsigned)now);
}
/** RFC 1982 comparison, uses unsigned integers, and tries to avoid
* compiler optimization (eg. by avoiding a-b<0 comparisons),
* this routine matches compare_serial(), for SOA serial number checks */
static int
compare_1982(uint32_t a, uint32_t b)
{
/* for 32 bit values */
const uint32_t cutoff = ((uint32_t) 1 << (32 - 1));
if (a == b) {
return 0;
} else if ((a < b && b - a < cutoff) || (a > b && a - b > cutoff)) {
return -1;
} else {
return 1;
}
}
/** if we know that b is larger than a, return the difference between them,
* that is the distance between them. in RFC1982 arith */
static uint32_t
subtract_1982(uint32_t a, uint32_t b)
{
/* for 32 bit values */
const uint32_t cutoff = ((uint32_t) 1 << (32 - 1));
if(a == b)
return 0;
if(a < b && b - a < cutoff) {
return b-a;
}
if(a > b && a - b > cutoff) {
return ((uint32_t)0xffffffff) - (a-b-1);
}
/* wrong case, b smaller than a */
return 0;
}
/** check rrsig dates */
static int
check_dates(struct val_env* ve, uint32_t unow, uint8_t* expi_p,

View File

@ -587,16 +587,18 @@ val_verify_new_DNSKEYs(struct regional* region, struct module_env* env,
return key_entry_create_rrset(region,
ds_rrset->rk.dname, ds_rrset->rk.dname_len,
ntohs(ds_rrset->rk.rrset_class), dnskey_rrset,
downprot?sigalg:NULL, *env->now);
downprot?sigalg:NULL, LDNS_EDE_NONE, NULL,
*env->now);
} else if(sec == sec_status_insecure) {
return key_entry_create_null(region, ds_rrset->rk.dname,
ds_rrset->rk.dname_len,
ds_rrset->rk.dname_len,
ntohs(ds_rrset->rk.rrset_class),
rrset_get_ttl(ds_rrset), *env->now);
rrset_get_ttl(ds_rrset), *reason_bogus, *reason,
*env->now);
}
return key_entry_create_bad(region, ds_rrset->rk.dname,
ds_rrset->rk.dname_len, ntohs(ds_rrset->rk.rrset_class),
BOGUS_KEY_TTL, *env->now);
BOGUS_KEY_TTL, *reason_bogus, *reason, *env->now);
}
enum sec_status
@ -694,7 +696,7 @@ val_verify_DNSKEY_with_TA(struct module_env* env, struct val_env* ve,
has_useful_ta = 1;
sec = dnskey_verify_rrset(env, ve, dnskey_rrset,
ta_dnskey, i, reason, NULL, LDNS_SECTION_ANSWER, qstate);
ta_dnskey, i, reason, reason_bogus, LDNS_SECTION_ANSWER, qstate);
if(sec == sec_status_secure) {
if(!sigalg || algo_needs_set_secure(&needs,
(uint8_t)dnskey_get_algo(ta_dnskey, i))) {
@ -743,16 +745,17 @@ val_verify_new_DNSKEYs_with_ta(struct regional* region, struct module_env* env,
return key_entry_create_rrset(region,
dnskey_rrset->rk.dname, dnskey_rrset->rk.dname_len,
ntohs(dnskey_rrset->rk.rrset_class), dnskey_rrset,
downprot?sigalg:NULL, *env->now);
downprot?sigalg:NULL, LDNS_EDE_NONE, NULL, *env->now);
} else if(sec == sec_status_insecure) {
return key_entry_create_null(region, dnskey_rrset->rk.dname,
dnskey_rrset->rk.dname_len,
ntohs(dnskey_rrset->rk.rrset_class),
rrset_get_ttl(dnskey_rrset), *env->now);
rrset_get_ttl(dnskey_rrset), *reason_bogus, *reason,
*env->now);
}
return key_entry_create_bad(region, dnskey_rrset->rk.dname,
dnskey_rrset->rk.dname_len, ntohs(dnskey_rrset->rk.rrset_class),
BOGUS_KEY_TTL, *env->now);
BOGUS_KEY_TTL, *reason_bogus, *reason, *env->now);
}
int

View File

@ -70,16 +70,16 @@ static void process_ds_response(struct module_qstate* qstate,
struct query_info* qinfo, struct sock_list* origin);
/* Updates the suplied EDE (RFC8914) code selectively so we don't loose
* a more specific code
*/
/* Updates the suplied EDE (RFC8914) code selectively so we don't lose
* a more specific code */
static void
update_reason_bogus(struct reply_info* rep, sldns_ede_code reason_bogus)
{
if (rep->reason_bogus == LDNS_EDE_DNSSEC_BOGUS ||
rep->reason_bogus == LDNS_EDE_NONE) {
rep->reason_bogus = reason_bogus;
}
if(reason_bogus == LDNS_EDE_NONE) return;
if(reason_bogus == LDNS_EDE_DNSSEC_BOGUS
&& rep->reason_bogus != LDNS_EDE_NONE
&& rep->reason_bogus != LDNS_EDE_DNSSEC_BOGUS) return;
rep->reason_bogus = reason_bogus;
}
@ -1672,20 +1672,13 @@ processInit(struct module_qstate* qstate, struct val_qstate* vq,
vq->state = VAL_FINISHED_STATE;
return 1;
} else if(key_entry_isbad(vq->key_entry)) {
sldns_ede_code ede = LDNS_EDE_DNSSEC_BOGUS;
/* the key could have a more spefic EDE than just bogus */
if(key_entry_get_reason_bogus(vq->key_entry) != LDNS_EDE_NONE) {
ede = key_entry_get_reason_bogus(vq->key_entry);
}
/* Bad keys should have the relevant EDE code and text */
sldns_ede_code ede = key_entry_get_reason_bogus(vq->key_entry);
/* key is bad, chain is bad, reply is bogus */
errinf_dname(qstate, "key for validation", vq->key_entry->name);
errinf_ede(qstate, "is marked as invalid", ede);
if(key_entry_get_reason(vq->key_entry)) {
errinf(qstate, "because of a previous");
errinf(qstate, key_entry_get_reason(vq->key_entry));
}
errinf(qstate, "because of a previous");
errinf(qstate, key_entry_get_reason(vq->key_entry));
/* no retries, stop bothering the authority until timeout */
vq->restart_count = ve->max_restart;
@ -1888,7 +1881,8 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
vq->chase_reply->security = sec_status_insecure;
val_mark_insecure(vq->chase_reply, vq->key_entry->name,
qstate->env->rrset_cache, qstate->env);
key_cache_insert(ve->kcache, vq->key_entry, qstate);
key_cache_insert(ve->kcache, vq->key_entry,
qstate->env->cfg->val_log_level >= 2);
return 1;
}
@ -1897,12 +1891,13 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
"of trust to keys for", vq->key_entry->name,
LDNS_RR_TYPE_DNSKEY, vq->key_entry->key_class);
vq->chase_reply->security = sec_status_bogus;
update_reason_bogus(vq->chase_reply, LDNS_EDE_DNSKEY_MISSING);
update_reason_bogus(vq->chase_reply,
key_entry_get_reason_bogus(vq->key_entry));
errinf_ede(qstate, "while building chain of trust",
LDNS_EDE_DNSKEY_MISSING);
key_entry_get_reason_bogus(vq->key_entry));
if(vq->restart_count >= ve->max_restart)
key_cache_insert(ve->kcache, vq->key_entry, qstate);
key_cache_insert(ve->kcache, vq->key_entry,
qstate->env->cfg->val_log_level >= 2);
return 1;
}
@ -2151,9 +2146,19 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
log_query_info(NO_VERBOSE, "validation failure",
&qstate->qinfo);
else {
char* err = errinf_to_str_bogus(qstate);
if(err) log_info("%s", err);
free(err);
char* err_str = errinf_to_str_bogus(qstate);
if(err_str) {
size_t err_str_len = strlen(err_str);
log_info("%s", err_str);
/* allocate space and store the error
* string */
vq->orig_msg->rep->reason_bogus_str = regional_alloc(
qstate->region,
sizeof(char) * (err_str_len+1));
memcpy(vq->orig_msg->rep->reason_bogus_str,
err_str, err_str_len+1);
}
free(err_str);
}
}
/*
@ -2195,6 +2200,9 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
}
}
}
/* Update rep->reason_bogus as it is the one being cached */
update_reason_bogus(vq->orig_msg->rep, errinf_to_reason_bogus(qstate));
/* store results in cache */
if(qstate->query_flags&BIT_RD) {
/* if secure, this will override cache anyway, no need
@ -2370,13 +2378,17 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
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(qstate->env->cfg->harden_dnssec_stripped) {
errinf_ede(qstate, "no DNSKEY rrset", LDNS_EDE_DNSKEY_MISSING);
errinf_ede(qstate, reason, reason_bogus);
kkey = key_entry_create_bad(qstate->region, ta->name,
ta->namelen, ta->dclass, BOGUS_KEY_TTL,
reason_bogus, reason,
*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);
if(!kkey) {
log_err("out of memory: allocate fail prime key");
@ -2409,9 +2421,11 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
errinf_ede(qstate, reason, reason_bogus);
kkey = key_entry_create_bad(qstate->region, ta->name,
ta->namelen, ta->dclass, BOGUS_KEY_TTL,
reason_bogus, reason,
*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);
if(!kkey) {
log_err("out of memory: allocate null prime key");
@ -2458,8 +2472,9 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
/* errors here pretty much break validation */
verbose(VERB_DETAIL, "DS response was error, thus bogus");
errinf(qstate, rc);
errinf_ede(qstate, "no DS", LDNS_EDE_NETWORK_ERROR);
reason = "no DS";
reason_bogus = LDNS_EDE_NETWORK_ERROR;
errinf_ede(qstate, reason, reason_bogus);
goto return_bogus;
}
@ -2473,7 +2488,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
if(!ds) {
log_warn("internal error: POSITIVE DS response was "
"missing DS.");
errinf_ede(qstate, "no DS record", LDNS_EDE_DNSSEC_BOGUS);
reason = "no DS record";
errinf_ede(qstate, reason, reason_bogus);
goto return_bogus;
}
/* Verify only returns BOGUS or SECURE. If the rrset is
@ -2492,13 +2508,11 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
if(!val_dsset_isusable(ds)) {
/* If they aren't usable, then we treat it like
* there was no DS. */
/* TODO add EDE Unsupported DS Digest Type; this needs
* EDE to be added on non SERVFAIL answers. */
*ke = key_entry_create_null(qstate->region,
qinfo->qname, qinfo->qname_len, qinfo->qclass,
ub_packed_rrset_ttl(ds), *qstate->env->now);
*ke = key_entry_create_null(qstate->region,
qinfo->qname, qinfo->qname_len, qinfo->qclass,
ub_packed_rrset_ttl(ds),
LDNS_EDE_UNSUPPORTED_DS_DIGEST, NULL,
*qstate->env->now);
return (*ke) != NULL;
}
@ -2506,7 +2520,7 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
log_query_info(VERB_DETAIL, "validated DS", qinfo);
*ke = key_entry_create_rrset(qstate->region,
qinfo->qname, qinfo->qname_len, qinfo->qclass, ds,
NULL, *qstate->env->now);
NULL, LDNS_EDE_NONE, NULL, *qstate->env->now);
return (*ke) != NULL;
} else if(subtype == VAL_CLASS_NODATA ||
subtype == VAL_CLASS_NAMEERROR) {
@ -2518,7 +2532,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
/* make sure there are NSECs or NSEC3s with signatures */
if(!val_has_signed_nsecs(msg->rep, &reason)) {
verbose(VERB_ALGO, "no NSECs: %s", reason);
errinf_ede(qstate, reason, LDNS_EDE_NSEC_MISSING);
reason_bogus = LDNS_EDE_NSEC_MISSING;
errinf_ede(qstate, reason, reason_bogus);
goto return_bogus;
}
@ -2530,7 +2545,7 @@ 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, qstate);
&proof_ttl, &reason, &reason_bogus, qstate);
switch(sec) {
case sec_status_secure:
verbose(VERB_DETAIL, "NSEC RRset for the "
@ -2538,6 +2553,7 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
*ke = key_entry_create_null(qstate->region,
qinfo->qname, qinfo->qname_len,
qinfo->qclass, proof_ttl,
LDNS_EDE_NONE, NULL,
*qstate->env->now);
return (*ke) != NULL;
case sec_status_insecure:
@ -2571,6 +2587,7 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
*ke = key_entry_create_null(qstate->region,
qinfo->qname, qinfo->qname_len,
qinfo->qclass, proof_ttl,
LDNS_EDE_NONE, NULL,
*qstate->env->now);
return (*ke) != NULL;
case sec_status_indeterminate:
@ -2593,7 +2610,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
* this is BOGUS. */
verbose(VERB_DETAIL, "DS %s ran out of options, so return "
"bogus", val_classification_to_string(subtype));
errinf(qstate, "no DS but also no proof of that");
reason = "no DS but also no proof of that";
errinf_ede(qstate, reason, reason_bogus);
goto return_bogus;
} else if(subtype == VAL_CLASS_CNAME ||
subtype == VAL_CLASS_CNAMENOANSWER) {
@ -2605,22 +2623,25 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
cname = reply_find_rrset_section_an(msg->rep, qinfo->qname,
qinfo->qname_len, LDNS_RR_TYPE_CNAME, qinfo->qclass);
if(!cname) {
errinf(qstate, "validator classified CNAME but no "
"CNAME of the queried name for DS");
reason = "validator classified CNAME but no "
"CNAME of the queried name for DS";
errinf_ede(qstate, reason, reason_bogus);
goto return_bogus;
}
if(((struct packed_rrset_data*)cname->entry.data)->rrsig_count
== 0) {
if(msg->rep->an_numrrsets != 0 && ntohs(msg->rep->
rrsets[0]->rk.type)==LDNS_RR_TYPE_DNAME) {
errinf(qstate, "DS got DNAME answer");
reason = "DS got DNAME answer";
} else {
errinf(qstate, "DS got unsigned CNAME answer");
reason = "DS got unsigned CNAME answer";
}
errinf_ede(qstate, reason, reason_bogus);
goto return_bogus;
}
sec = val_verify_rrset_entry(qstate->env, ve, cname,
vq->key_entry, &reason, NULL, LDNS_SECTION_ANSWER, qstate);
sec = val_verify_rrset_entry(qstate->env, ve, cname,
vq->key_entry, &reason, &reason_bogus,
LDNS_SECTION_ANSWER, qstate);
if(sec == sec_status_secure) {
verbose(VERB_ALGO, "CNAME validated, "
"proof that DS does not exist");
@ -2629,12 +2650,13 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
return 1;
}
errinf(qstate, "CNAME in DS response was not secure.");
errinf(qstate, reason);
errinf_ede(qstate, reason, reason_bogus);
goto return_bogus;
} else {
verbose(VERB_QUERY, "Encountered an unhandled type of "
"DS response, thus bogus.");
errinf(qstate, "no DS and");
reason = "no DS";
if(FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR) {
char rc[16];
rc[0]=0;
@ -2647,8 +2669,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
}
return_bogus:
*ke = key_entry_create_bad(qstate->region, qinfo->qname,
qinfo->qname_len, qinfo->qclass,
BOGUS_KEY_TTL, *qstate->env->now);
qinfo->qname_len, qinfo->qclass, BOGUS_KEY_TTL,
reason_bogus, reason, *qstate->env->now);
return (*ke) != NULL;
}
@ -2768,14 +2790,17 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
vq->restart_count++;
return;
}
vq->key_entry = key_entry_create_bad(qstate->region,
reason = "No DNSKEY record";
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, *qstate->env->now);
BOGUS_KEY_TTL, reason_bogus, reason,
*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, "No DNSKEY record", LDNS_EDE_DNSKEY_MISSING);
errinf_ede(qstate, reason, reason_bogus);
errinf_origin(qstate, origin);
errinf_dname(qstate, "for key", qinfo->qname);
vq->state = VAL_VALIDATE_STATE;
@ -2822,7 +2847,8 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
qstate->errinf = NULL;
/* The DNSKEY validated, so cache it as a trusted key rrset. */
key_cache_insert(ve->kcache, vq->key_entry, qstate);
key_cache_insert(ve->kcache, vq->key_entry,
qstate->env->cfg->val_log_level >= 2);
/* If good, we stay in the FINDKEY state. */
log_query_info(VERB_DETAIL, "validated DNSKEY", qinfo);
@ -2890,7 +2916,8 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
errinf_origin(qstate, origin);
errinf_dname(qstate, "for trust anchor", ta->name);
/* store the freshly primed entry in the cache */
key_cache_insert(ve->kcache, vq->key_entry, qstate);
key_cache_insert(ve->kcache, vq->key_entry,
qstate->env->cfg->val_log_level >= 2);
}
/* If the result of the prime is a null key, skip the FINDKEY state.*/

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: bsd.port.mk.5,v 1.587 2023/09/04 22:36:55 thfr Exp $
.\" $OpenBSD: bsd.port.mk.5,v 1.602 2023/09/05 13:58:49 espie 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: September 4 2023 $
.Dd $Mdocdate: September 5 2023 $
.Dt BSD.PORT.MK 5
.Os
.Sh NAME
@ -41,15 +41,31 @@ tree
framework, in the form of documented public targets,
variables and paths.
.Pp
The actual
.Nm
file lives under
.Pa ${PORTSDIR}/infrastructure/mk ,
with
.Xr make 1 Ns 's
system include file redirecting to it.
.Pp
Optional parts of this framework have been moved to
.Xr port-modules 5
in an effort to shrink the main file
.Po
see also
.Ev MODULES
.Pc .
.Pp
Identifiers beginning with an underscore
are internal-use only and likely to change without
notice.
.Pp
This documentation contains sections covering targets, variables,
diagnostics, and filenames, ordered in alphabetic order, followed
by a section covering the fake framework, a section
explaining flavors and multi-packages, and a section covering
the generation of package information.
by a section covering the fake framework, a section covering debug
packages generation, a section explaining flavors and multi-packages,
and a section covering the generation of package information.
.Pp
It ends with sections covering some obsolete targets, variables and files,
outlining conversion
@ -84,6 +100,13 @@ run it, or to run regression tests.
The output is formatted as package specification pairs, in a form suitable
for
.Xr tsort 1 .
.Pp
Note that is is possible to obtain reverse dependency information by
using
.Nm show-reverse-deps
from the
.Pa sqlports
package.
.It Cm full-{build,run,all,test}-depends
Print all dependencies a package depends upon for building, running,
or both, as a list of package names, sorted by dependency order with
@ -235,6 +258,14 @@ for details.
.It Cm dump-vars
Dump the values of all relevant variables in a port, prepended with the
port's FULLPKGPATH.
.Pp
Can be limited to some specific information by setting
.Ev DPB
to nothing or
.Sq fetch .
Mostly used by
.Xr dpb 1
for obtaining vital information from the ports tree.
.It Cm extract
Extract the distribution files under
.Pa ${WRKDIR}
@ -252,15 +283,16 @@ and
.Cm do-extract
hooks.
.It Cm fake
Do a fake port installation, that is, simulate the port installation under
${WRKINST}.
Do a fake port installation, that is, simulate the port installation into
the staging area ${WRKINST}.
There is no
.Cm do-fake
and
.Cm post-fake
hooks.
hooks:
instead
.Cm fake
actually uses
runs
.Cm pre-fake ,
.Cm pre-install ,
.Cm do-install
@ -272,9 +304,20 @@ Override
or
.Cm post-install
to change behavior.
Do not touch
.Pp
There are only a handful of ports that use
.Cm pre-fake :
that hook can be used to finish setting up a
.Pa fake
directory before starting the installation proper.
Stuff run during
.Cm pre-fake
unless you really know what you are doing.
will not register with
.Cm update-plist ,
whereas stuff run during
.Cm pre-install
will be considered part of the installation process.
.Pp
See
.Sx THE FAKE FRAMEWORK
section below.
@ -291,7 +334,7 @@ and
.Ev PATCHFILES*
using ${FETCH_CMD}.
Files are normally retrieved from the list of sites in
.Ev MASTER_SITES* .
.Ev SITES* .
.Pp
Appending
.Sq :0
@ -299,9 +342,9 @@ to
.Sq :9
to an entry will let
${FETCH_CMD} retrieve from
.Ev MASTER_SITES0
.Ev SITES0
to
.Ev MASTER_SITES9
.Ev SITES9
instead (deprecated).
.Pp
Preferably, adding a suffix to
@ -309,11 +352,11 @@ Preferably, adding a suffix to
.Ev PATCHFILES ,
.Ev SUPDISTFILES
will switch the site entry to the corresponding
.Ev MASTER_SITES
.Ev SITES
variable, e.g.,
.Bd -literal -offset indent
DISTFILES.go = ...
MASTER_SITES.go = ...
SITES.go = ...
.Ed
.Pp
If the rest of the entry parses as
@ -346,9 +389,10 @@ all files relevant to a port,
.Cm dpb Fl F
is more efficient.
.Pp
Use of
There are no
.Cm {pre,do,post}-fetch
hooks is forbidden, as this would make mirroring of distfiles very complicated.
hooks, as this would break
.Xr dpb 1 .
.Pp
See
.Ev ALL_DISTFILES ,
@ -361,18 +405,16 @@ See
.Ev FETCH_MANUALLY ,
.Ev FULLDISTDIR ,
.Ev MAKESUMFILES ,
.Ev MASTER_SITES* ,
.Ev MASTER_SITES0 , ... ,
.Ev MASTER_SITES9 ,
.Ev PATCHFILES* ,
.Ev SUPDISTFILES* ,
.Ev REFETCH .
.Ev SITES* ,
.It Cm fetch-all
Like
.Cm fetch ,
but also fetches
.Ev SUPDISTFILES* ,
for use with e.g.,
for use by e.g.,
.Cm makesum .
.It Cm fix-permissions
Ensure permissions are correct when using
@ -425,9 +467,6 @@ and before
or
.Cm update-plist .
Always rerun, as it is cheap enough.
.It Cm index
Top-level target, see
.Xr ports 7 .
.It Cm install-depends
Before package installation, install and verify dependencies constructed from
.Ev RUN_DEPENDS , LIB_DEPENDS ,
@ -456,17 +495,18 @@ Verify that the
.Ev LIB_DEPENDS
and
.Ev WANTLIB
are accurate for the port.
recorded in the port's packages are accurate.
See
.Cm port-lib-depends-check ,
which is quicker.
which checks files under the fake staging directory instead,
and thus has faster turn-around.
.It Cm license-check
Check that
.Ev PERMIT_PACKAGE
settings match:
if any dependency has a more restrictive setting, warn about it.
This warning is advisory, because the automated license checking cannot
figure out which ports were used only for building and did not taint
This warning is advisory, because automated license checking cannot
know that some ports were only used for building and did not taint
the current port.
.It Cm lock
Manually obtain a lock on a given directory.
@ -477,14 +517,18 @@ Seldom used, see
.Xr ports 7
for details.
.It Cm makesum
Run
Uses
.Cm fetch-all
to fetch missing ${MAKESUMFILES}
without verifying their digest, then run
.Xr sha256 1
on ${MAKESUMFILES}
that is, files listed in ${DISTFILES*}, ${SUPDISTFILES*} and ${PATCHFILES*},
and store the result in ${CHECKSUM_FILE}, normally
on them that is,
files listed in ${DISTFILES*}, ${SUPDISTFILES*} and ${PATCHFILES*}.
The result is stored in ${CHECKSUM_FILE}, normally
.Pa distinfo .
Also store the lengths of all files for a quick check during
.Cm fetch .
.Cm fetch ,
.Cm fetch-all .
.It Cm no-lib-depends-args
Degenerate form of
.Cm lib-depends-args
@ -511,9 +555,18 @@ for each package in the
.Ev MULTI_PACKAGES
list.
If the repository already contains up-to-date packages, they are not rebuilt.
If PLIST_REPOSITORY is set, the resulting packaging information is compared
with existing stuff, and saved if new, with loud complaints if it changed
without a REVISION bump.
If PLIST_REPOSITORY is set (the default), the resulting packaging
information is compared with existing stuff, and saved if new,
with loud complaints if it changed without a
.Ev REVISION
bump.
.Pp
if
.Ev DEBUG_PACKAGES
is set, some debug information may also be set aside and saved
in
.Pa debug-*
packages transparently.
.Pp
Also note that
.Pa ${PLIST_REPOSITORY}/${MACHINE_ARCH}/history
@ -569,7 +622,7 @@ will be applied under
.Ev WRKDIST .
.It Cm peek-ftp
Connect to the first site in
.Ev MASTER_SITES ,
.Ev SITES ,
in the right directory, and leaves user at
.Xr ftp 1 Ns 's
prompt.
@ -787,7 +840,12 @@ Print the list of
.Xr pkgpath 7
for all ports that will be affected by the
current port changing.
Works by walking the list of dependencies, in reverse.
Works by walking the full list of all dependencies of all ports, in reverse.
.Pp
Very slow, prefer installing the
.Pa sqlports
package and using
.Nm show-reverse-deps .
.It Cm show-run-depends
Print all running dependencies for a port, one per-line, without duplicates.
.It Cm subpackage
@ -993,9 +1051,7 @@ Automatically set as soon as
.Ev CONFIGURE_STYLE
is gnu or higher.
.It Ev AUTOCONF_VERSION
Starting with
.Ox 3.3 ,
several versions of autoconf may coexist peacefully.
Several versions of autoconf may coexist peacefully.
The main autoconf script is a shell wrapper in the
.Pa devel/metaauto
package, and similarly for automake.
@ -1271,7 +1327,10 @@ This is essentially the same as running
after each package build.
Defaults to
.Sq \&No ,
as this can be a big performance hit.
as this can be a big performance hit, and also because
.Ev lib-depends-check
doesn't know about library subdirectories or dynamic loading through
.Xr dlopen 3 .
.It Ev CHECKSUMFILES
List of all files that need to be retrieved by
.Cm fetch ,
@ -1284,8 +1343,9 @@ See also
.It Ev CHECKSUM_FILE
Location for this port's checksums, used by
.Cm checksum ,
.Cm makesum ,
and
.Cm makesum .
.Xr dpb 1 .
Defaults to
.Pa distinfo .
.It Ev CHECKSUM_PACKAGES
@ -1594,9 +1654,9 @@ and
entries can be added as needed
.Pc .
The components are used to build
.Ev MASTER_SITES.name
.Ev SITES.name
.Ev DISTFILES.name
and
and (optionally)
.Ev HOMEPAGE .
.Pp
At the end of
@ -1622,7 +1682,7 @@ into account.
.It Ev DISTFILES*
The main port's distribution files (the actual software source, except
for binary-only ports).
Will be retrieved from the corresponding MASTER_SITES* (see
Will be retrieved from the corresponding SITES* (see
.Cm fetch ) ,
checksummed and extracted (see
.Cm checksum ,
@ -1633,16 +1693,16 @@ normally holds a list of files, possibly with
to
.Sq :9
appended to select a different
.Ev MASTER_SITES .
.Ev SITES .
.Pp
Preferably, adding a suffix to
.Ev DISTFILES ,
will switch the site entry to the corresponding
.Ev MASTER_SITES
.Ev SITES
variable, e.g.,
.Bd -literal -offset indent
DISTFILES.go = ...
MASTER_SITES.go = ...
SITES.go = ...
.Ed
.Pp
Each entry may optionally be of the form
@ -1669,8 +1729,17 @@ If ${DISTFILES*} varies depending on
or architecture, use
.Ev SUPDISTFILES*
to ensure distfiles mirroring and
.Cm makesum
.Cm makesum Ns 's
proper operation.
.Pp
If no
.Ev DISTFILES*
is set and if
.Ev SITES
is not null, then
.Ev DISTFILES
will be set to
.Pa ${DISNAME}${EXTRACT_SUFX} .
.It Ev DISTNAME
Name used to identify the port.
See
@ -1724,9 +1793,13 @@ If defined,
.Nm
will provide dummy values for variables mandatory for a minimally functional
port.
Used by various pieces of the ports tree to perform introspection and get to
Used by
.Pa sqlports
and
.Xr dpb 1
to perform introspection and obtain
.Nm Ns 's
variables.
default values for variables without needing to access any specific port.
.It Ev ECHO_MSG
User settings.
Used to display
@ -1782,6 +1855,9 @@ for instance to flag erroneous combinations of
and
.Ev BROKEN
for other common issues).
.Pp
Note that setting fatal errors defeats all introspection mechanisms and breaks
.Pa sqlports .
.It Ev EXTRACT_CASES
In the normal extraction stage (when
.Ev EXTRACT_ONLY
@ -1874,7 +1950,7 @@ Target built by ${MAKE_PROGRAM} on fake invocation.
Defaults to ${INSTALL_TARGET}.
.It Ev FAKEOBJDIR
User settings.
If non empty, used as a base for the fake area.
If non empty, used as a base for the fake staging area.
The real fake directory ${WRKINST} is created there.
Can be set on a per-${PKGPATH} basis.
For instance, setting FAKEOBJDIR_www/mozilla-firefox=/tmp/obj
@ -2024,7 +2100,7 @@ See
Simple support for GitHub-hosted projects.
Leave empty for non hosted projects.
Yields a suitable default for
.Ev MASTER_SITES_GITHUB
.Ev SITES_GITHUB
and
.Ev DISTNAME .
.It Ev GH_ACCOUNT
@ -2106,12 +2182,17 @@ to simplify bulk-package builds.
Set to
.Sq Yes
if port needs human interaction to build.
Porters should strive to minimize
.Pp
Note that
.Ev IS_INTERACTIVE
ports, by using
.Ev FLAVORS
for multiple choice ports, and by postponing human intervention
to package installation time.
ports won't be built as official packages,
so avoid at all cost.
.Pp
Human intervention should be moved to binary package
installation and/or post-installation configuration instead.
.Pp
Discrete Yes/No choices are better modelled as
.Ev FLAVORS .
.It Ev LE_ARCHS
Set to the list of little-endian architectures.
Read-only.
@ -2273,45 +2354,6 @@ prepended and with master site selection extension removed.
Read-only.
See also
.Ev CHECKSUMFILES .
.It Ev MASTER_SITE_BACKUP
User settings.
List of sites to try after normal master sites.
Normally includes ${MASTER_SITE_OPENBSD} and ${MASTER_SITE_FREEBSD}.
.It Ev MASTER_SITE_*
Lists of standard sites to retrieve files from, refer to
.Pa ${PORTSDIR}/infrastructure/db/network.conf
for a complete list.
.Pp
Generally used with the standard
.Xr make 1 Ns 's
.Li ${VARIABLE:=subdir/}
construct to append the relevant subdir at the end of each entry, e.g.,
.Dl MASTER_SITES = ${MASTER_SITE_GNU:=cgicc/}
.It Ev MASTER_SITES
List of primary locations from which distribution files and patchfiles are
retrieved.
See the
.Cm fetch
target for details.
Defaults to ${MASTER_SITES_GITHUB} for GitHub-hosted projects,
see
.Ev GH_* .
See
.Xr ports 7
for user configuration.
.It Ev MASTER_SITES*
List of alternate locations from which ${DISTFILES*}, ${PATCHFILES*},
${SUPDISTFILES*} are retrieved.
See
.Cm fetch
for details.
Suffix should start with
.Sq \&.
for consistency.
.Pp
.It Ev MASTER_SITES0 , ... , MASTER_SITES9
Supplementary locations from which distribution files and patchfiles are
retrieved.
.It Ev MESSAGE
File recorded in the package and displayed during installation.
Defaults to ${PKGDIR}/MESSAGE if this file exists.
@ -3117,6 +3159,45 @@ Porters of software using libtool should make sure
.Ev MAKE_FLAGS
get propagated to the libtool invocations.
This should be enough in most cases.
.It Ev SITE_BACKUP
User settings.
List of sites to try after normal master sites.
Normally includes ${SITE_OPENBSD} and ${SITE_FREEBSD}.
.It Ev SITE_*
Lists of standard sites to retrieve files from, refer to
.Pa ${PORTSDIR}/infrastructure/db/network.conf
for a complete list.
.Pp
Generally used with the standard
.Xr make 1 Ns 's
.Li ${VARIABLE:=subdir/}
construct to append the relevant subdir at the end of each entry, e.g.,
.Dl SITES = ${SITE_GNU:=cgicc/}
.It Ev SITES
List of primary locations from which distribution files and patchfiles are
retrieved.
See the
.Cm fetch
target for details.
Defaults to ${SITES_GITHUB} for GitHub-hosted projects,
see
.Ev GH_* .
See
.Xr ports 7
for user configuration.
.It Ev SITES*
List of alternate locations from which ${DISTFILES*}, ${PATCHFILES*},
${SUPDISTFILES*} are retrieved.
See
.Cm fetch
for details.
Suffix should start with
.Sq \&.
for consistency.
.Pp
.It Ev SITES0 , ... , SITES9
Supplementary locations from which distribution files and patchfiles are
retrieved (deprecated).
.It Ev SKIPDIR
See
.Xr ports 7 .
@ -3329,13 +3410,6 @@ when using
.Ev DIST_TUPLE .
Very similar to
.Ev TEMPLATE_DISTFILES.<name> .
.It Ev TEMPLATES
Base location for the templates used in the
.Cm readmes
target.
User settings.
Defaults to
.Pa ${PORTSDIR}/infrastructure/templates .
.It Ev TEST_DEPENDS
See
.Ev BUILD_DEPENDS
@ -3592,7 +3666,8 @@ Subdirectory of ${WRKDIR} where the actual source is.
Base for configuration (default: ${WRKDIST}).
Note that WRKSRC may be a symbolic link, if set to ${WRKDIR}.
.It Ev WRKINST
Subdirectory of ${WRKDIR} where port normally installs (see the
Subdirectory of ${WRKDIR} used as a staging area for installing the port.
(See
.Cm fake
target).
.It Ev WRKOBJDIR
@ -3640,14 +3715,16 @@ Set to bison if needed.
.Sh THE FAKE FRAMEWORK
The
.Cm fake
target is used to install the port in a private directory first, ready for
target is used to install the port under a staging directory first, ready for
packaging by the
.Cm package
target, so that the actual installation will use the package.
target, so that the actual
.Cm install
target will use the binary package instead.
.Pp
Essentially,
.Cm fake
invokes a real install process after tweaking a few variables.
invokes the install process after tweaking a few variables.
.Pp
.Cm fake
first creates a skeleton tree under ${WRKINST}, using
@ -3660,6 +3737,10 @@ target may be used to complete that skeleton tree.
For instance, a few ports may need supplementary stuff to be present (as
it would be installed if the port's dependencies were present).
.Pp
In most cases,
.Cm pre-install
is preferred.
.Pp
If
.Cm {pre,do,post}-install
overrides are present, they are used with some
@ -4390,7 +4471,7 @@ resulting in a double inclusion.
This would lead to weird results, such as
.Ev PKG_ARGS
being defined twice.
.It "Fatal: MASTER_SITES* is not defined but referenced by <file> in <DISTFILES*/PATCHFILES*/SUPDISTFILES*>"
.It "Fatal: SITES* is not defined but referenced by <file> in <DISTFILES*/PATCHFILES*/SUPDISTFILES*>"
Pretty much self-explanatory.
.It "Fatal: SUBPACKAGES should always begin with -: <offending list>"
That is the only way to differentiate between

View File

@ -1,4 +1,4 @@
/* $OpenBSD: vmm_machdep.c,v 1.6 2023/09/03 09:30:43 mlarkin Exp $ */
/* $OpenBSD: vmm_machdep.c,v 1.7 2023/09/05 14:00:40 mlarkin Exp $ */
/*
* Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
*
@ -6319,7 +6319,7 @@ vmm_handle_cpuid(struct vcpu *vcpu)
*rax = eax;
*rbx = ebx;
*rcx = ecx;
*rdx = edx & VMM_APMI_EDX_MASK;
*rdx = edx & VMM_APMI_EDX_INCLUDE_MASK;
break;
case 0x80000008: /* Phys bits info and topology (AMD) */
*rax = eax;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: vmmvar.h,v 1.92 2023/09/03 09:30:43 mlarkin Exp $ */
/* $OpenBSD: vmmvar.h,v 1.93 2023/09/05 14:00:41 mlarkin Exp $ */
/*
* Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org>
*
@ -559,7 +559,9 @@ struct vm_mprotect_ept_params {
CPUIDEBX_STIBP | CPUIDEBX_IBRS_ALWAYSON | CPUIDEBX_STIBP_ALWAYSON | \
CPUIDEBX_IBRS_PREF | CPUIDEBX_SSBD | CPUIDEBX_VIRT_SSBD | \
CPUIDEBX_SSBD_NOTREQ)
#define VMM_APMI_EDX_MASK ~(CPUIDEDX_HWPSTATE)
/* This mask is an include list for bits we want to expose */
#define VMM_APMI_EDX_INCLUDE_MASK (CPUIDEDX_ITSC)
/*
* SEFF flags - copy from host minus:

View File

@ -1,4 +1,4 @@
/* $OpenBSD: apldc.c,v 1.9 2023/07/03 15:54:07 tobhe Exp $ */
/* $OpenBSD: apldc.c,v 1.10 2023/09/05 11:04:06 tobhe Exp $ */
/*
* Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
*
@ -575,17 +575,22 @@ apldchidev_handle_gpio_req(struct apldchidev_softc *sc, uint8_t iface,
if (sc->sc_ngpios >= APLDCHIDEV_NUM_GPIOS)
return;
if (iface == sc->sc_iface_mt)
node = OF_getnodebyname(sc->sc_node, "multi-touch");
else if (iface == sc->sc_iface_stm)
node = OF_getnodebyname(sc->sc_node, "stm");
if (node == -1)
return;
node = sc->sc_node;
snprintf(name, sizeof(name), "apple,%s-gpios", req->name);
len = OF_getproplen(node, name);
if (len <= 0 || len > sizeof(gpio))
return;
if (len <= 0 || len > sizeof(gpio)) {
/* XXX: older device trees store gpios in sub-nodes */
if (iface == sc->sc_iface_mt)
node = OF_getnodebyname(sc->sc_node, "multi-touch");
else if (iface == sc->sc_iface_stm)
node = OF_getnodebyname(sc->sc_node, "stm");
if (node == -1)
return;
len = OF_getproplen(node, name);
if (len <= 0 || len > sizeof(gpio))
return;
}
OF_getpropintarray(node, name, gpio, len);
gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT);
gpio_controller_set_pin(gpio, 0);

View File

@ -31,7 +31,7 @@ POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
/* $OpenBSD: if_em.c,v 1.365 2023/02/09 21:21:27 naddy Exp $ */
/* $OpenBSD: if_em.c,v 1.366 2023/09/05 13:06:42 naddy Exp $ */
/* $FreeBSD: if_em.c,v 1.46 2004/09/29 18:28:28 mlaier Exp $ */
#include <dev/pci/if_em.h>
@ -1474,7 +1474,7 @@ em_iff(struct em_softc *sc)
ETHER_NEXT_MULTI(step, enm);
}
em_mc_addr_list_update(&sc->hw, mta, ac->ac_multicnt, 0, 1);
em_mc_addr_list_update(&sc->hw, mta, ac->ac_multicnt, 0);
}
E1000_WRITE_REG(&sc->hw, RCTL, reg_rctl);

View File

@ -31,7 +31,7 @@
*******************************************************************************/
/* $OpenBSD: if_em_hw.c,v 1.117 2023/04/11 00:45:08 jsg Exp $ */
/* $OpenBSD: if_em_hw.c,v 1.118 2023/09/05 13:06:42 naddy Exp $ */
/*
* if_em_hw.c Shared functions for accessing and configuring the MAC
*/
@ -7884,20 +7884,16 @@ em_init_rx_addrs(struct em_hw *hw)
* mc_addr_list - the list of new multicast addresses
* mc_addr_count - number of addresses
* pad - number of bytes between addresses in the list
* rar_used_count - offset where to start adding mc addresses into the RAR's
*
* The given list replaces any existing list. Clears the last 15 receive
* address registers and the multicast table. Uses receive address registers
* for the first 15 multicast addresses, and hashes the rest into the
* The given list replaces any existing list and hashes the addresses into the
* multicast table.
*****************************************************************************/
void
em_mc_addr_list_update(struct em_hw *hw, uint8_t *mc_addr_list,
uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count)
uint32_t mc_addr_count, uint32_t pad)
{
uint32_t hash_value;
uint32_t i;
uint32_t num_rar_entry;
uint32_t num_mta_entry;
DEBUGFUNC("em_mc_addr_list_update");
/*
@ -7906,28 +7902,6 @@ em_mc_addr_list_update(struct em_hw *hw, uint8_t *mc_addr_list,
*/
hw->num_mc_addrs = mc_addr_count;
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
num_rar_entry = E1000_RAR_ENTRIES;
if (IS_ICH8(hw->mac_type))
num_rar_entry = E1000_RAR_ENTRIES_ICH8LAN;
if (hw->mac_type == em_ich8lan)
num_rar_entry -= 1;
/*
* Reserve a spot for the Locally Administered Address to work around
* an 82571 issue in which a reset on one port will reload the MAC on
* the other port.
*/
if ((hw->mac_type == em_82571) && (hw->laa_is_present == TRUE))
num_rar_entry -= 1;
for (i = rar_used_count; i < num_rar_entry; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
E1000_WRITE_FLUSH(hw);
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
E1000_WRITE_FLUSH(hw);
}
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
num_mta_entry = E1000_NUM_MTA_REGISTERS;
@ -7954,18 +7928,7 @@ em_mc_addr_list_update(struct em_hw *hw, uint8_t *mc_addr_list,
(i * (ETH_LENGTH_OF_ADDRESS + pad)));
DEBUGOUT1(" Hash value = 0x%03X\n", hash_value);
/*
* Place this multicast address in the RAR if there is room, *
* else put it in the MTA
*/
if (rar_used_count < num_rar_entry) {
em_rar_set(hw, mc_addr_list +
(i * (ETH_LENGTH_OF_ADDRESS + pad)),
rar_used_count);
rar_used_count++;
} else {
em_mta_set(hw, hash_value);
}
em_mta_set(hw, hash_value);
}
DEBUGOUT("MC Update Complete\n");
}

View File

@ -31,7 +31,7 @@
*******************************************************************************/
/* $OpenBSD: if_em_hw.h,v 1.88 2022/11/06 18:17:56 mbuhl Exp $ */
/* $OpenBSD: if_em_hw.h,v 1.89 2023/09/05 13:06:43 naddy Exp $ */
/* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */
/* if_em_hw.h
@ -428,7 +428,7 @@ boolean_t em_get_flash_presence_i210(struct em_hw *);
/* Filters (multicast, vlan, receive) */
void em_mc_addr_list_update(struct em_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count,
uint32_t pad, uint32_t rar_used_count);
uint32_t pad);
uint32_t em_hash_mc_addr(struct em_hw *hw, uint8_t *mc_addr);
void em_mta_set(struct em_hw *hw, uint32_t hash_value);
void em_rar_set(struct em_hw *hw, uint8_t *mc_addr, uint32_t rar_index);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ksmn.c,v 1.8 2023/06/23 03:47:10 mlarkin Exp $ */
/* $OpenBSD: ksmn.c,v 1.9 2023/09/05 13:06:01 stsp Exp $ */
/*
* Copyright (c) 2019 Bryan Steele <brynet@openbsd.org>
@ -105,6 +105,7 @@ static const struct pci_matchid ksmn_devices[] = {
{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_1X_RC },
{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_3X_RC },
{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_6X_RC },
{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_19_4X_RC },
{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_19_6X_RC },
};

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