📄 udp.c
字号:
/* 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 + -