| @@ -1,56 +1,72 @@ | | | @@ -1,56 +1,72 @@ |
1 | $NetBSD: patch-lib_isc_unix_socket.c,v 1.6 2021/10/24 06:40:28 taca Exp $ | | 1 | $NetBSD: patch-lib_isc_unix_socket.c,v 1.6.2.1 2022/03/03 18:51:38 bsiegert Exp $ |
2 | | | 2 | |
3 | * Apply fixes from NetBSD base system. | | 3 | * Apply fixes from NetBSD base system. |
4 | * Fix build on SmartOS. In this special case, _XOPEN_SOURCE has to be only | | 4 | * Fix build on SunOS. In this special case, _XOPEN_SOURCE has to be only |
5 | defined on SmartOS. | | 5 | defined on SunOS. |
6 | | | 6 | |
7 | --- lib/isc/unix/socket.c.orig 2021-09-07 09:37:05.000000000 +0000 | | 7 | --- lib/isc/unix/socket.c.orig 2022-01-12 13:50:10.000000000 +0000 |
8 | +++ lib/isc/unix/socket.c | | 8 | +++ lib/isc/unix/socket.c |
9 | @@ -360,6 +360,10 @@ struct isc_socket { | | 9 | @@ -13,6 +13,15 @@ |
| | | 10 | |
| | | 11 | /*! \file */ |
| | | 12 | |
| | | 13 | +/* needed for CMSG_DATA */ |
| | | 14 | +#if defined(__sun) |
| | | 15 | +#if (__STDC_VERSION__ - 0 < 199901L) |
| | | 16 | +#define _XOPEN_SOURCE 500 |
| | | 17 | +#else |
| | | 18 | +#define _XOPEN_SOURCE 600 |
| | | 19 | +#endif |
| | | 20 | +#endif |
| | | 21 | + |
| | | 22 | #include <inttypes.h> |
| | | 23 | #include <stdbool.h> |
| | | 24 | #include <sys/param.h> |
| | | 25 | @@ -362,6 +371,10 @@ struct isc_socket { |
10 | unsigned char overflow; /* used for MSG_TRUNC fake */ | | 26 | unsigned char overflow; /* used for MSG_TRUNC fake */ |
11 | #endif /* ifdef ISC_PLATFORM_RECVOVERFLOW */ | | 27 | #endif /* ifdef ISC_PLATFORM_RECVOVERFLOW */ |
12 | | | 28 | |
13 | + void *fdwatcharg; | | 29 | + void *fdwatcharg; |
14 | + isc_sockfdwatch_t fdwatchcb; | | 30 | + isc_sockfdwatch_t fdwatchcb; |
15 | + int fdwatchflags; | | 31 | + int fdwatchflags; |
16 | + isc_task_t *fdwatchtask; | | 32 | + isc_task_t *fdwatchtask; |
17 | unsigned int dscp; | | 33 | unsigned int dscp; |
18 | }; | | 34 | }; |
19 | | | 35 | |
20 | @@ -469,6 +473,14 @@ static bool | | 36 | @@ -471,6 +484,14 @@ static bool |
21 | process_ctlfd(isc__socketthread_t *thread); | | 37 | process_ctlfd(isc__socketthread_t *thread); |
22 | static void | | 38 | static void |
23 | setdscp(isc_socket_t *sock, isc_dscp_t dscp); | | 39 | setdscp(isc_socket_t *sock, isc_dscp_t dscp); |
24 | +static void | | 40 | +static void |
25 | +dispatch_recv(isc_socket_t *sock); | | 41 | +dispatch_recv(isc_socket_t *sock); |
26 | +static void | | 42 | +static void |
27 | +dispatch_send(isc_socket_t *sock); | | 43 | +dispatch_send(isc_socket_t *sock); |
28 | +static void | | 44 | +static void |
29 | +internal_fdwatch_read(isc_socket_t *sock); | | 45 | +internal_fdwatch_read(isc_socket_t *sock); |
30 | +static void | | 46 | +static void |
31 | +internal_fdwatch_write(isc_socket_t *sock); | | 47 | +internal_fdwatch_write(isc_socket_t *sock); |
32 | | | 48 | |
33 | #define SELECT_POKE_SHUTDOWN (-1) | | 49 | #define SELECT_POKE_SHUTDOWN (-1) |
34 | #define SELECT_POKE_NOTHING (-2) | | 50 | #define SELECT_POKE_NOTHING (-2) |
35 | @@ -1573,6 +1585,7 @@ doio_recv(isc_socket_t *sock, isc_socket | | 51 | @@ -1574,6 +1595,7 @@ doio_recv(isc_socket_t *sock, isc_socket |
36 | case isc_sockettype_udp: | | 52 | case isc_sockettype_udp: |
37 | case isc_sockettype_raw: | | 53 | case isc_sockettype_raw: |
38 | break; | | 54 | break; |
39 | + case isc_sockettype_fdwatch: | | 55 | + case isc_sockettype_fdwatch: |
40 | default: | | 56 | default: |
41 | INSIST(0); | | 57 | INSIST(0); |
42 | ISC_UNREACHABLE(); | | 58 | ISC_UNREACHABLE(); |
43 | @@ -1781,9 +1794,26 @@ socketclose(isc__socketthread_t *thread, | | 59 | @@ -1782,9 +1804,26 @@ socketclose(isc__socketthread_t *thread, |
44 | */ | | 60 | */ |
45 | LOCK(&thread->fdlock[lockid]); | | 61 | LOCK(&thread->fdlock[lockid]); |
46 | thread->fds[fd] = NULL; | | 62 | thread->fds[fd] = NULL; |
47 | + if (sock->type == isc_sockettype_fdwatch) | | 63 | + if (sock->type == isc_sockettype_fdwatch) |
48 | + thread->fdstate[fd] = CLOSED; | | 64 | + thread->fdstate[fd] = CLOSED; |
49 | + else | | 65 | + else |
50 | thread->fdstate[fd] = CLOSE_PENDING; | | 66 | thread->fdstate[fd] = CLOSE_PENDING; |
51 | UNLOCK(&thread->fdlock[lockid]); | | 67 | UNLOCK(&thread->fdlock[lockid]); |
52 | - select_poke(thread->manager, thread->threadid, fd, SELECT_POKE_CLOSE); | | 68 | - select_poke(thread->manager, thread->threadid, fd, SELECT_POKE_CLOSE); |
53 | + if (sock->type == isc_sockettype_fdwatch) { | | 69 | + if (sock->type == isc_sockettype_fdwatch) { |
54 | + /* | | 70 | + /* |
55 | + * The caller may close the socket once this function returns, | | 71 | + * The caller may close the socket once this function returns, |
56 | + * and `fd' may be reassigned for a new socket. So we do | | 72 | + * and `fd' may be reassigned for a new socket. So we do |
| @@ -58,90 +74,90 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1 | | | @@ -58,90 +74,90 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1 |
58 | + * Note: this may complicate data protection among threads and | | 74 | + * Note: this may complicate data protection among threads and |
59 | + * may reduce performance due to additional locks. One way to | | 75 | + * may reduce performance due to additional locks. One way to |
60 | + * solve this would be to dup() the watched descriptor, but we | | 76 | + * solve this would be to dup() the watched descriptor, but we |
61 | + * take a simpler approach at this moment. | | 77 | + * take a simpler approach at this moment. |
62 | + */ | | 78 | + */ |
63 | + (void)unwatch_fd(thread, fd, SELECT_POKE_READ); | | 79 | + (void)unwatch_fd(thread, fd, SELECT_POKE_READ); |
64 | + (void)unwatch_fd(thread, fd, SELECT_POKE_WRITE); | | 80 | + (void)unwatch_fd(thread, fd, SELECT_POKE_WRITE); |
65 | + } else | | 81 | + } else |
66 | + select_poke(thread->manager, thread->threadid, fd, | | 82 | + select_poke(thread->manager, thread->threadid, fd, |
67 | + SELECT_POKE_CLOSE); | | 83 | + SELECT_POKE_CLOSE); |
68 | | | 84 | |
69 | inc_stats(thread->manager->stats, sock->statsindex[STATID_CLOSE]); | | 85 | inc_stats(thread->manager->stats, sock->statsindex[STATID_CLOSE]); |
70 | | | 86 | |
71 | @@ -2190,6 +2220,13 @@ again: | | 87 | @@ -2191,6 +2230,13 @@ again: |
72 | } | | 88 | } |
73 | #endif /* if defined(PF_ROUTE) */ | | 89 | #endif /* if defined(PF_ROUTE) */ |
74 | break; | | 90 | break; |
75 | + case isc_sockettype_fdwatch: | | 91 | + case isc_sockettype_fdwatch: |
76 | + /* | | 92 | + /* |
77 | + * We should not be called for isc_sockettype_fdwatch | | 93 | + * We should not be called for isc_sockettype_fdwatch |
78 | + * sockets. | | 94 | + * sockets. |
79 | + */ | | 95 | + */ |
80 | + INSIST(0); | | 96 | + INSIST(0); |
81 | + break; | | 97 | + break; |
82 | } | | 98 | } |
83 | } else { | | 99 | } else { |
84 | sock->fd = dup(dup_socket->fd); | | 100 | sock->fd = dup(dup_socket->fd); |
85 | @@ -2439,6 +2476,7 @@ socket_create(isc_socketmgr_t *manager, | | 101 | @@ -2440,6 +2486,7 @@ socket_create(isc_socketmgr_t *manager, |
86 | | | 102 | |
87 | REQUIRE(VALID_MANAGER(manager)); | | 103 | REQUIRE(VALID_MANAGER(manager)); |
88 | REQUIRE(socketp != NULL && *socketp == NULL); | | 104 | REQUIRE(socketp != NULL && *socketp == NULL); |
89 | + REQUIRE(type != isc_sockettype_fdwatch); | | 105 | + REQUIRE(type != isc_sockettype_fdwatch); |
90 | | | 106 | |
91 | result = allocate_socket(manager, type, &sock); | | 107 | result = allocate_socket(manager, type, &sock); |
92 | if (result != ISC_R_SUCCESS) { | | 108 | if (result != ISC_R_SUCCESS) { |
93 | @@ -2553,6 +2591,7 @@ isc_socket_open(isc_socket_t *sock) { | | 109 | @@ -2554,6 +2601,7 @@ isc_socket_open(isc_socket_t *sock) { |
94 | REQUIRE(isc_refcount_current(&sock->references) >= 1); | | 110 | REQUIRE(isc_refcount_current(&sock->references) >= 1); |
95 | REQUIRE(sock->fd == -1); | | 111 | REQUIRE(sock->fd == -1); |
96 | REQUIRE(sock->threadid == -1); | | 112 | REQUIRE(sock->threadid == -1); |
97 | + REQUIRE(sock->type != isc_sockettype_fdwatch); | | 113 | + REQUIRE(sock->type != isc_sockettype_fdwatch); |
98 | | | 114 | |
99 | result = opensocket(sock->manager, sock, NULL); | | 115 | result = opensocket(sock->manager, sock, NULL); |
100 | | | 116 | |
101 | @@ -2631,6 +2670,7 @@ isc_socket_close(isc_socket_t *sock) { | | 117 | @@ -2632,6 +2680,7 @@ isc_socket_close(isc_socket_t *sock) { |
102 | | | 118 | |
103 | LOCK(&sock->lock); | | 119 | LOCK(&sock->lock); |
104 | | | 120 | |
105 | + REQUIRE(sock->type != isc_sockettype_fdwatch); | | 121 | + REQUIRE(sock->type != isc_sockettype_fdwatch); |
106 | REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks); | | 122 | REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks); |
107 | | | 123 | |
108 | INSIST(!sock->connecting); | | 124 | INSIST(!sock->connecting); |
109 | @@ -2661,6 +2701,24 @@ isc_socket_close(isc_socket_t *sock) { | | 125 | @@ -2662,6 +2711,24 @@ isc_socket_close(isc_socket_t *sock) { |
110 | return (ISC_R_SUCCESS); | | 126 | return (ISC_R_SUCCESS); |
111 | } | | 127 | } |
112 | | | 128 | |
113 | +static void | | 129 | +static void |
114 | +dispatch_recv(isc_socket_t *sock) { | | 130 | +dispatch_recv(isc_socket_t *sock) { |
115 | + if (sock->type != isc_sockettype_fdwatch) { | | 131 | + if (sock->type != isc_sockettype_fdwatch) { |
116 | + internal_recv(sock); | | 132 | + internal_recv(sock); |
117 | + } else { | | 133 | + } else { |
118 | + internal_fdwatch_read(sock); | | 134 | + internal_fdwatch_read(sock); |
119 | + } | | 135 | + } |
120 | +} | | 136 | +} |
121 | + | | 137 | + |
122 | +static void | | 138 | +static void |
123 | +dispatch_send(isc_socket_t *sock) { | | 139 | +dispatch_send(isc_socket_t *sock) { |
124 | + if (sock->type != isc_sockettype_fdwatch) { | | 140 | + if (sock->type != isc_sockettype_fdwatch) { |
125 | + internal_send(sock); | | 141 | + internal_send(sock); |
126 | + } else { | | 142 | + } else { |
127 | + internal_fdwatch_write(sock); | | 143 | + internal_fdwatch_write(sock); |
128 | + } | | 144 | + } |
129 | +} | | 145 | +} |
130 | + | | 146 | + |
131 | /* | | 147 | /* |
132 | * Dequeue an item off the given socket's read queue, set the result code | | 148 | * Dequeue an item off the given socket's read queue, set the result code |
133 | * in the done event to the one provided, and send it to the task it was | | 149 | * in the done event to the one provided, and send it to the task it was |
134 | @@ -3101,6 +3159,58 @@ finish: | | 150 | @@ -3102,6 +3169,58 @@ finish: |
135 | } | | 151 | } |
136 | } | | 152 | } |
137 | | | 153 | |
138 | +static void | | 154 | +static void |
139 | +internal_fdwatch_write(isc_socket_t *sock) | | 155 | +internal_fdwatch_write(isc_socket_t *sock) |
140 | +{ | | 156 | +{ |
141 | + int more_data; | | 157 | + int more_data; |
142 | + | | 158 | + |
143 | + INSIST(VALID_SOCKET(sock)); | | 159 | + INSIST(VALID_SOCKET(sock)); |
144 | + | | 160 | + |
145 | + isc_refcount_increment(&sock->references); | | 161 | + isc_refcount_increment(&sock->references); |
146 | + UNLOCK(&sock->lock); | | 162 | + UNLOCK(&sock->lock); |
147 | + | | 163 | + |
| @@ -180,72 +196,72 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1 | | | @@ -180,72 +196,72 @@ $NetBSD: patch-lib_isc_unix_socket.c,v 1 |
180 | + UNLOCK(&sock->lock); | | 196 | + UNLOCK(&sock->lock); |
181 | + destroy(&sock); | | 197 | + destroy(&sock); |
182 | + return; | | 198 | + return; |
183 | + } | | 199 | + } |
184 | + | | 200 | + |
185 | + if (more_data) | | 201 | + if (more_data) |
186 | + select_poke(sock->manager, sock->threadid, sock->fd, | | 202 | + select_poke(sock->manager, sock->threadid, sock->fd, |
187 | + SELECT_POKE_READ); | | 203 | + SELECT_POKE_READ); |
188 | +} | | 204 | +} |
189 | + | | 205 | + |
190 | /* | | 206 | /* |
191 | * Process read/writes on each fd here. Avoid locking | | 207 | * Process read/writes on each fd here. Avoid locking |
192 | * and unlocking twice if both reads and writes are possible. | | 208 | * and unlocking twice if both reads and writes are possible. |
193 | @@ -3148,7 +3258,7 @@ process_fd(isc__socketthread_t *thread, | | 209 | @@ -3149,7 +3268,7 @@ process_fd(isc__socketthread_t *thread, |
194 | if (sock->connecting) { | | 210 | if (sock->connecting) { |
195 | internal_connect(sock); | | 211 | internal_connect(sock); |
196 | } else { | | 212 | } else { |
197 | - internal_send(sock); | | 213 | - internal_send(sock); |
198 | + dispatch_send(sock); | | 214 | + dispatch_send(sock); |
199 | } | | 215 | } |
200 | } | | 216 | } |
201 | | | 217 | |
202 | @@ -3156,7 +3266,7 @@ process_fd(isc__socketthread_t *thread, | | 218 | @@ -3157,7 +3276,7 @@ process_fd(isc__socketthread_t *thread, |
203 | if (sock->listener) { | | 219 | if (sock->listener) { |
204 | internal_accept(sock); /* unlocks sock */ | | 220 | internal_accept(sock); /* unlocks sock */ |
205 | } else { | | 221 | } else { |
206 | - internal_recv(sock); | | 222 | - internal_recv(sock); |
207 | + dispatch_recv(sock); | | 223 | + dispatch_recv(sock); |
208 | UNLOCK(&sock->lock); | | 224 | UNLOCK(&sock->lock); |
209 | } | | 225 | } |
210 | } else { | | 226 | } else { |
211 | @@ -3797,7 +3907,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, i | | 227 | @@ -3798,7 +3917,7 @@ isc_socketmgr_create2(isc_mem_t *mctx, i |
212 | isc_thread_create(netthread, &manager->threads[i], | | 228 | isc_thread_create(netthread, &manager->threads[i], |
213 | &manager->threads[i].thread); | | 229 | &manager->threads[i].thread); |
214 | char tname[1024]; | | 230 | char tname[1024]; |
215 | - sprintf(tname, "isc-socket-%d", i); | | 231 | - sprintf(tname, "isc-socket-%d", i); |
216 | + sprintf(tname, "socket-%d", i); | | 232 | + sprintf(tname, "socket-%d", i); |
217 | isc_thread_setname(manager->threads[i].thread, tname); | | 233 | isc_thread_setname(manager->threads[i].thread, tname); |
218 | } | | 234 | } |
219 | | | 235 | |
220 | @@ -5218,7 +5328,7 @@ static isc_once_t hasreuseport_once = IS | | 236 | @@ -5219,7 +5338,7 @@ static isc_once_t hasreuseport_once = IS |
221 | static bool hasreuseport = false; | | 237 | static bool hasreuseport = false; |
222 | | | 238 | |
223 | static void | | 239 | static void |
224 | -init_hasreuseport() { | | 240 | -init_hasreuseport() { |
225 | +init_hasreuseport(void) { | | 241 | +init_hasreuseport(void) { |
226 | /* | | 242 | /* |
227 | * SO_REUSEPORT works very differently on *BSD and on Linux (because why not). | | 243 | * SO_REUSEPORT works very differently on *BSD and on Linux (because why not). |
228 | * We only want to use it on Linux, if it's available. On BSD we want to dup() | | 244 | * We only want to use it on Linux, if it's available. On BSD we want to dup() |
229 | @@ -5272,6 +5382,8 @@ _socktype(isc_sockettype_t type) { | | 245 | @@ -5273,6 +5392,8 @@ _socktype(isc_sockettype_t type) { |
230 | return ("tcp"); | | 246 | return ("tcp"); |
231 | case isc_sockettype_unix: | | 247 | case isc_sockettype_unix: |
232 | return ("unix"); | | 248 | return ("unix"); |
233 | + case isc_sockettype_fdwatch: | | 249 | + case isc_sockettype_fdwatch: |
234 | + return ("fdwatch"); | | 250 | + return ("fdwatch"); |
235 | default: | | 251 | default: |
236 | return ("not-initialized"); | | 252 | return ("not-initialized"); |
237 | } | | 253 | } |
238 | @@ -5502,3 +5614,113 @@ error: | | 254 | @@ -5503,3 +5624,113 @@ error: |
239 | return (result); | | 255 | return (result); |
240 | } | | 256 | } |
241 | #endif /* HAVE_JSON_C */ | | 257 | #endif /* HAVE_JSON_C */ |
242 | + | | 258 | + |
243 | +/* | | 259 | +/* |
244 | + * Create a new 'type' socket managed by 'manager'. Events | | 260 | + * Create a new 'type' socket managed by 'manager'. Events |
245 | + * will be posted to 'task' and when dispatched 'action' will be | | 261 | + * will be posted to 'task' and when dispatched 'action' will be |
246 | + * called with 'arg' as the arg value. The new socket is returned | | 262 | + * called with 'arg' as the arg value. The new socket is returned |
247 | + * in 'socketp'. | | 263 | + * in 'socketp'. |
248 | + */ | | 264 | + */ |
249 | +isc_result_t | | 265 | +isc_result_t |
250 | +isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, | | 266 | +isc_socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags, |
251 | + isc_sockfdwatch_t callback, void *cbarg, | | 267 | + isc_sockfdwatch_t callback, void *cbarg, |