📄 udp.c
字号:
if (udp_fd->uf_flags & UFF_READ_IP) udp_packet2user(udp_fd); } if (share_fd) { flags= share_fd->uf_udpopt.nwuo_flags; if (flags & NWUO_EN_IPOPT) pack= ipopt_pack; else pack= no_ipopt_pack; pack->acc_linkC++; udp_rd_enqueue(share_fd, pack, exp_tim); if (share_fd->uf_flags & UFF_READ_IP) udp_packet2user(share_fd); } } if (ipopt_pack) bf_afree(ipopt_pack); if (no_ipopt_pack) bf_afree(no_ipopt_pack); if (!delivered) { DBLOCK(0x2, printf("udp: could not deliver packet from "); writeIpAddr(src_addr); printf(".%u to ", ntohs(src_port)); writeIpAddr(dst_addr); printf(".%u\n", ntohs(dst_port))); pack= bf_append(ip_hdr_acc, udp_acc); ip_hdr_acc= NULL; udp_acc= NULL; icmp_snd_unreachable(udp_port->up_ipdev, pack, ICMP_PORT_UNRCH); return; } assert (ip_hdr_acc); bf_afree(ip_hdr_acc); assert (udp_acc); bf_afree(udp_acc);}PUBLIC void udp_close(fd)int fd;{ udp_fd_t *udp_fd; acc_t *tmp_acc, *next_acc; udp_fd= &udp_fd_table[fd]; assert (udp_fd->uf_flags & UFF_INUSE); if (udp_fd->uf_flags & UFF_OPTSET) unhash_fd(udp_fd); udp_fd->uf_flags= UFF_EMPTY; 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;}PUBLIC int udp_write(fd, count)int fd;size_t count;{ udp_fd_t *udp_fd; udp_port_t *udp_port; udp_fd= &udp_fd_table[fd]; udp_port= udp_fd->uf_port; if (!(udp_fd->uf_flags & UFF_OPTSET)) { reply_thr_get (udp_fd, EBADMODE, FALSE); return NW_OK; }assert (!(udp_fd->uf_flags & UFF_WRITE_IP)); udp_fd->uf_wr_count= count; udp_fd->uf_flags |= UFF_WRITE_IP; restart_write_fd(udp_fd); if (udp_fd->uf_flags & UFF_WRITE_IP) { DBLOCK(1, printf("replying NW_SUSPEND\n")); return NW_SUSPEND; } else { return NW_OK; }}PRIVATE void restart_write_fd(udp_fd)udp_fd_t *udp_fd;{ udp_port_t *udp_port; acc_t *pack, *ip_hdr_pack, *udp_hdr_pack, *ip_opt_pack, *user_data; udp_hdr_t *udp_hdr; udp_io_hdr_t *udp_io_hdr; ip_hdr_t *ip_hdr; size_t ip_opt_size, user_data_size; unsigned long flags; u16_t chksum; u8_t u16[2]; int result; udp_port= udp_fd->uf_port; if (udp_port->up_flags & UPF_WRITE_IP) { udp_port->up_flags |= UPF_MORE2WRITE; return; }assert (udp_fd->uf_flags & UFF_WRITE_IP); udp_fd->uf_flags &= ~UFF_WRITE_IP;assert (!udp_port->up_wr_pack); pack= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0, udp_fd->uf_wr_count, FALSE); if (!pack) { udp_fd->uf_flags &= ~UFF_WRITE_IP; reply_thr_get (udp_fd, EFAULT, FALSE); return; } flags= udp_fd->uf_udpopt.nwuo_flags; ip_hdr_pack= bf_memreq(IP_MIN_HDR_SIZE); ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_pack); udp_hdr_pack= bf_memreq(UDP_HDR_SIZE); udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_hdr_pack); if (flags & NWUO_RWDATALL) { pack= bf_packIffLess(pack, UDP_IO_HDR_SIZE); udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(pack);#if CONF_UDP_IO_NW_BYTE_ORDER ip_opt_size= ntohs(udp_io_hdr->uih_ip_opt_len);#else ip_opt_size= udp_io_hdr->uih_ip_opt_len;#endif if (UDP_IO_HDR_SIZE+ip_opt_size>udp_fd->uf_wr_count) { bf_afree(ip_hdr_pack); bf_afree(udp_hdr_pack); bf_afree(pack); reply_thr_get (udp_fd, EINVAL, FALSE); return; } if (ip_opt_size & 3) { bf_afree(ip_hdr_pack); bf_afree(udp_hdr_pack); bf_afree(pack); reply_thr_get (udp_fd, EFAULT, FALSE); return; } if (ip_opt_size) ip_opt_pack= bf_cut(pack, UDP_IO_HDR_SIZE, ip_opt_size); else ip_opt_pack= 0; user_data_size= udp_fd->uf_wr_count-UDP_IO_HDR_SIZE- ip_opt_size; user_data= bf_cut(pack, UDP_IO_HDR_SIZE+ip_opt_size, user_data_size); bf_afree(pack); } else { udp_io_hdr= 0; ip_opt_size= 0; user_data_size= udp_fd->uf_wr_count; ip_opt_pack= 0; user_data= pack; } ip_hdr->ih_vers_ihl= (IP_MIN_HDR_SIZE+ip_opt_size) >> 2; ip_hdr->ih_tos= UDP_TOS; ip_hdr->ih_flags_fragoff= HTONS(UDP_IP_FLAGS); ip_hdr->ih_ttl= IP_DEF_TTL; ip_hdr->ih_proto= IPPROTO_UDP; if (flags & NWUO_RA_SET) { ip_hdr->ih_dst= udp_fd->uf_udpopt.nwuo_remaddr; } else {assert (udp_io_hdr); ip_hdr->ih_dst= udp_io_hdr->uih_dst_addr; } if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_ANY) udp_hdr->uh_src_port= udp_fd->uf_udpopt.nwuo_locport; else {assert (udp_io_hdr); udp_hdr->uh_src_port= udp_io_hdr->uih_src_port; } if (flags & NWUO_RP_SET) udp_hdr->uh_dst_port= udp_fd->uf_udpopt.nwuo_remport; else {assert (udp_io_hdr); udp_hdr->uh_dst_port= udp_io_hdr->uih_dst_port; } udp_hdr->uh_length= htons(UDP_HDR_SIZE+user_data_size); udp_hdr->uh_chksum= 0; udp_hdr_pack->acc_next= user_data; chksum= pack_oneCsum(udp_hdr_pack); chksum= oneC_sum(chksum, (u16_t *)&udp_fd->uf_port->up_ipaddr, sizeof(ipaddr_t)); chksum= oneC_sum(chksum, (u16_t *)&ip_hdr->ih_dst, sizeof(ipaddr_t)); u16[0]= 0; u16[1]= IPPROTO_UDP; chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16)); chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length, sizeof(u16_t)); if (~chksum) chksum= ~chksum; udp_hdr->uh_chksum= chksum; if (ip_opt_pack) { ip_opt_pack= bf_packIffLess(ip_opt_pack, ip_opt_size); ip_opt_pack->acc_next= udp_hdr_pack; udp_hdr_pack= ip_opt_pack; } ip_hdr_pack->acc_next= udp_hdr_pack;assert (!udp_port->up_wr_pack);assert (!(udp_port->up_flags & UPF_WRITE_IP)); udp_port->up_wr_pack= ip_hdr_pack; udp_port->up_flags |= UPF_WRITE_IP; result= ip_write(udp_port->up_ipfd, bf_bufsize(ip_hdr_pack)); if (result == NW_SUSPEND) { udp_port->up_flags |= UPF_WRITE_SP; udp_fd->uf_flags |= UFF_WRITE_IP; udp_port->up_write_fd= udp_fd; } else if (result<0) reply_thr_get(udp_fd, result, FALSE); else reply_thr_get (udp_fd, udp_fd->uf_wr_count, FALSE);}PRIVATE u16_t pack_oneCsum(pack)acc_t *pack;{ u16_t prev; int odd_byte; char *data_ptr; int length; char byte_buf[2]; assert (pack); prev= 0; odd_byte= FALSE; for (; pack; pack= pack->acc_next) { data_ptr= ptr2acc_data(pack); length= pack->acc_length; if (!length) continue; if (odd_byte) { byte_buf[1]= *data_ptr; prev= oneC_sum(prev, (u16_t *)byte_buf, 2); data_ptr++; length--; odd_byte= FALSE; } if (length & 1) { odd_byte= TRUE; length--; byte_buf[0]= data_ptr[length]; } if (!length) continue; prev= oneC_sum (prev, (u16_t *)data_ptr, length); } if (odd_byte) { byte_buf[1]= 0; prev= oneC_sum (prev, (u16_t *)byte_buf, 1); } return prev;}PRIVATE void udp_restart_write_port(udp_port )udp_port_t *udp_port;{ udp_fd_t *udp_fd; int i;assert (!udp_port->up_wr_pack);assert (!(udp_port->up_flags & (UPF_WRITE_IP|UPF_WRITE_SP))); while (udp_port->up_flags & UPF_MORE2WRITE) { udp_port->up_flags &= ~UPF_MORE2WRITE; for (i= 0, udp_fd= udp_port->up_next_fd; i<UDP_FD_NR; i++, udp_fd++) { if (udp_fd == &udp_fd_table[UDP_FD_NR]) udp_fd= udp_fd_table; if (!(udp_fd->uf_flags & UFF_INUSE)) continue; if (!(udp_fd->uf_flags & UFF_WRITE_IP)) continue; if (udp_fd->uf_port != udp_port) continue; restart_write_fd(udp_fd); if (udp_port->up_flags & UPF_WRITE_IP) { udp_port->up_next_fd= udp_fd+1; udp_port->up_flags |= UPF_MORE2WRITE; return; } } }}PUBLIC int udp_cancel(fd, which_operation)int fd;int which_operation;{ udp_fd_t *udp_fd; DBLOCK(0x10, printf("udp_cancel(%d, %d)\n", fd, which_operation)); udp_fd= &udp_fd_table[fd]; switch (which_operation) { case SR_CANCEL_READ:assert (udp_fd->uf_flags & UFF_READ_IP); udp_fd->uf_flags &= ~UFF_READ_IP; reply_thr_put(udp_fd, EINTR, FALSE); break; case SR_CANCEL_WRITE:assert (udp_fd->uf_flags & UFF_WRITE_IP); udp_fd->uf_flags &= ~UFF_WRITE_IP; if (udp_fd->uf_port->up_write_fd == udp_fd) udp_fd->uf_port->up_write_fd= NULL; reply_thr_get(udp_fd, EINTR, FALSE); break; case SR_CANCEL_IOCTL:assert (udp_fd->uf_flags & UFF_IOCTL_IP); udp_fd->uf_flags &= ~UFF_IOCTL_IP; udp_fd->uf_flags &= ~UFF_PEEK_IP; reply_thr_get(udp_fd, EINTR, TRUE); break; default: ip_panic(( "got unknown cancel request" )); } return NW_OK;}PRIVATE void udp_buffree (priority)int priority;{ int i; udp_fd_t *udp_fd; acc_t *tmp_acc; if (priority == UDP_PRI_FDBUFS_EXTRA) { for (i=0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++) { while (udp_fd->uf_rdbuf_head && udp_fd->uf_rdbuf_head->acc_ext_link) { tmp_acc= udp_fd->uf_rdbuf_head; udp_fd->uf_rdbuf_head= tmp_acc->acc_ext_link; bf_afree(tmp_acc); } } } if (priority == UDP_PRI_FDBUFS) { for (i=0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++) { while (udp_fd->uf_rdbuf_head) { tmp_acc= udp_fd->uf_rdbuf_head; udp_fd->uf_rdbuf_head= tmp_acc->acc_ext_link; bf_afree(tmp_acc); } } }}PRIVATE void udp_rd_enqueue(udp_fd, pack, exp_tim)udp_fd_t *udp_fd;acc_t *pack;clock_t exp_tim;{ acc_t *tmp_acc; int result; if (pack->acc_linkC != 1) { tmp_acc= bf_dupacc(pack); bf_afree(pack); pack= tmp_acc; } pack->acc_ext_link= NULL; if (udp_fd->uf_rdbuf_head == NULL) { udp_fd->uf_exp_tim= exp_tim; udp_fd->uf_rdbuf_head= pack; } else udp_fd->uf_rdbuf_tail->acc_ext_link= pack; udp_fd->uf_rdbuf_tail= pack; if (udp_fd->uf_flags & UFF_PEEK_IP) { 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; udp_fd->uf_flags &= ~UFF_PEEK_IP; result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, result, (acc_t *)0, TRUE); assert (result == 0); } if (udp_fd->uf_flags & UFF_SEL_READ) { udp_fd->uf_flags &= ~UFF_SEL_READ; if (udp_fd->uf_select_res) udp_fd->uf_select_res(udp_fd->uf_srfd, SR_SELECT_READ); else printf("udp_rd_enqueue: no select_res\n"); }}PRIVATE void hash_fd(udp_fd)udp_fd_t *udp_fd;{ udp_port_t *udp_port; int hash; udp_port= udp_fd->uf_port; if ((udp_fd->uf_udpopt.nwuo_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY) { udp_fd->uf_port_next= udp_port->up_port_any; udp_port->up_port_any= udp_fd; } else { hash= udp_fd->uf_udpopt.nwuo_locport; hash ^= (hash >> 8); hash &= (UDP_PORT_HASH_NR-1); udp_fd->uf_port_next= udp_port->up_port_hash[hash]; udp_port->up_port_hash[hash]= udp_fd; }}PRIVATE void unhash_fd(udp_fd)udp_fd_t *udp_fd;{ udp_port_t *udp_port; udp_fd_t *prev, *curr, **udp_fd_p; int hash; udp_port= udp_fd->uf_port; if ((udp_fd->uf_udpopt.nwuo_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY) { udp_fd_p= &udp_port->up_port_any; } else { hash= udp_fd->uf_udpopt.nwuo_locport; hash ^= (hash >> 8); hash &= (UDP_PORT_HASH_NR-1); udp_fd_p= &udp_port->up_port_hash[hash]; } for (prev= NULL, curr= *udp_fd_p; curr; prev= curr, curr= curr->uf_port_next) { if (curr == udp_fd) break; } assert(curr); if (prev) prev->uf_port_next= curr->uf_port_next; else *udp_fd_p= curr->uf_port_next;}#ifdef BUF_CONSISTENCY_CHECKPRIVATE void udp_bufcheck(){ int i; udp_port_t *udp_port; udp_fd_t *udp_fd; acc_t *tmp_acc; for (i= 0, udp_port= udp_port_table; i<udp_conf_nr; i++, udp_port++) { if (udp_port->up_wr_pack) bf_check_acc(udp_port->up_wr_pack); } for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++) { for (tmp_acc= udp_fd->uf_rdbuf_head; tmp_acc; tmp_acc= tmp_acc->acc_ext_link) { bf_check_acc(tmp_acc); } }}#endif/* * $PchId: udp.c,v 1.25 2005/06/28 14:14:44 philip Exp $ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -