1 #include "e.h"
2 #include "byte.h"
3 #include "dns.h"
4 
dns_packet_copy(const unsigned char * buf,long long len,long long pos,unsigned char * out,long long outlen)5 long long dns_packet_copy(const unsigned char *buf, long long len, long long pos, unsigned char *out, long long outlen) {
6 
7     while (outlen > 0) {
8         if (pos >= len) { errno = EPROTO; return 0; }
9         *out = buf[pos++];
10         ++out; --outlen;
11     }
12     return pos;
13 }
14 
dns_packet_skipname(const unsigned char * buf,long long len,long long pos)15 long long dns_packet_skipname(const unsigned char *buf, long long len, long long pos) {
16 
17     unsigned char ch;
18 
19     for (;;) {
20         if (pos >= len) break;
21         ch = buf[pos++];
22         if (ch >= 192) return pos + 1;
23         if (ch >= 64) break;
24         if (!ch) return pos;
25         pos += ch;
26     }
27 
28     errno = EPROTO;
29     return 0;
30 }
31 
dns_packet_getname(const unsigned char * buf,long long len,long long pos,unsigned char ** d)32 long long dns_packet_getname(const unsigned char *buf, long long len, long long pos, unsigned char **d) {
33 
34     long long loop = 0;
35     long long state = 0;
36     long long firstcompress = 0;
37     long long where;
38     unsigned char ch;
39     unsigned char name[255];
40     long long namelen = 0;
41 
42     for (;;) {
43         if (pos >= len) goto PROTO; ch = buf[pos++];
44         if (++loop >= 1000) goto PROTO;
45 
46         if (state > 0) {
47             if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch;
48             --state;
49         }
50         else {
51             while (ch >= 192) {
52                 where = ch; where -= 192; where <<= 8;
53                 if (pos >= len) goto PROTO; ch = buf[pos++];
54                 if (!firstcompress) firstcompress = pos;
55                 pos = where + ch;
56                 if (pos >= len) goto PROTO; ch = buf[pos++];
57                 if (++loop >= 1000) goto PROTO;
58             }
59             if (ch >= 64) goto PROTO;
60             if (namelen + 1 > sizeof name) goto PROTO; name[namelen++] = ch;
61             if (!ch) break;
62             state = ch;
63         }
64     }
65 
66     if (!dns_domain_copy(d, name)) return 0;
67 
68     if (firstcompress) return firstcompress;
69     return pos;
70 
71 PROTO:
72     errno = EPROTO;
73     return 0;
74 }
75 
dns_packet_getname_static(const unsigned char * buf,long long len,long long pos,unsigned char * name)76 long long dns_packet_getname_static(const unsigned char *buf, long long len, long long pos, unsigned char *name) {
77 
78     long long loop = 0;
79     long long state = 0;
80     long long firstcompress = 0;
81     long long where;
82     unsigned char ch;
83     long long namelen = 0;
84 
85     byte_zero(name, 256);
86 
87     for (;;) {
88         if (pos >= len) goto PROTO; ch = buf[pos++];
89         if (++loop >= 1000) goto PROTO;
90 
91         if (state > 0) {
92             if (namelen + 1 > 255) goto PROTO; name[namelen++] = ch;
93             --state;
94         }
95         else {
96             while (ch >= 192) {
97                 where = ch; where -= 192; where <<= 8;
98                 if (pos >= len) goto PROTO; ch = buf[pos++];
99                 if (!firstcompress) firstcompress = pos;
100                 pos = where + ch;
101                 if (pos >= len) goto PROTO; ch = buf[pos++];
102                 if (++loop >= 1000) goto PROTO;
103             }
104             if (ch >= 64) goto PROTO;
105             if (namelen + 1 > 255) goto PROTO; name[namelen++] = ch;
106             if (!ch) break;
107             state = ch;
108         }
109     }
110 
111     if (firstcompress) return firstcompress;
112     return pos;
113 
114 PROTO:
115     errno = EPROTO;
116     return 0;
117 }
118