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

📄 udp.c

📁 minix3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*udp.cCopyright 1995 Philip Homburg*/#include "inet.h"#include "type.h"#include "assert.h"#include "buf.h"#include "clock.h"#include "icmp_lib.h"#include "io.h"#include "ip.h"#include "sr.h"#include "udp.h"#include "udp_int.h"THIS_FILEFORWARD void read_ip_packets ARGS(( udp_port_t *udp_port ));FORWARD void udp_buffree ARGS(( int priority ));#ifdef BUF_CONSISTENCY_CHECKFORWARD void udp_bufcheck ARGS(( void ));#endifFORWARD void udp_main ARGS(( udp_port_t *udp_port ));FORWARD int udp_select ARGS(( int fd, unsigned operations ));FORWARD acc_t *udp_get_data ARGS(( int fd, size_t offset, size_t count, 	int for_ioctl ));FORWARD int udp_put_data ARGS(( int fd, size_t offset, acc_t *data, 		int for_ioctl ));FORWARD int udp_peek ARGS(( udp_fd_t * ));FORWARD int udp_sel_read ARGS(( udp_fd_t * ));FORWARD void udp_restart_write_port ARGS(( udp_port_t *udp_port ));FORWARD void udp_ip_arrived ARGS(( int port, acc_t *pack, size_t pack_size ));FORWARD void reply_thr_put ARGS(( udp_fd_t *udp_fd, int reply,	int for_ioctl ));FORWARD void reply_thr_get ARGS(( udp_fd_t *udp_fd, int reply,	int for_ioctl ));FORWARD int udp_setopt ARGS(( udp_fd_t *udp_fd ));FORWARD udpport_t find_unused_port ARGS(( int fd ));FORWARD int is_unused_port ARGS(( Udpport_t port ));FORWARD int udp_packet2user ARGS(( udp_fd_t *udp_fd ));FORWARD void restart_write_fd ARGS(( udp_fd_t *udp_fd ));FORWARD u16_t pack_oneCsum ARGS(( acc_t *pack ));FORWARD void udp_rd_enqueue ARGS(( udp_fd_t *udp_fd, acc_t *pack,							clock_t exp_tim ));FORWARD void hash_fd ARGS(( udp_fd_t *udp_fd ));FORWARD void unhash_fd ARGS(( udp_fd_t *udp_fd ));PUBLIC udp_port_t *udp_port_table;PUBLIC udp_fd_t udp_fd_table[UDP_FD_NR];PUBLIC void udp_prep(){	udp_port_table= alloc(udp_conf_nr * sizeof(udp_port_table[0]));}PUBLIC void udp_init(){	udp_fd_t *udp_fd;	udp_port_t *udp_port;	int i, j, ifno;	assert (BUF_S >= sizeof(struct nwio_ipopt));	assert (BUF_S >= sizeof(struct nwio_ipconf));	assert (BUF_S >= sizeof(struct nwio_udpopt));	assert (BUF_S >= sizeof(struct udp_io_hdr));	assert (UDP_HDR_SIZE == sizeof(udp_hdr_t));	assert (UDP_IO_HDR_SIZE == sizeof(udp_io_hdr_t));	for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)	{		udp_fd->uf_flags= UFF_EMPTY;		udp_fd->uf_rdbuf_head= NULL;	}#ifndef BUF_CONSISTENCY_CHECK	bf_logon(udp_buffree);#else	bf_logon(udp_buffree, udp_bufcheck);#endif	for (i= 0, udp_port= udp_port_table; i<udp_conf_nr; i++, udp_port++)	{		udp_port->up_ipdev= udp_conf[i].uc_port;		udp_port->up_flags= UPF_EMPTY;		udp_port->up_state= UPS_EMPTY;		udp_port->up_next_fd= udp_fd_table;		udp_port->up_write_fd= NULL;		udp_port->up_wr_pack= NULL;		udp_port->up_port_any= NULL;		for (j= 0; j<UDP_PORT_HASH_NR; j++)			udp_port->up_port_hash[j]= NULL;		ifno= ip_conf[udp_port->up_ipdev].ic_ifno;		sr_add_minor(if2minor(ifno, UDP_DEV_OFF),			i, udp_open, udp_close, udp_read,			udp_write, udp_ioctl, udp_cancel, udp_select);		udp_main(udp_port);	}}PUBLIC int udp_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;{	int i;	udp_fd_t *udp_fd;	for (i= 0; i<UDP_FD_NR && (udp_fd_table[i].uf_flags & UFF_INUSE);		i++);	if (i>= UDP_FD_NR)	{		DBLOCK(1, printf("out of fds\n"));		return EAGAIN;	}	udp_fd= &udp_fd_table[i];	udp_fd->uf_flags= UFF_INUSE;	udp_fd->uf_port= &udp_port_table[port];	udp_fd->uf_srfd= srfd;	udp_fd->uf_udpopt.nwuo_flags= UDP_DEF_OPT;	udp_fd->uf_get_userdata= get_userdata;	udp_fd->uf_put_userdata= put_userdata;	udp_fd->uf_select_res= select_res;	assert(udp_fd->uf_rdbuf_head == NULL);	udp_fd->uf_port_next= NULL;	return i;}PUBLIC int udp_ioctl (fd, req)int fd;ioreq_t req;{	udp_fd_t *udp_fd;	udp_port_t *udp_port;	nwio_udpopt_t *udp_opt;	acc_t *opt_acc;	int result;	udp_fd= &udp_fd_table[fd];assert (udp_fd->uf_flags & UFF_INUSE);	udp_port= udp_fd->uf_port;	udp_fd->uf_flags |= UFF_IOCTL_IP;	udp_fd->uf_ioreq= req;	if (udp_port->up_state != UPS_MAIN)		return NW_SUSPEND;	switch(req)	{	case NWIOSUDPOPT:		result= udp_setopt(udp_fd);		break;	case NWIOGUDPOPT:		opt_acc= bf_memreq(sizeof(*udp_opt));assert (opt_acc->acc_length == sizeof(*udp_opt));		udp_opt= (nwio_udpopt_t *)ptr2acc_data(opt_acc);		*udp_opt= udp_fd->uf_udpopt;		udp_opt->nwuo_locaddr= udp_fd->uf_port->up_ipaddr;		result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, 0, opt_acc,			TRUE);		if (result == NW_OK)			reply_thr_put(udp_fd, NW_OK, TRUE);		break;	case NWIOUDPPEEK:		result= udp_peek(udp_fd);		break;	default:		reply_thr_get(udp_fd, EBADIOCTL, TRUE);		result= NW_OK;		break;	}	if (result != NW_SUSPEND)		udp_fd->uf_flags &= ~UFF_IOCTL_IP;	return result;}PUBLIC int udp_read (fd, count)int fd;size_t count;{	udp_fd_t *udp_fd;	acc_t *tmp_acc, *next_acc;	udp_fd= &udp_fd_table[fd];	if (!(udp_fd->uf_flags & UFF_OPTSET))	{		reply_thr_put(udp_fd, EBADMODE, FALSE);		return NW_OK;	}	udp_fd->uf_rd_count= count;	if (udp_fd->uf_rdbuf_head)	{		if (get_time() <= udp_fd->uf_exp_tim)			return udp_packet2user (udp_fd);		tmp_acc= udp_fd->uf_rdbuf_head;		while (tmp_acc)		{			next_acc= tmp_acc->acc_ext_link;			bf_afree(tmp_acc);			tmp_acc= next_acc;		}		udp_fd->uf_rdbuf_head= NULL;	}	udp_fd->uf_flags |= UFF_READ_IP;	return NW_SUSPEND;}PRIVATE void udp_main(udp_port)udp_port_t *udp_port;{	udp_fd_t *udp_fd;	int result, i;	switch (udp_port->up_state)	{	case UPS_EMPTY:		udp_port->up_state= UPS_SETPROTO;		udp_port->up_ipfd= ip_open(udp_port->up_ipdev, 			udp_port->up_ipdev, udp_get_data, udp_put_data,			udp_ip_arrived, 0 /* no select_res */);		if (udp_port->up_ipfd < 0)		{			udp_port->up_state= UPS_ERROR;			DBLOCK(1, printf("%s, %d: unable to open ip port\n",				__FILE__, __LINE__));			return;		}		result= ip_ioctl(udp_port->up_ipfd, NWIOSIPOPT);		if (result == NW_SUSPEND)			udp_port->up_flags |= UPF_SUSPEND;		if (result<0)		{			return;		}		if (udp_port->up_state != UPS_GETCONF)			return;		/* drops through */	case UPS_GETCONF:		udp_port->up_flags &= ~UPF_SUSPEND;		result= ip_ioctl(udp_port->up_ipfd, NWIOGIPCONF);		if (result == NW_SUSPEND)			udp_port->up_flags |= UPF_SUSPEND;		if (result<0)		{			return;		}		if (udp_port->up_state != UPS_MAIN)			return;		/* drops through */	case UPS_MAIN:		udp_port->up_flags &= ~UPF_SUSPEND;		for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)		{			if (!(udp_fd->uf_flags & UFF_INUSE))				continue;			if (udp_fd->uf_port != udp_port)				continue;			if (udp_fd->uf_flags & UFF_IOCTL_IP)				udp_ioctl(i, udp_fd->uf_ioreq);		}		read_ip_packets(udp_port);		return;	default:		DBLOCK(1, printf("udp_port_table[%d].up_state= %d\n",			udp_port->up_ipdev, udp_port->up_state));		ip_panic(( "unknown state" ));		break;	}}PRIVATE int udp_select(fd, operations)int fd;unsigned operations;{	int i;	unsigned resops;	udp_fd_t *udp_fd;	udp_fd= &udp_fd_table[fd];	assert (udp_fd->uf_flags & UFF_INUSE);	resops= 0;	if (operations & SR_SELECT_READ)	{		if (udp_sel_read(udp_fd))			resops |= SR_SELECT_READ;		else if (!(operations & SR_SELECT_POLL))			udp_fd->uf_flags |= UFF_SEL_READ;	}	if (operations & SR_SELECT_WRITE)	{		/* Should handle special case when the interface is down */		resops |= SR_SELECT_WRITE;	}	if (operations & SR_SELECT_EXCEPTION)	{		printf("udp_select: not implemented for exceptions\n");	}	return resops;}PRIVATE acc_t *udp_get_data (port, offset, count, for_ioctl)int port;size_t offset;size_t count;int for_ioctl;{	udp_port_t *udp_port;	udp_fd_t *udp_fd;	int result;	udp_port= &udp_port_table[port];	switch(udp_port->up_state)	{	case UPS_SETPROTO:assert (for_ioctl);		if (!count)		{			result= (int)offset;			if (result<0)			{				udp_port->up_state= UPS_ERROR;				break;			}			udp_port->up_state= UPS_GETCONF;			if (udp_port->up_flags & UPF_SUSPEND)				udp_main(udp_port);			return NULL;		}		else		{			struct nwio_ipopt *ipopt;			acc_t *acc;assert (!offset);assert (count == sizeof(*ipopt));			acc= bf_memreq(sizeof(*ipopt));			ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);			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_UDP;			return acc;		}	case UPS_MAIN:assert (!for_ioctl);assert (udp_port->up_flags & UPF_WRITE_IP);		if (!count)		{			result= (int)offset;assert (udp_port->up_wr_pack);			bf_afree(udp_port->up_wr_pack);			udp_port->up_wr_pack= 0;			if (udp_port->up_flags & UPF_WRITE_SP)			{				if (udp_port->up_write_fd)				{					udp_fd= udp_port->up_write_fd;					udp_port->up_write_fd= NULL;					udp_fd->uf_flags &= ~UFF_WRITE_IP;					reply_thr_get(udp_fd, result, FALSE);				}				udp_port->up_flags &= ~(UPF_WRITE_SP | 					UPF_WRITE_IP);				if (udp_port->up_flags & UPF_MORE2WRITE)				{					udp_restart_write_port(udp_port);				}			}			else				udp_port->up_flags &= ~UPF_WRITE_IP;		}		else		{			return bf_cut (udp_port->up_wr_pack, offset, count);		}		break;	default:		printf("udp_get_data(%d, 0x%x, 0x%x) called but up_state= 0x%x\n",			port, offset, count, udp_port->up_state);		break;	}	return NULL;}PRIVATE int udp_put_data (fd, offset, data, for_ioctl)int fd;size_t offset;acc_t *data;int for_ioctl;{	udp_port_t *udp_port;	int result;	udp_port= &udp_port_table[fd];	switch (udp_port->up_state)	{	case UPS_GETCONF:		if (!data)		{			result= (int)offset;			if (result<0)			{				udp_port->up_state= UPS_ERROR;				return NW_OK;			}			udp_port->up_state= UPS_MAIN;			if (udp_port->up_flags & UPF_SUSPEND)				udp_main(udp_port);		}		else		{			struct nwio_ipconf *ipconf;			data= bf_packIffLess(data, sizeof(*ipconf));			ipconf= (struct nwio_ipconf *)ptr2acc_data(data);assert (ipconf->nwic_flags & NWIC_IPADDR_SET);			udp_port->up_ipaddr= ipconf->nwic_ipaddr;			bf_afree(data);		}		break;	case UPS_MAIN:		assert(0);		assert (udp_port->up_flags & UPF_READ_IP);		if (!data)		{			result= (int)offset;			compare (result, >=, 0);			if (udp_port->up_flags & UPF_READ_SP)			{				udp_port->up_flags &= ~(UPF_READ_SP|					UPF_READ_IP);				read_ip_packets(udp_port);			}			else				udp_port->up_flags &= ~UPF_READ_IP;		}		else		{assert (!offset);	/* This isn't a valid assertion but ip sends only			 * whole datagrams up */			udp_ip_arrived(fd, data, bf_bufsize(data));		}		break;	default:		ip_panic((		"udp_put_data(%d, 0x%x, %p) called but up_state= 0x%x\n",					fd, offset, data, udp_port->up_state ));	}	return NW_OK;}PRIVATE int udp_setopt(udp_fd)udp_fd_t *udp_fd;{	udp_fd_t *fd_ptr;	nwio_udpopt_t oldopt, newopt;	acc_t *data;	unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags,		all_flags, flags;	unsigned long new_flags;	int i;	data= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0, 		sizeof(nwio_udpopt_t), TRUE);	if (!data)		return EFAULT;	data= bf_packIffLess(data, sizeof(nwio_udpopt_t));assert (data->acc_length == sizeof(nwio_udpopt_t));	newopt= *(nwio_udpopt_t *)ptr2acc_data(data);	bf_afree(data);	oldopt= udp_fd->uf_udpopt;	old_en_flags= oldopt.nwuo_flags & 0xffff;	old_di_flags= (oldopt.nwuo_flags >> 16) & 0xffff;	new_en_flags= newopt.nwuo_flags & 0xffff;	new_di_flags= (newopt.nwuo_flags >> 16) & 0xffff;	if (new_en_flags & new_di_flags)	{		DBLOCK(1, printf("returning EBADMODE\n"));		reply_thr_get(udp_fd, EBADMODE, TRUE);		return NW_OK;	}	/* NWUO_ACC_MASK */	if (new_di_flags & NWUO_ACC_MASK)	{		DBLOCK(1, printf("returning EBADMODE\n"));		reply_thr_get(udp_fd, EBADMODE, TRUE);		return NW_OK;		/* access modes can't be disabled */	}	if (!(new_en_flags & NWUO_ACC_MASK))		new_en_flags |= (old_en_flags & NWUO_ACC_MASK);	/* NWUO_LOCPORT_MASK */	if (new_di_flags & NWUO_LOCPORT_MASK)	{		DBLOCK(1, printf("returning EBADMODE\n"));		reply_thr_get(udp_fd, EBADMODE, TRUE);		return NW_OK;		/* the loc ports can't be disabled */	}	if (!(new_en_flags & NWUO_LOCPORT_MASK))	{		new_en_flags |= (old_en_flags & NWUO_LOCPORT_MASK);		newopt.nwuo_locport= oldopt.nwuo_locport;	}	else if ((new_en_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SEL)	{		newopt.nwuo_locport= find_unused_port(udp_fd-udp_fd_table);	}	else if ((new_en_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)	{		if (!newopt.nwuo_locport)		{			DBLOCK(1, printf("returning EBADMODE\n"));			reply_thr_get(udp_fd, EBADMODE, TRUE);			return NW_OK;		}

⌨️ 快捷键说明

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