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

📄 ip.c

📁 操作系统源代码
💻 C
字号:
/*ip.c*/#include "inet.h"#include "buf.h"#include "type.h"#include "arp.h"#include "assert.h"#include "clock.h"#include "eth.h"#include "icmp.h"#include "icmp_lib.h"#include "io.h"#include "ip.h"#include "ip_int.h"#include "ipr.h"#include "sr.h"INIT_PANIC();FORWARD void ip_eth_main ARGS(( ip_port_t *port ));FORWARD void ip_close ARGS(( int fd ));FORWARD int ip_cancel ARGS(( int fd, int which_operation ));FORWARD acc_t *get_eth_data ARGS(( int fd, size_t offset,	size_t count, int for_ioctl ));FORWARD int put_eth_data ARGS(( int fd, size_t offset,	acc_t *data, int for_ioctl ));FORWARD void rarp_func ARGS(( int fd, ipaddr_t ipaddr ));FORWARD void do_eth_read ARGS(( ip_port_t *port ));#if IP_ROUTERFORWARD void ip_route ARGS(( ip_port_t *port, acc_t *pack ));#endif /* IP_ROUTER */PUBLIC ip_port_t ip_port_table[IP_PORT_NR];PUBLIC ip_fd_t ip_fd_table[IP_FD_NR];PUBLIC ip_ass_t ip_ass_table[IP_ASS_NR];PRIVATE int ip_cancel (fd, which_operation)int fd;int which_operation;{	ip_fd_t *ip_fd;	acc_t *repl_res;	int result;	ip_fd= &ip_fd_table[fd];	switch (which_operation)	{	case SR_CANCEL_IOCTL:assert (ip_fd->if_flags & IFF_GIPCONF_IP);		ip_fd->if_flags &= ~IFF_GIPCONF_IP;		repl_res= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, 			(size_t)EINTR, (size_t)0, TRUE);assert (!repl_res);		break;	case SR_CANCEL_READ:assert (ip_fd->if_flags & IFF_READ_IP);		ip_fd->if_flags &= ~IFF_READ_IP;		result= (*ip_fd->if_put_userdata)(ip_fd->if_srfd, 			(size_t)EINTR, (acc_t *)0, FALSE);assert (!result);		break;	case SR_CANCEL_WRITE:assert (ip_fd->if_flags & IFF_WRITE_MASK);		ip_fd->if_flags &= ~IFF_WRITE_MASK;		repl_res= (*ip_fd->if_get_userdata)(ip_fd->if_srfd, 			(size_t)EINTR, (size_t)0, FALSE);assert (!repl_res);		break;	default:		ip_panic(( "unknown cancel request" ));		break;	}	return NW_OK;}PUBLIC void ip_init(){	int i, result;	ip_ass_t *ip_ass;	ip_fd_t *ip_fd;	ip_port_t *ip_port;	assert (BUF_S >= sizeof(struct nwio_ethopt));	assert (BUF_S >= IP_MAX_HDR_SIZE + ETH_HDR_SIZE);	assert (BUF_S >= sizeof(nwio_ipopt_t));	assert (BUF_S >= sizeof(nwio_route_t));	ip_port_table[0].ip_dl.dl_eth.de_port= ETH0;	ip_port_table[0].ip_dl_type= IPDL_ETH;	ip_port_table[0].ip_minor= IP_DEV0;	for (i=0, ip_ass= ip_ass_table; i<IP_ASS_NR; i++, ip_ass++)	{		ip_ass->ia_frags= 0;		ip_ass->ia_first_time= 0;		ip_ass->ia_port= 0;	}	for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)	{		ip_fd->if_flags= IFF_EMPTY;	}	for (i=0, ip_port= ip_port_table; i<IP_PORT_NR; i++, ip_port++)	{		ip_port->ip_flags= IPF_EMPTY;		switch(ip_port->ip_dl_type)		{		case IPDL_ETH:			ip_port->ip_dl.dl_eth.de_state= IES_EMPTY;			ip_port->ip_dl.dl_eth.de_flags= IEF_EMPTY;			break;		default:			ip_panic(( "unknown ip_dl_type" ));			break;		}	}	icmp_init();	ipr_init();	for (i=0, ip_port= ip_port_table; i<IP_PORT_NR; i++, ip_port++)	{		ip_port->ip_frame_id= (u16_t)get_time();		result= sr_add_minor(ip_port->ip_minor,			ip_port-ip_port_table, ip_open, ip_close,			ip_read, ip_write, ip_ioctl, ip_cancel);		assert (result>=0);		switch(ip_port->ip_dl_type)		{		case IPDL_ETH:			ip_eth_main(ip_port);			break;		default:			ip_panic(( "unknown ip_dl_type" ));		}	}}PRIVATE void ip_eth_main(ip_port)ip_port_t *ip_port;{	int result, i;	ip_fd_t *ip_fd;	switch (ip_port->ip_dl.dl_eth.de_state)	{	case IES_EMPTY:		ip_port->ip_dl.dl_eth.de_wr_ipaddr= (ipaddr_t)0;		ip_port->ip_dl.dl_eth.de_state= IES_SETPROTO;		ip_port->ip_dl.dl_eth.de_fd= eth_open(ip_port->			ip_dl.dl_eth.de_port, ip_port-ip_port_table,			get_eth_data, put_eth_data);		if (ip_port->ip_dl.dl_eth.de_fd < 0)		{			printf("ip.c: unable to open eth port\n");			return;		}		result= eth_ioctl(ip_port->ip_dl.dl_eth.de_fd,			NWIOSETHOPT);		if (result == NW_SUSPEND)			ip_port->ip_dl.dl_eth.de_flags |= IEF_SUSPEND;		if (result<0)		{#if DEBUG { where(); printf("eth_ioctl(..,%lx)=%d\n", NWIOSETHOPT, result); }#endif			return;		}		if (ip_port->ip_dl.dl_eth.de_state != IES_SETPROTO)			return;		/* drops through */	case IES_SETPROTO:		ip_port->ip_dl.dl_eth.de_state= IES_GETIPADDR;		result= rarp_req (ip_port->ip_dl.dl_eth.de_port,			ip_port-ip_port_table, rarp_func);		if (result == NW_SUSPEND)			ip_port->ip_dl.dl_eth.de_flags |= IEF_SUSPEND;		if (result<0)		{#if DEBUG & 256 { where(); printf("rarp_req(...)=%d\n", result); }#endif			return;		}		if (ip_port->ip_dl.dl_eth.de_state != IES_GETIPADDR)			return;		/* drops through */	case IES_GETIPADDR:		ip_port->ip_dl.dl_eth.de_state= IES_MAIN;		for (i=0, ip_fd= ip_fd_table; i<IP_FD_NR; i++, ip_fd++)		{			if (!(ip_fd->if_flags & IFF_INUSE))			{#if DEBUG & 256 { where(); printf("%d not inuse\n", i); }#endif				continue;			}			if (ip_fd->if_port != ip_port)			{#if DEBUG { where(); printf("%d wrong port\n", i); }#endif				continue;			}#if DEBUG & 256 { where(); printf("(ip_fd_t *)0x%x->if_flags= 0x%x\n", ip_fd, ip_fd->if_flags); }#endif			if (ip_fd->if_flags & IFF_WRITE_IP)			{#if DEBUG { where(); printf("%d write ip\n", i); }#endif				ip_fd->if_flags &= ~IFF_WRITE_IP;				ip_write (i, ip_fd->if_wr_count);			}			if (ip_fd->if_flags & IFF_GIPCONF_IP)			{#if DEBUG  & 256 { where(); printf("restarting ip_ioctl (.., NWIOGIPCONF)\n"); }#endif				ip_ioctl (i, NWIOGIPCONF);			}		}#if DEBUG & 256 { where(); printf("ip_port->ip_ipaddr= "); writeIpAddr(ip_port->ip_ipaddr); 	printf("\n"); }#endif		icmp_getnetmask(ip_port-ip_port_table);		do_eth_read(ip_port);		return;	default:		ip_panic(( "unknown state" ));	}}PRIVATE acc_t *get_eth_data (fd, offset, count, for_ioctl)int fd;size_t offset;size_t count;int for_ioctl;{	ip_port_t *port;	acc_t *data;	int result;#if DEBUG & 256 { where(); printf("get_eth_data(fd= %d, offset= %d, count= %u) called\n",		fd, offset, count); }#endif	port= &ip_port_table[fd];	switch (port->ip_dl.dl_eth.de_state)	{	case IES_SETPROTO:		if (!count)		{			result= (int)offset;			if (result<0)			{				port->ip_dl.dl_eth.de_state= IES_ERROR;				break;			}			if (port->ip_dl.dl_eth.de_flags & IEF_SUSPEND)				ip_eth_main(port);			return NW_OK;		}		assert ((!offset) && (count == sizeof(struct nwio_ethopt)));		{			struct nwio_ethopt *ethopt;			acc_t *acc;			acc= bf_memreq(sizeof(*ethopt));			ethopt= (struct nwio_ethopt *)ptr2acc_data(acc);			ethopt->nweo_flags= NWEO_COPY|NWEO_EN_BROAD|				NWEO_TYPESPEC;			ethopt->nweo_type= htons(ETH_IP_PROTO);			return acc;		}	case IES_MAIN:		assert (port->ip_dl.dl_eth.de_flags & IEF_WRITE_IP);		if (!count)		{			result= (int)offset;#if DEBUG & 256 { where(); printf("get_eth_data: result= %d\n", result); }#endif			if (result<0)				printf("ip.c: error on write: %d\n",					result);			bf_afree (port->ip_dl.dl_eth.de_wr_frame);			port->ip_dl.dl_eth.de_wr_frame= 0;#if DEBUG & 256 { where(); printf("eth_write completed\n"); }#endif			if (port->ip_dl.dl_eth.de_flags & IEF_WRITE_SP)			{#if DEBUG & 256 { where(); printf("calling dl_eth_write_frame\n"); }#endif				port->ip_dl.dl_eth.de_flags &=					~(IEF_WRITE_SP|IEF_WRITE_IP);				dll_eth_write_frame(port);			}#if DEBUG & 256 else { where(); printf("not calling dl_eth_write_frame\n"); }#endif			return NW_OK;		}#if DEBUG & 256 { where(); printf("supplying data for eth\n"); }#endif		data= bf_cut (port->ip_dl.dl_eth.de_wr_frame, offset,			count);		assert (data);		return data;	default:		printf("get_eth_data(%d, 0x%d, 0x%d) called but ip_state=0x%x\n",			fd, offset, count, port->ip_dl.dl_eth.de_state);		break;	}	return 0;}PRIVATE void rarp_func (port, ipaddr)int port;ipaddr_t ipaddr;{	ip_port_t *ip_port;#if DEBUG & 256 { where(); printf("rarp_func\n"); }#endif	ip_port= &ip_port_table[port];	if (!(ip_port->ip_flags & IPF_IPADDRSET))	{		ip_port->ip_ipaddr= ipaddr;		ip_port->ip_flags |= IPF_IPADDRSET;	}	switch (ip_port->ip_dl_type)	{	case IPDL_ETH:		if (ip_port->ip_dl.dl_eth.de_flags & IEF_SUSPEND)			ip_eth_main(ip_port);		break;	default:		ip_panic(( "unknown dl_type" ));	}}PRIVATE void do_eth_read(port)ip_port_t *port;{	int result;	while (!(port->ip_dl.dl_eth.de_flags & IEF_READ_IP))	{		port->ip_dl.dl_eth.de_flags &= ~IEF_READ_SP;		port->ip_dl.dl_eth.de_flags |= IEF_READ_IP;		result= eth_read (port->ip_dl.dl_eth.de_fd,			ETH_MAX_PACK_SIZE);		if (result == NW_SUSPEND)			port->ip_dl.dl_eth.de_flags |= IEF_READ_SP;		if (result<0)		{#if DEBUG & 256 { where(); printf("eth_read(%d, ...)= %d\n", port->ip_dl.dl_eth.de_fd,	result); }#endif			return;		}		port->ip_dl.dl_eth.de_flags &= ~IEF_READ_IP;	}}PRIVATE int put_eth_data (port, offset, data, for_ioctl)int port;size_t offset;acc_t *data;int for_ioctl;{	ip_port_t *ip_port;	acc_t *pack;	int result;#if DEBUG & 256 { where(); printf("put_eth_data() called\n"); }#endif	ip_port= &ip_port_table[port];	if (ip_port->ip_dl.dl_eth.de_flags & IEF_READ_IP)	{		if (!data)		{			result= (int)offset;			if (result<0)			{#if DEBUG { where(); printf("ip.c: put_eth_data(..,%d,..)\n", result); }#endif				return NW_OK;			}			ip_port->ip_dl.dl_eth.de_flags &= ~IEF_READ_IP;			if (ip_port->ip_dl.dl_eth.de_flags &				IEF_READ_SP)			{				do_eth_read(ip_port);			}			return NW_OK;		}		assert (!offset);		/* Warning: the above assertion is illegal; puts and		   gets of data can be brokenup in any piece the server		   likes. However we assume that the server is eth.c		   and it transfers only whole packets. */		ip_eth_arrived(ip_port, data);		return NW_OK;	}	printf("ip_port->ip_dl.dl_eth.de_state= 0x%x",		ip_port->ip_dl.dl_eth.de_state);	ip_panic (( "strange status" ));}PUBLIC int ip_open (port, srfd, get_userdata, put_userdata)int port;int srfd;get_userdata_t get_userdata;put_userdata_t put_userdata;{	int i;	ip_fd_t *ip_fd;	for (i=0; i<IP_FD_NR && (ip_fd_table[i].if_flags & IFF_INUSE);		i++);	if (i>=IP_FD_NR)	{#if DEBUG { where(); printf("out of fds\n"); }#endif		return EOUTOFBUFS;	}	ip_fd= &ip_fd_table[i];	ip_fd->if_flags= IFF_INUSE;	ip_fd->if_ipopt.nwio_flags= NWIO_DEFAULT;	ip_fd->if_ipopt.nwio_tos= 0;	ip_fd->if_ipopt.nwio_df= FALSE;	ip_fd->if_ipopt.nwio_ttl= 255;	ip_fd->if_ipopt.nwio_hdropt.iho_opt_siz= 0;	ip_fd->if_port= &ip_port_table[port];	ip_fd->if_srfd= srfd;	ip_fd->if_rd_buf= 0;	ip_fd->if_get_userdata= get_userdata;	ip_fd->if_put_userdata= put_userdata;	return i;}PRIVATE void ip_close (fd)int fd;{	ip_fd_t *ip_fd;	ip_fd= &ip_fd_table[fd];	assert ((ip_fd->if_flags & IFF_INUSE) &&		!(ip_fd->if_flags & IFF_BUSY));	ip_fd->if_flags= IFF_EMPTY;	if (ip_fd->if_rd_buf)	{		bf_afree(ip_fd->if_rd_buf);		ip_fd->if_rd_buf= 0;	}}

⌨️ 快捷键说明

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