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 SYMBOL(x) p = psym(p, ep, x)
28 #define STRING(x) p = pstr(p, ep, x)
29 #define BYTES(x, n) p = pbytes(p, ep, x, n)
30 #define USHORT(x) p = pushort(p, ep, x)
31 #define UCHAR(x) p = puchar(p, ep, x)
32 #define ULONG(x) p = pulong(p, ep, x)
33 #define V4ADDR(x) p = pv4addr(p, ep, x)
34 #define V6ADDR(x) p = pv6addr(p, ep, x)
37 psym(uchar *p, uchar *ep, char *np)
42 if(n >= Strlen) /* DNS maximum length string */
44 if(ep - p < n+1) /* see if it fits in the buffer */
52 pstr(uchar *p, uchar *ep, char *np)
54 return psym(p, ep, np);
58 pbytes(uchar *p, uchar *ep, uchar *np, int n)
67 puchar(uchar *p, uchar *ep, int val)
76 pushort(uchar *p, uchar *ep, int val)
86 pulong(uchar *p, uchar *ep, int val)
98 pv4addr(uchar *p, uchar *ep, char *name)
110 pv6addr(uchar *p, uchar *ep, char *name)
112 if(ep - p < IPaddrlen)
115 return p + IPaddrlen;
119 pname(uchar *p, uchar *ep, char *np, Dict *dp)
123 char *last; /* last component packed */
125 if(strlen(np) >= Domlen) /* make sure we don't exceed DNS limits */
130 /* look through every component in the dictionary for a match */
131 for(i = 0; i < dp->n; i++)
132 if(strcmp(np, dp->x[i].name) == 0){
135 if ((dp->x[i].offset>>8) & 0xc0)
136 dnslog("convDNS2M: offset too big for "
137 "DNS packet format");
138 *p++ = dp->x[i].offset>>8 | 0xc0;
139 *p++ = dp->x[i].offset;
143 /* if there's room, enter this name in dictionary */
146 /* the whole name is already in dp->buf */
147 last = strchr(last, '.') + 1;
148 dp->x[dp->n].name = last;
149 dp->x[dp->n].offset = p - dp->start;
154 if(dp->ep + i + 1 < &dp->buf[sizeof dp->buf]){
155 memmove(dp->ep, np, i);
157 dp->x[dp->n].name = dp->ep;
159 dp->x[dp->n].offset = p - dp->start;
165 /* put next component into message */
166 cp = strchr(np, '.');
169 cp = np + i; /* point to null terminator */
172 cp++; /* point past '.' */
178 *p++ = i; /* count of chars in label */
186 *p++ = 0; /* add top level domain */
192 convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
198 NAME(rp->owner->name);
200 USHORT(rp->owner->class);
202 /* egregious overuse of ttl (it's absolute time in the cache) */
211 lp = p; /* leave room for the rdata length */
220 SYMBOL(rp->cpu->name);
221 SYMBOL(rp->os->name);
228 NAME(rp->host->name);
240 NAME(rp->host->name);
243 V4ADDR(rp->ip->name);
246 V6ADDR(rp->ip->name);
252 NAME(rp->host->name);
254 ULONG(rp->soa->serial);
255 ULONG(rp->soa->refresh);
256 ULONG(rp->soa->retry);
257 ULONG(rp->soa->expire);
258 ULONG(rp->soa->minttl);
261 USHORT(rp->srv->pri);
262 USHORT(rp->srv->weight);
264 STRING(rp->host->name); /* rfc2782 sez no name compression */
267 for(t = rp->txt; t != nil; t = t->next)
271 BYTES(rp->null->data, rp->null->dlen);
278 USHORT(rp->key->flags);
279 UCHAR(rp->key->proto);
281 BYTES(rp->key->data, rp->key->dlen);
284 USHORT(rp->sig->type);
286 UCHAR(rp->sig->labels);
289 ULONG(rp->sig->incep);
290 USHORT(rp->sig->tag);
291 NAME(rp->sig->signer->name);
292 BYTES(rp->sig->data, rp->sig->dlen);
295 USHORT(rp->cert->type);
296 USHORT(rp->cert->tag);
297 UCHAR(rp->cert->alg);
298 BYTES(rp->cert->data, rp->cert->dlen);
302 /* stuff in the rdata section length */
311 convQ2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
313 NAME(rp->owner->name);
315 USHORT(rp->owner->class);
320 rrloop(RR *rp, int *countp, uchar *p, uchar *ep, Dict *dp, int quest)
325 for(; rp && p < ep; rp = rp->next){
327 np = convQ2M(rp, p, ep, dp);
329 np = convRR2M(rp, p, ep, dp);
339 * convert into a message
342 convDNS2M(DNSmsg *m, uchar *buf, int len)
352 m->qdcount = m->ancount = m->nscount = m->arcount = 0;
354 /* first pack in the RR's so we can get real counts */
357 p = rrloop(m->qd, &m->qdcount, p, ep, &d, 1);
358 p = rrloop(m->an, &m->ancount, p, ep, &d, 0);
359 p = rrloop(m->ns, &m->nscount, p, ep, &d, 0);
360 p = rrloop(m->ar, &m->arcount, p, ep, &d, 0);
363 dnslog("udp packet full; truncating my reply");
367 /* now pack the rest */
372 USHORT(m->flags | trunc);