File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / hping2 / ars.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:11:37 2012 UTC (12 years, 3 months ago) by misho
Branches: hping2, MAIN
CVS tags: v2_0_0rc3p7, v2_0_0rc3p5, v2_0_0rc3p4, v2_0_0rc3p0, v2_0_0rc3, HEAD
hping2

    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.1.1.1 2012/02/21 22:11:37 misho 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>