⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ars.c

📁 VC++源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 2000,2001 Salvatore Sanfilippo <antirez@invece.org> * See the LICENSE file for more information. *  * TODO: * o Functions to add addresses and timestamps for some IP and TCP option * o IGMP support * o DNS support * o ARS add_build_layer() facility and Co., read the PROPOSAL file. *//* $Id: ars.c,v 1.4 2003/07/28 09:00:54 njombart Exp $ */#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <string.h>#include <sys/types.h>#ifndef WIN32#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#else#include <winsock2.h>#include <ws2tcpip.h>#endif#include <unistd.h>#include "ars.h"/* prototypes */int ars_compiler_ip(struct ars_packet *pkt, int layer);int ars_compiler_ipopt(struct ars_packet *pkt, int layer);int ars_compiler_tcp(struct ars_packet *pkt, int layer);int ars_compiler_tcpopt(struct ars_packet *pkt, int layer);int ars_compiler_udp(struct ars_packet *pkt, int layer);int ars_compiler_icmp(struct ars_packet *pkt, int layer);int ars_compiler_abort(struct ars_packet *pkt, int layer) { return 0; }/* Initialize a packets context: * must be called before to work with the packet's layers */int ars_init(struct ars_packet *pkt){	int j;	pkt->p_error = NULL;	pkt->p_layer_nr = 0;	for (j = 0; j < ARS_MAX_LAYER; j++) {		pkt->p_layer[j].l_size = 0;		pkt->p_layer[j].l_flags = 0;		pkt->p_layer[j].l_type = ARS_TYPE_NULL;		pkt->p_layer[j].l_data = NULL;		pkt->p_layer[j].l_packet = pkt;	}	for (j = 0; j < ARS_TYPE_SIZE; j++)		pkt->p_default[j] = NULL;	return -ARS_OK;}/* Destroy (free the allocated memory) a packet context */int ars_destroy(struct ars_packet *pkt){	int j;	free(pkt->p_error);	for (j = 0; j < ARS_MAX_LAYER; j++) {		if (pkt->p_layer[j].l_type != ARS_TYPE_NULL &&		    pkt->p_layer[j].l_data != NULL)			free(pkt->p_layer[j].l_data);	}	return ars_init(pkt); /* Re-initialize it */}/* THe out of memory message must be statically allocated */char *ars_error_nomem = "Out of memory";/* Set the error description */int ars_set_error(struct ars_packet *pkt, char *error){	if (pkt == NULL)		return -ARS_OK;	free(pkt->p_error); /* p_error is initialized to NULL */	if ((pkt->p_error = strdup(error)) == NULL) {		/* To put the error description for the -KO_NOMEM		 * error we needs a statically allocated error message:		 * Note that all other functions don't need to report		 * a statically allocated error message for -KO_NOMEM		 * it will be auto-selected if strdup() returns NULL */		pkt->p_error = ars_error_nomem;	}	return -ARS_OK; /* report anyway success */}/* Set the default for a layer */int ars_set_default(struct ars_packet *pkt, int layer_type, void *def){	pkt->p_default[layer_type] = def;	return -ARS_OK;}/* return nonzero if the packet is full */int ars_nospace(struct ars_packet *pkt){	return (pkt->p_layer_nr == ARS_MAX_LAYER);}/* Check if the layer number is valid */int ars_valid_layer(int layer){	if (layer < 0 || layer >= ARS_MAX_LAYER)		return -ARS_INVALID;	return -ARS_OK;}/* Add an a generic layer */int ars_add_generic(struct ars_packet *pkt, size_t size, int type){	int layer;	if (ars_nospace(pkt)) {		ars_set_error(pkt, "No space for the next layer");		return -ARS_NOSPACE;	}	layer = pkt->p_layer_nr;	/* You may want to create a 0 len layer and then realloc */	if (size != 0) {		pkt->p_layer[layer].l_data = malloc(size);		if (pkt->p_layer[layer].l_data == NULL) {			ars_set_error(pkt, "Out of memory adding a new layer");			return -ARS_NOMEM;		}		memset(pkt->p_layer[layer].l_data, 0, size);		/* Copy the default if any */		if (pkt->p_default[type] != NULL) {			memcpy(pkt->p_layer[layer].l_data,			       pkt->p_default[type], size);		}	}	pkt->p_layer[layer].l_type = type;	pkt->p_layer[layer].l_size = size;	return -ARS_OK;}/* Add an IP layer */void *ars_add_iphdr(struct ars_packet *pkt, int unused){	int retval;	retval = ars_add_generic(pkt, sizeof(struct ars_iphdr), ARS_TYPE_IP);	if (retval != -ARS_OK)		return NULL;	pkt->p_layer_nr++;	return pkt->p_layer[pkt->p_layer_nr-1].l_data;}/* Add on IP option */void *ars_add_ipopt(struct ars_packet *pkt, int option){	int retval;	struct ars_ipopt *ipopt;	int opt_len;	switch(option) {	case ARS_IPOPT_END:	case ARS_IPOPT_NOOP:		opt_len = 1;		break;	case ARS_IPOPT_SEC:		opt_len = 11;		break;	case ARS_IPOPT_SID:		opt_len = 4;		break;	case ARS_IPOPT_LSRR:	case ARS_IPOPT_SSRR:	case ARS_IPOPT_RR:	case ARS_IPOPT_TIMESTAMP:		/* We allocate the max (40 bytes) but the real layer size		 * may be modified by ars_ipopt_set*() functions */		opt_len = 40;		break;	default:		return NULL; /* Unsupported option */		break;	}	retval = ars_add_generic(pkt, opt_len, ARS_TYPE_IPOPT);	if (retval != -ARS_OK)		return NULL;	ipopt = pkt->p_layer[pkt->p_layer_nr].l_data;	pkt->p_layer_nr++;	ipopt->kind = option;	ipopt->len = opt_len; /* the default, can be modified inside switch() */	/* Perform some special operation for some option */	switch(option) {	case ARS_IPOPT_LSRR: /* ars_ipopt_setls() will change some field */	case ARS_IPOPT_SSRR: /* ars_ipopt_setss() will change some field */	case ARS_IPOPT_RR:   /* ars_ipopt_setrr() will change some field */		/* RFC 791 needs the roomlen - 3 octects, so the gateways		 * can compare len and ptr to check for room.		 * Try to break this to stress lame TCP/IP implementation */		ipopt->len = opt_len - 2 - 3;		ipopt->un.rr.ptr = 4;		break;	case ARS_IPOPT_TIMESTAMP:		ipopt->un.tstamp.ptr = 5;		ipopt->un.tstamp.flags = ARS_IPOPT_TS_TSONLY; /* default */		break;	}	return ipopt;}/* Add a UDP layer */void *ars_add_udphdr(struct ars_packet *pkt, int unused){	int retval;	retval = ars_add_generic(pkt, sizeof(struct ars_udphdr), ARS_TYPE_UDP);	if (retval != -ARS_OK)		return NULL;	pkt->p_layer_nr++;	return pkt->p_layer[pkt->p_layer_nr-1].l_data;}/* Add a TCP layer */void *ars_add_tcphdr(struct ars_packet *pkt, int unused){	int retval;	retval = ars_add_generic(pkt, sizeof(struct ars_tcphdr), ARS_TYPE_TCP);	if (retval != -ARS_OK)		return NULL;	pkt->p_layer_nr++;	return pkt->p_layer[pkt->p_layer_nr-1].l_data;}/* Add TCP options */void *ars_add_tcpopt(struct ars_packet *pkt, int option){	int retval;	struct ars_tcpopt *tcpopt;	int opt_len;	switch(option) {	case ARS_TCPOPT_NOP:	case ARS_TCPOPT_EOL:		opt_len = 1;		break;	case ARS_TCPOPT_MAXSEG:		opt_len = 4;		break;	case ARS_TCPOPT_WINDOW:		opt_len = 3;		break;	case ARS_TCPOPT_SACK_PERM: /* ars_tcpopt_setsack() must change this */	case ARS_TCPOPT_SACK:		opt_len = 2;		break;	case ARS_TCPOPT_ECHOREQUEST:	case ARS_TCPOPT_ECHOREPLY:		opt_len = 6;		break;	case ARS_TCPOPT_TIMESTAMP:		opt_len = 10;		break;	default:		return NULL; /* Unsupported option */		break;	}	retval = ars_add_generic(pkt, opt_len, ARS_TYPE_TCPOPT);	if (retval != -ARS_OK)		return NULL;	tcpopt = pkt->p_layer[pkt->p_layer_nr].l_data;	pkt->p_layer_nr++;	tcpopt->kind = option;	/* EOL and NOP lacks the len field */	if (option != ARS_TCPOPT_EOL && option != ARS_TCPOPT_NOP)		tcpopt->len = opt_len;	/* Perform some special operation for the option */	switch(option) {	case ARS_TCPOPT_ECHOREQUEST:	case ARS_TCPOPT_ECHOREPLY:		memset(tcpopt->un.echo.info, 0, 4);		break;	case ARS_TCPOPT_TIMESTAMP:		memset(tcpopt->un.timestamp.tsval, 0, 4);		memset(tcpopt->un.timestamp.tsecr, 0, 4);		break;	}	return tcpopt;}/* Add an ICMP layer */void *ars_add_icmphdr(struct ars_packet *pkt, int unused){	int retval;	struct ars_icmphdr *icmp;	retval = ars_add_generic(pkt, sizeof(struct ars_icmphdr),ARS_TYPE_ICMP);	if (retval != -ARS_OK)		return NULL;	icmp = pkt->p_layer[pkt->p_layer_nr].l_data;	pkt->p_layer_nr++;	return (struct ars_icmphdr*) pkt->p_layer[pkt->p_layer_nr-1].l_data;}/* Add data, for IP-RAW, TCP, UDP, and so on */void *ars_add_data(struct ars_packet *pkt, int size){	int retval;	void *boguspointer = "zzappt"; /* we can't return NULL for size == 0 */	if (size < 0) {		ars_set_error(pkt, "Tryed to add a DATA layer with size < 0");		return NULL;	}	retval = ars_add_generic(pkt, size, ARS_TYPE_DATA);	if (retval != -ARS_OK)		return NULL;	pkt->p_layer_nr++;	if (size > 0)		return pkt->p_layer[pkt->p_layer_nr-1].l_data;	else		return boguspointer;}/* Remove a layer */int ars_remove_layer(struct ars_packet *pkt, int layer){	if (layer == ARS_LAST_LAYER)		layer = pkt->p_layer_nr -1;	if (ars_valid_layer(layer) != -ARS_OK)		return -ARS_INVALID;	free(pkt->p_layer[layer].l_data); /* No problem if it's NULL */	pkt->p_layer[layer].l_type = ARS_TYPE_NULL;	pkt->p_layer[layer].l_size = 0;	pkt->p_layer[layer].l_flags = 0;	pkt->p_layer[layer].l_data = NULL;	pkt->p_layer[layer].l_packet = pkt;	return -ARS_OK;}/* Return the sum of the size of the specifed layer and of all the * following layers */size_t ars_relative_size(struct ars_packet *pkt, int layer_nr){	int j = layer_nr, rel_size = 0;	while (j < ARS_MAX_LAYER && pkt->p_layer[j].l_type != ARS_TYPE_NULL) {		rel_size += pkt->p_layer[j].l_size;		j++;	}	return rel_size;}/* Just a short cut for ars_relative_size(), to get the total size */size_t ars_packet_size(struct ars_packet *pkt){	return ars_relative_size(pkt, 0);}/* from R. Stevens's Network Programming */u_int16_t ars_cksum(void *vbuf, size_t nbytes){	u_int16_t *buf = (u_int16_t*) vbuf;	u_int32_t sum;	u_int16_t oddbyte;	sum = 0;	while (nbytes > 1) {		sum += *buf++;		nbytes -= 2;	}	if (nbytes == 1) {		oddbyte = 0;		*((u_int16_t *) &oddbyte) = *(u_int8_t *) buf;		sum += oddbyte;	}	sum = (sum >> 16) + (sum & 0xffff);	sum += (sum >> 16);	return (u_int16_t) ~sum;}/* Multiple buffers checksum facility */u_int16_t ars_multi_cksum(struct mc_context *c, int op, void *vbuf,							size_t nbytes){	u_int16_t *buf = (u_int16_t*) vbuf;	u_int32_t sum;	u_int16_t oddbyte;	void *tmp;	if (op == ARS_MC_INIT) {		c->oddbyte_flag = 0;		c->old = 0;		return -ARS_OK;	} else if (op == ARS_MC_UPDATE) {		if (c->oddbyte_flag) {			u_int8_t *x = (u_int8_t*)&oddbyte;			oddbyte = 0;			*((u_int16_t *) &oddbyte) = c->oddbyte << 8;			*((u_int16_t *) &oddbyte) |= *(u_int8_t *) buf;			oddbyte = (x[0] << 8) | x[1]; /* fix endianess */			c->old += oddbyte;			nbytes--;			c->oddbyte_flag = 0;			/* We need to stay aligned -- bad slowdown, fix? */			tmp = alloca(nbytes);			memcpy(tmp, vbuf+1, nbytes);			buf = tmp;		}		sum = c->old;		while (nbytes > 1) {			sum += *buf++;			nbytes -= 2;		}		c->old = sum;		if (nbytes == 1) {			c->oddbyte = *(u_int8_t*) buf;			c->oddbyte_flag++;		}		return -ARS_OK;	} else if (op == ARS_MC_FINAL) {		sum = c->old;		if (c->oddbyte_flag == 1) {			oddbyte = 0;			*((u_int16_t *) &oddbyte) = c->oddbyte;			sum += oddbyte;		}		sum = (sum >> 16) + (sum & 0xffff);		sum += (sum >> 16);		return (u_int16_t) ~sum;	} else {		assert("else reached in ars_multi_cksum()" == "");	}	return 0; /* unreached, here to prevent warnings */}/* The ARS compiler table is just a function pointers array: * For example to select the right function to compile an IP * layer use: ars_compiler[ARS_TYPE_IP](pkt, layer); * You can, of course, add your protocols and compilers: * * WARNING: take it syncronized with ars.h ARS_TYPE_* defines */struct ars_layer_info ars_linfo[ARS_TYPE_SIZE] = {	/* NAME			COMPILER		ID *	 * ----                 --------                -- */	{ "NULL",		ars_compiler_abort,	0 },	{ "IP",			ars_compiler_ip,	1 },	{ "IPOPT",		ars_compiler_ipopt,	2 },	{ "ICMP",		ars_compiler_icmp,	3 },	{ "UDP",		ars_compiler_udp,	4 },

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -