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