chiark / gitweb /
WIP NEW COMM
[secnet.git] / dns-transp-server.c
1 /* Module for (ab)using DNS as a transport */
2
3 /* This provides two new kinds of closure, both of type comm.
4  *  dns-transport-server
5  *    which takes an underlying udp comm
6  *    and which never supports lookup by address
7  *  dns-transport-client
8  */
9
10
11 /*
12  * Query format: create assoc:
13  *    1 bit set    this a create assoc query
14  *   32 bits       clientnonce
15  *   10 bits       offset of this data fragment in packet
16  *    1 bit        is this the last fragment ?
17  *    remainder    data packet fragment
18  * data packet sequence number is always implicitly zero
19  *
20  * Query format: submit:
21  *    1 bit clear  this is not a create assoc query
22  *   32 bits       associd
23  *   16 bits       data packet sequence number
24  *   10 bits       offset of this data fragment in packet
25  *    1 bit        is this the last fragment
26  *    remainder    data packet fragment
27  *
28  * Query format: fetch:
29  *    1 bit clear  this is not a create assoc query
30  *   32 bits       associd
31  *   16 bits       client query distinguishper (for defeating dns cache)
32  *
33  * Response format:
34  * [ 32 bits       associd  - only for responses to create assoc ]
35  *    4 bits       log_2( number of bytes of outstanding data on server)
36  *   10 bits       offset of this data fragment in packet
37  *    1 bit        is this the last fragment ?
38  *    remainder    data packet fragment
39  */
40
41 /*
42  * Query bitstring, from above, is encoded as follows:
43  *   1. 
44  *    . append our server's domain
45
46 struct expires {
47     struct expires *next;
48     struct timeval expires;
49 };
50
51 struct dedupe {
52     uint8_t *qsubdomhash; /* of length dns_server->hash->len */
53     struct expires expires;
54     int responselen;   /* -1 if we are holding this query */
55     uint8_t *response; /*  0 if we are holding this query */
56 };
57
58 struct holding {
59     struct holding *next, *back;
60     struct expires expires;
61     int qsubdomlen; /* in octets */
62     uint8_t *qsubdom; /* in dns format ready for packet */
63     struct dedupe *dedupe;
64 };
65
66 struct assoc {
67     uint32_t associd;
68     struct expires expires; /* clock is running once the clientinit expires */
69     /* table of incoming partial messages */
70     int incoming_used, incoming_allocd;
71     uint32_t incoming_firstseq;
72     struct incomingmsg *incoming;
73     /* table of outgoing messages */
74     int outgoing_used, outgoing_allocd;
75     uint32_t outgoingmsg *outgoing;
76     /* dedupe table */
77     HASHTABLE(struct dedupe) dedupe;
78     /* holding responses */
79     SLIST(struct holding) holding;
80 };
81
82 struct clientinit {
83     struct sockaddr_in clientaddr;
84     uint32_t clientnonce;
85     struct expires expires;
86     struct assoc *assoc;
87 };
88
89 struct dns_server {
90     closure_t cl;
91     struct comm_if ops;
92     struct comm_if *port;
93     struct hash_if *hash; /* used for dedupe */
94     HASHTABLE(struct clientinit) clientinits;
95     HASHTABLE(struct assoc) assocs;
96 };
97
98 /*
99  * Incoming packet
100  *
101  * 1. decode dns packet, check it is for us, etc.
102  * 2. hash qsubdom
103  * 3. check qsubdomhash in dedupe
104  *    if found, send response (or discard, if we are holding), done.
105  * 4a. create assoc packet
106  *    look up {clientaddr,clientnonce} in clientinit
107  *    if not then create an assoc
108  *