[Nagiosplug-devel] LPD plugin (fwd)

slurn at verisign.com slurn at verisign.com
Mon Jan 6 16:46:01 CET 2003


Greetings, 

  Sourceforge isn't accepting mail from my ISP domain apparently.  I've
been trying to send this to the list for a couple of weeks.   I'm posting
from another address, but the reply-to address (slurn at pacbell.net) 
is the correct address to use for correspondance).

Contained within this message,  please find 
'check_lpd.c' and 'Makefile.in.diff'.

This work was based upon the nagios-plugins-1.3.0-beta2 release.

It is provided under GPL.

scott lurndal
(slurn at pacbell.net)

---------------------------[Begin check_lpd.c]---------------------------------

/******************************************************************************
 * CHECK_LPD.C
 *
 * Program: LPD/LPR protocol plugin for Nagios
 * License: GPL
 * Copyright (c) 2002 Scott Lurndal (slurn at pacbell.net)
 * 
 * Last Modified: $Date$
 *
 * Command line: check_lpr -h <host> [-p port] [-s source] [-q queue]
 *
 * Description:
 *
 * This plugin is for testing a lpd/lpr server.
 *
 * Modifications:
 *
 *
 *****************************************************************************/

#define PROGNAME "check_lpr"
#define REVISION "$Revision:$"

#include "config.h"
#include "common.h"
#include "netutils.h"
#include "utils.h"

/*
 * Global data
 */
static char *myname;			/* Name application invoked as */

static void print_help();
static void print_usage();

/**
 * process_arguments
 *
 *     This function will process the input arguments.
 * 
 * @param argc   The count of arguments in <i>argv</i>
 * @param argv   A Vector of character string arguments.
 * @param host   A pointer to a character pointer to which the hostname
 *               will be returned.
 * @param port   A pointer to a short to which the LPD port will be returned.
 * @param src    A pointer to a short to which the source port will be returned.
 * @param queue  A pointer to a character pointer to which the queue name
 *               will be returned.
 */
void
process_arguments(int argc, char **argv, char **host, 
		  short *port, short *src, char **queue)
{
    int c;

#define GETOPT_STR "hVH:p:s:q:"
#ifdef HAVE_GETOPT_H
    int option_index = 0;
    /* initialize the long option struct */
    static struct option longopts[] = {
	    {"help", no_argument, 0, 'h'},
	    {"version", no_argument, 0, 'V'},
	    {"host", required_argument, 0, 'H'},
	    {"port", required_argument, 0, 'p'},
	    {"source", required_argument, 0, 's'},
	    {"queue", required_argument, 0, 'q'},
	    {0, 0, 0, 0}
    };
#endif


    while (1) {
	char *start;
	unsigned long lport;

#ifdef HAVE_GETOPT_H
	c = getopt_long(argc, argv, GETOPT_STR,
			longopts, &option_index);
#else
	c = getopt(argc, argv, "+?" GETOPT_STR);
#endif

	if (c == -1 || c == EOF) {
	    break;
	}

	switch (c) {
	case 'h':
	    print_help ();
	    exit (STATE_OK);
	case 'V':
	    print_revision (PROGNAME, REVISION);
	    exit (STATE_OK);
	case 'H':
	    *host = optarg;
	    break;
	case 'p': 
	case 's':
	    lport = strtoul(optarg, &start, 0);
	    if ((*optarg == '\0')
	     || (*start != '\0')) {
		fprintf(stdout, "%s: Missing or invalid integer port\n",
				myname);
		exit(STATE_UNKNOWN);
	    }
	    if ((lport == 0)
	     || (lport > SHRT_MAX)) {
		fprintf(stdout, "%s: Port must be between 1 and %d\n", 
				myname, SHRT_MAX);
		exit(STATE_UNKNOWN);
	    }
	    if (c == 's') {
		if ((lport < 721)
		 || (lport > 731)) {
		    fprintf(stdout, "%s: 721 <= %d <= 731: port out of range\n",
			    myname, lport);
		}
		*src = (short)lport;
	    } else {
		*port = (short)lport;
	    }
	    break;
	default:
	    fprintf(stdout, "%s: Illegal option '%c'\n", myname, c);
	    exit(STATE_UNKNOWN);
	    break;
	}
    }
}

/**
 * print_help
 *
 *    This function is used to print the help message.
 */
