3 #ifndef ADNS_INTERNAL_H_INCLUDED
4 #define ADNS_INTERNAL_H_INCLUDED
6 #define PRINTFFORMAT(a,b) __attribute__((format(printf,a,b)))
7 typedef unsigned char byte
;
17 /* Configuration and constants */
20 #define UDPMAXRETRIES /*15*/5
21 #define UDPRETRYMS 2000
23 #define LOCALRESOURCEMS 20
26 #define DNS_MAXUDP 512
27 #define DNS_MAXDOMAIN 255
28 #define DNS_HDRSIZE 12
29 #define DNS_CLASS_IN 1
40 /* Shared data structures */
64 adns_status (*get_fn
)(adns_state ads
, adns_query qu
, int serv
,
65 const byte
*dgram
, int dglen
,
66 int *cbyte_io
, int max
,
67 int nsstart
, int arcount
, int *arstart_io
,
68 int roff
, int *rcount_io
);
72 /* FIXME: make sure this is all init'd properly */
73 enum { query_udp
, query_tcpwait
, query_tcpsent
, query_child
, query_done
} state
;
74 adns_query back
, next
, parent
;
75 struct { adns_query head
, tail
; } children
;
76 struct { adns_query back
, next
; } siblings
;
78 const typeinfo
*typei
;
80 int id
, flags
, udpretries
;
82 unsigned long udpsent
, tcpfailed
; /* bitmap indexed by server */
83 struct timeval timeout
;
85 int querylen
, cnameoff
, rrsoff
;
88 /* After the owner name and nul comes the query message, pointed to by querymsg */
92 * state Queue child id answer nextudpserver sentudp failedtcp
94 * udp NONE null >=0 null 0 zero zero
95 * udp timew null >=0 null any nonzero zero
96 * udp NONE null >=0 null any nonzero zero
98 * tcpwait timew null >=0 null irrelevant zero any
99 * tcpsent timew null >=0 null irrelevant zero any
101 * child childw set >=0 partial irrelevant irrelevant irrelevant
102 * done output null -1 set/null irrelevant irrelevant irrelevant
104 * +------------------------+
105 * START -----> | udp/NONE |
106 * +------------------------+
108 * too big for UDP / UDP timeout \ \ send via UDP
109 * do this ASAP! / more retries \ \ do this ASAP!
111 * +---------------+ +-----------+
112 * | tcpwait/timew | ____ | udp/timew |
113 * +---------------+ \ +-----------+
115 * TCP conn'd; | | TCP died | | |
116 * send via TCP | | more | UDP timeout | |
117 * do this ASAP! | | servers | no more | |
118 * v | to try | retries | |
119 * +---------------+ | desired | |
120 * | tcpsent/timew | ____ | | |
121 * +---------------+ \| | |
122 * \ \ TCP died | TCP | |
123 * \ \ no more | timeout / |
127 * reply \ _| +------------------+ / reply
128 * \ | done/output FAIL | /
129 * \ +------------------+ /
132 * (..... got reply ....)
134 * need child query/ies / \ no child query
137 * +--------------+ +----------------+
138 * | child/childw | ----------------> | done/output OK |
139 * +--------------+ children done +----------------+
144 adns_initflags iflags
;
146 struct { adns_query head
, tail
; } timew
, childw
, output
;
147 int nextid
, udpsocket
, tcpsocket
;
148 vbuf rqbuf
, tcpsend
, tcprecv
;
149 int nservers
, tcpserver
;
150 enum adns__tcpstate
{ server_disconnected
, server_connecting
, server_ok
} tcpstate
;
151 struct timeval tcptimeout
;
154 } servers
[MAXSERVERS
];
159 void adns__vdiag(adns_state ads
, const char *pfx
, adns_initflags prevent
,
160 int serv
, const char *fmt
, va_list al
);
161 void adns__debug(adns_state ads
, int serv
, const char *fmt
, ...) PRINTFFORMAT(3,4);
162 void adns__warn(adns_state ads
, int serv
, const char *fmt
, ...) PRINTFFORMAT(3,4);
163 void adns__diag(adns_state ads
, int serv
, const char *fmt
, ...) PRINTFFORMAT(3,4);
165 int adns__vbuf_ensure(vbuf
*vb
, int want
);
166 int adns__vbuf_append(vbuf
*vb
, const byte
*data
, int len
);
167 int adns__vbuf_malloc(vbuf
*vb
, size_t len
);
168 /* 1=>success, 0=>realloc failed */
169 void adns__vbuf_appendq(vbuf
*vb
, const byte
*data
, int len
);
170 void adns__vbuf_init(vbuf
*vb
);
172 int adns__setnonblock(adns_state ads
, int fd
); /* => errno value */
176 void adns__query_nomem(adns_state ads
, adns_query qu
);
177 void adns__query_finish(adns_state ads
, adns_query qu
, adns_status stat
);
178 void adns__query_fail(adns_state ads
, adns_query qu
, adns_status stat
);
182 void adns__query_udp(adns_state ads
, adns_query qu
, struct timeval now
);
183 void adns__query_tcp(adns_state ads
, adns_query qu
, struct timeval now
);
184 adns_status
adns__mkquery(adns_state ads
, const char *owner
, int ol
, int id
,
185 const typeinfo
*typei
, adns_queryflags flags
);
189 void adns__procdgram(adns_state ads
, const byte
*dgram
, int len
,
190 int serv
, struct timeval now
);
194 const typeinfo
*adns__findtype(adns_rrtype type
);
198 int vbuf__append_quoted1035(vbuf
*vb
, const byte
*buf
, int len
);
200 adns_status
adns__get_label(const byte
*dgram
, int dglen
, int *max_io
,
201 int *cbyte_io
, int *lablen_r
, int *labstart_r
,
203 adns_status
adns__get_domain_perm(adns_state ads
, adns_query qu
, int serv
,
204 const byte
*dgram
, int dglen
,
205 int *cbyte_io
, int max
, int *domainstart_r
);
206 adns_status
adns__get_domain_temp(adns_state ads
, adns_query qu
, int serv
,
207 const byte
*dgram
, int dglen
,
208 int *cbyte_io
, int max
, int *domainstart_r
);
209 adns_status
adns__get_rr_temp(adns_state ads
, adns_query qu
, int serv
,
210 const byte
*dgram
, int dglen
, int *cbyte_io
,
211 int *type_r
, int *class_r
, int *rdlen_r
, int *rdstart_r
,
212 const byte
*eo_dgram
, int eo_dglen
, int eo_cbyte
,
217 void adns__tcp_broken(adns_state ads
, const char *what
, const char *why
);
218 void adns__tcp_tryconnect(adns_state ads
, struct timeval now
);
219 void adns__autosys(adns_state ads
, struct timeval now
);
221 /* Useful static inline functions: */
223 static inline void timevaladd(struct timeval
*tv_io
, long ms
) {
227 tmp
.tv_usec
+= (ms
%1000)*1000000;
228 tmp
.tv_sec
+= ms
/1000;
229 if (tmp
.tv_usec
>= 1000000) { tmp
.tv_sec
++; tmp
.tv_usec
-= 1000; }
233 static inline int ctype_whitespace(int c
) { return c
==' ' || c
=='\n' || c
=='\t'; }
234 static inline int ctype_digit(int c
) { return c
>='0' && c
<='9'; }
235 static inline int ctype_alpha(int c
) {
236 return (c
>= 'a' && c
<= 'z') || (c
>= 'A' || c
<= 'Z');
241 #define LIST_INIT(list) ((list).head= (list).tail= 0)
243 #define LIST_UNLINK_PART(list,node,part) \
245 if ((node)->back) (node)->back->part next= (node)->part next; \
246 else (list).head= (node)->part next; \
247 if ((node)->next) (node)->next->part back= (node)->part back; \
248 else (list).tail= (node)->part back; \
251 #define LIST_LINK_TAIL_PART(list,node,part) \
253 (node)->part back= 0; \
254 (node)->part next= (list).tail; \
255 if ((list).tail) (list).tail->part back= (node); else (list).part head= (node); \
256 (list).tail= (node); \
259 #define LIST_UNLINK(list,node) LIST_UNLINK_PART(list,node,)
260 #define LIST_LINK_TAIL(list,node) LIST_LINK_TAIL_PART(list,node,)
262 #define GETIL_B(cb) (dgram[(cb)++])
263 #define GET_B(cb,tv) ((tv)= GETIL_B((cb)))
264 #define GET_W(cb,tv) ((tv)=0, (tv)|=(GETIL_B((cb))<<8), (tv)|=GETIL_B(cb), (tv))