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

📄 ars.c

📁 VC++源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	{ "TCP",		ars_compiler_tcp,	5 },	{ "TCPOPT",		ars_compiler_tcpopt,	6 },	{ NULL, NULL, 7 },	{ NULL, NULL, 8 },	{ NULL, NULL, 9 },	{ NULL, NULL, 10 },	{ NULL, NULL, 11 },	{ NULL, NULL, 12 },	{ NULL, NULL, 13 },	{ NULL, NULL, 14 },	{ NULL, NULL, 15 },	{ NULL, NULL, 16 },	{ NULL, NULL, 17 },	{ NULL, NULL, 18 },	{ NULL, NULL, 19 },	{ NULL, NULL, 20 },	{ NULL, NULL, 21 },	{ NULL, NULL, 22 },	{ NULL, NULL, 23 },	{ NULL, NULL, 24 },	{ NULL, NULL, 25 },	{ NULL, NULL, 26 },	{ NULL, NULL, 27 },	{ NULL, NULL, 28 },	{ NULL, NULL, 29 },	{ NULL, NULL, 30 },	{ "DATA",		NULL,			31 }};/* This function call the right compiler for all the layers of the packet: * A compiler just set the protocol fields like the checksum, len, and so on * accordly to the following layers. * Note that the layers are compiled from the last to the first, to ensure * that the checksum and other dependences are sane. */int ars_compile(struct ars_packet *pkt){	int j, err;	for (j = pkt->p_layer_nr - 1; j >= 0; j--) {		__D(printf("Compiling layer %d\n", j);)		/* Skip NULL compilers */		if (ars_linfo[pkt->p_layer[j].l_type].li_compiler != NULL) {			/* Call the compiler */			err = ars_linfo[pkt->p_layer[j].l_type].li_compiler(pkt, j);			if (err != -ARS_OK)				return err;		}	}	return -ARS_OK;}/* The IP compiler: probably the more complex, but still simple */int ars_compiler_ip(struct ars_packet *pkt, int layer){	struct ars_iphdr *ip = pkt->p_layer[layer].l_data;	int j = layer, err;	int flags = pkt->p_layer[layer].l_flags;	int ipoptlen = 0;	struct mc_context mc; /* multi-buffer checksum context */	/* IP version */	if (ARS_DONTTAKE(flags, ARS_TAKE_IP_VERSION))		ip->version = 4;	/* IP header len */	if (ARS_DONTTAKE(flags, ARS_TAKE_IP_HDRLEN)) {		ip->ihl = (ARS_IPHDR_SIZE >> 2);		/* Add IP options len */		for (j = layer+1; j < ARS_MAX_LAYER; j++) {			if (pkt->p_layer[j].l_type != ARS_TYPE_IPOPT)				break;			ipoptlen += pkt->p_layer[j].l_size; 		}		ip->ihl += ipoptlen >> 2;	}	/* IP tot len */	if (ARS_DONTTAKE(flags, ARS_TAKE_IP_TOTLEN))		ip->tot_len = htons(ars_relative_size(pkt, layer));	/* IP protocol field */	if (ARS_DONTTAKE(flags, ARS_TAKE_IP_PROTOCOL)) {		ip->protocol = ARS_IPPROTO_RAW; /* This is the default */		while (j < ARS_MAX_LAYER) {			if (pkt->p_layer[j].l_type == ARS_TYPE_IPOPT) {				j++;				continue;			}			switch(pkt->p_layer[j].l_type) {			case ARS_TYPE_IP:				ip->protocol = ARS_IPPROTO_IPIP;				break;			case ARS_TYPE_ICMP:				ip->protocol = ARS_IPPROTO_ICMP;				break;			case ARS_TYPE_UDP:				ip->protocol = ARS_IPPROTO_UDP;				break;			case ARS_TYPE_TCP:				ip->protocol = ARS_IPPROTO_TCP;				break;			}			break;		}	}	/* We always calculate the IP checksum, since the kernel	 * do it only for the first IP header in the datagram */	if (ARS_DONTTAKE(flags, ARS_TAKE_IP_CKSUM)) {		ip->check = 0;		ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);		err = ars_multi_cksum(&mc, ARS_MC_UPDATE, ip, ARS_IPHDR_SIZE);		if (err != -ARS_OK)			return err;		for (j = layer+1; j < ARS_MAX_LAYER; j++) {			if (pkt->p_layer[j].l_type != ARS_TYPE_IPOPT)				break;			err = ars_multi_cksum(&mc, ARS_MC_UPDATE,						pkt->p_layer[j].l_data,						pkt->p_layer[j].l_size);			if  (err != -ARS_OK)				return err;		}		ip->check = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0);	}	return -ARS_OK;}/* The ip options compiler: do just option padding with NOP options */int ars_compiler_ipopt(struct ars_packet *pkt, int layer){	int j, opt_size;	/* Padding is needed only in the last IP option */	if (layer != ARS_MAX_LAYER-1 &&	    pkt->p_layer[layer+1].l_type == ARS_TYPE_IPOPT)		return ARS_OK;	/* Search the layer of the relative first TCP option */	j = layer - 1; /* We know that 'layer' is a tcp option */	while (j < ARS_MAX_LAYER && j >= 0 &&	       pkt->p_layer[j].l_type == ARS_TYPE_IPOPT)		j--;	j++;	__D(printf("First IP OPTION layer is %d\n", j);)	opt_size = ars_relative_size(pkt, j) - ars_relative_size(pkt, layer+1);	__D(printf("IP OPTION size %d\n", opt_size);)	if (opt_size % 4) {		int padding = 4 - (opt_size % 4);		unsigned char *t;		int cur_size = pkt->p_layer[layer].l_size;		__D(printf("IP OPTION at layer %d needs %d bytes "			   "of padding\n", layer, padding);)		t = realloc(pkt->p_layer[layer].l_data, cur_size + padding);		if (t == NULL) {			ars_set_error(pkt, "Out of memory padding IP options");			return -ARS_NOMEM;		}		memset(t+cur_size, ARS_IPOPT_NOP, padding);		pkt->p_layer[layer].l_size += padding;	}	return -ARS_OK;}/* Compute the UDP and TCP checksum using the pseudoheader. * Note that this functions automatically care about TCP/UDP data */int ars_udptcp_cksum(struct ars_packet *pkt, int layer, u_int16_t *sum){	struct ars_iphdr *ip;	struct ars_pseudohdr pseudo;	struct mc_context mc; /* multi-buffer checksum context */	int j = layer - 1, err;	/* search the first IP layer on the left:	 * it returns an error if between the IP and	 * the TCP layer there aren't just IPOPT layers:	 * even with malformed packets this does not	 * makes sense. */	while (j > 0 && pkt->p_layer[j].l_type == ARS_TYPE_IPOPT)		j--;	if (pkt->p_layer[j].l_type != ARS_TYPE_IP) {		ars_set_error(pkt, "TCP/UDP checksum requested, but IP header "				    "not found");		return -ARS_INVALID;	}	ip = pkt->p_layer[j].l_data;	memset(&pseudo, 0, sizeof(pseudo)); /* actually not needed */	/* Copy the src and dst IP address */	memcpy(&pseudo.saddr, &ip->saddr, 4);	memcpy(&pseudo.daddr, &ip->daddr, 4);	pseudo.protocol = (pkt->p_layer[layer].l_type == ARS_TYPE_TCP)		? ARS_IPPROTO_TCP : ARS_IPPROTO_UDP;	pseudo.lenght = htons(ars_relative_size(pkt, layer));	/* Finally do the checksum */	ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);	err = ars_multi_cksum(&mc, ARS_MC_UPDATE, &pseudo, sizeof(pseudo));	if (err != -ARS_OK)		return err;	for (j = layer; j < ARS_MAX_LAYER; j++) {		if (pkt->p_layer[j].l_type == ARS_TYPE_NULL)			break;		err = ars_multi_cksum(&mc, ARS_MC_UPDATE,					pkt->p_layer[j].l_data,					pkt->p_layer[j].l_size);		if  (err != -ARS_OK)			return err;	}	*sum = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0);	return -ARS_OK;}/* The tcp compiler */int ars_compiler_tcp(struct ars_packet *pkt, int layer){	struct ars_tcphdr *tcp = pkt->p_layer[layer].l_data;	int j, err, tcpoptlen = 0;	int flags = pkt->p_layer[layer].l_flags;	if (ARS_DONTTAKE(flags, ARS_TAKE_TCP_HDRLEN)) {		tcp->th_off = ARS_TCPHDR_SIZE >> 2;		/* Add the len of the options */		for (j = layer+1; j < ARS_MAX_LAYER; j++) {			if (pkt->p_layer[j].l_type != ARS_TYPE_TCPOPT)				break;			tcpoptlen += pkt->p_layer[j].l_size;		}		tcp->th_off += tcpoptlen >> 2;	}	if (ARS_DONTTAKE(flags, ARS_TAKE_TCP_CKSUM)) {		tcp->th_sum = 0;		err = ars_udptcp_cksum(pkt, layer, &tcp->th_sum);		if (err != -ARS_OK)			return err;	}	return -ARS_OK;}/* The tcp options compiler: do just option padding with NOP options */int ars_compiler_tcpopt(struct ars_packet *pkt, int layer){	int j, opt_size;	/* Padding is needed only in the last TCP option */	if (layer != ARS_MAX_LAYER-1 &&	    pkt->p_layer[layer+1].l_type == ARS_TYPE_TCPOPT)		return ARS_OK;	/* Search the layer of the relative first TCP option */	j = layer - 1; /* We know that 'layer' is a tcp option */	while (j < ARS_MAX_LAYER && j >= 0 &&	       pkt->p_layer[j].l_type == ARS_TYPE_TCPOPT)		j--;	j++;	__D(printf("First TCP OPTION layer is %d\n", j);)	opt_size = ars_relative_size(pkt, j) - ars_relative_size(pkt, layer+1);	__D(printf("TCP OPTION size %d\n", opt_size);)	if (opt_size % 4) {		int padding = 4 - (opt_size % 4);		unsigned char *t;		int cur_size = pkt->p_layer[layer].l_size;		__D(printf("TCP OPTION at layer %d needs %d bytes "			   "of padding\n", layer, padding);)		t = realloc(pkt->p_layer[layer].l_data, cur_size + padding);		if (t == NULL) {			ars_set_error(pkt, "Out of memory padding TCP options");			return -ARS_NOMEM;		}		memset(t+cur_size, ARS_TCPOPT_NOP, padding);		pkt->p_layer[layer].l_size += padding;	}	return -ARS_OK;}/* The udp compiler, very simple */int ars_compiler_udp(struct ars_packet *pkt, int layer){	struct ars_udphdr *udp = pkt->p_layer[layer].l_data;	int err;	int flags = pkt->p_layer[layer].l_flags;	if (ARS_DONTTAKE(flags, ARS_TAKE_UDP_LEN))		udp->uh_ulen = htons(ars_relative_size(pkt, layer));	if (ARS_DONTTAKE(flags, ARS_TAKE_UDP_CKSUM)) {		udp->uh_sum = 0;		err = ars_udptcp_cksum(pkt, layer, &udp->uh_sum);		if (err != -ARS_OK)			return err;	}	return -ARS_OK;}/* The icmp compiler, just compute the checksum */int ars_compiler_icmp(struct ars_packet *pkt, int layer){	struct ars_icmphdr *icmp = pkt->p_layer[layer].l_data;	struct mc_context mc; /* multi-buffer checksum context */	int err, j;	int flags = pkt->p_layer[layer].l_flags;	if (ARS_DONTTAKE(flags, ARS_TAKE_ICMP_CKSUM)) {		icmp->checksum = 0;		ars_multi_cksum(&mc, ARS_MC_INIT, NULL, 0);		for (j = layer; j < ARS_MAX_LAYER; j++) {			if (pkt->p_layer[j].l_type == ARS_TYPE_NULL)				break;			err = ars_multi_cksum(&mc, ARS_MC_UPDATE,						pkt->p_layer[j].l_data,						pkt->p_layer[j].l_size);			if  (err != -ARS_OK)				return err;		}		icmp->checksum = ars_multi_cksum(&mc, ARS_MC_FINAL, NULL, 0);	}	return -ARS_OK;}/* Open a raw socket, ready for IP header creation and broadcast addresses */int ars_open_rawsocket(struct ars_packet *pkt){	int s;	const int one = 1;	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) {		ars_set_error(pkt, "Can't open the raw socket");		return -ARS_ERROR;	}	if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&one,		sizeof(one)) == -1 ||	    setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char*)&one,		sizeof(one)) == -1)	{		close(s);		ars_set_error(pkt, "Can't set socket options");		return -ARS_ERROR;	}	return s;}/* Create the packets using the layers. This function is often called * after the layers compilation. Note that since the packet created * is sane the strange-rawsocket-behaviour of some *BSD will not * be able to send this packet. Use the function ars_bsd_fix() to fix it. * WARNING: The packets returned is malloc()ated, free it */int ars_build_packet(struct ars_packet *pkt, unsigned char **packet, size_t *size){	size_t tot_size, offset = 0;	int j = 0;	if ((tot_size = ars_packet_size(pkt)) == 0) {		ars_set_error(pkt, "Total size 0 building the packet");		return -ARS_INVALID;	}	if ((*packet = malloc(tot_size)) == NULL) {		ars_set_error(pkt, "Out of memory building the packet");		return -ARS_NOMEM;	}	while (j < ARS_MAX_LAYER && pkt->p_layer[j].l_type != ARS_TYPE_NULL) {		memcpy((*packet)+offset, pkt->p_layer[j].l_data,					 pkt->p_layer[j].l_size);		offset += pkt->p_layer[j].l_size;		j++;	}	*size = tot_size;	return -ARS_OK;}/* FreeBSD and NetBSD have a strange raw socket layer :( * Call this function anyway to increase portability * since it does not perform any operation if the * system isn't FreeBSD or NetBSD. */int ars_bsd_fix(struct ars_packet *pkt, unsigned char *packet, size_t size){	struct ars_iphdr *ip;	if (pkt->p_layer[0].l_type != ARS_TYPE_IP ||	    size < sizeof(struct ars_iphdr)) {		ars_set_error(pkt, "BSD fix requested, but layer 0 not IP");		return -ARS_INVALID;	}	ip = (struct ars_iphdr*) packet;#if defined OSTYPE_FREEBSD || defined OSTYPE_NETBSD || defined OSTYPE_BSDI	ip->tot_len = ntohs(ip->tot_len);	ip->frag_off = ntohs(ip->frag_off);#endif	return -ARS_OK;}/* Set the flags for some layer: if layer == -1 the last layer will be used */int ars_set_flags(struct ars_packet *pkt, int layer, int flags){	if (layer == ARS_LAST_LAYER)		layer = pkt->p_layer_nr - 1;	if (layer < 0 || layer >= ARS_MAX_LAYER) {		ars_set_error(pkt, "Invalid layer setting layer flags");		return -ARS_INVALID;	}	pkt->p_layer[layer].l_flags = flags;	return -ARS_OK;}/* Build, fix, and send the packet */int ars_send(int s, struct ars_packet *pkt, struct sockaddr *sa, socklen_t slen){	struct sockaddr_in sain;	struct sockaddr *_sa = sa;	unsigned char *packet;	size_t size;	int error;	/* Perform the socket address completion if sa == NULL */	if (sa == NULL) {		struct ars_iphdr *ip;		memset(&sain, 0, sizeof(sain));		sain.sin_family = AF_INET;		/* The first layer MUST be IP if the user requested		 * the socket address completion */		if (pkt->p_layer[0].l_type != ARS_TYPE_IP) {			ars_set_error(pkt, "socket address completion"				"requested, but layer 0 isn't IP");			return -ARS_ERROR;		}		ip = (struct ars_iphdr*) pkt->p_layer[0].l_data;		memcpy(&sain.sin_addr.s_addr, &ip->daddr, 4);		_sa = (struct sockaddr*) &sain;		slen = sizeof(sain);	}	if ((error = ars_build_packet(pkt, &packet, &size)) != ARS_OK)		return error;	if ((error = ars_bsd_fix(pkt, packet, size)) != ARS_OK)		return error;	error = sendto(s, packet, size, 0, _sa, slen);	free(packet);	return (error != -1) ? -ARS_OK : -ARS_ERROR;}/* Resolve an hostname and write to 'dest' the IP */int ars_resolve(struct ars_packet *pkt, u_int32_t *dest, char *hostname){	struct sockaddr_in sa;#ifndef WIN32	if (inet_aton(hostname, &sa.sin_addr) == 0) {#else	if ((sa.sin_addr.S_un.S_addr = inet_addr(hostname)) == INADDR_NONE) {#endif		struct hostent *he;		he = gethostbyname(hostname);		if (he == NULL) {			ars_set_error(pkt, "Can't resolve the hostname");			return -ARS_ERROR;		}		sa.sin_addr.s_addr = ((struct in_addr*) he->h_addr)->s_addr;	}	memcpy(dest, &sa.sin_addr.s_addr, sizeof(u_int32_t));	return -ARS_OK;}

⌨️ 快捷键说明

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