static void
print_help ()
{
    print_revision (PROGNAME, REVISION);
    printf("Copyright (c) 2002 Scott Lurndal\n"
	     "License: GPL\n" "\n");
    print_usage ();
    printf ("\n"
	     "Options:\n"
	     "\t-H [--host] ... host\n"
	     "\t-p [--port] ... server lpd port\n"
	     "\t-s [--source] ... source port (default 731)\n"
	     "\t-q [--queue] ... LPD queue to check\n"
	     "\n");
}

/**
 * print_usage
 *
 *    This function is used to print the usage string in case of parameter
 *    error.
 *
 */
static void
print_usage ()
{
    printf("Usage: %s -H <host> [-p port] [-s source] [-q queue]\n", myname);
}

/**
 * perform_test
 *
 *    This function is responsible for testing the LPD daemon.  It will
 *    open a socket to the daemon and submit a 'return status on queue(short)'
 *    command with a queue name to the daemon and return the response.
 *
 *    Note that RFC1179-compliant daemons will require the source port
 *    to be in the range 721<=sourceport<=731 which will require that
 *    this function execute as a privileged user.
 *
 * @param host   The hostname to connect to
 * @param port   The port on <i>hostname</i> to connect to.
 * @param source The source port to bind the socket to.
 * @param queue  The queue name to test on the LPD daemon
 * @param buffer A buffer which will be used to return the response from
 *               the LPD daemon.
 * @param buflen The size, in bytes, of <i>buffer</i>
 * @returns The Nagios Status code for the test.
 */
static int
perform_test(char *host, short port, short source, char *queue, 
	     unsigned char *buffer, size_t buflen)
{
    struct hostent *hp;
    struct servent *sp;
    struct sockaddr_in addr;
    int    fd;
    int    diag;
    int    value;
    struct linger l;

    /*
     * Fetch host internet address information
     */
    hp = gethostbyname(host);
    if (hp == NULL) {
	fprintf(stdout, "%s: Unable to resolve host '%s': %s\n", 
		myname, host, strerror(errno));
	return STATE_UNKNOWN;
    }

    /*
     * Obtain a socket
     */
    fd = socket(PF_INET, SOCK_STREAM, 0);
    if (fd == -1) {
	fprintf(stdout, "%s: Unable to create socket: %s\n", 
		myname, strerror(errno));
	return STATE_UNKNOWN;
    }

    value = 1;
    diag = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
    if (diag == -1) {
	fprintf(stderr, "%s: Unable to set REUSEADDR: %s\n", 
		myname, strerror(errno));
	return STATE_UNKNOWN;
    }

    /*
     * Bind the socket to a privileged local source port which
     * must be in the range 721 -> 731 inclusive.
     */
    addr.sin_family = hp->h_addrtype;
    addr.sin_port = htons(source);
    addr.sin_addr.s_addr = INADDR_ANY;
    diag = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
    if (diag == -1) {
	fprintf(stdout, "%s: Unable to bind to source port %d: %s\n", 
		myname, source, strerror(errno));
	close(fd);
	return STATE_UNKNOWN;
    }

    /*
     * Connect to the LPD server
     */
    addr.sin_family = hp->h_addrtype;
    addr.sin_port = htons(port);
    memcpy((char *)&addr.sin_addr, *hp->h_addr_list, hp->h_length);
    diag = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
    if (diag == -1) {
	fprintf(stdout, "%s: Unable to connect to '%s:%d': %s\n", 
		myname, host, port, strerror(errno));
	close(fd);
	return STATE_CRITICAL;
    }

    /*
     * Send the inquiry string
     */
    diag = snprintf(buffer, buflen, "%c%s\n", 0x03, queue);
    if (diag > buflen) {
	fprintf(stdout, "%s: Queue name '%s' too large\n", myname, queue);
	close(fd);
	return STATE_UNKNOWN;
    }

    diag = send(fd, buffer, diag, 0);
    if (diag == -1) {
	fprintf(stdout, "%s: Unable to send to '%s:%d': %s\n",
		myname, host, port, strerror(errno));
	close(fd);
	return STATE_CRITICAL;
    }

    /*
     * Read the response
     */
    diag = recv(fd, buffer, buflen, 0);
    if (diag == -1) {
	fprintf(stdout, "%s: Unable to receive from '%s:%d': %s\n",
		myname, host, port, strerror(errno));
	close(fd);
	return STATE_CRITICAL;
    }

    /*
     * Make sure buffer is null-terminated and return it to the caller. 
     * (diag - 1 ensures that the newline is replaced with a null byte)
     */
    buffer[diag - 1] = '\0';
    if (!isprint(buffer[0])) {
	buffer[0] = ' ';	/* LPRng returns command in first byte */
    }

    /*
     * Make sure we don't linger during the close on the socket.  Just flush
     * any remaining receive or transmit data.
     */
    l.l_onoff = 0;
    l.l_linger = 0;
    diag = setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l));
    if (diag == -1) {
	fprintf(stdout, "%s: Unable to set linger to zero on socket: %s\n",
		myname, strerror(errno));
	close(fd);
	return STATE_CRITICAL;
    }

    close(fd);
    return STATE_OK;
}

/**
 *  check_lpd
 *  
 *     This Nagios plugin is responsible for determining the status
 *     of the LPD service on a host.  
 *
 *     The caller must specify the hostname, and optionally may 
 *     specify the LPD port on the given hostname as well as the 
 *     source port (in the range 721 <= source <= 731).  The default
 *     host port is 515 (per RFC1179), while the default source 
 *     port is 730. 
 *
 *     Note that binding to source port in the designated range requires
 *     privileges on unix systems.  
 *
 *     So long as the LPD daemon returns a response, the service is considered
 *     STATUS_OK.   Any command-line errors (bad hostname, port etc.) will 
 *     be considered STATUS_UNKNOWN, while connect, send and receive failures
 *     will be considered STATUS_CRITICAL.   The actual response returned
 *     from the LPD daemon will be included in the status message.
 *
 *     A 'Return Status on Queue' operation is used to communicate with the
 *     LPD daemon;  the caller may specify a queue name using the -q 
 *     argument.  The default queue name is 'pr2'.
 *
 * @param argc	The count of entries in the argument vector <i>argv</i>
 * @param argv  A Vector of arguments provided to this application.
 * @param envp  A Vector of Environment Strings
 * @returns  A Nagios Status code.
 */
int
main (int argc, char **argv, char **envp)
{
    struct timeval start;
    struct timeval end;
    suseconds_t	usec;
    short	port = 515; 
    short	source = 730;
    char        *host = "localhost";
    char        *queue = "pr2";
    unsigned char response[256];
    int		result;
    double	responsetime;

    myname = argv[0];		/* Save name invoked as */
    strcpy(response, "No Response");

    process_arguments(argc, argv, &host, &port, &source, &queue);

    gettimeofday(&start, NULL);

    result = perform_test(host, port, source, queue, 
			  response, sizeof(response));

    responsetime = delta_time(start);

    /* print out the result */
    if (result == STATE_OK) {
	printf("LPD: %s (%.3f second response)\n",
		response, responsetime);
    }

    return result;
}

/* vim: sw=4 sts=4 sta ts=8:
 */

-----------------------------[end check_lpd.c]---------------------------------

-----------------------------[begin Makefile.in.diff]--------------------------
$ diff -u Makefile.in.orig Makefile.in 
--- Makefile.in.orig    2002-12-19 17:31:44.000000000 -0800
+++ Makefile.in 2002-12-19 17:35:32.000000000 -0800
@@ -138,7 +138,7 @@
        check_nagios check_by_ssh check_dns
 
 
-check_tcp_programs = check_ftp check_imap check_nntp check_pop
+check_tcp_programs = check_ftp check_imap check_nntp check_pop check_lpd
 
 EXTRA_DIST = t utils.c netutils.c popen.c getopt.h getopt.c getopt1.c \
        snprintf.c getloadavg.c
@@ -169,6 +169,7 @@
 check_hpjd_LDADD = $(BASEOBJS) popen.o
 check_ldap_LDADD = $(NETLIBS) $(LDAPLIBS)
 check_load_LDADD = $(BASEOBJS) popen.o
+check_lpd_LDADD = $(BASEOBJS)
 check_mrtg_LDADD = $(BASEOBJS)
 check_mrtgtraf_LDADD = $(BASEOBJS)
 check_mysql_LDADD = $(BASEOBJS) $(MYSQLLIBS)
@@ -204,6 +205,7 @@
 check_hpjd_DEPENDENCIES = check_hpjd.c $(BASEOBJS) popen.o $(DEPLIBS)
 check_ldap_DEPENDENCIES = check_ldap.c $(NETOBJS) $(DEPLIBS)
 check_load_DEPENDENCIES = check_load.c $(BASEOBJS) popen.o $(DEPLIBS)
