1 /**************************************************************************************************
2 	$Id: task.h,v 1.18 2005/04/20 16:49:12 bboy Exp $
3 
4 	Copyright (C) 2002-2005  Don Moore <bboy@bboy.net>
5 
6 	This program is free software; you can redistribute it and/or modify
7 	it under the terms of the GNU General Public License as published by
8 	the Free Software Foundation; either version 2 of the License, or
9 	(at Your option) any later version.
10 
11 	This program is distributed in the hope that it will be useful,
12 	but WITHOUT ANY WARRANTY; without even the implied warranty of
13 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 	GNU General Public License for more details.
15 
16 	You should have received a copy of the GNU General Public License
17 	along with this program; if not, write to the Free Software
18 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 **************************************************************************************************/
20 
21 #ifndef _MYDNS_TASK_H
22 #define _MYDNS_TASK_H
23 
24 /* If defined, DYNAMIC_NAMES causes dynamic allocation of the encoded names list.  It's slow. */
25 #define	DYNAMIC_NAMES	0
26 
27 #define	MAX_CNAME_LEVEL	6
28 
29 
30 /* Task completion codes */
31 typedef enum _task_execstatus_t {
32   TASK_ABANDONED	=-2,		/* Task needs to be abandoned - release fd */
33   TASK_FAILED		=-1,		/* Task failed to execute properly kill */
34 
35   TASK_COMPLETED	= 0,		/* Task has run to completion dequeue */
36   TASK_FINISHED		= 1,		/* Task finished normally free all resources */
37   TASK_TIMED_OUT	= 2,		/* Task has timed out - dequeue */
38 
39   TASK_EXECUTED		= 3,		/* Task executed but did not complete retry later */
40   TASK_DID_NOT_EXECUTE	= 4,		/* Task did not execute try again later */
41   TASK_CONTINUE		= 5,		/* Task needs to run again */
42 } taskexec_t;
43 
44 /* Task type select */
45 typedef enum _taskpriority_t {
46   HIGH_PRIORITY_TASK = 0,
47   NORMAL_PRIORITY_TASK = 1,
48   LOW_PRIORITY_TASK = 2,
49 } taskpriority_t;
50 
51 typedef enum _tasktype_t {
52   NORMAL_TASK = 0,			/* Old style task */
53   IO_TASK = 1,				/* New task dependent on IO event to run */
54   PERIODIC_TASK = 2,			/* Task that runs on a tick */
55 } tasktype_t;
56 
57 #define Needs2Read		0x0001
58 #define Needs2Write		0x0002
59 #define Needs2Connect		0x0004
60 #define Needs2Exec		0x0008
61 
62 #define Needs2Recurse		0x0010
63 
64 /*
65  * Use the following scheme for task status
66  *
67  * Split the enum into 3 fields -
68  *	 upper 16 bits are operation identifiers
69  *	 upper byte of lower 16 bits is the class of operation being processed
70  *	 lower byte of lower 16 bits contains bit mask of type of operation as above
71  *
72  *	A Query Task - i.e. incoming request, outgoing response
73  *      A Request Task - i.e. outgoing request, incoming response e.g. Notify
74  *	A Periodic Task
75  *
76  */
77 #define QueryTask		0x0100
78 #define ReqTask			0x0200
79 #define TickTask		0x0400
80 #define RunTask			0x0800
81 
82 #define TASKCLASS(n)		((n)&(QueryTask|ReqTask|TickTask|RunTask))
83 #define TASKIOTYPE(n)		((n)&(Needs2Read|Needs2Write|Needs2Connect|Needs2Exec))
84 #define TaskIsRecursive(n)	((n)&Needs2Recurse)
85 #define TASKSTAT(n)		((n)<<16)
86 #define TASKSTATVAL(n)		(((n)>>16)&0xFFFF)
87 #define TASKTIMESOUT(n)		((n)&(QueryTask|ReqTask|TickTask))
88 
89 /* Task status flags */
90 typedef enum _taskstat_t {
91   /* We need to read the question */
92   NEED_READ = TASKSTAT(0)|QueryTask|Needs2Read,
93   /* We need to find the answer */
94   NEED_ANSWER = TASKSTAT(1)|QueryTask|Needs2Exec,
95   /* We need to write the answer */
96   NEED_WRITE = TASKSTAT(2)|QueryTask|Needs2Write,
97   /* We need to process an IXFR request */
98   NEED_IXFR = TASKSTAT(3)|QueryTask|Needs2Exec,
99 
100   /* Need to open connection to recursive server */
101   NEED_RECURSIVE_FWD_CONNECT = TASKSTAT(0)|QueryTask|Needs2Connect|Needs2Recurse,
102   /* TCP connection has started but not finished */
103   NEED_RECURSIVE_FWD_CONNECTING = TASKSTAT(1)|QueryTask|Needs2Write|Needs2Recurse,
104   /* Need to write the question to recursive forwarder */
105   NEED_RECURSIVE_FWD_WRITE = TASKSTAT(2)|QueryTask|Needs2Exec|Needs2Recurse,
106   /* Have sent message will need to retry on timeout */
107   NEED_RECURSIVE_FWD_RETRY = TASKSTAT(3)|TickTask|Needs2Exec|Needs2Recurse,
108   /* Need to read the answer from recursive forwarder */
109   NEED_RECURSIVE_FWD_READ = TASKSTAT(4)|QueryTask|Needs2Read|Needs2Recurse,
110   /* Need the task to finish connecting before can be scheduled */
111   NEED_RECURSIVE_FWD_CONNECTED = TASKSTAT(5)|QueryTask|Needs2Exec|Needs2Recurse,
112 
113   /* Need to read a response to a notify */
114   NEED_NOTIFY_READ = TASKSTAT(0)|ReqTask|Needs2Read,
115   /* Need to write a notify to a server */
116   NEED_NOTIFY_WRITE = TASKSTAT(1)|ReqTask|Needs2Write,
117   /* Need to retry if slaves do not reply */
118   NEED_NOTIFY_RETRY = TASKSTAT(2)|TickTask|Needs2Exec,
119 
120   /* Need to run these tasks */
121   NEED_TASK_RUN = TASKSTAT(0)|RunTask|Needs2Exec,
122   NEED_AXFR = TASKSTAT(1)|RunTask|Needs2Exec,
123   NEED_TASK_READ = TASKSTAT(2)|RunTask|Needs2Read,
124 
125   /* Interprocess commands */
126   NEED_COMMAND_READ = TASKSTAT(3)|QueryTask|Needs2Read,
127   NEED_COMMAND_WRITE = TASKSTAT(4)|QueryTask|Needs2Write,
128 } taskstat_t;
129 
130 
131 /* RR: A single resource record (of any supported type) */
132 typedef struct _named_rr {
133   dns_rrtype_t		rrtype;			/* Record type (what table this data came from) */
134   uint32_t		id;			/* ID associated with RR */
135   unsigned char		name[DNS_MAXNAMELEN];	/* Name to send with reply */
136   off_t			offset;			/* The offset within the reply data (t->rdata) */
137   size_t		length;			/* The length of data within the reply */
138   uint8_t		sort_level;		/* Primary sort order */
139   uint32_t		sort1, sort2;		/* Sort order within level */
140   unsigned int		lb_low, lb_high;	/* High/low values for load balancing (ugh) */
141   void			*rr;			/* The RR data */
142 
143   struct _named_rr	*next;			/* Pointer to the next item */
144 } RR;
145 
146 /* RRLIST: A list of resource records */
147 typedef struct _named_rrlist {
148   size_t	        size;			/* Count of records */
149 
150   int			a_records;		/* Number of A or AAAA records (for sorting) */
151   int			mx_records;		/* Number of MX records (for sorting) */
152   int			srv_records;		/* Number of SRV records (for sorting) */
153 
154   RR	       		*head;			/* Head of list */
155   RR	       		*tail;			/* Tail of list */
156 } RRLIST;
157 
158 typedef struct _named_task *TASKP;
159 
160 typedef void (*FreeExtension)(TASKP, void*);
161 typedef taskexec_t (*RunExtension)(TASKP, void*);
162 typedef taskexec_t (*TimeExtension)(TASKP, void*);
163 
164 /* TASK: DNS query task */
165 typedef struct _named_task {
166   QUEUEP		*TaskQ;			/* Queue holding task */
167   struct _named_task	*prev, *next;		/* Pointers to previous/next rec in queue */
168   tasktype_t		type;
169   taskpriority_t	priority;
170 
171   uint16_t		internal_id;		/* Internal task ID */
172   taskstat_t		status;			/* Current status of query */
173   time_t		timeout;		/* Time task expires (timeout) */
174 
175   void			*extension;		/* Data for new tasking model */
176   FreeExtension		freeextension;		/* Free extension data */
177   RunExtension		runextension;		/* Run extension */
178   TimeExtension		timeextension;		/* Extension timed out */
179 
180   /* IO Tasks */
181   int			fd;			/* Socket FD */
182   int			protocol;		/* Type of socket (SOCK_DGRAM/SOCK_STREAM) */
183   int			family;			/* Socket family (AF_INET/AF_INET6) */
184 
185   struct sockaddr_in	addr4;			/* IPv4 address of client */
186 #if HAVE_IPV6
187   struct sockaddr_in6	addr6;			/* IPv6 address of client */
188 #endif
189 
190   /* I/O information for TCP queries */
191   size_t		len;			/* Query length */
192   char	       		*query;			/* Query data */
193   size_t		offset;			/* Current offset */
194   int			len_written;		/* Have we written length octets? */
195 
196   /* Query information */
197   uint32_t		minimum_ttl;		/* Minimum TTL for current zone */
198   uint16_t		id;			/* Query ID */
199   DNS_HEADER		hdr;			/* Header */
200   dns_class_t		qclass;			/* Query class */
201   dns_qtype_t		qtype;			/* Query type */
202   char			qname[DNS_MAXNAMELEN];	/* Query name object */
203   task_error_t		reason;			/* Further explanation of the error */
204 
205   uint32_t		Cnames[MAX_CNAME_LEVEL];/* Array of CNAMEs found */
206 
207   unsigned char  	*qd;			/* Question section data */
208   size_t		qdlen;			/* Size of question section */
209   uint16_t		qdcount;		/* "qdcount", from header */
210   uint16_t		ancount;		/* "ancount", from header */
211   uint16_t		nscount;		/* "nscount", from header */
212   uint16_t		arcount;		/* "arcount", from header */
213 
214   int			no_markers;		/* Do not use markers? */
215 
216 #if DYNAMIC_NAMES
217   char	      		**Names;		/* Names stored in reply */
218   unsigned int   	*Offsets;		/* Offsets for names */
219 #else
220 #define	MAX_STORED_NAMES	128
221   char			Names[MAX_STORED_NAMES][DNS_MAXNAMELEN + 1];	/* Names stored in reply */
222   unsigned int		Offsets[MAX_STORED_NAMES];			/* Offsets for names */
223 #endif
224 
225   unsigned int		numNames;		/* Number of names in the list */
226 
227   uint32_t		zone;			/* Zone ID */
228 
229   uint8_t		sort_level;		/* Current sort level */
230 
231   RRLIST		an, ns, ar;		/* RR's for ANSWER, AUTHORITY, ADDITIONAL */
232 
233   char	       		*rdata;			/* Header portion of reply */
234   size_t		rdlen;			/* Length of `rdata' */
235 
236   char	       		*reply;			/* Total constructed reply data */
237   size_t		replylen;		/* Length of `reply' */
238 
239   int			reply_from_cache;	/* Did reply come from reply cache? */
240 
241   int			reply_cache_ok;		/* Can we cache this reply? */
242   int			name_ok;		/* Does _some_ record match the name? */
243 
244   int			forwarded;		/* Forwarded to a recursive server? */
245 
246   int			update_done;		/* Did we do any dynamic updates? */
247   int			info_already_out;	/* Has the info already been output? */
248 } TASK;
249 
250 #endif /* !_MYDNS_TASK_H */
251 /* vi:set ts=3: */
252