* - comments regarding library data structures
*/
/*
- * This file is part of adns, which is Copyright (C) 1997-1999 Ian Jackson
+ * This file is
+ * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *
+ * It is part of adns, which is
+ * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ * Copyright (C) 1999 Tony Finch <dot@dotat.at>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <unistd.h>
#include <signal.h>
#include <errno.h>
+#include <string.h>
#include <sys/time.h>
#include "adns.h"
+#include "dlist.h"
/* Configuration and constants */
#define MAX_POLLFDS ADNS_POLLFDS_RECOMMENDED
+typedef enum {
+ cc_user,
+ cc_entex,
+ cc_freq
+} consistency_checks;
+
typedef enum {
rcode_noerror,
rcode_formaterror,
struct adns__query {
adns_state ads;
- enum { query_udp, query_tcpwait, query_tcpsent, query_child, query_done } state;
+ enum { query_tosend, query_tcpwait, query_tcpsent, query_child, query_done } state;
adns_query back, next, parent;
struct { adns_query head, tail; } children;
struct { adns_query back, next; } siblings;
/* Possible states:
*
- * state Queue child id nextudpserver sentudp failedtcp
+ * state Queue child id nextudpserver udpsent tcpfailed
*
- * udp NONE null >=0 0 zero zero
- * udp timew null >=0 any nonzero zero
- * udp NONE null >=0 any nonzero zero
+ * tosend NONE null >=0 0 zero zero
+ * tosend timew null >=0 any nonzero zero
+ * tosend NONE null >=0 any nonzero zero
*
- * tcpwait timew null >=0 irrelevant zero any
- * tcpsent timew null >=0 irrelevant zero any
+ * tcpwait timew null >=0 irrelevant any any
+ * tcpsent timew null >=0 irrelevant any any
*
* child childw set >=0 irrelevant irrelevant irrelevant
* child NONE null >=0 irrelevant irrelevant irrelevant
adns_query forallnext;
int nextid, udpsocket, tcpsocket;
vbuf tcpsend, tcprecv;
- int nservers, nsortlist, nsearchlist, searchndots, tcpserver;
+ int nservers, nsortlist, nsearchlist, searchndots, tcpserver, tcprecv_skip;
enum adns__tcpstate { server_disconnected, server_connecting, server_ok } tcpstate;
struct timeval tcptimeout;
struct sigaction stdsigpipe;
/* From setup.c: */
int adns__setnonblock(adns_state ads, int fd); /* => errno value */
-void adns__checkqueues(adns_state ads); /* expensive walk, for checking */
/* From general.c: */
/* If SIGPIPE protection is not disabled, will block all signals except
* SIGPIPE, and set SIGPIPE's disposition to SIG_IGN. (And then restore.)
* Each call to _protect must be followed by a call to _unprotect before
- * any significant amount of code gets to run.
+ * any significant amount of code gets to run, since the old signal mask
+ * is stored in the adns structure.
*/
/* From transmit.c: */
*
* adns__tcp_tryconnect should already have been called - _tcp
* will only use an existing connection (if there is one), which it
- * may break. If the conn list lost then the caller is responsible for any
+ * may break. If the conn is lost then the caller is responsible for any
* reestablishment and retry.
*/
-void adns__query_udp(adns_query qu, struct timeval now);
-/* Query must be in state udp/NONE; it will be moved to a new state,
+void adns__query_send(adns_query qu, struct timeval now);
+/* Query must be in state tosend/NONE; it will be moved to a new state,
* and no further processing can be done on it for now.
* (Resulting state is one of udp/timew, tcpwait/timew (if server not connected),
* tcpsent/timew, child/childw or done/output.)
+ * __query_send may decide to use either UDP or TCP depending whether
+ * _qf_usevc is set (or has become set) and whether the query is too
+ * large.
*/
/* From query.c: */
/* From reply.c: */
void adns__procdgram(adns_state ads, const byte *dgram, int len,
- int serv, struct timeval now);
+ int serv, int viatcp, struct timeval now);
+/* This function is allowed to cause new datagrams to be constructed
+ * and sent, or even new queries to be started. However,
+ * query-sending functions are not allowed to call any general event
+ * loop functions in case they accidentally call this.
+ */
/* From types.c: */
void adns__tcp_tryconnect(adns_state ads, struct timeval now);
void adns__autosys(adns_state ads, struct timeval now);
-/* Make all the system calls we want to if the application wants us to. */
+/* Make all the system calls we want to if the application wants us to.
+ * Must not be called from within adns internal processing functions,
+ * lest we end up in recursive descent !
+ */
void adns__must_gettimeofday(adns_state ads, const struct timeval **now_io,
struct timeval *tv_buf);
int maxfd, const fd_set *readfds,
const fd_set *writefds, const fd_set *exceptfds,
struct timeval now, int *r_r);
+int adns__internal_check(adns_state ads,
+ adns_query *query_io,
+ adns_answer **answer,
+ void **context_r);
+
+/* From check.c: */
+
+void adns__consistency(adns_state ads, adns_query qu, consistency_checks cc);
/* Useful static inline functions: */
static inline int ctype_alpha(int c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
+static inline int ctype_822special(int c) { return strchr("()<>@,;:\\\".[]",c) != 0; }
static inline int errno_resources(int e) { return e==ENOMEM || e==ENOBUFS; }
(( ((sz)+sizeof(union maxalign)-1) / sizeof(union maxalign) ) \
* sizeof(union maxalign) )
-#define LIST_INIT(list) ((list).head= (list).tail= 0)
-#define LINK_INIT(link) ((link).next= (link).back= 0)
-
-#define LIST_UNLINK_PART(list,node,part) \
- do { \
- if ((node)->part back) (node)->part back->part next= (node)->part next; \
- else (list).head= (node)->part next; \
- if ((node)->part next) (node)->part next->part back= (node)->part back; \
- else (list).tail= (node)->part back; \
- } while(0)
-
-#define LIST_LINK_TAIL_PART(list,node,part) \
- do { \
- (node)->part next= 0; \
- (node)->part back= (list).tail; \
- if ((list).tail) (list).tail->part next= (node); else (list).head= (node); \
- (list).tail= (node); \
- } while(0)
-
-#define LIST_UNLINK(list,node) LIST_UNLINK_PART(list,node,)
-#define LIST_LINK_TAIL(list,node) LIST_LINK_TAIL_PART(list,node,)
-
#define GETIL_B(cb) (((dgram)[(cb)++]) & 0x0ff)
#define GET_B(cb,tv) ((tv)= GETIL_B((cb)))
#define GET_W(cb,tv) ((tv)=0, (tv)|=(GETIL_B((cb))<<8), (tv)|=GETIL_B(cb), (tv))