Coverage Report

Created: 2025-08-11 06:35

/src/net-snmp/snmplib/snmp_service.c
Line
Count
Source (jump to first uncovered line)
1
#include <net-snmp/net-snmp-config.h>
2
3
#include <stdlib.h>
4
#include <string.h>
5
6
#include <net-snmp/net-snmp-includes.h>
7
#include <net-snmp/library/snmp_transport.h>
8
9
static char**
10
create_word_array_helper(const char* cptr, size_t idx, char* tmp, size_t tmplen)
11
20.2k
{
12
20.2k
    char* item;
13
20.2k
    char** res;
14
20.2k
    cptr = copy_nword_const(cptr, tmp, tmplen);
15
20.2k
    item = strdup(tmp);
16
20.2k
    if (cptr)
17
10.3k
        res = create_word_array_helper(cptr, idx + 1, tmp, tmplen);
18
9.89k
    else {
19
9.89k
        res = (char**)malloc(sizeof(char*) * (idx + 2));
20
9.89k
        res[idx + 1] = NULL;
21
9.89k
    }
22
20.2k
    res[idx] = item;
23
20.2k
    return res;
24
20.2k
}
25
26
static char**
27
create_word_array(const char* cptr)
28
9.89k
{
29
9.89k
    size_t tmplen = strlen(cptr);
30
9.89k
    char* tmp = (char*)malloc(tmplen + 1);
31
9.89k
    char** res = create_word_array_helper(cptr, 0, tmp, tmplen + 1);
32
9.89k
    free(tmp);
33
9.89k
    return res;
34
9.89k
}
35
36
static void
37
destroy_word_array(char** arr)
38
19.3k
{
39
19.3k
    if (arr) {
40
9.73k
        char** run = arr;
41
29.6k
        while(*run) {
42
19.8k
            free(*run);
43
19.8k
            ++run;
44
19.8k
        }
45
9.73k
        free(arr);
46
9.73k
    }
47
19.3k
}
48
49
struct netsnmp_lookup_domain {
50
    char* application;
51
    char** userDomain;
52
    char** domain;
53
    struct netsnmp_lookup_domain* next;
54
};
55
56
static struct netsnmp_lookup_domain* domains = NULL;
57
58
int
59
netsnmp_register_default_domain(const char* application, const char* domain)
60
9.60k
{
61
9.60k
    struct netsnmp_lookup_domain *run = domains, *prev = NULL;
62
9.60k
    int res = 0;
63
64
12.8k
    while (run != NULL && strcmp(run->application, application) < 0) {
65
3.20k
  prev = run;
66
3.20k
  run = run->next;
67
3.20k
    }
68
9.60k
    if (run && strcmp(run->application, application) == 0) {
69
0
      if (run->domain != NULL) {
70
0
          destroy_word_array(run->domain);
71
0
    run->domain = NULL;
72
0
    res = 1;
73
0
      }
74
9.60k
    } else {
75
9.60k
  run = SNMP_MALLOC_STRUCT(netsnmp_lookup_domain);
76
9.60k
  run->application = strdup(application);
77
9.60k
  run->userDomain = NULL;
78
9.60k
  if (prev) {
79
3.20k
      run->next = prev->next;
80
3.20k
      prev->next = run;
81
6.40k
  } else {
82
6.40k
      run->next = domains;
83
6.40k
      domains = run;
84
6.40k
  }
85
9.60k
    }
86
9.60k
    if (domain) {
87
9.60k
        run->domain = create_word_array(domain);
88
9.60k
    } else if (run->userDomain == NULL) {
89
0
  if (prev)
90
0
      prev->next = run->next;
91
0
  else
92
0
      domains = run->next;
93
0
  free(run->application);
94
0
  free(run);
95
0
    }
96
9.60k
    return res;
97
9.60k
}
98
99
void
100
netsnmp_clear_default_domain(void)
101
3.20k
{
102
12.8k
    while (domains) {
103
9.60k
  struct netsnmp_lookup_domain *tmp = domains;
104
9.60k
  domains = domains->next;
105
9.60k
  free(tmp->application);
106
9.60k
        destroy_word_array(tmp->userDomain);
107
9.60k
        destroy_word_array(tmp->domain);
108
9.60k
  free(tmp);
109
9.60k
    }
110
3.20k
}
111
112
static void
113
netsnmp_register_user_domain(const char* token, char* cptr)
114
323
{
115
323
    struct netsnmp_lookup_domain *run = domains, *prev = NULL;
116
323
    size_t len = strlen(cptr) + 1;
117
323
    char* application = (char*)malloc(len);
118
323
    char** domain;
119
120
323
    {
121
323
        char* cp = copy_nword(cptr, application, len);
122
323
        if (cp == NULL) {
123
35
            netsnmp_config_error("No domain(s) in registration of "
124
35
                                 "defDomain \"%s\"", application);
125
35
            free(application);
126
35
            return;
127
35
        }
128
288
        domain = create_word_array(cp);
129
288
    }
130
131
16.8k
    while (run != NULL && strcmp(run->application, application) < 0) {
132
16.5k
  prev = run;
133
16.5k
  run = run->next;
134
16.5k
    }
135
288
    if (run && strcmp(run->application, application) == 0) {
136
134
  if (run->userDomain != NULL) {
137
133
      config_perror("Default transport already registered for this "
138
133
        "application");
139
133
            destroy_word_array(domain);
140
133
            free(application);
141
133
      return;
142
133
  }
143
154
    } else {
144
154
  run = SNMP_MALLOC_STRUCT(netsnmp_lookup_domain);
145
154
  run->application = strdup(application);
146
154
  run->domain = NULL;
147
154
  if (prev) {
148
150
      run->next = prev->next;
149
150
      prev->next = run;
150
150
  } else {
151
4
      run->next = domains;
152
4
      domains = run;
153
4
  }
154
154
    }
155
155
    run->userDomain = domain;
156
155
    free(application);
157
155
}
158
159
static void
160
netsnmp_clear_user_domain(void)
161
12.8k
{
162
12.8k
    struct netsnmp_lookup_domain *run = domains, *prev = NULL;
163
164
51.2k
    while (run) {
165
38.4k
  if (run->userDomain != NULL) {
166
0
            destroy_word_array(run->userDomain);
167
0
      run->userDomain = NULL;
168
0
  }
169
38.4k
  if (run->domain == NULL) {
170
0
      struct netsnmp_lookup_domain *tmp = run;
171
0
      if (prev)
172
0
    run = prev->next = run->next;
173
0
      else
174
0
    run = domains = run->next;
175
0
      free(tmp->application);
176
0
      free(tmp);
177
38.4k
  } else {
178
38.4k
      prev = run;
179
38.4k
      run = run->next;
180
38.4k
  }
181
38.4k
    }
182
12.8k
}
183
184
const char* const *
185
netsnmp_lookup_default_domains(const char* application)
186
3.20k
{
187
3.20k
    const char * const * res;
188
189
3.20k
    if (application == NULL)
190
0
  res = NULL;
191
3.20k
    else {
192
3.20k
        struct netsnmp_lookup_domain *run = domains;
193
194
6.40k
  while (run && strcmp(run->application, application) < 0)
195
3.20k
      run = run->next;
196
3.20k
  if (run && strcmp(run->application, application) == 0)
197
3.20k
      if (run->userDomain)
198
0
                res = (const char * const *)run->userDomain;
199
3.20k
      else
200
3.20k
                res = (const char * const *)run->domain;
201
0
  else
202
0
      res = NULL;
203
3.20k
    }
204
3.20k
    DEBUGMSGTL(("defaults",
205
3.20k
                "netsnmp_lookup_default_domain(\"%s\") ->",
206
3.20k
                application ? application : "[NIL]"));
207
3.20k
    if (res) {
208
3.20k
        const char * const * r = res;
209
9.60k
        while(*r) {
210
6.40k
            DEBUGMSG(("defaults", " \"%s\"", *r));
211
6.40k
            ++r;
212
6.40k
        }
213
3.20k
        DEBUGMSG(("defaults", "\n"));
214
3.20k
    } else
215
0
        DEBUGMSG(("defaults", " \"[NIL]\"\n"));
216
3.20k
    return res;
217
3.20k
}
218
219
const char*
220
netsnmp_lookup_default_domain(const char* application)
221
0
{
222
0
    const char * const * res = netsnmp_lookup_default_domains(application);
223
0
    return (res ? *res : NULL);
224
0
}
225
226
struct netsnmp_lookup_target {
227
    char* application;
228
    char* domain;
229
    char* userTarget;
230
    char* target;
231
    struct netsnmp_lookup_target* next;
232
};
233
234
static struct netsnmp_lookup_target* targets = NULL;
235
236
/**
237
 * Add an (application, domain, target) triplet to the targets list if target
238
 * != NULL. Remove an entry if target == NULL and the userTarget pointer for
239
 * the entry found is also NULL. Keep at most one target per (application,
240
 * domain) pair.
241
 *
242
 * @return 1 if an entry for (application, domain) was already present in the
243
 *   targets list or 0 if such an entry was not yet present in the targets list.
244
 */
