release
[hcoop/zz_old/debian/djbdns.git] / dns_packet.c
1 /*
2 DNS should have used LZ77 instead of its own sophomoric compression algorithm.
3 */
4
5 #include "error.h"
6 #include "dns.h"
7
8 unsigned int dns_packet_copy(const char *buf,unsigned int len,unsigned int pos,char *out,unsigned int outlen)
9 {
10 while (outlen) {
11 if (pos >= len) { errno = error_proto; return 0; }
12 *out = buf[pos++];
13 ++out; --outlen;
14 }
15 return pos;
16 }
17
18 unsigned int dns_packet_skipname(const char *buf,unsigned int len,unsigned int pos)
19 {
20 unsigned char ch;
21
22 for (;;) {
23 if (pos >= len) break;
24 ch = buf[pos++];
25 if (ch >= 192) return pos + 1;
26 if (ch >= 64) break;
27 if (!ch) return pos;
28 pos += ch;
29 }
30
31 errno = error_proto;
32 return 0;
33 }
34
35 unsigned int dns_packet_getname(const char *buf,unsigned int len,unsigned int pos,char **d)
36 {
37 unsigned int loop = 0;
38 unsigned int state = 0;
39 unsigned int firstcompress = 0;
40 unsigned int where;
41 unsigned char ch;
42 char name[255];
43 unsigned int namelen = 0;
44
45 for (;;) {
46 if (pos >= len) goto PROTO; ch = buf[pos++];
47 if (++loop >= 1000) goto PROTO;
48
49 if (state) {
50 if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch;
51 --state;
52 }
53 else {
54 while (ch >= 192) {
55 where = ch; where -= 192; where <<= 8;
56 if (pos >= len) goto PROTO; ch = buf[pos++];
57 if (!firstcompress) firstcompress = pos;
58 pos = where + ch;
59 if (pos >= len) goto PROTO; ch = buf[pos++];
60 if (++loop >= 1000) goto PROTO;
61 }
62 if (ch >= 64) goto PROTO;
63 if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch;
64 if (!ch) break;
65 state = ch;
66 }
67 }
68
69 if (!dns_domain_copy(d,name)) return 0;
70
71 if (firstcompress) return firstcompress;
72 return pos;
73
74 PROTO:
75 errno = error_proto;
76 return 0;
77 }