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