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