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 {
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 {
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 {