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