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

📄 icmp.c

📁 Minix比较全的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		{			odd_byte= TRUE;			length--;			byte_buf[0]= data_ptr[length];		}		if (!length)			continue;		prev= oneC_sum (prev, (u16_t *)data_ptr, length);	}	if (odd_byte)		prev= oneC_sum (prev, (u16_t *)byte_buf, 1);	return prev;}PRIVATE acc_t *make_repl_ip(ip_hdr, ip_len)ip_hdr_t *ip_hdr;int ip_len;{	ip_hdr_t *repl_ip_hdr;	acc_t *repl;	int repl_hdr_len;	if (ip_len>IP_MIN_HDR_SIZE)	{		DBLOCK(1, printf("ip_hdr options NOT supported (yet?)\n"));		ip_len= IP_MIN_HDR_SIZE;	}	repl_hdr_len= IP_MIN_HDR_SIZE;	repl= bf_memreq(repl_hdr_len);	repl_ip_hdr= (ip_hdr_t *)ptr2acc_data(repl);	repl_ip_hdr->ih_vers_ihl= repl_hdr_len >> 2;	repl_ip_hdr->ih_tos= ip_hdr->ih_tos;	repl_ip_hdr->ih_ttl= ICMP_DEF_TTL;	repl_ip_hdr->ih_proto= IPPROTO_ICMP;	repl_ip_hdr->ih_dst= ip_hdr->ih_src;	repl_ip_hdr->ih_flags_fragoff= 0;	return repl;}PRIVATE void enqueue_pack(icmp_port, reply_ip_hdr)icmp_port_t *icmp_port;acc_t *reply_ip_hdr;{	int r;	ev_arg_t ev_arg;	/* Check rate */	if (icmp_port->icp_rate_count >= ICMP_MAX_RATE)	{		/* Something is going wrong; check policy */		r= icmp_rate_limit(icmp_port, reply_ip_hdr);		if (r == -1)		{			bf_afree(reply_ip_hdr);			reply_ip_hdr= NULL;			return;		}		/* OK, continue */	}	icmp_port->icp_rate_count++;	reply_ip_hdr->acc_ext_link= 0;	if (icmp_port->icp_head_queue)	{		icmp_port->icp_tail_queue->acc_ext_link=			reply_ip_hdr;	}	else	{		icmp_port->icp_head_queue= reply_ip_hdr;	}	reply_ip_hdr->acc_ext_link= NULL;	icmp_port->icp_tail_queue= reply_ip_hdr;	if (!(icmp_port->icp_flags & ICPF_WRITE_IP))	{		icmp_port->icp_flags |= ICPF_WRITE_IP;		ev_arg.ev_ptr= icmp_port;		ev_enqueue(&icmp_port->icp_event, icmp_write, ev_arg);	}}PRIVATE int icmp_rate_limit(icmp_port, reply_ip_hdr)icmp_port_t *icmp_port;acc_t *reply_ip_hdr;{	time_t t;	acc_t *pack;	ip_hdr_t *ip_hdr;	icmp_hdr_t *icmp_hdr;	int hdrlen, icmp_hdr_len, type;	/* Check the time first */	t= get_time();	if (t >= icmp_port->icp_rate_lasttime + ICMP_RATE_INTERVAL)	{		icmp_port->icp_rate_lasttime= t;		icmp_port->icp_rate_count= 0;		return 0;	}	icmp_port->icp_rate_count++;	/* Adjust report limit if necessary */	if (icmp_port->icp_rate_count >		icmp_port->icp_rate_report+ICMP_RATE_WARN)	{		icmp_port->icp_rate_report *= 2;		return -1;	}	/* Do we need to report */	if (icmp_port->icp_rate_count < icmp_port->icp_rate_report)		return -1;	pack= bf_dupacc(reply_ip_hdr);	pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);	printf("icmp[%d]: dropping ICMP packet #%d to ",		icmp_port->icp_ipport, icmp_port->icp_rate_count);	writeIpAddr(ip_hdr->ih_dst);	hdrlen= (ip_hdr->ih_vers_ihl & IH_IHL_MASK)*4;	pack= bf_packIffLess(pack, hdrlen+ICMP_MIN_HDR_SIZE);	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);	icmp_hdr= (icmp_hdr_t *)(ptr2acc_data(pack)+hdrlen);	type= icmp_hdr->ih_type;	printf(" type %d, code %d\n", type, icmp_hdr->ih_code);	switch(type)	{	case ICMP_TYPE_DST_UNRCH:	case ICMP_TYPE_SRC_QUENCH:	case ICMP_TYPE_REDIRECT:	case ICMP_TYPE_TIME_EXCEEDED:	case ICMP_TYPE_PARAM_PROBLEM:		icmp_hdr_len= offsetof(struct icmp_hdr, ih_dun);		pack= bf_packIffLess(pack,			hdrlen+icmp_hdr_len+IP_MIN_HDR_SIZE);		ip_hdr= (ip_hdr_t *)(ptr2acc_data(pack)+hdrlen+icmp_hdr_len);		icmp_hdr= (icmp_hdr_t *)(ptr2acc_data(pack)+hdrlen);		printf("\tinfo %08x, original dst ",			ntohs(icmp_hdr->ih_hun.ihh_unused));		writeIpAddr(ip_hdr->ih_dst);		printf(", proto %d, length %u\n",			ip_hdr->ih_proto, ntohs(ip_hdr->ih_length));		break;	default:		break;	}	bf_afree(pack); pack= NULL;	return -1;}PRIVATE void icmp_write(ev, ev_arg)event_t *ev;ev_arg_t ev_arg;{	int result;	icmp_port_t *icmp_port;	acc_t *data;	icmp_port= ev_arg.ev_ptr;	assert(ev == &icmp_port->icp_event);	assert (icmp_port->icp_flags & ICPF_WRITE_IP);	assert (!(icmp_port->icp_flags & ICPF_WRITE_SP));	while (icmp_port->icp_head_queue != NULL)	{		data= icmp_port->icp_head_queue;		icmp_port->icp_head_queue= data->acc_ext_link;		result= ip_send(icmp_port->icp_ipfd, data,			bf_bufsize(data));		if (result != NW_WOULDBLOCK)		{			if (result == NW_OK)				continue;			DBLOCK(1, printf("icmp_write: error %d\n", result););			continue;		}		assert(icmp_port->icp_write_pack == NULL);		icmp_port->icp_write_pack= data;					result= ip_write(icmp_port->icp_ipfd,			bf_bufsize(icmp_port->icp_write_pack));		if (result == NW_SUSPEND)		{			icmp_port->icp_flags |= ICPF_WRITE_SP;			return;		}	}	icmp_port->icp_flags &= ~ICPF_WRITE_IP;}PRIVATE void icmp_buffree(priority)int priority;{	acc_t *tmp_acc;	int i;	icmp_port_t *icmp_port;	if (priority == ICMP_PRI_QUEUE)	{		for (i=0, icmp_port= icmp_port_table; i<ip_conf_nr;			i++, icmp_port++)		{			while(icmp_port->icp_head_queue)			{				tmp_acc= icmp_port->icp_head_queue;				icmp_port->icp_head_queue=					tmp_acc->acc_ext_link;				bf_afree(tmp_acc);			}		}	}}#ifdef BUF_CONSISTENCY_CHECKPRIVATE void icmp_bufcheck(){	int i;	icmp_port_t *icmp_port;	acc_t *pack;	for (i= 0, icmp_port= icmp_port_table; i<ip_conf_nr; i++, icmp_port++)	{		for (pack= icmp_port->icp_head_queue; pack; 			pack= pack->acc_ext_link)		{			bf_check_acc(pack);		}		bf_check_acc(icmp_port->icp_write_pack);	}}#endifPRIVATE void icmp_dst_unreach(icmp_port, ip_pack, ip_hdr_len, ip_hdr, icmp_pack,	icmp_len, icmp_hdr)icmp_port_t *icmp_port;acc_t *ip_pack;int ip_hdr_len;ip_hdr_t *ip_hdr;acc_t *icmp_pack;int icmp_len;icmp_hdr_t *icmp_hdr;{	acc_t *old_ip_pack;	ip_hdr_t *old_ip_hdr;	int ip_port_nr;	ipaddr_t dst, mask;	size_t old_pack_size;	u16_t new_mtu;	if (icmp_len < 8 + IP_MIN_HDR_SIZE)	{		DBLOCK(1, printf("dest unrch with wrong size\n"));		return;	}	old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);	old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);	old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);	if (old_ip_hdr->ih_src != ip_hdr->ih_dst)	{		DBLOCK(1, printf("dest unrch based on wrong packet\n"));		bf_afree(old_ip_pack);		return;	}	ip_port_nr= icmp_port->icp_ipport;	switch(icmp_hdr->ih_code)	{	case ICMP_NET_UNRCH:		dst= old_ip_hdr->ih_dst;		mask= ip_get_netmask(dst);		ipr_destunrch (ip_port_nr, dst & mask, mask,			IPR_UNRCH_TIMEOUT);		break;	case ICMP_HOST_UNRCH:		ipr_destunrch (ip_port_nr, old_ip_hdr->ih_dst, (ipaddr_t)-1,			IPR_UNRCH_TIMEOUT);		break;	case ICMP_PORT_UNRCH:		/* At the moment we don't do anything with this information.		 * It should be handed to the appropriate transport layer.		 */		break;	case ICMP_FRAGM_AND_DF:		DBLOCK(1, printf("icmp_dst_unreach: got mtu icmp from ");			writeIpAddr(ip_hdr->ih_src);			printf("; original destination: ");			writeIpAddr(old_ip_hdr->ih_dst);			printf("; protocol: %d\n",			old_ip_hdr->ih_proto));		old_pack_size= ntohs(old_ip_hdr->ih_length);		if (!old_pack_size)			break;		new_mtu= ntohs(icmp_hdr->ih_hun.ihh_mtu.im_mtu);		if (!new_mtu || new_mtu > old_pack_size)			new_mtu= old_pack_size-1;		ipr_mtu(ip_port_nr, old_ip_hdr->ih_dst, new_mtu,			IPR_MTU_TIMEOUT);		break;	default:		DBLOCK(1, printf("icmp_dst_unreach: got strange code %d from ",			icmp_hdr->ih_code);			writeIpAddr(ip_hdr->ih_src);			printf("; original destination: ");			writeIpAddr(old_ip_hdr->ih_dst);			printf("; protocol: %d\n",			old_ip_hdr->ih_proto));		break;	}	bf_afree(old_ip_pack);}PRIVATE void icmp_time_exceeded(icmp_port, ip_pack, ip_hdr_len, ip_hdr,	icmp_pack, icmp_len, icmp_hdr)icmp_port_t *icmp_port;acc_t *ip_pack;int ip_hdr_len;ip_hdr_t *ip_hdr;acc_t *icmp_pack;int icmp_len;icmp_hdr_t *icmp_hdr;{	acc_t *old_ip_pack;	ip_hdr_t *old_ip_hdr;	int ip_port_nr;	if (icmp_len < 8 + IP_MIN_HDR_SIZE)	{		DBLOCK(1, printf("time exceeded with wrong size\n"));		return;	}	old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);	old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);	old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);	if (old_ip_hdr->ih_src != ip_hdr->ih_dst)	{		DBLOCK(1, printf("time exceeded based on wrong packet\n"));		bf_afree(old_ip_pack);		return;	}	ip_port_nr= icmp_port->icp_ipport;	switch(icmp_hdr->ih_code)	{	case ICMP_TTL_EXC:		ipr_ttl_exc (ip_port_nr, old_ip_hdr->ih_dst, (ipaddr_t)-1,			IPR_TTL_TIMEOUT);		break;	case ICMP_FRAG_REASSEM:		/* Ignore reassembly time-outs. */		break;	default:		DBLOCK(1, printf("got strange code: %d\n",			icmp_hdr->ih_code));		break;	}	bf_afree(old_ip_pack);}PRIVATE void icmp_router_advertisement(icmp_port, icmp_pack, icmp_len, icmp_hdr)icmp_port_t *icmp_port;acc_t *icmp_pack;int icmp_len;icmp_hdr_t *icmp_hdr;{	int entries;	int entry_size;	u32_t addr;	i32_t pref;	u16_t lifetime;	int i;	char *bufp;	ip_port_t *ip_port;	if (icmp_len < 8)	{		DBLOCK(1,		printf("router advertisement with wrong size (%d)\n",			icmp_len));		return;	}	if (icmp_hdr->ih_code != 0)	{		DBLOCK(1,		printf("router advertisement with wrong code (%d)\n", 			icmp_hdr->ih_code));		return;	}	entries= icmp_hdr->ih_hun.ihh_ram.iram_na;	entry_size= icmp_hdr->ih_hun.ihh_ram.iram_aes * 4;	if (entries < 1)	{		DBLOCK(1, printf(		"router advertisement with wrong number of entries (%d)\n", 			entries));		return;	}	if (entry_size < 8)	{		DBLOCK(1, printf(		"router advertisement with wrong entry size (%d)\n", 			entry_size));		return;	}	if (icmp_len < 8 + entries * entry_size)	{		DBLOCK(1,			printf("router advertisement with wrong size\n"); 			printf(			"\t(entries= %d, entry_size= %d, icmp_len= %d)\n",			entries, entry_size, icmp_len));		return;	}	lifetime= ntohs(icmp_hdr->ih_hun.ihh_ram.iram_lt);	if (lifetime > 9000)	{		DBLOCK(1, printf(			"router advertisement with wrong lifetime (%d)\n",			lifetime));		return;	}	ip_port= &ip_port_table[icmp_port->icp_ipport];	for (i= 0, bufp= (char *)&icmp_hdr->ih_dun.uhd_data[0]; i< entries; i++,		bufp += entry_size)	{		addr= *(ipaddr_t *)bufp;		pref= ntohl(*(u32_t *)(bufp+4));		ipr_add_oroute(icmp_port->icp_ipport, HTONL(0L), HTONL(0L), 			addr, lifetime ? lifetime * HZ : 1,			1, 0, 0, pref, NULL);	}}		PRIVATE void icmp_redirect(icmp_port, ip_hdr, icmp_pack, icmp_len, icmp_hdr)icmp_port_t *icmp_port;ip_hdr_t *ip_hdr;acc_t *icmp_pack;int icmp_len;icmp_hdr_t *icmp_hdr;{	acc_t *old_ip_pack;	ip_hdr_t *old_ip_hdr;	int ip_port_nr;	ipaddr_t dst, mask;	if (icmp_len < 8 + IP_MIN_HDR_SIZE)	{		DBLOCK(1, printf("redirect with wrong size\n"));		return;	}	old_ip_pack= bf_cut (icmp_pack, 8, icmp_len-8);	old_ip_pack= bf_packIffLess(old_ip_pack, IP_MIN_HDR_SIZE);	old_ip_hdr= (ip_hdr_t *)ptr2acc_data(old_ip_pack);	ip_port_nr= icmp_port->icp_ipport;	switch(icmp_hdr->ih_code)	{	case ICMP_REDIRECT_NET:		dst= old_ip_hdr->ih_dst;		mask= ip_get_netmask(dst);		ipr_redirect (ip_port_nr, dst & mask, mask,			ip_hdr->ih_src, icmp_hdr->ih_hun.ihh_gateway, 			IPR_REDIRECT_TIMEOUT);		break;	case ICMP_REDIRECT_HOST:		ipr_redirect (ip_port_nr, old_ip_hdr->ih_dst, (ipaddr_t)-1,			ip_hdr->ih_src, icmp_hdr->ih_hun.ihh_gateway, 			IPR_REDIRECT_TIMEOUT);		break;	default:		DBLOCK(1, printf("got strange code: %d\n",			icmp_hdr->ih_code));		break;	}	bf_afree(old_ip_pack);}PRIVATE acc_t *icmp_err_pack(pack, icmp_hdr_pp)acc_t *pack;icmp_hdr_t **icmp_hdr_pp;{	ip_hdr_t *ip_hdr;	icmp_hdr_t *icmp_hdr_p;	acc_t *ip_pack, *icmp_pack, *tmp_pack;	int ip_hdr_len, icmp_hdr_len, ih_type;	size_t size, pack_len;	ipaddr_t dest, netmask;	nettype_t nettype;	pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;	pack_len= bf_bufsize(pack);	/* If the IP protocol is ICMP (except echo request/reply) or the	 * fragment offset is non-zero,	 * drop the packet. Also check if the source address is valid.	 */	if ((ntohs(ip_hdr->ih_flags_fragoff) & IH_FRAGOFF_MASK) != 0)	{		bf_afree(pack);		return NULL;	}	if (ip_hdr->ih_proto == IPPROTO_ICMP)	{		if (ip_hdr_len>IP_MIN_HDR_SIZE)		{			pack= bf_packIffLess(pack, ip_hdr_len);			ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);		}		if (pack_len < ip_hdr_len+ICMP_MIN_HDR_SIZE)		{			bf_afree(pack);			return NULL;		}		icmp_pack= bf_cut(pack, ip_hdr_len, ICMP_MIN_HDR_SIZE);		icmp_pack= bf_packIffLess (icmp_pack, ICMP_MIN_HDR_SIZE);		icmp_hdr_p= (icmp_hdr_t *)ptr2acc_data(icmp_pack);		ih_type= icmp_hdr_p->ih_type;		bf_afree(icmp_pack); icmp_pack= NULL;		if (ih_type != ICMP_TYPE_ECHO_REQ &&			ih_type != ICMP_TYPE_ECHO_REPL)		{			bf_afree(pack);			return NULL;		}	}	dest= ip_hdr->ih_src;	nettype= ip_nettype(dest);	netmask= ip_netmask(nettype);	if (nettype != IPNT_CLASS_A && nettype != IPNT_LOCAL &&		nettype != IPNT_CLASS_B && nettype != IPNT_CLASS_C)	{		printf("icmp_err_pack: invalid source address: ");		writeIpAddr(dest);		printf("\n");		bf_afree(pack);		return NULL;	}	/* Take the IP header and the first 64 bits of user data. */	size= ntohs(ip_hdr->ih_length);	if (size < ip_hdr_len || pack_len < size)	{		printf("icmp_err_pack: wrong packet size:\n");		printf("\thdrlen= %d, ih_length= %d, bufsize= %d\n",			ip_hdr_len, size, pack_len);		bf_afree(pack);		return NULL;	}	if (ip_hdr_len + 8 < size)		size= ip_hdr_len+8;	tmp_pack= bf_cut(pack, 0, size);	bf_afree(pack);	pack= tmp_pack;	tmp_pack= NULL;	/* Create a minimal size ICMP hdr. */	icmp_hdr_len= offsetof(icmp_hdr_t, ih_dun);	icmp_pack= bf_memreq(icmp_hdr_len);	pack= bf_append(icmp_pack, pack);	size += icmp_hdr_len;	pack= bf_packIffLess(pack, icmp_hdr_len);	icmp_hdr_p= (icmp_hdr_t *)ptr2acc_data(pack);	icmp_hdr_p->ih_type= 0;	icmp_hdr_p->ih_code= 0;	icmp_hdr_p->ih_chksum= 0;	icmp_hdr_p->ih_hun.ihh_unused= 0;	icmp_hdr_p->ih_chksum= ~icmp_pack_oneCsum(pack);	*icmp_hdr_pp= icmp_hdr_p;	/* Create an IP header */	ip_hdr_len= IP_MIN_HDR_SIZE;	ip_pack= bf_memreq(ip_hdr_len);	ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_pack);	ip_hdr->ih_vers_ihl= ip_hdr_len >> 2;	ip_hdr->ih_tos= 0;	ip_hdr->ih_length= htons(ip_hdr_len + size);	ip_hdr->ih_flags_fragoff= 0;	ip_hdr->ih_ttl= ICMP_DEF_TTL;	ip_hdr->ih_proto= IPPROTO_ICMP;	ip_hdr->ih_dst= dest;	assert(ip_pack->acc_next == NULL);	ip_pack->acc_next= pack;	return ip_pack;}/* * $PchId: icmp.c,v 1.23 2005/06/28 14:16:56 philip Exp $ */

⌨️ 快捷键说明

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