9 * a dictionary of domain names for packing messages
15 typedef struct Dict Dict;
19 ushort offset; /* pointer to packed name in message */
20 char *name; /* pointer to unpacked name in buf */
22 int n; /* size of dictionary */
23 uchar *start; /* start of packed message */
24 char buf[4*1024]; /* buffer for unpacked names */
25 char *ep; /* first free char in buf */
28 #define NAME(x) p = pname(p, ep, x, dp)
29 #define SYMBOL(x) p = psym(p, ep, x)
30 #define STRING(x) p = pstr(p, ep, x)
31 #define BYTES(x, n) p = pbytes(p, ep, x, n)
32 #define USHORT(x) p = pushort(p, ep, x)
33 #define UCHAR(x) p = puchar(p, ep, x)
34 #define ULONG(x) p = pulong(p, ep, x)
35 #define V4ADDR(x) p = pv4addr(p, ep, x)
36 #define V6ADDR(x) p = pv6addr(p, ep, x)
39 psym(uchar *p, uchar *ep, char *np)
44 if(n >= Strlen) /* DNS maximum length string */
46 if(ep - p < n+1) /* see if it fits in the buffer */
54 pstr(uchar *p, uchar *ep, char *np)
59 if(n >= Strlen) /* DNS maximum length string */
61 if(ep - p < n+1) /* see if it fits in the buffer */
69 pbytes(uchar *p, uchar *ep, uchar *np, int n)
78 puchar(uchar *p, uchar *ep, int val)
87 pushort(uchar *p, uchar *ep, int val)
97 pulong(uchar *p, uchar *ep, int val)
109 pv4addr(uchar *p, uchar *ep, char *name)
122 pv6addr(uchar *p, uchar *ep, char *name)
124 if(ep - p < IPaddrlen)
127 return p + IPaddrlen;
132 pname(uchar *p, uchar *ep, char *np, Dict *dp)
136 char *last; /* last component packed */
138 if(strlen(np) >= Domlen) /* make sure we don't exceed DNS limits */
143 /* look through every component in the dictionary for a match */
144 for(i = 0; i < dp->n; i++){
145 if(strcmp(np, dp->x[i].name) == 0){
148 *p++ = (dp->x[i].offset>>8) | 0xc0;
149 *p++ = dp->x[i].offset;
154 /* if there's room, enter this name in dictionary */
157 /* the whole name is already in dp->buf */
158 last = strchr(last, '.') + 1;
159 dp->x[dp->n].name = last;
160 dp->x[dp->n].offset = p - dp->start;
165 if(dp->ep + i + 1 < &dp->buf[sizeof(dp->buf)]){
167 dp->x[dp->n].name = dp->ep;
169 dp->x[dp->n].offset = p - dp->start;
176 /* put next component into message */
177 cp = strchr(np, '.');
180 cp = np + i; /* point to null terminator */
183 cp++; /* point past '.' */
187 *p++ = i; /* count of chars in label */
195 *p++ = 0; /* add top level domain */
201 convRR2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
207 NAME(rp->owner->name);
209 USHORT(rp->owner->class);
211 /* egregious overuse of ttl (it's absolute time in the cache) */
220 lp = p; /* leave room for the rdata length */
229 SYMBOL(rp->cpu->name);
230 SYMBOL(rp->os->name);
237 NAME(rp->host->name);
249 NAME(rp->host->name);
252 V4ADDR(rp->ip->name);
255 V6ADDR(rp->ip->name);
261 NAME(rp->host->name);
263 ULONG(rp->soa->serial);
264 ULONG(rp->soa->refresh);
265 ULONG(rp->soa->retry);
266 ULONG(rp->soa->expire);
267 ULONG(rp->soa->minttl);
270 for(t = rp->txt; t != nil; t = t->next)
274 BYTES(rp->null->data, rp->null->dlen);
281 USHORT(rp->key->flags);
282 UCHAR(rp->key->proto);
284 BYTES(rp->key->data, rp->key->dlen);
287 USHORT(rp->sig->type);
289 UCHAR(rp->sig->labels);
292 ULONG(rp->sig->incep);
293 USHORT(rp->sig->tag);
294 NAME(rp->sig->signer->name);
295 BYTES(rp->sig->data, rp->sig->dlen);
298 USHORT(rp->cert->type);
299 USHORT(rp->cert->tag);
300 UCHAR(rp->cert->alg);
301 BYTES(rp->cert->data, rp->cert->dlen);
305 /* stuff in the rdata section length */
314 convQ2M(RR *rp, uchar *p, uchar *ep, Dict *dp)
316 NAME(rp->owner->name);
318 USHORT(rp->owner->class);
323 rrloop(RR *rp, int *countp, uchar *p, uchar *ep, Dict *dp, int quest)
328 for(; rp && p < ep; rp = rp->next){
330 np = convQ2M(rp, p, ep, dp);
332 np = convRR2M(rp, p, ep, dp);
342 * convert into a message
345 convDNS2M(DNSmsg *m, uchar *buf, int len)
354 m->qdcount = m->ancount = m->nscount = m->arcount = 0;
356 /* first pack in the RR's so we can get real counts */
359 p = rrloop(m->qd, &m->qdcount, p, ep, &d, 1);
360 p = rrloop(m->an, &m->ancount, p, ep, &d, 0);
361 p = rrloop(m->ns, &m->nscount, p, ep, &d, 0);
362 p = rrloop(m->ar, &m->arcount, p, ep, &d, 0);
366 /* now pack the rest */