7 * a dictionary of domain names for packing messages
13 typedef struct Dict Dict;
17 ushort offset; /* pointer to packed name in message */
18 char *name; /* pointer to unpacked name in buf */
20 int n; /* size of dictionary */
21 uchar *start; /* start of packed message */
22 char buf[16*1024]; /* buffer for unpacked names (was 4k) */
23 char *ep; /* first free char in buf */
26 #define NAME(x) p = pname(p, ep, x, dp)
27 #define LABEL(x) p = pname(p, ep, x, nil)
28 #define SYMBOL(x) p = psym(p, ep, x)
29 #define STRING(x) p = pstr(p, ep, x)
30 #define BYTES(x, n) p = pbytes(p, ep, x, n)
31 #define USHORT(x) p = pushort(p, ep, x)
32 #define UCHAR(x) p = puchar(p, ep, x)
33 #define ULONG(x) p = pulong(p, ep, x)
34 #define V4ADDR(x) p = pv4addr(p, ep, x)
35 #define V6ADDR(x) p = pv6addr(p, ep, x)
38 psym(uchar *p, uchar *ep, char *np)
43 if(n >= Strlen) /* DNS maximum length string */
45 if(ep - p < n+1) /* see if it fits in the buffer */
53 pstr(uchar *p, uchar *ep, char *np)
55 return psym(p, ep, np);
59 pbytes(uchar *p, uchar *ep, uchar *np, int n)
68 puchar(uchar *p, uchar *ep, int val)
77 pushort(uchar *p, uchar *ep, int val)
87 pulong(uchar *p, uchar *ep, int val)
99 pv4addr(uchar *p, uchar *ep, char *name)
111 pv6addr(uchar *p, uchar *ep, char *name)
113 if(ep - p < IPaddrlen)
116 return p + IPaddrlen;
120 pname(uchar *p, uchar *ep, char *np, Dict *dp)
124 char *last; /* last component packed */
126 if(strlen(np) >= Domlen) /* make sure we don't exceed DNS limits */
132 /* look through every component in the dictionary for a match */
133 for(i = 0; i < dp->n; i++){
134 if(strcmp(np, dp->x[i].name) == 0){
137 if ((dp->x[i].offset>>8) & 0xc0)
139 *p++ = dp->x[i].offset>>8 | 0xc0;
140 *p++ = dp->x[i].offset;
144 /* if there's room, enter this name in dictionary */
147 /* the whole name is already in dp->buf */
148 last = strchr(last, '.') + 1;
149 dp->x[dp->n].name = last;
150 dp->x[dp->n].offset = p - dp->start;
155 if(dp->ep + i + 1 < &dp->buf[sizeof dp->buf]){
156 memmove(dp->ep, np, i);
158 dp->x[dp->n].name = dp->ep;
160 dp->x[dp->n].offset = p - dp->start;
168 /* put next component into message */
169 cp = strchr(np, '.');
172 cp = np + i; /* point to null terminator */
175 cp++; /* point past '.' */
181 *p++ = i; /* count of chars in label */
189 *p++ = 0; /* add top level domain */
195 convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
202 NAME(rp->owner->name);
204 USHORT(rp->owner->class);
206 if(rp->db || (ttl = (long)(rp->expire - now)) > rp->ttl)
212 lp = p; /* leave room for the rdata length */
221 SYMBOL(rp->cpu->name);
222 SYMBOL(rp->os->name);
229 NAME(rp->host->name);
241 NAME(rp->host->name);
244 V4ADDR(rp->ip->name);
247 V6ADDR(rp->ip->name);
253 NAME(rp->host->name);
255 ULONG(rp->soa->serial);
256 ULONG(rp->soa->refresh);
257 ULONG(rp->soa->retry);
258 ULONG(rp->soa->expire);
259 ULONG(rp->soa->minttl);
262 USHORT(rp->srv->pri);
263 USHORT(rp->srv->weight);
265 LABEL(rp->host->name); /* rfc2782 sez no name compression */
268 for(t = rp->txt; t != nil; t = t->next)
272 BYTES(rp->null->data, rp->null->dlen);
279 USHORT(rp->key->flags);
280 UCHAR(rp->key->proto);
282 BYTES(rp->key->data, rp->key->dlen);
285 USHORT(rp->sig->type);
287 UCHAR(rp->sig->labels);
290 ULONG(rp->sig->incep);
291 USHORT(rp->sig->tag);
292 NAME(rp->sig->signer->name);
293 BYTES(rp->sig->data, rp->sig->dlen);
296 USHORT(rp->cert->type);
297 USHORT(rp->cert->tag);
298 UCHAR(rp->cert->alg);
299 BYTES(rp->cert->data, rp->cert->dlen);
303 /* stuff in the rdata section length */
312 convQ2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
314 NAME(rp->owner->name);
316 USHORT(rp->owner->class);
321 rrloop(RR *rp, int *countp, uchar *p, uchar *ep, Dict *dp, int quest)
326 for(; rp && p < ep; rp = rp->next){
328 np = convQ2M(rp, p, ep, dp);
330 np = convRR2M(rp, p, ep, dp);
340 * convert into a message
343 convDNS2M(DNSmsg *m, uchar *buf, int len)
353 m->qdcount = m->ancount = m->nscount = m->arcount = 0;
355 /* first pack in the RR's so we can get real counts */
358 p = rrloop(m->qd, &m->qdcount, p, ep, &d, 1);
359 p = rrloop(m->an, &m->ancount, p, ep, &d, 0);
360 p = rrloop(m->ns, &m->nscount, p, ep, &d, 0);
361 p = rrloop(m->ar, &m->arcount, p, ep, &d, 0);
364 dnslog("udp packet full; truncating my reply");
368 /* now pack the rest */
373 USHORT(m->flags | trunc);