1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License as published by 4 * the Free Software Foundation; either version 2 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, see <http://www.gnu.org/licenses/>. 14 */ 15 16 #ifndef FD_TRANS_H 17 #define FD_TRANS_H 18 19 #include "qemu/lockable.h" 20 21 typedef abi_long (*TargetFdDataFunc)(void *, size_t); 22 typedef abi_long (*TargetFdAddrFunc)(void *, abi_ulong, socklen_t); 23 typedef struct TargetFdTrans { 24 TargetFdDataFunc host_to_target_data; 25 TargetFdDataFunc target_to_host_data; 26 TargetFdAddrFunc target_to_host_addr; 27 } TargetFdTrans; 28 29 extern TargetFdTrans **target_fd_trans; 30 extern QemuMutex target_fd_trans_lock; 31 32 extern unsigned int target_fd_max; 33 34 static inline void fd_trans_init(void) 35 { 36 qemu_mutex_init(&target_fd_trans_lock); 37 } 38 39 static inline TargetFdDataFunc fd_trans_target_to_host_data(int fd) 40 { 41 if (fd < 0) { 42 return NULL; 43 } 44 45 QEMU_LOCK_GUARD(&target_fd_trans_lock); 46 if (fd < target_fd_max && target_fd_trans[fd]) { 47 return target_fd_trans[fd]->target_to_host_data; 48 } 49 return NULL; 50 } 51 52 static inline TargetFdDataFunc fd_trans_host_to_target_data(int fd) 53 { 54 if (fd < 0) { 55 return NULL; 56 } 57 58 QEMU_LOCK_GUARD(&target_fd_trans_lock); 59 if (fd < target_fd_max && target_fd_trans[fd]) { 60 return target_fd_trans[fd]->host_to_target_data; 61 } 62 return NULL; 63 } 64 65 static inline TargetFdAddrFunc fd_trans_target_to_host_addr(int fd) 66 { 67 if (fd < 0) { 68 return NULL; 69 } 70 71 QEMU_LOCK_GUARD(&target_fd_trans_lock); 72 if (fd < target_fd_max && target_fd_trans[fd]) { 73 return target_fd_trans[fd]->target_to_host_addr; 74 } 75 return NULL; 76 } 77 78 static inline void internal_fd_trans_register_unsafe(int fd, 79 TargetFdTrans *trans) 80 { 81 unsigned int oldmax; 82 83 if (fd >= target_fd_max) { 84 oldmax = target_fd_max; 85 target_fd_max = ((fd >> 6) + 1) << 6; /* by slice of 64 entries */ 86 target_fd_trans = g_renew(TargetFdTrans *, 87 target_fd_trans, target_fd_max); 88 memset((void *)(target_fd_trans + oldmax), 0, 89 (target_fd_max - oldmax) * sizeof(TargetFdTrans *)); 90 } 91 target_fd_trans[fd] = trans; 92 } 93 94 static inline void fd_trans_register(int fd, TargetFdTrans *trans) 95 { 96 QEMU_LOCK_GUARD(&target_fd_trans_lock); 97 internal_fd_trans_register_unsafe(fd, trans); 98 } 99 100 static inline void internal_fd_trans_unregister_unsafe(int fd) 101 { 102 if (fd >= 0 && fd < target_fd_max) { 103 target_fd_trans[fd] = NULL; 104 } 105 } 106 107 static inline void fd_trans_unregister(int fd) 108 { 109 if (fd < 0) { 110 return; 111 } 112 113 QEMU_LOCK_GUARD(&target_fd_trans_lock); 114 internal_fd_trans_unregister_unsafe(fd); 115 } 116 117 static inline void fd_trans_dup(int oldfd, int newfd) 118 { 119 QEMU_LOCK_GUARD(&target_fd_trans_lock); 120 internal_fd_trans_unregister_unsafe(newfd); 121 if (oldfd < target_fd_max && target_fd_trans[oldfd]) { 122 internal_fd_trans_register_unsafe(newfd, target_fd_trans[oldfd]); 123 } 124 } 125 126 extern TargetFdTrans target_packet_trans; 127 #ifdef CONFIG_RTNETLINK 128 extern TargetFdTrans target_netlink_route_trans; 129 #endif 130 extern TargetFdTrans target_netlink_audit_trans; 131 extern TargetFdTrans target_signalfd_trans; 132 extern TargetFdTrans target_eventfd_trans; 133 #if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \ 134 (defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \ 135 defined(__NR_inotify_init1)) 136 extern TargetFdTrans target_inotify_trans; 137 #endif 138 #endif 139