Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Knot projects
Knot DNS
Commits
fff3431c
Commit
fff3431c
authored
May 06, 2018
by
Jan Hák
Committed by
Daniel Salzman
Sep 14, 2022
Browse files
kdig: add +json (RFC 8427) option
parent
0ba75bdc
Pipeline
#104253
passed with stages
in 5 minutes and 54 seconds
Changes
14
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
doc/man/kdig.1in
View file @
fff3431c
...
...
@@ -337,6 +337,9 @@ is an optional hex encoded string to use as EDNS option value. This argument
can be used multiple times. +noednsopt clears all EDNS options specified by
+ednsopt.
.TP
\fB+\fP[\fBno\fP]\fBjson\fP
Use JSON for output encoding (RFC 8427).
.TP
\fB+noidn\fP
Disable the IDN transformation to ASCII and vice versa. IDN support depends
on libidn availability during project building! If used in \fIcommon\-settings\fP,
...
...
doc/man_kdig.rst
View file @
fff3431c
...
...
@@ -316,6 +316,9 @@ Options
can be used multiple times. +noednsopt clears all EDNS options specified by
+ednsopt.
**+**\ [\ **no**\ ]\ **json**
Use JSON for output encoding (RFC 8427).
**+noidn**
Disable the IDN transformation to ASCII and vice versa. IDN support depends
on libidn availability during project building! If used in *common-settings*,
...
...
src/contrib/json.c
View file @
fff3431c
...
...
@@ -20,6 +20,8 @@
#include
"contrib/json.h"
#include
"contrib/string.h"
#define MAX_DEPTH 8
enum
{
...
...
@@ -201,6 +203,17 @@ void jsonw_bool(jsonw_t *w, const char *key, bool value)
fprintf
(
w
->
out
,
"%s"
,
value
?
"true"
:
"false"
);
}
void
jsonw_hex
(
jsonw_t
*
w
,
const
char
*
key
,
const
uint8_t
*
data
,
size_t
len
)
{
assert
(
w
);
char
*
hex
=
bin_to_hex
(
data
,
len
,
true
);
if
(
hex
!=
NULL
)
{
jsonw_str
(
w
,
key
,
hex
);
}
free
(
hex
);
}
void
jsonw_end
(
jsonw_t
*
w
)
{
assert
(
w
);
...
...
src/contrib/json.h
View file @
fff3431c
...
...
@@ -18,6 +18,7 @@
#include
<stdio.h>
#include
<stdbool.h>
#include
<stdint.h>
/*!
* Simple pretty JSON writer.
...
...
@@ -75,6 +76,11 @@ void jsonw_int(jsonw_t *w, const char *key, int value);
*/
void
jsonw_bool
(
jsonw_t
*
w
,
const
char
*
key
,
bool
value
);
/*!
* Write binary data encoded to HEX as JSON.
*/
void
jsonw_hex
(
jsonw_t
*
w
,
const
char
*
key
,
const
uint8_t
*
data
,
size_t
len
);
/*!
* Terminate in-progress object or list.
*/
...
...
src/contrib/string.c
View file @
fff3431c
...
...
@@ -173,10 +173,11 @@ void *memzero(void *s, size_t n)
}
static
const
char
BIN_TO_HEX
[]
=
{
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
,
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
};
char
*
bin_to_hex
(
const
uint8_t
*
bin
,
size_t
bin_len
)
char
*
bin_to_hex
(
const
uint8_t
*
bin
,
size_t
bin_len
,
bool
upper_case
)
{
if
(
bin
==
NULL
)
{
return
NULL
;
...
...
@@ -188,9 +189,10 @@ char *bin_to_hex(const uint8_t *bin, size_t bin_len)
return
NULL
;
}
unsigned
offset
=
upper_case
?
16
:
0
;
for
(
size_t
i
=
0
;
i
<
bin_len
;
i
++
)
{
hex
[
2
*
i
]
=
BIN_TO_HEX
[
bin
[
i
]
>>
4
];
hex
[
2
*
i
+
1
]
=
BIN_TO_HEX
[
bin
[
i
]
&
0x0f
];
hex
[
2
*
i
]
=
BIN_TO_HEX
[
offset
+
(
bin
[
i
]
>>
4
)
];
hex
[
2
*
i
+
1
]
=
BIN_TO_HEX
[
offset
+
(
bin
[
i
]
&
0x0f
)
];
}
hex
[
hex_size
]
=
'\0'
;
...
...
src/contrib/string.h
View file @
fff3431c
/* Copyright (C) 202
1
CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 202
2
CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -20,6 +20,7 @@
#pragma once
#include
<stdbool.h>
#include
<stddef.h>
#include
<stdint.h>
...
...
@@ -95,7 +96,7 @@ void *memzero(void *s, size_t n);
/*!
* \brief Convert binary data to hexadecimal string.
*/
char
*
bin_to_hex
(
const
uint8_t
*
bin
,
size_t
bin_len
);
char
*
bin_to_hex
(
const
uint8_t
*
bin
,
size_t
bin_len
,
bool
upper_case
);
/*!
* \brief Convert hex encoded string to binary data.
...
...
src/knot/catalog/generate.c
View file @
fff3431c
/* Copyright (C) 202
1
CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 202
2
CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -35,7 +35,7 @@ static knot_dname_t *catalog_member_owner(const knot_dname_t *member,
SipHash24_Update
(
&
hash
,
&
u64time
,
sizeof
(
u64time
));
uint64_t
hashres
=
SipHash24_End
(
&
hash
);
char
*
hexhash
=
bin_to_hex
((
uint8_t
*
)
&
hashres
,
sizeof
(
hashres
));
char
*
hexhash
=
bin_to_hex
((
uint8_t
*
)
&
hashres
,
sizeof
(
hashres
)
,
false
);
if
(
hexhash
==
NULL
)
{
return
NULL
;
}
...
...
src/libdnssec/keystore/pkcs11.c
View file @
fff3431c
...
...
@@ -214,7 +214,7 @@ static int pkcs11_generate_key(void *_ctx, gnutls_pk_algorithm_t algorithm,
return
DNSSEC_KEY_GENERATE_ERROR
;
}
char
*
id
=
bin_to_hex
(
cka_id
.
data
,
cka_id
.
size
);
char
*
id
=
bin_to_hex
(
cka_id
.
data
,
cka_id
.
size
,
false
);
if
(
id
==
NULL
)
{
return
DNSSEC_ENOMEM
;
}
...
...
@@ -297,7 +297,7 @@ static int pkcs11_import_key(void *_ctx, const dnssec_binary_t *pem, char **id_p
return
DNSSEC_KEY_IMPORT_ERROR
;
}
*
id_ptr
=
bin_to_hex
(
id
.
data
,
id
.
size
);
*
id_ptr
=
bin_to_hex
(
id
.
data
,
id
.
size
,
false
);
if
(
*
id_ptr
==
NULL
)
{
return
DNSSEC_ENOMEM
;
}
...
...
src/libdnssec/shared/keyid_gnutls.c
View file @
fff3431c
/* Copyright (C) 20
19
CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 20
22
CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -70,7 +70,7 @@ static int keyid_hex(gnutls_x509_privkey_t key, gnutls_pubkey_t pubkey, char **i
return
r
;
}
*
id
=
bin_to_hex
(
bin
.
data
,
bin
.
size
);
*
id
=
bin_to_hex
(
bin
.
data
,
bin
.
size
,
false
);
if
(
*
id
==
NULL
)
{
return
DNSSEC_ENOMEM
;
}
...
...
src/utils/common/exec.c
View file @
fff3431c
...
...
@@ -30,6 +30,8 @@
#include
"contrib/ucw/lists.h"
#include
"contrib/wire_ctx.h"
static
const
char
*
JSON_INDENT
=
" "
;
static
knot_lookup_t
rtypes
[]
=
{
{
KNOT_RRTYPE_A
,
"has IPv4 address"
},
{
KNOT_RRTYPE_NS
,
"nameserver is"
},
...
...
@@ -534,6 +536,124 @@ static void print_error_host(const knot_pkt_t *packet, const style_t *style)
free
(
owner
);
}
static
void
json_dname
(
jsonw_t
*
w
,
const
char
*
key
,
const
knot_dname_t
*
dname
)
{
knot_dname_txt_storage_t
name
;
if
(
knot_dname_to_str
(
name
,
dname
,
sizeof
(
name
))
!=
NULL
)
{
jsonw_str
(
w
,
key
,
name
);
}
}
static
void
json_rdata
(
jsonw_t
*
w
,
const
knot_rrset_t
*
rrset
)
{
char
type
[
16
];
if
(
knot_rrtype_to_string
(
rrset
->
type
,
type
,
sizeof
(
type
))
<=
0
||
strncmp
(
type
,
"TYPE"
,
4
)
==
0
)
{
// Unknown/hex format.
return
;
}
char
key
[
32
]
=
"rdata"
;
strlcat
(
key
,
type
,
sizeof
(
key
));
char
data
[
16384
];
const
knot_dump_style_t
*
style
=
&
KNOT_DUMP_STYLE_DEFAULT
;
if
(
knot_rrset_txt_dump_data
(
rrset
,
0
,
data
,
sizeof
(
data
),
style
)
>
0
)
{
jsonw_str
(
w
,
key
,
data
);
}
}
static
void
json_print_section
(
jsonw_t
*
w
,
const
char
*
name
,
const
knot_pktsection_t
*
section
)
{
if
(
section
->
count
==
0
)
{
return
;
}
char
str
[
16
];
jsonw_list
(
w
,
name
);
for
(
int
i
=
0
;
i
<
section
->
count
;
i
++
)
{
const
knot_rrset_t
*
rr
=
knot_pkt_rr
(
section
,
i
);
jsonw_object
(
w
,
NULL
);
json_dname
(
w
,
"NAME"
,
rr
->
owner
);
jsonw_int
(
w
,
"TYPE"
,
rr
->
type
);
if
(
knot_rrtype_to_string
(
rr
->
type
,
str
,
sizeof
(
str
))
>
0
)
{
jsonw_str
(
w
,
"TYPEname"
,
str
);
}
jsonw_int
(
w
,
"CLASS"
,
rr
->
rclass
);
if
(
rr
->
type
!=
KNOT_RRTYPE_OPT
&&
// OPT class meaning is different.
knot_rrclass_to_string
(
rr
->
rclass
,
str
,
sizeof
(
str
))
>
0
)
{
jsonw_str
(
w
,
"CLASSname"
,
str
);
}
jsonw_int
(
w
,
"TTL"
,
rr
->
ttl
);
if
(
rr
->
type
!=
KNOT_RRTYPE_OPT
)
{
// OPT with HEX rdata.
json_rdata
(
w
,
rr
);
}
jsonw_int
(
w
,
"RDLENGTH"
,
rr
->
rrs
.
rdata
->
len
);
if
(
rr
->
rrs
.
rdata
->
len
>
0
)
{
jsonw_hex
(
w
,
"RDATAHEX"
,
rr
->
rrs
.
rdata
->
data
,
rr
->
rrs
.
rdata
->
len
);
}
jsonw_end
(
w
);
}
jsonw_end
(
w
);
}
static
void
print_packet_json
(
jsonw_t
*
w
,
const
knot_pkt_t
*
pkt
,
time_t
time
)
{
if
(
pkt
==
NULL
)
{
return
;
}
char
str
[
16
];
struct
tm
tm
;
char
date
[
64
];
localtime_r
(
&
time
,
&
tm
);
strftime
(
date
,
sizeof
(
date
),
"%Y-%m-%dT%H:%M:%S%z"
,
&
tm
);
jsonw_str
(
w
,
"dateString"
,
date
);
jsonw_int
(
w
,
"dateSeconds"
,
time
);
jsonw_int
(
w
,
"msgLength"
,
pkt
->
size
);
if
(
pkt
->
parsed
>=
KNOT_WIRE_HEADER_SIZE
)
{
jsonw_int
(
w
,
"ID"
,
knot_wire_get_id
(
pkt
->
wire
));
jsonw_int
(
w
,
"QR"
,
(
bool
)
knot_wire_get_qr
(
pkt
->
wire
));
jsonw_int
(
w
,
"Opcode"
,
knot_wire_get_opcode
(
pkt
->
wire
));
jsonw_int
(
w
,
"AA"
,
(
bool
)
knot_wire_get_aa
(
pkt
->
wire
));
jsonw_int
(
w
,
"TC"
,
(
bool
)
knot_wire_get_tc
(
pkt
->
wire
));
jsonw_int
(
w
,
"RD"
,
(
bool
)
knot_wire_get_rd
(
pkt
->
wire
));
jsonw_int
(
w
,
"RA"
,
(
bool
)
knot_wire_get_ra
(
pkt
->
wire
));
jsonw_int
(
w
,
"AD"
,
(
bool
)
knot_wire_get_ad
(
pkt
->
wire
));
jsonw_int
(
w
,
"CD"
,
(
bool
)
knot_wire_get_cd
(
pkt
->
wire
));
jsonw_int
(
w
,
"RCODE"
,
knot_wire_get_rcode
(
pkt
->
wire
));
jsonw_int
(
w
,
"QDCOUNT"
,
knot_wire_get_qdcount
(
pkt
->
wire
));
jsonw_int
(
w
,
"ANCOUNT"
,
knot_wire_get_ancount
(
pkt
->
wire
));
jsonw_int
(
w
,
"NSCOUNT"
,
knot_wire_get_nscount
(
pkt
->
wire
));
jsonw_int
(
w
,
"ARCOUNT"
,
knot_wire_get_arcount
(
pkt
->
wire
));
}
if
(
knot_wire_get_qdcount
(
pkt
->
wire
)
==
1
)
{
json_dname
(
w
,
"QNAME"
,
knot_pkt_qname
(
pkt
));
jsonw_int
(
w
,
"QTYPE"
,
knot_pkt_qtype
(
pkt
));
if
(
knot_rrtype_to_string
(
knot_pkt_qtype
(
pkt
),
str
,
sizeof
(
str
))
>
0
)
{
jsonw_str
(
w
,
"QTYPEname"
,
str
);
}
jsonw_int
(
w
,
"QCLASS"
,
knot_pkt_qclass
(
pkt
));
if
(
knot_rrclass_to_string
(
knot_pkt_qclass
(
pkt
),
str
,
sizeof
(
str
))
>
0
)
{
jsonw_str
(
w
,
"QCLASSname"
,
str
);
}
}
if
(
pkt
->
rrset_count
)
{
json_print_section
(
w
,
"answerRRs"
,
knot_pkt_section
(
pkt
,
KNOT_ANSWER
));
json_print_section
(
w
,
"authorityRRs"
,
knot_pkt_section
(
pkt
,
KNOT_AUTHORITY
));
json_print_section
(
w
,
"additionalRRs"
,
knot_pkt_section
(
pkt
,
KNOT_ADDITIONAL
));
}
if
(
pkt
->
parsed
<
pkt
->
size
)
{
jsonw_hex
(
w
,
"messageOctetsHEX"
,
pkt
->
wire
,
pkt
->
size
);
}
}
knot_pkt_t
*
create_empty_packet
(
const
uint16_t
max_size
)
{
// Create packet skeleton.
...
...
@@ -549,6 +669,64 @@ knot_pkt_t *create_empty_packet(const uint16_t max_size)
return
packet
;
}
jsonw_t
*
print_header_xfr_json
(
const
knot_pkt_t
*
query
,
const
time_t
exec_time
,
const
style_t
*
style
)
{
if
(
style
==
NULL
)
{
DBG_NULL
;
return
NULL
;
}
jsonw_t
*
w
=
jsonw_new
(
stdout
,
JSON_INDENT
);
if
(
w
==
NULL
)
{
return
NULL
;
}
if
(
style
->
show_query
)
{
jsonw_object
(
w
,
NULL
);
jsonw_object
(
w
,
"queryMessage"
);
print_packet_json
(
w
,
query
,
exec_time
);
jsonw_end
(
w
);
jsonw_list
(
w
,
"responseMessage"
);
}
else
{
jsonw_list
(
w
,
NULL
);
}
return
w
;
}
void
print_data_xfr_json
(
jsonw_t
*
w
,
const
knot_pkt_t
*
reply
,
const
time_t
exec_time
)
{
if
(
w
==
NULL
)
{
DBG_NULL
;
return
;
}
jsonw_object
(
w
,
NULL
);
print_packet_json
(
w
,
reply
,
exec_time
);
jsonw_end
(
w
);
}
void
print_footer_xfr_json
(
jsonw_t
**
w
,
const
style_t
*
style
)
{
if
(
w
==
NULL
||
style
==
NULL
)
{
DBG_NULL
;
return
;
}
jsonw_end
(
*
w
);
// list (responseMessage)
if
(
style
->
show_query
)
{
jsonw_end
(
*
w
);
// object
}
jsonw_free
(
w
);
*
w
=
NULL
;
}
void
print_header_xfr
(
const
knot_pkt_t
*
packet
,
const
style_t
*
style
)
{
if
(
style
==
NULL
)
{
...
...
@@ -629,6 +807,40 @@ void print_footer_xfr(const size_t total_len,
}
}
void
print_packets_json
(
const
knot_pkt_t
*
query
,
const
knot_pkt_t
*
reply
,
const
net_t
*
net
,
const
time_t
exec_time
,
const
style_t
*
style
)
{
if
(
style
==
NULL
)
{
DBG_NULL
;
return
;
}
jsonw_t
*
w
=
jsonw_new
(
stdout
,
JSON_INDENT
);
if
(
w
==
NULL
)
{
return
;
}
jsonw_object
(
w
,
NULL
);
if
(
style
->
show_query
)
{
jsonw_object
(
w
,
"queryMessage"
);
print_packet_json
(
w
,
query
,
exec_time
);
jsonw_end
(
w
);
jsonw_object
(
w
,
"responseMessage"
);
}
print_packet_json
(
w
,
reply
,
exec_time
);
if
(
style
->
show_query
)
{
jsonw_end
(
w
);
}
jsonw_end
(
w
);
jsonw_free
(
&
w
);
}
void
print_packet
(
const
knot_pkt_t
*
packet
,
const
net_t
*
net
,
const
size_t
size
,
...
...
src/utils/common/exec.h
View file @
fff3431c
/* Copyright (C) 20
18
CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 20
22
CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
...
...
@@ -21,6 +21,7 @@
#include
"utils/common/netio.h"
#include
"utils/common/params.h"
#include
"libknot/libknot.h"
#include
"contrib/json.h"
/*!
* \brief Allocates empty packet and sets packet size and random id.
...
...
@@ -68,9 +69,58 @@ void print_footer_xfr(const size_t total_len,
const
style_t
*
style
);
/*!
* \brief Prints
one response packe
t.
* \brief Prints
initial JSON part of XFR outpu
t.
*
* \param packet Response packet.
* \param query Query packet.
* \param exec_time Time of the packet creation.
* \param style Style of the output.
*
* \retval JSON witter if success.
* \retval NULL if error.
*/
jsonw_t
*
print_header_xfr_json
(
const
knot_pkt_t
*
query
,
const
time_t
exec_time
,
const
style_t
*
style
);
/*!
* \brief Prints one XFR reply packet in JSON.
*
* \param w JSON writter.
* \param reply Reply packet (possibly one of many).
* \param exec_time Time of the packet creation.
*/
void
print_data_xfr_json
(
jsonw_t
*
w
,
const
knot_pkt_t
*
reply
,
const
time_t
exec_time
);
/*!
* \brief Prints trailing JSON part of XFR output.
*
* \param w JSON writter.
* \param style Style of the output.
*/
void
print_footer_xfr_json
(
jsonw_t
**
w
,
const
style_t
*
style
);
/*!
* \brief Prints one or query/reply pair of DNS packets in JSON format.
*
* \param query Query DNS packet.
* \param reply Reply DNS packet.
* \param net Connection information.
* \param exec_time Time of the packet creation.
* \param style Style of the output.
*/
void
print_packets_json
(
const
knot_pkt_t
*
query
,
const
knot_pkt_t
*
reply
,
const
net_t
*
net
,
const
time_t
exec_time
,
const
style_t
*
style
);
/*!
* \brief Prints one DNS packet.
*
* \param packet DNS packet.
* \param net Connection information.
* \param size Original packet wire size.
* \param elapsed Total elapsed time.
...
...
src/utils/common/params.h
View file @
fff3431c
...
...
@@ -59,7 +59,9 @@ typedef enum {
/*!< Brief host output. */
FORMAT_HOST
,
/*!< Brief nsupdate output. */
FORMAT_NSUPDATE
FORMAT_NSUPDATE
,
/*!< Machine readable JSON format (RFC 8427). */
FORMAT_JSON
}
format_t
;
/*! \brief Text output settings. */
...
...
src/utils/kdig/kdig_exec.c
View file @
fff3431c
...
...
@@ -25,6 +25,7 @@
#include
"utils/common/netio.h"
#include
"utils/common/sign.h"
#include
"libknot/libknot.h"
#include
"contrib/json.h"
#include
"contrib/sockaddr.h"
#include
"contrib/time.h"
#include
"contrib/ucw/lists.h"
...
...
@@ -626,7 +627,7 @@ static int process_query_packet(const knot_pkt_t *query,
{
struct
timespec
t_start
,
t_query
,
t_query_full
,
t_end
,
t_end_full
;
time_t
timestamp
;
knot_pkt_t
*
reply
;
knot_pkt_t
*
reply
=
NULL
;
uint8_t
in
[
MAX_PACKET_SIZE
];
int
in_len
;
int
ret
;
...
...
@@ -662,7 +663,7 @@ static int process_query_packet(const knot_pkt_t *query,
#endif // USE_DNSTAP
// Print query packet if required.
if
(
style
->
show_query
)
{
if
(
style
->
show_query
&&
style
->
format
!=
FORMAT_JSON
)
{
// Create copy of query packet for parsing.
knot_pkt_t
*
q
=
knot_pkt_new
(
query
->
wire
,
query
->
size
,
NULL
);
if
(
q
!=
NULL
)
{
...
...
@@ -683,11 +684,12 @@ static int process_query_packet(const knot_pkt_t *query,
// Loop over incoming messages, unless reply id is correct or timeout.
while
(
true
)
{
reply
=
NULL
;
// Receive a reply message.
in_len
=
net_receive
(
net
,
in
,
sizeof
(
in
));
if
(
in_len
<=
0
)
{
net_close
(
net
);
return
-
1
;
goto
fail
;
}
// Get stop reply time.
...
...
@@ -705,8 +707,7 @@ static int process_query_packet(const knot_pkt_t *query,
reply
=
knot_pkt_new
(
in
,
in_len
,
NULL
);
if
(
reply
==
NULL
)
{
ERR
(
"internal error (%s)"
,
knot_strerror
(
KNOT_ENOMEM
));
net_close
(
net
);
return
-
1
;
goto
fail
;
}
// Parse reply to the packet structure.
...
...
@@ -715,9 +716,7 @@ static int process_query_packet(const knot_pkt_t *query,
WARN
(
"malformed reply packet (%s)"
,
knot_strerror
(
ret
));
}
else
if
(
ret
!=
KNOT_EOK
)
{
ERR
(
"malformed reply packet from %s"
,
net
->
remote_str
);
knot_pkt_free
(
reply
);
net_close
(
net
);
return
-
1
;
goto
fail
;
}
// Compare reply header id.
...
...
@@ -725,9 +724,7 @@ static int process_query_packet(const knot_pkt_t *query,
break
;
// Check for timeout.
}
else
if
(
time_diff_ms
(
&
t_query
,
&
t_end
)
>
1000
*
net
->
wait
)
{
knot_pkt_free
(
reply
);
net_close
(
net
);
return
-
1
;
goto
fail
;
}
knot_pkt_free
(
reply
);
...
...
@@ -755,8 +752,15 @@ static int process_query_packet(const knot_pkt_t *query,
check_reply_qr
(
reply
);
// Print reply packet.
print_packet
(
reply
,
net
,
in_len
,
time_diff_ms
(
&
t_start
,
&
t_end
),
timestamp
,
true
,
style
);
if
(
style
->
format
!=
FORMAT_JSON
)
{
print_packet
(
reply
,
net
,
in_len
,
time_diff_ms
(
&
t_start
,
&
t_end
),
timestamp
,
true
,
style
);
}
else
{
knot_pkt_t
*
q
=
knot_pkt_new
(
query
->
wire
,
query
->
size
,
NULL
);
(
void
)
knot_pkt_parse
(
q
,
KNOT_PF_NOCANON
);
print_packets_json
(
q
,
reply
,
net
,
timestamp
,
style
);
knot_pkt_free
(
q
);
}
// Verify signature if a key was specified.
if
(
sign_ctx
->
digest
!=
NULL
)
{
...
...
@@ -780,17 +784,15 @@ static int process_query_packet(const knot_pkt_t *query,
uint8_t
*
opt
=
knot_pkt_edns_option
(
reply
,
KNOT_EDNS_OPTION_COOKIE
);
if
(
opt
==
NULL
)
{
ERR
(
"bad cookie, missing EDNS section"
);
knot_pkt_free
(
reply
);
return
-
1
;
goto
fail
;
}
const
uint8_t
*
data
=
knot_edns_opt_get_data
(
opt
);
uint16_t
data_len
=
knot_edns_opt_get_length
(
opt
);
ret
=
knot_edns_cookie_parse
(
&
new_ctx
.
cc
,
&
new_ctx
.
sc
,
data
,
data_len
);
if
(
ret
!=
KNOT_EOK
)
{
knot_pkt_free
(
reply
);
ERR
(
"bad cookie, missing EDNS cookie option"
);
return
-
1
;
goto
fail
;
}
knot_pkt_free
(
reply
);
...
...
@@ -811,6 +813,19 @@ static int process_query_packet(const knot_pkt_t *query,
net_close_keepopen
(
net
,
query_ctx
);
return
0
;
fail:
if
(
style
->
format
==
FORMAT_JSON
)
{
knot_pkt_t
*
q
=
knot_pkt_new
(
query
->
wire
,
query
->
size
,
NULL
);
(
void
)
knot_pkt_parse
(
q
,
KNOT_PF_NOCANON
);
print_packets_json
(
q
,
reply
,
net
,
timestamp
,
style
);
knot_pkt_free
(
q
);
}
knot_pkt_free
(
reply
);
net_close
(
net
);
return
-
1
;
}