Coverage Report

Created: 2026-05-23 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/net-snmp/snmplib/snmp_service.c
Line
Count
Source
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
22.3k
{
12
22.3k
    char* item;
13
22.3k
    char** res;
14
22.3k
    cptr = copy_nword_const(cptr, tmp, tmplen);
15
22.3k
    item = strdup(tmp);
16
22.3k
    if (cptr)
17
11.4k
        res = create_word_array_helper(cptr, idx + 1, tmp, tmplen);
18
10.9k
    else {
19
10.9k
        res = (char**)malloc(sizeof(char*) * (idx + 2));
20
10.9k
        res[idx + 1] = NULL;
21
10.9k
    }
22
22.3k
    res[idx] = item;
23
22.3k
    return res;
24
22.3k
}
25
26
static char**
27
create_word_array(const char* cptr)
28
10.9k
{
29
10.9k
    size_t tmplen = strlen(cptr);
30
10.9k
    char* tmp = (char*)malloc(tmplen + 1);
31
10.9k
    char** res = create_word_array_helper(cptr, 0, tmp, tmplen + 1);
32
10.9k
    free(tmp);
33
10.9k
    return res;
34
10.9k
}
35
36
static void
37
destroy_word_array(char** arr)
38
21.2k
{
39
21.2k
    if (arr) {
40
10.6k
        char** run = arr;
41
32.5k
        while(*run) {
42
21.8k
            free(*run);
43
21.8k
            ++run;
44
21.8k
        }
45
10.6k
        free(arr);
46
10.6k
    }
47
21.2k
}
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
10.5k
{
61
10.5k
    struct netsnmp_lookup_domain *run = domains, *prev = NULL;
62
10.5k
    int res = 0;
63
64
14.1k
    while (run != NULL && strcmp(run->application, application) < 0) {
65
3.55k
  prev = run;
66
3.55k
  run = run->next;
67
3.55k
    }
68
10.5k
    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
10.5k
    } else {
75
10.5k
  run = SNMP_MALLOC_STRUCT(netsnmp_lookup_domain);
76
10.5k
  run->application = strdup(application);
77
10.5k
  run->userDomain = NULL;
78
10.5k
  if (prev) {
79
3.55k
      run->next = prev->next;
80
3.55k
      prev->next = run;
81
7.04k
  } else {
82
7.04k
      run->next = domains;
83
7.04k
      domains = run;
84
7.04k
  }
85
10.5k
    }
86
10.5k
    if (domain) {
87
10.5k
        run->domain = create_word_array(domain);
88
10.5k
    } 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
10.5k
    return res;
97
10.5k
}
98
99
void
100
netsnmp_clear_default_domain(void)
101
3.55k
{
102
14.1k
    while (domains) {
103
10.5k
  struct netsnmp_lookup_domain *tmp = domains;
104
10.5k
  domains = domains->next;
105
10.5k
  free(tmp->application);
106
10.5k
        destroy_word_array(tmp->userDomain);
107
10.5k
        destroy_word_array(tmp->domain);
108
10.5k
  free(tmp);
109
10.5k
    }
110
3.55k
}
111
112
static void
113
netsnmp_register_user_domain(const char* token, char* cptr)
114
383
{
115
383
    struct netsnmp_lookup_domain *run = domains, *prev = NULL;
116
383
    size_t len = strlen(cptr) + 1;
117
383
    char* application = (char*)malloc(len);
118
383
    char** domain;
119
120
383
    {
121
383
        char* cp = copy_nword(cptr, application, len);
122
383
        if (cp == NULL) {
123
37
            netsnmp_config_error("No domain(s) in registration of "
124
37
                                 "defDomain \"%s\"", application);
125
37
            free(application);
126
37
            return;
127
37
        }
128
346
        domain = create_word_array(cp);
129
346
    }
130
131
21.5k
    while (run != NULL && strcmp(run->application, application) < 0) {
132
21.2k
  prev = run;
133
21.2k
  run = run->next;
134
21.2k
    }
135
346
    if (run && strcmp(run->application, application) == 0) {
136
99
  if (run->userDomain != NULL) {
137
98
      config_perror("Default transport already registered for this "
138
98
        "application");
139
98
            destroy_word_array(domain);
140
98
            free(application);
141
98
      return;
142
98
  }
143
247
    } else {
144
247
  run = SNMP_MALLOC_STRUCT(netsnmp_lookup_domain);
145
247
  run->application = strdup(application);
146
247
  run->domain = NULL;
147
247
  if (prev) {
148
246
      run->next = prev->next;
149
246
      prev->next = run;
150
246
  } else {
151
1
      run->next = domains;
152
1
      domains = run;
153
1
  }
154
247
    }
155
248
    run->userDomain = domain;
156
248
    free(application);
157
248
}
158
159
static void
160
netsnmp_clear_user_domain(void)
161
14.2k
{
162
14.2k
    struct netsnmp_lookup_domain *run = domains, *prev = NULL;
163
164
56.5k
    while (run) {
165
42.3k
  if (run->userDomain != NULL) {
166
0
            destroy_word_array(run->userDomain);
167
0
      run->userDomain = NULL;
168
0
  }
169
42.3k
  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
42.3k
  } else {
178
42.3k
      prev = run;
179
42.3k
      run = run->next;
180
42.3k
  }
181
42.3k
    }
182
14.2k
}
183
184
const char* const *
185
netsnmp_lookup_default_domains(const char* application)
186
3.55k
{
187
3.55k
    const char * const * res;
188
189
3.55k
    if (application == NULL)
190
0
  res = NULL;
191
3.55k
    else {
192
3.55k
        struct netsnmp_lookup_domain *run = domains;
193
194
7.17k
  while (run && strcmp(run->application, application) < 0)
195
3.61k
      run = run->next;
196
3.55k
  if (run && strcmp(run->application, application) == 0)
197
3.48k
      if (run->userDomain)
198
0
                res = (const char * const *)run->userDomain;
199
3.48k
      else
200
3.48k
                res = (const char * const *)run->domain;
201
66
  else
202
66
      res = NULL;
203
3.55k
    }
204
3.55k
    DEBUGMSGTL(("defaults",
205
3.55k
                "netsnmp_lookup_default_domain(\"%s\") ->",
206
3.55k
                application ? application : "[NIL]"));
207
3.55k
    if (res) {
208
3.48k
        const char * const * r = res;
209
10.4k
        while(*r) {
210
6.97k
            DEBUGMSG(("defaults", " \"%s\"", *r));
211
6.97k
            ++r;
212
6.97k
        }
213
3.48k
        DEBUGMSG(("defaults", "\n"));
214
3.48k
    } else
215
66
        DEBUGMSG(("defaults", " \"[NIL]\"\n"));
216
3.55k
    return res;
217
3.55k
}
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
56.7k
{
249
56.7k
    struct netsnmp_lookup_target *run = targets, *prev = NULL;
250
56.7k
    int i = 0, res = 0;
251
280k
    while (run && ((i = strcmp(run->application, application)) < 0 ||
252
223k
       (i == 0 && strcmp(run->domain, domain) < 0))) {
253
223k
  prev = run;
254
223k
  run = run->next;
255
223k
    }
256
56.7k
    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
56.7k
    } else {
263
56.7k
  run = SNMP_MALLOC_STRUCT(netsnmp_lookup_target);
264
56.7k
  run->application = strdup(application);
265
56.7k
  run->domain = strdup(domain);
266
56.7k
  run->userTarget = NULL;
267
56.7k
  if (prev) {
268
39.0k
      run->next = prev->next;
269
39.0k
      prev->next = run;
270
39.0k
  } else {
271
17.6k
      run->next = targets;
272
17.6k
      targets = run;
273
17.6k
  }
274
56.7k
    }
275
56.7k
    if (target) {
276
56.7k
  run->target = strdup(target);
277
56.7k
    } 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
56.7k
    return res;
287
56.7k
}
288
289
/**
290
 * Clear the targets list.
291
 */
292
void
293
netsnmp_clear_default_target(void)
294
3.55k
{
295
60.2k
    while (targets) {
296
56.7k
  struct netsnmp_lookup_target *tmp = targets;
297
56.7k
  targets = targets->next;
298
56.7k
  free(tmp->application);
299
56.7k
  free(tmp->domain);
300
56.7k
  free(tmp->userTarget);
301
56.7k
  free(tmp->target);
302
56.7k
  free(tmp);
303
56.7k
    }
304
3.55k
}
305
306
static void
307
netsnmp_register_user_target(const char* token, char* cptr)
308
863
{
309
863
    struct netsnmp_lookup_target *run = targets, *prev = NULL;
310
863
    size_t len = strlen(cptr) + 1;
311
863
    char* application = (char*)malloc(len);
312
863
    char* domain = (char*)malloc(len);
313
863
    char* target = (char*)malloc(len);
314
863
    int i = 0;
315
316
863
    if (application == NULL || domain == NULL || target == NULL) {
317
0
        goto done;
318
0
    }
319
863
    {
320
863
  char* cp = copy_nword(cptr, application, len);
321
863
        if (cp == NULL) {
322
24
            netsnmp_config_error("No domain and target in registration of "
323
24
                                 "defTarget \"%s\"", application);
324
24
            goto done;
325
24
        }
326
839
  cp = copy_nword(cp, domain, len);
327
839
        if (cp == NULL) {
328
89
            netsnmp_config_error("No target in registration of "
329
89
                                 "defTarget \"%s\" \"%s\"",
330
89
                                 application, domain);
331
89
            goto done;
332
89
        }
333
750
  cp = copy_nword(cp, target, len);
334
750
  if (cp)
335
182
      config_pwarn("Trailing junk found");
336
750
    }
337
338
64.0k
    while (run && ((i = strcmp(run->application, application)) < 0 ||
339
63.3k
       (i == 0 && strcmp(run->domain, domain) < 0))) {
340
63.3k
  prev = run;
341
63.3k
  run = run->next;
342
63.3k
    }
343
750
    if (run && i == 0 && strcmp(run->domain, domain) == 0) {
344
277
  if (run->userTarget != NULL) {
345
277
      config_perror("Default target already registered for this "
346
277
        "application-domain combination");
347
277
      goto done;
348
277
  }
349
473
    } else {
350
473
  run = SNMP_MALLOC_STRUCT(netsnmp_lookup_target);
351
473
  run->application = strdup(application);
352
473
  run->domain = strdup(domain);
353
473
  run->target = NULL;
354
473
  if (prev) {
355
470
      run->next = prev->next;
356
470
      prev->next = run;
357
470
  } else {
358
3
      run->next = targets;
359
3
      targets = run;
360
3
  }
361
473
    }
362
473
    run->userTarget = strdup(target);
363
863
 done:
364
863
    free(target);
365
863
    free(domain);
366
863
    free(application);
367
863
}
368
369
static void
370
netsnmp_clear_user_target(void)
371
14.2k
{
372
14.2k
    struct netsnmp_lookup_target *run = targets, *prev = NULL;
373
374
241k
    while (run) {
375
226k
  if (run->userTarget != NULL) {
376
0
      free(run->userTarget);
377
0
      run->userTarget = NULL;
378
0
  }
379
226k
  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
226k
  } else {
389
226k
      prev = run;
390
226k
      run = run->next;
391
226k
  }
392
226k
    }
393
14.2k
}
394
395
const char*
396
netsnmp_lookup_default_target(const char* application, const char* domain)
397
3.55k
{
398
3.55k
    int i = 0;
399
3.55k
    struct netsnmp_lookup_target *run = targets;
400
3.55k
    const char *res;
401
402
3.55k
    if (application == NULL || domain == NULL)
403
0
  res = NULL;
404
3.55k
    else {
405
28.8k
  while (run && ((i = strcmp(run->application, application)) < 0 ||
406
20.9k
           (i == 0 && strcmp(run->domain, domain) < 0)))
407
25.3k
      run = run->next;
408
3.55k
  if (run && i == 0 && strcmp(run->domain, domain) == 0)
409
3.48k
      if (run->userTarget != NULL)
410
0
    res = run->userTarget;
411
3.48k
      else
412
3.48k
    res = run->target;
413
66
  else
414
66
      res = NULL;
415
3.55k
    }
416
3.55k
    DEBUGMSGTL(("defaults",
417
3.55k
    "netsnmp_lookup_default_target(\"%s\", \"%s\") -> \"%s\"\n",
418
3.55k
    application ? application : "[NIL]",
419
3.55k
    domain ? domain : "[NIL]",
420
3.55k
    res ? res : "[NIL]"));
421
3.55k
    return res;
422
3.55k
}
423
424
void
425
netsnmp_register_service_handlers(void)
426
3.55k
{
427
3.55k
    register_config_handler("snmp:", "defDomain",
428
3.55k
          netsnmp_register_user_domain,
429
3.55k
          netsnmp_clear_user_domain,
430
3.55k
          "application domain");
431
3.55k
    register_config_handler("snmp:", "defTarget",
432
3.55k
          netsnmp_register_user_target,
433
3.55k
          netsnmp_clear_user_target,
434
3.55k
          "application domain target");
435
3.55k
}