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