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

📄 ip_read.c

📁 minix3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			}			pack->acc_linkC++;			ip_packet2user(ip_fd, pack, exp_time, size);		}		if (share_fd)		{			pack->acc_linkC++;			ip_packet2user(share_fd, pack, exp_time, size);		}	}	if (first_fd)	{		if (first_fd->if_put_pkt &&			(first_fd->if_flags & IFF_READ_IP) &&			!(first_fd->if_ipopt.nwio_flags & NWIO_RWDATONLY))		{			(*first_fd->if_put_pkt)(first_fd->if_srfd, pack,				size);		}		else			ip_packet2user(first_fd, pack, exp_time, size);	}	else	{		if (ip_pack_stat == NWIO_EN_LOC)		{			DBLOCK(0x01,			printf("ip_port_arrive: dropping packet for proto %d\n",				proto));		}		else		{			DBLOCK(0x20, printf("dropping packet for proto %d\n",				proto));		}		bf_afree(pack);	}}PUBLIC void ip_arrived(ip_port, pack)ip_port_t *ip_port;acc_t *pack;{	ip_hdr_t *ip_hdr;	ipaddr_t dest;	int ip_frag_len, ip_hdr_len, highbyte;	size_t pack_size;	acc_t *tmp_pack, *hdr_pack;	ev_arg_t ev_arg;	pack_size= bf_bufsize(pack);	if (pack_size < IP_MIN_HDR_SIZE)	{		DBLOCK(1, printf("wrong acc_length\n"));		bf_afree(pack);		return;	}	pack= bf_align(pack, IP_MIN_HDR_SIZE, 4);	pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);assert (pack->acc_length >= IP_MIN_HDR_SIZE);	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);	ip_hdr_len= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;	if (ip_hdr_len>IP_MIN_HDR_SIZE)	{		pack= bf_packIffLess(pack, ip_hdr_len);		ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);	}	ip_frag_len= ntohs(ip_hdr->ih_length);	if (ip_frag_len != pack_size)	{		if (pack_size < ip_frag_len)		{			/* Sent ICMP? */			DBLOCK(1, printf("wrong acc_length\n"));			bf_afree(pack);			return;		}		assert(ip_frag_len<pack_size);		tmp_pack= pack;		pack= bf_cut(tmp_pack, 0, ip_frag_len);		bf_afree(tmp_pack);		pack_size= ip_frag_len;	}	if (!ip_frag_chk(pack))	{		DBLOCK(1, printf("fragment not allright\n"));		bf_afree(pack);		return;	}	/* Decide about local delivery or routing. Local delivery can happen	 * when the destination is the local ip address, or one of the 	 * broadcast addresses and the packet happens to be delivered 	 * point-to-point.	 */	dest= ip_hdr->ih_dst;	if (dest == ip_port->ip_ipaddr)	{		ip_port_arrive (ip_port, pack, ip_hdr);		return;	}	if (broadcast_dst(ip_port, dest))	{		ip_port_arrive (ip_port, pack, ip_hdr);		return;	}	if (pack->acc_linkC != 1 || pack->acc_buffer->buf_linkC != 1)	{		/* Get a private copy of the IP header */		hdr_pack= bf_memreq(ip_hdr_len);		memcpy(ptr2acc_data(hdr_pack), ip_hdr, ip_hdr_len);		pack= bf_delhead(pack, ip_hdr_len);		hdr_pack->acc_next= pack;		pack= hdr_pack; hdr_pack= NULL;		ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);	}	assert(pack->acc_linkC == 1);	assert(pack->acc_buffer->buf_linkC == 1);	/* Try to decrement the ttl field with one. */	if (ip_hdr->ih_ttl < 2)	{		icmp_snd_time_exceeded(ip_port->ip_port, pack,			ICMP_TTL_EXC);		return;	}	ip_hdr->ih_ttl--;	ip_hdr_chksum(ip_hdr, ip_hdr_len);	/* Avoid routing to bad destinations. */	highbyte= ntohl(dest) >> 24;	if (highbyte == 0 || highbyte == 127 ||		(highbyte == 169 && (((ntohl(dest) >> 16) & 0xff) == 254)) ||		highbyte >= 0xe0)	{		/* Bogus destination address */		bf_afree(pack);		return;	}	/* Further processing from an event handler */	if (pack->acc_linkC != 1)	{		tmp_pack= bf_dupacc(pack);		bf_afree(pack);		pack= tmp_pack;		tmp_pack= NULL;	}	pack->acc_ext_link= NULL;	if (ip_port->ip_routeq_head)	{		ip_port->ip_routeq_tail->acc_ext_link= pack;		ip_port->ip_routeq_tail= pack;		return;	}	ip_port->ip_routeq_head= pack;	ip_port->ip_routeq_tail= pack;	ev_arg.ev_ptr= ip_port;	ev_enqueue(&ip_port->ip_routeq_event, route_packets, ev_arg);}PUBLIC void ip_arrived_broadcast(ip_port, pack)ip_port_t *ip_port;acc_t *pack;{	ip_hdr_t *ip_hdr;	int ip_frag_len, ip_hdr_len;	size_t pack_size;	acc_t *tmp_pack;	pack_size= bf_bufsize(pack);	if (pack_size < IP_MIN_HDR_SIZE)	{		DBLOCK(1, printf("wrong acc_length\n"));		bf_afree(pack);		return;	}	pack= bf_align(pack, IP_MIN_HDR_SIZE, 4);	pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);assert (pack->acc_length >= IP_MIN_HDR_SIZE);	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);	DIFBLOCK(0x20, (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)	{		pack= bf_align(pack, IP_MIN_HDR_SIZE, 4);		pack= bf_packIffLess(pack, ip_hdr_len);		ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);	}	ip_frag_len= ntohs(ip_hdr->ih_length);	if (ip_frag_len<pack_size)	{		tmp_pack= pack;		pack= bf_cut(tmp_pack, 0, ip_frag_len);		bf_afree(tmp_pack);	}	if (!ip_frag_chk(pack))	{		DBLOCK(1, printf("fragment not allright\n"));		bf_afree(pack);		return;	}	if (!broadcast_dst(ip_port, ip_hdr->ih_dst))	{#if 0		printf(		"ip[%d]: broadcast packet for ip-nonbroadcast addr, src=",			ip_port->ip_port);		writeIpAddr(ip_hdr->ih_src);		printf(" dst=");		writeIpAddr(ip_hdr->ih_dst);		printf("\n");#endif		bf_afree(pack);		return;	}	ip_port_arrive (ip_port, pack, ip_hdr);}PRIVATE void route_packets(ev, ev_arg)event_t *ev;ev_arg_t ev_arg;{	ip_port_t *ip_port;	ipaddr_t dest;	acc_t *pack;	iroute_t *iroute;	ip_port_t *next_port;	int r, type;	ip_hdr_t *ip_hdr;	size_t req_mtu;	ip_port= ev_arg.ev_ptr;	assert(&ip_port->ip_routeq_event == ev);	while (pack= ip_port->ip_routeq_head, pack != NULL)	{		ip_port->ip_routeq_head= pack->acc_ext_link;		ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);		dest= ip_hdr->ih_dst;		iroute= iroute_frag(ip_port->ip_port, dest);		if (iroute == NULL || iroute->irt_dist == IRTD_UNREACHABLE)		{			/* Also unreachable */			/* Finding out if we send a network unreachable is too			 * much trouble.			 */			if (iroute == NULL)			{				printf("ip[%d]: no route to ",					ip_port-ip_port_table);				writeIpAddr(dest);				printf("\n");			}			icmp_snd_unreachable(ip_port->ip_port, pack,				ICMP_HOST_UNRCH);			continue;		}		next_port= &ip_port_table[iroute->irt_port];		if (ip_hdr->ih_flags_fragoff & HTONS(IH_DONT_FRAG))		{			req_mtu= bf_bufsize(pack);			if (req_mtu > next_port->ip_mtu ||				(iroute->irt_mtu && req_mtu>iroute->irt_mtu))			{				icmp_snd_mtu(ip_port->ip_port, pack,					next_port->ip_mtu);				continue;			}		}		if (next_port != ip_port)		{			if (iroute->irt_gateway != 0)			{				/* Just send the packet to the next gateway */				pack->acc_linkC++; /* Extra ref for ICMP */				r= next_port->ip_dev_send(next_port,					iroute->irt_gateway,					pack, IP_LT_NORMAL);				if (r == EDSTNOTRCH)				{					printf("ip[%d]: gw ",						ip_port-ip_port_table);					writeIpAddr(iroute->irt_gateway);					printf(" on ip[%d] is down for dest ",						next_port-ip_port_table);					writeIpAddr(dest);					printf("\n");					icmp_snd_unreachable(next_port-						ip_port_table, pack,						ICMP_HOST_UNRCH);					pack= NULL;				}				else				{					assert(r == 0);					bf_afree(pack); pack= NULL;				}				continue;			}			/* The packet is for the attached network. Special			 * addresses are the ip address of the interface and			 * net.0 if no IP_42BSD_BCAST.			 */			if (dest == next_port->ip_ipaddr)			{				ip_port_arrive (next_port, pack, ip_hdr);				continue;			}			if (dest == iroute->irt_dest)			{				/* Never forward obsolete directed broadcasts */#if IP_42BSD_BCAST && 0				type= IP_LT_BROADCAST;#else				/* Bogus destination address */				DBLOCK(1, printf(			"ip[%d]: dropping old-fashioned directed broadcast ",						ip_port-ip_port_table);					writeIpAddr(dest);					printf("\n"););				icmp_snd_unreachable(next_port-ip_port_table,					pack, ICMP_HOST_UNRCH);				continue;#endif			}			else if (dest == (iroute->irt_dest |				~iroute->irt_subnetmask))			{				if (!ip_forward_directed_bcast)				{					/* Do not forward directed broadcasts */					DBLOCK(1, printf(					"ip[%d]: dropping directed broadcast ",							ip_port-ip_port_table);						writeIpAddr(dest);						printf("\n"););					icmp_snd_unreachable(next_port-						ip_port_table, pack,						ICMP_HOST_UNRCH);					continue;				}				else					type= IP_LT_BROADCAST;			}			else				type= IP_LT_NORMAL;			/* Just send the packet to it's destination */			pack->acc_linkC++; /* Extra ref for ICMP */			r= next_port->ip_dev_send(next_port, dest, pack, type);			if (r == EDSTNOTRCH)			{				DBLOCK(1, printf("ip[%d]: next hop ",					ip_port-ip_port_table);					writeIpAddr(dest);					printf(" on ip[%d] is down\n",					next_port-ip_port_table););				icmp_snd_unreachable(next_port-ip_port_table,					pack, ICMP_HOST_UNRCH);				pack= NULL;			}			else			{				assert(r == 0 || (printf("r = %d\n", r), 0));				bf_afree(pack); pack= NULL;			}			continue;		}		/* Now we know that the packet should be routed over the same		 * network as it came from. If there is a next hop gateway,		 * we can send the packet to that gateway and send a redirect		 * ICMP to the sender if the sender is on the attached		 * network. If there is no gateway complain.		 */		if (iroute->irt_gateway == 0)		{			printf("ip_arrived: packet should not be here, src=");			writeIpAddr(ip_hdr->ih_src);			printf(" dst=");			writeIpAddr(ip_hdr->ih_dst);			printf("\n");			bf_afree(pack);			continue;		}		if (((ip_hdr->ih_src ^ ip_port->ip_ipaddr) &			ip_port->ip_subnetmask) == 0)		{			/* Finding out if we can send a network redirect			 * instead of a host redirect is too much trouble.			 */			pack->acc_linkC++;			icmp_snd_redirect(ip_port->ip_port, pack,				ICMP_REDIRECT_HOST, iroute->irt_gateway);		}		else		{			printf("ip_arrived: packet is wrongly routed, src=");			writeIpAddr(ip_hdr->ih_src);			printf(" dst=");			writeIpAddr(ip_hdr->ih_dst);			printf("\n");			printf("in port %d, output %d, dest net ",				ip_port->ip_port, 				iroute->irt_port);			writeIpAddr(iroute->irt_dest);			printf("/");			writeIpAddr(iroute->irt_subnetmask);			printf(" next hop ");			writeIpAddr(iroute->irt_gateway);			printf("\n");			bf_afree(pack);			continue;		}		/* No code for unreachable ICMPs here. The sender should		 * process the ICMP redirect and figure it out.		 */		ip_port->ip_dev_send(ip_port, iroute->irt_gateway, pack,			IP_LT_NORMAL);	}}PRIVATE int broadcast_dst(ip_port, dest)ip_port_t *ip_port;ipaddr_t dest;{	ipaddr_t my_ipaddr, netmask, classmask;	/* Treat class D (multicast) address as broadcasts. */	if ((dest & HTONL(0xF0000000)) == HTONL(0xE0000000))	{		return 1;	}	/* Accept without complaint if netmask not yet configured. */	if (!(ip_port->ip_flags & IPF_NETMASKSET))	{		return 1;	}	/* Two possibilities, 0 (iff IP_42BSD_BCAST) and -1 */	if (dest == HTONL((ipaddr_t)-1))		return 1;#if IP_42BSD_BCAST	if (dest == HTONL((ipaddr_t)0))		return 1;#endif	netmask= ip_port->ip_subnetmask;	my_ipaddr= ip_port->ip_ipaddr;	if (((my_ipaddr ^ dest) & netmask) != 0)	{		classmask= ip_port->ip_classfulmask;		/* Not a subnet broadcast, maybe a classful broadcast */		if (((my_ipaddr ^ dest) & classmask) != 0)		{			return 0;		}		/* Two possibilities, net.0 (iff IP_42BSD_BCAST) and net.-1 */		if ((dest & ~classmask) == ~classmask)		{			return 1;		}#if IP_42BSD_BCAST		if ((dest & ~classmask) == 0)			return 1;#endif		return 0;	}	if (!(ip_port->ip_flags & IPF_SUBNET_BCAST))		return 0;	/* No subnet broadcasts on this network */	/* Two possibilities, subnet.0 (iff IP_42BSD_BCAST) and subnet.-1 */	if ((dest & ~netmask) == ~netmask)		return 1;#if IP_42BSD_BCAST	if ((dest & ~netmask) == 0)		return 1;#endif	return 0;}void ip_process_loopb(ev, arg)event_t *ev;ev_arg_t arg;{	ip_port_t *ip_port;	acc_t *pack;	ip_port= arg.ev_ptr;	assert(ev == &ip_port->ip_loopb_event);	while(pack= ip_port->ip_loopb_head, pack != NULL)	{		ip_port->ip_loopb_head= pack->acc_ext_link;		ip_arrived(ip_port, pack);	}}/* * $PchId: ip_read.c,v 1.33 2005/06/28 14:18:50 philip Exp $ */

⌨️ 快捷键说明

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