Coverage Report

Created: 2025-10-10 07:11

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