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

📄 udp.c

📁 minux的源代码,一个非常小的操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* 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)
	{
#if DEBUG
 { where(); printf("returning EBADMODE\n"); }
#endif
		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)
		{
#if DEBUG
 { where(); printf("returning EBADMODE\n"); }
#endif
			reply_thr_get(udp_fd, EBADMODE, TRUE);
			return NW_OK;
		}
	}

	/* 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;
	}
#if DEBUG & 256
 { where(); printf("newopt.nwuo_remport= %d\n", ntohs(newopt.nwuo_remport)); }
#endif
	
	/* 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))))
	{
#if DEBUG
 { where(); printf("returning EBADMODE\n"); }
#endif
		reply_thr_get(udp_fd, EBADMODE, TRUE);
		return NW_OK;
	}

	/* Let's 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;
			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))
			{
#if DEBUG
 { where(); 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); }
#endif
				reply_thr_get(udp_fd, EADDRINUSE, TRUE);
				return NW_OK;
			}
		}
	}

	newopt.nwuo_flags= new_flags;
	udp_fd->uf_udpopt= newopt;

	all_flags= new_en_flags | new_di_flags;
#if DEBUG & 256
 { where();
	printf("NWUO_ACC_MASK: %s set\n", all_flags & NWUO_ACC_MASK ? "" : "not"); 
	printf("NWUO_LOCADDR_MASK: %s set\n", all_flags & NWUO_LOCADDR_MASK ? "" : "not"); 
	printf("NWUO_BROAD_MASK: %s set\n", all_flags & NWUO_BROAD_MASK ? "" : "not"); 
	printf("NWUO_REMPORT_MASK: %s set\n", all_flags & NWUO_REMPORT_MASK ? "" : "not"); 
	printf("NWUO_REMADDR_MASK: %s set\n", all_flags & NWUO_REMADDR_MASK ? "" : "not"); 
	printf("NWUO_RW_MASK: %s set\n", all_flags & NWUO_RW_MASK ? "" : "not"); 
	printf("NWUO_IPOPT_MASK: %s set\n", all_flags & NWUO_IPOPT_MASK ? "" : "not"); 
 }
#endif
	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;
	}

	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; 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 int reply_thr_put(udp_fd, reply, for_ioctl)
udp_fd_t *udp_fd;
int reply;
int for_ioctl;
{
#if DEBUG
 { where(); printf("reply_thr_put(&udp_fd_table[%d], %d, %d) called\n",
	udp_fd-udp_fd_table, reply, for_ioctl); }
#endif
#if DEBUG & 2
 { where(); printf("calling 0x%x\n", udp_fd->uf_put_userdata); }
#endif
assert (udp_fd);
	return (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, reply,
		(acc_t *)0, for_ioctl);
}

/*
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;
#if DEBUG & 256
 { where(); printf("reply_thr_get(&udp_fd_table[%d], %d, %d) called\n",
	udp_fd-udp_fd_table, reply, for_ioctl); }
#endif
	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;
#if DEBUG & 256
 { where(); printf("doing ip_read\n"); }
#endif
		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));
}


PUBLIC int udp_read (fd, count)
int fd;
size_t count;
{
	udp_fd_t *udp_fd;

	udp_fd= &udp_fd_table[fd];
	if (!(udp_fd->uf_flags & UFF_OPTSET))
		return reply_thr_put(udp_fd, EBADMODE, FALSE);

	udp_fd->uf_rd_count= count;

	if (udp_fd->uf_rd_buf)
	{
		if (get_time() <= udp_fd->uf_exp_tim)
			return udp_packet2user (udp_fd);
		bf_afree(udp_fd->uf_rd_buf);
		udp_fd->uf_rd_buf= 0;
	}
	udp_fd->uf_flags |= UFF_READ_IP;
#if DEBUG & 256
 { where(); printf("udp_fd_table[%d].uf_flags= 0x%x\n",
	udp_fd-udp_fd_table, udp_fd->uf_flags); }
#endif
	return NW_SUSPEND;
}

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_rd_buf;
	udp_fd->uf_rd_buf= 0;

	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);
		hdr_len= UDP_IO_HDR_SIZE+hdr->uih_ip_opt_len;

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 process_inc_fragm(udp_port, pack)
udp_port_t *udp_port;
acc_t *pack;
{
	udp_fd_t *udp_fd, *share_fd;
	acc_t *ip_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 pack_size, ip_hdr_size;
	size_t udp_size;
	ipaddr_t src_addr, dst_addr;
	u8_t u16[2];
	u16_t chksum;
	unsigned long dst_type, flags;
	time_t  exp_tim;
	udpport_t src_port, dst_port;
	int i;

#if DEBUG & 256
 { where(); printf("in process_inc_fragm\n"); }
#endif
	pack_size= bf_bufsize(pack);

	pack= bf_packIffLess(pack, IP_MIN_HDR_SIZE);
assert (pack->acc_length >= IP_MIN_HDR_SIZE);
	ip_hdr= (ip_hdr_t *)ptr2acc_data(pack);
	ip_hdr_size= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
	ip_acc= bf_cut(pack, (size_t)0, ip_hdr_size);

	src_addr= ip_hdr->ih_src;
	dst_addr= ip_hdr->ih_dst;

	udp_acc= bf_cut(pack, ip_hdr_size, pack_size-ip_hdr_size);
	bf_afree(pack);
	pack_size -= ip_hdr_size;
	if (pack_size < UDP_HDR_SIZE)
	{
#if DEBUG
 { where(); printf("packet too small\n"); }
#endif
		bf_afree(ip_acc);
		bf_afree(udp_acc);
		return;
	}
	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)
	{
#if DEBUG
 { where(); printf("packet too large\n"); }
#endif
		bf_afree(ip_acc);
		bf_afree(udp_acc);
		return;
	}
	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)
		{
#if DEBUG 
 { where(); printf("udp chksum error\n"); }
#endif
			bf_afree(ip_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;

	if (dst_addr == udp_port->up_ipaddr)
		dst_type= NWUO_EN_LOC;
	else
		dst_type= NWUO_EN_BROAD;

	share_fd= 0;
	ipopt_pack= 0;
	no_ipopt_pack= 0;

	for (i=0, udp_fd=udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
	{
		if (!(udp_fd->uf_flags & UFF_INUSE))
		{
#if DEBUG & 256
 { where(); printf("%d: not inuse\n", i); }
#endif
			continue;
		}
		if (!(udp_fd->uf_flags & UFF_OPTSET))
		{
#if DEBUG
 { where(); printf("%d: options not set\n", i); }
#endif
			continue;
		}
		flags= udp_fd->uf_udpopt.nwuo_flags;
		if (!(flags & dst_type))
		{
#if DEBUG & 256
 { where(); printf("%d: wrong type\n", i); }
#endif
			continue;
		}
		if ((flags & (NWUO_LP_SEL|NWUO_LP_SET)) &&
			udp_fd->uf_udpopt.nwuo_locport != dst_port)
		{
#if DEBUG & 256
 { where(); printf("%d: wrong loc port, got %d, expected %d\n", i,
	dst_port, udp_fd->uf_udpopt.nwuo_locport); }
#endif
			continue;
		}
		if ((flags & NWUO_RP_SET) && 
			udp_fd->uf_udpopt.nwuo_remport != src_port)
		{
#if DEBUG
 { where(); printf("%d: wrong rem port, I got %d, expected %d\n", i,
	ntohs(src_port), ntohs(udp_fd->uf_udpopt.nwuo_remport)); }
#endif
			continue;
		}
		if ((flags & NWUO_RA_SET) && 
			udp_fd->uf_udpopt.nwuo_remaddr != src_addr)
		{
#if DEBUG
 { where(); printf("%d: wrong rem addr\n", i); }
#endif
			continue;
		}

		if (!no_ipopt_pack)
		{
			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;
			udp_io_hdr->uih_ip_opt_len= 0;
			udp_io_hdr->uih_data_len= udp_size-UDP_HDR_SIZE;
			no_ipopt_pack->acc_next= bf_cut(udp_acc, 
				UDP_HDR_SIZE, udp_io_hdr->uih_data_len);
			if (ip_hdr_size == IP_MIN_HDR_SIZE)
			{
				ipopt_pack= no_ipopt_pack;
				ipopt_pack->acc_linkC++;
			}
			else
				ipopt_pack= 0;
		}
		if (flags & NWUO_EN_IPOPT)
		{
			if (!ipopt_pack)
			{
				ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);

⌨️ 快捷键说明

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