Coverage Report

Created: 2026-08-13 09:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/net-snmp/snmplib/transports/snmpUDPDomain.c
Line
Count
Source
1
/* Portions of this file are subject to the following copyright(s).  See
2
 * the Net-SNMP's COPYING file for more details and other copyrights
3
 * that may apply:
4
 */
5
/*
6
 * Portions of this file are copyrighted by:
7
 * Copyright Copyright 2003 Sun Microsystems, Inc. All rights reserved.
8
 * Use is subject to license terms specified in the COPYING file
9
 * distributed with the Net-SNMP package.
10
 *
11
 * Portions of this file are copyrighted by:
12
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
13
 * Use is subject to license terms specified in the COPYING file
14
 * distributed with the Net-SNMP package.
15
 */
16
17
#include <net-snmp/net-snmp-config.h>
18
19
#include <net-snmp/types.h>
20
#include "snmpIPBaseDomain.h"
21
#include <net-snmp/library/snmpUDPDomain.h>
22
#include <net-snmp/library/snmpUDPIPv4BaseDomain.h>
23
24
#include <stddef.h>
25
#include <stdio.h>
26
#include <sys/types.h>
27
#include <ctype.h>
28
#include <errno.h>
29
30
#ifdef HAVE_STRING_H
31
#include <string.h>
32
#else
33
#include <strings.h>
34
#endif
35
#ifdef HAVE_STDLIB_H
36
#include <stdlib.h>
37
#endif
38
#ifdef HAVE_UNISTD_H
39
#include <unistd.h>
40
#endif
41
#ifdef HAVE_SYS_SOCKET_H
42
#include <sys/socket.h>
43
#endif
44
#ifdef HAVE_NETINET_IN_H
45
#include <netinet/in.h>
46
#endif
47
#ifdef HAVE_ARPA_INET_H
48
#include <arpa/inet.h>
49
#endif
50
#ifdef HAVE_NETDB_H
51
#include <netdb.h>
52
#endif
53
#ifdef HAVE_NETGROUP_H
54
#include <netgroup.h>
55
#endif
56
#ifdef HAVE_SYS_UIO_H
57
#include <sys/uio.h>
58
#endif
59
60
#include <net-snmp/types.h>
61
#include <net-snmp/output_api.h>
62
#include <net-snmp/config_api.h>
63
64
#include <net-snmp/library/snmp_impl.h>
65
#include <net-snmp/library/snmp_transport.h>
66
#include <net-snmp/library/snmpSocketBaseDomain.h>
67
#include <net-snmp/library/system.h>
68
#include <net-snmp/library/tools.h>
69
70
#include "inet_ntop.h"
71
#include "inet_pton.h"
72
73
#ifndef INADDR_NONE
74
#define INADDR_NONE -1
75
#endif
76
77
#ifndef INET_ADDRSTRLEN
78
#define INET_ADDRSTRLEN 16
79
#endif
80
81
static netsnmp_tdomain udpDomain;
82
83
/*
84
 * needs to be in sync with the definitions in snmplib/snmpTCPDomain.c 
85
 * and perl/agent/agent.xs 
86
 */
87
typedef netsnmp_indexed_addr_pair netsnmp_udp_addr_pair;
88
89
/*
90
 * Return a string representing the address in data, or else the "far end"
91
 * address if data is NULL.  
92
 */
93
94
char *
95
netsnmp_udp_fmtaddr(netsnmp_transport *t, const void *data, int len)
96
0
{
97
0
    return netsnmp_ipv4_fmtaddr("UDP", t, data, len);
98
0
}
99
100
static int
101
netsnmp_udp_resolve_source(char *source, struct in_addr *network,
102
        struct in_addr *mask)
103
445
{
104
    /* Split the source/netmask parts */
105
445
    char *strmask = strchr(source, '/');
106
445
    if (strmask != NULL)
107
        /* Mask given. */
108
268
        *strmask++ = '\0';
109
110
    /* Try interpreting as a dotted quad. */
111
445
   if (inet_pton(AF_INET, source, network) == 0) {
112
        /* Nope, wasn't a dotted quad.  Must be a hostname. */
113
438
        int ret = netsnmp_gethostbyname_v4(source, &(network->s_addr));
114
438
        if (ret < 0) {
115
193
            config_perror("cannot resolve source hostname");
116
193
            return ret;
117
193
        }
118
438
    }
119
120
    /* Now work out the mask. */
121
252
    if (strmask == NULL || *strmask == '\0') {
122
        /* No mask was given. Assume /32 */
123
28
        mask->s_addr = (in_addr_t)(~0UL);
124
224
    } else {
125
        /* Try to interpret mask as a "number of 1 bits". */
126
224
        char* cp;
127
224
        long maskLen = strtol(strmask, &cp, 10);
128
224
        if (*cp == '\0') {
129
202
            if (0 < maskLen && maskLen <= 32)
130
32
                mask->s_addr = htonl((in_addr_t)(~0UL << (32 - maskLen)));
131
170
            else if (maskLen == 0)
132
14
                mask->s_addr = 0;
133
156
            else {
134
156
                config_perror("bad mask length");
135
156
                return -1;
136
156
            }
137
202
        }
138
        /* Try to interpret mask as a dotted quad. */
139
22
        else if (inet_pton(AF_INET, strmask, mask) == 0) {
140
18
            config_perror("bad mask");
141
18
            return -1;
142
18
        }
143
144
        /* Check that the network and mask are consistent. */
145
50
        if (network->s_addr & ~mask->s_addr) {
146
44
            config_perror("source/mask mismatch");
147
44
            return -1;
148
44
        }
149
50
    }
150
34
    return 0;
151
252
}
152
153
#if defined(HAVE_IP_PKTINFO) || (defined(HAVE_IP_RECVDSTADDR) && defined(HAVE_IP_SENDSRCADDR))
154
155
int
156
netsnmp_udp_recvfrom(NETSNMP_SOCKET sock, void *buf, int len,
157
                     struct sockaddr *from, socklen_t *fromlen,
158
                     struct sockaddr *dstip, socklen_t *dstlen, int *if_index)
159
46
{
160
    /** udpipv4 just calls udpbase. should we skip directly to there? */
161
46
    return netsnmp_udpipv4_recvfrom(sock, buf, len, from, fromlen, dstip, dstlen,
162
46
                                    if_index);
163
46
}
164
165
int netsnmp_udp_sendto(NETSNMP_SOCKET sock, const struct in_addr *srcip,
166
                       int if_index, const struct sockaddr *remote,
167
                       const void *data, int len)
168
20
{
169
    /** udpipv4 just calls udpbase. should we skip directly to there? */
170
20
    return netsnmp_udpipv4_sendto(sock, srcip, if_index, remote, data, len);
171
20
}
172
#endif /* HAVE_IP_PKTINFO || HAVE_IP_RECVDSTADDR */
173
174
/*
175
 * Common initialization of udp transport.
176
 */
177
178
static netsnmp_transport *
179
netsnmp_udp_transport_base(netsnmp_transport *t)
180
3.48k
{
181
3.48k
    if (NULL == t) {
182
0
        return NULL;
183
0
    }
184
185
    /*
186
     * Set Domain
187
     */
188
189
3.48k
    t->domain = netsnmpUDPDomain;
190
3.48k
    t->domain_length = netsnmpUDPDomain_len;
191
192
    /*
193
     * 16-bit length field, 8 byte UDP header, 20 byte IPv4 header  
194
     */
195
196
3.48k
    t->msgMaxSize = 0xffff - 8 - 20;
197
3.48k
    t->f_recv     = netsnmp_udpbase_recv;
198
3.48k
    t->f_send     = netsnmp_udpbase_send;
199
3.48k
    t->f_close    = netsnmp_socketbase_close;
200
3.48k
    t->f_accept   = NULL;
201
3.48k
    t->f_setup_session = netsnmp_ipbase_session_init;
202
3.48k
    t->f_fmtaddr  = netsnmp_udp_fmtaddr;
203
3.48k
    t->f_get_taddr = netsnmp_ipv4_get_taddr;
204
205
3.48k
    return t;
206
3.48k
}
207
208
/*
209
 * Open a UDP-based transport for SNMP.  Local is TRUE if addr is the local
210
 * address to bind to (i.e. this is a server-type session); otherwise addr is
211
 * the remote address to send things to.
212
 */
213
netsnmp_transport *
214
netsnmp_udp_transport(const struct netsnmp_ep *ep, int local)
215
0
{
216
0
    netsnmp_transport *t = NULL;
217
218
0
    t = netsnmp_udpipv4base_transport(ep, local);
219
0
    if (NULL != t) {
220
0
        netsnmp_udp_transport_base(t);
221
0
    }
222
0
    return t;
223
0
}
224
225
/*
226
 * Open a UDP-based transport for SNMP.  Local is TRUE if addr is the local
227
 * address to bind to (i.e. this is a server-type session); otherwise addr is
228
 * the remote address to send things to and src_addr is the optional addr
229
 * to send from.
230
 */
231
netsnmp_transport *
232
netsnmp_udp_transport_with_source(const struct netsnmp_ep *ep, int local,
233
                                  const struct netsnmp_ep *src_addr)
234
235
0
{
236
0
    netsnmp_transport *t = NULL;
237
238
0
    t = netsnmp_udpipv4base_transport_with_source(ep, local, src_addr);
239
0
    if (NULL != t) {
240
0
        netsnmp_udp_transport_base(t);
241
0
    }
242
0
    return t;
243
0
}
244
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
245
/*
246
 * The following functions provide the "com2sec" configuration token
247
 * functionality for compatibility.
248
 */
249
250
1.06k
#define EXAMPLE_NETWORK   "NETWORK"
251
633
#define EXAMPLE_COMMUNITY "COMMUNITY"
252
253
struct com2SecEntry_s {
254
    const char *secName;
255
    const char *contextName;
256
    struct com2SecEntry_s *next;
257
    in_addr_t   network;
258
    in_addr_t   mask;
259
    int         negate;
260
    const char  community[1];
261
};
262
263
static com2SecEntry   *com2SecList = NULL, *com2SecListLast = NULL;
264
265
int
266
netsnmp_udp_com2SecEntry_create(com2SecEntry **entryp, const char *community,
267
                    const char *secName, const char *contextName,
268
                    struct in_addr *network, struct in_addr *mask,
269
                    int negate)
270
41
{
271
41
    int communityLen, secNameLen, contextNameLen, len;
272
41
    com2SecEntry* e;
273
41
    char* last;
274
41
    struct in_addr dflt_network, dflt_mask;
275
276
41
    if (NULL != entryp)
277
0
        *entryp = NULL;
278
279
41
    if (NULL == community || NULL == secName)
280
0
        return C2SE_ERR_MISSING_ARG;
281
282
41
    if (NULL == network) {
283
0
        network = &dflt_network;
284
0
        dflt_network.s_addr = 0;
285
0
    }
286
41
    if (NULL == mask) {
287
0
        mask = &dflt_mask;
288
0
        dflt_mask.s_addr = 0;
289
0
    }
290
291
    /** Check that the network and mask are consistent. */
292
41
    if (network->s_addr & ~mask->s_addr)
293
0
        return C2SE_ERR_MASK_MISMATCH;
294
295
41
    communityLen = strlen(community);
296
41
    if (communityLen > COMMUNITY_MAX_LEN)
297
0
        return C2SE_ERR_COMMUNITY_TOO_LONG;
298
299
41
    secNameLen = strlen(secName);
300
41
    if (secNameLen > VACM_MAX_STRING)
301
8
        return C2SE_ERR_SECNAME_TOO_LONG;
302
303
33
    contextNameLen = contextName ? strlen(contextName) : 0;
304
33
    if (contextNameLen > VACM_MAX_STRING)
305
1
        return C2SE_ERR_CONTEXT_TOO_LONG;
306
307
    /** alloc space for struct + 3 strings with NULLs */
308
32
    len = offsetof(com2SecEntry, community) + communityLen + secNameLen +
309
32
        contextNameLen + 3;
310
32
    e = calloc(len, 1);
311
32
    if (e == NULL)
312
0
        return C2SE_ERR_MEMORY;
313
32
    last = ((char*)e) + offsetof(com2SecEntry, community);
314
315
32
    DEBUGIF("netsnmp_udp_parse_security") {
316
0
        char buf1[INET_ADDRSTRLEN];
317
0
        char buf2[INET_ADDRSTRLEN];
318
0
        DEBUGMSGTL(("netsnmp_udp_parse_security",
319
0
                    "<\"%s\", %s/%s> => \"%s\"\n", community,
320
0
                    inet_ntop(AF_INET, network, buf1, sizeof(buf1)),
321
0
                    inet_ntop(AF_INET, mask, buf2, sizeof(buf2)),
322
0
                    secName));
323
0
    }
324
325
32
    memcpy(last, community, communityLen);
326
32
    last += communityLen + 1;
327
32
    memcpy(last, secName, secNameLen);
328
32
    e->secName = last;
329
32
    last += secNameLen + 1;
330
32
    if (contextNameLen) {
331
9
        memcpy(last, contextName, contextNameLen);
332
9
        e->contextName = last;
333
9
    } else
334
23
        e->contextName = last - 1;
335
32
    e->network = network->s_addr;
336
32
    e->mask = mask->s_addr;
337
32
    e->negate = negate;
338
32
    e->next = NULL;
339
340
32
    if (com2SecListLast != NULL) {
341
31
        com2SecListLast->next = e;
342
31
        com2SecListLast = e;
343
31
    } else {
344
1
        com2SecListLast = com2SecList = e;
345
1
    }
346
347
32
    if (NULL != entryp)
348
0
        *entryp = e;
349
350
32
    return C2SE_ERR_SUCCESS;
351
32
}
352
353
void
354
netsnmp_udp_com2SecEntry_check_return_code(int rc)
355
41
{
356
    /*
357
     * Check return code of the newly created com2Sec entry.
358
     */
359
41
    switch(rc) {
360
32
        case C2SE_ERR_SUCCESS:
361
32
            break;
362
1
        case C2SE_ERR_CONTEXT_TOO_LONG:
363
1
            config_perror("context name too long");
364
1
            break;
365
0
        case C2SE_ERR_COMMUNITY_TOO_LONG:
366
0
            config_perror("community name too long");
367
0
            break;
368
8
        case C2SE_ERR_SECNAME_TOO_LONG:
369
8
            config_perror("security name too long");
370
8
            break;
371
0
        case C2SE_ERR_MASK_MISMATCH:
372
0
            config_perror("source/mask mismatch");
373
0
            break;
374
0
        case C2SE_ERR_MISSING_ARG:
375
0
        default:
376
0
            config_perror("unexpected error; could not create com2SecEntry");
377
41
    }
378
41
}
379
380
#if defined(HAVE_ENDNETGRENT) && defined(HAVE_GETNETGRENT)
381
int netsnmp_parse_source_as_netgroup(const char *sourcep, const char *community,
382
                       const char *secName, const char *contextName, int negate)
383
450
{
384
450
    const char *netgroup = sourcep+1;
385
450
    char *host, *user, *domain;
386
450
    struct in_addr network, mask;
387
450
    int rc;
388
389
    /* Without '@' it has to be an address or hostname */
390
450
    if (*sourcep != '@')
391
445
        return 0;
392
393
    /* Interpret as netgroup */
394
5
#ifdef SETNETGRENT_RETURNS_INT
395
5
    if (!setnetgrent(netgroup)) {
396
5
        config_perror("netgroup could not be found");
397
5
        return 1;
398
5
    }
399
#else
400
    setnetgrent(netgroup);
401
#endif
402
0
    while (getnetgrent(&host, &user, &domain)) {
403
        /* Parse source address and network mask for each netgroup host. */
404
0
        if (netsnmp_udp_resolve_source(host, &network, &mask) == 0) {
405
            /* Create a new com2Sec entry. */
406
0
            rc = netsnmp_udp_com2SecEntry_create(NULL, community, secName, contextName,
407
0
                   &network, &mask, negate);
408
0
            netsnmp_udp_com2SecEntry_check_return_code(rc);
409
0
        } else {
410
0
            config_perror("netgroup host address parsing issue");
411
0
            break;
412
0
        }
413
0
    }
414
0
    endnetgrent();
415
0
    return 1;
416
5
}
417
#else
418
int netsnmp_parse_source_as_netgroup(const char *sourcep, const char *community,
419
                       const char *secName, const char *contextName, int negate)