245
int
246
netsnmp_register_default_target(const char* application, const char* domain,
247
        const char* target)
248
51.2k
{
249
51.2k
    struct netsnmp_lookup_target *run = targets, *prev = NULL;
250
51.2k
    int i = 0, res = 0;
251
253k
    while (run && ((i = strcmp(run->application, application)) < 0 ||
252
240k
       (i == 0 && strcmp(run->domain, domain) < 0))) {
253
201k
  prev = run;
254
201k
  run = run->next;
255
201k
    }
256
51.2k
    if (run && i == 0 && strcmp(run->domain, domain) == 0) {
257
0
      if (run->target != NULL) {
258
0
      free(run->target);
259
0
      run->target = NULL;
260
0
      res = 1;
261
0
      }
262
51.2k
    } else {
263
51.2k
  run = SNMP_MALLOC_STRUCT(netsnmp_lookup_target);
264
51.2k
  run->application = strdup(application);
265
51.2k
  run->domain = strdup(domain);
266
51.2k
  run->userTarget = NULL;
267
51.2k
  if (prev) {
268
35.2k
      run->next = prev->next;
269
35.2k
      prev->next = run;
270
35.2k
  } else {
271
16.0k
      run->next = targets;
272
16.0k
      targets = run;
273
16.0k
  }
274
51.2k
    }
275
51.2k
    if (target) {
276
51.2k
  run->target = strdup(target);
277
51.2k
    } else if (run->userTarget == NULL) {
278
0
  if (prev)
279
0
      prev->next = run->next;
280
0
  else
281
0
      targets = run->next;
282
0
  free(run->domain);
283
0
  free(run->application);
284
0
  free(run);
285
0
    }
286
51.2k
    return res;
287
51.2k
}
288
289
/**
290
 * Clear the targets list.
291
 */
