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
fd_trans_init(void)34 static inline void fd_trans_init(void)
35 {
36 qemu_mutex_init(&target_fd_trans_lock);
37 }
38
fd_trans_prefork(void)39 static inline void fd_trans_prefork(void)
40 {
41 qemu_mutex_lock(&target_fd_trans_lock);
42 }
43
fd_trans_postfork(void)44 static inline void fd_trans_postfork(void)
45 {
46 qemu_mutex_unlock(&target_fd_trans_lock);
47 }
48
fd_trans_target_to_host_data(int fd)49 static inline TargetFdDataFunc fd_trans_target_to_host_data(int fd)
50 {
51 if (fd < 0) {
52 return NULL;
53 }
54
55 QEMU_LOCK_GUARD(&target_fd_trans_lock);
56 if (fd < target_fd_max && target_fd_trans[fd]) {
57 return target_fd_trans[fd]->target_to_host_data;
58 }
59 return NULL;
60 }
61
fd_trans_host_to_target_data(int fd)62 static inline TargetFdDataFunc fd_trans_host_to_target_data(int fd)
63 {
64 if (fd < 0) {
65 return NULL;
66 }
67
68 QEMU_LOCK_GUARD(&target_fd_trans_lock);
69 if (fd < target_fd_max && target_fd_trans[fd]) {
70 return target_fd_trans[fd]->host_to_target_data;
71 }
72 return NULL;
73 }
74
fd_trans_target_to_host_addr(int fd)75 static inline TargetFdAddrFunc fd_trans_target_to_host_addr(int fd)
76 {
77 if (fd < 0) {
78 return NULL;
79 }
80
81 QEMU_LOCK_GUARD(&target_fd_trans_lock);
82 if (fd < target_fd_max && target_fd_trans[fd]) {
83 return target_fd_trans[fd]->target_to_host_addr;
84 }
85 return NULL;
86 }
87
internal_fd_trans_register_unsafe(int fd,TargetFdTrans * trans)88 static inline void internal_fd_trans_register_unsafe(int fd,
89 TargetFdTrans *trans)
90 {
91 unsigned int oldmax;
92
93 if (fd >= target_fd_max) {
94 oldmax = target_fd_max;
95 target_fd_max = ((fd >> 6) + 1) << 6; /* by slice of 64 entries */
96 target_fd_trans = g_renew(TargetFdTrans *,
97 target_fd_trans, target_fd_max);
98 memset((void *)(target_fd_trans + oldmax), 0,
99 (target_fd_max - oldmax) * sizeof(TargetFdTrans *));
100 }
101 target_fd_trans[fd] = trans;
102 }
103
fd_trans_register(int fd,TargetFdTrans * trans)104 static inline void fd_trans_register(int fd, TargetFdTrans *trans)
105 {
106 QEMU_LOCK_GUARD(&target_fd_trans_lock);
107 internal_fd_trans_register_unsafe(fd, trans);
108 }
109
internal_fd_trans_unregister_unsafe(int fd)110 static inline void internal_fd_trans_unregister_unsafe(int fd)
111 {
112 if (fd >= 0 && fd < target_fd_max) {
113 target_fd_trans[fd] = NULL;
114 }
115 }
116
fd_trans_unregister(int fd)117 static inline void fd_trans_unregister(int fd)
118 {
119 if (fd < 0) {
120 return;
121 }
122
123 QEMU_LOCK_GUARD(&target_fd_trans_lock);
124 internal_fd_trans_unregister_unsafe(fd);
125 }
126
fd_trans_dup(int oldfd,int newfd)127 static inline void fd_trans_dup(int oldfd, int newfd)
128 {
129 QEMU_LOCK_GUARD(&target_fd_trans_lock);
130 internal_fd_trans_unregister_unsafe(newfd);
131 if (oldfd < target_fd_max && target_fd_trans[oldfd]) {
132 internal_fd_trans_register_unsafe(newfd, target_fd_trans[oldfd]);
133 }
134 }
135
136 extern TargetFdTrans target_packet_trans;
137 #ifdef CONFIG_RTNETLINK
138 extern TargetFdTrans target_netlink_route_trans;
139 #endif
140 extern TargetFdTrans target_netlink_audit_trans;
141 extern TargetFdTrans target_signalfd_trans;
142 extern TargetFdTrans target_eventfd_trans;
143 extern TargetFdTrans target_timerfd_trans;
144 #if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \
145 (defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \
146 defined(__NR_inotify_init1))
147 extern TargetFdTrans target_inotify_trans;
148 #endif
149 #endif
150