Bug Summary

File:src/sbin/unwind/frontend.c
Warning:line 1749, column 20
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name frontend.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/unwind/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/unwind -I /usr/src/sbin/unwind -I /usr/src/sbin/unwind/libunbound/libunbound -I /usr/src/sbin/unwind/libunbound -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/unwind/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/unwind/frontend.c
1/* $OpenBSD: frontend.c,v 1.69 2021/11/16 16:45:23 kn Exp $ */
2
3/*
4 * Copyright (c) 2018 Florian Obser <florian@openbsd.org>
5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6 * Copyright (c) 2004 Esben Norby <norby@openbsd.org>
7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22#include <sys/types.h>
23#include <sys/queue.h>
24#include <sys/socket.h>
25#include <sys/syslog.h>
26#include <sys/tree.h>
27#include <sys/uio.h>
28
29#include <netinet/in.h>
30#include <net/if.h>
31#include <net/route.h>
32
33#include <errno(*__errno()).h>
34#include <event.h>
35#include <ifaddrs.h>
36#include <imsg.h>
37#include <netdb.h>
38#include <pwd.h>
39#include <signal.h>
40#include <stdint.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <time.h>
45#include <unistd.h>
46
47#include "libunbound/config.h"
48#include "libunbound/sldns/pkthdr.h"
49#include "libunbound/sldns/sbuffer.h"
50#include "libunbound/sldns/str2wire.h"
51#include "libunbound/sldns/wire2str.h"
52#include "libunbound/util/alloc.h"
53#include "libunbound/util/net_help.h"
54#include "libunbound/util/regional.h"
55#include "libunbound/util/data/dname.h"
56#include "libunbound/util/data/msgencode.h"
57#include "libunbound/util/data/msgparse.h"
58#include "libunbound/util/data/msgreply.h"
59
60#include "log.h"
61#include "unwind.h"
62#include "frontend.h"
63#include "control.h"
64#include "dns64_synth.h"
65
66#define ROUTE_SOCKET_BUF_SIZE16384 16384
67
68/*
69 * size of a resource record with name a two octed pointer to qname
70 * 2 octets pointer to qname
71 * 2 octets TYPE
72 * 2 octets CLASS
73 * 4 octets TTL
74 * 2 octets RDLENGTH
75 */
76#define COMPRESSED_RR_SIZE12 12
77#define MINIMIZE_ANSWER1 1
78
79#define FD_RESERVE5 5
80#define TCP_TIMEOUT15 15
81#define DEFAULT_TCP_SIZE512 512
82
83struct udp_ev {
84 struct event ev;
85 uint8_t query[65536];
86 struct msghdr rcvmhdr;
87 struct iovec rcviov[1];
88 struct sockaddr_storage from;
89} udp4ev, udp6ev;
90
91struct tcp_accept_ev {
92 struct event ev;
93 struct event pause;
94} tcp4ev, tcp6ev;
95
96struct pending_query {
97 TAILQ_ENTRY(pending_query)struct { struct pending_query *tqe_next; struct pending_query
**tqe_prev; }
entry;
98 struct sockaddr_storage from;
99 struct sldns_buffer *qbuf;
100 struct sldns_buffer *abuf;
101 struct regional *region;
102 struct query_info qinfo;
103 struct msg_parse *qmsg;
104 struct edns_data edns;
105 struct event ev; /* for tcp */
106 struct event resp_ev; /* for tcp */
107 struct event tmo_ev; /* for tcp */
108 uint64_t imsg_id;
109 int fd;
110 int tcp;
111 int dns64_synthesize;
112};
113
114TAILQ_HEAD(, pending_query)struct { struct pending_query *tqh_first; struct pending_query
**tqh_last; }
pending_queries;
115
116struct bl_node {
117 RB_ENTRY(bl_node)struct { struct bl_node *rbe_left; struct bl_node *rbe_right;
struct bl_node *rbe_parent; int rbe_color; }
entry;
118 char *domain;
119};
120
121__dead__attribute__((__noreturn__)) void frontend_shutdown(void);
122void frontend_sig_handler(int, short, void *);
123void frontend_startup(void);
124void udp_receive(int, short, void *);
125void handle_query(struct pending_query *);
126void free_pending_query(struct pending_query *);
127void tcp_accept(int, short, void *);
128int accept_reserve(int, struct sockaddr *, socklen_t *);
129void accept_paused(int, short, void *);
130void tcp_request(int, short, void *);
131void tcp_response(int, short, void *);
132void tcp_timeout(int, short, void *);
133int check_query(sldns_buffer*);
134void noerror_answer(struct pending_query *);
135void synthesize_dns64_answer(struct pending_query *);
136void resend_dns64_query(struct pending_query *);
137void chaos_answer(struct pending_query *);
138void error_answer(struct pending_query *, int rcode);
139void send_answer(struct pending_query *);
140void route_receive(int, short, void *);
141void handle_route_message(struct rt_msghdr *,
142 struct sockaddr **);
143void get_rtaddrs(int, struct sockaddr *,
144 struct sockaddr **);
145void rtmget_default(void);
146struct pending_query *find_pending_query(uint64_t);
147void parse_trust_anchor(struct trust_anchor_head *, int);
148void send_trust_anchors(struct trust_anchor_head *);
149void write_trust_anchors(struct trust_anchor_head *, int);
150void parse_blocklist(int);
151int bl_cmp(struct bl_node *, struct bl_node *);
152void free_bl(void);
153int pending_query_cnt(void);
154void check_available_af(void);
155
156struct uw_conf *frontend_conf;
157static struct imsgev *iev_main;
158static struct imsgev *iev_resolver;
159struct event ev_route;
160int udp4sock = -1, udp6sock = -1;
161int tcp4sock = -1, tcp6sock = -1;
162int ta_fd = -1;
163
164static struct trust_anchor_head trust_anchors, new_trust_anchors;
165
166RB_HEAD(bl_tree, bl_node)struct bl_tree { struct bl_node *rbh_root; } bl_head = RB_INITIALIZER(&bl_head){ ((void*)0) };
167RB_PROTOTYPE(bl_tree, bl_node, entry, bl_cmp)void bl_tree_RB_INSERT_COLOR(struct bl_tree *, struct bl_node
*); void bl_tree_RB_REMOVE_COLOR(struct bl_tree *, struct bl_node
*, struct bl_node *); struct bl_node *bl_tree_RB_REMOVE(struct
bl_tree *, struct bl_node *); struct bl_node *bl_tree_RB_INSERT
(struct bl_tree *, struct bl_node *); struct bl_node *bl_tree_RB_FIND
(struct bl_tree *, struct bl_node *); struct bl_node *bl_tree_RB_NFIND
(struct bl_tree *, struct bl_node *); struct bl_node *bl_tree_RB_NEXT
(struct bl_node *); struct bl_node *bl_tree_RB_PREV(struct bl_node
*); struct bl_node *bl_tree_RB_MINMAX(struct bl_tree *, int)
;
168RB_GENERATE(bl_tree, bl_node, entry, bl_cmp)void bl_tree_RB_INSERT_COLOR(struct bl_tree *head, struct bl_node
*elm) { struct bl_node *parent, *gparent, *tmp; while ((parent
= (elm)->entry.rbe_parent) && (parent)->entry.
rbe_color == 1) { gparent = (parent)->entry.rbe_parent; if
(parent == (gparent)->entry.rbe_left) { tmp = (gparent)->
entry.rbe_right; if (tmp && (tmp)->entry.rbe_color
== 1) { (tmp)->entry.rbe_color = 0; do { (parent)->entry
.rbe_color = 0; (gparent)->entry.rbe_color = 1; } while (0
); elm = gparent; continue; } if ((parent)->entry.rbe_right
== elm) { do { (tmp) = (parent)->entry.rbe_right; if (((parent
)->entry.rbe_right = (tmp)->entry.rbe_left)) { ((tmp)->
entry.rbe_left)->entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->entry.rbe_parent = (parent)->entry.rbe_parent
)) { if ((parent) == ((parent)->entry.rbe_parent)->entry
.rbe_left) ((parent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((parent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_left = (parent); (parent)->entry.rbe_parent = (tmp); do
{} while (0); if (((tmp)->entry.rbe_parent)) do {} while (
0); } while (0); tmp = parent; parent = elm; elm = tmp; } do {
(parent)->entry.rbe_color = 0; (gparent)->entry.rbe_color
= 1; } while (0); do { (tmp) = (gparent)->entry.rbe_left;
if (((gparent)->entry.rbe_left = (tmp)->entry.rbe_right
)) { ((tmp)->entry.rbe_right)->entry.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (gparent
)->entry.rbe_parent)) { if ((gparent) == ((gparent)->entry
.rbe_parent)->entry.rbe_left) ((gparent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((gparent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_right = (gparent); (gparent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); } else { tmp = (gparent)->
entry.rbe_left; if (tmp && (tmp)->entry.rbe_color ==
1) { (tmp)->entry.rbe_color = 0; do { (parent)->entry.
rbe_color = 0; (gparent)->entry.rbe_color = 1; } while (0)
; elm = gparent; continue; } if ((parent)->entry.rbe_left ==
elm) { do { (tmp) = (parent)->entry.rbe_left; if (((parent
)->entry.rbe_left = (tmp)->entry.rbe_right)) { ((tmp)->
entry.rbe_right)->entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->entry.rbe_parent = (parent)->entry.rbe_parent
)) { if ((parent) == ((parent)->entry.rbe_parent)->entry
.rbe_left) ((parent)->entry.rbe_parent)->entry.rbe_left
= (tmp); else ((parent)->entry.rbe_parent)->entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->entry
.rbe_right = (parent); (parent)->entry.rbe_parent = (tmp);
do {} while (0); if (((tmp)->entry.rbe_parent)) do {} while
(0); } while (0); tmp = parent; parent = elm; elm = tmp; } do
{ (parent)->entry.rbe_color = 0; (gparent)->entry.rbe_color
= 1; } while (0); do { (tmp) = (gparent)->entry.rbe_right
; if (((gparent)->entry.rbe_right = (tmp)->entry.rbe_left
)) { ((tmp)->entry.rbe_left)->entry.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (gparent
)->entry.rbe_parent)) { if ((gparent) == ((gparent)->entry
.rbe_parent)->entry.rbe_left) ((gparent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((gparent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_left = (gparent); (gparent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); } } (head->rbh_root)->
entry.rbe_color = 0; } void bl_tree_RB_REMOVE_COLOR(struct bl_tree
*head, struct bl_node *parent, struct bl_node *elm) { struct
bl_node *tmp; while ((elm == ((void*)0) || (elm)->entry.rbe_color
== 0) && elm != (head)->rbh_root) { if ((parent)->
entry.rbe_left == elm) { tmp = (parent)->entry.rbe_right; if
((tmp)->entry.rbe_color == 1) { do { (tmp)->entry.rbe_color
= 0; (parent)->entry.rbe_color = 1; } while (0); do { (tmp
) = (parent)->entry.rbe_right; if (((parent)->entry.rbe_right
= (tmp)->entry.rbe_left)) { ((tmp)->entry.rbe_left)->
entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->
entry.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent
) == ((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_left = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = (parent)->entry.rbe_right; } if (((tmp)->entry.rbe_left
== ((void*)0) || ((tmp)->entry.rbe_left)->entry.rbe_color
== 0) && ((tmp)->entry.rbe_right == ((void*)0) ||
((tmp)->entry.rbe_right)->entry.rbe_color == 0)) { (tmp
)->entry.rbe_color = 1; elm = parent; parent = (elm)->entry
.rbe_parent; } else { if ((tmp)->entry.rbe_right == ((void
*)0) || ((tmp)->entry.rbe_right)->entry.rbe_color == 0)
{ struct bl_node *oleft; if ((oleft = (tmp)->entry.rbe_left
)) (oleft)->entry.rbe_color = 0; (tmp)->entry.rbe_color
= 1; do { (oleft) = (tmp)->entry.rbe_left; if (((tmp)->
entry.rbe_left = (oleft)->entry.rbe_right)) { ((oleft)->
entry.rbe_right)->entry.rbe_parent = (tmp); } do {} while (
0); if (((oleft)->entry.rbe_parent = (tmp)->entry.rbe_parent
)) { if ((tmp) == ((tmp)->entry.rbe_parent)->entry.rbe_left
) ((tmp)->entry.rbe_parent)->entry.rbe_left = (oleft); else
((tmp)->entry.rbe_parent)->entry.rbe_right = (oleft); }
else (head)->rbh_root = (oleft); (oleft)->entry.rbe_right
= (tmp); (tmp)->entry.rbe_parent = (oleft); do {} while (
0); if (((oleft)->entry.rbe_parent)) do {} while (0); } while
(0); tmp = (parent)->entry.rbe_right; } (tmp)->entry.rbe_color
= (parent)->entry.rbe_color; (parent)->entry.rbe_color
= 0; if ((tmp)->entry.rbe_right) ((tmp)->entry.rbe_right
)->entry.rbe_color = 0; do { (tmp) = (parent)->entry.rbe_right
; if (((parent)->entry.rbe_right = (tmp)->entry.rbe_left
)) { ((tmp)->entry.rbe_left)->entry.rbe_parent = (parent
); } do {} while (0); if (((tmp)->entry.rbe_parent = (parent
)->entry.rbe_parent)) { if ((parent) == ((parent)->entry
.rbe_parent)->entry.rbe_left) ((parent)->entry.rbe_parent
)->entry.rbe_left = (tmp); else ((parent)->entry.rbe_parent
)->entry.rbe_right = (tmp); } else (head)->rbh_root = (
tmp); (tmp)->entry.rbe_left = (parent); (parent)->entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->entry.rbe_parent
)) do {} while (0); } while (0); elm = (head)->rbh_root; break
; } } else { tmp = (parent)->entry.rbe_left; if ((tmp)->
entry.rbe_color == 1) { do { (tmp)->entry.rbe_color = 0; (
parent)->entry.rbe_color = 1; } while (0); do { (tmp) = (parent
)->entry.rbe_left; if (((parent)->entry.rbe_left = (tmp
)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->entry
.rbe_parent = (parent); } do {} while (0); if (((tmp)->entry
.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent) ==
((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
tmp = (parent)->entry.rbe_left; } if (((tmp)->entry.rbe_left
== ((void*)0) || ((tmp)->entry.rbe_left)->entry.rbe_color
== 0) && ((tmp)->entry.rbe_right == ((void*)0) ||
((tmp)->entry.rbe_right)->entry.rbe_color == 0)) { (tmp
)->entry.rbe_color = 1; elm = parent; parent = (elm)->entry
.rbe_parent; } else { if ((tmp)->entry.rbe_left == ((void*
)0) || ((tmp)->entry.rbe_left)->entry.rbe_color == 0) {
struct bl_node *oright; if ((oright = (tmp)->entry.rbe_right
)) (oright)->entry.rbe_color = 0; (tmp)->entry.rbe_color
= 1; do { (oright) = (tmp)->entry.rbe_right; if (((tmp)->
entry.rbe_right = (oright)->entry.rbe_left)) { ((oright)->
entry.rbe_left)->entry.rbe_parent = (tmp); } do {} while (
0); if (((oright)->entry.rbe_parent = (tmp)->entry.rbe_parent
)) { if ((tmp) == ((tmp)->entry.rbe_parent)->entry.rbe_left
) ((tmp)->entry.rbe_parent)->entry.rbe_left = (oright);
else ((tmp)->entry.rbe_parent)->entry.rbe_right = (oright
); } else (head)->rbh_root = (oright); (oright)->entry.
rbe_left = (tmp); (tmp)->entry.rbe_parent = (oright); do {
} while (0); if (((oright)->entry.rbe_parent)) do {} while
(0); } while (0); tmp = (parent)->entry.rbe_left; } (tmp)
->entry.rbe_color = (parent)->entry.rbe_color; (parent)
->entry.rbe_color = 0; if ((tmp)->entry.rbe_left) ((tmp
)->entry.rbe_left)->entry.rbe_color = 0; do { (tmp) = (
parent)->entry.rbe_left; if (((parent)->entry.rbe_left =
(tmp)->entry.rbe_right)) { ((tmp)->entry.rbe_right)->
entry.rbe_parent = (parent); } do {} while (0); if (((tmp)->
entry.rbe_parent = (parent)->entry.rbe_parent)) { if ((parent
) == ((parent)->entry.rbe_parent)->entry.rbe_left) ((parent
)->entry.rbe_parent)->entry.rbe_left = (tmp); else ((parent
)->entry.rbe_parent)->entry.rbe_right = (tmp); } else (
head)->rbh_root = (tmp); (tmp)->entry.rbe_right = (parent
); (parent)->entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->entry.rbe_parent)) do {} while (0); } while (0);
elm = (head)->rbh_root; break; } } } if (elm) (elm)->entry
.rbe_color = 0; } struct bl_node * bl_tree_RB_REMOVE(struct bl_tree
*head, struct bl_node *elm) { struct bl_node *child, *parent
, *old = elm; int color; if ((elm)->entry.rbe_left == ((void
*)0)) child = (elm)->entry.rbe_right; else if ((elm)->entry
.rbe_right == ((void*)0)) child = (elm)->entry.rbe_left; else
{ struct bl_node *left; elm = (elm)->entry.rbe_right; while
((left = (elm)->entry.rbe_left)) elm = left; child = (elm
)->entry.rbe_right; parent = (elm)->entry.rbe_parent; color
= (elm)->entry.rbe_color; if (child) (child)->entry.rbe_parent
= parent; if (parent) { if ((parent)->entry.rbe_left == elm
) (parent)->entry.rbe_left = child; else (parent)->entry
.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->entry.rbe_parent == old) parent = elm
; (elm)->entry = (old)->entry; if ((old)->entry.rbe_parent
) { if (((old)->entry.rbe_parent)->entry.rbe_left == old
) ((old)->entry.rbe_parent)->entry.rbe_left = elm; else
((old)->entry.rbe_parent)->entry.rbe_right = elm; do {
} while (0); } else (head)->rbh_root = elm; ((old)->entry
.rbe_left)->entry.rbe_parent = elm; if ((old)->entry.rbe_right
) ((old)->entry.rbe_right)->entry.rbe_parent = elm; if (
parent) { left = parent; do { do {} while (0); } while ((left
= (left)->entry.rbe_parent)); } goto color; } parent = (elm
)->entry.rbe_parent; color = (elm)->entry.rbe_color; if
(child) (child)->entry.rbe_parent = parent; if (parent) {
if ((parent)->entry.rbe_left == elm) (parent)->entry.rbe_left
= child; else (parent)->entry.rbe_right = child; do {} while
(0); } else (head)->rbh_root = child; color: if (color ==
0) bl_tree_RB_REMOVE_COLOR(head, parent, child); return (old
); } struct bl_node * bl_tree_RB_INSERT(struct bl_tree *head,
struct bl_node *elm) { struct bl_node *tmp; struct bl_node *
parent = ((void*)0); int comp = 0; tmp = (head)->rbh_root;
while (tmp) { parent = tmp; comp = (bl_cmp)(elm, parent); if
(comp < 0) tmp = (tmp)->entry.rbe_left; else if (comp >
0) tmp = (tmp)->entry.rbe_right; else return (tmp); } do {
(elm)->entry.rbe_parent = parent; (elm)->entry.rbe_left
= (elm)->entry.rbe_right = ((void*)0); (elm)->entry.rbe_color
= 1; } while (0); if (parent != ((void*)0)) { if (comp < 0
) (parent)->entry.rbe_left = elm; else (parent)->entry.
rbe_right = elm; do {} while (0); } else (head)->rbh_root =
elm; bl_tree_RB_INSERT_COLOR(head, elm); return (((void*)0))
; } struct bl_node * bl_tree_RB_FIND(struct bl_tree *head, struct
bl_node *elm) { struct bl_node *tmp = (head)->rbh_root; int
comp; while (tmp) { comp = bl_cmp(elm, tmp); if (comp < 0
) tmp = (tmp)->entry.rbe_left; else if (comp > 0) tmp =
(tmp)->entry.rbe_right; else return (tmp); } return (((void
*)0)); } struct bl_node * bl_tree_RB_NFIND(struct bl_tree *head
, struct bl_node *elm) { struct bl_node *tmp = (head)->rbh_root
; struct bl_node *res = ((void*)0); int comp; while (tmp) { comp
= bl_cmp(elm, tmp); if (comp < 0) { res = tmp; tmp = (tmp
)->entry.rbe_left; } else if (comp > 0) tmp = (tmp)->
entry.rbe_right; else return (tmp); } return (res); } struct bl_node
* bl_tree_RB_NEXT(struct bl_node *elm) { if ((elm)->entry
.rbe_right) { elm = (elm)->entry.rbe_right; while ((elm)->
entry.rbe_left) elm = (elm)->entry.rbe_left; } else { if (
(elm)->entry.rbe_parent && (elm == ((elm)->entry
.rbe_parent)->entry.rbe_left)) elm = (elm)->entry.rbe_parent
; else { while ((elm)->entry.rbe_parent && (elm ==
((elm)->entry.rbe_parent)->entry.rbe_right)) elm = (elm
)->entry.rbe_parent; elm = (elm)->entry.rbe_parent; } }
return (elm); } struct bl_node * bl_tree_RB_PREV(struct bl_node
*elm) { if ((elm)->entry.rbe_left) { elm = (elm)->entry
.rbe_left; while ((elm)->entry.rbe_right) elm = (elm)->
entry.rbe_right; } else { if ((elm)->entry.rbe_parent &&
(elm == ((elm)->entry.rbe_parent)->entry.rbe_right)) elm
= (elm)->entry.rbe_parent; else { while ((elm)->entry.
rbe_parent && (elm == ((elm)->entry.rbe_parent)->
entry.rbe_left)) elm = (elm)->entry.rbe_parent; elm = (elm
)->entry.rbe_parent; } } return (elm); } struct bl_node * bl_tree_RB_MINMAX
(struct bl_tree *head, int val) { struct bl_node *tmp = (head
)->rbh_root; struct bl_node *parent = ((void*)0); while (tmp
) { parent = tmp; if (val < 0) tmp = (tmp)->entry.rbe_left
; else tmp = (tmp)->entry.rbe_right; } return (parent); }
169
170struct dns64_prefix *dns64_prefixes;
171int dns64_prefix_count;
172
173void
174frontend_sig_handler(int sig, short event, void *bula)
175{
176 /*
177 * Normal signal handler rules don't apply because libevent
178 * decouples for us.
179 */
180
181 switch (sig) {
182 case SIGINT2:
183 case SIGTERM15:
184 frontend_shutdown();
185 default:
186 fatalx("unexpected signal");
187 }
188}
189
190void
191frontend(int debug, int verbose)
192{
193 struct event ev_sigint, ev_sigterm;
194 struct passwd *pw;
195
196 frontend_conf = config_new_empty();
197
198 log_init(debug, LOG_DAEMON)uw_log_init(debug, (3<<3));
199 log_setverbose(verbose);
200
201 if ((pw = getpwnam(UNWIND_USER"_unwind")) == NULL((void*)0))
202 fatal("getpwnam");
203
204 if (chroot(pw->pw_dir) == -1)
205 fatal("chroot");
206 if (chdir("/") == -1)
207 fatal("chdir(\"/\")");
208
209 setproctitle("%s", "frontend");
210 log_procinit("frontend");
211
212 if (setgroups(1, &pw->pw_gid) ||
213 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
214 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
215 fatal("can't drop privileges");
216
217 if (pledge("stdio dns unix recvfd", NULL((void*)0)) == -1)
218 fatal("pledge");
219
220 event_init();
221
222 /* Setup signal handler. */
223 signal_set(&ev_sigint, SIGINT, frontend_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, frontend_sig_handler,
((void*)0))
;
224 signal_set(&ev_sigterm, SIGTERM, frontend_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, frontend_sig_handler
, ((void*)0))
;
225 signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void*)0));
226 signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void*)0));
227 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
228 signal(SIGHUP1, SIG_IGN(void (*)(int))1);
229
230 /* Setup pipe and event handler to the parent process. */
231 if (iev_main != NULL((void*)0))
232 fatal("iev_main");
233 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL((void*)0))
234 fatal(NULL((void*)0));
235 imsg_init(&iev_main->ibuf, 3);
236 iev_main->handler = frontend_dispatch_main;
237 iev_main->events = EV_READ0x02;
238 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
239 iev_main->handler, iev_main);
240 event_add(&iev_main->ev, NULL((void*)0));
241
242 udp4ev.rcviov[0].iov_base = (caddr_t)udp4ev.query;
243 udp4ev.rcviov[0].iov_len = sizeof(udp4ev.query);
244 udp4ev.rcvmhdr.msg_name = (caddr_t)&udp4ev.from;
245 udp4ev.rcvmhdr.msg_namelen = sizeof(udp4ev.from);
246 udp4ev.rcvmhdr.msg_iov = udp4ev.rcviov;
247 udp4ev.rcvmhdr.msg_iovlen = 1;
248
249 udp6ev.rcviov[0].iov_base = (caddr_t)udp6ev.query;
250 udp6ev.rcviov[0].iov_len = sizeof(udp6ev.query);
251 udp6ev.rcvmhdr.msg_name = (caddr_t)&udp6ev.from;
252 udp6ev.rcvmhdr.msg_namelen = sizeof(udp6ev.from);
253 udp6ev.rcvmhdr.msg_iov = udp6ev.rcviov;
254 udp6ev.rcvmhdr.msg_iovlen = 1;
255
256 TAILQ_INIT(&pending_queries)do { (&pending_queries)->tqh_first = ((void*)0); (&
pending_queries)->tqh_last = &(&pending_queries)->
tqh_first; } while (0)
;
257
258 TAILQ_INIT(&trust_anchors)do { (&trust_anchors)->tqh_first = ((void*)0); (&trust_anchors
)->tqh_last = &(&trust_anchors)->tqh_first; } while
(0)
;
259 TAILQ_INIT(&new_trust_anchors)do { (&new_trust_anchors)->tqh_first = ((void*)0); (&
new_trust_anchors)->tqh_last = &(&new_trust_anchors
)->tqh_first; } while (0)
;
260
261 add_new_ta(&trust_anchors, KSK2017". 172800 IN DNSKEY 257 3 8 AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3+/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kvArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+eoZG+SrDK6nWeL3c6H5Apxz7LjVc1uTIdsIXxuOLYA4/ilBmSVIzuDWfdRUfhHdY6+cn8HFRm+2hM8AnXGXws9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU=");
262
263 event_dispatch();
264
265 frontend_shutdown();
266}
267
268__dead__attribute__((__noreturn__)) void
269frontend_shutdown(void)
270{
271 /* Close pipes. */
272 msgbuf_write(&iev_resolver->ibuf.w);
273 msgbuf_clear(&iev_resolver->ibuf.w);
274 close(iev_resolver->ibuf.fd);
275 msgbuf_write(&iev_main->ibuf.w);
276 msgbuf_clear(&iev_main->ibuf.w);
277 close(iev_main->ibuf.fd);
278
279 config_clear(frontend_conf);
280
281 free(iev_resolver);
282 free(iev_main);
283
284 log_info("frontend exiting")uw_log_info("frontend exiting");
285 exit(0);
286}
287
288int
289frontend_imsg_compose_main(int type, pid_t pid, void *data, uint16_t datalen)
290{
291 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
292}
293
294int
295frontend_imsg_compose_resolver(int type, pid_t pid, void *data,
296 uint16_t datalen)
297{
298 return (imsg_compose_event(iev_resolver, type, 0, pid, -1, data,
299 datalen));
300}
301
302void
303frontend_dispatch_main(int fd, short event, void *bula)
304{
305 static struct uw_conf *nconf;
306 struct imsg imsg;
307 struct imsgev *iev = bula;
308 struct imsgbuf *ibuf = &iev->ibuf;
309 int n, shut = 0;
310
311 if (event & EV_READ0x02) {
312 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
313 fatal("imsg_read error");
314 if (n == 0) /* Connection closed. */
315 shut = 1;
316 }
317 if (event & EV_WRITE0x04) {
318 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
319 fatal("msgbuf_write");
320 if (n == 0) /* Connection closed. */
321 shut = 1;
322 }
323
324 for (;;) {
325 if ((n = imsg_get(ibuf, &imsg)) == -1)
326 fatal("%s: imsg_get error", __func__);
327 if (n == 0) /* No more messages. */
328 break;
329
330 switch (imsg.hdr.type) {
331 case IMSG_SOCKET_IPC_RESOLVER:
332 /*
333 * Setup pipe and event handler to the resolver
334 * process.
335 */
336 if (iev_resolver) {
337 fatalx("%s: received unexpected imsg fd "
338 "to frontend", __func__);
339 break;
340 }
341 if ((fd = imsg.fd) == -1) {
342 fatalx("%s: expected to receive imsg fd to "
343 "frontend but didn't receive any",
344 __func__);
345 break;
346 }
347
348 if (iev_resolver != NULL((void*)0))
349 fatal("iev_resolver");
350 iev_resolver = malloc(sizeof(struct imsgev));
351 if (iev_resolver == NULL((void*)0))
352 fatal(NULL((void*)0));
353
354 imsg_init(&iev_resolver->ibuf, fd);
355 iev_resolver->handler = frontend_dispatch_resolver;
356 iev_resolver->events = EV_READ0x02;
357
358 event_set(&iev_resolver->ev, iev_resolver->ibuf.fd,
359 iev_resolver->events, iev_resolver->handler,
360 iev_resolver);
361 event_add(&iev_resolver->ev, NULL((void*)0));
362 break;
363 case IMSG_RECONF_CONF:
364 case IMSG_RECONF_BLOCKLIST_FILE:
365 case IMSG_RECONF_FORWARDER:
366 case IMSG_RECONF_DOT_FORWARDER:
367 case IMSG_RECONF_FORCE:
368 imsg_receive_config(&imsg, &nconf);
369 break;
370 case IMSG_RECONF_END:
371 if (nconf == NULL((void*)0))
372 fatalx("%s: IMSG_RECONF_END without "
373 "IMSG_RECONF_CONF", __func__);
374 merge_config(frontend_conf, nconf);
375 if (frontend_conf->blocklist_file == NULL((void*)0))
376 free_bl();
377 nconf = NULL((void*)0);
378 break;
379 case IMSG_UDP6SOCK:
380 if (udp6sock != -1)
381 fatalx("%s: received unexpected udp6sock",
382 __func__);
383 if ((udp6sock = imsg.fd) == -1)
384 fatalx("%s: expected to receive imsg "
385 "UDP6 fd but didn't receive any", __func__);
386 event_set(&udp6ev.ev, udp6sock, EV_READ0x02 | EV_PERSIST0x10,
387 udp_receive, &udp6ev);
388 event_add(&udp6ev.ev, NULL((void*)0));
389 break;
390 case IMSG_UDP4SOCK:
391 if (udp4sock != -1)
392 fatalx("%s: received unexpected udp4sock",
393 __func__);
394 if ((udp4sock = imsg.fd) == -1)
395 fatalx("%s: expected to receive imsg "
396 "UDP4 fd but didn't receive any", __func__);
397 event_set(&udp4ev.ev, udp4sock, EV_READ0x02 | EV_PERSIST0x10,
398 udp_receive, &udp4ev);
399 event_add(&udp4ev.ev, NULL((void*)0));
400 break;
401 case IMSG_TCP4SOCK:
402 if (tcp4sock != -1)
403 fatalx("%s: received unexpected tcp4sock",
404 __func__);
405 if ((tcp4sock = imsg.fd) == -1)
406 fatalx("%s: expected to receive imsg "
407 "TCP4 fd but didn't receive any", __func__);
408 event_set(&tcp4ev.ev, tcp4sock, EV_READ0x02 | EV_PERSIST0x10,
409 tcp_accept, &tcp4ev);
410 event_add(&tcp4ev.ev, NULL((void*)0));
411 evtimer_set(&tcp4ev.pause, accept_paused, &tcp4ev)event_set(&tcp4ev.pause, -1, 0, accept_paused, &tcp4ev
)
;
412 break;
413 case IMSG_TCP6SOCK:
414 if (tcp6sock != -1)
415 fatalx("%s: received unexpected tcp6sock",
416 __func__);
417 if ((tcp6sock = imsg.fd) == -1)
418 fatalx("%s: expected to receive imsg "
419 "TCP6 fd but didn't receive any", __func__);
420 event_set(&tcp6ev.ev, tcp6sock, EV_READ0x02 | EV_PERSIST0x10,
421 tcp_accept, &tcp6ev);
422 event_add(&tcp6ev.ev, NULL((void*)0));
423 evtimer_set(&tcp6ev.pause, accept_paused, &tcp6ev)event_set(&tcp6ev.pause, -1, 0, accept_paused, &tcp6ev
)
;
424 break;
425 case IMSG_ROUTESOCK: {
426 static int routesock = -1;
427
428 if (routesock != -1)
429 fatalx("%s: received unexpected routesock",
430 __func__);
431 if ((fd = imsg.fd) == -1)
432 fatalx("%s: expected to receive imsg "
433 "routesocket fd but didn't receive any",
434 __func__);
435 routesock = fd;
436 event_set(&ev_route, fd, EV_READ0x02 | EV_PERSIST0x10,
437 route_receive, NULL((void*)0));
438 break;
439 }
440 case IMSG_STARTUP:
441 frontend_startup();
442 break;
443 case IMSG_CONTROLFD:
444 if ((fd = imsg.fd) == -1)
445 fatalx("%s: expected to receive imsg control "
446 "fd but didn't receive any", __func__);
447 /* Listen on control socket. */
448 control_listen(fd);
449 break;
450 case IMSG_TAFD:
451 if ((ta_fd = imsg.fd) != -1)
452 parse_trust_anchor(&trust_anchors, ta_fd);
453 if (!TAILQ_EMPTY(&trust_anchors)(((&trust_anchors)->tqh_first) == ((void*)0)))
454 send_trust_anchors(&trust_anchors);
455 break;
456 case IMSG_BLFD:
457 if ((fd = imsg.fd) == -1)
458 fatalx("%s: expected to receive imsg block "
459 "list fd but didn't receive any", __func__);
460 parse_blocklist(fd);
461 break;
462 default:
463 log_debug("%s: error handling imsg %d", __func__,
464 imsg.hdr.type);
465 break;
466 }
467 imsg_free(&imsg);
468 }
469 if (!shut)
470 imsg_event_add(iev);
471 else {
472 /* This pipe is dead. Remove its event handler. */
473 event_del(&iev->ev);
474 event_loopexit(NULL((void*)0));
475 }
476}
477
478void
479frontend_dispatch_resolver(int fd, short event, void *bula)
480{
481 static struct dns64_prefix *new_dns64_prefixes = NULL((void*)0);
482 static int new_dns64_prefix_count = 0;
483 static int new_dns64_prefix_pos = 0;
484 struct pending_query *pq;
485 struct imsgev *iev = bula;
486 struct imsgbuf *ibuf = &iev->ibuf;
487 struct imsg imsg;
488 int n, shut = 0, chg;
489
490 if (event & EV_READ0x02) {
491 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
492 fatal("imsg_read error");
493 if (n == 0) /* Connection closed. */
494 shut = 1;
495 }
496 if (event & EV_WRITE0x04) {
497 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
498 fatal("msgbuf_write");
499 if (n == 0) /* Connection closed. */
500 shut = 1;
501 }
502
503 for (;;) {
504 if ((n = imsg_get(ibuf, &imsg)) == -1)
505 fatal("%s: imsg_get error", __func__);
506 if (n == 0) /* No more messages. */
507 break;
508
509 switch (imsg.hdr.type) {
510 case IMSG_ANSWER: {
511 struct answer_header *answer_header;
512 int data_len;
513 uint8_t *data;
514
515 if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) < sizeof(*answer_header))
516 fatalx("%s: IMSG_ANSWER wrong length: "
517 "%lu", __func__, IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)));
518 answer_header = (struct answer_header *)imsg.data;
519 data = (uint8_t *)imsg.data + sizeof(*answer_header);
520 if (answer_header->answer_len > UINT16_MAX0xffff)
521 fatalx("%s: IMSG_ANSWER answer too big: %d",
522 __func__, answer_header->answer_len);
523 data_len = IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) -
524 sizeof(*answer_header);
525
526 if ((pq = find_pending_query(answer_header->id)) ==
527 NULL((void*)0)) {
528 log_warnx("%s: cannot find pending query %llu",
529 __func__, answer_header->id);
530 break;
531 }
532
533 if (answer_header->srvfail) {
534 error_answer(pq, LDNS_RCODE_SERVFAIL);
535 send_answer(pq);
536 break;
537 }
538
539 if (answer_header->bogus && !(pq->qmsg->flags &
540 BIT_CD0x0010)) {
541 error_answer(pq, LDNS_RCODE_SERVFAIL);
542 send_answer(pq);
543 break;
544 }
545
546 if (sldns_buffer_position(pq->abuf) == 0 &&
547 !sldns_buffer_set_capacity(pq->abuf,
548 answer_header->answer_len)) {
549 error_answer(pq, LDNS_RCODE_SERVFAIL);
550 send_answer(pq);
551 break;
552 }
553
554 if (sldns_buffer_position(pq->abuf) + data_len >
555 sldns_buffer_capacity(pq->abuf))
556 fatalx("%s: IMSG_ANSWER answer too big: %d",
557 __func__, data_len);
558 sldns_buffer_write(pq->abuf, data, data_len);
559
560 if (sldns_buffer_position(pq->abuf) ==
561 sldns_buffer_capacity(pq->abuf)) {
562 sldns_buffer_flip(pq->abuf);
563 if (pq->dns64_synthesize) {
564 synthesize_dns64_answer(pq);
565 send_answer(pq);
566 } else {
567 noerror_answer(pq);
568 if (pq->dns64_synthesize)
569 /* we did not find a answer */
570 resend_dns64_query(pq);
571 else
572 send_answer(pq);
573 }
574 }
575 break;
576 }
577 case IMSG_CTL_RESOLVER_INFO:
578 case IMSG_CTL_AUTOCONF_RESOLVER_INFO:
579 case IMSG_CTL_MEM_INFO:
580 case IMSG_CTL_END:
581 control_imsg_relay(&imsg);
582 break;
583 case IMSG_NEW_TA:
584 /* make sure this is a string */
585 ((char *)imsg.data)[IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) - 1] = '\0';
586 add_new_ta(&new_trust_anchors, imsg.data);
587 break;
588 case IMSG_NEW_TAS_ABORT:
589 free_tas(&new_trust_anchors);
590 break;
591 case IMSG_NEW_TAS_DONE:
592 chg = merge_tas(&new_trust_anchors, &trust_anchors);
593 if (chg)
594 send_trust_anchors(&trust_anchors);
595
596 /*
597 * always write trust anchors, the modify date on
598 * the file is an indication when we made progress
599 */
600 if (ta_fd != -1)
601 write_trust_anchors(&trust_anchors, ta_fd);
602 break;
603 case IMSG_NEW_DNS64_PREFIXES_START:
604 if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) !=
605 sizeof(new_dns64_prefix_count))
606 fatalx("%s: IMSG_NEW_DNS64_PREFIXES_START "
607 "wrong length: %lu", __func__,
608 IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)));
609 memcpy(&new_dns64_prefix_count, imsg.data,
610 sizeof(new_dns64_prefix_count));
611 free(new_dns64_prefixes);
612 new_dns64_prefixes = NULL((void*)0);
613 if (new_dns64_prefix_count > 0)
614 new_dns64_prefixes =
615 calloc(new_dns64_prefix_count,
616 sizeof(struct dns64_prefix));
617 new_dns64_prefix_pos = 0;
618 break;
619 case IMSG_NEW_DNS64_PREFIX: {
620 if (IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)) != sizeof(struct dns64_prefix))
621 fatalx("%s: IMSG_NEW_DNS64_PREFIX wrong "
622 "length: %lu", __func__,
623 IMSG_DATA_SIZE(imsg)((imsg).hdr.len - sizeof(struct imsg_hdr)));
624 if (new_dns64_prefixes == NULL((void*)0))
625 break;
626 if (new_dns64_prefix_pos >= new_dns64_prefix_count)
627 fatalx("%s: IMSG_NEW_DNS64_PREFIX: too many "
628 "prefixes", __func__);
629 memcpy(&new_dns64_prefixes[new_dns64_prefix_pos++],
630 imsg.data, sizeof(struct dns64_prefix));
631 break;
632 }
633 case IMSG_NEW_DNS64_PREFIXES_DONE:
634 free(dns64_prefixes);
635 dns64_prefixes = new_dns64_prefixes;
636 dns64_prefix_count = new_dns64_prefix_count;
637 new_dns64_prefixes = NULL((void*)0);
638 break;
639 default:
640 log_debug("%s: error handling imsg %d", __func__,
641 imsg.hdr.type);
642 break;
643 }
644 imsg_free(&imsg);
645 }
646 if (!shut)
647 imsg_event_add(iev);
648 else {
649 /* This pipe is dead. Remove its event handler. */
650 event_del(&iev->ev);
651 event_loopexit(NULL((void*)0));
652 }
653}
654
655void
656frontend_startup(void)
657{
658 if (!event_initialized(&ev_route)((&ev_route)->ev_flags & 0x80))
659 fatalx("%s: did not receive a route socket from the main "
660 "process", __func__);
661
662 event_add(&ev_route, NULL((void*)0));
663
664 frontend_imsg_compose_main(IMSG_STARTUP_DONE, 0, NULL((void*)0), 0);
665 check_available_af();
666}
667
668void
669free_pending_query(struct pending_query *pq)
670{
671 if (!pq
6.1
'pq' is non-null
)
7
Taking false branch
672 return;
673
674 TAILQ_REMOVE(&pending_queries, pq, entry)do { if (((pq)->entry.tqe_next) != ((void*)0)) (pq)->entry
.tqe_next->entry.tqe_prev = (pq)->entry.tqe_prev; else (
&pending_queries)->tqh_last = (pq)->entry.tqe_prev;
*(pq)->entry.tqe_prev = (pq)->entry.tqe_next; ; ; } while
(0)
;
8
Assuming field 'tqe_next' is equal to null
9
Taking false branch
10
Loop condition is false. Exiting loop
675 regional_destroy(pq->region);
676 sldns_buffer_free(pq->qbuf);
677 sldns_buffer_free(pq->abuf);
678 if (pq->tcp) {
11
Assuming field 'tcp' is 0
12
Taking false branch
679 if (event_initialized(&pq->ev)((&pq->ev)->ev_flags & 0x80))
680 event_del(&pq->ev);
681 if (event_initialized(&pq->resp_ev)((&pq->resp_ev)->ev_flags & 0x80))
682 event_del(&pq->resp_ev);
683 if (event_initialized(&pq->tmo_ev)((&pq->tmo_ev)->ev_flags & 0x80))
684 event_del(&pq->tmo_ev);
685 if (pq->fd != -1)
686 close(pq->fd);
687 }
688 free(pq);
13
Memory is released
689}
690
691void
692udp_receive(int fd, short events, void *arg)
693{
694 struct udp_ev *udpev = (struct udp_ev *)arg;
695 struct pending_query *pq = NULL((void*)0);
696 ssize_t len;
697
698 if ((len = recvmsg(fd, &udpev->rcvmhdr, 0)) == -1) {
699 log_warn("recvmsg")uw_log_warn("recvmsg");
700 return;
701 }
702
703 if ((pq = calloc(1, sizeof(*pq))) == NULL((void*)0)) {
704 log_warn(NULL)uw_log_warn(((void*)0));
705 return;
706 }
707
708 do {
709 arc4random_buf(&pq->imsg_id, sizeof(pq->imsg_id));
710 } while(find_pending_query(pq->imsg_id) != NULL((void*)0));
711
712 TAILQ_INSERT_TAIL(&pending_queries, pq, entry)do { (pq)->entry.tqe_next = ((void*)0); (pq)->entry.tqe_prev
= (&pending_queries)->tqh_last; *(&pending_queries
)->tqh_last = (pq); (&pending_queries)->tqh_last = &
(pq)->entry.tqe_next; } while (0)
;
713
714 pq->from = udpev->from;
715 pq->fd = fd;
716 pq->qbuf = sldns_buffer_new(len);
717 pq->abuf = sldns_buffer_new(len); /* make sure we can send errors */
718 pq->region = regional_create();
719 pq->qmsg = regional_alloc(pq->region, sizeof(*pq->qmsg));
720
721 if (!pq->qbuf || !pq->abuf || !pq->region || !pq->qmsg) {
722 log_warnx("out of memory");
723 free_pending_query(pq);
724 return;
725 }
726
727 memset(pq->qmsg, 0, sizeof(*pq->qmsg));
728 sldns_buffer_write(pq->qbuf, udpev->query, len);
729 sldns_buffer_flip(pq->qbuf);
730 handle_query(pq);
731}
732
733void
734handle_query(struct pending_query *pq)
735{
736 struct query_imsg query_imsg;
737 struct bl_node find;
738 int rcode;
739 char *str;
740 char dname[LDNS_MAX_DOMAINLEN255 + 1];
741 char qclass_buf[16];
742 char qtype_buf[16];
743
744 if (log_getverbose() & OPT_VERBOSE20x00000002 && (str =
745 sldns_wire2str_pkt(sldns_buffer_begin(pq->qbuf),
746 sldns_buffer_limit(pq->qbuf))) != NULL((void*)0)) {
747 log_debug("from: %s\n%s", ip_port((struct sockaddr *)
748 &pq->from), str);
749 free(str);
750 }
751
752 if (!query_info_parse(&pq->qinfo, pq->qbuf)) {
753 log_warnx("query_info_parse failed");
754 goto drop;
755 }
756
757 sldns_buffer_rewind(pq->qbuf);
758
759 if (parse_packet(pq->qbuf, pq->qmsg, pq->region) !=
760 LDNS_RCODE_NOERROR) {
761 log_warnx("parse_packet failed");
762 goto drop;
763 }
764
765 rcode = check_query(pq->qbuf);
766 switch (rcode) {
767 case LDNS_RCODE_NOERROR:
768 break;
769 case -1:
770 goto drop;
771 default:
772 error_answer(pq, rcode);
773 goto send_answer;
774 }
775
776 rcode = parse_extract_edns(pq->qmsg, &pq->edns, pq->region);
777 if (rcode != LDNS_RCODE_NOERROR) {
778 error_answer(pq, rcode);
779 goto send_answer;
780 }
781
782 if (!dname_valid(pq->qinfo.qname, pq->qinfo.qname_len)) {
783 error_answer(pq, LDNS_RCODE_FORMERR);
784 goto send_answer;
785 }
786 dname_str(pq->qinfo.qname, dname);
787
788 sldns_wire2str_class_buf(pq->qinfo.qclass, qclass_buf,
789 sizeof(qclass_buf));
790 sldns_wire2str_type_buf(pq->qinfo.qtype, qtype_buf, sizeof(qtype_buf));
791 log_debug("%s: %s %s %s ?", ip_port((struct sockaddr *)&pq->from),
792 dname, qclass_buf, qtype_buf);
793
794 find.domain = dname;
795 if (RB_FIND(bl_tree, &bl_head, &find)bl_tree_RB_FIND(&bl_head, &find) != NULL((void*)0)) {
796 if (frontend_conf->blocklist_log)
797 log_info("blocking %s", dname)uw_log_info("blocking %s", dname);
798 error_answer(pq, LDNS_RCODE_REFUSED);
799 goto send_answer;
800 }
801
802 if (pq->qinfo.qtype == LDNS_RR_TYPE_AXFR || pq->qinfo.qtype ==
803 LDNS_RR_TYPE_IXFR) {
804 error_answer(pq, LDNS_RCODE_REFUSED);
805 goto send_answer;
806 }
807
808 if(pq->qinfo.qtype == LDNS_RR_TYPE_OPT ||
809 pq->qinfo.qtype == LDNS_RR_TYPE_TSIG ||
810 pq->qinfo.qtype == LDNS_RR_TYPE_TKEY ||
811 pq->qinfo.qtype == LDNS_RR_TYPE_MAILA ||
812 pq->qinfo.qtype == LDNS_RR_TYPE_MAILB ||
813 (pq->qinfo.qtype >= 128 && pq->qinfo.qtype <= 248)) {
814 error_answer(pq, LDNS_RCODE_FORMERR);
815 goto send_answer;
816 }
817
818 if (pq->qinfo.qclass == LDNS_RR_CLASS_CH) {
819 if (strcasecmp(dname, "version.server.") == 0 ||
820 strcasecmp(dname, "version.bind.") == 0) {
821 chaos_answer(pq);
822 } else
823 error_answer(pq, LDNS_RCODE_REFUSED);
824 goto send_answer;
825 }
826
827 if (strlcpy(query_imsg.qname, dname, sizeof(query_imsg.qname)) >=
828 sizeof(query_imsg.qname)) {
829 log_warnx("qname too long");
830 error_answer(pq, LDNS_RCODE_FORMERR);
831 goto send_answer;
832 }
833 query_imsg.id = pq->imsg_id;
834 query_imsg.t = pq->qinfo.qtype;
835 query_imsg.c = pq->qinfo.qclass;
836
837 if (frontend_imsg_compose_resolver(IMSG_QUERY, 0, &query_imsg,
838 sizeof(query_imsg)) == -1) {
839 error_answer(pq, LDNS_RCODE_SERVFAIL);
840 goto send_answer;
841 }
842 return;
843
844 send_answer:
845 send_answer(pq);
846 return;
847
848 drop:
849 free_pending_query(pq);
850}
851
852void
853noerror_answer(struct pending_query *pq)
854{
855 struct query_info skip, qinfo;
856 struct reply_info *rinfo = NULL((void*)0);
857 struct alloc_cache alloc;
858 struct edns_data edns;
859 struct ub_packed_rrset_key *an_rrset = NULL((void*)0);
860 struct packed_rrset_data *an_rrset_data = NULL((void*)0);
861
862 alloc_init(&alloc, NULL((void*)0), 0);
863 memset(&qinfo, 0, sizeof(qinfo));
864 /* read past query section, no memory is allocated */
865 if (!query_info_parse(&skip, pq->abuf))
866 goto srvfail;
867
868 if (reply_info_parse(pq->abuf, &alloc, &qinfo, &rinfo, pq->region,
869 &edns) != 0)
870 goto srvfail;
871
872 if ((an_rrset = reply_find_answer_rrset(&qinfo, rinfo)) != NULL((void*)0))
873 an_rrset_data = (struct packed_rrset_data*)an_rrset->entry.data;
874
875 /* reply_info_parse() allocates memory */
876 query_info_clear(&qinfo);
877
878 /* XXX check that there a no AAAA records in answer section? */
879 if ((an_rrset_data == NULL((void*)0) || an_rrset_data->count == 0) &&
880 !pq->dns64_synthesize && pq->qinfo.qtype == LDNS_RR_TYPE_AAAA &&
881 pq->qinfo.qclass == LDNS_RR_CLASS_IN && dns64_prefix_count > 0) {
882 pq->dns64_synthesize = 1;
883 return;
884 }
885
886 sldns_buffer_clear(pq->abuf);
887 if (reply_info_encode(&pq->qinfo, rinfo, pq->qmsg->id, rinfo->flags,
888 pq->abuf, 0, pq->region, pq->tcp ? UINT16_MAX0xffff : pq->edns.udp_size,
889 pq->edns.bits & EDNS_DO0x8000, MINIMIZE_ANSWER1) == 0)
890 goto srvfail;
891
892 reply_info_parsedelete(rinfo, &alloc);
893 alloc_clear(&alloc);
894 return;
895
896 srvfail:
897 reply_info_parsedelete(rinfo, &alloc);
898 alloc_clear(&alloc);
899 error_answer(pq, LDNS_RCODE_SERVFAIL);
900}
901
902void
903synthesize_dns64_answer(struct pending_query *pq)
904{
905 struct query_info skip, qinfo;
906 struct reply_info *rinfo = NULL((void*)0), *synth_rinfo = NULL((void*)0);
907 struct alloc_cache alloc;
908 struct edns_data edns;
909 size_t i;
910
911 pq->dns64_synthesize = 0;
912
913 alloc_init(&alloc, NULL((void*)0), 0);
914 memset(&qinfo, 0, sizeof(qinfo));
915 /* read past query section, no memory is allocated */
916 if (!query_info_parse(&skip, pq->abuf))
917 goto srvfail;
918
919 if (reply_info_parse(pq->abuf, &alloc, &qinfo, &rinfo, pq->region,
920 &edns) != 0)
921 goto srvfail;
922
923 /* reply_info_parse() allocates memory */
924 query_info_clear(&qinfo);
925
926 synth_rinfo = construct_reply_info_base(pq->region, rinfo->flags,
927 rinfo->qdcount, rinfo->ttl, rinfo->prefetch_ttl,
928 rinfo->serve_expired_ttl, rinfo->an_numrrsets,
929 rinfo->ns_numrrsets, rinfo->ar_numrrsets, rinfo->rrset_count,
930 rinfo->security);
931
932 if (!synth_rinfo)
933 goto srvfail;
934
935 if(!reply_info_alloc_rrset_keys(synth_rinfo, NULL((void*)0), pq->region))
936 goto srvfail;
937
938 for (i = 0; i < synth_rinfo->rrset_count; i++) {
939 struct ub_packed_rrset_key *src_rrset_key, *dst_rrset_key;
940 struct packed_rrset_data *src_rrset_data;
941 struct packed_rrset_data *dst_rrset_data;
942
943 src_rrset_key = rinfo->rrsets[i];
944 src_rrset_data =
945 (struct packed_rrset_data *)src_rrset_key->entry.data;
946 dst_rrset_key = synth_rinfo->rrsets[i];
947
948 dst_rrset_key->id = src_rrset_key->id;
949 dst_rrset_key->rk = src_rrset_key->rk;
950
951 if (i < rinfo->an_numrrsets && src_rrset_key->rk.type ==
952 htons(LDNS_RR_TYPE_A)(__uint16_t)(__builtin_constant_p(LDNS_RR_TYPE_A) ? (__uint16_t
)(((__uint16_t)(LDNS_RR_TYPE_A) & 0xffU) << 8 | ((__uint16_t
)(LDNS_RR_TYPE_A) & 0xff00U) >> 8) : __swap16md(LDNS_RR_TYPE_A
))
) {
953 dns64_synth_aaaa_data(src_rrset_key, src_rrset_data,
954 dst_rrset_key, &dst_rrset_data, pq->region);
955 if (dst_rrset_data == NULL((void*)0))
956 goto srvfail;
957 } else {
958 dst_rrset_key->entry.hash = src_rrset_key->entry.hash;
959 dst_rrset_key->rk.dname = regional_alloc_init(
960 pq->region, src_rrset_key->rk.dname,
961 src_rrset_key->rk.dname_len);
962 if (dst_rrset_key->rk.dname == NULL((void*)0))
963 goto srvfail;
964
965 dst_rrset_data = regional_alloc_init(pq->region,
966 src_rrset_data,
967 packed_rrset_sizeof(src_rrset_data));
968 if (dst_rrset_data == NULL((void*)0))
969 goto srvfail;
970 }
971
972 packed_rrset_ptr_fixup(dst_rrset_data);
973 dst_rrset_key->entry.data = dst_rrset_data;
974 }
975
976 if (!sldns_buffer_set_capacity(pq->abuf, pq->tcp ? UINT16_MAX0xffff :
977 pq->edns.udp_size))
978 goto srvfail;
979
980 sldns_buffer_clear(pq->abuf);
981
982 if (reply_info_encode(&pq->qinfo, synth_rinfo, pq->qmsg->id,
983 synth_rinfo->flags, pq->abuf, 0, pq->region,
984 pq->tcp ? UINT16_MAX0xffff : pq->edns.udp_size,
985 pq->edns.bits & EDNS_DO0x8000, MINIMIZE_ANSWER1) == 0)
986 goto srvfail;
987
988 reply_info_parsedelete(rinfo, &alloc);
989 alloc_clear(&alloc);
990 return;
991
992 srvfail:
993 reply_info_parsedelete(rinfo, &alloc);
994 alloc_clear(&alloc);
995 error_answer(pq, LDNS_RCODE_SERVFAIL);
996}
997
998void
999resend_dns64_query(struct pending_query *opq) {
1000 struct pending_query *pq;
1001 struct query_imsg query_imsg;
1002 int rcode;
1003 char dname[LDNS_MAX_DOMAINLEN255 + 1];
1004
1005 if ((pq = calloc(1, sizeof(*pq))) == NULL((void*)0)) {
1006 log_warn(NULL)uw_log_warn(((void*)0));
1007 return;
1008 }
1009
1010 do {
1011 arc4random_buf(&pq->imsg_id, sizeof(pq->imsg_id));
1012 } while(find_pending_query(pq->imsg_id) != NULL((void*)0));
1013
1014 TAILQ_INSERT_TAIL(&pending_queries, pq, entry)do { (pq)->entry.tqe_next = ((void*)0); (pq)->entry.tqe_prev
= (&pending_queries)->tqh_last; *(&pending_queries
)->tqh_last = (pq); (&pending_queries)->tqh_last = &
(pq)->entry.tqe_next; } while (0)
;
1015
1016 pq->from = opq->from;
1017 pq->fd = opq->fd;
1018 opq->fd = -1;
1019 pq->tcp = opq->tcp;
1020 pq->qbuf = sldns_buffer_new(sldns_buffer_capacity(opq->qbuf));
1021 pq->abuf = sldns_buffer_new(sldns_buffer_capacity(opq->abuf));
1022 pq->region = regional_create();
1023 pq->qmsg = regional_alloc(pq->region, sizeof(*pq->qmsg));
1024
1025 if (!pq->qbuf || !pq->abuf || !pq->region || !pq->qmsg) {
1026 log_warnx("out of memory");
1027 free_pending_query(pq);
1028 free_pending_query(opq);
1029 return;
1030 }
1031
1032 sldns_buffer_rewind(opq->qbuf);
1033 sldns_buffer_write(pq->qbuf, sldns_buffer_current(opq->qbuf),
1034 sldns_buffer_remaining(opq->qbuf));
1035 sldns_buffer_flip(pq->qbuf);
1036 memset(pq->qmsg, 0, sizeof(*pq->qmsg));
1037
1038 if (pq->tcp) {
1039 struct timeval timeout = {TCP_TIMEOUT15, 0};
1040
1041 event_set(&pq->ev, pq->fd, EV_READ0x02 | EV_PERSIST0x10, tcp_request,
1042 pq);
1043 event_set(&pq->resp_ev, pq->fd, EV_WRITE0x04 | EV_PERSIST0x10,
1044 tcp_response, pq);
1045 evtimer_set(&pq->tmo_ev, tcp_timeout, pq)event_set(&pq->tmo_ev, -1, 0, tcp_timeout, pq);
1046 evtimer_add(&pq->tmo_ev, &timeout)event_add(&pq->tmo_ev, &timeout);
1047 }
1048
1049 if (!query_info_parse(&pq->qinfo, pq->qbuf)) {
1050 log_warnx("query_info_parse failed");
1051 goto drop;
1052 }
1053
1054 sldns_buffer_rewind(pq->qbuf);
1055
1056 if (parse_packet(pq->qbuf, pq->qmsg, pq->region) !=
1057 LDNS_RCODE_NOERROR) {
1058 log_warnx("parse_packet failed");
1059 goto drop;
1060 }
1061
1062 rcode = parse_extract_edns(pq->qmsg, &pq->edns, pq->region);
1063 if (rcode != LDNS_RCODE_NOERROR) {
1064 error_answer(pq, rcode);
1065 goto send_answer;
1066 }
1067
1068 dname_str(pq->qinfo.qname, dname);
1069 strlcpy(query_imsg.qname, dname, sizeof(query_imsg.qname));
1070 query_imsg.id = pq->imsg_id;
1071 query_imsg.t = LDNS_RR_TYPE_A;
1072 query_imsg.c = pq->qinfo.qclass;
1073
1074 pq->dns64_synthesize = 1;
1075
1076 if (frontend_imsg_compose_resolver(IMSG_QUERY, 0, &query_imsg,
1077 sizeof(query_imsg)) == -1) {
1078 error_answer(pq, LDNS_RCODE_SERVFAIL);
1079 goto send_answer;
1080 }
1081
1082 free_pending_query(opq);
1083 return;
1084
1085 send_answer:
1086 free_pending_query(opq);
1087 send_answer(pq);
1088 return;
1089
1090 drop:
1091 free_pending_query(opq);
1092 free_pending_query(pq);
1093}
1094
1095void
1096chaos_answer(struct pending_query *pq)
1097{
1098 size_t len;
1099 const char *name = "unwind";
1100
1101 len = strlen(name);
1102 if (!sldns_buffer_set_capacity(pq->abuf,
1103 sldns_buffer_capacity(pq->qbuf) + COMPRESSED_RR_SIZE12 + 1 + len)) {
1104 error_answer(pq, LDNS_RCODE_SERVFAIL);
1105 return;
1106 }
1107
1108 sldns_buffer_copy(pq->abuf, pq->qbuf);
1109
1110 sldns_buffer_clear(pq->abuf);
1111
1112 sldns_buffer_skip(pq->abuf, sizeof(uint16_t)); /* skip id */
1113 sldns_buffer_write_u16(pq->abuf, 0); /* clear flags */
1114 LDNS_QR_SET(sldns_buffer_begin(pq->abuf))(*(sldns_buffer_begin(pq->abuf)+2) |= 0x80U);
1115 LDNS_RA_SET(sldns_buffer_begin(pq->abuf))(*(sldns_buffer_begin(pq->abuf)+3) |= 0x80U);
1116 if (LDNS_RD_WIRE(sldns_buffer_begin(pq->qbuf))(*(sldns_buffer_begin(pq->qbuf)+2) & 0x01U))
1117 LDNS_RD_SET(sldns_buffer_begin(pq->abuf))(*(sldns_buffer_begin(pq->abuf)+2) |= 0x01U);
1118 if (LDNS_CD_WIRE(sldns_buffer_begin(pq->qbuf))(*(sldns_buffer_begin(pq->qbuf)+3) & 0x10U))
1119 LDNS_CD_SET(sldns_buffer_begin(pq->abuf))(*(sldns_buffer_begin(pq->abuf)+3) |= 0x10U);
1120 LDNS_RCODE_SET(sldns_buffer_begin(pq->abuf), LDNS_RCODE_NOERROR)(*(sldns_buffer_begin(pq->abuf)+3) = ((*(sldns_buffer_begin
(pq->abuf)+3)) & ~0x0fU) | (LDNS_RCODE_NOERROR))
;
1121 sldns_buffer_write_u16(pq->abuf, 1); /* qdcount */
1122 sldns_buffer_write_u16(pq->abuf, 1); /* ancount */
1123 sldns_buffer_write_u16(pq->abuf, 0); /* nscount */
1124 sldns_buffer_write_u16(pq->abuf, 0); /* arcount */
1125 (void)query_dname_len(pq->abuf); /* skip qname */
1126 sldns_buffer_skip(pq->abuf, sizeof(uint16_t)); /* skip qtype */
1127 sldns_buffer_skip(pq->abuf, sizeof(uint16_t)); /* skip qclass */
1128
1129 sldns_buffer_write_u16(pq->abuf, 0xc00c); /* ptr to query */
1130 sldns_buffer_write_u16(pq->abuf, LDNS_RR_TYPE_TXT);
1131 sldns_buffer_write_u16(pq->abuf, LDNS_RR_CLASS_CH);
1132 sldns_buffer_write_u32(pq->abuf, 0); /* TTL */
1133 sldns_buffer_write_u16(pq->abuf, 1 + len); /* RDLENGTH */
1134 sldns_buffer_write_u8(pq->abuf, len); /* length octed */
1135 sldns_buffer_write(pq->abuf, name, len);
1136 sldns_buffer_flip(pq->abuf);
1137}
1138
1139void
1140error_answer(struct pending_query *pq, int rcode)
1141{
1142 sldns_buffer_clear(pq->abuf);
1143 error_encode(pq->abuf, rcode, &pq->qinfo, pq->qmsg->id,
1144 pq->qmsg->flags, pq->edns.edns_present ? &pq->edns : NULL((void*)0));
1145}
1146
1147int
1148check_query(sldns_buffer* pkt)
1149{
1150 if(sldns_buffer_limit(pkt) < LDNS_HEADER_SIZE12) {
1151 log_warnx("bad query: too short, dropped");
1152 return -1;
1153 }
1154 if(LDNS_QR_WIRE(sldns_buffer_begin(pkt))(*(sldns_buffer_begin(pkt)+2) & 0x80U)) {
1155 log_warnx("bad query: QR set, dropped");
1156 return -1;
1157 }
1158 if(LDNS_TC_WIRE(sldns_buffer_begin(pkt))(*(sldns_buffer_begin(pkt)+2) & 0x02U)) {
1159 LDNS_TC_CLR(sldns_buffer_begin(pkt))(*(sldns_buffer_begin(pkt)+2) &= ~0x02U);
1160 log_warnx("bad query: TC set");
1161 return (LDNS_RCODE_FORMERR);
1162 }
1163 if(!(LDNS_RD_WIRE(sldns_buffer_begin(pkt))(*(sldns_buffer_begin(pkt)+2) & 0x01U))) {
1164 log_warnx("bad query: RD not set");
1165 return (LDNS_RCODE_REFUSED);
1166 }
1167 if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt))((*(sldns_buffer_begin(pkt)+2) & 0x78U) >> 3) != LDNS_PACKET_QUERY) {
1168 log_warnx("bad query: unknown opcode %d",
1169 LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt))((*(sldns_buffer_begin(pkt)+2) & 0x78U) >> 3));
1170 return (LDNS_RCODE_NOTIMPL);
1171 }
1172
1173 if (LDNS_QDCOUNT(sldns_buffer_begin(pkt))(sldns_read_uint16(sldns_buffer_begin(pkt)+4)) != 1 &&
1174 LDNS_ANCOUNT(sldns_buffer_begin(pkt))(sldns_read_uint16(sldns_buffer_begin(pkt)+6))!= 0 &&
1175 LDNS_NSCOUNT(sldns_buffer_begin(pkt))(sldns_read_uint16(sldns_buffer_begin(pkt)+8))!= 0 &&
1176 LDNS_ARCOUNT(sldns_buffer_begin(pkt))(sldns_read_uint16(sldns_buffer_begin(pkt)+10)) > 1) {
1177 log_warnx("bad query: qdcount: %d, ancount: %d "
1178 "nscount: %d, arcount: %d",
1179 LDNS_QDCOUNT(sldns_buffer_begin(pkt))(sldns_read_uint16(sldns_buffer_begin(pkt)+4)),
1180 LDNS_ANCOUNT(sldns_buffer_begin(pkt))(sldns_read_uint16(sldns_buffer_begin(pkt)+6)),
1181 LDNS_NSCOUNT(sldns_buffer_begin(pkt))(sldns_read_uint16(sldns_buffer_begin(pkt)+8)),
1182 LDNS_ARCOUNT(sldns_buffer_begin(pkt))(sldns_read_uint16(sldns_buffer_begin(pkt)+10)));
1183 return (LDNS_RCODE_FORMERR);
1184 }
1185 return 0;
1186}
1187
1188void
1189send_answer(struct pending_query *pq)
1190{
1191 char *str;
1192
1193 if (log_getverbose() & OPT_VERBOSE20x00000002 && (str =
1194 sldns_wire2str_pkt(sldns_buffer_begin(pq->abuf),
1195 sldns_buffer_limit(pq->abuf))) != NULL((void*)0)) {
1196 log_debug("from: %s\n%s", ip_port((struct sockaddr *)
1197 &pq->from), str);
1198 free(str);
1199 }
1200
1201 if (!pq->tcp) {
1202 if(sendto(pq->fd, sldns_buffer_current(pq->abuf),
1203 sldns_buffer_remaining(pq->abuf), 0,
1204 (struct sockaddr *)&pq->from, pq->from.ss_len) == -1)
1205 log_warn("sendto")uw_log_warn("sendto");
1206 free_pending_query(pq);
1207 } else {
1208 struct sldns_buffer *tmp;
1209
1210 tmp = sldns_buffer_new(sldns_buffer_limit(pq->abuf) + 2);
1211
1212 if (!tmp) {
1213 free_pending_query(pq);
1214 return;
1215 }
1216
1217 sldns_buffer_write_u16(tmp, sldns_buffer_limit(pq->abuf));
1218 sldns_buffer_write(tmp, sldns_buffer_current(pq->abuf),
1219 sldns_buffer_remaining(pq->abuf));
1220 sldns_buffer_flip(tmp);
1221 sldns_buffer_free(pq->abuf);
1222 pq->abuf = tmp;
1223 event_add(&pq->resp_ev, NULL((void*)0));
1224 }
1225}
1226
1227char*
1228ip_port(struct sockaddr *sa)
1229{
1230 static char hbuf[NI_MAXHOST256], buf[NI_MAXHOST256];
1231
1232 if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL((void*)0), 0,
1233 NI_NUMERICHOST1) != 0) {
1234 snprintf(buf, sizeof(buf), "%s", "(unknown)");
1235 return buf;
1236 }
1237
1238 if (sa->sa_family == AF_INET624)
1239 snprintf(buf, sizeof(buf), "[%s]:%d", hbuf, ntohs((__uint16_t)(__builtin_constant_p(((struct sockaddr_in6 *)sa)
->sin6_port) ? (__uint16_t)(((__uint16_t)(((struct sockaddr_in6
*)sa)->sin6_port) & 0xffU) << 8 | ((__uint16_t)
(((struct sockaddr_in6 *)sa)->sin6_port) & 0xff00U) >>
8) : __swap16md(((struct sockaddr_in6 *)sa)->sin6_port))
1240 ((struct sockaddr_in6 *)sa)->sin6_port)(__uint16_t)(__builtin_constant_p(((struct sockaddr_in6 *)sa)
->sin6_port) ? (__uint16_t)(((__uint16_t)(((struct sockaddr_in6
*)sa)->sin6_port) & 0xffU) << 8 | ((__uint16_t)
(((struct sockaddr_in6 *)sa)->sin6_port) & 0xff00U) >>
8) : __swap16md(((struct sockaddr_in6 *)sa)->sin6_port))
);
1241 if (sa->sa_family == AF_INET2)
1242 snprintf(buf, sizeof(buf), "[%s]:%d", hbuf, ntohs((__uint16_t)(__builtin_constant_p(((struct sockaddr_in *)sa)->
sin_port) ? (__uint16_t)(((__uint16_t)(((struct sockaddr_in *
)sa)->sin_port) & 0xffU) << 8 | ((__uint16_t)(((
struct sockaddr_in *)sa)->sin_port) & 0xff00U) >>
8) : __swap16md(((struct sockaddr_in *)sa)->sin_port))
1243 ((struct sockaddr_in *)sa)->sin_port)(__uint16_t)(__builtin_constant_p(((struct sockaddr_in *)sa)->
sin_port) ? (__uint16_t)(((__uint16_t)(((struct sockaddr_in *
)sa)->sin_port) & 0xffU) << 8 | ((__uint16_t)(((
struct sockaddr_in *)sa)->sin_port) & 0xff00U) >>
8) : __swap16md(((struct sockaddr_in *)sa)->sin_port))
);
1244
1245 return buf;
1246}
1247
1248struct pending_query*
1249find_pending_query(uint64_t id)
1250{
1251 struct pending_query *pq;
1252
1253 TAILQ_FOREACH(pq, &pending_queries, entry)for((pq) = ((&pending_queries)->tqh_first); (pq) != ((
void*)0); (pq) = ((pq)->entry.tqe_next))
1254 if (pq->imsg_id == id)
1255 return pq;
1256 return NULL((void*)0);
1257}
1258
1259void
1260route_receive(int fd, short events, void *arg)
1261{
1262 static uint8_t *buf;
1263
1264 struct rt_msghdr *rtm;
1265 struct sockaddr *sa, *rti_info[RTAX_MAX15];
1266 ssize_t n;
1267
1268 if (buf == NULL((void*)0)) {
1269 buf = malloc(ROUTE_SOCKET_BUF_SIZE16384);
1270 if (buf == NULL((void*)0))
1271 fatal("malloc");
1272 }
1273 rtm = (struct rt_msghdr *)buf;
1274 if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE16384)) == -1) {
1275 if (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)
1276 return;
1277 log_warn("dispatch_rtmsg: read error")uw_log_warn("dispatch_rtmsg: read error");
1278 return;
1279 }
1280
1281 if (n == 0)
1282 fatal("routing socket closed");
1283
1284 if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) {
1285 log_warnx("partial rtm of %zd in buffer", n);
1286 return;
1287 }
1288
1289 if (rtm->rtm_version != RTM_VERSION5)
1290 return;
1291
1292 sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen);
1293 get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
1294
1295 handle_route_message(rtm, rti_info);
1296}
1297
1298#define ROUNDUP(a)((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof
(long))
\
1299 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
1300
1301void
1302get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
1303{
1304 int i;
1305
1306 for (i = 0; i < RTAX_MAX15; i++) {
1307 if (addrs & (1 << i)) {
1308 rti_info[i] = sa;
1309 sa = (struct sockaddr *)((char *)(sa) +
1310 ROUNDUP(sa->sa_len)((sa->sa_len) > 0 ? (1 + (((sa->sa_len) - 1) | (sizeof
(long) - 1))) : sizeof(long))
);
1311 } else
1312 rti_info[i] = NULL((void*)0);
1313 }
1314}
1315
1316void
1317handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info)
1318{
1319 struct imsg_rdns_proposal rdns_proposal;
1320 struct sockaddr_rtdns *rtdns;
1321 struct if_announcemsghdr *ifan;
1322
1323 switch (rtm->rtm_type) {
1324 case RTM_IFANNOUNCE0xf:
1325 ifan = (struct if_announcemsghdr *)rtm;
1326 if (ifan->ifan_what == IFAN_ARRIVAL0)
1327 break;
1328 rdns_proposal.if_index = ifan->ifan_index;
1329 rdns_proposal.src = 0;
1330 rdns_proposal.rtdns.sr_family = AF_INET2;
1331 rdns_proposal.rtdns.sr_len = offsetof(struct sockaddr_rtdns,__builtin_offsetof(struct sockaddr_rtdns, sr_dns)
1332 sr_dns)__builtin_offsetof(struct sockaddr_rtdns, sr_dns);
1333 frontend_imsg_compose_resolver(IMSG_REPLACE_DNS, 0,
1334 &rdns_proposal, sizeof(rdns_proposal));
1335 break;
1336 case RTM_IFINFO0xe:
1337 frontend_imsg_compose_resolver(IMSG_NETWORK_CHANGED, 0, NULL((void*)0),
1338 0);
1339 break;
1340 case RTM_PROPOSAL0x13:
1341 if (!(rtm->rtm_addrs & RTA_DNS0x1000))
1342 break;
1343
1344 rtdns = (struct sockaddr_rtdns*)rti_info[RTAX_DNS12];
1345 rdns_proposal.if_index = rtm->rtm_index;
1346 rdns_proposal.src = rtm->rtm_priority;
1347 memcpy(&rdns_proposal.rtdns, rtdns, sizeof(rdns_proposal.rtdns));
1348 frontend_imsg_compose_resolver(IMSG_REPLACE_DNS, 0,
1349 &rdns_proposal, sizeof(rdns_proposal));
1350 break;
1351 case RTM_NEWADDR0xc:
1352 case RTM_DELADDR0xd:
1353 case RTM_DESYNC0x10:
1354 check_available_af();
1355 break;
1356 default:
1357 break;
1358 }
1359}
1360
1361void
1362add_new_ta(struct trust_anchor_head *tah, char *val)
1363{
1364 struct trust_anchor *ta, *i;
1365 int cmp;
1366
1367 if ((ta = malloc(sizeof(*ta))) == NULL((void*)0))
1368 fatal("%s", __func__);
1369 if ((ta->ta = strdup(val)) == NULL((void*)0))
1370 fatal("%s", __func__);
1371
1372 /* keep the list sorted to prevent churn if the order changes in DNS */
1373 TAILQ_FOREACH(i, tah, entry)for((i) = ((tah)->tqh_first); (i) != ((void*)0); (i) = ((i
)->entry.tqe_next))
{
1374 cmp = strcmp(i->ta, ta->ta);
1375 if ( cmp == 0) {
1376 /* duplicate */
1377 free(ta->ta);
1378 free(ta);
1379 return;
1380 } else if (cmp > 0) {
1381 TAILQ_INSERT_BEFORE(i, ta, entry)do { (ta)->entry.tqe_prev = (i)->entry.tqe_prev; (ta)->
entry.tqe_next = (i); *(i)->entry.tqe_prev = (ta); (i)->
entry.tqe_prev = &(ta)->entry.tqe_next; } while (0)
;
1382 return;
1383 }
1384 }
1385 TAILQ_INSERT_TAIL(tah, ta, entry)do { (ta)->entry.tqe_next = ((void*)0); (ta)->entry.tqe_prev
= (tah)->tqh_last; *(tah)->tqh_last = (ta); (tah)->
tqh_last = &(ta)->entry.tqe_next; } while (0)
;
1386}
1387
1388void
1389free_tas(struct trust_anchor_head *tah)
1390{
1391 struct trust_anchor *ta;
1392
1393 while ((ta = TAILQ_FIRST(tah)((tah)->tqh_first))) {
1394 TAILQ_REMOVE(tah, ta, entry)do { if (((ta)->entry.tqe_next) != ((void*)0)) (ta)->entry
.tqe_next->entry.tqe_prev = (ta)->entry.tqe_prev; else (
tah)->tqh_last = (ta)->entry.tqe_prev; *(ta)->entry.
tqe_prev = (ta)->entry.tqe_next; ; ; } while (0)
;
1395 free(ta->ta);
1396 free(ta);
1397 }
1398}
1399
1400int
1401merge_tas(struct trust_anchor_head *newh, struct trust_anchor_head *oldh)
1402{
1403 struct trust_anchor *i, *j;
1404 int chg = 0;
1405
1406 j = TAILQ_FIRST(oldh)((oldh)->tqh_first);
1407
1408 TAILQ_FOREACH(i, newh, entry)for((i) = ((newh)->tqh_first); (i) != ((void*)0); (i) = ((
i)->entry.tqe_next))
{
1409 if (j == NULL((void*)0) || strcmp(i->ta, j->ta) != 0) {
1410 chg = 1;
1411 break;
1412 }
1413 j = TAILQ_NEXT(j, entry)((j)->entry.tqe_next);
1414 }
1415 if (j != NULL((void*)0))
1416 chg = 1;
1417
1418 if (chg) {
1419 free_tas(oldh);
1420 TAILQ_CONCAT(oldh, newh, entry)do { if (!(((newh)->tqh_first) == ((void*)0))) { *(oldh)->
tqh_last = (newh)->tqh_first; (newh)->tqh_first->entry
.tqe_prev = (oldh)->tqh_last; (oldh)->tqh_last = (newh)
->tqh_last; do { ((newh))->tqh_first = ((void*)0); ((newh
))->tqh_last = &((newh))->tqh_first; } while (0); }
} while (0)
;
1421 } else {
1422 free_tas(newh);
1423 }
1424 return (chg);
1425}
1426
1427void
1428parse_trust_anchor(struct trust_anchor_head *tah, int fd)
1429{
1430 size_t len, dname_len;
1431 ssize_t n, sz;
1432 uint8_t rr[LDNS_RR_BUF_SIZE65535];
1433 char *str, *p, buf[512], *line;
1434
1435 sz = 0;
1436 str = NULL((void*)0);
1437
1438 while ((n = read(fd, buf, sizeof(buf))) > 0) {
1439 p = recallocarray(str, sz, sz + n, 1);
1440 if (p == NULL((void*)0)) {
1441 log_warn("%s", __func__)uw_log_warn("%s", __func__);
1442 goto out;
1443 }
1444 str = p;
1445 memcpy(str + sz, buf, n);
1446 sz += n;
1447 }
1448
1449 if (n == -1) {
1450 log_warn("%s", __func__)uw_log_warn("%s", __func__);
1451 goto out;
1452 }
1453
1454 /* make it a string */
1455 p = recallocarray(str, sz, sz + 1, 1);
1456 if (p == NULL((void*)0)) {
1457 log_warn("%s", __func__)uw_log_warn("%s", __func__);
1458 goto out;
1459 }
1460 str = p;
1461 sz++;
1462
1463 len = sizeof(rr);
1464
1465 while ((line = strsep(&p, "\n")) != NULL((void*)0)) {
1466 if (sldns_str2wire_rr_buf(line, rr, &len, &dname_len,
1467 ROOT_DNSKEY_TTL172800, NULL((void*)0), 0, NULL((void*)0), 0) != 0)
1468 continue;
1469 if (sldns_wirerr_get_type(rr, len, dname_len) ==
1470 LDNS_RR_TYPE_DNSKEY)
1471 add_new_ta(tah, line);
1472 }
1473
1474out:
1475 free(str);
1476 return;
1477}
1478
1479void
1480send_trust_anchors(struct trust_anchor_head *tah)
1481{
1482 struct trust_anchor *ta;
1483
1484 TAILQ_FOREACH(ta, tah, entry)for((ta) = ((tah)->tqh_first); (ta) != ((void*)0); (ta) = (
(ta)->entry.tqe_next))
1485 frontend_imsg_compose_resolver(IMSG_NEW_TA, 0, ta->ta,
1486 strlen(ta->ta) + 1);
1487 frontend_imsg_compose_resolver(IMSG_NEW_TAS_DONE, 0, NULL((void*)0), 0);
1488}
1489
1490void
1491write_trust_anchors(struct trust_anchor_head *tah, int fd)
1492{
1493 struct trust_anchor *ta;
1494 size_t len = 0;
1495 ssize_t n;
1496 char *str;
1497
1498 if (lseek(fd, 0, SEEK_SET0) == -1) {
1499 log_warn("%s", __func__)uw_log_warn("%s", __func__);
1500 goto out;
1501 }
1502
1503 TAILQ_FOREACH(ta, tah, entry)for((ta) = ((tah)->tqh_first); (ta) != ((void*)0); (ta) = (
(ta)->entry.tqe_next))
{
1504 if ((n = asprintf(&str, "%s\n", ta->ta)) == -1) {
1505 log_warn("%s", __func__)uw_log_warn("%s", __func__);
1506 len = 0;
1507 goto out;
1508 }
1509 len += n;
1510 if (write(fd, str, n) != n) {
1511 log_warn("%s", __func__)uw_log_warn("%s", __func__);
1512 free(str);
1513 len = 0;
1514 goto out;
1515 }
1516 free(str);
1517 }
1518out:
1519 ftruncate(fd, len);
1520 fsync(fd);
1521}
1522
1523void
1524parse_blocklist(int fd)
1525{
1526 FILE *f;
1527 struct bl_node *bl_node;
1528 char *line = NULL((void*)0);
1529 size_t linesize = 0;
1530 ssize_t linelen;
1531
1532 if((f = fdopen(fd, "r")) == NULL((void*)0)) {
1533 log_warn("cannot read block list")uw_log_warn("cannot read block list");
1534 close(fd);
1535 return;
1536 }
1537
1538 free_bl();
1539
1540 while ((linelen = getline(&line, &linesize, f)) != -1) {
1541 if (line[linelen - 1] == '\n') {
1542 if (linelen >= 2 && line[linelen - 2] != '.')
1543 line[linelen - 1] = '.';
1544 else
1545 line[linelen - 1] = '\0';
1546 }
1547
1548 bl_node = malloc(sizeof *bl_node);
1549 if (bl_node == NULL((void*)0))
1550 fatal("%s: malloc", __func__);
1551 if ((bl_node->domain = strdup(line)) == NULL((void*)0))
1552 fatal("%s: strdup", __func__);
1553 if (RB_INSERT(bl_tree, &bl_head, bl_node)bl_tree_RB_INSERT(&bl_head, bl_node) != NULL((void*)0)) {
1554 log_warnx("duplicate blocked domain \"%s\"", line);
1555 free(bl_node->domain);
1556 free(bl_node);
1557 }
1558 }
1559 free(line);
1560 if (ferror(f)(!__isthreaded ? (((f)->_flags & 0x0040) != 0) : (ferror
)(f))
)
1561 log_warn("getline")uw_log_warn("getline");
1562 fclose(f);
1563}
1564
1565int
1566bl_cmp(struct bl_node *e1, struct bl_node *e2) {
1567 return (strcasecmp(e1->domain, e2->domain));
1568}
1569
1570void
1571free_bl(void)
1572{
1573 struct bl_node *n, *nxt;
1574
1575 RB_FOREACH_SAFE(n, bl_tree, &bl_head, nxt)for ((n) = bl_tree_RB_MINMAX(&bl_head, -1); ((n) != ((void
*)0)) && ((nxt) = bl_tree_RB_NEXT(n), 1); (n) = (nxt)
)
{
1576 RB_REMOVE(bl_tree, &bl_head, n)bl_tree_RB_REMOVE(&bl_head, n);
1577 free(n->domain);
1578 free(n);
1579 }
1580}
1581
1582int
1583pending_query_cnt(void)
1584{
1585 struct pending_query *e;
1586 int cnt = 0;
1587
1588 TAILQ_FOREACH(e, &pending_queries, entry)for((e) = ((&pending_queries)->tqh_first); (e) != ((void
*)0); (e) = ((e)->entry.tqe_next))
1589 cnt++;
1590 return cnt;
1591}
1592
1593void
1594accept_paused(int fd, short events, void *arg)
1595{
1596 struct tcp_accept_ev *tcpev = arg;
1597 event_add(&tcpev->ev, NULL((void*)0));
1598}
1599
1600int
1601accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
1602{
1603 if (getdtablecount() + FD_RESERVE5 >= getdtablesize()) {
1604 log_debug("%s: inflight fds exceeded", __func__);
1605 errno(*__errno()) = EMFILE24;
1606 return -1;
1607 }
1608 return accept4(sockfd, addr, addrlen, SOCK_NONBLOCK0x4000 | SOCK_CLOEXEC0x8000);
1609}
1610
1611void
1612tcp_accept(int fd, short events, void *arg)
1613{
1614 static struct timeval timeout = {TCP_TIMEOUT15, 0};
1615 static struct timeval backoff = {1, 0};
1616 struct pending_query *pq;
1617 struct tcp_accept_ev *tcpev;
1618 struct sockaddr_storage ss;
1619 socklen_t len;
1620 int s;
1621
1622 tcpev = arg;
1623 len = sizeof(ss);
1624
1625 if ((s = accept_reserve(fd, (struct sockaddr *)&ss, &len)) == -1) {
1626 switch (errno(*__errno())) {
1627 case EINTR4:
1628 case EWOULDBLOCK35:
1629 case ECONNABORTED53:
1630 return;
1631 case EMFILE24:
1632 case ENFILE23:
1633 event_del(&tcpev->ev);
1634 evtimer_add(&tcpev->pause, &backoff)event_add(&tcpev->pause, &backoff);
1635 return;
1636 default:
1637 fatal("accept");
1638 }
1639 }
1640
1641 if ((pq = calloc(1, sizeof(*pq))) == NULL((void*)0)) {
1642 log_warn(NULL)uw_log_warn(((void*)0));
1643 close(s);
1644 return;
1645 }
1646
1647 do {
1648 arc4random_buf(&pq->imsg_id, sizeof(pq->imsg_id));
1649 } while(find_pending_query(pq->imsg_id) != NULL((void*)0));
1650
1651 TAILQ_INSERT_TAIL(&pending_queries, pq, entry)do { (pq)->entry.tqe_next = ((void*)0); (pq)->entry.tqe_prev
= (&pending_queries)->tqh_last; *(&pending_queries
)->tqh_last = (pq); (&pending_queries)->tqh_last = &
(pq)->entry.tqe_next; } while (0)
;
1652
1653 pq->from = ss;
1654 pq->fd = s;
1655 pq->tcp = 1;
1656 pq->qbuf = sldns_buffer_new(DEFAULT_TCP_SIZE512);
1657 pq->region = regional_create();
1658 pq->qmsg = regional_alloc(pq->region, sizeof(*pq->qmsg));
1659
1660 if (!pq->qbuf || !pq->region || !pq->qmsg) {
1661 free_pending_query(pq);
1662 return;
1663 }
1664
1665 memset(pq->qmsg, 0, sizeof(*pq->qmsg));
1666
1667 event_set(&pq->ev, s, EV_READ0x02 | EV_PERSIST0x10, tcp_request, pq);
1668 event_add(&pq->ev, NULL((void*)0));
1669 event_set(&pq->resp_ev, s, EV_WRITE0x04 | EV_PERSIST0x10, tcp_response, pq);
1670
1671 evtimer_set(&pq->tmo_ev, tcp_timeout, pq)event_set(&pq->tmo_ev, -1, 0, tcp_timeout, pq);
1672 evtimer_add(&pq->tmo_ev, &timeout)event_add(&pq->tmo_ev, &timeout);
1673}
1674
1675void
1676tcp_request(int fd, short events, void *arg)
1677{
1678 struct pending_query *pq;
1679 ssize_t n;
1680
1681 pq = arg;
1682
1683 n = read(fd, sldns_buffer_current(pq->qbuf),
1684 sldns_buffer_remaining(pq->qbuf));
1685
1686 switch (n) {
1687 case -1:
1688 switch (errno(*__errno())) {
1689 case EINTR4:
1690 case EAGAIN35:
1691 return;
1692 default:
1693 goto fail;
1694 }
1695 break;
1696 case 0:
1697 log_debug("closed connection");
1698 goto fail;
1699 default:
1700 break;
1701 }
1702
1703 sldns_buffer_skip(pq->qbuf, n);
1704
1705 if (sldns_buffer_position(pq->qbuf) >= 2 && !pq->abuf) {
1706 struct sldns_buffer *tmp;
1707 uint16_t len;
1708
1709 sldns_buffer_flip(pq->qbuf);
1710 len = sldns_buffer_read_u16(pq->qbuf);
1711 tmp = sldns_buffer_new(len);
1712 pq->abuf = sldns_buffer_new(len);
1713
1714 if (!tmp || !pq->abuf)
1715 goto fail;
1716
1717 sldns_buffer_write(tmp, sldns_buffer_current(pq->qbuf),
1718 sldns_buffer_remaining(pq->qbuf));
1719 sldns_buffer_free(pq->qbuf);
1720 pq->qbuf = tmp;
1721 }
1722 if (sldns_buffer_remaining(pq->qbuf) == 0) {
1723 sldns_buffer_flip(pq->qbuf);
1724 shutdown(fd, SHUT_RD0);
1725 event_del(&pq->ev);
1726 handle_query(pq);
1727 }
1728 return;
1729fail:
1730 free_pending_query(pq);
1731}
1732
1733void
1734tcp_response(int fd, short events, void *arg)
1735{
1736 struct pending_query *pq;
1737 ssize_t n;
1738
1739 pq = arg;
1740
1741 n = write(fd, sldns_buffer_current(pq->abuf),
1742 sldns_buffer_remaining(pq->abuf));
1743
1744 if (n == -1) {
1
Assuming the condition is true
2
Taking true branch
1745 if (errno(*__errno()) == EAGAIN35 || errno(*__errno()) == EINTR4)
3
Assuming the condition is false
4
Assuming the condition is false
5
Taking false branch
1746 return;
1747 free_pending_query(pq);
6
Calling 'free_pending_query'
14
Returning; memory was released via 1st parameter
1748 }
1749 sldns_buffer_skip(pq->abuf, n);
15
Use of memory after it is freed
1750 if (sldns_buffer_remaining(pq->abuf) == 0)
1751 free_pending_query(pq);
1752}
1753
1754void
1755tcp_timeout(int fd, short events, void *arg)
1756{
1757 free_pending_query(arg);
1758}
1759
1760void
1761check_available_af()
1762{
1763 static int available_af = HAVE_IPV41 | HAVE_IPV62;
1764 static int rtable = -1;
1765 struct ifaddrs *ifap, *ifa;
1766 struct if_data *ifa_data;
1767 struct sockaddr_in *sin4;
1768 struct sockaddr_in6 *sin6;
1769 int new_available_af = 0, ifa_rtable = -1;
1770
1771 if (rtable == -1)
1772 rtable = getrtable();
1773
1774 if (getifaddrs(&ifap) != 0) {
1775 log_warn("getifaddrs")uw_log_warn("getifaddrs");
1776 return;
1777 }
1778
1779 for (ifa = ifap; ifa != NULL((void*)0); ifa = ifa->ifa_next) {
1780 if (ifa->ifa_addr == NULL((void*)0))
1781 continue;
1782 switch(ifa->ifa_addr->sa_family) {
1783 case AF_LINK18:
1784 /* AF_LINK comes before inet / inet6 on an interface */
1785 ifa_data = (struct if_data *)ifa->ifa_data;
1786 ifa_rtable = ifa_data->ifi_rdomain;
1787 break;
1788 case AF_INET2:
1789 if (ifa_rtable != rtable)
1790 continue;
1791
1792 sin4 = (struct sockaddr_in *)ifa->ifa_addr;
1793 if ((ntohl(sin4->sin_addr.s_addr)(__uint32_t)(__builtin_constant_p(sin4->sin_addr.s_addr) ?
(__uint32_t)(((__uint32_t)(sin4->sin_addr.s_addr) & 0xff
) << 24 | ((__uint32_t)(sin4->sin_addr.s_addr) &
0xff00) << 8 | ((__uint32_t)(sin4->sin_addr.s_addr)
& 0xff0000) >> 8 | ((__uint32_t)(sin4->sin_addr
.s_addr) & 0xff000000) >> 24) : __swap32md(sin4->
sin_addr.s_addr))
>> 24) ==
1794 IN_LOOPBACKNET127)
1795 continue;
1796 new_available_af |= HAVE_IPV41;
1797 break;
1798 case AF_INET624:
1799 if (ifa_rtable != rtable)
1800 continue;
1801
1802 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
1803 if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)((*(const u_int32_t *)(const void *)(&(&sin6->sin6_addr
)->__u6_addr.__u6_addr8[0]) == 0) && (*(const u_int32_t
*)(const void *)(&(&sin6->sin6_addr)->__u6_addr
.__u6_addr8[4]) == 0) && (*(const u_int32_t *)(const void
*)(&(&sin6->sin6_addr)->__u6_addr.__u6_addr8[8
]) == 0) && (*(const u_int32_t *)(const void *)(&
(&sin6->sin6_addr)->__u6_addr.__u6_addr8[12]) == (__uint32_t
)(__builtin_constant_p(1) ? (__uint32_t)(((__uint32_t)(1) &
0xff) << 24 | ((__uint32_t)(1) & 0xff00) << 8
| ((__uint32_t)(1) & 0xff0000) >> 8 | ((__uint32_t
)(1) & 0xff000000) >> 24) : __swap32md(1))))
||
1804 IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xfe
) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8
[1] & 0xc0) == 0x80))
||
1805 IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xff
) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8
[1] & 0x0f) == 0x02))
||
1806 IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr)(((&sin6->sin6_addr)->__u6_addr.__u6_addr8[0] == 0xff
) && (((&sin6->sin6_addr)->__u6_addr.__u6_addr8
[1] & 0x0f) == 0x01))
)
1807 continue;
1808 new_available_af |= HAVE_IPV62;
1809 break;
1810 default:
1811 break;
1812 }
1813 if (new_available_af == (HAVE_IPV41 | HAVE_IPV62))
1814 break;
1815 }
1816 freeifaddrs(ifap);
1817 if (new_available_af != available_af) {
1818 available_af = new_available_af;
1819 frontend_imsg_compose_resolver(IMSG_CHANGE_AFS, 0,
1820 &available_af, sizeof(available_af));
1821 }
1822}