net-snmp 5.7
|
00001 /* UNIT: File Descriptor (FD) Event Manager */ 00002 #include <net-snmp/net-snmp-config.h> 00003 #ifdef HAVE_SYS_SELECT 00004 #include <sys/select.h> 00005 #endif 00006 #include <net-snmp/net-snmp-includes.h> 00007 #include <net-snmp/net-snmp-features.h> 00008 #include <net-snmp/library/snmp_api.h> 00009 #include <net-snmp/library/fd_event_manager.h> 00010 #include <net-snmp/library/snmp_logging.h> 00011 #include <net-snmp/library/large_fd_set.h> 00012 00013 netsnmp_feature_child_of(fd_event_manager, libnetsnmp) 00014 00015 #ifndef NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER 00016 int external_readfd[NUM_EXTERNAL_FDS], external_readfdlen = 0; 00017 int external_writefd[NUM_EXTERNAL_FDS], external_writefdlen = 0; 00018 int external_exceptfd[NUM_EXTERNAL_FDS], external_exceptfdlen = 0; 00019 void (*external_readfdfunc[NUM_EXTERNAL_FDS]) (int, void *); 00020 void (*external_writefdfunc[NUM_EXTERNAL_FDS]) (int, void *); 00021 void (*external_exceptfdfunc[NUM_EXTERNAL_FDS]) (int, void *); 00022 void *external_readfd_data[NUM_EXTERNAL_FDS]; 00023 void *external_writefd_data[NUM_EXTERNAL_FDS]; 00024 void *external_exceptfd_data[NUM_EXTERNAL_FDS]; 00025 00026 static int external_fd_unregistered; 00027 00028 /* 00029 * Register a given fd for read events. Call callback when events 00030 * are received. 00031 */ 00032 int 00033 register_readfd(int fd, void (*func) (int, void *), void *data) 00034 { 00035 if (external_readfdlen < NUM_EXTERNAL_FDS) { 00036 external_readfd[external_readfdlen] = fd; 00037 external_readfdfunc[external_readfdlen] = func; 00038 external_readfd_data[external_readfdlen] = data; 00039 external_readfdlen++; 00040 DEBUGMSGTL(("fd_event_manager:register_readfd", "registered fd %d\n", fd)); 00041 return FD_REGISTERED_OK; 00042 } else { 00043 snmp_log(LOG_CRIT, "register_readfd: too many file descriptors\n"); 00044 return FD_REGISTRATION_FAILED; 00045 } 00046 } 00047 00048 /* 00049 * Register a given fd for write events. Call callback when events 00050 * are received. 00051 */ 00052 int 00053 register_writefd(int fd, void (*func) (int, void *), void *data) 00054 { 00055 if (external_writefdlen < NUM_EXTERNAL_FDS) { 00056 external_writefd[external_writefdlen] = fd; 00057 external_writefdfunc[external_writefdlen] = func; 00058 external_writefd_data[external_writefdlen] = data; 00059 external_writefdlen++; 00060 DEBUGMSGTL(("fd_event_manager:register_writefd", "registered fd %d\n", fd)); 00061 return FD_REGISTERED_OK; 00062 } else { 00063 snmp_log(LOG_CRIT, 00064 "register_writefd: too many file descriptors\n"); 00065 return FD_REGISTRATION_FAILED; 00066 } 00067 } 00068 00069 /* 00070 * Register a given fd for exception events. Call callback when events 00071 * are received. 00072 */ 00073 int 00074 register_exceptfd(int fd, void (*func) (int, void *), void *data) 00075 { 00076 if (external_exceptfdlen < NUM_EXTERNAL_FDS) { 00077 external_exceptfd[external_exceptfdlen] = fd; 00078 external_exceptfdfunc[external_exceptfdlen] = func; 00079 external_exceptfd_data[external_exceptfdlen] = data; 00080 external_exceptfdlen++; 00081 DEBUGMSGTL(("fd_event_manager:register_exceptfd", "registered fd %d\n", fd)); 00082 return FD_REGISTERED_OK; 00083 } else { 00084 snmp_log(LOG_CRIT, 00085 "register_exceptfd: too many file descriptors\n"); 00086 return FD_REGISTRATION_FAILED; 00087 } 00088 } 00089 00090 /* 00091 * Unregister a given fd for read events. 00092 */ 00093 int 00094 unregister_readfd(int fd) 00095 { 00096 int i, j; 00097 00098 for (i = 0; i < external_readfdlen; i++) { 00099 if (external_readfd[i] == fd) { 00100 external_readfdlen--; 00101 for (j = i; j < external_readfdlen; j++) { 00102 external_readfd[j] = external_readfd[j + 1]; 00103 external_readfdfunc[j] = external_readfdfunc[j + 1]; 00104 external_readfd_data[j] = external_readfd_data[j + 1]; 00105 } 00106 DEBUGMSGTL(("fd_event_manager:unregister_readfd", "unregistered fd %d\n", fd)); 00107 external_fd_unregistered = 1; 00108 return FD_UNREGISTERED_OK; 00109 } 00110 } 00111 return FD_NO_SUCH_REGISTRATION; 00112 } 00113 00114 /* 00115 * Unregister a given fd for read events. 00116 */ 00117 int 00118 unregister_writefd(int fd) 00119 { 00120 int i, j; 00121 00122 for (i = 0; i < external_writefdlen; i++) { 00123 if (external_writefd[i] == fd) { 00124 external_writefdlen--; 00125 for (j = i; j < external_writefdlen; j++) { 00126 external_writefd[j] = external_writefd[j + 1]; 00127 external_writefdfunc[j] = external_writefdfunc[j + 1]; 00128 external_writefd_data[j] = external_writefd_data[j + 1]; 00129 } 00130 DEBUGMSGTL(("fd_event_manager:unregister_writefd", "unregistered fd %d\n", fd)); 00131 external_fd_unregistered = 1; 00132 return FD_UNREGISTERED_OK; 00133 } 00134 } 00135 return FD_NO_SUCH_REGISTRATION; 00136 } 00137 00138 /* 00139 * Unregister a given fd for exception events. 00140 */ 00141 int 00142 unregister_exceptfd(int fd) 00143 { 00144 int i, j; 00145 00146 for (i = 0; i < external_exceptfdlen; i++) { 00147 if (external_exceptfd[i] == fd) { 00148 external_exceptfdlen--; 00149 for (j = i; j < external_exceptfdlen; j++) { 00150 external_exceptfd[j] = external_exceptfd[j + 1]; 00151 external_exceptfdfunc[j] = external_exceptfdfunc[j + 1]; 00152 external_exceptfd_data[j] = external_exceptfd_data[j + 1]; 00153 } 00154 DEBUGMSGTL(("fd_event_manager:unregister_exceptfd", "unregistered fd %d\n", 00155 fd)); 00156 external_fd_unregistered = 1; 00157 return FD_UNREGISTERED_OK; 00158 } 00159 } 00160 return FD_NO_SUCH_REGISTRATION; 00161 } 00162 00163 /* 00164 * NET-SNMP External Event Info 00165 */ 00166 void netsnmp_external_event_info(int *numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) 00167 { 00168 netsnmp_large_fd_set lreadfds; 00169 netsnmp_large_fd_set lwritefds; 00170 netsnmp_large_fd_set lexceptfds; 00171 00172 netsnmp_large_fd_set_init(&lreadfds, FD_SETSIZE); 00173 netsnmp_large_fd_set_init(&lwritefds, FD_SETSIZE); 00174 netsnmp_large_fd_set_init(&lexceptfds, FD_SETSIZE); 00175 00176 netsnmp_copy_fd_set_to_large_fd_set(&lreadfds, readfds); 00177 netsnmp_copy_fd_set_to_large_fd_set(&lwritefds, writefds); 00178 netsnmp_copy_fd_set_to_large_fd_set(&lexceptfds, exceptfds); 00179 00180 netsnmp_external_event_info2(numfds, &lreadfds, &lwritefds, &lexceptfds); 00181 00182 if (netsnmp_copy_large_fd_set_to_fd_set(readfds, &lreadfds) < 0 00183 || netsnmp_copy_large_fd_set_to_fd_set(writefds, &lwritefds) < 0 00184 || netsnmp_copy_large_fd_set_to_fd_set(exceptfds, &lexceptfds) < 0) 00185 { 00186 snmp_log(LOG_ERR, 00187 "Use netsnmp_external_event_info2() for processing" 00188 " large file descriptors\n"); 00189 } 00190 00191 netsnmp_large_fd_set_cleanup(&lreadfds); 00192 netsnmp_large_fd_set_cleanup(&lwritefds); 00193 netsnmp_large_fd_set_cleanup(&lexceptfds); 00194 } 00195 00196 void netsnmp_external_event_info2(int *numfds, 00197 netsnmp_large_fd_set *readfds, 00198 netsnmp_large_fd_set *writefds, 00199 netsnmp_large_fd_set *exceptfds) 00200 { 00201 int i; 00202 00203 external_fd_unregistered = 0; 00204 00205 for (i = 0; i < external_readfdlen; i++) { 00206 NETSNMP_LARGE_FD_SET(external_readfd[i], readfds); 00207 if (external_readfd[i] >= *numfds) 00208 *numfds = external_readfd[i] + 1; 00209 } 00210 for (i = 0; i < external_writefdlen; i++) { 00211 NETSNMP_LARGE_FD_SET(external_writefd[i], writefds); 00212 if (external_writefd[i] >= *numfds) 00213 *numfds = external_writefd[i] + 1; 00214 } 00215 for (i = 0; i < external_exceptfdlen; i++) { 00216 NETSNMP_LARGE_FD_SET(external_exceptfd[i], exceptfds); 00217 if (external_exceptfd[i] >= *numfds) 00218 *numfds = external_exceptfd[i] + 1; 00219 } 00220 } 00221 00222 /* 00223 * NET-SNMP Dispatch External Events 00224 */ 00225 void netsnmp_dispatch_external_events(int *count, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) 00226 { 00227 netsnmp_large_fd_set lreadfds; 00228 netsnmp_large_fd_set lwritefds; 00229 netsnmp_large_fd_set lexceptfds; 00230 00231 netsnmp_large_fd_set_init(&lreadfds, FD_SETSIZE); 00232 netsnmp_large_fd_set_init(&lwritefds, FD_SETSIZE); 00233 netsnmp_large_fd_set_init(&lexceptfds, FD_SETSIZE); 00234 00235 netsnmp_copy_fd_set_to_large_fd_set(&lreadfds, readfds); 00236 netsnmp_copy_fd_set_to_large_fd_set(&lwritefds, writefds); 00237 netsnmp_copy_fd_set_to_large_fd_set(&lexceptfds, exceptfds); 00238 00239 netsnmp_dispatch_external_events2(count, &lreadfds, &lwritefds, &lexceptfds); 00240 00241 if (netsnmp_copy_large_fd_set_to_fd_set(readfds, &lreadfds) < 0 00242 || netsnmp_copy_large_fd_set_to_fd_set(writefds, &lwritefds) < 0 00243 || netsnmp_copy_large_fd_set_to_fd_set(exceptfds, &lexceptfds) < 0) 00244 { 00245 snmp_log(LOG_ERR, 00246 "Use netsnmp_dispatch_external_events2() for processing" 00247 " large file descriptors\n"); 00248 } 00249 00250 netsnmp_large_fd_set_cleanup(&lreadfds); 00251 netsnmp_large_fd_set_cleanup(&lwritefds); 00252 netsnmp_large_fd_set_cleanup(&lexceptfds); 00253 } 00254 00255 void netsnmp_dispatch_external_events2(int *count, 00256 netsnmp_large_fd_set *readfds, 00257 netsnmp_large_fd_set *writefds, 00258 netsnmp_large_fd_set *exceptfds) 00259 { 00260 int i; 00261 for (i = 0; 00262 *count && (i < external_readfdlen) && !external_fd_unregistered; i++) { 00263 if (NETSNMP_LARGE_FD_ISSET(external_readfd[i], readfds)) { 00264 DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", 00265 "readfd[%d] = %d\n", i, external_readfd[i])); 00266 external_readfdfunc[i] (external_readfd[i], 00267 external_readfd_data[i]); 00268 NETSNMP_LARGE_FD_CLR(external_readfd[i], readfds); 00269 (*count)--; 00270 } 00271 } 00272 for (i = 0; 00273 *count && (i < external_writefdlen) && !external_fd_unregistered; i++) { 00274 if (NETSNMP_LARGE_FD_ISSET(external_writefd[i], writefds)) { 00275 DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", 00276 "writefd[%d] = %d\n", i, external_writefd[i])); 00277 external_writefdfunc[i] (external_writefd[i], 00278 external_writefd_data[i]); 00279 NETSNMP_LARGE_FD_CLR(external_writefd[i], writefds); 00280 (*count)--; 00281 } 00282 } 00283 for (i = 0; 00284 *count && (i < external_exceptfdlen) && !external_fd_unregistered; i++) { 00285 if (NETSNMP_LARGE_FD_ISSET(external_exceptfd[i], exceptfds)) { 00286 DEBUGMSGTL(("fd_event_manager:netsnmp_dispatch_external_events", 00287 "exceptfd[%d] = %d\n", i, external_exceptfd[i])); 00288 external_exceptfdfunc[i] (external_exceptfd[i], 00289 external_exceptfd_data[i]); 00290 NETSNMP_LARGE_FD_CLR(external_exceptfd[i], exceptfds); 00291 (*count)--; 00292 } 00293 } 00294 } 00295 #else /* !NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */ 00296 netsnmp_feature_unused(fd_event_manager); 00297 #endif /* !NETSNMP_FEATURE_REMOVE_FD_EVENT_MANAGER */