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 {