1 /**********************************************************************
2 * packet.c May 2003
3 * Horms horms@verge.net.au
4 *
5 * Packets for map queries
6 *
7 * perdition
8 * Mail retrieval proxy server
9 * Copyright (C) 1999-2005 Horms
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of the
14 * License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
24 *
25 **********************************************************************/
26
27 #include "packet.h"
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <inttypes.h>
32 #include <netinet/in.h>
33 #include <vanessa_logger.h>
34
35
36 static int
37 perdition_packet_init_v1_head(perdition_packet_t **packet,
38 uint16_t cs_type, uint16_t flags,
39 uint32_t saddr, uint16_t sport,
40 uint32_t daddr, uint16_t dport, size_t body_len);
41
42 static int
43 perdition_packet_verify_v1_head(perdition_packet_t *packet, size_t len);
44
45 static int
46 perdition_packet_verify_v1_tail(perdition_packet_t *packet, size_t body_len);
47
48
49 perdition_packet_t *
perdition_packet_create(void)50 perdition_packet_create(void)
51 {
52 perdition_packet_t *packet;
53
54 packet = (perdition_packet_t *)
55 calloc(1, sizeof(perdition_packet_t));
56 if(!packet) {
57 VANESSA_LOGGER_DEBUG_ERRNO("calloc");
58 return(NULL);
59 }
60
61 return(packet);
62 }
63
64 void
perdition_packet_destroy(perdition_packet_t * packet)65 perdition_packet_destroy(perdition_packet_t *packet)
66 {
67 if(!packet) {
68 return;
69 }
70 free(packet);
71 }
72
73 #define PACKET_STR_SET(buf, p_str) \
74 { \
75 perdition_packet_str_t str; \
76 str.length = p_str ? htons(p_str->length) : 0; \
77 memcpy(buf, &(str.length), sizeof(str.length)); \
78 buf += sizeof(str.length); \
79 if (str.length) { \
80 memcpy(buf, p_str->data, p_str->length); \
81 buf += p_str->length; \
82 } \
83 }
84
85
86 int
perdition_packet_init_v1_req(perdition_packet_t ** packet,uint16_t cs_type,uint32_t saddr,uint16_t sport,uint32_t daddr,uint16_t dport,perdition_packet_str_t * key,perdition_packet_str_t * domain_delimiter)87 perdition_packet_init_v1_req(perdition_packet_t **packet,
88 uint16_t cs_type,
89 uint32_t saddr, uint16_t sport,
90 uint32_t daddr, uint16_t dport,
91 perdition_packet_str_t *key,
92 perdition_packet_str_t *domain_delimiter)
93 {
94 char *buf;
95 perdition_packet_str_t str;
96 size_t body_len;
97
98 body_len = sizeof(str.length) + (key ? key->length : 0) +
99 sizeof(str.length) +
100 (domain_delimiter ? domain_delimiter->length : 0);
101
102 if(perdition_packet_init_v1_head(packet, cs_type, PERDITION_PACKET_REQ,
103 saddr, sport, daddr, dport, body_len) < 0) {
104 VANESSA_LOGGER_DEBUG("perdition_packet_init_v1_head");
105 return(-1);
106 }
107
108 buf = (*packet)->body;
109
110 /* Fill in Key */
111 PACKET_STR_SET(buf, key);
112 /* Fill in Domain Delimiter */
113 PACKET_STR_SET(buf, domain_delimiter);
114
115 return(0);
116 }
117
118 int
perdition_packet_init_v1_str_req(perdition_packet_t ** packet,uint16_t cs_type,perdition_packet_str_t * saddr,perdition_packet_str_t * sport,perdition_packet_str_t * daddr,perdition_packet_str_t * dport,perdition_packet_str_t * key,perdition_packet_str_t * domain_delimiter)119 perdition_packet_init_v1_str_req(perdition_packet_t **packet,
120 uint16_t cs_type,
121 perdition_packet_str_t *saddr,
122 perdition_packet_str_t *sport,
123 perdition_packet_str_t *daddr,
124 perdition_packet_str_t *dport,
125 perdition_packet_str_t *key,
126 perdition_packet_str_t *domain_delimiter)
127 {
128 char *buf;
129 perdition_packet_str_t str;
130 size_t body_len;
131
132 body_len = sizeof(str.length) + (saddr ? saddr->length : 0) +
133 sizeof(str.length) + (sport ? sport->length : 0) +
134 sizeof(str.length) + (daddr ? daddr->length : 0) +
135 sizeof(str.length) + (dport ? dport->length : 0) +
136 sizeof(str.length) + (key ? key->length : 0) +
137 sizeof(str.length) + (domain_delimiter ?
138 domain_delimiter->length : 0);
139
140 if(perdition_packet_init_v1_head(packet, cs_type,
141 PERDITION_PACKET_STR_REQ,
142 0, 0, 0, 0, body_len) < 0) {
143 VANESSA_LOGGER_DEBUG("perdition_packet_init_v1_head");
144 return -1;
145 }
146
147 buf = (*packet)->body;
148
149 /* Fill in Body */
150 PACKET_STR_SET(buf, key);
151 PACKET_STR_SET(buf, domain_delimiter);
152 PACKET_STR_SET(buf, saddr);
153 PACKET_STR_SET(buf, sport);
154 PACKET_STR_SET(buf, daddr);
155 PACKET_STR_SET(buf, dport);
156
157 return 0;
158 }
159
160 int
perdition_packet_init_v1_rsp(perdition_packet_t ** packet,uint16_t cs_type,perdition_packet_str_t * user,perdition_packet_str_t * server,perdition_packet_str_t * port)161 perdition_packet_init_v1_rsp(perdition_packet_t **packet,
162 uint16_t cs_type, perdition_packet_str_t *user,
163 perdition_packet_str_t *server,
164 perdition_packet_str_t *port)
165 {
166 char *buf;
167 perdition_packet_str_t str;
168 size_t body_len;
169
170 body_len = sizeof(str.length) + (user ? user->length : 0) +
171 sizeof(str.length) + (server ? server->length : 0) +
172 sizeof(str.length) + (port ? port->length : 0);
173
174 if(perdition_packet_init_v1_head(packet, cs_type, PERDITION_PACKET_RSP,
175 0, 0, 0, 0, body_len) < 0) {
176 VANESSA_LOGGER_DEBUG("perdition_packet_init_v1_head");
177 return(-1);
178 }
179 buf = (*packet)->body;
180
181 /* Fill in User */
182 PACKET_STR_SET(buf, user);
183 /* Fill in Server */
184 PACKET_STR_SET(buf, server);
185 /* Fill in Port */
186 PACKET_STR_SET(buf, port);
187
188 return(0);
189 }
190
191 static int
perdition_packet_init_v1_head(perdition_packet_t ** packet,uint16_t cs_type,uint16_t flags,uint32_t saddr,uint16_t sport,uint32_t daddr,uint16_t dport,size_t body_len)192 perdition_packet_init_v1_head(perdition_packet_t **packet,
193 uint16_t cs_type, uint16_t flags,
194 uint32_t saddr, uint16_t sport,
195 uint32_t daddr, uint16_t dport, size_t body_len)
196 {
197 if (cs_type != PERDITION_PACKET_CS_NONE) {
198 VANESSA_LOGGER_DEBUG("Only checksum type none is implemented");
199 return(-1);
200 }
201
202 if (body_len > PERDITION_PACKET_MAX_BODY_LEN) {
203 VANESSA_LOGGER_DEBUG("Strings supplied would overflow body");
204 return(-1);
205 }
206
207 if (!*packet) {
208 *packet = perdition_packet_create();
209 if (!*packet) {
210 VANESSA_LOGGER_DEBUG("perdition_packet_create");
211 return(-1);
212 }
213 }
214 else {
215 memset(*packet, 0, sizeof(perdition_packet_t));
216 }
217
218 /* Fill in Head */
219 (*packet)->head.magic = htonl(PERDITION_PACKET_MAGIC);
220 (*packet)->head.version = htons(PERDITION_PACKET_VERSION);
221 (*packet)->head.flags = htons(flags);
222 (*packet)->head.length = htons(sizeof(perdition_packet_head_t) +
223 body_len);
224 (*packet)->head.cs_type = htons(cs_type);
225 (*packet)->head.saddr = htonl(saddr);
226 (*packet)->head.sport = htons(sport);
227 (*packet)->head.daddr = htonl(daddr);
228 (*packet)->head.dport = htons(dport);
229
230 return(0);
231 }
232
packet_str_get(char * buf,perdition_packet_str_t * p_str)233 static size_t packet_str_get(char *buf, perdition_packet_str_t *p_str)
234 {
235 perdition_packet_str_t str;
236
237 memcpy(&str.length, buf, sizeof(str.length));
238 str.length = ntohs(str.length);
239
240 if (p_str) {
241 p_str->length = str.length;
242 if (p_str->length)
243 p_str->data = (unsigned char *) buf +
244 sizeof(str.length);
245 else
246 p_str->data = NULL;
247 }
248
249 return str.length + sizeof(str.length);
250 }
251
252 #define PACKET_STR_GET(buf, p_str) \
253 do { \
254 buf += packet_str_get(buf, p_str); \
255 } while (0)
256
257 int
perdition_packet_verify_v1_req(perdition_packet_t * packet,size_t len,perdition_packet_str_t * key,perdition_packet_str_t * domain_delimiter)258 perdition_packet_verify_v1_req(perdition_packet_t *packet,
259 size_t len, perdition_packet_str_t *key,
260 perdition_packet_str_t *domain_delimiter)
261 {
262 char *buf;
263
264 if(perdition_packet_verify_v1_head(packet, len) < 0) {
265 VANESSA_LOGGER_DEBUG("perdition_packet_verify_v1_head");
266 return(-1);
267 }
268
269 if(ntohs(packet->head.flags) != PERDITION_PACKET_REQ) {
270 VANESSA_LOGGER_DEBUG("Packet is not a request");
271 return(-1);
272 }
273
274 buf = packet->body;
275
276 /* Fill in Key */
277 PACKET_STR_GET(buf, key);
278 /* Fill in Domain Delimiter */
279 PACKET_STR_GET(buf, domain_delimiter);
280
281 if(perdition_packet_verify_v1_tail(packet, buf - packet->body) < 0) {
282 VANESSA_LOGGER_DEBUG("perdition_packet_verify_v1_head");
283 return(-1);
284 }
285
286 return(0);
287 }
288
289
290
291 int
perdition_packet_verify_v1_str_req(perdition_packet_t * packet,size_t len,perdition_packet_str_t * saddr,perdition_packet_str_t * sport,perdition_packet_str_t * daddr,perdition_packet_str_t * dport,perdition_packet_str_t * key,perdition_packet_str_t * domain_delimiter)292 perdition_packet_verify_v1_str_req(perdition_packet_t *packet, size_t len,
293 perdition_packet_str_t *saddr,
294 perdition_packet_str_t *sport,
295 perdition_packet_str_t *daddr,
296 perdition_packet_str_t *dport,
297 perdition_packet_str_t *key,
298 perdition_packet_str_t *domain_delimiter)
299 {
300 char *buf;
301
302 if (perdition_packet_verify_v1_head(packet, len) < 0) {
303 VANESSA_LOGGER_DEBUG("perdition_packet_verify_v1_head");
304 return -1;
305 }
306
307 if (ntohs(packet->head.flags) != PERDITION_PACKET_STR_REQ) {
308 VANESSA_LOGGER_DEBUG("Packet is not a string request");
309 return -1;
310 }
311
312 buf = packet->body;
313
314 PACKET_STR_GET(buf, key);
315 PACKET_STR_GET(buf, domain_delimiter);
316 PACKET_STR_GET(buf, saddr);
317 PACKET_STR_GET(buf, sport);
318 PACKET_STR_GET(buf, daddr);
319 PACKET_STR_GET(buf, dport);
320
321 if(perdition_packet_verify_v1_tail(packet, buf - packet->body) < 0) {
322 VANESSA_LOGGER_DEBUG("perdition_packet_verify_v1_head");
323 return -1;
324 }
325
326 return 0;
327 }
328
329
330 int
perdition_packet_verify_v1_rsp(perdition_packet_t * packet,size_t len,perdition_packet_str_t * user,perdition_packet_str_t * server,perdition_packet_str_t * port)331 perdition_packet_verify_v1_rsp(perdition_packet_t *packet,
332 size_t len, perdition_packet_str_t *user,
333 perdition_packet_str_t *server,
334 perdition_packet_str_t *port)
335 {
336 char *buf;
337
338 if(perdition_packet_verify_v1_head(packet, len) < 0) {
339 VANESSA_LOGGER_DEBUG("perdition_packet_verify_v1_head");
340 return(-1);
341 }
342
343 if(ntohs(packet->head.flags) != PERDITION_PACKET_RSP) {
344 VANESSA_LOGGER_DEBUG("Packet is not a response");
345 return(-1);
346 }
347
348 buf = packet->body;
349
350 /* Fill in Key */
351 PACKET_STR_GET(buf, user);
352 /* Fill in Server */
353 PACKET_STR_GET(buf, server);
354 /* Fill in Port */
355 PACKET_STR_GET(buf, port);
356
357 if(perdition_packet_verify_v1_tail(packet, buf - packet->body) < 0) {
358 VANESSA_LOGGER_DEBUG("perdition_packet_verify_v1_head");
359 return(-1);
360 }
361
362 return(0);
363 }
364
365
366 static int
perdition_packet_verify_v1_head(perdition_packet_t * packet,size_t len)367 perdition_packet_verify_v1_head(perdition_packet_t *packet, size_t len)
368 {
369 if (len < sizeof(perdition_packet_head_t)) {
370 VANESSA_LOGGER_DEBUG("Packet is too short to contain body");
371 return(-1);
372 }
373
374 if (packet->head.magic != htonl(PERDITION_PACKET_MAGIC)) {
375 VANESSA_LOGGER_DEBUG("Magic number missmatch");
376 return(-1);
377 }
378
379 if (len > PERDITION_PACKET_MAX_PACKET_LEN) {
380 VANESSA_LOGGER_DEBUG("Packet is too long");
381 return(-1);
382 }
383
384 if (len != ntohs(packet->head.length)) {
385 VANESSA_LOGGER_DEBUG_UNSAFE("Packet length missmatch. "
386 "Have %d bytes, header specifies %d bytes",
387 len, ntohs(packet->head.length));
388 }
389
390 if (packet->head.cs_type != PERDITION_PACKET_CS_NONE) {
391 VANESSA_LOGGER_DEBUG("Only checksum type none is implemented");
392 return(-1);
393 }
394
395 return(0);
396 }
397
398 static int
perdition_packet_verify_v1_tail(perdition_packet_t * packet,size_t body_len)399 perdition_packet_verify_v1_tail(perdition_packet_t *packet, size_t body_len)
400 {
401 if (body_len > PERDITION_PACKET_MAX_BODY_LEN) {
402 VANESSA_LOGGER_DEBUG("Strings supplied would overflow body");
403 return(-1);
404 }
405
406 if(body_len + sizeof(packet->head) != ntohs(packet->head.length)) {
407 VANESSA_LOGGER_DEBUG_UNSAFE("Length of strings in body does "
408 "not match length of packet."
409 "strings (%d) + head (%d) != %d",
410 body_len, sizeof(packet->head),
411 ntohs(packet->head.length));
412 return(-1);
413 }
414
415 return(0);
416 }
417