1 /* Module for (ab)using DNS as a transport */
3 /* This provides two new kinds of closure, both of type comm.
5 * which takes an underlying udp comm
6 * and which never supports lookup by address
12 * Query format: create assoc:
14 * 1 bit set this is a create assoc query
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
20 * Query format: submit:
22 * 1 bit clear this is not a create assoc query
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
28 * Query format: fetch:
30 * 1 bit clear this is not a create assoc query
31 * 16 bits client query distinguisher (for defeating dns cache)
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
42 * Query bitstring, from above, is encoded as follows:
44 * . append our server's domain
45 * Max DNS domain is 255 bytes.
46 * Max UDP packet is 512 bytes.
47 * If our domain is .s.chiark.net. (12 bytes)
48 * then we have 241 bytes of payload left.
49 * We need at least 4 subdomains to avoid blowing the 63-byte limit
50 * So that means we need 3 more dots, so 238 chars.
51 * At 5 bits per char that's 1190 bits. Minus our submit
52 * header (1+32+16+10+1 = 60 bits) that's 1130 bits or 141.25 bytes.
57 struct timeval expires;
61 uint8_t *qsubdomhash; /* of length dns_server->hash->len */
62 struct expires expires;
63 int responselen; /* -1 if we are holding this query */
64 uint8_t *response; /* 0 if we are holding this query */
68 struct holding *next, *back;
69 struct expires expires;
70 int qsubdomlen; /* in octets */
71 uint8_t *qsubdom; /* in dns format ready for packet */
72 struct dedupe *dedupe;
77 struct expires expires; /* clock is running once the clientinit expires */
78 /* table of incoming partial messages */
79 int incoming_used, incoming_allocd;
80 uint32_t incoming_firstseq;
81 struct incomingmsg *incoming;
82 /* table of outgoing messages */
83 int outgoing_used, outgoing_allocd;
84 uint32_t outgoingmsg *outgoing;
86 HASHTABLE(struct dedupe) dedupe;
87 /* holding responses */
88 SLIST(struct holding) holding;
92 struct sockaddr_in clientaddr;
94 struct expires expires;
101 struct comm_if *port;
102 struct hash_if *hash; /* used for dedupe */
103 HASHTABLE(struct clientinit) clientinits;
104 HASHTABLE(struct assoc) assocs;
110 * 1. decode dns packet, check it is for us, etc.
112 * 3. check qsubdomhash in dedupe
113 * if found, send response (or discard, if we are holding), done.
114 * 4a. create assoc packet
115 * look up {clientaddr,clientnonce} in clientinit
116 * if not then create an assoc
122 void incoming_packet(const uint8_t pkt, int len) {
123 if (len < DNS_HDRLEN)
124 return badpkt("shorter than dns header");