420
{
421
    return 0;
422
}
423
#endif
424
425
void
426
netsnmp_udp_parse_security(const char *token, char *param)
427
755
{
428
    /** copy_nword does null term, so we need vars of max size + 2. */
429
    /** (one for null, one to detect param too long */
430
755
    char            secName[VACMSTRINGLEN]; /* == VACM_MAX_STRING + 2 */
431
755
    char            contextName[VACMSTRINGLEN];
432
755
    char            community[COMMUNITY_MAX_LEN + 2];
433
755
    char            source[271]; /* !(1)+dns-name(253)+/(1)+mask(15)+\0(1) */
434
755
    char            *sourcep;
435
755
    struct in_addr  network, mask;
436
755
    int             negate;
437
755
    int rc;
438
439
    /*
440
     * Get security, source address/netmask and community strings.
441
     */
442
443
755
    param = copy_nword( param, secName, sizeof(secName));
444
755
    if (strcmp(secName, "-Cn") == 0) {
445
29
        if (!param) {
446
3
            config_perror("missing CONTEXT_NAME parameter");
447
3
            return;
448
3
        }
449
26
        param = copy_nword( param, contextName, sizeof(contextName));
450
26
        if (!param) {
451
2
            config_perror("missing NAME parameter");
452
2
            return;
453
2
        }
454
24
        param = copy_nword( param, secName, sizeof(secName));
455
24
    } else
456
726
        contextName[0] = '\0';
457
458
750
    if (secName[0] == '\0') {
459
66
        config_perror("empty NAME parameter");
460
66
        return;
461
66
    }
462
463
684
    if (!param) {
464
147
        config_perror("missing SOURCE parameter");
465
147
        return;
466
147
    }
467
537
    param = copy_nword( param, source, sizeof(source));
468
537
    if (source[0] == '\0') {
469
5
        config_perror("empty SOURCE parameter");
470
5
        return;
471
5
    }
472
532
    if (strncmp(source, EXAMPLE_NETWORK, strlen(EXAMPLE_NETWORK)) == 0) {
473
2
        config_perror("example config NETWORK not properly configured");
474
2
        return;
475
2
    }
476
477
530
    if (!param) {
478
67
        config_perror("missing COMMUNITY parameter");
479
67
        return;
480
67
    }
481
463
    param = copy_nword( param, community, sizeof(community));
482
463
    if (community[0] == '\0') {
483
4
        config_perror("empty COMMUNITY parameter");
484
4
        return;
485
4
    }
486
459
    if ((strlen(community) + 1) == sizeof(EXAMPLE_COMMUNITY) &&
487
87
        memcmp(community, EXAMPLE_COMMUNITY, sizeof(EXAMPLE_COMMUNITY)) == 0) {
488
2
        config_perror("example config COMMUNITY not properly configured");
489
2
        return;
490
2
    }
491
492
    /* Deal with the "default" case first. */
493
457
    if (strcmp(source, "default") == 0) {
494
7
        network.s_addr = 0;
495
7
        mask.s_addr = 0;
496
7
        negate = 0;
497
        /* Create a new com2Sec entry. */
498
7
        rc = netsnmp_udp_com2SecEntry_create(NULL, community, secName, contextName,
499
7
                                             &network, &mask, negate);
500
7
        netsnmp_udp_com2SecEntry_check_return_code(rc);
501
450
    } else {
502
450
        if (*source == '!') {
503
31
            negate = 1;
504
31
            sourcep = source + 1;
505
419
        } else {
506
419
            negate = 0;
507
419
            sourcep = source;
508
419
        }
509
450
        if (!netsnmp_parse_source_as_netgroup(sourcep, community, secName,
510
450
                                              contextName, negate)) {
511
            /* Parse source address and network mask. */
512
445
            if (netsnmp_udp_resolve_source(sourcep, &network, &mask) == 0) {
513
                /* Create a new com2Sec entry. */
514
34
                rc = netsnmp_udp_com2SecEntry_create(NULL, community, secName, contextName,
515
34
                                                     &network, &mask, negate);
516
34
                netsnmp_udp_com2SecEntry_check_return_code(rc);
517
34
            }
518
445
        }
519
450
    }
520
457
}
521
522
void
523
netsnmp_udp_com2Sec_free(com2SecEntry *e)
524
0
{
525
0
    free(e);
526
0
}
527
528
int
529
netsnmp_udp_com2SecList_remove(com2SecEntry *e)
530
0
{
531
0
    com2SecEntry   *c = com2SecList, *p = NULL;
532
0
    for (; c != NULL; p = c, c = c->next) {
533
0
        if (e == c)
534
0
            break;
535
0
    }
536
0
    if (NULL == c)
537
0
        return 1;
538
539
0
    if (NULL == p)
540
0
        com2SecList = e->next;
541
0
    else
542
0
        p->next = e->next;
543
0
    e->next = NULL;
544
545
0
    if (e == com2SecListLast)
546
0
        com2SecListLast = p;
547
548
0
    return 0;
549
0
}
550
551
void
552
netsnmp_udp_com2SecList_free(void)
553
6.87k
{
554
6.87k
    com2SecEntry   *e = com2SecList;
555
6.87k
    while (e != NULL) {
556
0
        com2SecEntry   *tmp = e;
557
0
        e = e->next;
558
0
        netsnmp_udp_com2Sec_free(tmp);
559
0
    }
560
6.87k
    com2SecList = com2SecListLast = NULL;
561
6.87k
}
562
#endif /* support for community based SNMP */
563
564
void
565
netsnmp_udp_agent_config_tokens_register(void)
566
3.43k
{
567
3.43k
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
568
3.43k
    register_app_config_handler("com2sec", netsnmp_udp_parse_security,
569
3.43k
                                netsnmp_udp_com2SecList_free,
570
3.43k
                                "[-Cn CONTEXT] secName IPv4-network-address[/netmask] community");
571
3.43k
#endif /* support for community based SNMP */
572
3.43k
}
573
574
575
576
/*
577
 * Return 0 if there are no com2sec entries, or return 1 if there ARE com2sec
578
 * entries.  On return, if a com2sec entry matched the passed parameters,
579
 * then *secName points at the appropriate security name, or is NULL if the
580
 * parameters did not match any com2sec entry.
581
 */
582
583
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
584
int
585
netsnmp_udp_getSecName(void *opaque, int olength,
586
                       const char *community,
587
                       size_t community_len, const char **secName,
588
                       const char **contextName)
589
0
{
590
0
    const com2SecEntry *c;
591
0
    netsnmp_udp_addr_pair *addr_pair = (netsnmp_udp_addr_pair *) opaque;
592
0
    struct sockaddr_in *from = (struct sockaddr_in *) &(addr_pair->remote_addr);
593
0
    char           *ztcommunity = NULL;
594
595
0
    if (secName != NULL) {
596
0
        *secName = NULL;  /* Haven't found anything yet */
597
0
    }
598
599
    /*
600
     * Special case if there are NO entries (as opposed to no MATCHING
601
     * entries).
602
     */
603
604
0
    if (com2SecList == NULL) {
605
0
        DEBUGMSGTL(("netsnmp_udp_getSecName", "no com2sec entries\n"));
606
0
        return 0;
607
0
    }
608
609
    /*
610
     * If there is no IPv4 source address, then there can be no valid security
611
     * name.
612
     */
613
614
0
   DEBUGMSGTL(("netsnmp_udp_getSecName", "opaque = %p (len = %d), sizeof = %d, family = %d (%d)\n",
615
0
   opaque, olength, (int)sizeof(netsnmp_udp_addr_pair), from->sin_family, AF_INET));
616
0
    if (opaque == NULL || olength != sizeof(netsnmp_udp_addr_pair) ||
617
0
        from->sin_family != AF_INET) {
618
0
        DEBUGMSGTL(("netsnmp_udp_getSecName",
619
0
        "no IPv4 source address in PDU?\n"));
620
0
        return 1;
621
0
    }
622
623
0
    DEBUGIF("netsnmp_udp_getSecName") {
624
0
  ztcommunity = (char *)malloc(community_len + 1);
625
0
  if (ztcommunity != NULL) {
626
0
      memcpy(ztcommunity, community, community_len);
627
0
      ztcommunity[community_len] = '\0';
628
0
  }
629
630
0
  DEBUGMSGTL(("netsnmp_udp_getSecName", "resolve <\"%s\", 0x%08lx>\n",
631
0
        ztcommunity ? ztcommunity : "<malloc error>",
632
0
        (unsigned long)(from->sin_addr.s_addr)));
633
0
    }
634
635
0
    for (c = com2SecList; c != NULL; c = c->next) {
636
0
        {
637
0
            char buf1[INET_ADDRSTRLEN];
638
0
            char buf2[INET_ADDRSTRLEN];
639
0
            DEBUGMSGTL(("netsnmp_udp_getSecName","compare <\"%s\", %s/%s>",
640
0
                        c->community,
641
0
                        inet_ntop(AF_INET, &c->network, buf1, sizeof(buf1)),
642
0
                        inet_ntop(AF_INET, &c->mask, buf2, sizeof(buf2))));
643
0
        }
644
0
        if ((community_len == strlen(c->community)) &&
645
0
      (memcmp(community, c->community, community_len) == 0) &&
646
0
            ((from->sin_addr.s_addr & c->mask) == c->network)) {
647
0
            DEBUGMSG(("netsnmp_udp_getSecName", "... SUCCESS\n"));
648
0
            if (c->negate) {
649
                /*
650
                 * If we matched a negative entry, then we are done - claim that we
651
                 * matched nothing.
652
                 */
653
0
                DEBUGMSG(("netsnmp_udp_getSecName", "... <negative entry>\n"));
654
0
                break;
655
0
            }
656
0
            if (secName != NULL) {
657
0
                *secName = c->secName;
658
0
                *contextName = c->contextName;
659
0
            }
660
0
            break;
661
0
        }
662
0
        DEBUGMSG(("netsnmp_udp_getSecName", "... nope\n"));
663
0
    }
664
0
    if (ztcommunity != NULL) {
665
0
        free(ztcommunity);
666
0
    }
667
0
    return 1;
668
0
}
669
#endif /* support for community based SNMP */
670
671
672
netsnmp_transport *
673
netsnmp_udp_create_tstring(const char *str, int local,
674
         const char *default_target)
