/src/net-snmp/snmplib/fd_event_manager.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* UNIT: File Descriptor (FD) Event Manager */ |
2 | | #include <net-snmp/net-snmp-config.h> |
3 | | #ifdef HAVE_SYS_SELECT |
4 | | #include <sys/select.h> |
5 | | #endif |
6 | | #include <net-snmp/net-snmp-includes.h> |
7 | | #include <net-snmp/net-snmp-features.h> |
8 | | #include <net-snmp/library/snmp_api.h> |
9 | | #include <net-snmp/library/fd_event_manager.h> |
10 | | #include <net-snmp/library/snmp_logging.h> |
11 | | #include <net-snmp/library/large_fd_set.h> |
12 | | |
13 | | netsnmp_feature_child_of(fd_event_manager, libnetsnmp); |
14 | | |
15 | | #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER |
16 | | int external_readfd[NUM_EXTERNAL_FDS], external_readfdlen = 0; |
17 | | int external_writefd[NUM_EXTERNAL_FDS], external_writefdlen = 0; |
18 | | int external_exceptfd[NUM_EXTERNAL_FDS], external_exceptfdlen = 0; |
19 | | void (*external_readfdfunc[NUM_EXTERNAL_FDS]) (int, void *); |
20 | | void (*external_writefdfunc[NUM_EXTERNAL_FDS]) (int, void *); |
21 | | void (*external_exceptfdfunc[NUM_EXTERNAL_FDS]) (int, void *); |
22 | | void *external_readfd_data[NUM_EXTERNAL_FDS]; |
23 | | void *external_writefd_data[NUM_EXTERNAL_FDS]; |
24 | | void *external_exceptfd_data[NUM_EXTERNAL_FDS]; |
25 | | |
26 | | static int external_fd_unregistered; |
27 | | |
28 | | /* |
29 | | * Register a given fd for read events. Call callback when events |
30 | | * are received. |
31 | | */ |
32 | | int |
33 | | register_readfd(int fd, void (*func) (int, void *), void *data) |
34 | 0 | { |
35 | 0 | if (external_readfdlen < NUM_EXTERNAL_FDS) { |
36 | 0 | external_readfd[external_readfdlen] = fd; |
37 | 0 | external_readfdfunc[external_readfdlen] = func; |
38 | 0 | external_readfd_data[external_readfdlen] = data; |
39 | 0 | external_readfdlen++; |
40 | 0 | DEBUGMSGTL(("fd_event_manager:register_readfd", "registered fd %d\n", fd)); |
41 | 0 | return FD_REGISTERED_OK; |
42 | 0 | } else { |
43 | 0 | snmp_log(LOG_CRIT, "register_readfd: too many file descriptors\n"); |
44 | 0 | return FD_REGISTRATION_FAILED; |
45 | 0 | } |
46 | 0 | } |
47 | | |
48 | | /* |
49 | | * Register a given fd for write events. Call callback when events |
50 | | * are received. |
51 | | */ |
52 | | int |
53 | | register_writefd(int fd, void (*func) (int, void *), void *data) |
54 | 0 | { |
55 | 0 | if (external_writefdlen < NUM_EXTERNAL_FDS) { |
56 | 0 | external_writefd[external_writefdlen] = fd; |
57 | 0 | external_writefdfunc[external_writefdlen] = func; |
58 | 0 | external_writefd_data[external_writefdlen] = data; |
59 | 0 | external_writefdlen++; |
60 | 0 | DEBUGMSGTL(("fd_event_manager:register_writefd", "registered fd %d\n", fd)); |
61 | 0 | return FD_REGISTERED_OK; |
62 | 0 | } else { |
63 | 0 | snmp_log(LOG_CRIT, |
64 | 0 | "register_writefd: too many file descriptors\n"); |
65 | 0 | return FD_REGISTRATION_FAILED; |
66 | 0 | } |
67 | 0 | } |
68 | | |
69 | | /* |
70 | | * Register a given fd for exception events. Call callback when events |
71 | | * are received. |
72 | | */ |
73 | | int |
74 | | register_exceptfd(int fd, void (*func) (int, void *), void *data) |
75 | 0 | { |
76 | 0 | if (external_exceptfdlen < NUM_EXTERNAL_FDS) { |
77 | 0 | external_exceptfd[external_exceptfdlen] = fd; |
78 | 0 | external_exceptfdfunc[external_exceptfdlen] = func; |
79 | 0 | external_exceptfd_data[external_exceptfdlen] = data; |
80 | 0 | external_exceptfdlen++; |
81 | 0 | DEBUGMSGTL(("fd_event_manager:register_exceptfd", "registered fd %d\n", fd)); |
82 | 0 | return FD_REGISTERED_OK; |
83 | 0 | } else { |
84 | 0 | snmp_log(LOG_CRIT, |
85 | 0 | "register_exceptfd: too many file descriptors\n"); |
86 | 0 | return FD_REGISTRATION_FAILED; |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | | /* |
91 | | * Unregister a given fd for read events. |
92 | | */ |
93 | | int |
94 | | unregister_readfd(int fd) |
95 | 0 | { |
96 | 0 | int i, j; |
97 | |
|
98 | 0 | for (i = 0; i < external_readfdlen; i++) { |
99 | 0 | if (external_readfd[i] == fd) { |
100 | 0 | external_readfdlen--; |
101 | 0 | for (j = i; j < external_readfdlen; j++) { |
102 | 0 | external_readfd[j] = external_readfd[j + 1]; |
103 | 0 | external_readfdfunc[j] = external_readfdfunc[j + 1]; |
104 | 0 | external_readfd_data[j] = external_readfd_data[j + 1]; |
105 | 0 | } |
106 | 0 | DEBUGMSGTL(("fd_event_manager:unregister_readfd", "unregistered fd %d\n", fd)); |
107 | 0 | external_fd_unregistered = 1; |
108 | 0 | return FD_UNREGISTERED_OK; |
109 | 0 | } |
110 | 0 | } |
111 | 0 | return FD_NO_SUCH_REGISTRATION; |
112 | 0 | } |
113 | | |
114 | | /* |
115 | | * Unregister a given fd for read events. |
116 | | */ |
117 | | int |
118 | | unregister_writefd(int fd) |
119 | 0 | { |
120 | 0 | int i, j; |
121 | |
|
122 | 0 | for (i = 0; i < external_writefdlen; i++) { |
123 | 0 | if (external_writefd[i] == fd) { |
124 | 0 | external_writefdlen--; |
125 | 0 | for (j = i; j < external_writefdlen; j++) { |
126 | 0 | external_writefd[j] = external_writefd[j + 1]; |
127 | 0 | external_writefdfunc[j] = external_writefdfunc[j + 1]; |
128 | 0 | external_writefd_data[j] = external_writefd_data[j + 1]; |
129 | 0 | } |
130 | 0 | DEBUGMSGTL(("fd_event_manager:unregister_writefd", "unregistered fd %d\n", fd)); |
131 | 0 | external_fd_unregistered = 1; |
132 | 0 | return FD_UNREGISTERED_OK; |
133 | 0 | } |
134 | 0 | } |
135 | 0 | return FD_NO_SUCH_REGISTRATION; |
136 | 0 | } |
137 | | |
138 | | /* |
139 | | * Unregister a given fd for exception events. |
140 | | */ |
141 | | int |
142 | | unregister_exceptfd(int fd) |
143 | 0 | { |
144 | 0 | int i, j; |
145 | |
|
146 | 0 | for (i = 0; i < external_exceptfdlen; i++) { |
147 | 0 | if (external_exceptfd[i] == fd) { |
148 | 0 | external_exceptfdlen--; |
149 | 0 | for (j = i; j < external_exceptfdlen; j++) { |
150 | 0 | external_exceptfd[j] = external_exceptfd[j + 1]; |
151 | 0 | external_exceptfdfunc[j] = external_exceptfdfunc[j + 1]; |
152 | 0 | external_exceptfd_data[j] = external_exceptfd_data[j + 1]; |
153 | 0 | } |
154 | 0 | DEBUGMSGTL(("fd_event_manager:unregister_exceptfd", "unregistered fd %d\n", |
155 | 0 | fd)); |
156 | 0 | external_fd_unregistered = 1; |
157 | 0 | return FD_UNREGISTERED_OK; |
158 | 0 | } |
159 | 0 | } |
160 | 0 | return FD_NO_SUCH_REGISTRATION; |
161 | 0 | } |
162 | | |
163 | | /* |
164 | | * NET-SNMP External Event Info |
165 | | */ |
166 | | void netsnmp_external_event_info(int *numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) |
167 | 0 | { |
168 | 0 | netsnmp_large_fd_set lreadfds; |
169 | 0 | netsnmp_large_fd_set lwritefds; |
170 | 0 | netsnmp_large_fd_set lexceptfds; |
171 | |
|
172 | 0 | netsnmp_large_fd_set_init(&lreadfds, FD_SETSIZE); |
173 | 0 | netsnmp_large_fd_set_init(&lwritefds, FD_SETSIZE); |
174 | 0 | netsnmp_large_fd_set_init(&lexceptfds, FD_SETSIZE); |
175 | |
|
176 | 0 | netsnmp_copy_fd_set_to_large_fd_set(&lreadfds, readfds); |
177 | 0 | netsnmp_copy_fd_set_to_large_fd_set(&lwritefds, writefds); |
178 | 0 | netsnmp_copy_fd_set_to_large_fd_set(&lexceptfds, exceptfds); |
179 | |
|
180 | 0 | netsnmp_external_event_info2(numfds, &lreadfds, &lwritefds, &lexceptfds); |
181 | |
|
182 | 0 | if (netsnmp_copy_large_fd_set_to_fd_set(readfds, &lreadfds) < 0 |
183 | 0 | || netsnmp_copy_large_fd_set_to_fd_set(writefds, &lwritefds) < 0 |
184 | 0 | || netsnmp_copy_large_fd_set_to_fd_set(exceptfds, &lexceptfds) < 0) |
185 | 0 | { |
186 | 0 | snmp_log(LOG_ERR, |
187 | 0 | "Use netsnmp_external_event_info2() for processing" |
188 | 0 | " large file descriptors\n"); |
189 | 0 | } |
190 | |
|
191 | 0 | netsnmp_large_fd_set_cleanup(&lreadfds); |
192 | 0 | netsnmp_large_fd_set_cleanup(&lwritefds); |
193 | 0 | netsnmp_large_fd_set_cleanup(&lexceptfds); |
194 | 0 | } |
195 | | |
196 | | void netsnmp_external_event_info2(int *numfds, |
197 | | netsnmp_large_fd_set *readfds, |
198 | | netsnmp_large_fd_set *writefds, |
199 | | netsnmp_large_fd_set *exceptfds) |
200 | 0 | { |
201 | 0 | int i; |
202 | |
|
203 | 0 | external_fd_unregistered = 0; |
204 | |
|
205 | 0 | for (i = 0; i < external_readfdlen; i++) { |
206 | 0 | NETSNMP_LARGE_FD_SET(external_readfd[i], readfds); |
207 | 0 | if (external_readfd[i] >= *numfds) |
208 | 0 | *numfds = external_readfd[i] + 1; |
209 | 0 | } |
210 | 0 | for (i = 0; i < external_writefdlen; i++) { |
211 | 0 | NETSNMP_LARGE_FD_SET(external_writefd[i], writefds); |
212 | 0 | if (external_writefd[i] >= *numfds) |
213 | 0 | *numfds = external_writefd[i] + 1; |
214 | 0 | } |
215 | 0 | for (i = 0; i < external_exceptfdlen; i++) { |
216 | 0 | NETSNMP_LARGE_FD_SET(external_exceptfd[i], exceptfds); |
217 | 0 | if (external_exceptfd[i] >= *numfds) |
218 | 0 | *numfds = external_exceptfd[i] + 1; |
219 | 0 | } |
220 | 0 | } |
221 | | |
222 | | /* |
223 | | * NET-SNMP Dispatch External Events |
224 | | */ |
225 | | void netsnmp_dispatch_external_events(int *count, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) |
226 | 0 | { |
227 | 0 | netsnmp_large_fd_set lreadfds; |
228 | 0 | netsnmp_large_fd_set lwritefds; |
229 | 0 | netsnmp_large_fd_set lexceptfds; |
230 | |
|
231 | 0 | netsnmp_large_fd_set_init(&lreadfds, FD_SETSIZE); |
232 | 0 | netsnmp_large_fd_set_init(&lwritefds, FD_SETSIZE); |
233 | 0 | netsnmp_large_fd_set_init(&lexceptfds, FD_SETSIZE); |
234 | |
|
235 | 0 | netsnmp_copy_fd_set_to_large_fd_set(&lreadfds, readfds); |
236 | 0 | netsnmp_copy_fd_set_to_large_fd_set(&lwritefds, writefds); |
237 | 0 | netsnmp_copy_fd_set_to_large_fd_set(&lexceptfds, exceptfds); |
238 | |
|
239 | 0 | netsnmp_dispatch_external_events2(count, &lreadfds, &lwritefds, &lexceptfds); |
240 | |
|
241 | 0 | if (netsnmp_copy_large_fd_set_to_fd_set(readfds, &lreadfds) < 0 |
242 | 0 | || netsnmp_copy_large_fd_set_to_fd_set(writefds, &lwritefds) < 0 |
243 | 0 | || netsnmp_copy_large_fd_set_to_fd_set(exceptfds, &lexceptfds) < 0) |
244 | 0 | { |
245 | 0 | snmp_log(LOG_ERR, |
246 | 0 | "Use netsnmp_dispatch_external_events2() for processing" |
247 | 0 | " large file descriptors\n"); |
248 | 0 | } |
249 | |
|
250 | 0 | netsnmp_large_fd_set_cleanup(&lreadfds); |
251 | 0 | netsnmp_large_fd_set_cleanup(&lwritefds); |
252 | 0 | netsnmp_large_fd_set_cleanup(&lexceptfds); |
253 | 0 | } |
254 | | |
255 | | void netsnmp_dispatch_external_events2(int *count, |
256 | | netsnmp_large_fd_set *readfds, |
257 | | netsnmp_large_fd_set *writefds, |
258 | | netsnmp_large_fd_set *exceptfds) |
259 | 0 | { |
260 | 0 | int i; |
261 | 0 | for (i = 0; |
262 | 0 | *count && (i < external_readfdlen) && !external_fd_unregistered; i++) { |
263 | 0 | if (NETSNMP_LARGE_FD_ISSET(external_readfd[i], readfds)) { |
264 | 0 | DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", |
265 | 0 | "readfd[%d] = %d\n", i, external_readfd[i])); |
266 | 0 | external_readfdfunc[i] (external_readfd[i], |
267 | 0 | external_readfd_data[i]); |
268 | 0 | NETSNMP_LARGE_FD_CLR(external_readfd[i], readfds); |
269 | 0 | (*count)--; |
270 | 0 | } |
271 | 0 | } |
272 | 0 | for (i = 0; |
273 | 0 | *count && (i < external_writefdlen) && !external_fd_unregistered; i++) { |
274 | 0 | if (NETSNMP_LARGE_FD_ISSET(external_writefd[i], writefds)) { |
275 | 0 | DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", |
276 | 0 | "writefd[%d] = %d\n", i, external_writefd[i])); |
277 | 0 | external_writefdfunc[i] (external_writefd[i], |
278 | 0 | external_writefd_data[i]); |
279 | 0 | NETSNMP_LARGE_FD_CLR(external_writefd[i], writefds); |
280 | 0 | (*count)--; |
281 | 0 | } |
282 | 0 | } |
283 | 0 | for (i = 0; |
284 | 0 | *count && (i < external_exceptfdlen) && !external_fd_unregistered; i++) { |
285 | 0 | if (NETSNMP_LARGE_FD_ISSET(external_exceptfd[i], exceptfds)) { |
286 | 0 | DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", |
287 | 0 | "exceptfd[%d] = %d\n", i, external_exceptfd[i])); |
288 | 0 | external_exceptfdfunc[i] (external_exceptfd[i], |
289 | 0 | external_exceptfd_data[i]); |
290 | 0 | NETSNMP_LARGE_FD_CLR(external_exceptfd[i], exceptfds); |
291 | 0 | (*count)--; |
292 | 0 | } |
293 | 0 | } |
294 | 0 | } |
295 | | #else /* !NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ |
296 | | netsnmp_feature_unused(fd_event_manager); |
297 | | #endif /* !NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ |