diff options
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/Makefile.am | 53 | ||||
-rw-r--r-- | plugins/getaddrinfo.c | 303 | ||||
-rw-r--r-- | plugins/getaddrinfo.h | 68 | ||||
-rw-r--r-- | plugins/gethostbyname.c | 228 | ||||
-rw-r--r-- | plugins/gethostbyname.h | 103 | ||||
-rw-r--r-- | plugins/netutils.c | 83 | ||||
-rw-r--r-- | plugins/netutils.h | 13 | ||||
-rw-r--r-- | plugins/utils.c | 81 | ||||
-rw-r--r-- | plugins/utils.h | 8 |
9 files changed, 810 insertions, 130 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 2524e1ac..a884b451 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -14,14 +14,15 @@ EXTRA_PROGRAMS = check_mysql check_radius check_pgsql check_snmp check_hpjd \ check_swap check_fping check_ldap check_game check_dig \ check_nagios check_by_ssh check_dns check_nt -check_tcp_programs = check_ftp check_imap check_nntp check_pop +check_tcp_programs = check_ftp check_imap check_nntp check_pop check_udp2 -EXTRA_DIST = t utils.c netutils.c popen.c utils.h netutils.h popen.h common.h +EXTRA_DIST = t utils.c netutils.c popen.c utils.h netutils.h popen.h common.h \ + getaddrinfo.c getaddrinfo.h gethostbyname.c gethostbyname.h PLUGINHDRS = common.h config.h BASEOBJS = utils.o ../lib/libnagiosplug.a -NETOBJS = netutils.o $(BASEOBJS) +NETOBJS = netutils.o $(BASEOBJS) $(EXTRA_NETOBJS) NETLIBS = $(NETOBJS) $(SOCKETLIBS) TESTS_ENVIRONMENT = perl -I $(top_builddir) -I $(top_srcdir) @@ -36,27 +37,27 @@ AM_INSTALL_PROGRAM_FLAGS = @INSTALL_OPTS@ ############################################################################## # the actual targets -check_dig_LDADD = $(BASEOBJS) popen.o +check_dig_LDADD = $(NETLIBS) popen.o check_disk_LDADD = $(BASEOBJS) popen.o -check_dns_LDADD = $(BASEOBJS) popen.o +check_dns_LDADD = $(NETLIBS) popen.o check_dummy_LDADD = $(BASEOBJS) -check_fping_LDADD = $(BASEOBJS) popen.o +check_fping_LDADD = $(NETLIBS) popen.o check_game_LDADD = $(BASEOBJS) check_http_LDADD = $(NETLIBS) $(SSLLIBS) -check_hpjd_LDADD = $(BASEOBJS) popen.o +check_hpjd_LDADD = $(NETLIBS) popen.o check_ldap_LDADD = $(NETLIBS) $(LDAPLIBS) check_load_LDADD = $(BASEOBJS) popen.o check_mrtg_LDADD = $(BASEOBJS) check_mrtgtraf_LDADD = $(BASEOBJS) -check_mysql_LDADD = $(BASEOBJS) $(MYSQLLIBS) +check_mysql_LDADD = $(NETLIBS) $(MYSQLLIBS) check_nagios_LDADD = $(BASEOBJS) popen.o check_nt_LDADD = $(NETLIBS) check_nwstat_LDADD = $(NETLIBS) check_overcr_LDADD = $(NETLIBS) -check_pgsql_LDADD = $(BASEOBJS) $(PGLIBS) -check_ping_LDADD = $(BASEOBJS) popen.o +check_pgsql_LDADD = $(NETLIBS) $(PGLIBS) +check_ping_LDADD = $(NETLIBS) popen.o check_procs_LDADD = $(BASEOBJS) popen.o -check_radius_LDADD = $(BASEOBJS) $(RADIUSLIBS) +check_radius_LDADD = $(NETLIBS) $(RADIUSLIBS) check_real_LDADD = $(NETLIBS) check_snmp_LDADD = $(BASEOBJS) popen.o check_smtp_LDADD = $(NETLIBS) @@ -68,31 +69,31 @@ check_udp_LDADD = $(NETLIBS) check_ups_LDADD = $(NETLIBS) check_users_LDADD = $(BASEOBJS) popen.o check_vsz_LDADD = $(BASEOBJS) popen.o -check_by_ssh_LDADD = $(BASEOBJS) popen.o +check_by_ssh_LDADD = $(NETLIBS) popen.o negate_LDADD = $(BASEOBJS) popen.o urlize_LDADD = $(BASEOBJS) popen.o -check_dig_DEPENDENCIES = check_dig.c $(BASEOBJS) popen.o $(DEPLIBS) +check_dig_DEPENDENCIES = check_dig.c $(NETOBJS) popen.o $(DEPLIBS) check_disk_DEPENDENCIES = check_disk.c $(BASEOBJS) popen.o $(DEPLIBS) -check_dns_DEPENDENCIES = check_dns.c $(BASEOBJS) popen.o $(DEPLIBS) -check_dummy_DEPENDENCIES = check_dummy.c $(DEPLIBS) -check_fping_DEPENDENCIES = check_fping.c $(BASEOBJS) popen.o $(DEPLIBS) +check_dns_DEPENDENCIES = check_dns.c $(NETOBJS) popen.o $(DEPLIBS) +check_dummy_DEPENDENCIES = check_dummy.c $(DEPLIBS) +check_fping_DEPENDENCIES = check_fping.c $(NETOBJS) popen.o $(DEPLIBS) check_game_DEPENDENCIES = check_game.c $(DEPLIBS) check_http_DEPENDENCIES = check_http.c $(NETOBJS) $(DEPLIBS) -check_hpjd_DEPENDENCIES = check_hpjd.c $(BASEOBJS) popen.o $(DEPLIBS) +check_hpjd_DEPENDENCIES = check_hpjd.c $(NETOBJS) popen.o $(DEPLIBS) check_ldap_DEPENDENCIES = check_ldap.c $(NETOBJS) $(DEPLIBS) check_load_DEPENDENCIES = check_load.c $(BASEOBJS) popen.o $(DEPLIBS) -check_mrtg_DEPENDENCIES = check_mrtg.c $(DEPLIBS) -check_mrtgtraf_DEPENDENCIES = check_mrtgtraf.c $(DEPLIBS) -check_mysql_DEPENDENCIES = check_mysql.c $(DEPLIBS) +check_mrtg_DEPENDENCIES = check_mrtg.c $(DEPLIBS) +check_mrtgtraf_DEPENDENCIES = check_mrtgtraf.c $(DEPLIBS) +check_mysql_DEPENDENCIES = check_mysql.c $(NETOBJS) $(DEPLIBS) check_nagios_DEPENDENCIES = check_nagios.c $(BASEOBJS) popen.o $(DEPLIBS) check_nt_DEPENDENCIES = check_nt.c $(NETOBJS) $(DEPLIBS) check_nwstat_DEPENDENCIES = check_nwstat.c $(NETOBJS) $(DEPLIBS) check_overcr_DEPENDENCIES = check_overcr.c $(NETOBJS) $(DEPLIBS) -check_pgsql_DEPENDENCIES = check_pgsql.c $(DEPLIBS) -check_ping_DEPENDENCIES = check_ping.c $(BASEOBJS) popen.o $(DEPLIBS) +check_pgsql_DEPENDENCIES = check_pgsql.c $(NETOBJS) $(DEPLIBS) +check_ping_DEPENDENCIES = check_ping.c $(NETOBJS) popen.o $(DEPLIBS) check_procs_DEPENDENCIES = check_procs.c $(BASEOBJS) popen.o $(DEPLIBS) -check_radius_DEPENDENCIES = check_radius.c $(DEPLIBS) +check_radius_DEPENDENCIES = check_radius.c $(NETOBJS) $(DEPLIBS) check_real_DEPENDENCIES = check_real.c $(NETOBJS) $(DEPLIBS) check_snmp_DEPENDENCIES = check_snmp.c $(BASEOBJS) popen.o $(DEPLIBS) check_smtp_DEPENDENCIES = check_smtp.c $(NETOBJS) $(DEPLIBS) @@ -104,7 +105,7 @@ check_udp_DEPENDENCIES = check_udp.c $(NETOBJS) $(DEPLIBS) check_ups_DEPENDENCIES = check_ups.c $(NETOBJS) $(DEPLIBS) check_users_DEPENDENCIES = check_users.c $(BASEOBJS) popen.o $(DEPLIBS) check_vsz_DEPENDENCIES = check_vsz.c $(BASEOBJS) popen.o $(DEPLIBS) -check_by_ssh_DEPENDENCIES = check_by_ssh.c $(BASEOBJS) popen.o $(DEPLIBS) +check_by_ssh_DEPENDENCIES = check_by_ssh.c $(NETOBJS) popen.o $(DEPLIBS) negate_DEPENDENCIES = negate.c $(BASEOBJS) popen.o $(DEPLIBS) urlize_DEPENDENCIES = urlize.c $(BASEOBJS) popen.o $(DEPLIBS) @@ -117,6 +118,10 @@ utils.o: utils.c utils.h $(PLUGINHDRS) netutils.o: netutils.c netutils.h $(PLUGINHDRS) +getaddrinfo.o: getaddrinfo.h $(PLUGINHDRS) + +gethostbyname.o: gethostbyname.h $(PLUGINHDRS) + all-local: $(check_tcp_programs) $(check_tcp_programs): check_tcp diff --git a/plugins/getaddrinfo.c b/plugins/getaddrinfo.c new file mode 100644 index 00000000..12ac67d6 --- /dev/null +++ b/plugins/getaddrinfo.c @@ -0,0 +1,303 @@ +/* + * This file is part of libESMTP, a library for submission of RFC 2822 + * formatted electronic mail messages using the SMTP protocol described + * in RFC 2821. + * Modified by Jeremy T. Bouse for use in Nagios plugins + * + * Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* An emulation of the RFC 2553 / Posix getaddrinfo resolver interface. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* Need to turn off Posix features in glibc to build this */ +#undef _POSIX_C_SOURCE +#undef _XOPEN_SOURCE + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> + +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <netdb.h> + +#include "gethostbyname.h" +#include "getaddrinfo.h" + +static struct addrinfo * +dup_addrinfo (struct addrinfo *info, void *addr, size_t addrlen) +{ + struct addrinfo *ret; + + ret = malloc (sizeof (struct addrinfo)); + if (ret == NULL) + return NULL; + memcpy (ret, info, sizeof (struct addrinfo)); + ret->ai_addr = malloc (addrlen); + if (ret->ai_addr == NULL) + { + free (ret); + return NULL; + } + memcpy (ret->ai_addr, addr, addrlen); + ret->ai_addrlen = addrlen; + return ret; +} + +int +getaddrinfo (const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct hostent *hp; + struct servent *servent; + const char *socktype; + int port; + struct addrinfo hint, result; + struct addrinfo *ai, *sai, *eai; + struct ghbnctx ghbnctx; + char **addrs; + int code; + + memset (&result, 0, sizeof result); + + /* default for hints */ + if (hints == NULL) + { + memset (&hint, 0, sizeof hint); + hint.ai_family = PF_UNSPEC; + hints = &hint; + } + + result.ai_socktype = hints->ai_socktype; + + /* Note: maintain port in host byte order to make debugging easier */ + if (servname != NULL) { + if (isdigit (*servname)) + port = strtol (servname, NULL, 10); + else if ((servent = getservbyname (servname, socktype)) != NULL) + port = ntohs (servent->s_port); + else + return EAI_NONAME; + } + + /* if nodename == NULL refer to the local host for a client or any + for a server */ + if (nodename == NULL) + { + struct sockaddr_in sin; + + /* check protocol family is PF_UNSPEC or PF_INET - could try harder + for IPv6 but that's more code than I'm prepared to write */ + if (hints->ai_family == PF_UNSPEC || hints->ai_family == PF_INET) + result.ai_family = AF_INET; + else + return EAI_FAMILY; + + sin.sin_family = result.ai_family; + sin.sin_port = htons (port); + if (hints->ai_flags & AI_PASSIVE) + sin.sin_addr.s_addr = htonl (INADDR_ANY); + else + sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + /* Duplicate result and addr and return */ + *res = dup_addrinfo (&result, &sin, sizeof sin); + return (*res == NULL) ? EAI_MEMORY : 0; + } + + /* If AI_NUMERIC is specified, use inet_addr to translate numbers and + dots notation. */ + if (hints->ai_flags & AI_NUMERICHOST) + { + struct sockaddr_in sin; + + /* check protocol family is PF_UNSPEC or PF_INET */ + if (hints->ai_family == PF_UNSPEC || hints->ai_family == PF_INET) + result.ai_family = AF_INET; + else + return EAI_FAMILY; + + sin.sin_family = result.ai_family; + sin.sin_port = htons (port); + sin.sin_addr.s_addr = inet_addr (nodename); + /* Duplicate result and addr and return */ + *res = dup_addrinfo (&result, &sin, sizeof sin); + return (*res == NULL) ? EAI_MEMORY : 0; + } + + errno = 0; + hp = gethostbyname_ctx (nodename, &ghbnctx); + if (hp == NULL) + { + if (errno != 0) + { + free_ghbnctx (&ghbnctx); + return EAI_SYSTEM; + } + code = h_error_ctx (&ghbnctx); + switch (code) + { + case HOST_NOT_FOUND: code = EAI_NODATA; break; + case NO_DATA: code = EAI_NODATA; break; +#if defined(NO_ADDRESS) && NO_ADDRESS != NO_DATA + case NO_ADDRESS: code = EAI_NODATA; break; +#endif + case NO_RECOVERY: code = EAI_FAIL; break; + case TRY_AGAIN: code = EAI_AGAIN; break; + default: code = EAI_FAIL; break; + } + free_ghbnctx (&ghbnctx); + return code; + } + + /* Check that the address family is acceptable. + */ + switch (hp->h_addrtype) + { + case AF_INET: + if (!(hints->ai_family == PF_UNSPEC || hints->ai_family == PF_INET)) + goto eai_family; + break; +#ifdef USE_IPV6 + case AF_INET6: + if (!(hints->ai_family == PF_UNSPEC || hints->ai_family == PF_INET6)) + goto eai_family; + break; +#endif + default: + eai_family: + free_ghbnctx (&ghbnctx); + return EAI_FAMILY; + } + + /* For each element pointed to by hp, create an element in the + result linked list. */ + sai = eai = NULL; + for (addrs = hp->h_addr_list; *addrs != NULL; addrs++) + { + struct sockaddr sa; + size_t addrlen; + + sa.sa_family = hp->h_addrtype; + switch (hp->h_addrtype) + { + case AF_INET: + ((struct sockaddr_in *) &sa)->sin_port = htons (port); + memcpy (&((struct sockaddr_in *) &sa)->sin_addr, + *addrs, hp->h_length); + addrlen = sizeof (struct sockaddr_in); + break; +#ifdef USE_IPV6 + case AF_INET6: +# if SIN6_LEN + ((struct sockaddr_in6 *) &sa)->sin6_len = hp->h_length; +# endif + ((struct sockaddr_in6 *) &sa)->sin6_port = htons (port); + memcpy (&((struct sockaddr_in6 *) &sa)->sin6_addr, + *addrs, hp->h_length); + addrlen = sizeof (struct sockaddr_in6); + break; +#endif + default: + continue; + } + + result.ai_family = hp->h_addrtype; + ai = dup_addrinfo (&result, &sa, addrlen); + if (ai == NULL) + { + free_ghbnctx (&ghbnctx); + freeaddrinfo (sai); + return EAI_MEMORY; + } + if (sai == NULL) + sai = ai; + else + eai->ai_next = ai; + eai = ai; + } + + if (sai == NULL) + { + free_ghbnctx (&ghbnctx); + return EAI_NODATA; + } + + if (hints->ai_flags & AI_CANONNAME) + { + sai->ai_canonname = malloc (strlen (hp->h_name) + 1); + if (sai->ai_canonname == NULL) + { + free_ghbnctx (&ghbnctx); + freeaddrinfo (sai); + return EAI_MEMORY; + } + strcpy (sai->ai_canonname, hp->h_name); + } + + free_ghbnctx (&ghbnctx); + *res = sai; + return 0; +} + +void +freeaddrinfo (struct addrinfo *ai) +{ + struct addrinfo *next; + + while (ai != NULL) + { + next = ai->ai_next; + if (ai->ai_canonname != NULL) + free (ai->ai_canonname); + if (ai->ai_addr != NULL) + free (ai->ai_addr); + free (ai); + ai = next; + } +} + +const char * +gai_strerror (int ecode) +{ + static const char *eai_descr[] = + { + "no error", + "address family for nodename not supported", /* EAI_ADDRFAMILY */ + "temporary failure in name resolution", /* EAI_AGAIN */ + "invalid value for ai_flags", /* EAI_BADFLAGS */ + "non-recoverable failure in name resolution", /* EAI_FAIL */ + "ai_family not supported", /* EAI_FAMILY */ + "memory allocation failure", /* EAI_MEMORY */ + "no address associated with nodename", /* EAI_NODATA */ + "nodename nor servname provided, or not known", /* EAI_NONAME */ + "servname not supported for ai_socktype", /* EAI_SERVICE */ + "ai_socktype not supported", /* EAI_SOCKTYPE */ + "system error returned in errno", /* EAI_SYSTEM */ + }; + + if (ecode < 0 || ecode > (int) (sizeof eai_descr/ sizeof eai_descr[0])) + return "unknown error"; + return eai_descr[ecode]; +} diff --git a/plugins/getaddrinfo.h b/plugins/getaddrinfo.h new file mode 100644 index 00000000..5bcc8844 --- /dev/null +++ b/plugins/getaddrinfo.h @@ -0,0 +1,68 @@ +#ifndef _getaddrinfo_h +#define _getaddrinfo_h +/* + * This file is part of libESMTP, a library for submission of RFC 2822 + * formatted electronic mail messages using the SMTP protocol described + * in RFC 2821. + * Modified by Jeremy T. Bouse for use in Nagios plugins + * + * Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Structure and prototypes aken from RFC 2553 */ + +struct addrinfo + { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for nodename */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ + }; + +/* Supposed to be defined in <netdb.h> */ +#define AI_PASSIVE 1 /* Socket address is intended for `bind'. */ +#define AI_CANONNAME 2 /* Request for canonical name. */ +#define AI_NUMERICHOST 4 /* Don't use name resolution. */ + +/* Supposed to be defined in <netdb.h> */ +#define EAI_ADDRFAMILY 1 /* address family for nodename not supported */ +#define EAI_AGAIN 2 /* temporary failure in name resolution */ +#define EAI_BADFLAGS 3 /* invalid value for ai_flags */ +#define EAI_FAIL 4 /* non-recoverable failure in name resolution */ +#define EAI_FAMILY 5 /* ai_family not supported */ +#define EAI_MEMORY 6 /* memory allocation failure */ +#define EAI_NODATA 7 /* no address associated with nodename */ +#define EAI_NONAME 8 /* nodename nor servname provided, or not known */ +#define EAI_SERVICE 9 /* servname not supported for ai_socktype */ +#define EAI_SOCKTYPE 10 /* ai_socktype not supported */ +#define EAI_SYSTEM 11 /* system error returned in errno */ + +/* RFC 2553 / Posix resolver */ +int getaddrinfo (const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res); + +/* Free addrinfo structure and associated storage */ +void freeaddrinfo (struct addrinfo *ai); + +/* Convert error return from getaddrinfo() to string */ +const char *gai_strerror (int code); + +#endif diff --git a/plugins/gethostbyname.c b/plugins/gethostbyname.c new file mode 100644 index 00000000..d151606d --- /dev/null +++ b/plugins/gethostbyname.c @@ -0,0 +1,228 @@ +/* + * This file is a ghastly hack because nobody can agree on + * gethostbyname_r()'s prototype. + * + * Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#define _SVID_SOURCE 1 /* Need this to get gethostbyname_r() */ + +#include <assert.h> + +#include <stdlib.h> +#include <string.h> +#include <netdb.h> +#include <errno.h> + +#include "gethostbyname.h" + +#if HAVE_GETIPNODEBYNAME + +void +free_ghbnctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + if (ctx->hostent != NULL) + freehostent (ctx->hostent); +} + +struct hostent * +gethostbyname_ctx (const char *host, struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + memset (ctx, 0, sizeof (struct ghbnctx)); + ctx->hostent = getipnodebyname (host, AF_UNSPEC, AI_ADDRCONFIG, &ctx->h_err); + return ctx->hostent; +} + +int +h_error_ctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + return ctx->h_err; +} + +#elif HAVE_GETHOSTBYNAME_R == 6 + +void +free_ghbnctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + if (ctx->hostbuf != NULL) + free (ctx->hostbuf); +} + +struct hostent * +gethostbyname_ctx (const char *host, struct ghbnctx *ctx) +{ + struct hostent *hp; + char *tmp; + int err; + + assert (ctx != NULL); + + memset (ctx, 0, sizeof (struct ghbnctx)); + ctx->hostbuf_len = 2048; + if ((ctx->hostbuf = malloc (ctx->hostbuf_len)) == NULL) + { + errno = ENOMEM; + return NULL; + } + while ((err = gethostbyname_r (host, + &ctx->hostent, ctx->hostbuf, ctx->hostbuf_len, + &hp, &ctx->h_err)) == ERANGE) + { + ctx->hostbuf_len += 1024; + if ((tmp = realloc (ctx->hostbuf, ctx->hostbuf_len)) == NULL) + { + errno = ENOMEM; + return NULL; + } + ctx->hostbuf = tmp; + } + if (err != 0) + { + errno = err; + return NULL; + } + return hp; +} + +int +h_error_ctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + return ctx->h_err; +} + +#elif HAVE_GETHOSTBYNAME_R == 5 + +void +free_ghbnctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + if (ctx->hostbuf != NULL) + free (ctx->hostbuf); +} + +struct hostent * +gethostbyname_ctx (const char *host, struct ghbnctx *ctx) +{ + struct hostent *hp; + char *tmp; + + assert (ctx != NULL); + + memset (ctx, 0, sizeof (struct ghbnctx)); + ctx->hostbuf_len = 2048; + if ((ctx->hostbuf = malloc (ctx->hostbuf_len)) == NULL) + { + errno = ENOMEM; + return NULL; + } + while ((hp = gethostbyname_r (host, &ctx->hostent, + ctx->hostbuf, ctx->hostbuf_len, + &ctx->h_err)) == NULL && errno == ERANGE) + { + ctx->hostbuf_len += 1024; + if ((tmp = realloc (ctx->hostbuf, ctx->hostbuf_len)) == NULL) + { + errno = ENOMEM; + return NULL; + } + ctx->hostbuf = tmp; + } + return hp; +} + +int +h_error_ctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + return ctx->h_err; +} + +#elif HAVE_GETHOSTBYNAME_R == 3 + +void +free_ghbnctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + /* FIXME: does this need to do anything? */ +} + +struct hostent * +gethostbyname_ctx (const char *host, struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + if (!gethostbyname_r (host, &ctx->hostent, &ctx->hostent_data)) + { + ctx->h_err = h_errno; /* FIXME: is this correct? */ + return NULL; + } + return &ctx->hostent; +} + +int +h_error_ctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + return ctx->h_err; +} + +#else + +void +free_ghbnctx (struct ghbnctx *ctx __attribute__ ((unused))) +{ + assert (ctx != NULL); +} + +struct hostent * +gethostbyname_ctx (const char *host, struct ghbnctx *ctx) +{ + struct hostent *hp; + + hp = gethostbyname (host); + if (hp == NULL) + ctx->h_err = h_errno; + return hp; +} + +int +h_error_ctx (struct ghbnctx *ctx) +{ + assert (ctx != NULL); + + return ctx->h_err; +} + +#endif diff --git a/plugins/gethostbyname.h b/plugins/gethostbyname.h new file mode 100644 index 00000000..2b963997 --- /dev/null +++ b/plugins/gethostbyname.h @@ -0,0 +1,103 @@ +/* + * This file is a ghastly hack because nobody can agree on + * gethostbyname_r()'s prototype. + * + * Copyright (C) 2001,2002 Brian Stafford <brian@stafford.uklinux.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/************************************************************************* + Usage: + + #include <errno.h> + #include "gethostbyname.h" + + f () + { + struct ghbnctx ctx; + + errno = 0; + hp = gethostbyname_ctx (host, &ctx); + if (hp == NULL) + { + if (errno != 0) + handle_value_of_errno (errno); + else + handle_value_of_h_errno (h_error_ctx (&ctx)); + } + else + { + ... + } + free_ghbnctx (&ctx); + } + *************************************************************************/ + +#ifndef _gethostbyname_h +#define _gethostbyname_h + +#if HAVE_GETIPNODEBYNAME + +struct ghbnctx + { + int h_err; + struct hostent *hostent; + }; + +#elif HAVE_GETHOSTBYNAME_R == 6 + +struct ghbnctx + { + int h_err; + struct hostent hostent; + char *hostbuf; + size_t hostbuf_len; + }; + +#elif HAVE_GETHOSTBYNAME_R == 5 + +struct ghbnctx + { + int h_err; + struct hostent hostent; + char *hostbuf; + int hostbuf_len; + }; + +#elif HAVE_GETHOSTBYNAME_R == 3 + +struct ghbnctx + { + int h_err; + struct hostent_data hostent_data; + struct hostent hostent; + }; + +#else + +struct ghbnctx + { + int h_err; + }; + +#endif + +struct hostent *gethostbyname_ctx (const char *host, struct ghbnctx *ctx); +int h_error_ctx (struct ghbnctx *ctx); +void free_ghbnctx (struct ghbnctx *ctx); + +#endif + diff --git a/plugins/netutils.c b/plugins/netutils.c index c0e82dad..4234c436 100644 --- a/plugins/netutils.c +++ b/plugins/netutils.c @@ -29,22 +29,9 @@ * ****************************************************************************/ -#include "config.h" -#include "common.h" -#include <netinet/in.h> -#include <arpa/inet.h> +#include "netutils.h" -extern int socket_timeout; -RETSIGTYPE socket_timeout_alarm_handler (int); - -int process_tcp_request2 (char *, int, char *, char *, int); -int process_tcp_request (char *, int, char *, char *, int); -int process_udp_request (char *, int, char *, char *, int); -int process_request (char *, int, int, char *, char *, int); - -int my_tcp_connect (char *, int, int *); -int my_udp_connect (char *, int, int *); -int my_connect (char *, int, int *, int); +int socket_timeout = DEFAULT_SOCKET_TIMEOUT; /* handles socket timeouts */ void @@ -304,3 +291,69 @@ my_connect (char *host_name, int port, int *sd, int proto) return STATE_CRITICAL; } } + +int +is_host (char *address) +{ + if (is_addr (address) || is_hostname (address)) + return (TRUE); + + return (FALSE); +} + +int +is_addr (char *address) +{ +#ifdef USE_IPV6 + if (is_inet_addr (address) || is_inet6_addr (address)) +#else + if (is_inet_addr (address)) +#endif + return (TRUE); + + return (FALSE); +} + +int +resolve_host_or_addr (char *address, int family) +{ + struct addrinfo hints; + struct addrinfo *res; + int retval; + + memset (&hints, 0, sizeof (hints)); + hints.ai_family = family; + retval = getaddrinfo (address, NULL, &hints, &res); + + if (retval != 0) + return FALSE; + else { + freeaddrinfo (res); + return TRUE; + } +} + +int +is_inet_addr (char *address) +{ + return resolve_host_or_addr (address, AF_INET); +} + +#ifdef USE_IPV6 +int +is_inet6_addr (char *address) +{ + return resolve_host_or_addr (address, AF_INET6); +} +#endif + +int +is_hostname (char *s1) +{ +#ifdef USE_IPV6 + return resolve_host_or_addr (s1, AF_UNSPEC); +#else + return resolve_host_or_addr (s1, AF_INET); +#endif +} + diff --git a/plugins/netutils.h b/plugins/netutils.h index 3ea51663..6c8eed36 100644 --- a/plugins/netutils.h +++ b/plugins/netutils.h @@ -43,11 +43,20 @@ int process_tcp_request (char *address, int port, char *sbuffer, char *rbuffer, int rsize); int process_udp_request (char *address, int port, char *sbuffer, char *rbuffer, int rsize); -int process_request (char *address, int port, char *proto, char *sbuffer, +int process_request (char *address, int port, int proto, char *sbuffer, char *rbuffer, int rsize); int my_tcp_connect (char *address, int port, int *sd); int my_udp_connect (char *address, int port, int *sd); int my_connect (char *address, int port, int *sd, int proto); -int socket_timeout = DEFAULT_SOCKET_TIMEOUT; +int is_host (char *); +int is_addr (char *); +int resolve_host_or_addr (char *, int); +int is_inet_addr (char *); +#ifdef USE_IPV6 +int is_inet6_addr (char *); +#endif +int is_hostname (char *); + +extern int socket_timeout; diff --git a/plugins/utils.c b/plugins/utils.c index 7361323f..e204e238 100644 --- a/plugins/utils.c +++ b/plugins/utils.c @@ -27,15 +27,6 @@ void print_revision (const char *, const char *); void terminate (int, const char *fmt, ...); RETSIGTYPE timeout_alarm_handler (int); -int is_host (char *); -int is_addr (char *); -int resolve_host_or_addr (char *, int); -int is_inet_addr (char *); -#ifdef USE_IPV6 -int is_inet6_addr (char *); -#endif -int is_hostname (char *); - int is_integer (char *); int is_intpos (char *); int is_intneg (char *); @@ -171,78 +162,6 @@ timeout_alarm_handler (int signo) } int -is_host (char *address) -{ - if (is_addr (address) || is_hostname (address)) - return (TRUE); - - return (FALSE); -} - -int -is_addr (char *address) -{ -#ifdef USE_IPV6 - if (is_inet_addr (address) || is_inet6_addr (address)) -#else - if (is_inet_addr (address)) -#endif - return (TRUE); - - return (FALSE); -} - -int -resolve_host_or_addr (char *address, int family) -{ - struct addrinfo hints; - struct addrinfo *res; - int retval; - - memset (&hints, 0, sizeof (hints)); - hints.ai_family = family; - retval = getaddrinfo (address, NULL, &hints, &res); - - if (retval != 0) - return FALSE; - else { - freeaddrinfo (res); - return TRUE; - } -} - -int -is_inet_addr (char *address) -{ - return resolve_host_or_addr (address, AF_INET); -} - -#ifdef USE_IPV6 -int -is_inet6_addr (char *address) -{ - return resolve_host_or_addr (address, AF_INET6); -} -#endif - -/* from RFC-1035 - * - * The labels must follow the rules for ARPANET host names. They must - * start with a letter, end with a letter or digit, and have as interior - * characters only letters, digits, and hyphen. There are also some - * restrictions on the length. Labels must be 63 characters or less. */ - -int -is_hostname (char *s1) -{ -#ifdef USE_IPV6 - return resolve_host_or_addr (s1, AF_UNSPEC); -#else - return resolve_host_or_addr (s1, AF_INET); -#endif -} - -int is_numeric (char *number) { char tmp[1]; diff --git a/plugins/utils.h b/plugins/utils.h index 89ada6f0..43b612c1 100644 --- a/plugins/utils.h +++ b/plugins/utils.h @@ -27,14 +27,6 @@ int timeout_interval = DEFAULT_SOCKET_TIMEOUT; /* Test input types */ -int is_host (char *); -int is_addr (char *); -int is_inet_addr (char *); -#ifdef USE_IPV6 -int is_inet6_addr (char *); -#endif -int is_hostname (char *); - int is_integer (char *); int is_intpos (char *); int is_intneg (char *); |