diff options
Diffstat (limited to 'snmplib/transports/snmpIPv4BaseDomain.c')
-rw-r--r-- | snmplib/transports/snmpIPv4BaseDomain.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/snmplib/transports/snmpIPv4BaseDomain.c b/snmplib/transports/snmpIPv4BaseDomain.c new file mode 100644 index 0000000..41a6cb6 --- /dev/null +++ b/snmplib/transports/snmpIPv4BaseDomain.c @@ -0,0 +1,223 @@ +/* IPV4 base transport support functions + */ + +#include <net-snmp/net-snmp-config.h> + +#include <net-snmp/types.h> +#include <net-snmp/library/snmpIPv4BaseDomain.h> + +#include <stddef.h> +#include <stdio.h> +#include <sys/types.h> +#include <ctype.h> +#if HAVE_STDLIB_H +#include <stdlib.h> +#endif +#if HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif +#if HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +#if HAVE_NETDB_H +#include <netdb.h> +#endif + +#include <net-snmp/types.h> +#include <net-snmp/library/snmp_debug.h> +#include <net-snmp/library/default_store.h> +#include <net-snmp/library/system.h> + + +#ifndef INADDR_NONE +#define INADDR_NONE -1 +#endif + +int +netsnmp_sockaddr_in(struct sockaddr_in *addr, + const char *inpeername, int remote_port) +{ + char buf[sizeof(int) * 3 + 2]; + sprintf(buf, ":%u", remote_port); + return netsnmp_sockaddr_in2(addr, inpeername, remote_port ? buf : NULL); +} + +int +netsnmp_sockaddr_in2(struct sockaddr_in *addr, + const char *inpeername, const char *default_target) +{ + int ret; + + if (addr == NULL) { + return 0; + } + + DEBUGMSGTL(("netsnmp_sockaddr_in", + "addr %p, inpeername \"%s\", default_target \"%s\"\n", + addr, inpeername ? inpeername : "[NIL]", + default_target ? default_target : "[NIL]")); + + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_addr.s_addr = htonl(INADDR_ANY); + addr->sin_family = AF_INET; + addr->sin_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->sin_port = htons((u_short)port); + } else if (default_target != NULL) + netsnmp_sockaddr_in2(addr, default_target, NULL); + } + + if (inpeername != NULL && *inpeername != '\0') { + const char *host, *port; + char *peername = NULL; + char *cp; + /* + * Duplicate the peername because we might want to mank around with + * it. + */ + + peername = strdup(inpeername); + if (peername == NULL) { + return 0; + } + + /* + * Try and extract an appended port number. + */ + cp = strchr(peername, ':'); + if (cp != NULL) { + *cp = '\0'; + port = cp + 1; + host = peername; + } else { + host = NULL; + port = peername; + } + + /* + * Try to convert the user port specifier + */ + if (port && *port == '\0') + port = NULL; + + if (port != NULL) { + long int l; + char* ep; + + DEBUGMSGTL(("netsnmp_sockaddr_in", "check user service %s\n", + port)); + + l = strtol(port, &ep, 10); + if (ep != port && *ep == '\0' && 0 <= l && l <= 0x0ffff) + addr->sin_port = htons((u_short)l); + else { + if (host == NULL) { + DEBUGMSGTL(("netsnmp_sockaddr_in", + "servname not numeric, " + "check if it really is a destination)\n")); + host = port; + port = NULL; + } else { + DEBUGMSGTL(("netsnmp_sockaddr_in", + "servname not numeric\n")); + free(peername); + return 0; + } + } + } + + /* + * Try to convert the user host specifier + */ + if (host && *host == '\0') + host = NULL; + + if (host != NULL) { + DEBUGMSGTL(("netsnmp_sockaddr_in", + "check destination %s\n", host)); + + + if (strcmp(peername, "255.255.255.255") == 0 ) { + /* + * The explicit broadcast address hack + */ + DEBUGMSGTL(("netsnmp_sockaddr_in", "Explicit UDP broadcast\n")); + addr->sin_addr.s_addr = INADDR_NONE; + } else { + ret = + netsnmp_gethostbyname_v4(peername, &addr->sin_addr.s_addr); + if (ret < 0) { + DEBUGMSGTL(("netsnmp_sockaddr_in", + "couldn't resolve hostname\n")); + free(peername); + return 0; + } + DEBUGMSGTL(("netsnmp_sockaddr_in", + "hostname (resolved okay)\n")); + } + } + free(peername); + } + + /* + * Finished + */ + + DEBUGMSGTL(("netsnmp_sockaddr_in", "return { AF_INET, %s:%hu }\n", + inet_ntoa(addr->sin_addr), ntohs(addr->sin_port))); + return 1; +} + +char * +netsnmp_ipv4_fmtaddr(const char *prefix, netsnmp_transport *t, + void *data, int len) +{ + netsnmp_indexed_addr_pair *addr_pair = NULL; + struct hostent *host; + char tmp[64]; + + if (data != NULL && len == sizeof(netsnmp_indexed_addr_pair)) { + addr_pair = (netsnmp_indexed_addr_pair *) data; + } else if (t != NULL && t->data != NULL) { + addr_pair = (netsnmp_indexed_addr_pair *) t->data; + } + + if (addr_pair == NULL) { + snprintf(tmp, sizeof(tmp), "%s: unknown", prefix); + } else { + struct sockaddr_in *to = NULL; + to = (struct sockaddr_in *) &(addr_pair->remote_addr); + if (to == NULL) { + snprintf(tmp, sizeof(tmp), "%s: unknown->[%s]:%hu", prefix, + inet_ntoa(addr_pair->local_addr.sin.sin_addr), + ntohs(addr_pair->local_addr.sin.sin_port)); + } else if ( t && t->flags & NETSNMP_TRANSPORT_FLAG_HOSTNAME ) { + /* XXX: hmm... why isn't this prefixed */ + /* assuming intentional */ + host = netsnmp_gethostbyaddr((char *)&to->sin_addr, 4, AF_INET); + return (host ? strdup(host->h_name) : NULL); + } else { + snprintf(tmp, sizeof(tmp), "%s: [%s]:%hu->", prefix, + inet_ntoa(to->sin_addr), ntohs(to->sin_port)); + snprintf(tmp + strlen(tmp), sizeof(tmp)-strlen(tmp), "[%s]:%hu", + inet_ntoa(addr_pair->local_addr.sin.sin_addr), + ntohs(addr_pair->local_addr.sin.sin_port)); + } + } + tmp[sizeof(tmp)-1] = '\0'; + return strdup(tmp); +} + |