int netsnmp_sockaddr_in6_2 (struct sockaddr_in6 *addr, const char *inpeername, const char *default_target) { char *cp = NULL, *peername = NULL; char debug_addr[INET6_ADDRSTRLEN]; #if HAVE_GETADDRINFO struct addrinfo *addrs = NULL; int err; #elif HAVE_GETIPNODEBYNAME struct hostent *hp = NULL; int err; #elif HAVE_GETHOSTBYNAME struct hostent *hp = NULL; #endif int portno; if (addr == NULL) { return 0; } DEBUGMSGTL (("netsnmp_sockaddr_in6", "addr %p, peername \"%s\", default_target \"%s\"\n", addr, inpeername ? inpeername : "[NIL]", default_target ? default_target : "[NIL]")); memset (addr, 0, sizeof (struct sockaddr_in6)); addr->sin6_family = AF_INET6; addr->sin6_addr = in6addr_any; addr->sin6_port = htons ((u_short) SNMP_PORT); { int port = netsnmp_ds_get_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DEFAULT_PORT); if (port != 0) addr->sin6_port = htons ((u_short) port); else if (default_target != NULL) netsnmp_sockaddr_in6_2 (addr, default_target, NULL); } if (inpeername != NULL) { /* * Duplicate the peername because we might want to mank around with * it. */ peername = strdup (inpeername); if (peername == NULL) { return 0; } for (cp = peername; *cp && isdigit ((unsigned char) *cp); cp++); portno = atoi (peername); if (!*cp && portno != 0) { /* * Okay, it looks like JUST a port number. */ DEBUGMSGTL (("netsnmp_sockaddr_in6", "totally numeric: %d\n", portno)); addr->sin6_port = htons ((u_short) portno); goto resolved; } /* * See if it is an IPv6 address covered with square brackets. Also check * for an appended :port. */ if (*peername == '[') { cp = strchr (peername, ']'); if (cp != NULL) { /* * See if it is an IPv6 link-local address with interface * name as <zone_id>, like fe80::1234%eth0. * Please refer to the internet draft, IPv6 Scoped Address Architecture * http://www.ietf.org/internet-drafts/draft-ietf-ipngwg-scoping-arch-04.txt * */ char *scope_id; unsigned int if_index = 0; *cp = '\0'; scope_id = strchr (peername + 1, '%'); if (scope_id != NULL) { *scope_id = '\0'; if_index = netsnmp_if_nametoindex (scope_id + 1); } if (*(cp + 1) == ':') { portno = atoi (cp + 2); if (portno != 0 && inet_pton (AF_INET6, peername + 1, (void *) &(addr->sin6_addr))) { DEBUGMSGTL (("netsnmp_sockaddr_in6", "IPv6 address with port suffix :%d\n", portno)); if (portno > 0 && portno < 0xffff) { addr->sin6_port = htons ((u_short) portno); } else { DEBUGMSGTL (("netsnmp_sockaddr_in6", "invalid port number: %d", portno)); return 0; } #if defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID) addr->sin6_scope_id = if_index; #endif goto resolved; } } else { if (inet_pton (AF_INET6, peername + 1, (void *) &(addr->sin6_addr))) { DEBUGMSGTL (("netsnmp_sockaddr_in6", "IPv6 address with square brackets\n")); portno = netsnmp_ds_get_int (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DEFAULT_PORT); if (portno <= 0) portno = SNMP_PORT; addr->sin6_port = htons ((u_short) portno); #if defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID) addr->sin6_scope_id = if_index; #endif goto resolved; } } if (scope_id != NULL) { *scope_id = '%'; } *cp = ']'; } } cp = strrchr (peername, ':'); if (cp != NULL) { char *scope_id; unsigned int if_index = 0; *cp = '\0'; scope_id = strchr (peername + 1, '%'); if (scope_id != NULL) { *scope_id = '\0'; if_index = netsnmp_if_nametoindex (scope_id + 1); } portno = atoi (cp + 1); if (portno != 0 && inet_pton (AF_INET6, peername, (void *) &(addr->sin6_addr))) { DEBUGMSGTL (("netsnmp_sockaddr_in6", "IPv6 address with port suffix :%d\n", atoi (cp + 1))); if (portno > 0 && portno < 0xffff) { addr->sin6_port = htons ((u_short) portno); } else { DEBUGMSGTL (("netsnmp_sockaddr_in6", "invalid port number: %d", portno)); return 0; } #if defined(HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID) addr->sin6_scope_id = if_index; #endif goto resolved; } if (scope_id != NULL) { *scope_id = '%'; } *cp = ':'; } /* * See if it is JUST an IPv6 address. */ if (inet_pton (AF_INET6, peername, (void *) &(addr->sin6_addr))) { DEBUGMSGTL (("netsnmp_sockaddr_in6", "just IPv6 address\n")); goto resolved; } /* * Well, it must be a hostname then, possibly with an appended :port. * Sort that out first. */ cp = strrchr (peername, ':'); if (cp != NULL) { *cp = '\0'; portno = atoi (cp + 1); if (portno != 0) { DEBUGMSGTL (("netsnmp_sockaddr_in6", "hostname(?) with port suffix :%d\n", portno)); if (portno > 0 && portno < 0xffff) { addr->sin6_port = htons ((u_short) portno); } else { DEBUGMSGTL (("netsnmp_sockaddr_in6", "invalid port number: %d", portno)); return 0; } } else { /* * No idea, looks bogus but we might as well pass the full thing to * the name resolver below. */ *cp = ':'; DEBUGMSGTL (("netsnmp_sockaddr_in6", "hostname(?) with embedded ':'?\n")); } /* * Fall through. */ } if (peername[0] == '\0') { DEBUGMSGTL (("netsnmp_sockaddr_in6", "empty hostname\n")); free (peername); return 0; } #if HAVE_GETADDRINFO { struct addrinfo hint = { 0 }; hint.ai_flags = 0; hint.ai_family = PF_INET6; hint.ai_socktype = SOCK_DGRAM; hint.ai_protocol = 0; err = netsnmp_getaddrinfo (peername, NULL, &hint, &addrs); } if (err != 0) { #if HAVE_GAI_STRERROR snmp_log (LOG_ERR, "getaddrinfo(\"%s\", NULL, ...): %s\n", peername, gai_strerror (err)); #else snmp_log (LOG_ERR, "getaddrinfo(\"%s\", NULL, ...): (error %d)\n", peername, err); #endif free (peername); return 0; } if (addrs != NULL) { DEBUGMSGTL (("netsnmp_sockaddr_in6", "hostname (resolved okay)\n")); memcpy (&addr->sin6_addr, &((struct sockaddr_in6 *) addrs->ai_addr)->sin6_addr, sizeof (struct in6_addr)); freeaddrinfo (addrs); } else { DEBUGMSGTL (("netsnmp_sockaddr_in6", "Failed to resolve IPv6 hostname\n")); } #elif HAVE_GETIPNODEBYNAME hp = getipnodebyname (peername, AF_INET6, 0, &err); if (hp == NULL) { DEBUGMSGTL (("netsnmp_sockaddr_in6", "hostname (couldn't resolve = %d)\n", err)); free (peername); return 0; } DEBUGMSGTL (("netsnmp_sockaddr_in6", "hostname (resolved okay)\n")); memcpy (&(addr->sin6_addr), hp->h_addr, hp->h_length); #elif HAVE_GETHOSTBYNAME hp = netsnmp_gethostbyname (peername); if (hp == NULL) { DEBUGMSGTL (("netsnmp_sockaddr_in6", "hostname (couldn't resolve)\n")); free (peername); return 0; } else { if (hp->h_addrtype != AF_INET6) { DEBUGMSGTL (("netsnmp_sockaddr_in6", "hostname (not AF_INET6!)\n")); free (peername); return 0; } else { DEBUGMSGTL (("netsnmp_sockaddr_in6", "hostname (resolved okay)\n")); memcpy (&(addr->sin6_addr), hp->h_addr, hp->h_length); } } #else /*HAVE_GETHOSTBYNAME */ /* * There is no name resolving function available. */ snmp_log (LOG_ERR, "no getaddrinfo()/getipnodebyname()/gethostbyname()\n"); free (peername); return 0; #endif /*HAVE_GETHOSTBYNAME */ } else { DEBUGMSGTL (("netsnmp_sockaddr_in6", "NULL peername")); return 0; } resolved: DEBUGMSGTL (("netsnmp_sockaddr_in6", "return { AF_INET6, [%s]:%hu }\n", inet_ntop (AF_INET6, &addr->sin6_addr, debug_addr, sizeof (debug_addr)), ntohs (addr->sin6_port))); free (peername); return 1; }
int netsnmp_gethostbyname_v4(const char* name, in_addr_t *addr_out) { #if HAVE_GETADDRINFO struct addrinfo *addrs = NULL; struct addrinfo hint; int err; memset(&hint, 0, sizeof hint); hint.ai_flags = 0; hint.ai_family = PF_INET; hint.ai_socktype = SOCK_DGRAM; hint.ai_protocol = 0; err = netsnmp_getaddrinfo(name, NULL, &hint, &addrs); if (err != 0) { return -1; } if (addrs != NULL) { memcpy(addr_out, &((struct sockaddr_in *) addrs->ai_addr)->sin_addr, sizeof(in_addr_t)); freeaddrinfo(addrs); } else { DEBUGMSGTL(("get_thisaddr", "Failed to resolve IPv4 hostname\n")); } return 0; #elif HAVE_GETHOSTBYNAME struct hostent *hp = NULL; hp = netsnmp_gethostbyname(name); if (hp == NULL) { DEBUGMSGTL(("get_thisaddr", "hostname (couldn't resolve)\n")); return -1; } else if (hp->h_addrtype != AF_INET) { DEBUGMSGTL(("get_thisaddr", "hostname (not AF_INET!)\n")); return -1; } else { DEBUGMSGTL(("get_thisaddr", "hostname (resolved okay)\n")); memcpy(addr_out, hp->h_addr, sizeof(in_addr_t)); } return 0; #elif HAVE_GETIPNODEBYNAME struct hostent *hp = NULL; int err; hp = getipnodebyname(peername, AF_INET, 0, &err); if (hp == NULL) { DEBUGMSGTL(("get_thisaddr", "hostname (couldn't resolve = %d)\n", err)); return -1; } DEBUGMSGTL(("get_thisaddr", "hostname (resolved okay)\n")); memcpy(addr_out, hp->h_addr, sizeof(in_addr_t)); return 0; #else /* HAVE_GETIPNODEBYNAME */ return -1; #endif }