Coverage Report

Created: 2025-08-11 06:35

/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 */