📄 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); }#endifassert (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 + -