1 /* Copyright (C) 2000,2001 Salvatore Sanfilippo <antirez@invece.org>
2  * See the LICENSE file for more information.
3  *
4  * TODO:
5  * o Functions to add addresses and timestamps for some IP and TCP option
6  * o IGMP support
7  * o DNS support
8  * o ARS add_build_layer() facility and Co., read the PROPOSAL file.
9  */
10 
11 /* $Id: ars.c,v 1.3 2004/04/14 12:30:18 antirez Exp $ */
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <assert.h>
16 #include <string.h>
17 #include <sys/types.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
20 #include <netdb.h>
21 #include <unistd.h>
22 #include <stdarg.h>
23 
24 #include "ars.h"
25 
26 /* prototypes */
27 int ars_compiler_ip(struct ars_packet *pkt, int layer);
28 int ars_compiler_ipopt(struct ars_packet *pkt, int layer);
29 int ars_compiler_tcp(struct ars_packet *pkt, int layer);
30 int ars_compiler_tcpopt(struct ars_packet *pkt, int layer);
31 int ars_compiler_udp(struct ars_packet *pkt, int layer);
32 int ars_compiler_icmp(struct ars_packet *pkt, int layer);
33 int ars_compiler_igrp(struct ars_packet *pkt, int layer);
ars_compiler_abort(struct ars_packet * pkt,int layer)34 int ars_compiler_abort(struct ars_packet *pkt, int layer) { return 0; }
35 
36 /* Initialize a packets context:
37  * must be called before to work with the packet's layers */
ars_init(struct ars_packet * pkt)38 int ars_init(struct ars_packet *pkt)
39 {
40 	int j;
41 
42 	pkt->p_error = NULL;
43 	pkt->p_layer_nr = 0;
44 	pkt->p_options = 0;
45 	for (j = 0; j < ARS_MAX_LAYER; j++) {
46 		pkt->p_layer[j].l_size = 0;
47 		pkt->p_layer[j].l_flags = 0;
48 		pkt->p_layer[j].l_type = ARS_TYPE_NULL;
49 		pkt->p_layer[j].l_data = NULL;
50 		pkt->p_layer[j].l_packet = pkt;
51 	}
52 	for (j = 0; j < ARS_TYPE_SIZE; j++)
53 		pkt->p_default[j] = NULL;
54 	return -ARS_OK;
55 }
56 
57 /* Destroy (free the allocated memory) a packet context */
ars_destroy(struct ars_packet * pkt)58 int ars_destroy(struct ars_packet *pkt)
59 {
60 	int j;
61 
62 	free(pkt->p_error);
63 	for (j = 0; j < ARS_MAX_LAYER; j++) {
64 		if (pkt->p_layer[j].l_type != ARS_TYPE_NULL &&
65 		    pkt->p_layer[j].l_data != NULL)
66 			free(pkt->p_layer[j].l_data);
67 	}
68 	return ars_init(pkt); /* Re-initialize it */
69 }
70 
71 /* THe out of memory message must be statically allocated */
72 char *ars_error_nomem = "Out of memory";
73 
74 /* Set the error description */
ars_set_error(struct ars_packet * pkt,const char * fmt,...)75 int ars_set_error(struct ars_packet *pkt, const char *fmt, ...)
76 {
77 	va_list ap;
78 	char buf[ARS_ERR_BUFSZ];
79 
80 	if (pkt == NULL)
81 		return -ARS_OK;
82 
83 	va_start(ap, fmt);
84 	vsnprintf(buf, ARS_ERR_BUFSZ, fmt, ap);
85 	buf[ARS_ERR_BUFSZ-1] = '\0';
86 	va_end(ap);
87 	free(pkt->p_error); /* p_error is initialized to NULL */
88 	if ((pkt->p_error = strdup(buf)) == NULL) {
89 		/* To put the error description for the -KO_NOMEM
90 		 * error we needs a statically allocated error message:
91 		 * Note that all other functions don't need to report
92 		 * a statically allocated error message for -KO_NOMEM
93 		 * it will be auto-selected if strdup() returns NULL */
94 		pkt->p_error = ars_error_nomem;
95 	}
96 	return -ARS_OK; /* report anyway success */
97 }
98 
99 /* Set the default for a layer */
ars_set_default(struct ars_packet * pkt,int layer_type,void * def)100 int ars_set_default(struct ars_packet *pkt, int layer_type, void *def)
101 {
102 	pkt->p_default[layer_type] = def;
103 	return -ARS_OK;
104 }
105 
106 /* return nonzero if the packet is full */
ars_nospace(struct ars_packet * pkt)107 int ars_nospace(struct ars_packet *pkt)
108 {
109 	return (pkt->p_layer_nr == ARS_MAX_LAYER);
110 }
111 
112 /* Check if the layer number is valid */
ars_valid_layer(int layer)113 int ars_valid_layer(int layer)
114 {
115 	if (layer < 0 || layer >= ARS_MAX_LAYER)
116 		return -ARS_INVALID;
117 	return -ARS_OK;
118 }
119 
120 /* Add an a generic layer */
ars_add_generic(struct ars_packet * pkt,size_t size,int type)121 int ars_add_generic(struct ars_packet *pkt, size_t size, int type)
122 {
123 	int layer;
124 
125 	if (ars_nospace(pkt)) {
126 		ars_set_error(pkt, "No space for the next layer");
127 		return -ARS_NOSPACE;
128 	}
129 	layer = pkt->p_layer_nr;
130 	/* You may want to create a 0 len layer and then realloc */
131 	if (size != 0) {
132 		pkt->p_layer[layer].l_data = malloc(size);
133 		if (pkt->p_layer[layer].l_data == NULL) {
134 			ars_set_error(pkt, "Out of memory adding a new layer");
135 			return -ARS_NOMEM;
136 		}
137 		memset(pkt->p_layer[layer].l_data, 0, size);
138 		/* Copy the default if any */
139 		if (pkt->p_default[type] != NULL) {
140 			memcpy(pkt->p_layer[layer].l_data,
141 			       pkt->p_default[type], size);
142 		}
143 	}
144 	pkt->p_layer[layer].l_type = type;
145 	pkt->p_layer[layer].l_size = size;
146 	return -ARS_OK;
147 }
148 
149 /* Add an IP layer */
ars_add_iphdr(struct ars_packet * pkt,int unused)150 void *ars_add_iphdr(struct ars_packet *pkt, int unused)
151 {
152 	int retval;
153 
154 	retval = ars_add_generic(pkt, sizeof(struct ars_iphdr), ARS_TYPE_IP);
155 	if (retval != -ARS_OK)
156 		return NULL;
157 	pkt->p_layer_nr++;
158 	return pkt->p_layer[pkt->p_layer_nr-1].l_data;
159 }
160 
161 /* Add on IP option */
ars_add_ipopt(struct ars_packet * pkt,int option)162 void *ars_add_ipopt(struct ars_packet *pkt, int option)
163 {
164 	int retval;
165 	struct ars_ipopt *ipopt;
166 	int opt_len;
167 
168 	switch(option) {
169 	case ARS_IPOPT_END:
170 	case ARS_IPOPT_NOOP:
171 		opt_len = 1;
172 		break;
173 	case ARS_IPOPT_SEC:
174 		opt_len = 11;
175 		break;
176 	case ARS_IPOPT_SID:
177 		opt_len = 4;
178 		break;
179 	case ARS_IPOPT_LSRR:
180 	case ARS_IPOPT_SSRR:
181 	case ARS_IPOPT_RR:
182 	case ARS_IPOPT_TIMESTAMP:
183 		/* We allocate the max (40 bytes) but the real layer size
184 		 * may be modified by ars_ipopt_set*() functions */
185 		opt_len = 40;
186 		break;
187 	default:
188 		return NULL; /* Unsupported option */
189 		break;
190 	}
191 
192 	retval = ars_add_generic(pkt, opt_len, ARS_TYPE_IPOPT);
193 	if (retval != -ARS_OK)
194 		return NULL;
195 	ipopt = pkt->p_layer[pkt->p_layer_nr].l_data;
196 	pkt->p_layer_nr++;
197 
198 	ipopt->kind = option;
199 	/* END and NOOP hasn't the length byte */
200 	if (option == ARS_IPOPT_END || option == ARS_IPOPT_NOOP)
201 		return ipopt;
202 	ipopt->len = opt_len; /* the default, can be modified inside switch() */
203 	/* Perform some special operation for some option */
204 	switch(option) {
205 	case ARS_IPOPT_LSRR: /* ars_ipopt_setls() will change some field */
206 	case ARS_IPOPT_SSRR: /* ars_ipopt_setss() will change some field */
207 	case ARS_IPOPT_RR:   /* ars_ipopt_setrr() will change some field */
208 		/* RFC 791 needs the roomlen - 3 octects, so the gateways
209 		 * can compare len and ptr to check for room.
210 		 * Try to break this to stress lame TCP/IP implementation */
211 		ipopt->len = opt_len - 2 - 3;
212 		ipopt->un.rr.ptr = 4;
213 		break;
214 	case ARS_IPOPT_TIMESTAMP:
215 		ipopt->len = opt_len - 2 - 4;
216 		ipopt->un.ts.ptr = 5;
217 		ipopt->un.ts.flags = ARS_IPOPT_TS_TSONLY; /* default */
218 		break;
219 	}
220 	return ipopt;
221 }
222 
223 /* Add a UDP layer */
ars_add_udphdr(struct ars_packet * pkt,int unused)224 void *ars_add_udphdr(struct ars_packet *pkt, int unused)
225 {
226 	int retval;
227 
228 	retval = ars_add_generic(pkt, sizeof(struct ars_udphdr), ARS_TYPE_UDP);
229 	if (retval != -ARS_OK)
230 		return NULL;
231 	pkt->p_layer_nr++;
232 	return pkt->p_layer[pkt->p_layer_nr-1].l_data;
233 }
234 
235 /* Add a TCP layer */
ars_add_tcphdr(struct ars_packet * pkt,int unused)236 void *ars_add_tcphdr(struct ars_packet *pkt, int unused)
237 {
238 	int retval;
239 
240 	retval = ars_add_generic(pkt, sizeof(struct ars_tcphdr), ARS_TYPE_TCP);
241 	if (retval != -ARS_OK)
242 		return NULL;
243 	pkt->p_layer_nr++;
244 	return pkt->p_layer[pkt->p_layer_nr-1].l_data;
245 }
246 
247 /* Add TCP options */
ars_add_tcpopt(struct ars_packet * pkt,int option)248 void *ars_add_tcpopt(struct ars_packet *pkt, int option)
249 {
250 	int retval;
251 	struct ars_tcpopt *tcpopt;
252 	int opt_len;
253 
254 	switch(option) {
255 	case ARS_TCPOPT_NOP:
256 	case ARS_TCPOPT_EOL:
257 		opt_len = 1;
258 		break;
259 	case ARS_TCPOPT_MAXSEG:
260 		opt_len = 4;
261 		break;
262 	case ARS_TCPOPT_WINDOW:
263 		opt_len = 3;
264 		break;
265 	case ARS_TCPOPT_SACK_PERM:
266 		opt_len = 2;
267 		break;
268 	case ARS_TCPOPT_SACK:
269 		opt_len = 8*4+2;
270 		break;
271 	case ARS_TCPOPT_ECHOREQUEST:
272 	case ARS_TCPOPT_ECHOREPLY:
273 		opt_len = 6;
274 		break;
275 	case ARS_TCPOPT_TIMESTAMP:
276 		opt_len = 10;
277 		break;
278 	default:
279 		return NULL; /* Unsupported option */
280 		break;
281 	}
282 
283 	retval = ars_add_generic(pkt, opt_len, ARS_TYPE_TCPOPT);
284 	if (retval != -ARS_OK)
285 		return NULL;
286 	tcpopt = pkt->p_layer[pkt->p_layer_nr].l_data;
287 	pkt->p_layer_nr++;
288 
289 	tcpopt->kind = option;
290 	/* EOL and NOP lacks the len field */
291 	if (option != ARS_TCPOPT_EOL && option != ARS_TCPOPT_NOP)
292 		tcpopt->len = opt_len;
293 
294 	/* Perform some special operation for the option */
295 	switch(option) {
296 	case ARS_TCPOPT_ECHOREQUEST:
297 	case ARS_TCPOPT_ECHOREPLY:
298 		memset(tcpopt->un.echo.info, 0, 4);
299 		break;
300 	case ARS_TCPOPT_TIMESTAMP:
301 		memset(tcpopt->un.timestamp.tsval, 0, 4);
302 		memset(tcpopt->un.timestamp.tsecr, 0, 4);
303 		break;
304 	}
305 	return tcpopt;
306 }
307 
308 /* Add an ICMP layer */
ars_add_icmphdr(struct ars_packet * pkt,int unused)309 void *ars_add_icmphdr(struct ars_packet *pkt, int unused)
310 {
311 	int retval;
312 	struct ars_icmphdr *icmp;
313 
314 	retval = ars_add_generic(pkt, sizeof(struct ars_icmphdr),ARS_TYPE_ICMP);
315 	if (retval != -ARS_OK)
316 		return NULL;
317 	icmp = pkt->p_layer[pkt->p_layer_nr].l_data;
318 	icmp->type = ARS_ICMP_ECHO;
319 	icmp->code = 0;
320 	pkt->p_layer_nr++;
321 	return (struct ars_icmphdr*) pkt->p_layer[pkt->p_layer_nr-1].l_data;
322 }
323 
324 /* Add an IGRP layer */
ars_add_igrphdr(struct ars_packet * pkt,int unused)325 void *ars_add_igrphdr(struct ars_packet *pkt, int unused)
326 {
327 	int retval;
328 	struct ars_igrphdr *igrp;
329 
330 	retval = ars_add_generic(pkt, sizeof(struct ars_igrphdr),ARS_TYPE_IGRP);
331 	if (retval != -ARS_OK)
332 		return NULL;
333 	igrp = pkt->p_layer[pkt->p_layer_nr].l_data;
334 	igrp->opcode = ARS_IGRP_OPCODE_REQUEST;
335 	igrp->version = 1;
336 	igrp->edition = 0;
337 	igrp->autosys = 0;
338 	igrp->interior = 0;
339 	igrp->system = 0;
340 	igrp->exterior = 0;
341 	pkt->p_layer_nr++;
342 	return pkt->p_layer[pkt->p_layer_nr-1].l_data;
343 }
344 
345 /* Add an IGRP entry */
ars_add_igrpentry(struct ars_packet * pkt,int unused)346 void *ars_add_igrpentry(struct ars_packet *pkt, int unused)
347 {
348 	int retval;
349 
350 	retval = ars_add_generic(pkt, sizeof(struct ars_igrpentry),ARS_TYPE_IGRPENTRY);
351 	if (retval != -ARS_OK)
352 		return NULL;
353 	pkt->p_layer_nr++;
354 	return pkt->p_layer[pkt->p_layer_nr-1].l_data;
355 }
356 
357 /* Add data, for IP-RAW, TCP, UDP, and so on */
ars_add_data(struct ars_packet * pkt,int size)358 void *ars_add_data(struct ars_packet *pkt, int size)
359 {
360 	int retval;
361 	static void *ptr = "zzappt"; /* we can't return NULL for size == 0 */
362 
363 	if (size < 0) {
364 		ars_set_error(pkt, "Tryed to add a DATA layer with size < 0");
365 		return NULL;
366 	}
367 	retval = ars_add_generic(pkt, size, ARS_TYPE_DATA);
368 	if (retval != -ARS_OK)
369 		return NULL;
370 	pkt->p_layer_nr++;
371 	if (size > 0)
372 		return pkt->p_layer[pkt->p_layer_nr-1].l_data;
373 	else
374 		return ptr;
375 }
376 
377 /* Remove a layer */
ars_remove_layer(struct ars_packet * pkt,int layer)378 int ars_remove_layer(struct ars_packet *pkt, int layer)
379 {
380 	if (layer == ARS_LAST_LAYER)
381 		layer = pkt->p_layer_nr -1;
382 	if (ars_valid_layer(layer) != -ARS_OK)
383 		return -ARS_INVALID;
384 
385 	free(pkt->p_layer[layer].l_data); /* No problem if it's NULL */
386 	pkt->p_layer[layer].l_type = ARS_TYPE_NULL;
387 	pkt->p_layer[layer].l_size = 0;
388 	pkt->p_layer[layer].l_flags = 0;
389 	pkt->p_layer[layer].l_data = NULL;
390 	pkt->p_layer[layer].l_packet = pkt;
391 	return -ARS_OK;
392 }
393 
394 /* Return the sum of the size of the specifed layer and of all the
395  * following layers */
ars_relative_size(struct ars_packet * pkt,int layer_nr)396 size_t ars_relative_size(struct ars_packet *pkt, int layer_nr)
397 {
398 	int j = layer_nr, rel_size = 0;
399 
400 	while (j < ARS_MAX_LAYER && pkt->p_layer[j].l_type != ARS_TYPE_NULL) {
401 		rel_size += pkt->p_layer[j].l_size;
402 		j++;
403 	}
404 	return rel_size;
405 }
406 
407 /* Just a short cut for ars_relative_size(), to get the total size */
ars_packet_size(struct ars_packet * pkt)408 size_t ars_packet_size(struct ars_packet *pkt)
409 {
410 	return ars_relative_size(pkt, 0);
411 }
412 
413 /* from R. Stevens's Network Programming */
ars_cksum(void * vbuf,size_t nbytes)414 u_int16_t ars_cksum(void *vbuf, size_t nbytes)
415 {
416 	u_int16_t *buf = (u_int16_t*) vbuf;
417 	u_int32_t sum;
418 	u_int16_t oddbyte;
419 
420 	sum = 0;
421 	while (nbytes > 1) {
422 		sum += *buf++;
423 		nbytes -= 2;
424 	}
425 	if (nbytes == 1) {
426 		oddbyte = 0;
427 		*((u_int16_t *) &oddbyte) = *(u_int16_t *) buf;
428 		sum += oddbyte;
429 	}
430 	sum = (sum >> 16) + (sum & 0xffff);
431 	sum += (sum >> 16);
432 	return (u_int16_t) ~sum;
433 }
434 
435 /* Multiple buffers checksum facility */
ars_multi_cksum(struct mc_context * c,int op,void * vbuf,size_t nbytes)436 u_int16_t ars_multi_cksum(struct mc_context *c, int op, void *vbuf,
437 							size_t nbytes)
438 {
439 	u_int16_t *buf = (u_int16_t*) vbuf;
440 	u_int32_t sum;
441 	u_int16_t oddbyte;
442 	void *tmp;
443 
444 	if (op == ARS_MC_INIT) {
445 		c->oddbyte_flag = 0;
446 		c->old = 0;
447 		return -ARS_OK;
448 	} else if (op == ARS_MC_UPDATE) {
449 		if (c->oddbyte_flag) {
450 			u_int8_t *x = (u_int8_t*)&oddbyte;
451 			oddbyte = 0;
452 			*((u_int16_t *) &oddbyte) = c->oddbyte << 8;
453 			*((u_int16_t *) &oddbyte) |= *(u_int16_t *) buf;
454 			oddbyte = (x[0] << 8) | x[1]; /* fix endianess */
455 			c->old += oddbyte;
456 			nbytes--;
457 			c->oddbyte_flag = 0;
458 			/* We need to stay aligned -- bad slowdown, fix? */
459 			tmp = alloca(nbytes);
460 			memcpy(tmp, vbuf+1, nbytes);
461 			buf = tmp;
462 		}
463 		sum = c->old;
464 		while (nbytes > 1) {
465 			sum += *buf++;
466 			nbytes -= 2;
467 		}
468 		c->old = sum;
469 		if (nbytes == 1) {
470 			c->oddbyte = *(u_int16_t*) buf;
471 			c->oddbyte_flag++;
472 		}
473 		return -ARS_OK;
474 	} else if (op == ARS_MC_FINAL) {
475 		sum = c->old;
476 		if (c->oddbyte_flag == 1) {
477 			oddbyte = 0;
478 			*((u_int16_t *) &oddbyte) = c->oddbyte;
479 			sum += oddbyte;
480 		}
481 		sum = (sum >> 16) + (sum & 0xffff);
482 		sum += (sum >> 16);
483 		return (u_int16_t) ~sum;
484 	} else {
485 		assert("else reached in ars_multi_cksum()" == "");
486 	}
487 	return 0; /* unreached, here to prevent warnings */
488 }
489 
490 /* The ARS compiler table is just a function pointers array:
491  * For example to select the right function to compile an IP
492  * layer use: ars_compiler[ARS_TYPE_IP](pkt, layer);
493  * You can, of course, add your protocols and compilers:
494  *
495  * WARNING: take it syncronized with ars.h ARS_TYPE_* defines
496  */
497 struct ars_layer_info ars_linfo[ARS_TYPE_SIZE] = {
498 /* NAME			COMPILER		ID *
499  * ----                 --------                -- */
500 { "NULL",		ars_compiler_abort,	NULL,			0 },
501 { "IP",			ars_compiler_ip,	ars_rapd_ip,		1 },
502 { "IPOPT",		ars_compiler_ipopt,	ars_rapd_ipopt,		2 },
503 { "ICMP",		ars_compiler_icmp,	ars_rapd_icmp,		3 },
504 { "UDP",		ars_compiler_udp,	ars_rapd_udp,		4 },
505 { "TCP",		ars_compiler_tcp,	ars_rapd_tcp,		5 },
506 { "TCPOPT",		ars_compiler_tcpopt,	ars_rapd_tcpopt,	6 },
507 { "IGRP", 		ars_compiler_igrp,	ars_rapd_igrp,		7 },
508 { "IGRPENTRY",		NULL,			ars_rapd_igrpentry,	8 },
509 { NULL, NULL, NULL, 9 },
510 { NULL, NULL, NULL, 10 },
511 { NULL, NULL, NULL, 11 },
512 { NULL, NULL, NULL, 12 },
513 { NULL, NULL, NULL, 13 },
514 { NULL, NULL, NULL, 14 },
515 { NULL, NULL, NULL, 15 },
516 { NULL, NULL, NULL, 16 },
517 { NULL, NULL, NULL, 17 },
518 { NULL, NULL, NULL, 18 },
519 { NULL, NULL, NULL, 19 },
520 { NULL, NULL, NULL, 20 },
521 { NULL, NULL, NULL, 21 },
522 { NULL, NULL, NULL, 22 },
523 { NULL, NULL, NULL, 23 },
524 { NULL, NULL, NULL, 24 },
525 { NULL, NULL, NULL, 25 },
526 { NULL, NULL, NULL, 26 },
527 { NULL, NULL, NULL, 27 },
528 { NULL, NULL, NULL, 28 },
529 { NULL, NULL, NULL, 29 },
530 { NULL, NULL, NULL, 30 },
531 { "DATA",		NULL,			ars_rapd_data,		31 }
532 };
533 
534 /* This function call the right compiler for all the layers of the packet:
535  * A compiler just set the protocol fields like the checksum, len, and so on
536  * accordly to the following layers.
537  * Note that the layers are compiled from the last to the first, to ensure
538  * that the checksum and other dependences are sane. */
ars_compile(struct ars_packet * pkt)539 int ars_compile(struct ars_packet *pkt)
540 {
541 	int j, err;
542 
543 	for (j = pkt->p_layer_nr - 1; j >= 0; j--) {
544 		__D(printf("Compiling layer %d\n", j);)
545 		/* Skip NULL compilers */
546 		if (ars_linfo[pkt->p_layer[j].l_type].li_compiler != NULL) {
547 			/* Call the compiler */
548 			err = ars_linfo[pkt->p_layer[j].l_type].li_compiler(pkt, j);
549 			if (err != -ARS_OK)
550 				return err;
551 		}
552 	}
553 	return -ARS_OK;
554 }
555 
556 /* The IP compiler: probably the more complex, but still simple */
ars_compiler_ip(struct ars_packet * pkt,int layer)557 int ars_compiler_ip(struct ars_packet *pkt, int layer)
558 {
559 	struct ars_iphdr *ip = pkt->p_layer[layer].l_data;
560 	int j = layer, err;
561 	int flags = pkt->p_layer[layer].l_flags;
562 	int ipoptlen = 0;
563 	struct mc_context mc; /* multi-buffer checksum context */
564 
565 	/* IP version */
566 	if (ARS_DONTTAKE(flags, ARS_TAKE_IP_VERSION))
567 		ip->version = 4;
568 	/* IP header len */
569 	if (ARS_DONTTAKE(flags, ARS_TAKE_IP_HDRLEN)) {
570 		ip->ihl = (ARS_IPHDR_SIZE >> 2);
571 		/* Add IP options len */
572 		for (j = layer+1; j < ARS_MAX_LAYER; j++) {
573 			if (pkt->p_layer[j].l_type != ARS_TYPE_IPOPT)
574 				break;
575 			ipoptlen += pkt->p_layer[j].l_size;
576 		}
577 		ip->ihl += ipoptlen >> 2;
578 	}
579 	/* IP tot len */
580 	if (ARS_DONTTAKE(flags, ARS_TAKE_IP_TOTLEN))
581 		ip->tot_len = htons(ars_relative_size(pkt, layer));
582 	/* IP protocol field */
583 	if (ARS_DONTTAKE(flags, ARS_TAKE_IP_PROTOCOL)) {
584 		ip->protocol = ARS_IPPROTO_RAW; /* This is the default */
585 		while (j < ARS_MAX_LAYER) {
586 			if (pkt->p_layer[j].l_type == ARS_TYPE_IPOPT) {
587 				j++;
588 				continue;
589 			}
590 			switch(pkt->p_layer[j].l_type) {
591 			case ARS_TYPE_IP:
592 				ip->protocol = ARS_IPPROTO_IPIP;
593 				break;
594 			case ARS_TYPE_ICMP:
595 				ip->protocol = ARS_IPPROTO_ICMP;
596 				break;
597 			case ARS_TYPE_UDP:
598 				ip->protocol = ARS_IPPROTO_UDP;
599 				break;
600 			case ARS_TYPE_TCP:
601 				ip->protocol = ARS_IPPROTO_TCP;
602 				break;
603 			case ARS_TYPE_IGRP:
604 				ip->protocol = ARS_IPPROTO_IGRP;
605 				break;
606 			}
607 			break;
608 		}
609 	}
610 	/* We always calculate the IP checksum, since the kernel
611 	 * do it only for the first IP header in the datagram */
612 	if (ARS_DONTTAKE(flags, ARS_TAKE_IP_CKSUM)) {
613 		ip->check = 0;
614 		ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);
615 		err = ars_multi_cksum(&mc, ARS_MC_UPDATE, ip, ARS_IPHDR_SIZE);
616 		if (err != -ARS_OK)
617 			return err;
618 		for (j = layer+1; j < ARS_MAX_LAYER; j++) {
619 			if (pkt->p_layer[j].l_type != ARS_TYPE_IPOPT)
620 				break;
621 			err = ars_multi_cksum(&mc, ARS_MC_UPDATE,
622 						pkt->p_layer[j].l_data,
623 						pkt->p_layer[j].l_size);
624 			if  (err != -ARS_OK)
625 				return err;
626 		}
627 		ip->check = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0);
628 	}
629 	return -ARS_OK;
630 }
631 
632 /* The ip options compiler: do just option padding with NOP options */
ars_compiler_ipopt(struct ars_packet * pkt,int layer)633 int ars_compiler_ipopt(struct ars_packet *pkt, int layer)
634 {
635 	int j, opt_size;
636 
637 	/* Padding is needed only in the last IP option */
638 	if (layer != ARS_MAX_LAYER-1 &&
639 	    pkt->p_layer[layer+1].l_type == ARS_TYPE_IPOPT)
640 		return ARS_OK;
641 
642 	/* Search the layer of the relative first IP option */
643 	j = layer - 1; /* We know that 'layer' is an IP option */
644 	while (j < ARS_MAX_LAYER && j >= 0 &&
645 	       pkt->p_layer[j].l_type == ARS_TYPE_IPOPT)
646 		j--;
647 	j++;
648 	__D(printf("First IP OPTION layer is %d\n", j);)
649 	opt_size = ars_relative_size(pkt, j) - ars_relative_size(pkt, layer+1);
650 	__D(printf("IP OPTION size %d\n", opt_size);)
651 	if (opt_size % 4) {
652 		int padding = 4 - (opt_size % 4);
653 		unsigned char *t;
654 		int cur_size = pkt->p_layer[layer].l_size;
655 
656 		__D(printf("IP OPTION at layer %d needs %d bytes "
657 			   "of padding\n", layer, padding);)
658 		t = realloc(pkt->p_layer[layer].l_data, cur_size + padding);
659 		if (t == NULL) {
660 			ars_set_error(pkt, "Out of memory padding IP options");
661 			return -ARS_NOMEM;
662 		}
663 		memset(t+cur_size, ARS_IPOPT_NOP, padding);
664 		__D(printf("The last IP OPTION length was: %d\n", cur_size);)
665 		pkt->p_layer[layer].l_data = t;
666 		pkt->p_layer[layer].l_size += padding;
667 		__D(printf("After padding it is: %d\n", pkt->p_layer[layer].l_size);)
668 	}
669 	return -ARS_OK;
670 }
671 
672 /* Compute the UDP and TCP checksum using the pseudoheader.
673  * Note that this functions automatically care about TCP/UDP data.
674  * FIXME: this doesn't work when the IP source address is 0.0.0.0 */
ars_udptcp_cksum(struct ars_packet * pkt,int layer,u_int16_t * sum)675 int ars_udptcp_cksum(struct ars_packet *pkt, int layer, u_int16_t *sum)
676 {
677 	struct ars_iphdr *ip;
678 	struct ars_pseudohdr pseudo;
679 	struct mc_context mc; /* multi-buffer checksum context */
680 	int j = layer - 1, err;
681 
682 	/* search the first IP layer on the left:
683 	 * it returns an error if between the IP and
684 	 * the TCP layer there aren't just IPOPT layers:
685 	 * even with malformed packets this does not
686 	 * makes sense. */
687 	while (j > 0 && pkt->p_layer[j].l_type == ARS_TYPE_IPOPT)
688 		j--;
689 	if (pkt->p_layer[j].l_type != ARS_TYPE_IP) {
690 		ars_set_error(pkt, "TCP/UDP checksum requested, but IP header "
691 				    "not found");
692 		return -ARS_INVALID;
693 	}
694 	ip = pkt->p_layer[j].l_data;
695 	memset(&pseudo, 0, sizeof(pseudo)); /* actually not needed */
696 	/* Copy the src and dst IP address */
697 	memcpy(&pseudo.saddr, &ip->saddr, 4);
698 	memcpy(&pseudo.daddr, &ip->daddr, 4);
699 	pseudo.protocol = (pkt->p_layer[layer].l_type == ARS_TYPE_TCP)
700 		? ARS_IPPROTO_TCP : ARS_IPPROTO_UDP;
701 	pseudo.lenght = htons(ars_relative_size(pkt, layer));
702 
703 	/* Finally do the checksum */
704 	ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);
705 	err = ars_multi_cksum(&mc, ARS_MC_UPDATE, &pseudo, sizeof(pseudo));
706 	if (err != -ARS_OK)
707 		return err;
708 	for (j = layer; j < ARS_MAX_LAYER; j++) {
709 		if (pkt->p_layer[j].l_type == ARS_TYPE_NULL)
710 			break;
711 		err = ars_multi_cksum(&mc, ARS_MC_UPDATE,
712 					pkt->p_layer[j].l_data,
713 					pkt->p_layer[j].l_size);
714 		if  (err != -ARS_OK)
715 			return err;
716 	}
717 	*sum = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0);
718 	return -ARS_OK;
719 }
720 
721 /* The tcp compiler */
ars_compiler_tcp(struct ars_packet * pkt,int layer)722 int ars_compiler_tcp(struct ars_packet *pkt, int layer)
723 {
724 	struct ars_tcphdr *tcp = pkt->p_layer[layer].l_data;
725 	int j, err, tcpoptlen = 0;
726 	int flags = pkt->p_layer[layer].l_flags;
727 
728 	if (ARS_DONTTAKE(flags, ARS_TAKE_TCP_HDRLEN)) {
729 		tcp->th_off = ARS_TCPHDR_SIZE >> 2;
730 		/* Add the len of the options */
731 		for (j = layer+1; j < ARS_MAX_LAYER; j++) {
732 			if (pkt->p_layer[j].l_type != ARS_TYPE_TCPOPT)
733 				break;
734 			tcpoptlen += pkt->p_layer[j].l_size;
735 		}
736 		tcp->th_off += tcpoptlen >> 2;
737 	}
738 	if (ARS_DONTTAKE(flags, ARS_TAKE_TCP_CKSUM)) {
739 		tcp->th_sum = 0;
740 		err = ars_udptcp_cksum(pkt, layer, &tcp->th_sum);
741 		if (err != -ARS_OK)
742 			return err;
743 	}
744 	return -ARS_OK;
745 }
746 
747 /* The tcp options compiler: do just option padding with NOP options */
ars_compiler_tcpopt(struct ars_packet * pkt,int layer)748 int ars_compiler_tcpopt(struct ars_packet *pkt, int layer)
749 {
750 	int j, opt_size;
751 
752 	/* Padding is needed only in the last TCP option */
753 	if (layer != ARS_MAX_LAYER-1 &&
754 	    pkt->p_layer[layer+1].l_type == ARS_TYPE_TCPOPT)
755 		return ARS_OK;
756 
757 	/* Search the layer of the relative first TCP option */
758 	j = layer - 1; /* We know that 'layer' is a tcp option */
759 	while (j < ARS_MAX_LAYER && j >= 0 &&
760 	       pkt->p_layer[j].l_type == ARS_TYPE_TCPOPT)
761 		j--;
762 	j++;
763 	__D(printf("First TCP OPTION layer is %d\n", j);)
764 	opt_size = ars_relative_size(pkt, j) - ars_relative_size(pkt, layer+1);
765 	__D(printf("TCP OPTION size %d\n", opt_size);)
766 	if (opt_size % 4) {
767 		int padding = 4 - (opt_size % 4);
768 		unsigned char *t;
769 		int cur_size = pkt->p_layer[layer].l_size;
770 
771 		__D(printf("TCP OPTION at layer %d needs %d bytes "
772 			   "of padding\n", layer, padding);)
773 		t = realloc(pkt->p_layer[layer].l_data, cur_size + padding);
774 		if (t == NULL) {
775 			ars_set_error(pkt, "Out of memory padding TCP options");
776 			return -ARS_NOMEM;
777 		}
778 		memset(t+cur_size, ARS_TCPOPT_NOP, padding);
779 		pkt->p_layer[layer].l_size += padding;
780 	}
781 	return -ARS_OK;
782 }
783 
784 /* The udp compiler, very simple */
ars_compiler_udp(struct ars_packet * pkt,int layer)785 int ars_compiler_udp(struct ars_packet *pkt, int layer)
786 {
787 	struct ars_udphdr *udp = pkt->p_layer[layer].l_data;
788 	int err;
789 	int flags = pkt->p_layer[layer].l_flags;
790 
791 	if (ARS_DONTTAKE(flags, ARS_TAKE_UDP_LEN))
792 		udp->uh_ulen = htons(ars_relative_size(pkt, layer));
793 
794 	if (ARS_DONTTAKE(flags, ARS_TAKE_UDP_CKSUM)) {
795 		udp->uh_sum = 0;
796 		err = ars_udptcp_cksum(pkt, layer, &udp->uh_sum);
797 		if (err != -ARS_OK)
798 			return err;
799 	}
800 	return -ARS_OK;
801 }
802 
803 /* The icmp compiler, just compute the checksum */
ars_compiler_icmp(struct ars_packet * pkt,int layer)804 int ars_compiler_icmp(struct ars_packet *pkt, int layer)
805 {
806 	struct ars_icmphdr *icmp = pkt->p_layer[layer].l_data;
807 	struct mc_context mc; /* multi-buffer checksum context */
808 	int err, j;
809 	int flags = pkt->p_layer[layer].l_flags;
810 
811 	if (ARS_DONTTAKE(flags, ARS_TAKE_ICMP_CKSUM)) {
812 		icmp->checksum = 0;
813 		ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);
814 		for (j = layer; j < ARS_MAX_LAYER; j++) {
815 			if (pkt->p_layer[j].l_type == ARS_TYPE_NULL)
816 				break;
817 			err = ars_multi_cksum(&mc, ARS_MC_UPDATE,
818 						pkt->p_layer[j].l_data,
819 						pkt->p_layer[j].l_size);
820 			if  (err != -ARS_OK)
821 				return err;
822 		}
823 		icmp->checksum = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0);
824 	}
825 	return -ARS_OK;
826 }
827 
828 /* The igrp compiler, just compute the checksum */
ars_compiler_igrp(struct ars_packet * pkt,int layer)829 int ars_compiler_igrp(struct ars_packet *pkt, int layer)
830 {
831 	struct ars_igrphdr *igrp = pkt->p_layer[layer].l_data;
832 	struct mc_context mc; /* multi-buffer checksum context */
833 	int err, j;
834 	int flags = pkt->p_layer[layer].l_flags;
835 
836 	if (ARS_DONTTAKE(flags, ARS_TAKE_IGRP_CKSUM)) {
837 		igrp->checksum = 0;
838 		ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);
839 		for (j = layer; j < ARS_MAX_LAYER; j++) {
840 			if (pkt->p_layer[j].l_type == ARS_TYPE_NULL)
841 				break;
842 			err = ars_multi_cksum(&mc, ARS_MC_UPDATE,
843 						pkt->p_layer[j].l_data,
844 						pkt->p_layer[j].l_size);
845 			if  (err != -ARS_OK)
846 				return err;
847 		}
848 		igrp->checksum = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0);
849 	}
850 	return -ARS_OK;
851 }
852 
853 /* Open a raw socket, ready for IP header creation and broadcast addresses */
ars_open_rawsocket(struct ars_packet * pkt)854 int ars_open_rawsocket(struct ars_packet *pkt)
855 {
856 	int s;
857 	const int one = 1;
858 
859 	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) {
860 		ars_set_error(pkt, "Can't open the raw socket");
861 		return -ARS_ERROR;
862 	}
863 	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&one,
864 		sizeof(one)) == -1 ||
865 	    setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char*)&one,
866 		sizeof(one)) == -1)
867 	{
868 		close(s);
869 		ars_set_error(pkt, "Can't set socket options");
870 		return -ARS_ERROR;
871 	}
872 	return s;
873 }
874 
875 /* Create the packets using the layers. This function is often called
876  * after the layers compilation. Note that since the packet created
877  * is sane the strange-rawsocket-behaviour of some *BSD will not
878  * be able to send this packet. Use the function ars_bsd_fix() to fix it.
879  * WARNING: The packets returned is malloc()ated, free it */
ars_build_packet(struct ars_packet * pkt,unsigned char ** packet,size_t * size)880 int ars_build_packet(struct ars_packet *pkt, unsigned char **packet, size_t *size)
881 {
882 	size_t tot_size, offset = 0;
883 	int j = 0;
884 
885 	if ((tot_size = ars_packet_size(pkt)) == 0) {
886 		ars_set_error(pkt, "Total size 0 building the packet");
887 		return -ARS_INVALID;
888 	}
889 	if ((*packet = malloc(tot_size)) == NULL) {
890 		ars_set_error(pkt, "Out of memory building the packet");
891 		return -ARS_NOMEM;
892 	}
893 	while (j < ARS_MAX_LAYER && pkt->p_layer[j].l_type != ARS_TYPE_NULL) {
894 		memcpy((*packet)+offset, pkt->p_layer[j].l_data,
895 					 pkt->p_layer[j].l_size);
896 		offset += pkt->p_layer[j].l_size;
897 		j++;
898 	}
899 	*size = tot_size;
900 	return -ARS_OK;
901 }
902 
903 /* FreeBSD and NetBSD have a strange raw socket layer :(
904  * Call this function anyway to increase portability
905  * since it does not perform any operation if the
906  * system isn't FreeBSD or NetBSD. */
ars_bsd_fix(struct ars_packet * pkt,unsigned char * packet,size_t size)907 int ars_bsd_fix(struct ars_packet *pkt, unsigned char *packet, size_t size)
908 {
909 	struct ars_iphdr *ip;
910 
911 	if (pkt->p_layer[0].l_type != ARS_TYPE_IP ||
912 	    size < sizeof(struct ars_iphdr)) {
913 		ars_set_error(pkt, "BSD fix requested, but layer 0 not IP");
914 		return -ARS_INVALID;
915 	}
916 	ip = (struct ars_iphdr*) packet;
917 #if defined OSTYPE_FREEBSD || defined OSTYPE_DRAGONFLY || defined OSTYPE_NETBSD || defined OSTYPE_BSDI
918 	ip->tot_len = ntohs(ip->tot_len);
919 	ip->frag_off = ntohs(ip->frag_off);
920 #endif
921 	return -ARS_OK;
922 }
923 
924 /* Set the flags for some layer: if layer == -1 the last layer will be used */
ars_set_flags(struct ars_packet * pkt,int layer,int flags)925 int ars_set_flags(struct ars_packet *pkt, int layer, int flags)
926 {
927 	if (layer == ARS_LAST_LAYER)
928 		layer = pkt->p_layer_nr - 1;
929 	if (layer < 0 || layer >= ARS_MAX_LAYER) {
930 		ars_set_error(pkt, "Invalid layer setting layer flags");
931 		return -ARS_INVALID;
932 	}
933 	pkt->p_layer[layer].l_flags = flags;
934 	return -ARS_OK;
935 }
936 
937 /* Build, fix, and send the packet */
ars_send(int s,struct ars_packet * pkt,struct sockaddr * sa,socklen_t slen)938 int ars_send(int s, struct ars_packet *pkt, struct sockaddr *sa, socklen_t slen)
939 {
940 	struct sockaddr_in sain;
941 	struct sockaddr *_sa = sa;
942 	unsigned char *packet;
943 	size_t size;
944 	int error;
945 
946 	/* Perform the socket address completion if sa == NULL */
947 	if (sa == NULL) {
948 		struct ars_iphdr *ip;
949 
950 		memset(&sain, 0, sizeof(sain));
951 		sain.sin_family = AF_INET;
952 		/* The first layer MUST be IP if the user requested
953 		 * the socket address completion */
954 		if (pkt->p_layer[0].l_type != ARS_TYPE_IP) {
955 			ars_set_error(pkt, "socket address completion"
956 				"requested, but layer 0 isn't IP");
957 			return -ARS_ERROR;
958 		}
959 		ip = (struct ars_iphdr*) pkt->p_layer[0].l_data;
960 		memcpy(&sain.sin_addr.s_addr, &ip->daddr, 4);
961 		_sa = (struct sockaddr*) &sain;
962 		slen = sizeof(sain);
963 	}
964 	if ((error = ars_build_packet(pkt, &packet, &size)) != ARS_OK)
965 		return error;
966 	if ((error = ars_bsd_fix(pkt, packet, size)) != ARS_OK)
967 		return error;
968 	error = sendto(s, packet, size, 0, _sa, slen);
969 	free(packet);
970 	return (error != -1) ? -ARS_OK : -ARS_ERROR;
971 }
972 
973 /* Resolve an hostname and write to 'dest' the IP */
ars_resolve(struct ars_packet * pkt,u_int32_t * dest,char * hostname)974 int ars_resolve(struct ars_packet *pkt, u_int32_t *dest, char *hostname)
975 {
976 	struct sockaddr_in sa;
977 
978 	if (inet_aton(hostname, &sa.sin_addr) == 0) {
979 		struct hostent *he;
980 		he = gethostbyname(hostname);
981 		if (he == NULL) {
982 			ars_set_error(pkt, "Can't resolve the hostname");
983 			return -ARS_ERROR;
984 		}
985 		sa.sin_addr.s_addr = ((struct in_addr*) he->h_addr)->s_addr;
986 	}
987 	memcpy(dest, &sa.sin_addr.s_addr, sizeof(u_int32_t));
988 	return -ARS_OK;
989 }
990