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

📄 ip_write.c

📁 最新Minix3源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*ip_write.c*/#include "inet.h"#include "buf.h"#include "type.h"#include "arp.h"#include "assert.h"#include "clock.h"#include "eth.h"#include "icmp_lib.h"#include "io.h"#include "ip.h"#include "ip_int.h"#include "ipr.h"INIT_PANIC();FORWARD acc_t *get_packet ARGS(( ip_fd_t *ip_fd,	U16_t id /* should be: u16_t id */ ));FORWARD int dll_ready ARGS(( ip_port_t *port, ipaddr_t dst ));FORWARD void dll_write ARGS(( ip_port_t *port, ipaddr_t dst,	acc_t *pack ));FORWARD int dll_eth_ready ARGS(( ip_port_t *port, ipaddr_t dst ));FORWARD void dll_eth_write ARGS(( ip_port_t *port, ipaddr_t dst,	acc_t *pack ));FORWARD void dll_eth_arp_func ARGS(( int fd,	ether_addr_t *ethaddr ));FORWARD acc_t *ip_split_pack ARGS(( acc_t **ref_last,	int first_size ));FORWARD void error_reply ARGS(( ip_fd_t *fd, int error ));FORWARD int chk_dstaddr ARGS(( ipaddr_t dst ));FORWARD void restart_netbroadcast ARGS(( void ));FORWARD int ip_localroute_addr ARGS(( ip_fd_t *ip_fd ));FORWARD void ip_remroute_addr ARGS(( ip_fd_t *ip_fd, U8_t ttl ));FORWARD void restart_fd_write ARGS(( ip_fd_t *ip_fd ));FORWARD void restart_netbroad_fd ARGS(( ip_fd_t *tcp_fd ));FORWARD void dll_eth_get_work ARGS(( ip_port_t *ip_port ));#define NF_EMPTY		0#define NF_INUSE		1#define NF_SUSPENDED		2PRIVATE unsigned int netbroad_flags= NF_EMPTY;PRIVATE acc_t *netbroad_pack;PRIVATE ipaddr_t netbroad_dst;PRIVATE ipaddr_t netbroad_netmask;PRIVATE ip_port_t *netbroad_port;PUBLIC int ip_write (fd, count)int fd;size_t count;{	ip_fd_t *ip_fd;	acc_t *data;	int result;	int ttl;#if DEBUG & 256 { where(); printf("ip_write.c: ip_write(fd= %d, count= %d\n", fd,	count); }#endif	ip_fd= &ip_fd_table[fd];	if (!(ip_fd->if_flags & IFF_OPTSET))	{		error_reply (ip_fd, EBADMODE);		return NW_OK;	}	if (ip_fd->if_ipopt.nwio_flags & NWIO_RWDATALL)	{		if (count < IP_MIN_HDR_SIZE || count > IP_MAX_PACKSIZE)		{			error_reply (ip_fd, EPACKSIZE);			return NW_OK;		}	}	else	{assert (ip_fd->if_ipopt.nwio_flags & NWIO_RWDATONLY);		if (count < 0 || count > IP_MAX_PACKSIZE-IP_MIN_HDR_SIZE)		{			error_reply (ip_fd, EPACKSIZE);			return NW_OK;		}	}	ip_fd->if_wr_count= count;	assert (!(ip_fd->if_flags & IFF_WRITE_IP));	ip_fd->if_flags &= ~IFF_WRITE_MASK;	ip_fd->if_flags |= IFF_WRITE_IP;	if (!(ip_fd->if_port->ip_flags & IPF_IPADDRSET))		return NW_SUSPEND;	if (ip_fd->if_ipopt.nwio_flags & NWIO_REMSPEC)		ip_fd->if_wr_dstaddr= ip_fd->if_ipopt.nwio_rem;	else	{		data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,			(size_t)(offsetof (struct ip_hdr, ih_dst)),			sizeof(ipaddr_t), FALSE);		if (!data)		{			ip_fd->if_flags &= ~IFF_WRITE_IP;			return NW_OK;		}		data= bf_packIffLess (data, sizeof(ipaddr_t));		ip_fd->if_wr_dstaddr= *(ipaddr_t *)ptr2acc_data(data);		bf_afree(data);		data= 0;	}	if (ip_fd->if_ipopt.nwio_flags & NWIO_HDR_O_SPEC)		ttl= 255;				/* For traceroute */	else	{		data= (*ip_fd->if_get_userdata)(ip_fd->if_srfd,			(size_t)(offsetof (struct ip_hdr, ih_ttl)),			sizeof(u8_t), FALSE);		if (!data)		{			ip_fd->if_flags &= ~IFF_WRITE_IP;			return NW_OK;		}		data= bf_packIffLess (data, sizeof(u8_t));		ttl= *(u8_t *)ptr2acc_data(data);		bf_afree(data);		data= 0;	}	result= ip_localroute_addr(ip_fd);	if (!result)		ip_remroute_addr(ip_fd, ttl);	if (ip_fd->if_flags & IFF_WRITE_IP)		return NW_SUSPEND;	else		return NW_OK;}PRIVATE int ip_localroute_addr (ip_fd)ip_fd_t *ip_fd;{	ipaddr_t dstaddr, netmask;	u8_t *addrInBytes;	acc_t *pack;	ip_hdr_t *hdr_ptr;	ip_port_t *ip_port;	int result, i;#if DEBUG & 256 { where(); printf("ip_write.c: ip_route_addr(...) to ");	writeIpAddr(ip_fd->if_wr_dstaddr); printf("\n"); }#endif	dstaddr= ip_fd->if_wr_dstaddr;	addrInBytes= (u8_t *)&dstaddr;	ip_port= ip_fd->if_port;	if ((addrInBytes[0] & 0xff) == 0x7f)	/* local loopback */	{		pack= get_packet(ip_fd, (u16_t)0);		if (!pack)		{			ip_fd->if_flags &= ~IFF_WRITE_IP;			return TRUE;		}		assert (pack->acc_length >= IP_MIN_HDR_SIZE);		assert (pack->acc_linkC == 1);		hdr_ptr= (ip_hdr_t *)ptr2acc_data(pack);		dstaddr= hdr_ptr->ih_dst;	/* src and dst						   addresses */		hdr_ptr->ih_dst= hdr_ptr->ih_src;		hdr_ptr->ih_src= dstaddr;		ip_port_arrive (ip_port, pack, hdr_ptr);		ip_fd->if_flags &= ~IFF_WRITE_IP;		error_reply (ip_fd, ip_fd->if_wr_count);		return TRUE;	}	if (dstaddr == (ipaddr_t)-1)	{		ip_fd->if_flags |= IFF_DLL_WR_IP;		ip_fd->if_wr_port= ip_port;#if DEBUG { where(); printf("calling restart_fd_write\n"); }#endif		restart_fd_write(ip_fd);		return TRUE;	}	netmask= ip_get_netmask(dstaddr);	for (i=0, ip_port= ip_port_table; i<IP_PORT_NR; i++, ip_port++)	{		if (!(ip_port->ip_flags & IPF_IPADDRSET))		{#if DEBUG  { where(); printf("!(ip_port_table[%d].ip_flags & IPF_IPADDRSET)\n",	ip_port-ip_port_table); }#endif			continue;		}#if DEBUG & 256 { where(); printf("ip_port_table[%d].ip_ipaddr=  ", ip_port-ip_port_table);	writeIpAddr(ip_port->ip_ipaddr); printf("\n"); }#endif		if (ip_port->ip_ipaddr == dstaddr)		{			pack= get_packet(ip_fd, (u16_t)0);			if (!pack)			{				ip_fd->if_flags &= ~IFF_WRITE_IP;				return TRUE;			}			assert (pack->acc_length >= IP_MIN_HDR_SIZE);			assert (pack->acc_linkC == 1);			ip_port_arrive (ip_port, pack, 				(ip_hdr_t *)ptr2acc_data(pack));			ip_fd->if_flags &= ~IFF_WRITE_IP;			error_reply (ip_fd, ip_fd->if_wr_count);			return TRUE;		}		if ((dstaddr & ip_port->ip_netmask) ==			(ip_port->ip_ipaddr & ip_port->ip_netmask))		{			ip_fd->if_wr_port= ip_port;			if ((dstaddr & ~ip_port->ip_netmask) ==				~ip_port->ip_netmask)				ip_fd->if_wr_dstaddr= (ipaddr_t)-1;			ip_fd->if_flags |= IFF_DLL_WR_IP;#if DEBUG & 256 { where(); printf("calling restart_fd_write\n"); }#endif			restart_fd_write(ip_fd);			return TRUE;		}		if (((dstaddr & netmask) == (ip_port->ip_ipaddr &			netmask)) && ((dstaddr & ~netmask) == ~netmask))		{			if (!(netbroad_flags & NF_INUSE))				restart_netbroad_fd(ip_fd);			else				ip_fd->if_flags |= IFF_NETBROAD_IP;			return TRUE;		}	}	return FALSE;}PRIVATE int dll_ready(port, dst)ip_port_t *port;ipaddr_t dst;{	switch (port->ip_dl_type)	{	case IPDL_ETH:		return dll_eth_ready (port, dst);	default:		ip_panic(( "strange dll_type" ));	}	return NW_OK;}PRIVATE int dll_eth_ready (port, dst)ip_port_t *port;ipaddr_t dst;{	int result;	if (port->ip_dl.dl_eth.de_wr_frame || port->ip_dl.dl_eth.		de_wr_frag)	{#if DEBUG & 256 { where(); printf("dll_eth_ready: frame or frag present\n"); }#endif		return NW_SUSPEND;	}	if (dst == (ipaddr_t)-1)	{#if DEBUG & 256 { where(); printf("dll_eth_ready: broadcast\n"); }#endif		port->ip_dl.dl_eth.de_wr_ipaddr= dst;		port->ip_dl.dl_eth.de_wr_ethaddr.ea_addr[0]= 0xff;		port->ip_dl.dl_eth.de_wr_ethaddr.ea_addr[1]= 0xff;		port->ip_dl.dl_eth.de_wr_ethaddr.ea_addr[2]= 0xff;		port->ip_dl.dl_eth.de_wr_ethaddr.ea_addr[3]= 0xff;		port->ip_dl.dl_eth.de_wr_ethaddr.ea_addr[4]= 0xff;		port->ip_dl.dl_eth.de_wr_ethaddr.ea_addr[5]= 0xff;		return NW_OK;	}#if DEBUG & 256 { where(); printf("ip_write.c: calling arp_ip_eth_nonbl(...)\n"); }#endif	result= arp_ip_eth_nonbl (port->ip_dl.dl_eth.de_port,		dst, &port->ip_dl.dl_eth.de_wr_ethaddr);#if DEBUG & 256 { where(); printf("ip_write.c: arp_ip_eth_nonbl(...)= %d\n", result); }#endif	if (result<0)		port->ip_dl.dl_eth.de_wr_ipaddr= (ipaddr_t)0;	if (result == EDSTNOTRCH)		return EDSTNOTRCH;	if (result >= 0)	{		port->ip_dl.dl_eth.de_wr_ipaddr= dst;		return NW_OK;	}assert (result == NW_SUSPEND);	if (!(port->ip_dl.dl_eth.de_flags & IEF_ARP_IP))	{#if DEBUG & 256 { where(); printf("dll_eth_ready: no ARP_IP\n"); }#endif		return NW_OK;	}#if DEBUG { where(); printf("dll_eth_ready: ARP_IP\n"); }#endif	return NW_SUSPEND;}PRIVATE void dll_write (port, dst, pack)ip_port_t *port;ipaddr_t dst;acc_t *pack;{	switch (port->ip_dl_type)	{	case IPDL_ETH:		dll_eth_write (port, dst, pack);		break;	default:		ip_panic(( "wrong dl_type" ));		break;	}}PRIVATE void dll_eth_write (ip_port, dst, pack)ip_port_t *ip_port;ipaddr_t dst;acc_t *pack;{	int result;	if (!ip_port->ip_dl.dl_eth.de_wr_frag)	{		if (ip_port->ip_dl.dl_eth.de_wr_ipaddr == dst)		{			ip_port->ip_dl.dl_eth.de_wr_frag= pack;			if (!(ip_port->ip_dl.dl_eth.de_flags &				IEF_WRITE_IP))			{				dll_eth_write_frame(ip_port);			}			return;		}		ip_port->ip_dl.dl_eth.de_wr_ipaddr= (ipaddr_t)0;#if DEBUG & 256 { where(); printf("ip_write.c: calling arp_ip_eth_nonbl(...)\n"); }#endif		result= arp_ip_eth_nonbl (ip_port->ip_dl.dl_eth.de_port,			dst, &ip_port->ip_dl.dl_eth.de_wr_ethaddr);#if DEBUG & 256 { where(); printf("ip_write.c: arp_ip_eth_nonbl(...)= %d\n", result); }#endif		if (result == NW_OK)		{			ip_port->ip_dl.dl_eth.de_wr_frag= pack;			if (!(ip_port->ip_dl.dl_eth.de_flags &				IEF_WRITE_IP))				dll_eth_write_frame(ip_port);			return;		}	}	assert (!(ip_port->ip_dl.dl_eth.de_flags & IEF_ARP_MASK));	ip_port->ip_dl.dl_eth.de_arp_pack= pack;	ip_port->ip_dl.dl_eth.de_flags |= IEF_ARP_IP;#if DEBUG & 256 { where(); printf("ip_write.c: calling arp_ip_eth(...)\n"); }#endif	result= arp_ip_eth (ip_port->ip_dl.dl_eth.de_port,		ip_port-ip_port_table, dst, dll_eth_arp_func);#if DEBUG & 256 { where(); printf("ip_write.c: arp_ip_eth(...)= %d\n", result); }#endif	if (result == NW_SUSPEND)		ip_port->ip_dl.dl_eth.de_flags |= IEF_ARP_SP;	else if (result == EDSTNOTRCH)	{		if (ip_port->ip_dl.dl_eth.de_arp_pack)		{			bf_afree(ip_port->ip_dl.dl_eth.de_arp_pack);			ip_port->ip_dl.dl_eth.de_arp_pack= 0;		}		ip_port->ip_dl.dl_eth.de_flags &= ~IEF_ARP_MASK;	}	else	{		assert (result == NW_OK);		assert (ip_port->ip_dl.dl_eth.de_flags & IEF_WRITE_IP);	}}PUBLIC void dll_eth_write_frame (ip_port)ip_port_t *ip_port;{	acc_t *frag, *frame, *hdr, *tail;	eth_hdr_t *eth_hdr;	size_t pack_size;	int result;#if DEBUG & 256 { where(); printf("ip_write.c: dll_eth_write_frame(...)\n"); }#endifassert (!(ip_port->ip_dl.dl_eth.de_flags & IEF_WRITE_IP));	ip_port->ip_dl.dl_eth.de_flags |= IEF_WRITE_IP;	do	{		if (!ip_port->ip_dl.dl_eth.de_wr_frag)		{			dll_eth_get_work (ip_port);			if (!ip_port->ip_dl.dl_eth.de_wr_frag)			{				ip_port->ip_dl.dl_eth.de_flags &=					~IEF_WRITE_IP;				return;			}		}assert (!ip_port->ip_dl.dl_eth.de_wr_frame);assert (ip_port->ip_dl.dl_eth.de_wr_frag);		frag= ip_port->ip_dl.dl_eth.de_wr_frag;		ip_port->ip_dl.dl_eth.de_wr_frag= 0;		frame= ip_split_pack(&frag, ETH_MAX_PACK_SIZE-			ETH_HDR_SIZE);		if (!frame)		{			assert (!frag);			continue;		}		ip_port->ip_dl.dl_eth.de_wr_frag= frag;		hdr= bf_memreq(ETH_HDR_SIZE);		eth_hdr= (eth_hdr_t *)ptr2acc_data(hdr);		eth_hdr->eh_dst= ip_port->ip_dl.dl_eth.de_wr_ethaddr;		hdr->acc_next= frame;		frame= hdr;		hdr= 0;		pack_size= bf_bufsize(frame);		if (pack_size<ETH_MIN_PACK_SIZE)		{#if DEBUG & 256 { where(); printf("pack_size= %d\n", pack_size); }#endif			tail= bf_memreq(ETH_MIN_PACK_SIZE-pack_size);			frame= bf_append(frame, tail);		}#if DEBUG & 256 { where(); printf("packet size= %d\n", bf_bufsize(ip_port->ip_dl.	dl_eth.de_wr_frame)); }#endif		ip_port->ip_dl.dl_eth.de_wr_frame= frame;		ip_port->ip_dl.dl_eth.de_flags &= ~IEF_WRITE_SP;#if DEBUG & 256 { where(); printf("ip_write.c: calling eth_write(...)\n"); }#endif		result= eth_write (ip_port->ip_dl.dl_eth.de_fd,			bf_bufsize(ip_port->ip_dl.dl_eth.de_wr_frame));#if DEBUG & 256 { where(); printf("ip_write.c: eth_write(...)= %d\n", result); }#endif		if (result == NW_SUSPEND)		{			ip_port->ip_dl.dl_eth.de_flags |= IEF_WRITE_SP;			return;		}	} while (!ip_port->ip_dl.dl_eth.de_wr_frame);	ip_port->ip_dl.dl_eth.de_flags &= ~IEF_WRITE_IP;}PRIVATE void dll_eth_arp_func (port, ethaddr)int port;ether_addr_t *ethaddr;{	ip_port_t *ip_port;#if DEBUG & 256 { where(); printf("ip_write.c: dll_eth_arp_func(port= %d, ...)\n",	port); }#endif	ip_port= &ip_port_table[port];	if (ethaddr && ip_port->ip_dl.dl_eth.de_arp_pack)	{		ip_port->ip_dl.dl_eth.de_arp_ethaddr= *ethaddr;		ip_port->ip_dl.dl_eth.de_flags |= IEF_ARP_COMPL;	}	else	{		if (ip_port->ip_dl.dl_eth.de_arp_pack)		{			bf_afree(ip_port->ip_dl.dl_eth.de_arp_pack);			ip_port->ip_dl.dl_eth.de_arp_pack= 0;		}		ip_port->ip_dl.dl_eth.de_flags &= ~IEF_ARP_MASK;	}	if (!(ip_port->ip_dl.dl_eth.de_flags & IEF_WRITE_IP))		dll_eth_write_frame(ip_port);}PRIVATE void dll_eth_get_work(ip_port)ip_port_t *ip_port;{	int i;	ip_fd_t *ip_fd;	if (ip_port->ip_dl.dl_eth.de_wr_frag)		return;	if ((netbroad_flags & NF_INUSE) && netbroad_port == ip_port)	{		restart_netbroadcast();		if (ip_port->ip_dl.dl_eth.de_wr_frag)			return;	}	if (ip_port->ip_dl.dl_eth.de_flags & IEF_ARP_COMPL)	{

⌨️ 快捷键说明

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