+check_lpd_DEPENDENCIES = check_lpd.c $(BASEOBJS)
 check_mrtg_DEPENDENCIES = check_mrtg.c  $(DEPLIBS)
 check_mrtgtraf_DEPENDENCIES = check_mrtgtraf.c  $(DEPLIBS)
 check_mysql_DEPENDENCIES = check_mysql.c  $(DEPLIBS)
@@ -288,6 +290,9 @@
 check_load_SOURCES = check_load.c
 check_load_OBJECTS =  check_load.o
 check_load_LDFLAGS = 
+check_lpd_SOURCES = check_lpd.c
+check_lpd_OBJECTS = check_lpd.o
+check_lpd_LDFLAGS = 
 check_mrtg_SOURCES = check_mrtg.c
 check_mrtg_OBJECTS =  check_mrtg.o
 check_mrtg_LDFLAGS = 
@@ -352,8 +357,8 @@
 
 TAR = gtar
 GZIP_ENV = --best
-SOURCES = check_mysql.c check_radius.c check_pgsql.c check_snmp.c check_hpjd.c check_swap.c check_fping.c check_ldap.c check_game.c check_dig.c check_nagios.c check_by_ssh.c check_dns.c check_disk.c check_dummy.c check_http.c check_load.c check_mrtg.c check_mrtgtraf.c check_nwstat.c check_overcr.c check_ping.c check_procs.c check_real.c check_smtp.c check_ssh.c check_tcp.c check_time.c check_udp.c check_ups.c check_users.c check_vsz.c negate.c urlize.c
-OBJECTS = check_mysql.o check_radius.o check_pgsql.o check_snmp.o check_hpjd.o check_swap.o check_fping.o check_ldap.o check_game.o check_dig.o check_nagios.o check_by_ssh.o check_dns.o check_disk.o check_dummy.o check_http.o check_load.o check_mrtg.o check_mrtgtraf.o check_nwstat.o check_overcr.o check_ping.o check_procs.o check_real.o check_smtp.o check_ssh.o check_tcp.o check_time.o check_udp.o check_ups.o check_users.o check_vsz.o negate.o urlize.o
+SOURCES = check_mysql.c check_radius.c check_pgsql.c check_snmp.c check_hpjd.c check_swap.c check_fping.c check_ldap.c check_game.c check_dig.c check_nagios.c check_by_ssh.c check_dns.c check_disk.c check_dummy.c check_http.c check_load.c check_mrtg.c check_mrtgtraf.c check_nwstat.c check_overcr.c check_ping.c check_procs.c check_real.c check_smtp.c check_ssh.c check_tcp.c check_time.c check_udp.c check_ups.c check_users.c check_vsz.c negate.c urlize.c check_lpd.c
+OBJECTS = check_mysql.o check_radius.o check_pgsql.o check_snmp.o check_hpjd.o check_swap.o check_fping.o check_ldap.o check_game.o check_dig.o check_nagios.o check_by_ssh.o check_dns.o check_disk.o check_dummy.o check_http.o check_load.o check_mrtg.o check_mrtgtraf.o check_nwstat.o check_overcr.o check_ping.o check_procs.o check_real.o check_smtp.o check_ssh.o check_tcp.o check_time.o check_udp.o check_ups.o check_users.o check_vsz.o negate.o urlize.o check_lpd.o
 
 all: all-redirect
 .SUFFIXES:
@@ -565,6 +570,10 @@
        @rm -f check_ldap
        $(LINK) $(check_ldap_LDFLAGS) $(check_ldap_OBJECTS) $(check_ldap_LDADD) $(LIBS)
 
+check_lpd: $(check_lpd_OBJECTS) $(check_lpd_DEPENDENCIES)
+       @rm -f check_lpd
+       $(LINK) $(check_lpd_LDFLAGS) $(check_lpd_OBJECTS) $(LIBS)
+
 check_game: $(check_game_OBJECTS) $(check_game_DEPENDENCIES)
        @rm -f check_game
        $(LINK) $(check_game_LDFLAGS) $(check_game_OBJECTS) $(check_game_LDADD) $(LIBS)

-------------------------[end Makefile.in.diff]---------------------------------





More information about the Devel mailing list