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

📄 udp.c

📁 minix3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	/* NWUO_LOCADDR_MASK */	if (!((new_en_flags | new_di_flags) & NWUO_LOCADDR_MASK))	{		new_en_flags |= (old_en_flags & NWUO_LOCADDR_MASK);		new_di_flags |= (old_di_flags & NWUO_LOCADDR_MASK);	}	/* NWUO_BROAD_MASK */	if (!((new_en_flags | new_di_flags) & NWUO_BROAD_MASK))	{		new_en_flags |= (old_en_flags & NWUO_BROAD_MASK);		new_di_flags |= (old_di_flags & NWUO_BROAD_MASK);	}	/* NWUO_REMPORT_MASK */	if (!((new_en_flags | new_di_flags) & NWUO_REMPORT_MASK))	{		new_en_flags |= (old_en_flags & NWUO_REMPORT_MASK);		new_di_flags |= (old_di_flags & NWUO_REMPORT_MASK);		newopt.nwuo_remport= oldopt.nwuo_remport;	}		/* NWUO_REMADDR_MASK */	if (!((new_en_flags | new_di_flags) & NWUO_REMADDR_MASK))	{		new_en_flags |= (old_en_flags & NWUO_REMADDR_MASK);		new_di_flags |= (old_di_flags & NWUO_REMADDR_MASK);		newopt.nwuo_remaddr= oldopt.nwuo_remaddr;	}	/* NWUO_RW_MASK */	if (!((new_en_flags | new_di_flags) & NWUO_RW_MASK))	{		new_en_flags |= (old_en_flags & NWUO_RW_MASK);		new_di_flags |= (old_di_flags & NWUO_RW_MASK);	}	/* NWUO_IPOPT_MASK */	if (!((new_en_flags | new_di_flags) & NWUO_IPOPT_MASK))	{		new_en_flags |= (old_en_flags & NWUO_IPOPT_MASK);		new_di_flags |= (old_di_flags & NWUO_IPOPT_MASK);	}	new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;	if ((new_flags & NWUO_RWDATONLY) && 		((new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY || 		(new_flags & (NWUO_RP_ANY|NWUO_RA_ANY|NWUO_EN_IPOPT))))	{		DBLOCK(1, printf("returning EBADMODE\n"));		reply_thr_get(udp_fd, EBADMODE, TRUE);		return NW_OK;	}	/* Check the access modes */	if ((new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SEL ||		(new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)	{		for (i= 0, fd_ptr= udp_fd_table; i<UDP_FD_NR; i++, fd_ptr++)		{			if (fd_ptr == udp_fd)				continue;			if (!(fd_ptr->uf_flags & UFF_INUSE))				continue;			if (fd_ptr->uf_port != udp_fd->uf_port)				continue;			flags= fd_ptr->uf_udpopt.nwuo_flags;			if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_SEL &&				(flags & NWUO_LOCPORT_MASK) != NWUO_LP_SET)				continue;			if (fd_ptr->uf_udpopt.nwuo_locport !=				newopt.nwuo_locport)			{				continue;			}			if ((flags & NWUO_ACC_MASK) != 				(new_flags & NWUO_ACC_MASK))			{				DBLOCK(1, printf(			"address inuse: new fd= %d, old_fd= %d, port= %u\n",					udp_fd-udp_fd_table,					fd_ptr-udp_fd_table,					newopt.nwuo_locport));				reply_thr_get(udp_fd, EADDRINUSE, TRUE);				return NW_OK;			}		}	}	if (udp_fd->uf_flags & UFF_OPTSET)		unhash_fd(udp_fd);	newopt.nwuo_flags= new_flags;	udp_fd->uf_udpopt= newopt;	all_flags= new_en_flags | new_di_flags;	if ((all_flags & NWUO_ACC_MASK) && (all_flags & NWUO_LOCPORT_MASK) &&		(all_flags & NWUO_LOCADDR_MASK) &&		(all_flags & NWUO_BROAD_MASK) &&		(all_flags & NWUO_REMPORT_MASK) &&		(all_flags & NWUO_REMADDR_MASK) &&		(all_flags & NWUO_RW_MASK) &&		(all_flags & NWUO_IPOPT_MASK))		udp_fd->uf_flags |= UFF_OPTSET;	else	{		udp_fd->uf_flags &= ~UFF_OPTSET;	}	if (udp_fd->uf_flags & UFF_OPTSET)		hash_fd(udp_fd);	reply_thr_get(udp_fd, NW_OK, TRUE);	return NW_OK;}PRIVATE udpport_t find_unused_port(fd)int fd;{	udpport_t port, nw_port;	for (port= 0x8000+fd; port < 0xffff-UDP_FD_NR; port+= UDP_FD_NR)	{		nw_port= htons(port);		if (is_unused_port(nw_port))			return nw_port;	}	for (port= 0x8000; port < 0xffff; port++)	{		nw_port= htons(port);		if (is_unused_port(nw_port))			return nw_port;	}	ip_panic(( "unable to find unused port (shouldn't occur)" ));	return 0;}/*reply_thr_put*/PRIVATE void reply_thr_put(udp_fd, reply, for_ioctl)udp_fd_t *udp_fd;int reply;int for_ioctl;{	int result;	result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, reply,		(acc_t *)0, for_ioctl);	assert(result == NW_OK);}/*reply_thr_get*/PRIVATE void reply_thr_get(udp_fd, reply, for_ioctl)udp_fd_t *udp_fd;int reply;int for_ioctl;{	acc_t *result;	result= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, reply,		(size_t)0, for_ioctl);	assert (!result);}PRIVATE int is_unused_port(port)udpport_t port;{	int i;	udp_fd_t *udp_fd;	for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++,		udp_fd++)	{		if (!(udp_fd->uf_flags & UFF_OPTSET))			continue;		if (udp_fd->uf_udpopt.nwuo_locport == port)			return FALSE;	}	return TRUE;}PRIVATE void read_ip_packets(udp_port)udp_port_t *udp_port;{	int result;	do	{		udp_port->up_flags |= UPF_READ_IP;		result= ip_read(udp_port->up_ipfd, UDP_MAX_DATAGRAM);		if (result == NW_SUSPEND)		{			udp_port->up_flags |= UPF_READ_SP;			return;		}assert(result == NW_OK);		udp_port->up_flags &= ~UPF_READ_IP;	} while(!(udp_port->up_flags & UPF_READ_IP));}PRIVATE int udp_peek (udp_fd)udp_fd_t *udp_fd;{	acc_t *pack, *tmp_acc, *next_acc;	int result;	if (!(udp_fd->uf_flags & UFF_OPTSET))	{		udp_fd->uf_flags &= ~UFF_IOCTL_IP;		reply_thr_put(udp_fd, EBADMODE, TRUE);		return NW_OK;	}	if (udp_fd->uf_rdbuf_head)	{		if (get_time() <= udp_fd->uf_exp_tim)		{			pack= bf_cut(udp_fd->uf_rdbuf_head, 0,				sizeof(udp_io_hdr_t));			result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,				(size_t)0, pack, TRUE);			udp_fd->uf_flags &= ~UFF_IOCTL_IP;			result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,				result, (acc_t *)0, TRUE);			assert (result == 0);			return result;		}		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_PEEK_IP;	return NW_SUSPEND;}PRIVATE int udp_sel_read (udp_fd)udp_fd_t *udp_fd;{	acc_t *pack, *tmp_acc, *next_acc;	int result;	if (!(udp_fd->uf_flags & UFF_OPTSET))		return 1;	/* Read will not block */	if (udp_fd->uf_rdbuf_head)	{		if (get_time() <= udp_fd->uf_exp_tim)			return 1;				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;	}	return 0;}PRIVATE int udp_packet2user (udp_fd)udp_fd_t *udp_fd;{	acc_t *pack, *tmp_pack;	udp_io_hdr_t *hdr;	int result, hdr_len;	size_t size, transf_size;	pack= udp_fd->uf_rdbuf_head;	udp_fd->uf_rdbuf_head= pack->acc_ext_link;	size= bf_bufsize (pack);	if (udp_fd->uf_udpopt.nwuo_flags & NWUO_RWDATONLY)	{		pack= bf_packIffLess (pack, UDP_IO_HDR_SIZE);		assert (pack->acc_length >= UDP_IO_HDR_SIZE);		hdr= (udp_io_hdr_t *)ptr2acc_data(pack);#if CONF_UDP_IO_NW_BYTE_ORDER		hdr_len= UDP_IO_HDR_SIZE+NTOHS(hdr->uih_ip_opt_len);#else		hdr_len= UDP_IO_HDR_SIZE+hdr->uih_ip_opt_len;#endif		assert (size>= hdr_len);		size -= hdr_len;		tmp_pack= bf_cut(pack, hdr_len, size);		bf_afree(pack);		pack= tmp_pack;	}	if (size>udp_fd->uf_rd_count)	{		tmp_pack= bf_cut (pack, 0, udp_fd->uf_rd_count);		bf_afree(pack);		pack= tmp_pack;		transf_size= udp_fd->uf_rd_count;	}	else		transf_size= size;	result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,		(size_t)0, pack, FALSE);	if (result >= 0)		if (size > transf_size)			result= EPACKSIZE;		else			result= transf_size;	udp_fd->uf_flags &= ~UFF_READ_IP;	result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, result,			(acc_t *)0, FALSE);	assert (result == 0);	return result;}PRIVATE void udp_ip_arrived(port, pack, pack_size)int port;acc_t *pack;size_t pack_size;{	udp_port_t *udp_port;	udp_fd_t *udp_fd, *share_fd;	acc_t *ip_hdr_acc, *udp_acc, *ipopt_pack, *no_ipopt_pack, *tmp_acc;	ip_hdr_t *ip_hdr;	udp_hdr_t *udp_hdr;	udp_io_hdr_t *udp_io_hdr;	size_t ip_hdr_size, udp_size, data_size, opt_size;	ipaddr_t src_addr, dst_addr, ipaddr;	udpport_t src_port, dst_port;	u8_t u16[2];	u16_t chksum;	unsigned long dst_type, flags;	clock_t exp_tim;	int i, delivered, hash;	udp_port= &udp_port_table[port];	ip_hdr_acc= bf_cut(pack, 0, IP_MIN_HDR_SIZE);	ip_hdr_acc= bf_packIffLess(ip_hdr_acc, IP_MIN_HDR_SIZE);	ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_acc);	ip_hdr_size= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;	if (ip_hdr_size != IP_MIN_HDR_SIZE)	{		bf_afree(ip_hdr_acc);		ip_hdr_acc= bf_cut(pack, 0, ip_hdr_size);		ip_hdr_acc= bf_packIffLess(ip_hdr_acc, ip_hdr_size);		ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_acc);	}	pack_size -= ip_hdr_size;	if (pack_size < UDP_HDR_SIZE)	{		if (pack_size == 0 && ip_hdr->ih_proto == 0)		{			/* IP layer reports new IP address */			ipaddr= ip_hdr->ih_src;			udp_port->up_ipaddr= ipaddr;			DBLOCK(1, printf("udp_ip_arrived: using address ");				writeIpAddr(ipaddr); printf("\n"));		}		else			DBLOCK(1, printf("packet too small\n"));		bf_afree(ip_hdr_acc);		bf_afree(pack);		return;	}	udp_acc= bf_delhead(pack, ip_hdr_size);	pack= NULL;	udp_acc= bf_packIffLess(udp_acc, UDP_HDR_SIZE);	udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_acc);	udp_size= ntohs(udp_hdr->uh_length);	if (udp_size > pack_size)	{		DBLOCK(1, printf("packet too large\n"));		bf_afree(ip_hdr_acc);		bf_afree(udp_acc);		return;	}	src_addr= ip_hdr->ih_src;	dst_addr= ip_hdr->ih_dst;	if (udp_hdr->uh_chksum)	{		u16[0]= 0;		u16[1]= ip_hdr->ih_proto;		chksum= pack_oneCsum(udp_acc);		chksum= oneC_sum(chksum, (u16_t *)&src_addr, sizeof(ipaddr_t));		chksum= oneC_sum(chksum, (u16_t *)&dst_addr, sizeof(ipaddr_t));		chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16));		chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length, 			sizeof(udp_hdr->uh_length));		if (~chksum & 0xffff)		{			DBLOCK(1, printf("checksum error in udp packet\n");				printf("src ip_addr= ");				writeIpAddr(src_addr);				printf(" dst ip_addr= ");				writeIpAddr(dst_addr);				printf("\n");				printf("packet chksum= 0x%x, sum= 0x%x\n",					udp_hdr->uh_chksum, chksum));			bf_afree(ip_hdr_acc);			bf_afree(udp_acc);			return;		}	}	exp_tim= get_time() + UDP_READ_EXP_TIME;	src_port= udp_hdr->uh_src_port;	dst_port= udp_hdr->uh_dst_port;	/* Send an ICMP port unreachable if the packet could not be	 * delivered.	 */	delivered= 0;	if (dst_addr == udp_port->up_ipaddr)		dst_type= NWUO_EN_LOC;	else	{		dst_type= NWUO_EN_BROAD;		/* Don't send ICMP error packets for broadcast packets */		delivered= 1;	}	DBLOCK(0x20, printf("udp: got packet from ");		writeIpAddr(src_addr);		printf(".%u to ", ntohs(src_port));		writeIpAddr(dst_addr);		printf(".%u\n", ntohs(dst_port)));	no_ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);	udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(no_ipopt_pack);	udp_io_hdr->uih_src_addr= src_addr;	udp_io_hdr->uih_dst_addr= dst_addr;	udp_io_hdr->uih_src_port= src_port;	udp_io_hdr->uih_dst_port= dst_port;	data_size = udp_size-UDP_HDR_SIZE;#if CONF_UDP_IO_NW_BYTE_ORDER	udp_io_hdr->uih_ip_opt_len= HTONS(0);	udp_io_hdr->uih_data_len= htons(data_size);#else	udp_io_hdr->uih_ip_opt_len= 0;	udp_io_hdr->uih_data_len= data_size;#endif	no_ipopt_pack->acc_next= bf_cut(udp_acc, UDP_HDR_SIZE, data_size);	if (ip_hdr_size == IP_MIN_HDR_SIZE)	{		ipopt_pack= no_ipopt_pack;		ipopt_pack->acc_linkC++;	}	else	{		ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);		*(udp_io_hdr_t *)ptr2acc_data(ipopt_pack)= *udp_io_hdr;		udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(ipopt_pack);		opt_size = ip_hdr_size-IP_MIN_HDR_SIZE;#if CONF_UDP_IO_NW_BYTE_ORDER		udp_io_hdr->uih_ip_opt_len= htons(opt_size);#else		udp_io_hdr->uih_ip_opt_len= opt_size;#endif		tmp_acc= bf_cut(ip_hdr_acc, (size_t)IP_MIN_HDR_SIZE, opt_size);		assert(tmp_acc->acc_linkC == 1);		assert(tmp_acc->acc_next == NULL);		ipopt_pack->acc_next= tmp_acc;		tmp_acc->acc_next= no_ipopt_pack->acc_next;		if (tmp_acc->acc_next)			tmp_acc->acc_next->acc_linkC++;	}	hash= dst_port;	hash ^= (hash >> 8);	hash &= (UDP_PORT_HASH_NR-1);	for (i= 0; i<2; i++)	{		share_fd= NULL;		udp_fd= (i == 0) ? udp_port->up_port_any :			udp_port->up_port_hash[hash];		for (; udp_fd; udp_fd= udp_fd->uf_port_next)		{			if (i && udp_fd->uf_udpopt.nwuo_locport != dst_port)				continue;					assert(udp_fd->uf_flags & UFF_INUSE);			assert(udp_fd->uf_flags & UFF_OPTSET);					if (udp_fd->uf_port != udp_port)				continue;			flags= udp_fd->uf_udpopt.nwuo_flags;			if (!(flags & dst_type))				continue;			if ((flags & NWUO_RP_SET) && 				udp_fd->uf_udpopt.nwuo_remport != src_port)			{				continue;			}			if ((flags & NWUO_RA_SET) && 				udp_fd->uf_udpopt.nwuo_remaddr != src_addr)			{				continue;			}			if (i)			{				/* Packet is considdered to be delivered */				delivered= 1;			}			if ((flags & NWUO_ACC_MASK) == NWUO_SHARED &&				(!share_fd || !udp_fd->uf_rdbuf_head))			{				share_fd= udp_fd;				continue;			}			if (flags & NWUO_EN_IPOPT)				pack= ipopt_pack;			else				pack= no_ipopt_pack;			pack->acc_linkC++;			udp_rd_enqueue(udp_fd, pack, exp_tim);

⌨️ 快捷键说明

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