292
void
293
netsnmp_clear_default_target(void)
294
3.20k
{
295
54.4k
    while (targets) {
296
51.2k
  struct netsnmp_lookup_target *tmp = targets;
297
51.2k
  targets = targets->next;
298
51.2k
  free(tmp->application);
299
51.2k
  free(tmp->domain);
300
51.2k
  free(tmp->userTarget);
301
51.2k
  free(tmp->target);
302
51.2k
  free(tmp);
303
51.2k
    }
304
3.20k
}
305
306
static void
307
netsnmp_register_user_target(const char* token, char* cptr)
308
705
{
309
705
    struct netsnmp_lookup_target *run = targets, *prev = NULL;
310
705
    size_t len = strlen(cptr) + 1;
311
705
    char* application = (char*)malloc(len);
312
705
    char* domain = (char*)malloc(len);
313
705
    char* target = (char*)malloc(len);
314
705
    int i = 0;
315
316
705
    if (application == NULL || domain == NULL || target == NULL) {
317
0
        goto done;
318
0
    }
319
705
    {
320
705
  char* cp = copy_nword(cptr, application, len);
321
705
        if (cp == NULL) {
322
46
            netsnmp_config_error("No domain and target in registration of "
323
46
                                 "defTarget \"%s\"", application);
324
46
            goto done;
325
46
        }
326
659
  cp = copy_nword(cp, domain, len);
327
659
        if (cp == NULL) {
328
80
            netsnmp_config_error("No target in registration of "
329
80
                                 "defTarget \"%s\" \"%s\"",
330
80
                                 application, domain);
331
80
            goto done;
332
80
        }
333
579
  cp = copy_nword(cp, target, len);
334
579
  if (cp)
335
176
      config_pwarn("Trailing junk found");
336
579
    }
337
338
38.6k
    while (run && ((i = strcmp(run->application, application)) < 0 ||
339
38.6k
       (i == 0 && strcmp(run->domain, domain) < 0))) {
340
38.0k
  prev = run;
341
38.0k
  run = run->next;
342
38.0k
    }
343
579
    if (run && i == 0 && strcmp(run->domain, domain) == 0) {
344
183
  if (run->userTarget != NULL) {
345
183
      config_perror("Default target already registered for this "
346
183
        "application-domain combination");
347
183
      goto done;
348
183
  }
349
396
    } else {
350
396
  run = SNMP_MALLOC_STRUCT(netsnmp_lookup_target);
351
396
  run->application = strdup(application);
352
396
  run->domain = strdup(domain);
353
396
  run->target = NULL;
354
396
  if (prev) {
355
384
      run->next = prev->next;
356
384
      prev->next = run;
357
384
  } else {
358
12
      run->next = targets;
359
12
      targets = run;
360
12
  }
361
396
    }
362
396
    run->userTarget = strdup(target);
363
705
 done:
364
705
    free(target);
365
705
    free(domain);
366
705
    free(application);
367
705
}
368
369
static void
370
netsnmp_clear_user_target(void)
371
12.8k
{
372
12.8k
    struct netsnmp_lookup_target *run = targets, *prev = NULL;
373
374
217k
    while (run) {
375
204k
  if (run->userTarget != NULL) {
376
0
      free(run->userTarget);
377
0
      run->userTarget = NULL;
378
0
  }
379
204k
  if (run->target == NULL) {
380
0
      struct netsnmp_lookup_target *tmp = run;
381
0
      if (prev)
382
0
    run = prev->next = run->next;
383
0
      else
384
0
    run = targets = run->next;
385
0
      free(tmp->application);
386
0
      free(tmp->domain);
387
0
      free(tmp);
388
204k
  } else {
389
204k
      prev = run;
390
204k
      run = run->next;
391
204k
  }
392
204k
    }
393
12.8k
}
394
395
const char*
396
netsnmp_lookup_default_target(const char* application, const char* domain)
397
3.20k
{
398
3.20k
    int i = 0;
399
3.20k
    struct netsnmp_lookup_target *run = targets;
400
3.20k
    const char *res;
401
402
3.20k
    if (application == NULL || domain == NULL)
403
0
  res = NULL;
404
3.20k
    else {
405
25.6k
  while (run && ((i = strcmp(run->application, application)) < 0 ||
406
25.6k
           (i == 0 && strcmp(run->domain, domain) < 0)))
407
22.4k
      run = run->next;
408
3.20k
  if (run && i == 0 && strcmp(run->domain, domain) == 0)
409
3.20k
      if (run->userTarget != NULL)
410
0
    res = run->userTarget;
411
3.20k
      else
412
3.20k
    res = run->target;
413
0
  else
414
0
      res = NULL;
415
3.20k
    }
416
3.20k
    DEBUGMSGTL(("defaults",
417
3.20k
    "netsnmp_lookup_default_target(\"%s\", \"%s\") -> \"%s\"\n",
418
3.20k
    application ? application : "[NIL]",
419
3.20k
    domain ? domain : "[NIL]",
420
3.20k
    res ? res : "[NIL]"));
421
3.20k
    return res;
422
3.20k
}
423
424
void
425
netsnmp_register_service_handlers(void)
426
3.20k
{
427
3.20k
    register_config_handler("snmp:", "defDomain",
428
3.20k
          netsnmp_register_user_domain,
429
3.20k
          netsnmp_clear_user_domain,
430
3.20k
          "application domain");
431
3.20k
    register_config_handler("snmp:", "defTarget",
432
3.20k
          netsnmp_register_user_target,
433
3.20k
          netsnmp_clear_user_target,
434
3.20k
          "application domain target");
435
3.20k
}