Blame snmplib/transports/snmpUDPDomain.c

Packit fcad23
/* Portions of this file are subject to the following copyright(s).  See
Packit fcad23
 * the Net-SNMP's COPYING file for more details and other copyrights
Packit fcad23
 * that may apply:
Packit fcad23
 */
Packit fcad23
/*
Packit fcad23
 * Portions of this file are copyrighted by:
Packit fcad23
 * Copyright Copyright 2003 Sun Microsystems, Inc. All rights reserved.
Packit fcad23
 * Use is subject to license terms specified in the COPYING file
Packit fcad23
 * distributed with the Net-SNMP package.
Packit fcad23
 *
Packit fcad23
 * Portions of this file are copyrighted by:
Packit fcad23
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
Packit fcad23
 * Use is subject to license terms specified in the COPYING file
Packit fcad23
 * distributed with the Net-SNMP package.
Packit fcad23
 */
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
Packit fcad23
#include <net-snmp/types.h>
Packit fcad23
#include <net-snmp/library/snmpUDPDomain.h>
Packit fcad23
#include <net-snmp/library/snmpUDPIPv4BaseDomain.h>
Packit fcad23
Packit fcad23
#include <stddef.h>
Packit fcad23
#include <stdio.h>
Packit fcad23
#include <sys/types.h>
Packit fcad23
#include <ctype.h>
Packit fcad23
#include <errno.h>
Packit fcad23
Packit fcad23
#if HAVE_STRING_H
Packit fcad23
#include <string.h>
Packit fcad23
#else
Packit fcad23
#include <strings.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_STDLIB_H
Packit fcad23
#include <stdlib.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
#include <unistd.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_SOCKET_H
Packit fcad23
#include <sys/socket.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETINET_IN_H
Packit fcad23
#include <netinet/in.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_ARPA_INET_H
Packit fcad23
#include <arpa/inet.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETDB_H
Packit fcad23
#include <netdb.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_UIO_H
Packit fcad23
#include <sys/uio.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#if HAVE_DMALLOC_H
Packit fcad23
#include <dmalloc.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#include <net-snmp/types.h>
Packit fcad23
#include <net-snmp/output_api.h>
Packit fcad23
#include <net-snmp/config_api.h>
Packit fcad23
Packit fcad23
#include <net-snmp/library/snmp_transport.h>
Packit fcad23
#include <net-snmp/library/snmpSocketBaseDomain.h>
Packit fcad23
#include <net-snmp/library/system.h>
Packit fcad23
#include <net-snmp/library/tools.h>
Packit fcad23
Packit fcad23
#include "inet_ntop.h"
Packit fcad23
#include "inet_pton.h"
Packit fcad23
Packit fcad23
#ifndef INADDR_NONE
Packit fcad23
#define INADDR_NONE	-1
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifndef INET_ADDRSTRLEN
Packit fcad23
#define INET_ADDRSTRLEN 16
Packit fcad23
#endif
Packit fcad23
Packit fcad23
static netsnmp_tdomain udpDomain;
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * needs to be in sync with the definitions in snmplib/snmpTCPDomain.c 
Packit fcad23
 * and perl/agent/agent.xs 
Packit fcad23
 */
Packit fcad23
typedef netsnmp_indexed_addr_pair netsnmp_udp_addr_pair;
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_sockaddr_in2(struct sockaddr_in *addr,
Packit fcad23
                     const char *inpeername, const char *default_target);
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Return a string representing the address in data, or else the "far end"
Packit fcad23
 * address if data is NULL.  
Packit fcad23
 */
