1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7  *
8  * See the COPYRIGHT file distributed with this work for additional
9  * information regarding copyright ownership.
10  */
11 
12 #ifndef NAMED_LWDCLIENT_H
13 #define NAMED_LWDCLIENT_H 1
14 
15 /*! \file */
16 
17 #include <isc/event.h>
18 #include <isc/eventclass.h>
19 #include <isc/netaddr.h>
20 #include <isc/sockaddr.h>
21 #include <isc/types.h>
22 
23 #include <dns/fixedname.h>
24 #include <dns/types.h>
25 
26 #include <lwres/lwres.h>
27 
28 #include <named/lwsearch.h>
29 
30 #define LWRD_EVENTCLASS		ISC_EVENTCLASS(4242)
31 
32 #define LWRD_SHUTDOWN		(LWRD_EVENTCLASS + 0x0001)
33 
34 /*% Lightweight Resolver Daemon Client */
35 struct ns_lwdclient {
36 	isc_sockaddr_t		address;	/*%< where to reply */
37 	struct in6_pktinfo	pktinfo;
38 	bool		pktinfo_valid;
39 	ns_lwdclientmgr_t	*clientmgr;	/*%< our parent */
40 	ISC_LINK(ns_lwdclient_t) link;
41 	unsigned int		state;
42 	void			*arg;		/*%< packet processing state */
43 
44 	/*
45 	 * Received data info.
46 	 */
47 	unsigned char		buffer[LWRES_RECVLENGTH]; /*%< receive buffer */
48 	uint32_t		recvlength;	/*%< length recv'd */
49 	lwres_lwpacket_t	pkt;
50 
51 	/*%
52 	 * Send data state.  If sendbuf != buffer (that is, the send buffer
53 	 * isn't our receive buffer) it will be freed to the lwres_context_t.
54 	 */
55 	unsigned char	       *sendbuf;
56 	uint32_t		sendlength;
57 	isc_buffer_t		recv_buffer;
58 
59 	/*%
60 	 * gabn (get address by name) state info.
61 	 */
62 	dns_adbfind_t		*find;
63 	dns_adbfind_t		*v4find;
64 	dns_adbfind_t		*v6find;
65 	unsigned int		find_wanted;	/*%< Addresses we want */
66 	dns_fixedname_t		query_name;
67 	dns_fixedname_t		target_name;
68 	ns_lwsearchctx_t	searchctx;
69 	lwres_gabnresponse_t	gabn;
70 
71 	/*%
72 	 * gnba (get name by address) state info.
73 	 */
74 	lwres_gnbaresponse_t	gnba;
75 	dns_byaddr_t	       *byaddr;
76 	unsigned int		options;
77 	isc_netaddr_t		na;
78 
79 	/*%
80 	 * grbn (get rrset by name) state info.
81 	 *
82 	 * Note: this also uses target_name and searchctx.
83 	 */
84 	lwres_grbnresponse_t	grbn;
85 	dns_lookup_t	       *lookup;
86 	dns_rdatatype_t		rdtype;
87 
88 	/*%
89 	 * Alias and address info.  This is copied up to the gabn/gnba
90 	 * structures eventually.
91 	 *
92 	 * XXXMLG We can keep all of this in a client since we only service
93 	 * three packet types right now.  If we started handling more,
94 	 * we'd need to use "arg" above and allocate/destroy things.
95 	 */
96 	char		       *aliases[LWRES_MAX_ALIASES];
97 	uint16_t		aliaslen[LWRES_MAX_ALIASES];
98 	lwres_addr_t		addrs[LWRES_MAX_ADDRS];
99 };
100 
101 /*%
102  * Client states.
103  *
104  * _IDLE	The client is not doing anything at all.
105  *
106  * _RECV	The client is waiting for data after issuing a socket recv().
107  *
108  * _RECVDONE	Data has been received, and is being processed.
109  *
110  * _FINDWAIT	An adb (or other) request was made that cannot be satisfied
111  *		immediately.  An event will wake the client up.
112  *
113  * _SEND	All data for a response has completed, and a reply was
114  *		sent via a socket send() call.
115  *
116  * Badly formatted state table:
117  *
118  *	IDLE -> RECV when client has a recv() queued.
119  *
120  *	RECV -> RECVDONE when recvdone event received.
121  *
122  *	RECVDONE -> SEND if the data for a reply is at hand.
123  *	RECVDONE -> FINDWAIT if more searching is needed, and events will
124  *		eventually wake us up again.
125  *
126  *	FINDWAIT -> SEND when enough data was received to reply.
127  *
128  *	SEND -> IDLE when a senddone event was received.
129  *
130  *	At any time -> IDLE on error.  Sometimes this will be -> SEND
131  *	instead, if enough data is on hand to reply with a meaningful
132  *	error.
133  *
134  *	Packets which are badly formatted may or may not get error returns.
135  */
136 #define NS_LWDCLIENT_STATEIDLE		1
137 #define NS_LWDCLIENT_STATERECV		2
138 #define NS_LWDCLIENT_STATERECVDONE	3
139 #define NS_LWDCLIENT_STATEFINDWAIT	4
140 #define NS_LWDCLIENT_STATESEND		5
141 #define NS_LWDCLIENT_STATESENDDONE	6
142 
143 #define NS_LWDCLIENT_ISIDLE(c)		\
144 			((c)->state == NS_LWDCLIENT_STATEIDLE)
145 #define NS_LWDCLIENT_ISRECV(c)		\
146 			((c)->state == NS_LWDCLIENT_STATERECV)
147 #define NS_LWDCLIENT_ISRECVDONE(c)	\
148 			((c)->state == NS_LWDCLIENT_STATERECVDONE)
149 #define NS_LWDCLIENT_ISFINDWAIT(c)	\
150 			((c)->state == NS_LWDCLIENT_STATEFINDWAIT)
151 #define NS_LWDCLIENT_ISSEND(c)		\
152 			((c)->state == NS_LWDCLIENT_STATESEND)
153 
154 /*%
155  * Overall magic test that means we're not idle.
156  */
157 #define NS_LWDCLIENT_ISRUNNING(c)	(!NS_LWDCLIENT_ISIDLE(c))
158 
159 #define NS_LWDCLIENT_SETIDLE(c)		\
160 			((c)->state = NS_LWDCLIENT_STATEIDLE)
161 #define NS_LWDCLIENT_SETRECV(c)		\
162 			((c)->state = NS_LWDCLIENT_STATERECV)
163 #define NS_LWDCLIENT_SETRECVDONE(c)	\
164 			((c)->state = NS_LWDCLIENT_STATERECVDONE)
165 #define NS_LWDCLIENT_SETFINDWAIT(c)	\
166 			((c)->state = NS_LWDCLIENT_STATEFINDWAIT)
167 #define NS_LWDCLIENT_SETSEND(c)		\
168 			((c)->state = NS_LWDCLIENT_STATESEND)
169 #define NS_LWDCLIENT_SETSENDDONE(c)	\
170 			((c)->state = NS_LWDCLIENT_STATESENDDONE)
171 
172 /*% lightweight daemon client manager */
173 struct ns_lwdclientmgr {
174 	ns_lwreslistener_t     *listener;
175 	isc_mem_t	       *mctx;
176 	isc_socket_t	       *sock;		/*%< socket to use */
177 	dns_view_t	       *view;
178 	lwres_context_t	       *lwctx;		/*%< lightweight proto context */
179 	isc_task_t	       *task;		/*%< owning task */
180 	unsigned int		flags;
181 	isc_mutex_t		lock;
182 	ISC_LINK(ns_lwdclientmgr_t)	link;
183 	ISC_LIST(ns_lwdclient_t)	idle;		/*%< idle client slots */
184 	ISC_LIST(ns_lwdclient_t)	running;	/*%< running clients */
185 };
186 
187 #define NS_LWDCLIENTMGR_FLAGRECVPENDING		0x00000001
188 #define NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN	0x00000002
189 
190 isc_result_t
191 ns_lwdclientmgr_create(ns_lwreslistener_t *, unsigned int, isc_taskmgr_t *);
192 
193 void
194 ns_lwdclient_initialize(ns_lwdclient_t *, ns_lwdclientmgr_t *);
195 
196 isc_result_t
197 ns_lwdclient_startrecv(ns_lwdclientmgr_t *);
198 
199 void
200 ns_lwdclient_stateidle(ns_lwdclient_t *);
201 
202 void
203 ns_lwdclient_recv(isc_task_t *, isc_event_t *);
204 
205 void
206 ns_lwdclient_shutdown(isc_task_t *, isc_event_t *);
207 
208 void
209 ns_lwdclient_send(isc_task_t *, isc_event_t *);
210 
211 isc_result_t
212 ns_lwdclient_sendreply(ns_lwdclient_t *client, isc_region_t *r);
213 
214 /*
215  * Processing functions of various types.
216  */
217 void ns_lwdclient_processgabn(ns_lwdclient_t *, lwres_buffer_t *);
218 void ns_lwdclient_processgnba(ns_lwdclient_t *, lwres_buffer_t *);
219 void ns_lwdclient_processgrbn(ns_lwdclient_t *, lwres_buffer_t *);
220 void ns_lwdclient_processnoop(ns_lwdclient_t *, lwres_buffer_t *);
221 
222 void ns_lwdclient_errorpktsend(ns_lwdclient_t *, uint32_t);
223 
224 void ns_lwdclient_log(int level, const char *format, ...)
225      ISC_FORMAT_PRINTF(2, 3);
226 
227 #endif /* NAMED_LWDCLIENT_H */
228