Remove trailing whitespace from debian/*.
[debian/iodine.git] / src / read.c
1 /*
2  * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
3  * 2006-2009 Bjorn Andersson <flex@kryo.se>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 #include <string.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21
22 static int
23 readname_loop(char *packet, int packetlen, char **src, char *dst, size_t length, size_t loop)
24 {
25         char *dummy;
26         char *s;
27         char *d;
28         int len;
29         int offset;
30         char c;
31
32         if (loop <= 0)
33                 return 0;
34
35         len = 0;
36         s = *src;
37         d = dst;
38         while(*s && len < length - 2) {
39                 c = *s++;
40
41                 /* is this a compressed label? */
42                 if((c & 0xc0) == 0xc0) {
43                         offset = (((s[-1] & 0x3f) << 8) | (s[0] & 0xff));
44                         if (offset > packetlen) {
45                                 if (len == 0) {
46                                         /* Bad jump first in packet */
47                                         return 0;
48                                 } else {
49                                         /* Bad jump after some data */
50                                         break;
51                                 }
52                         }
53                         dummy = packet + offset;
54                         len += readname_loop(packet, packetlen, &dummy, d, length - len, loop - 1);
55                         goto end;
56                 }
57
58                 while(c && len < length - 1) {
59                         *d++ = *s++;
60                         len++;
61
62                         c--;
63                 }
64
65                 if (len >= length - 1) {
66                         break; /* We used up all space */
67                 }
68
69                 if (*s != 0) {
70                         *d++ = '.';
71                         len++;
72                 }
73         }
74         dst[len++] = '\0';
75
76 end:
77         (*src) = s+1;
78         return len;
79 }
80
81 int
82 readname(char *packet, int packetlen, char **src, char *dst, size_t length)
83 {
84         return readname_loop(packet, packetlen, src, dst, length, 10);
85 }
86
87 int
88 readshort(char *packet, char **src, unsigned short *dst)
89 {
90         unsigned char *p;
91
92         p = (unsigned char *) *src;
93         *dst = (p[0] << 8) | p[1];
94
95         (*src) += sizeof(unsigned short);
96         return sizeof(unsigned short);
97 }
98
99 int
100 readlong(char *packet, char **src, uint32_t *dst)
101 {
102         /* A long as described in dns protocol is always 32 bits */
103         unsigned char *p;
104
105         p = (unsigned char *) *src;
106
107         *dst = ((uint32_t)p[0] << 24)
108                  | ((uint32_t)p[1] << 16)
109                  | ((uint32_t)p[2] << 8)
110                  | ((uint32_t)p[3]);
111
112         (*src) += sizeof(uint32_t);
113         return sizeof(uint32_t);
114 }
115
116 int
117 readdata(char *packet, char **src, char *dst, size_t len)
118 {
119         memcpy(dst, *src, len);
120
121         (*src) += len;
122
123         return len;
124 }
125
126 int
127 readtxtbin(char *packet, char **src, size_t srcremain, char *dst, size_t dstremain)
128 {
129         unsigned char *uc;
130         int tocopy;
131         int dstused = 0;
132
133         while (srcremain > 0)
134         {
135                 uc = (unsigned char*) (*src);
136                 tocopy = *uc;
137                 (*src)++;
138                 srcremain--;
139
140                 if (tocopy > srcremain)
141                         return 0;       /* illegal, better have nothing */
142                 if (tocopy > dstremain)
143                         return 0;       /* doesn't fit, better have nothing */
144
145                 memcpy(dst, *src, tocopy);
146                 dst += tocopy;
147                 (*src) += tocopy;
148                 srcremain -= tocopy;
149                 dstremain -= tocopy;
150                 dstused += tocopy;
151         }
152         return dstused;
153 }
154
155 int
156 putname(char **buf, size_t buflen, const char *host)
157 {
158         char *word;
159         int left;
160         char *h;
161         char *p;
162
163         h = strdup(host);
164         left = buflen;
165         p = *buf;
166
167         word = strtok(h, ".");
168         while(word) {
169                 if (strlen(word) > 63 || strlen(word) > left) {
170                         free(h);
171                         return -1;
172                 }
173
174                 left -= (strlen(word) + 1);
175                 *p++ = (char)strlen(word);
176                 memcpy(p, word, strlen(word));
177                 p += strlen(word);
178
179                 word = strtok(NULL, ".");
180         }
181
182         *p++ = 0;
183
184         free(h);
185
186         *buf = p;
187         return buflen - left;
188 }
189
190 int
191 putbyte(char **dst, unsigned char value)
192 {
193         **dst = value;
194         (*dst)++;
195
196         return sizeof(char);
197 }
198
199 int
200 putshort(char **dst, unsigned short value)
201 {
202         unsigned char *p;
203
204         p = (unsigned char *) *dst;
205
206         *p++ = (value >> 8);
207         *p++ = value;
208
209         (*dst) = (char *) p;
210         return sizeof(short);
211 }
212
213 int
214 putlong(char **dst, uint32_t value)
215 {
216         /* A long as described in dns protocol is always 32 bits */
217         unsigned char *p;
218
219         p = (unsigned char *) *dst;
220
221         *p++ = (value >> 24);
222         *p++ = (value >> 16);
223         *p++ = (value >> 8);
224         *p++ = (value);
225
226         (*dst) = (char *) p;
227         return sizeof(uint32_t);
228 }
229
230 int
231 putdata(char **dst, char *data, size_t len)
232 {
233         memcpy(*dst, data, len);
234
235         (*dst) += len;
236         return len;
237 }
238
239 int
240 puttxtbin(char **buf, size_t bufremain, char *from, size_t fromremain)
241 {
242         unsigned char uc;
243         unsigned char *ucp = &uc;
244         char *cp = (char *) ucp;
245         int tocopy;
246         int bufused = 0;
247
248         while (fromremain > 0)
249         {
250                 tocopy = fromremain;
251                 if (tocopy > 252)
252                         tocopy = 252;   /* allow off-by-1s in caches etc */
253                 if (tocopy + 1 > bufremain)
254                         return -1;      /* doesn't fit, better have nothing */
255
256                 uc = tocopy;
257                 **buf = *cp;
258                 (*buf)++;
259                 bufremain--;
260                 bufused++;
261
262                 memcpy(*buf, from, tocopy);
263                 (*buf) += tocopy;
264                 from += tocopy;
265                 bufremain -= tocopy;
266                 fromremain -= tocopy;
267                 bufused += tocopy;
268         }
269         return bufused;
270 }