Packit fcad23
Packit fcad23
char *
Packit fcad23
netsnmp_udp_fmtaddr(netsnmp_transport *t, const void *data, int len)
Packit fcad23
{
Packit fcad23
    return netsnmp_ipv4_fmtaddr("UDP", t, data, len);
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
#if defined(HAVE_IP_PKTINFO) || (defined(HAVE_IP_RECVDSTADDR) && defined(HAVE_IP_SENDSRCADDR))
Packit fcad23
Packit fcad23
int netsnmp_udp_recvfrom(int s, void *buf, int len, struct sockaddr *from, socklen_t *fromlen, struct sockaddr *dstip, socklen_t *dstlen, int *if_index)
Packit fcad23
{
Packit fcad23
    /** udpipv4 just calls udpbase. should we skip directly to there? */
Packit fcad23
    return netsnmp_udpipv4_recvfrom(s, buf, len, from, fromlen, dstip, dstlen,
Packit fcad23
                                    if_index);
Packit fcad23
}
Packit fcad23
Packit fcad23
int netsnmp_udp_sendto(int fd, const struct in_addr *srcip, int if_index,
Packit fcad23
                       const struct sockaddr *remote, const void *data, int len)
Packit fcad23
{
Packit fcad23
    /** udpipv4 just calls udpbase. should we skip directly to there? */
Packit fcad23
    return netsnmp_udpipv4_sendto(fd, srcip, if_index, remote, data, len);
Packit fcad23
}
Packit fcad23
#endif /* HAVE_IP_PKTINFO || HAVE_IP_RECVDSTADDR */
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Common initialization of udp transport.
Packit fcad23
 */
Packit fcad23
Packit fcad23
static netsnmp_transport *
Packit fcad23
netsnmp_udp_transport_base(netsnmp_transport *t)
Packit fcad23
{
Packit fcad23
    if (NULL == t) {
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Set Domain
Packit fcad23
     */
Packit fcad23
Packit fcad23
    t->domain = netsnmpUDPDomain;
Packit fcad23
    t->domain_length = netsnmpUDPDomain_len;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * 16-bit length field, 8 byte UDP header, 20 byte IPv4 header  
Packit fcad23
     */
Packit fcad23
Packit fcad23
    t->msgMaxSize = 0xffff - 8 - 20;
Packit fcad23
    t->f_recv     = netsnmp_udpbase_recv;
Packit fcad23
    t->f_send     = netsnmp_udpbase_send;
Packit fcad23
    t->f_close    = netsnmp_socketbase_close;
Packit fcad23
    t->f_accept   = NULL;
Packit fcad23
    t->f_fmtaddr  = netsnmp_udp_fmtaddr;
Packit fcad23
    t->f_get_taddr = netsnmp_ipv4_get_taddr;
Packit fcad23
Packit fcad23
    return t;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Open a UDP-based transport for SNMP.  Local is TRUE if addr is the local
Packit fcad23
 * address to bind to (i.e. this is a server-type session); otherwise addr is
Packit fcad23
 * the remote address to send things to.
Packit fcad23
 */
Packit fcad23
netsnmp_transport *
Packit fcad23
netsnmp_udp_transport(const struct sockaddr_in *addr, int local)
Packit fcad23
{
Packit fcad23
    netsnmp_transport *t = NULL;
Packit fcad23
Packit fcad23
    t = netsnmp_udpipv4base_transport(addr, local);
Packit fcad23
    if (NULL != t) {
Packit fcad23
        netsnmp_udp_transport_base(t);
Packit fcad23
    }
Packit fcad23
    return t;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Open a UDP-based transport for SNMP.  Local is TRUE if addr is the local
Packit fcad23
 * address to bind to (i.e. this is a server-type session); otherwise addr is
Packit fcad23
 * the remote address to send things to and src_addr is the optional addr
Packit fcad23
 * to send from.
Packit fcad23
 */
Packit fcad23
netsnmp_transport *
Packit fcad23
netsnmp_udp_transport_with_source(const struct sockaddr_in *addr, int local,
Packit fcad23
                                  const struct sockaddr_in *src_addr)
Packit fcad23
Packit fcad23
{
Packit fcad23
    netsnmp_transport *t = NULL;
Packit fcad23
Packit fcad23
    t = netsnmp_udpipv4base_transport_with_source(addr, local, src_addr);
Packit fcad23
    if (NULL != t) {
Packit fcad23
        netsnmp_udp_transport_base(t);
Packit fcad23
    }
Packit fcad23
    return t;
Packit fcad23
}
Packit fcad23
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
Packit fcad23
/*
Packit fcad23
 * The following functions provide the "com2sec" configuration token
Packit fcad23
 * functionality for compatibility.
Packit fcad23
 */
Packit fcad23
Packit fcad23
#define EXAMPLE_NETWORK		"NETWORK"
Packit fcad23
#define EXAMPLE_COMMUNITY	"COMMUNITY"
Packit fcad23
Packit fcad23
struct com2SecEntry_s {
Packit fcad23
    const char *secName;
Packit fcad23
    const char *contextName;
Packit fcad23
    struct com2SecEntry_s *next;
Packit fcad23
    in_addr_t   network;
Packit fcad23
    in_addr_t   mask;
Packit fcad23
    int         negate;
Packit fcad23
    const char  community[1];
Packit fcad23
};
Packit fcad23
Packit fcad23
static com2SecEntry   *com2SecList = NULL, *com2SecListLast = NULL;
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_udp_com2SecEntry_create(com2SecEntry **entryp, const char *community,
Packit fcad23
                    const char *secName, const char *contextName,
Packit fcad23
                    struct in_addr *network, struct in_addr *mask,
Packit fcad23
                    int negate)
Packit fcad23
{
Packit fcad23
    int communityLen, secNameLen, contextNameLen, len;
Packit fcad23
    com2SecEntry* e;
Packit fcad23
    char* last;
Packit fcad23
    struct in_addr dflt_network, dflt_mask;
Packit fcad23
Packit fcad23
    if (NULL != entryp)
Packit fcad23
        *entryp = NULL;
Packit fcad23
Packit fcad23
    if (NULL == community || NULL == secName)
Packit fcad23
        return C2SE_ERR_MISSING_ARG;
Packit fcad23
Packit fcad23
    if (NULL == network) {
Packit fcad23
        network = &dflt_network;
Packit fcad23
        dflt_network.s_addr = 0;
Packit fcad23
    }
Packit fcad23
    if (NULL == mask) {
Packit fcad23
        mask = &dflt_mask;
Packit fcad23
        dflt_mask.s_addr = 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /** Check that the network and mask are consistent. */
Packit fcad23
    if (network->s_addr & ~mask->s_addr)
Packit fcad23
        return C2SE_ERR_MASK_MISMATCH;
Packit fcad23
Packit fcad23
    communityLen = strlen(community);
Packit fcad23
    if (communityLen > COMMUNITY_MAX_LEN)
Packit fcad23
        return C2SE_ERR_COMMUNITY_TOO_LONG;
Packit fcad23
Packit fcad23
    secNameLen = strlen(secName);
Packit fcad23
    if (secNameLen > VACM_MAX_STRING)
Packit fcad23
        return C2SE_ERR_SECNAME_TOO_LONG;
Packit fcad23
Packit fcad23
    contextNameLen = contextName ? strlen(contextName) : 0;
Packit fcad23
    if (contextNameLen > VACM_MAX_STRING)
Packit fcad23
        return C2SE_ERR_CONTEXT_TOO_LONG;
Packit fcad23
Packit fcad23
    /** alloc space for struct + 3 strings with NULLs */
Packit fcad23
    len = offsetof(com2SecEntry, community) + communityLen + secNameLen +
Packit fcad23
        contextNameLen + 3;
Packit fcad23
    e = (com2SecEntry*)calloc(len, 1);
Packit fcad23
    if (e == NULL)
Packit fcad23
        return C2SE_ERR_MEMORY;
Packit fcad23
    last = ((char*)e) + offsetof(com2SecEntry, community);
Packit fcad23
Packit fcad23
    DEBUGIF("netsnmp_udp_parse_security") {
Packit fcad23
        char buf1[INET_ADDRSTRLEN];
Packit fcad23
        char buf2[INET_ADDRSTRLEN];
Packit fcad23
        DEBUGMSGTL(("netsnmp_udp_parse_security",
Packit fcad23
                    "<\"%s\", %s/%s> => \"%s\"\n", community,
Packit fcad23
                    inet_ntop(AF_INET, network, buf1, sizeof(buf1)),
Packit fcad23
                    inet_ntop(AF_INET, mask, buf2, sizeof(buf2)),
Packit fcad23
                    secName));
Packit fcad23
    }
Packit fcad23
Packit fcad23
    memcpy(last, community, communityLen);
Packit fcad23
    last += communityLen + 1;
Packit fcad23
    memcpy(last, secName, secNameLen);
Packit fcad23
    e->secName = last;
Packit fcad23
    last += secNameLen + 1;
Packit fcad23
    if (contextNameLen) {
Packit fcad23
        memcpy(last, contextName, contextNameLen);
Packit fcad23
        e->contextName = last;
Packit fcad23
    } else
Packit fcad23
        e->contextName = last - 1;
Packit fcad23
    e->network = network->s_addr;
Packit fcad23
    e->mask = mask->s_addr;
Packit fcad23
    e->negate = negate;
Packit fcad23
    e->next = NULL;
Packit fcad23
Packit fcad23
    if (com2SecListLast != NULL) {
Packit fcad23
        com2SecListLast->next = e;
Packit fcad23
        com2SecListLast = e;
Packit fcad23
    } else {
Packit fcad23
        com2SecListLast = com2SecList = e;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (NULL != entryp)
Packit fcad23
        *entryp = e;
Packit fcad23
Packit fcad23
    return C2SE_ERR_SUCCESS;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_udp_parse_security(const char *token, char *param)
Packit fcad23
{
Packit fcad23
    /** copy_nword does null term, so we need vars of max size + 2. */
Packit fcad23
    /** (one for null, one to detect param too long */
Packit fcad23
    char            secName[VACMSTRINGLEN]; /* == VACM_MAX_STRING + 2 */
Packit fcad23
    char            contextName[VACMSTRINGLEN];
Packit fcad23
    char            community[COMMUNITY_MAX_LEN + 2];
Packit fcad23
    char            source[271]; /* !(1)+dns-name(253)+/(1)+mask(15)+\0(1) */
Packit fcad23
    char            *sourcep;
Packit fcad23
    struct in_addr  network, mask;
Packit fcad23
    int             negate;
Packit fcad23
    int rc;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Get security, source address/netmask and community strings.
Packit fcad23
     */
Packit fcad23
Packit fcad23
    param = copy_nword( param, secName, sizeof(secName));
Packit fcad23
    if (strcmp(secName, "-Cn") == 0) {
Packit fcad23
        if (!param) {
Packit fcad23
            config_perror("missing CONTEXT_NAME parameter");
Packit fcad23
            return;
Packit fcad23
        }
Packit fcad23
        param = copy_nword( param, contextName, sizeof(contextName));
Packit fcad23
        if (!param) {
Packit fcad23
            config_perror("missing NAME parameter");
Packit fcad23
            return;
Packit fcad23
        }
Packit fcad23
        param = copy_nword( param, secName, sizeof(secName));
Packit fcad23
    } else
Packit fcad23
        contextName[0] = '\0';
Packit fcad23
Packit fcad23
    if (secName[0] == '\0') {
Packit fcad23
        config_perror("empty NAME parameter");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (!param) {
Packit fcad23
        config_perror("missing SOURCE parameter");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    param = copy_nword( param, source, sizeof(source));
Packit fcad23
    if (source[0] == '\0') {
Packit fcad23
        config_perror("empty SOURCE parameter");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    if (strncmp(source, EXAMPLE_NETWORK, strlen(EXAMPLE_NETWORK)) == 0) {
Packit fcad23
        config_perror("example config NETWORK not properly configured");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (!param) {
Packit fcad23
        config_perror("missing COMMUNITY parameter");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    param = copy_nword( param, community, sizeof(community));
Packit fcad23
    if (community[0] == '\0') {
Packit fcad23
        config_perror("empty COMMUNITY parameter");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    if ((strlen(community) + 1) == sizeof(EXAMPLE_COMMUNITY) &&
Packit fcad23
        memcmp(community, EXAMPLE_COMMUNITY, sizeof(EXAMPLE_COMMUNITY)) == 0) {
Packit fcad23
        config_perror("example config COMMUNITY not properly configured");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /* Deal with the "default" case first. */
Packit fcad23
    if (strcmp(source, "default") == 0) {
Packit fcad23
        network.s_addr = 0;
Packit fcad23
        mask.s_addr = 0;
Packit fcad23
        negate = 0;
Packit fcad23
    } else {
Packit fcad23
        if (*source == '!') {
Packit fcad23
            negate = 1;
Packit fcad23
            sourcep = source + 1;
Packit fcad23
        } else {
Packit fcad23
            negate = 0;
Packit fcad23
            sourcep = source;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /* Split the source/netmask parts */
Packit fcad23
        char *strmask = strchr(sourcep, '/');
Packit fcad23
        if (strmask != NULL)
Packit fcad23
            /* Mask given. */
Packit fcad23
            *strmask++ = '\0';
Packit fcad23
Packit fcad23
        /* Try interpreting as a dotted quad. */
Packit fcad23
        if (inet_pton(AF_INET, sourcep, &network) == 0) {
Packit fcad23
            /* Nope, wasn't a dotted quad.  Must be a hostname. */
Packit fcad23
            int ret = netsnmp_gethostbyname_v4(sourcep, &network.s_addr);
Packit fcad23
            if (ret < 0) {
Packit fcad23
                config_perror("cannot resolve source hostname");
Packit fcad23
                return;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /* Now work out the mask. */
Packit fcad23
        if (strmask == NULL || *strmask == '\0') {
Packit fcad23
            /* No mask was given. Assume /32 */
Packit fcad23
            mask.s_addr = (in_addr_t)(~0UL);
Packit fcad23
        } else {
Packit fcad23
            /* Try to interpret mask as a "number of 1 bits". */
Packit fcad23
            char* cp;
Packit fcad23
            long maskLen = strtol(strmask, &cp, 10);
Packit fcad23
            if (*cp == '\0') {
Packit fcad23
                if (0 < maskLen && maskLen <= 32)
Packit fcad23
                    mask.s_addr = htonl((in_addr_t)(~0UL << (32 - maskLen)));
Packit fcad23
                else if (0 == maskLen)
Packit fcad23
                    mask.s_addr = 0;
Packit fcad23
                else {
Packit fcad23
                    config_perror("bad mask length");
Packit fcad23
                    return;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
            /* Try to interpret mask as a dotted quad. */
Packit fcad23
            else if (inet_pton(AF_INET, strmask, &mask) == 0) {
Packit fcad23
                config_perror("bad mask");
Packit fcad23
                return;
Packit fcad23
            }
Packit fcad23
Packit fcad23
            /* Check that the network and mask are consistent. */
Packit fcad23
            if (network.s_addr & ~mask.s_addr) {
Packit fcad23
                config_perror("source/mask mismatch");
Packit fcad23
                return;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Everything is okay.  Copy the parameters to the structure allocated
Packit fcad23
     * above and add it to END of the list.
Packit fcad23
     */
Packit fcad23
    rc = netsnmp_udp_com2SecEntry_create(NULL, community, secName, contextName,
Packit fcad23
                                         &network, &mask, negate);
Packit fcad23
    switch(rc) {
Packit fcad23
        case C2SE_ERR_SUCCESS:
Packit fcad23
            break;
Packit fcad23
        case C2SE_ERR_CONTEXT_TOO_LONG:
Packit fcad23
            config_perror("context name too long");
Packit fcad23
            break;
Packit fcad23
        case C2SE_ERR_COMMUNITY_TOO_LONG:
Packit fcad23
            config_perror("community name too long");
Packit fcad23
            break;
Packit fcad23
        case C2SE_ERR_SECNAME_TOO_LONG:
Packit fcad23
            config_perror("security name too long");
Packit fcad23
            break;
Packit fcad23
        case C2SE_ERR_MASK_MISMATCH:
Packit fcad23
            config_perror("source/mask mismatch");
Packit fcad23
            break;
Packit fcad23
        case C2SE_ERR_MISSING_ARG:
Packit fcad23
        default:
Packit fcad23
            config_perror("unexpected error; could not create com2SecEntry");
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_udp_com2Sec_free(com2SecEntry *e)
Packit fcad23
{
Packit fcad23
    free(e);
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
netsnmp_udp_com2SecList_remove(com2SecEntry *e)
Packit fcad23
{
Packit fcad23
    com2SecEntry   *c = com2SecList, *p = NULL;
Packit fcad23
    for (; c != NULL; p = c, c = c->next) {
Packit fcad23
        if (e == c)
Packit fcad23
            break;
Packit fcad23
    }
Packit fcad23
    if (NULL == c)
Packit fcad23
        return 1;
Packit fcad23
Packit fcad23
    if (NULL == p)
Packit fcad23
        com2SecList = e->next;
Packit fcad23
    else
Packit fcad23
        p->next = e->next;
Packit fcad23
    e->next = NULL;
Packit fcad23
Packit fcad23
    if (e == com2SecListLast)
Packit fcad23
        com2SecListLast = p;
Packit fcad23
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_udp_com2SecList_free(void)
Packit fcad23
{
Packit fcad23
    com2SecEntry   *e = com2SecList;
Packit fcad23
    while (e != NULL) {
Packit fcad23
        com2SecEntry   *tmp = e;
Packit fcad23
        e = e->next;
Packit fcad23
        netsnmp_udp_com2Sec_free(tmp);
Packit fcad23
    }
Packit fcad23
    com2SecList = com2SecListLast = NULL;
Packit fcad23
}
Packit fcad23
#endif /* support for community based SNMP */
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_udp_agent_config_tokens_register(void)
Packit fcad23
{
Packit fcad23
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
Packit fcad23
    register_app_config_handler("com2sec", netsnmp_udp_parse_security,
Packit fcad23
                                netsnmp_udp_com2SecList_free,
Packit fcad23
                                "[-Cn CONTEXT] secName IPv4-network-address[/netmask] community");
Packit fcad23
#endif /* support for community based SNMP */
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * Return 0 if there are no com2sec entries, or return 1 if there ARE com2sec
Packit fcad23
 * entries.  On return, if a com2sec entry matched the passed parameters,
Packit fcad23
 * then *secName points at the appropriate security name, or is NULL if the
Packit fcad23
 * parameters did not match any com2sec entry.
Packit fcad23
 */
Packit fcad23
Packit fcad23
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
Packit fcad23
int
Packit fcad23
netsnmp_udp_getSecName(void *opaque, int olength,
Packit fcad23
                       const char *community,
Packit fcad23
                       size_t community_len, const char **secName,
Packit fcad23
                       const char **contextName)
Packit fcad23
{
Packit fcad23
    const com2SecEntry *c;
Packit fcad23
    netsnmp_udp_addr_pair *addr_pair = (netsnmp_udp_addr_pair *) opaque;
Packit fcad23
    struct sockaddr_in *from = (struct sockaddr_in *) &(addr_pair->remote_addr);
Packit fcad23
    char           *ztcommunity = NULL;
Packit fcad23
Packit fcad23
    if (secName != NULL) {
Packit fcad23
        *secName = NULL;  /* Haven't found anything yet */
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Special case if there are NO entries (as opposed to no MATCHING
Packit fcad23
     * entries).
Packit fcad23
     */
Packit fcad23
Packit fcad23
    if (com2SecList == NULL) {
Packit fcad23
        DEBUGMSGTL(("netsnmp_udp_getSecName", "no com2sec entries\n"));
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * If there is no IPv4 source address, then there can be no valid security
Packit fcad23
     * name.
Packit fcad23
     */
Packit fcad23
Packit fcad23
   DEBUGMSGTL(("netsnmp_udp_getSecName", "opaque = %p (len = %d), sizeof = %d, family = %d (%d)\n",
Packit fcad23
   opaque, olength, (int)sizeof(netsnmp_udp_addr_pair), from->sin_family, AF_INET));
Packit fcad23
    if (opaque == NULL || olength != sizeof(netsnmp_udp_addr_pair) ||
Packit fcad23
        from->sin_family != AF_INET) {
Packit fcad23
        DEBUGMSGTL(("netsnmp_udp_getSecName",
Packit fcad23
		    "no IPv4 source address in PDU?\n"));
Packit fcad23
        return 1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGIF("netsnmp_udp_getSecName") {
Packit fcad23
	ztcommunity = (char *)malloc(community_len + 1);
Packit fcad23
	if (ztcommunity != NULL) {
Packit fcad23
	    memcpy(ztcommunity, community, community_len);
Packit fcad23
	    ztcommunity[community_len] = '\0';
Packit fcad23
	}
Packit fcad23
Packit fcad23
	DEBUGMSGTL(("netsnmp_udp_getSecName", "resolve <\"%s\", 0x%08lx>\n",
Packit fcad23
		    ztcommunity ? ztcommunity : "<malloc error>",
Packit fcad23
		    (unsigned long)(from->sin_addr.s_addr)));
Packit fcad23
    }
Packit fcad23
Packit fcad23
    for (c = com2SecList; c != NULL; c = c->next) {
Packit fcad23
        {
Packit fcad23
            char buf1[INET_ADDRSTRLEN];
Packit fcad23
            char buf2[INET_ADDRSTRLEN];
Packit fcad23
            DEBUGMSGTL(("netsnmp_udp_getSecName","compare <\"%s\", %s/%s>",
Packit fcad23
                        c->community,
Packit fcad23
                        inet_ntop(AF_INET, &c->network, buf1, sizeof(buf1)),
Packit fcad23
                        inet_ntop(AF_INET, &c->mask, buf2, sizeof(buf2))));
Packit fcad23
        }
Packit fcad23
        if ((community_len == strlen(c->community)) &&
Packit fcad23
	    (memcmp(community, c->community, community_len) == 0) &&
Packit fcad23
            ((from->sin_addr.s_addr & c->mask) == c->network)) {
Packit fcad23
            DEBUGMSG(("netsnmp_udp_getSecName", "... SUCCESS\n"));
Packit fcad23
            if (c->negate) {
Packit fcad23
                /*
Packit fcad23
                 * If we matched a negative entry, then we are done - claim that we
Packit fcad23
                 * matched nothing.
Packit fcad23
                 */
Packit fcad23
                DEBUGMSG(("netsnmp_udp_getSecName", "... <negative entry>\n"));
Packit fcad23
                break;
Packit fcad23
            }
Packit fcad23
            if (secName != NULL) {
Packit fcad23
                *secName = c->secName;
Packit fcad23
                *contextName = c->contextName;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
        }
Packit fcad23
        DEBUGMSG(("netsnmp_udp_getSecName", "... nope\n"));
Packit fcad23
    }
Packit fcad23
    if (ztcommunity != NULL) {
Packit fcad23
        free(ztcommunity);
Packit fcad23
    }
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
#endif /* support for community based SNMP */
Packit fcad23
Packit fcad23
Packit fcad23
netsnmp_transport *
Packit fcad23
netsnmp_udp_create_tstring(const char *str, int local,
Packit fcad23
			   const char *default_target)
Packit fcad23
{
Packit fcad23
    struct sockaddr_in addr;
Packit fcad23
Packit fcad23
    if (netsnmp_sockaddr_in2(&addr, str, default_target)) {
Packit fcad23
        return netsnmp_udp_transport(&addr, local);
Packit fcad23
    } else {
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_transport *
Packit fcad23
netsnmp_udp_create_tspec(netsnmp_tdomain_spec *tspec)
Packit fcad23
{
Packit fcad23
    netsnmp_transport *t = netsnmp_udpipv4base_tspec_transport(tspec);
Packit fcad23
    if (NULL != t) {
Packit fcad23
        netsnmp_udp_transport_base(t);
Packit fcad23
    }
Packit fcad23
    return t;
Packit fcad23
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_transport *
Packit fcad23
netsnmp_udp_create_ostring(const void *o, size_t o_len, int local)
Packit fcad23
{
Packit fcad23
    struct sockaddr_in sin;
Packit fcad23
Packit fcad23
    if (netsnmp_ipv4_ostring_to_sockaddr(&sin, o, o_len))
Packit fcad23
        return netsnmp_udp_transport(&sin, local);
Packit fcad23
    return NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
void
Packit fcad23
netsnmp_udp_ctor(void)
Packit fcad23
{
Packit fcad23
    udpDomain.name = netsnmpUDPDomain;
Packit fcad23
    udpDomain.name_length = netsnmpUDPDomain_len;
Packit fcad23
    udpDomain.prefix = (const char**)calloc(2, sizeof(char *));
Packit fcad23
    udpDomain.prefix[0] = "udp";
Packit fcad23
Packit fcad23
    udpDomain.f_create_from_tstring     = NULL;
Packit fcad23
    udpDomain.f_create_from_tstring_new = netsnmp_udp_create_tstring;
Packit fcad23
    udpDomain.f_create_from_tspec       = netsnmp_udp_create_tspec;
Packit fcad23
    udpDomain.f_create_from_ostring     = netsnmp_udp_create_ostring;
Packit fcad23
Packit fcad23
    netsnmp_tdomain_register(&udpDomain);
Packit fcad23
}