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)
199 NAME(rp->owner->name);
201 USHORT(rp->owner->class);
203 if(rp->db || (ttl = (long)(rp->expire - now)) > rp->ttl)
209 lp = p; /* leave room for the rdata length */
218 SYMBOL(rp->cpu->name);
219 SYMBOL(rp->os->name);
226 NAME(rp->host->name);
238 NAME(rp->host->name);
241 V4ADDR(rp->ip->name);
244 V6ADDR(rp->ip->name);
250 NAME(rp->host->name);
252 ULONG(rp->soa->serial);
253 ULONG(rp->soa->refresh);
254 ULONG(rp->soa->retry);
255 ULONG(rp->soa->expire);
256 ULONG(rp->soa->minttl);
259 USHORT(rp->srv->pri);
260 USHORT(rp->srv->weight);
262 STRING(rp->host->name); /* rfc2782 sez no name compression */
265 for(t = rp->txt; t != nil; t = t->next)
269 BYTES(rp->null->data, rp->null->dlen);
276 USHORT(rp->key->flags);
277 UCHAR(rp->key->proto);
279 BYTES(rp->key->data, rp->key->dlen);
282 USHORT(rp->sig->type);
284 UCHAR(rp->sig->labels);
287 ULONG(rp->sig->incep);
288 USHORT(rp->sig->tag);
289 NAME(rp->sig->signer->name);
290 BYTES(rp->sig->data, rp->sig->dlen);
293 USHORT(rp->cert->type);
294 USHORT(rp->cert->tag);
295 UCHAR(rp->cert->alg);
296 BYTES(rp->cert->data, rp->cert->dlen);
300 /* stuff in the rdata section length */
309 convQ2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
311 NAME(rp->owner->name);
313 USHORT(rp->owner->class);
318 rrloop(RR *rp, int *countp, uchar *p, uchar *ep, Dict *dp, int quest)
323 for(; rp && p < ep; rp = rp->next){
325 np = convQ2M(rp, p, ep, dp);
327 np = convRR2M(rp, p, ep, dp);
337 * convert into a message
340 convDNS2M(DNSmsg *m, uchar *buf, int len)
350 m->qdcount = m->ancount = m->nscount = m->arcount = 0;
352 /* first pack in the RR's so we can get real counts */
355 p = rrloop(m->qd, &m->qdcount, p, ep, &d, 1);
356 p = rrloop(m->an, &m->ancount, p, ep, &d, 0);
357 p = rrloop(m->ns, &m->nscount, p, ep, &d, 0);
358 p = rrloop(m->ar, &m->arcount, p, ep, &d, 0);
361 dnslog("udp packet full; truncating my reply");
365 /* now pack the rest */
370 USHORT(m->flags | trunc);