Beispiel #1
0
static int
netsnmp_tlstcp_close(netsnmp_transport *t)
{
    _netsnmpTLSBaseData *tlsdata;

    if (NULL == t || NULL == t->data)
        return -1;

    /* RFC5953 Section 5.4.  Closing a Session

       1)  Increment either the snmpTlstmSessionClientCloses or the
           snmpTlstmSessionServerCloses counter as appropriate.
    */
    if (t->flags & NETSNMP_TLSBASE_IS_CLIENT)
        snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONCLIENTCLOSES);
    else
        snmp_increment_statistic(STAT_TLSTM_SNMPTLSTMSESSIONSERVERCLOSES);

    /* RFC5953 Section 5.4.  Closing a Session
       2)  Look up the session using the tmSessionID.
    */
    tlsdata = (_netsnmpTLSBaseData *) t->data;

    /* RFC5953 Section 5.4.  Closing a Session
       3)  If there is no open session associated with the tmSessionID, then
           closeSession processing is completed.
    */
    /* Implementation notes: if we have a non-zero tlsdata then it's
       always true */

    /* RFC5953 Section 5.3.1: Establishing a Session as a Client
       4)  Have (D)TLS close the specified connection.  This SHOULD include
           sending a close_notify TLS Alert to inform the other side that
           session cleanup may be performed.
    */

    DEBUGMSGTL(("tlstcp", "Shutting down SSL connection\n"));
    if (tlsdata->ssl) {
        SSL_shutdown(tlsdata->ssl);
    }

    netsnmp_tlsbase_free_tlsdata(tlsdata);

    t->data = NULL;
    return netsnmp_socketbase_close(t);
}
netsnmp_transport *
netsnmp_udpipv4base_transport(struct sockaddr_in *addr, int local)
{
    netsnmp_transport *t = NULL;
    int             rc = 0, rc2;
    char           *str = NULL;
    char           *client_socket = NULL;
    netsnmp_indexed_addr_pair addr_pair;
    socklen_t       local_addr_len;

    if (addr == NULL || addr->sin_family != AF_INET) {
        return NULL;
    }

    memset(&addr_pair, 0, sizeof(netsnmp_indexed_addr_pair));
    memcpy(&(addr_pair.remote_addr), addr, sizeof(struct sockaddr_in));

    t = SNMP_MALLOC_TYPEDEF(netsnmp_transport);
    netsnmp_assert_or_return(t != NULL, NULL);

    str = netsnmp_udp_fmtaddr(NULL, (void *)&addr_pair,
                                 sizeof(netsnmp_indexed_addr_pair));
    DEBUGMSGTL(("netsnmp_udpbase", "open %s %s\n", local ? "local" : "remote",
                str));
    free(str);

    t->sock = socket(PF_INET, SOCK_DGRAM, 0);
    DEBUGMSGTL(("UDPBase", "openned socket %d as local=%d\n", t->sock, local)); 
    if (t->sock < 0) {
        netsnmp_transport_free(t);
        return NULL;
    }

    _netsnmp_udp_sockopt_set(t->sock, local);

    if (local) {
        /*
         * This session is inteneded as a server, so we must bind on to the
         * given IP address, which may include an interface address, or could
         * be INADDR_ANY, but certainly includes a port number.
         */

      t->local = (u_char *) malloc(6);
        if (t->local == NULL) {
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->local, (u_char *) & (addr->sin_addr.s_addr), 4);
        t->local[4] = (htons(addr->sin_port) & 0xff00) >> 8;
        t->local[5] = (htons(addr->sin_port) & 0x00ff) >> 0;
        t->local_length = 6;

#if defined(linux) && defined(IP_PKTINFO)
        { 
            int sockopt = 1;
            if (setsockopt(t->sock, SOL_IP, IP_PKTINFO, &sockopt, sizeof sockopt) == -1) {
                DEBUGMSGTL(("netsnmp_udpbase", "couldn't set IP_PKTINFO: %s\n",
                    strerror(errno)));
                netsnmp_transport_free(t);
                return NULL;
            }
            DEBUGMSGTL(("netsnmp_udpbase", "set IP_PKTINFO\n"));
        }
#endif
        rc = bind(t->sock, (struct sockaddr *) addr,
                  sizeof(struct sockaddr));
        if (rc != 0) {
            netsnmp_socketbase_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        t->data = NULL;
        t->data_length = 0;
    } else {
Beispiel #3
0
netsnmp_transport *
netsnmp_udp6_transport(struct sockaddr_in6 *addr, int local)
{
    netsnmp_transport *t = NULL;
    int             rc = 0;
    char           *str = NULL;
    int             socket_initialized = 0;

#ifdef NETSNMP_NO_LISTEN_SUPPORT
    if (local)
        return NULL;
#endif /* NETSNMP_NO_LISTEN_SUPPORT */

    if (addr == NULL || addr->sin6_family != AF_INET6) {
        return NULL;
    }

    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (t == NULL) {
        return NULL;
    }

    str = netsnmp_udp6_fmtaddr(NULL, (void *) addr,
				  sizeof(struct sockaddr_in6));
    DEBUGMSGTL(("netsnmp_udp6", "open %s %s\n", local ? "local" : "remote",
                str));
    free(str);

    memset(t, 0, sizeof(netsnmp_transport));

    t->domain = netsnmp_UDPIPv6Domain;
    t->domain_length =
        sizeof(netsnmp_UDPIPv6Domain) / sizeof(netsnmp_UDPIPv6Domain[0]);

#ifndef NETSNMP_NO_SYSTEMD
    /*
     * Maybe the socket was already provided by systemd...
     */
    if (local) {
        t->sock = netsnmp_sd_find_inet_socket(PF_INET6, SOCK_DGRAM, -1,
                ntohs(addr->sin6_port));
        if (t->sock)
            socket_initialized = 1;
    }
#endif
    if (!socket_initialized)
        t->sock = (int) socket(PF_INET6, SOCK_DGRAM, 0);
    if (t->sock < 0) {
        netsnmp_transport_free(t);
        return NULL;
    }

    _netsnmp_udp_sockopt_set(t->sock, local);

    if (local) {
#ifndef NETSNMP_NO_LISTEN_SUPPORT
        /*
         * This session is intended as a server, so we must bind on to the
         * given IP address, which may include an interface address, or could
         * be INADDR_ANY, but certainly includes a port number.
         */

#ifdef IPV6_V6ONLY
        /* Try to restrict PF_INET6 socket to IPv6 communications only. */
        {
	  int one=1;
	  if (setsockopt(t->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) != 0) {
	    DEBUGMSGTL(("netsnmp_udp6", "couldn't set IPV6_V6ONLY to %d bytes: %s\n", one, strerror(errno)));
	  } 
	}
#endif
        if (!socket_initialized) {
            rc = bind(t->sock, (struct sockaddr *) addr,
                    sizeof(struct sockaddr_in6));
            if (rc != 0) {
                netsnmp_socketbase_close(t);
                netsnmp_transport_free(t);
                return NULL;
            }
        }
        t->local = (unsigned char*)malloc(18);
        if (t->local == NULL) {
            netsnmp_socketbase_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->local, addr->sin6_addr.s6_addr, 16);
        t->local[16] = (addr->sin6_port & 0xff00) >> 8;
        t->local[17] = (addr->sin6_port & 0x00ff) >> 0;
        t->local_length = 18;
        t->data = NULL;
        t->data_length = 0;
#else /* NETSNMP_NO_LISTEN_SUPPORT */
        return NULL;
#endif /* NETSNMP_NO_LISTEN_SUPPORT */
    } else {
Beispiel #4
0
netsnmp_transport *
netsnmp_tcp6_transport(struct sockaddr_in6 *addr, int local)
{
    netsnmp_transport *t = NULL;
    int             rc = 0;
    char           *str = NULL;
    int             socket_initialized = 0;

#ifdef NETSNMP_NO_LISTEN_SUPPORT
    if (local)
        return NULL;
#endif /* NETSNMP_NO_LISTEN_SUPPORT */

    if (addr == NULL || addr->sin6_family != AF_INET6) {
        return NULL;
    }

    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));
    if (t == NULL) {
        return NULL;
    }
    memset(t, 0, sizeof(netsnmp_transport));

    str = netsnmp_tcp6_fmtaddr(NULL, (void *)addr,
				  sizeof(struct sockaddr_in6));
    DEBUGMSGTL(("netsnmp_tcp6", "open %s %s\n", local ? "local" : "remote",
                str));
    free(str);

    memset(t, 0, sizeof(netsnmp_transport));

    t->data = malloc(sizeof(netsnmp_indexed_addr_pair));
    if (t->data == NULL) {
        netsnmp_transport_free(t);
        return NULL;
    }
    t->data_length = sizeof(netsnmp_indexed_addr_pair);
    memcpy(t->data, addr, sizeof(netsnmp_indexed_addr_pair));

    t->domain = netsnmp_TCPIPv6Domain;
    t->domain_length = sizeof(netsnmp_TCPIPv6Domain) / sizeof(oid);

#ifndef NETSNMP_NO_SYSTEMD
    /*
     * Maybe the socket was already provided by systemd...
     */
    if (local) {
        t->sock = netsnmp_sd_find_inet_socket(PF_INET6, SOCK_STREAM, 1,
                ntohs(addr->sin6_port));
        if (t->sock)
            socket_initialized = 1;
    }
#endif
    if (!socket_initialized)
        t->sock = (int) socket(PF_INET6, SOCK_STREAM, 0);
    if (t->sock < 0) {
        netsnmp_transport_free(t);
        return NULL;
    }

    t->flags = NETSNMP_TRANSPORT_FLAG_STREAM;

    if (local) {
#ifndef NETSNMP_NO_LISTEN_SUPPORT
        int opt = 1;

        /*
         * This session is inteneded as a server, so we must bind on to the
         * given IP address, which may include an interface address, or could
         * be INADDR_ANY, but certainly includes a port number.
         */

#ifdef IPV6_V6ONLY
        /* Try to restrict PF_INET6 socket to IPv6 communications only. */
        {
	  int one=1;
	  if (setsockopt(t->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) != 0) {
	    DEBUGMSGTL(("netsnmp_tcp6", "couldn't set IPV6_V6ONLY to %d bytes: %s\n", one, strerror(errno)));
	  } 
	}
#endif

        t->flags |= NETSNMP_TRANSPORT_FLAG_LISTEN;
        t->local = (unsigned char*)malloc(18);
        if (t->local == NULL) {
            netsnmp_socketbase_close(t);
            netsnmp_transport_free(t);
            return NULL;
        }
        memcpy(t->local, addr->sin6_addr.s6_addr, 16);
        t->local[16] = (addr->sin6_port & 0xff00) >> 8;
        t->local[17] = (addr->sin6_port & 0x00ff) >> 0;
        t->local_length = 18;

        /*
         * We should set SO_REUSEADDR too.  
         */

        setsockopt(t->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt));

        if (!socket_initialized) {
            rc = bind(t->sock, (struct sockaddr *) addr,
                    sizeof(struct sockaddr_in6));
            if (rc != 0) {
                netsnmp_socketbase_close(t);
                netsnmp_transport_free(t);
                return NULL;
            }
        }

        /*
         * Since we are going to be letting select() tell us when connections
         * are ready to be accept()ed, we need to make the socket n0n-blocking
         * to avoid the race condition described in W. R. Stevens, ``Unix
         * Network Programming Volume I Second Edition'', pp. 422--4, which
         * could otherwise wedge the agent.
         */

        netsnmp_set_non_blocking_mode(t->sock, TRUE);

        /*
         * Now sit here and wait for connections to arrive.  
         */

        if (!socket_initialized) {
            rc = listen(t->sock, NETSNMP_STREAM_QUEUE_LEN);
            if (rc != 0) {
                netsnmp_socketbase_close(t);
                netsnmp_transport_free(t);
                return NULL;
            }
        }
        
        /*
         * no buffer size on listen socket - doesn't make sense
         */
#else /* NETSNMP_NO_LISTEN_SUPPORT */
        return NULL;
#endif /* NETSNMP_NO_LISTEN_SUPPORT */
    } else {