675
0
{
676
0
    struct netsnmp_ep addr;
677
678
0
    if (netsnmp_sockaddr_in3(&addr, str, default_target)) {
679
0
        return netsnmp_udp_transport(&addr, local);
680
0
    } else {
681
0
        return NULL;
682
0
    }
683
0
}
684
685
netsnmp_transport *
686
netsnmp_udp_create_tspec(netsnmp_tdomain_spec *tspec)
687
3.48k
{
688
3.48k
    netsnmp_transport *t = netsnmp_udpipv4base_tspec_transport(tspec);
689
3.48k
    if (NULL != t) {
690
3.48k
        netsnmp_udp_transport_base(t);
691
3.48k
    }
692
3.48k
    return t;
693
694
3.48k
}
695
696
netsnmp_transport *
697
netsnmp_udp_create_ostring(const void *o, size_t o_len, int local)
698
0
{
699
0
    struct netsnmp_ep ep;
700
701
0
    memset(&ep, 0, sizeof(ep));
702
0
    if (netsnmp_ipv4_ostring_to_sockaddr(&ep.a.sin, o, o_len))
703
0
        return netsnmp_udp_transport(&ep, local);
704
0
    return NULL;
705
0
}
706
707
708
void
709
netsnmp_udp_ctor(void)
710
4.25k
{
711
4.25k
    udpDomain.name = netsnmpUDPDomain;
712
4.25k
    udpDomain.name_length = netsnmpUDPDomain_len;
713
4.25k
    udpDomain.prefix = calloc(2, sizeof(char *));
714
4.25k
    if (!udpDomain.prefix) {
715
0
        snmp_log(LOG_ERR, "calloc() failed - out of memory\n");
716
0
        return;
717
0
    }
718
4.25k
    udpDomain.prefix[0] = "udp";
719
720
4.25k
    udpDomain.f_create_from_tstring_new = netsnmp_udp_create_tstring;
721
4.25k
    udpDomain.f_create_from_tspec       = netsnmp_udp_create_tspec;
722
4.25k
    udpDomain.f_create_from_ostring     = netsnmp_udp_create_ostring;
723
724
4.25k
    netsnmp_tdomain_register(&udpDomain);
725
4.25k
}