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

📄 psip.c

📁 Minix比较全的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*generic/psip.cImplementation of a pseudo IP device.Created:	Apr 22, 1993 by Philip HomburgCopyright 1995 Philip Homburg*/#include "inet.h"#include "assert.h"#include "buf.h"#include "event.h"#include "type.h"#include "ip_int.h"#include "psip.h"#include "sr.h"THIS_FILEtypedef struct psip_port{	int pp_flags;	int pp_ipdev;	int pp_opencnt;	struct psip_fd *pp_rd_head;	struct psip_fd *pp_rd_tail;	acc_t *pp_promisc_head;	acc_t *pp_promisc_tail;} psip_port_t;#define PPF_EMPTY	0#define PPF_CONFIGURED	1#define PPF_ENABLED	2#define PPF_PROMISC	4#define PSIP_FD_NR	(1*IP_PORT_MAX)typedef struct psip_fd{	int pf_flags;	int pf_srfd;	psip_port_t *pf_port;	get_userdata_t pf_get_userdata;	put_userdata_t pf_put_userdata;	struct psip_fd *pf_rd_next;	size_t pf_rd_count;	nwio_psipopt_t pf_psipopt;} psip_fd_t;#define PFF_EMPTY	0#define PFF_INUSE	1#define PFF_READ_IP	2#define PFF_PROMISC	4#define PFF_NEXTHOP	8PRIVATE psip_port_t *psip_port_table;PRIVATE psip_fd_t psip_fd_table[PSIP_FD_NR];FORWARD int psip_open ARGS(( int port, int srfd,	get_userdata_t get_userdata, put_userdata_t put_userdata,	put_pkt_t pkt_pkt, select_res_t select_res ));FORWARD int psip_ioctl ARGS(( int fd, ioreq_t req ));FORWARD int psip_read ARGS(( int fd, size_t count ));FORWARD int psip_write ARGS(( int fd, size_t count ));FORWARD int psip_select ARGS(( int port_nr, unsigned operations ));FORWARD void psip_close ARGS(( int fd ));FORWARD int psip_cancel ARGS(( int fd, int which_operation ));FORWARD void promisc_restart_read ARGS(( psip_port_t *psip_port ));FORWARD int psip_setopt ARGS(( psip_fd_t *psip_fd, nwio_psipopt_t *newoptp ));FORWARD void psip_buffree ARGS(( int priority ));FORWARD void check_promisc ARGS(( psip_port_t *psip_port ));#ifdef BUF_CONSISTENCY_CHECKFORWARD void psip_bufcheck ARGS(( void ));#endifFORWARD void reply_thr_put ARGS(( psip_fd_t *psip_fd, int reply,	int for_ioctl ));FORWARD void reply_thr_get ARGS(( psip_fd_t *psip_fd, int reply,	int for_ioctl ));PUBLIC void psip_prep(){	psip_port_table= alloc(psip_conf_nr * sizeof(psip_port_table[0]));}PUBLIC void psip_init(){	int i;	psip_port_t *psip_port;	psip_fd_t *psip_fd;	for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)		psip_port->pp_flags= PPF_EMPTY;	for (i=0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)		psip_fd->pf_flags= PFF_EMPTY;	for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)	{		psip_port->pp_flags |= PPF_CONFIGURED;		psip_port->pp_opencnt= 0;		psip_port->pp_rd_head= NULL;		psip_port->pp_promisc_head= NULL;	}#ifndef BUF_CONSISTENCY_CHECK	bf_logon(psip_buffree);#else	bf_logon(psip_buffree, psip_bufcheck);#endif}PUBLIC int psip_enable(port_nr, ip_port_nr)int port_nr;int ip_port_nr;{	psip_port_t *psip_port;	assert(port_nr >= 0);	if (port_nr >= psip_conf_nr)		return -1;	psip_port= &psip_port_table[port_nr];	if (!(psip_port->pp_flags &PPF_CONFIGURED))		return -1;	psip_port->pp_ipdev= ip_port_nr;	psip_port->pp_flags |= PPF_ENABLED;	sr_add_minor(if2minor(psip_conf[port_nr].pc_ifno, PSIP_DEV_OFF),		port_nr, psip_open, psip_close, psip_read,		psip_write, psip_ioctl, psip_cancel, psip_select);	return NW_OK;}PUBLIC int psip_send(port_nr, dest, pack)int port_nr;ipaddr_t dest;acc_t *pack;{	psip_port_t *psip_port;	psip_fd_t *psip_fd, *mark_fd;	int i, result, result1;	size_t buf_size, extrasize;	acc_t *hdr_pack, *acc;	psip_io_hdr_t *hdr;	assert(port_nr >= 0 && port_nr < psip_conf_nr);	psip_port= &psip_port_table[port_nr];	if (psip_port->pp_opencnt == 0)	{		bf_afree(pack);		return NW_OK;	}	for(;;)	{		mark_fd= psip_port->pp_rd_tail;		for(i= 0; i<PSIP_FD_NR; i++)		{			psip_fd= psip_port->pp_rd_head;			if (!psip_fd)				return NW_SUSPEND;			psip_port->pp_rd_head= psip_fd->pf_rd_next;			if (!(psip_fd->pf_flags & PFF_PROMISC))				break;			psip_fd->pf_rd_next= NULL;			if (psip_port->pp_rd_head == NULL)				psip_port->pp_rd_head= psip_fd;			else				psip_port->pp_rd_tail->pf_rd_next= psip_fd;			psip_port->pp_rd_tail= psip_fd;			if (psip_fd == mark_fd)				return NW_SUSPEND;		}		if (i == PSIP_FD_NR)			ip_panic(( "psip_send: loop" ));		assert(psip_fd->pf_flags & PFF_READ_IP);		psip_fd->pf_flags &= ~PFF_READ_IP;		if (psip_fd->pf_flags & PFF_NEXTHOP)			extrasize= sizeof(dest);		else			extrasize= 0;		buf_size= bf_bufsize(pack);		if (buf_size+extrasize <= psip_fd->pf_rd_count)		{			if (psip_port->pp_flags & PPF_PROMISC)			{				/* Deal with promiscuous mode. */				hdr_pack= bf_memreq(sizeof(*hdr));				hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);				memset(hdr, '\0', sizeof(*hdr));				hdr->pih_flags |= PF_LOC2REM;				hdr->pih_nexthop= dest;				pack->acc_linkC++;				hdr_pack->acc_next= pack;				hdr_pack->acc_ext_link= NULL;				if (psip_port->pp_promisc_head)				{					/* Append at the end. */					psip_port->pp_promisc_tail->						acc_ext_link= hdr_pack;					psip_port->pp_promisc_tail= hdr_pack;				}				else				{					/* First packet. */					psip_port->pp_promisc_head= hdr_pack;					psip_port->pp_promisc_tail= hdr_pack;					if (psip_port->pp_rd_head)					    promisc_restart_read(psip_port);				}			}			if (extrasize)			{				/* Prepend nexthop address */				acc= bf_memreq(sizeof(dest));				*(ipaddr_t *)(ptr2acc_data(acc))= dest;				acc->acc_next= pack;				pack= acc; acc= NULL;				buf_size += extrasize;			}			result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 				(size_t)0, pack, FALSE);			if (result == NW_OK)				result= buf_size;		}		else			result= EPACKSIZE;		result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,				(size_t)result, NULL, FALSE);		assert(result1 == NW_OK);		if (result == EPACKSIZE)			continue;		return NW_OK;	}	return NW_SUSPEND;}PRIVATE int psip_open(port, srfd, get_userdata, put_userdata, put_pkt,	select_res)int port;int srfd;get_userdata_t get_userdata;put_userdata_t put_userdata;put_pkt_t put_pkt;select_res_t select_res;{	psip_port_t *psip_port;	psip_fd_t *psip_fd;	int i;	assert(port >= 0 && port < psip_conf_nr);	psip_port= &psip_port_table[port];	if (!(psip_port->pp_flags & PPF_ENABLED))		return ENXIO;	for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)	{		if (psip_fd->pf_flags & PFF_INUSE)			continue;		break;	}	if (i == PSIP_FD_NR)		return ENFILE;	psip_fd->pf_flags |= PFF_INUSE;	psip_fd->pf_srfd= srfd;	psip_fd->pf_port= psip_port;	psip_fd->pf_get_userdata= get_userdata;	psip_fd->pf_put_userdata= put_userdata;	psip_port->pp_opencnt++;	return i;}PRIVATE int psip_ioctl(fd, req)int fd;ioreq_t req;{	int result;	psip_fd_t *psip_fd;	acc_t *data;	nwio_ipconf_t *ipconfp;	nwio_psipopt_t *psip_opt, *newoptp;	assert(fd >= 0 && fd < PSIP_FD_NR);	psip_fd= &psip_fd_table[fd];	switch(req)	{	case NWIOSIPCONF:		data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0, 			sizeof(*ipconfp), TRUE);		if (!data)		{			result= EFAULT;			break;		}		data= bf_packIffLess(data, sizeof(*ipconfp));		assert (data->acc_length == sizeof(*ipconfp));		ipconfp= (nwio_ipconf_t *)ptr2acc_data(data);		result= ip_setconf(psip_fd->pf_port->pp_ipdev, ipconfp);		bf_afree(data);		reply_thr_get(psip_fd, result, TRUE);		break;	case NWIOSPSIPOPT:		data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0, 			sizeof(*psip_opt), TRUE);		if (!data)		{			result= EFAULT;			break;		}		data= bf_packIffLess(data, sizeof(*psip_opt));		assert (data->acc_length == sizeof(*psip_opt));		newoptp= (nwio_psipopt_t *)ptr2acc_data(data);		result= psip_setopt(psip_fd, newoptp);		bf_afree(data);		if (result == NW_OK)		{			if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_PROMISC)			{				psip_fd->pf_flags |= PFF_PROMISC;				psip_fd->pf_port->pp_flags |= PPF_PROMISC;			}			else			{				psip_fd->pf_flags &= ~PFF_PROMISC;				check_promisc(psip_fd->pf_port);			}			if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_NEXTHOP)			{				psip_fd->pf_flags |= PFF_NEXTHOP;			}			else			{				psip_fd->pf_flags &= ~PFF_NEXTHOP;			}		}		reply_thr_get(psip_fd, result, TRUE);		break;	case NWIOGPSIPOPT:		data= bf_memreq(sizeof(*psip_opt));		psip_opt= (nwio_psipopt_t *)ptr2acc_data(data);		*psip_opt= psip_fd->pf_psipopt;		result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 0,			data, TRUE);		if (result == NW_OK)			reply_thr_put(psip_fd, NW_OK, TRUE);		break;	default:		reply_thr_put(psip_fd, ENOTTY, TRUE);		break;	}	return NW_OK;}PRIVATE int psip_read(fd, count)int fd;size_t count;{	psip_port_t *psip_port;	psip_fd_t *psip_fd;	acc_t *pack;	size_t buf_size;	int result, result1;	assert(fd >= 0 && fd < PSIP_FD_NR);	psip_fd= &psip_fd_table[fd];	psip_port= psip_fd->pf_port;	if ((psip_fd->pf_flags & PFF_PROMISC) && psip_port->pp_promisc_head)	{		/* Deliver a queued packet. */		pack= psip_port->pp_promisc_head;		buf_size= bf_bufsize(pack);		if (buf_size <= count)		{			psip_port->pp_promisc_head= pack->acc_ext_link;			result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 				(size_t)0, pack, FALSE);			if (result == NW_OK)				result= buf_size;		}		else			result= EPACKSIZE;		result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,				(size_t)result, NULL, FALSE);		assert(result1 == NW_OK);		return NW_OK;	}	psip_fd->pf_rd_count= count;	if (psip_port->pp_rd_head == NULL)

⌨️ 快捷键说明

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