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

📄 icmp.c

📁 Minix比较全的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*icmp.cCopyright 1995 Philip Homburg*/#include "inet.h"#include "buf.h"#include "event.h"#include "type.h"#include "assert.h"#include "clock.h"#include "icmp.h"#include "icmp_lib.h"#include "io.h"#include "ip.h"#include "ip_int.h"#include "ipr.h"THIS_FILEtypedef struct icmp_port{	int icp_flags;	int icp_state;	int icp_ipport;	int icp_ipfd;	unsigned icp_rate_count;	unsigned icp_rate_report;	time_t icp_rate_lasttime;	acc_t *icp_head_queue;	acc_t *icp_tail_queue;	acc_t *icp_write_pack;	event_t icp_event;} icmp_port_t;#define ICPF_EMPTY	0x0#define ICPF_SUSPEND	0x1#define ICPF_READ_IP	0x2#define ICPF_READ_SP	0x4#define ICPF_WRITE_IP	0x8#define ICPF_WRITE_SP	0x10#define ICPS_BEGIN	0#define ICPS_IPOPT	1#define ICPS_MAIN	2#define ICPS_ERROR	3PRIVATE icmp_port_t *icmp_port_table;FORWARD void icmp_main ARGS(( icmp_port_t *icmp_port ));FORWARD acc_t *icmp_getdata ARGS(( int port, size_t offset,	size_t count, int for_ioctl ));FORWARD int icmp_putdata ARGS(( int port, size_t offset,	acc_t *data, int for_ioctl ));FORWARD void icmp_read ARGS(( icmp_port_t *icmp_port ));FORWARD void process_data ARGS(( icmp_port_t *icmp_port,	acc_t *data ));FORWARD u16_t icmp_pack_oneCsum ARGS(( acc_t *ip_pack ));FORWARD void icmp_echo_request ARGS(( 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 ));FORWARD void icmp_dst_unreach ARGS(( 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 ));FORWARD void icmp_time_exceeded ARGS(( 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 ));FORWARD void icmp_router_advertisement ARGS(( icmp_port_t *icmp_port,	acc_t *icmp_pack, int icmp_len, icmp_hdr_t *icmp_hdr ));FORWARD void icmp_redirect ARGS(( icmp_port_t *icmp_port,	ip_hdr_t *ip_hdr, acc_t *icmp_pack, int icmp_len,	icmp_hdr_t *icmp_hdr ));FORWARD acc_t *make_repl_ip ARGS(( ip_hdr_t *ip_hdr,	int ip_len ));FORWARD void enqueue_pack ARGS(( icmp_port_t *icmp_port,	acc_t *reply_ip_hdr ));FORWARD int icmp_rate_limit ARGS(( icmp_port_t *icmp_port,	acc_t *reply_ip_hdr ));FORWARD void icmp_write ARGS(( event_t *ev, ev_arg_t ev_arg ));FORWARD void icmp_buffree ARGS(( int priority ));FORWARD acc_t *icmp_err_pack ARGS(( acc_t *pack, icmp_hdr_t **icmp_hdr_pp ));#ifdef BUF_CONSISTENCY_CHECKFORWARD void icmp_bufcheck ARGS(( void ));#endifPUBLIC void icmp_prep(){	icmp_port_table= alloc(ip_conf_nr * sizeof(icmp_port_table[0]));}PUBLIC void icmp_init(){	int i;	icmp_port_t *icmp_port;	assert (BUF_S >= sizeof (nwio_ipopt_t));	for (i= 0, icmp_port= icmp_port_table; i<ip_conf_nr; i++, icmp_port++)	{		icmp_port->icp_flags= ICPF_EMPTY;		icmp_port->icp_state= ICPS_BEGIN;		icmp_port->icp_ipport= i;		icmp_port->icp_rate_count= 0;		icmp_port->icp_rate_report= ICMP_MAX_RATE;		icmp_port->icp_rate_lasttime= 0;		ev_init(&icmp_port->icp_event);	}#ifndef BUF_CONSISTENCY_CHECK	bf_logon(icmp_buffree);#else	bf_logon(icmp_buffree, icmp_bufcheck);#endif	for (i= 0, icmp_port= icmp_port_table; i<ip_conf_nr; i++, icmp_port++)	{		icmp_main (icmp_port);	}}PRIVATE void icmp_main(icmp_port)icmp_port_t *icmp_port;{	int result;	switch (icmp_port->icp_state)	{	case ICPS_BEGIN:		icmp_port->icp_head_queue= 0;		icmp_port->icp_ipfd= ip_open(icmp_port->icp_ipport,			icmp_port->icp_ipport, icmp_getdata, icmp_putdata,			0 /* no put_pkt */, 0 /* no select_res */);		if (icmp_port->icp_ipfd<0)		{			DBLOCK(1, printf("unable to open ip_port %d\n",				icmp_port->icp_ipport));			break;		}		icmp_port->icp_state= ICPS_IPOPT;		icmp_port->icp_flags &= ~ICPF_SUSPEND;		result= ip_ioctl (icmp_port->icp_ipfd, NWIOSIPOPT);		if (result == NW_SUSPEND)		{			icmp_port->icp_flags |= ICPF_SUSPEND;			break;		}		assert(result == NW_OK);		/* falls through */	case ICPS_IPOPT:		icmp_port->icp_state= ICPS_MAIN;		icmp_port->icp_flags &= ~ICPF_SUSPEND;		icmp_read(icmp_port);		break;	default:		DBLOCK(1, printf("unknown state %d\n",			icmp_port->icp_state));		break;	}}PRIVATE acc_t *icmp_getdata(port, offset, count, for_ioctl)int port;size_t offset, count;int for_ioctl;{	icmp_port_t *icmp_port;	nwio_ipopt_t *ipopt;	acc_t *data;	int result;	ev_arg_t ev_arg;	icmp_port= &icmp_port_table[port];	if (icmp_port->icp_flags & ICPF_WRITE_IP)	{		if (!count)		{			bf_afree(icmp_port->icp_write_pack);			icmp_port->icp_write_pack= 0;			result= (int)offset;			if (result<0)			{				DBLOCK(1, printf("got write error %d\n",					result));			}			if (icmp_port->icp_flags & ICPF_WRITE_SP)			{				icmp_port->icp_flags &= ~ICPF_WRITE_SP;				ev_arg.ev_ptr= icmp_port;				ev_enqueue(&icmp_port->icp_event, icmp_write,					ev_arg);			}			return NW_OK;		}		return bf_cut(icmp_port->icp_write_pack, offset, count);	}	switch (icmp_port->icp_state)	{	case ICPS_IPOPT:		if (!count)		{			result= (int)offset;			assert(result == NW_OK);			if (result < 0)			{				icmp_port->icp_state= ICPS_ERROR;				break;			}			if (icmp_port->icp_flags & ICPF_SUSPEND)				icmp_main(icmp_port);			return NW_OK;		}		data= bf_memreq (sizeof (*ipopt));		ipopt= (nwio_ipopt_t *)ptr2acc_data(data);		ipopt->nwio_flags= NWIO_COPY | NWIO_EN_LOC |			NWIO_EN_BROAD |			NWIO_REMANY | NWIO_PROTOSPEC |			NWIO_HDR_O_ANY | NWIO_RWDATALL;		ipopt->nwio_proto= IPPROTO_ICMP;		return data;	default:		break;	}	DBLOCK(1, printf("unknown state %d\n", icmp_port->icp_state));	return NULL;}PRIVATE int icmp_putdata(port, offset, data, for_ioctl)int port;size_t offset;acc_t *data;int for_ioctl;{	icmp_port_t *icmp_port;	int result;	icmp_port= &icmp_port_table[port];	if (icmp_port->icp_flags & ICPF_READ_IP)	{		if (!data)		{			result= (int)offset;			if (result<0)			{				DBLOCK(1, printf("got read error %d\n",					result));			}			if (icmp_port->icp_flags & ICPF_READ_SP)			{				icmp_port->icp_flags &=					~(ICPF_READ_IP|ICPF_READ_SP);				icmp_read (icmp_port);			}			return NW_OK;		}		process_data(icmp_port, data);		return NW_OK;	}	switch (icmp_port->icp_state)	{	default:		DBLOCK(1, printf("unknown state %d\n",			icmp_port->icp_state));		return 0;	}}PRIVATE void icmp_read(icmp_port)icmp_port_t *icmp_port;{	int result;	for (;;)	{		icmp_port->icp_flags |= ICPF_READ_IP;		icmp_port->icp_flags &= ~ICPF_READ_SP;		result= ip_read(icmp_port->icp_ipfd, ICMP_MAX_DATAGRAM);		if (result == NW_SUSPEND)		{			icmp_port->icp_flags |= ICPF_READ_SP;			return;		}	}}PUBLIC void icmp_snd_time_exceeded(port_nr, pack, code)int port_nr;acc_t *pack;int code;{	icmp_hdr_t *icmp_hdr;	icmp_port_t *icmp_port;	if (port_nr >= 0 && port_nr < ip_conf_nr)		icmp_port= &icmp_port_table[port_nr];	else	{		printf("icmp_snd_time_exceeded: strange port %d\n", port_nr);		bf_afree(pack);		return;	}	pack= icmp_err_pack(pack, &icmp_hdr);	if (pack == NULL)		return;	icmp_hdr->ih_type= ICMP_TYPE_TIME_EXCEEDED;	icmp_hdr->ih_code= code;	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,		(u16_t *)&icmp_hdr->ih_type, 2);	enqueue_pack(icmp_port, pack);}PUBLIC void icmp_snd_redirect(port_nr, pack, code, gw)int port_nr;acc_t *pack;int code;ipaddr_t gw;{	icmp_hdr_t *icmp_hdr;	icmp_port_t *icmp_port;	if (port_nr >= 0 && port_nr < ip_conf_nr)		icmp_port= &icmp_port_table[port_nr];	else	{		printf("icmp_snd_redirect: strange port %d\n", port_nr);		bf_afree(pack);		return;	}	pack= icmp_err_pack(pack, &icmp_hdr);	if (pack == NULL)		return;	icmp_hdr->ih_type= ICMP_TYPE_REDIRECT;	icmp_hdr->ih_code= code;	icmp_hdr->ih_hun.ihh_gateway= gw;	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,		(u16_t *)&icmp_hdr->ih_type, 2);	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,		(u16_t *)&icmp_hdr->ih_hun.ihh_gateway, 4);	enqueue_pack(icmp_port, pack);}PUBLIC void icmp_snd_unreachable(port_nr, pack, code)int port_nr;acc_t *pack;int code;{	icmp_hdr_t *icmp_hdr;	icmp_port_t *icmp_port;	if (port_nr >= 0 && port_nr < ip_conf_nr)		icmp_port= &icmp_port_table[port_nr];	else	{		printf("icmp_snd_unreachable: strange port %d\n", port_nr);		bf_afree(pack);		return;	}	pack= icmp_err_pack(pack, &icmp_hdr);	if (pack == NULL)		return;	icmp_hdr->ih_type= ICMP_TYPE_DST_UNRCH;	icmp_hdr->ih_code= code;	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,		(u16_t *)&icmp_hdr->ih_type, 2);	enqueue_pack(icmp_port, pack);}PUBLIC void icmp_snd_mtu(port_nr, pack, mtu)int port_nr;acc_t *pack;u16_t mtu;{	icmp_hdr_t *icmp_hdr;	icmp_port_t *icmp_port;	if (port_nr >= 0 && port_nr < ip_conf_nr)		icmp_port= &icmp_port_table[port_nr];	else	{		printf("icmp_snd_mtu: strange port %d\n", port_nr);		bf_afree(pack);		return;	}	pack= icmp_err_pack(pack, &icmp_hdr);	if (pack == NULL)		return;	icmp_hdr->ih_type= ICMP_TYPE_DST_UNRCH;	icmp_hdr->ih_code= ICMP_FRAGM_AND_DF;	icmp_hdr->ih_hun.ihh_mtu.im_mtu= htons(mtu);	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,		(u16_t *)&icmp_hdr->ih_type, 2);	icmp_hdr->ih_chksum= ~oneC_sum(~icmp_hdr->ih_chksum,		(u16_t *)&icmp_hdr->ih_hun.ihh_mtu.im_mtu, 2);	enqueue_pack(icmp_port, pack);}PRIVATE void process_data(icmp_port, data)icmp_port_t *icmp_port;acc_t *data;{	ip_hdr_t *ip_hdr;	icmp_hdr_t *icmp_hdr;	acc_t *icmp_data;	int ip_hdr_len;	size_t pack_len;	/* Align entire packet */	data= bf_align(data, BUF_S, 4);	data= bf_packIffLess(data, IP_MIN_HDR_SIZE);	ip_hdr= (ip_hdr_t *)ptr2acc_data(data);	DIFBLOCK(0x10, (ip_hdr->ih_dst & HTONL(0xf0000000)) == HTONL(0xe0000000),		printf("got multicast packet\n"));	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;	if (ip_hdr_len>IP_MIN_HDR_SIZE)	{		data= bf_packIffLess(data, ip_hdr_len);		ip_hdr= (ip_hdr_t *)ptr2acc_data(data);	}	pack_len= bf_bufsize(data);	pack_len -= ip_hdr_len;	if (pack_len < ICMP_MIN_HDR_SIZE)	{		if (pack_len == 0 && ip_hdr->ih_proto == 0)		{			/* IP layer reports new ip address, which can be			 * ignored.			 */		}		else			DBLOCK(1, printf("got an incomplete icmp packet\n"));		bf_afree(data);		return;	}	icmp_data= bf_cut(data, ip_hdr_len, pack_len);	icmp_data= bf_packIffLess (icmp_data, ICMP_MIN_HDR_SIZE);	icmp_hdr= (icmp_hdr_t *)ptr2acc_data(icmp_data);	if ((u16_t)~icmp_pack_oneCsum(icmp_data))	{		DBLOCK(1, printf(			"got packet with bad checksum (= 0x%x, 0x%x)\n",			icmp_hdr->ih_chksum,			(u16_t)~icmp_pack_oneCsum(icmp_data)));		bf_afree(data);		bf_afree(icmp_data);		return;	}	switch (icmp_hdr->ih_type)	{	case ICMP_TYPE_ECHO_REPL:		break;	case ICMP_TYPE_DST_UNRCH:		icmp_dst_unreach (icmp_port, data, ip_hdr_len, ip_hdr,			icmp_data, pack_len, icmp_hdr);		break;	case ICMP_TYPE_SRC_QUENCH:		/* Ignore src quench ICMPs */		DBLOCK(2, printf("ignoring SRC QUENCH ICMP.\n"));		break;	case ICMP_TYPE_REDIRECT:		icmp_redirect (icmp_port, ip_hdr, icmp_data, pack_len,			icmp_hdr);		break;	case ICMP_TYPE_ECHO_REQ:		icmp_echo_request(icmp_port, data, ip_hdr_len, ip_hdr,			icmp_data, pack_len, icmp_hdr);		return;	case ICMP_TYPE_ROUTER_ADVER:		icmp_router_advertisement(icmp_port, icmp_data, pack_len, 			icmp_hdr);		break;	case ICMP_TYPE_ROUTE_SOL:		break;	/* Should be handled by a routing deamon. */	case ICMP_TYPE_TIME_EXCEEDED:		icmp_time_exceeded (icmp_port, data, ip_hdr_len, ip_hdr,			icmp_data, pack_len, icmp_hdr);		break;	default:		DBLOCK(1, printf("got an unknown icmp (%d) from ",			icmp_hdr->ih_type); 			writeIpAddr(ip_hdr->ih_src); printf("\n"));		break;	}	bf_afree(data);	bf_afree(icmp_data);}PRIVATE void icmp_echo_request(icmp_port, ip_data, ip_len, ip_hdr,	icmp_data, icmp_len, icmp_hdr)icmp_port_t *icmp_port;acc_t *ip_data, *icmp_data;int ip_len, icmp_len;ip_hdr_t *ip_hdr;icmp_hdr_t *icmp_hdr;{	acc_t *repl_ip_hdr, *repl_icmp;	ipaddr_t tmpaddr, locaddr, netmask;	icmp_hdr_t *repl_icmp_hdr;	i32_t tmp_chksum;	ip_port_t *ip_port;	if (icmp_hdr->ih_code != 0)	{		DBLOCK(1,		printf("got an icmp echo request with unknown code (%d)\n",			icmp_hdr->ih_code));		bf_afree(ip_data);		bf_afree(icmp_data);		return;	}	if (icmp_len < ICMP_MIN_HDR_SIZE + sizeof(icmp_id_seq_t))	{		DBLOCK(1, printf("got an incomplete icmp echo request\n"));		bf_afree(ip_data);		bf_afree(icmp_data);		return;	}	tmpaddr= ntohl(ip_hdr->ih_dst);	if ((tmpaddr & 0xe0000000) == 0xe0000000 &&		tmpaddr != 0xffffffff)	{		/* Respond only to the all hosts multicast address until		 * a decent listening service has been implemented		 */		if (tmpaddr != 0xe0000001)		{			bf_afree(ip_data);			bf_afree(icmp_data);			return;		}	}	/* Limit subnet broadcasts to the local net */	ip_port= &ip_port_table[icmp_port->icp_ipport];	locaddr= ip_port->ip_ipaddr;	netmask= ip_port->ip_subnetmask;	if (ip_hdr->ih_dst == (locaddr | ~netmask) &&		(ip_port->ip_flags & IPF_SUBNET_BCAST) &&		((ip_hdr->ih_src ^ locaddr) & netmask) != 0)	{		/* Directed broadcast */		bf_afree(ip_data);		bf_afree(icmp_data);		return;	}	repl_ip_hdr= make_repl_ip(ip_hdr, ip_len);	repl_icmp= bf_memreq (ICMP_MIN_HDR_SIZE);	repl_icmp_hdr= (icmp_hdr_t *)ptr2acc_data(repl_icmp);	repl_icmp_hdr->ih_type= ICMP_TYPE_ECHO_REPL;	repl_icmp_hdr->ih_code= 0;	DBLOCK(2,	printf("ih_chksum= 0x%x, ih_type= 0x%x, repl->ih_type= 0x%x\n",		icmp_hdr->ih_chksum, *(u16_t *)&icmp_hdr->ih_type, 		*(u16_t *)&repl_icmp_hdr->ih_type));	tmp_chksum= (~icmp_hdr->ih_chksum & 0xffff) - 		(i32_t)*(u16_t *)&icmp_hdr->ih_type+		*(u16_t *)&repl_icmp_hdr->ih_type;	tmp_chksum= (tmp_chksum >> 16) + (tmp_chksum & 0xffff);	tmp_chksum= (tmp_chksum >> 16) + (tmp_chksum & 0xffff);	repl_icmp_hdr->ih_chksum= ~tmp_chksum;	DBLOCK(2, printf("sending chksum 0x%x\n", repl_icmp_hdr->ih_chksum));	repl_ip_hdr->acc_next= repl_icmp;	repl_icmp->acc_next= bf_cut (icmp_data, ICMP_MIN_HDR_SIZE,		icmp_len - ICMP_MIN_HDR_SIZE);	bf_afree(ip_data);	bf_afree(icmp_data);	enqueue_pack(icmp_port, repl_ip_hdr);}PRIVATE u16_t icmp_pack_oneCsum(icmp_pack)acc_t *icmp_pack;{	u16_t prev;	int odd_byte;	char *data_ptr;	int length;	char byte_buf[2];	prev= 0;	odd_byte= FALSE;	for (; icmp_pack; icmp_pack= icmp_pack->acc_next)	{		data_ptr= ptr2acc_data(icmp_pack);		length= icmp_pack->acc_length;		if (!length)			continue;		if (odd_byte)		{			byte_buf[1]= *data_ptr;			prev= oneC_sum(prev, (u16_t *)byte_buf, 2);			data_ptr++;			length--;			odd_byte= FALSE;		}		if (length & 1)

⌨️ 快捷键说明

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