Blame apps/snmptrapd_log.c

Packit fcad23
/*
Packit fcad23
 * snmptrapd_log.c - format SNMP trap information for logging
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
/*****************************************************************
Packit fcad23
	Copyright 1989, 1991, 1992 by Carnegie Mellon University
Packit fcad23
Packit fcad23
                      All Rights Reserved
Packit fcad23
Packit fcad23
Permission to use, copy, modify, and distribute this software and its
Packit fcad23
documentation for any purpose and without fee is hereby granted,
Packit fcad23
provided that the above copyright notice appear in all copies and that
Packit fcad23
both that copyright notice and this permission notice appear in
Packit fcad23
supporting documentation, and that the name of CMU not be
Packit fcad23
used in advertising or publicity pertaining to distribution of the
Packit fcad23
software without specific, written prior permission.
Packit fcad23
Packit fcad23
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
Packit fcad23
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
Packit fcad23
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
Packit fcad23
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Packit fcad23
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
Packit fcad23
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit fcad23
SOFTWARE.
Packit fcad23
******************************************************************/
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
Packit fcad23
#if HAVE_STDLIB_H
Packit fcad23
#include <stdlib.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
#include <unistd.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_STRING_H
Packit fcad23
#include <string.h>
Packit fcad23
#else
Packit fcad23
#include <strings.h>
Packit fcad23
#endif
Packit fcad23
#include <sys/types.h>
Packit fcad23
#if HAVE_SYS_WAIT_H
Packit fcad23
#include <sys/wait.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_SOCKET_H
Packit fcad23
#include <sys/socket.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_SOCKIO_H
Packit fcad23
#include <sys/sockio.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETINET_IN_H
Packit fcad23
#include <netinet/in.h>
Packit fcad23
#endif
Packit fcad23
#include <stdio.h>
Packit fcad23
#include <ctype.h>
Packit fcad23
#if !defined(mingw32) && defined(HAVE_SYS_TIME_H)
Packit fcad23
# include <sys/time.h>
Packit fcad23
# if TIME_WITH_SYS_TIME
Packit fcad23
#  include <time.h>
Packit fcad23
# endif
Packit fcad23
#else
Packit fcad23
# include <time.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_SELECT_H
Packit fcad23
#include <sys/select.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_PARAM_H
Packit fcad23
#include <sys/param.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYSLOG_H
Packit fcad23
#include <syslog.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_SYS_IOCTL_H
Packit fcad23
#include <sys/ioctl.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NET_IF_H
Packit fcad23
#include <net/if.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_NETDB_H
Packit fcad23
#include <netdb.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_ARPA_INET_H
Packit fcad23
#include <arpa/inet.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_FCNTL_H
Packit fcad23
#include <fcntl.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-includes.h>
Packit fcad23
#include "snmptrapd_handlers.h"
Packit fcad23
#include "snmptrapd_log.h"
Packit fcad23
Packit fcad23
Packit fcad23
#ifndef BSD4_3
Packit fcad23
#define BSD4_2
Packit fcad23
#endif
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * These flags mark undefined values in the options structure 
Packit fcad23
 */
Packit fcad23
#define UNDEF_CMD '*'
Packit fcad23
#define UNDEF_PRECISION -1
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * This structure holds the options for a single format command 
Packit fcad23
 */
Packit fcad23
typedef struct {
Packit fcad23
    char            cmd;        /* the format command itself */
Packit fcad23
    size_t          width;      /* the field's minimum width */
Packit fcad23
    int             precision;  /* the field's precision */
Packit fcad23
    int             left_justify;       /* if true, left justify this field */
Packit fcad23
    int             alt_format; /* if true, display in alternate format */
Packit fcad23
    int             leading_zeroes;     /* if true, display with leading zeroes */
Packit fcad23
} options_type;
Packit fcad23
Packit fcad23
char            separator[32];
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * These symbols define the characters that the parser recognizes.
Packit fcad23
 * The rather odd choice of symbols comes from an attempt to avoid
Packit fcad23
 * colliding with the ones that printf uses, so that someone could add
Packit fcad23
 * printf functionality to this code and turn it into a library
Packit fcad23
 * routine in the future.  
Packit fcad23
 */
Packit fcad23
typedef enum {
Packit fcad23
    CHR_FMT_DELIM = '%',        /* starts a format command */
Packit fcad23
    CHR_LEFT_JUST = '-',        /* left justify */
Packit fcad23
    CHR_LEAD_ZERO = '0',        /* use leading zeroes */
Packit fcad23
    CHR_ALT_FORM = '#',         /* use alternate format */
Packit fcad23
    CHR_FIELD_SEP = '.',        /* separates width and precision fields */
Packit fcad23
Packit fcad23
    /* Date / Time Information */
Packit fcad23
    CHR_CUR_TIME = 't',         /* current time, Unix format */
Packit fcad23
    CHR_CUR_YEAR = 'y',         /* current year */
Packit fcad23
    CHR_CUR_MONTH = 'm',        /* current month */
Packit fcad23
    CHR_CUR_MDAY = 'l',         /* current day of month */
Packit fcad23
    CHR_CUR_HOUR = 'h',         /* current hour */
Packit fcad23
    CHR_CUR_MIN = 'j',          /* current minute */
Packit fcad23
    CHR_CUR_SEC = 'k',          /* current second */
Packit fcad23
    CHR_UP_TIME = 'T',          /* uptime, Unix format */
Packit fcad23
    CHR_UP_YEAR = 'Y',          /* uptime year */
Packit fcad23
    CHR_UP_MONTH = 'M',         /* uptime month */
Packit fcad23
    CHR_UP_MDAY = 'L',          /* uptime day of month */
Packit fcad23
    CHR_UP_HOUR = 'H',          /* uptime hour */
Packit fcad23
    CHR_UP_MIN = 'J',           /* uptime minute */
Packit fcad23
    CHR_UP_SEC = 'K',           /* uptime second */
Packit fcad23
Packit fcad23
    /* transport information */
Packit fcad23
    CHR_AGENT_IP = 'a',         /* agent's IP address */
Packit fcad23
    CHR_AGENT_NAME = 'A',       /* agent's host name if available */
Packit fcad23
Packit fcad23
    /* authentication information */
Packit fcad23
    CHR_SNMP_VERSION = 's',     /* SNMP Version Number */
Packit fcad23
    CHR_SNMP_SECMOD  = 'S',     /* SNMPv3 Security Model Version Number */
Packit fcad23
    CHR_SNMP_USER = 'u',        /* SNMPv3 secName or v1/v2c community */
Packit fcad23
    CHR_TRAP_CONTEXTID = 'E',   /* SNMPv3 context engineID if available */
Packit fcad23
Packit fcad23
    /* PDU information */
Packit fcad23
    CHR_PDU_IP = 'b',           /* PDU's IP address */
Packit fcad23
    CHR_PDU_NAME = 'B',         /* PDU's host name if available */
Packit fcad23
    CHR_PDU_ENT = 'N',          /* PDU's enterprise string */
Packit fcad23
    CHR_PDU_WRAP = 'P',         /* PDU's wrapper info (community, security) */
Packit fcad23
    CHR_TRAP_NUM = 'w',         /* trap number */
Packit fcad23
    CHR_TRAP_DESC = 'W',        /* trap's description (textual) */
Packit fcad23
    CHR_TRAP_STYPE = 'q',       /* trap's subtype */
Packit fcad23
    CHR_TRAP_VARSEP = 'V',      /* character (or string) to separate variables */
Packit fcad23
    CHR_TRAP_VARS = 'v'        /* tab-separated list of trap's variables */
Packit fcad23
Packit fcad23
} parse_chr_type;
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * These symbols define the states for the parser's state machine 
Packit fcad23
 */
Packit fcad23
typedef enum {
Packit fcad23
    PARSE_NORMAL,               /* looking for next character */
Packit fcad23
    PARSE_BACKSLASH,            /* saw a backslash */
Packit fcad23
    PARSE_IN_FORMAT,            /* saw a % sign, in a format command */
Packit fcad23
    PARSE_GET_WIDTH,            /* getting field width */
Packit fcad23
    PARSE_GET_PRECISION,        /* getting field precision */
Packit fcad23
    PARSE_GET_SEPARATOR         /* getting field separator */
Packit fcad23
} parse_state_type;
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * macros 
Packit fcad23
 */
Packit fcad23
Packit fcad23
#define is_cur_time_cmd(chr) ((((chr) == CHR_CUR_TIME)     \
Packit fcad23
			       || ((chr) == CHR_CUR_YEAR)  \
Packit fcad23
			       || ((chr) == CHR_CUR_MONTH) \
Packit fcad23
			       || ((chr) == CHR_CUR_MDAY)  \
Packit fcad23
			       || ((chr) == CHR_CUR_HOUR)  \
Packit fcad23
			       || ((chr) == CHR_CUR_MIN)   \
Packit fcad23
			       || ((chr) == CHR_CUR_SEC)) ? TRUE : FALSE)
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Returns true if the character is a format command that outputs
Packit fcad23
      * some field that deals with the current time.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    chr - character to check
Packit fcad23
      */
Packit fcad23
Packit fcad23
#define is_up_time_cmd(chr) ((((chr) == CHR_UP_TIME)     \
Packit fcad23
			      || ((chr) == CHR_UP_YEAR)  \
Packit fcad23
			      || ((chr) == CHR_UP_MONTH) \
Packit fcad23
			      || ((chr) == CHR_UP_MDAY)  \
Packit fcad23
			      || ((chr) == CHR_UP_HOUR)  \
Packit fcad23
			      || ((chr) == CHR_UP_MIN)   \
Packit fcad23
			      || ((chr) == CHR_UP_SEC)) ? TRUE : FALSE)
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Returns true if the character is a format command that outputs
Packit fcad23
      * some field that deals with up-time.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    chr - character to check
Packit fcad23
      */
Packit fcad23
Packit fcad23
#define is_agent_cmd(chr) ((((chr) == CHR_AGENT_IP) \
Packit fcad23
			    || ((chr) == CHR_AGENT_NAME)) ? TRUE : FALSE)
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Returns true if the character outputs information about the
Packit fcad23
      * agent.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    chr - the character to check
Packit fcad23
      */
Packit fcad23
Packit fcad23
#define is_pdu_ip_cmd(chr) ((((chr) == CHR_PDU_IP)   \
Packit fcad23
			  || ((chr) == CHR_PDU_NAME)) ? TRUE : FALSE)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Returns true if the character outputs information about the SNMP
Packit fcad23
      *      authentication information
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    chr - the character to check
Packit fcad23
      */
Packit fcad23
Packit fcad23
#define is_auth_cmd(chr) ((((chr) == CHR_SNMP_VERSION       \
Packit fcad23
                            || (chr) == CHR_SNMP_SECMOD     \
Packit fcad23
                            || (chr) == CHR_SNMP_USER)) ? TRUE : FALSE)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Returns true if the character outputs information about the PDU's
Packit fcad23
      * host name or IP address.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    chr - the character to check
Packit fcad23
      */
Packit fcad23
Packit fcad23
#define is_trap_cmd(chr) ((((chr) == CHR_TRAP_NUM)      \
Packit fcad23
			   || ((chr) == CHR_TRAP_DESC)  \
Packit fcad23
			   || ((chr) == CHR_TRAP_STYPE) \
Packit fcad23
			   || ((chr) == CHR_TRAP_VARS)) ? TRUE : FALSE)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Returns true if the character outputs information about the trap.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    chr - the character to check
Packit fcad23
      */
Packit fcad23
Packit fcad23
#define is_fmt_cmd(chr) ((is_cur_time_cmd (chr)     \
Packit fcad23
			  || is_up_time_cmd (chr)   \
Packit fcad23
			  || is_auth_cmd (chr)   \
Packit fcad23
			  || is_agent_cmd (chr)     \
Packit fcad23
			  || is_pdu_ip_cmd (chr)    \
Packit fcad23
                          || ((chr) == CHR_PDU_ENT) \
Packit fcad23
                          || ((chr) == CHR_TRAP_CONTEXTID) \
Packit fcad23
                          || ((chr) == CHR_PDU_WRAP) \
Packit fcad23
			  || is_trap_cmd (chr)) ? TRUE : FALSE)
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Returns true if the character is a format command.
Packit fcad23
      * 
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    chr - character to check
Packit fcad23
      */
Packit fcad23
Packit fcad23
#define is_numeric_cmd(chr) ((is_cur_time_cmd(chr)   \
Packit fcad23
			      || is_up_time_cmd(chr) \
Packit fcad23
			      || (chr) == CHR_TRAP_NUM) ? TRUE : FALSE)
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Returns true if this is a numeric format command.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    chr - character to check
Packit fcad23
      */
Packit fcad23
Packit fcad23
#define reference(var) ((var) == (var))
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Some compiler options will tell the compiler to be picky and
Packit fcad23
      * warn you if you pass a parameter to a function but don't use it.
Packit fcad23
      * This macro lets you reference a parameter so that the compiler won't
Packit fcad23
      * generate the warning. It has no other effect.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    var - the parameter to reference
Packit fcad23
      */
Packit fcad23
Packit fcad23
static void
Packit fcad23
init_options(options_type * options)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Initialize a structure that contains the option settings for
Packit fcad23
      * a format command.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    options - points to the structure to initialize
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    /*
Packit fcad23
     * initialize the structure's fields 
Packit fcad23
     */
Packit fcad23
    options->cmd = '*';
Packit fcad23
    options->width = 0;
Packit fcad23
    options->precision = UNDEF_PRECISION;
Packit fcad23
    options->left_justify = FALSE;
Packit fcad23
    options->alt_format = FALSE;
Packit fcad23
    options->leading_zeroes = FALSE;
Packit fcad23
    return;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
static int
Packit fcad23
realloc_output_temp_bfr(u_char ** buf, size_t * buf_len, size_t * out_len,
Packit fcad23
                        int allow_realloc,
Packit fcad23
                        u_char ** temp_buf, options_type * options)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Append the contents of the temporary buffer to the specified
Packit fcad23
      * buffer using the correct justification, leading zeroes, width,
Packit fcad23
      * precision, and other characteristics specified in the options
Packit fcad23
      * structure.
Packit fcad23
      *
Packit fcad23
      *    buf, buf_len, out_len, allow_realloc - standard relocatable
Packit fcad23
      *                                           buffer parameters
Packit fcad23
      *    temp_buf - pointer to string to append onto output buffer.  THIS
Packit fcad23
      *               STRING IS free()d BY THIS FUNCTION.
Packit fcad23
      *    options  - what options to use when appending string
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    size_t          temp_len;   /* length of temporary buffer */
Packit fcad23
    size_t          temp_to_write;      /* # of chars to write from temp bfr */
Packit fcad23
    size_t          char_to_write;      /* # of other chars to write */
Packit fcad23
    size_t          zeroes_to_write;    /* fill to precision with zeroes for numbers */
Packit fcad23
Packit fcad23
    if (temp_buf == NULL || *temp_buf == NULL) {
Packit fcad23
        return 1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Figure out how many characters are in the temporary buffer now,
Packit fcad23
     * and how many of them we'll write.
Packit fcad23
     */
Packit fcad23
    temp_len = strlen((char *) *temp_buf);
Packit fcad23
    temp_to_write = temp_len;
Packit fcad23
Packit fcad23
    if (options->precision != UNDEF_PRECISION &&
Packit fcad23
        temp_to_write > (size_t)options->precision) {
Packit fcad23
        temp_to_write = options->precision;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Handle leading characters.  
Packit fcad23
     */
Packit fcad23
    if ((!options->left_justify) && (temp_to_write < options->width)) {
Packit fcad23
        zeroes_to_write = options->precision - temp_to_write;
Packit fcad23
        if (!is_numeric_cmd(options->cmd)) {
Packit fcad23
            zeroes_to_write = 0;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        for (char_to_write = options->width - temp_to_write;
Packit fcad23
             char_to_write > 0; char_to_write--) {
Packit fcad23
            if ((*out_len + 1) >= *buf_len) {
Packit fcad23
                if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                    *(*buf + *out_len) = '\0';
Packit fcad23
                    free(*temp_buf);
Packit fcad23
                    return 0;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
            if (options->leading_zeroes || zeroes_to_write-- > 0) {
Packit fcad23
                *(*buf + *out_len) = '0';
Packit fcad23
            } else {
Packit fcad23
                *(*buf + *out_len) = ' ';
Packit fcad23
            }
Packit fcad23
            (*out_len)++;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Truncate the temporary buffer and append its contents.  
Packit fcad23
     */
Packit fcad23
    *(*temp_buf + temp_to_write) = '\0';
Packit fcad23
    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, *temp_buf)) {
Packit fcad23
        free(*temp_buf);
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Handle trailing characters.  
Packit fcad23
     */
Packit fcad23
    if ((options->left_justify) && (temp_to_write < options->width)) {
Packit fcad23
        for (char_to_write = options->width - temp_to_write;
Packit fcad23
             char_to_write > 0; char_to_write--) {
Packit fcad23
            if ((*out_len + 1) >= *buf_len) {
Packit fcad23
                if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                    *(*buf + *out_len) = '\0';
Packit fcad23
                    free(*temp_buf);
Packit fcad23
                    return 0;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
            *(*buf + *out_len) = '0';
Packit fcad23
            (*out_len)++;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Slap on a trailing \0 for good measure.  
Packit fcad23
     */
Packit fcad23
Packit fcad23
    *(*buf + *out_len) = '\0';
Packit fcad23
    free(*temp_buf);
Packit fcad23
    *temp_buf = NULL;
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
static int
Packit fcad23
realloc_handle_time_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
Packit fcad23
                        int allow_realloc,
Packit fcad23
                        options_type * options, netsnmp_pdu *pdu)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Handle a format command that deals with the current or up-time.
Packit fcad23
      * Append the correct time information to the buffer subject to the
Packit fcad23
      * buffer's length limit.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    buf, buf_len, out_len, allow_realloc - standard relocatable
Packit fcad23
      *                                           buffer parameters
Packit fcad23
      *    options - options governing how to write the field
Packit fcad23
      *    pdu     - information about this trap
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    time_t          time_val;   /* the time value to output */
Packit fcad23
    unsigned long   time_ul;    /* u_long time/timeticks */
Packit fcad23
    struct tm      *parsed_time;        /* parsed version of current time */
Packit fcad23
    char           *safe_bfr = NULL;
Packit fcad23
    char            fmt_cmd = options->cmd;     /* the format command to use */
Packit fcad23
Packit fcad23
    if ((safe_bfr = (char *) calloc(30, 1)) == NULL) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Get the time field to output.  
Packit fcad23
     */
Packit fcad23
    if (is_up_time_cmd(fmt_cmd)) {
Packit fcad23
        time_ul = pdu->time;
Packit fcad23
    } else {
Packit fcad23
        /*
Packit fcad23
         * Note: a time_t is a signed long.  
Packit fcad23
         */
Packit fcad23
        time(&time_val);
Packit fcad23
        time_ul = (unsigned long) time_val;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Handle output in Unix time format.  
Packit fcad23
     */
Packit fcad23
    if (fmt_cmd == CHR_CUR_TIME) {
Packit fcad23
        sprintf(safe_bfr, "%lu", time_ul);
Packit fcad23
    } else if (fmt_cmd == CHR_UP_TIME && !options->alt_format) {
Packit fcad23
        sprintf(safe_bfr, "%lu", time_ul);
Packit fcad23
    } else if (fmt_cmd == CHR_UP_TIME) {
Packit fcad23
        unsigned int    centisecs, seconds, minutes, hours, days;
Packit fcad23
Packit fcad23
        centisecs = time_ul % 100;
Packit fcad23
        time_ul /= 100;
Packit fcad23
        days = time_ul / (60 * 60 * 24);
Packit fcad23
        time_ul %= (60 * 60 * 24);
Packit fcad23
Packit fcad23
        hours = time_ul / (60 * 60);
Packit fcad23
        time_ul %= (60 * 60);
Packit fcad23
Packit fcad23
        minutes = time_ul / 60;
Packit fcad23
        seconds = time_ul % 60;
Packit fcad23
Packit fcad23
        switch (days) {
Packit fcad23
        case 0:
Packit fcad23
            sprintf(safe_bfr, "%u:%02u:%02u.%02u",
Packit fcad23
                    hours, minutes, seconds, centisecs);
Packit fcad23
            break;
Packit fcad23
        case 1:
Packit fcad23
            sprintf(safe_bfr, "1 day, %u:%02u:%02u.%02u",
Packit fcad23
                    hours, minutes, seconds, centisecs);
Packit fcad23
            break;
Packit fcad23
        default:
Packit fcad23
            sprintf(safe_bfr, "%u days, %u:%02u:%02u.%02u",
Packit fcad23
                    days, hours, minutes, seconds, centisecs);
Packit fcad23
        }
Packit fcad23
    } else {
Packit fcad23
        /*
Packit fcad23
         * Handle other time fields.  
Packit fcad23
         */
Packit fcad23
Packit fcad23
        if (options->alt_format) {
Packit fcad23
            parsed_time = gmtime(&time_val);
Packit fcad23
        } else {
Packit fcad23
            parsed_time = localtime(&time_val);
Packit fcad23
        }
Packit fcad23
Packit fcad23
        switch (fmt_cmd) {
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * Output year. The year field is unusual: if there's a restriction 
Packit fcad23
             * on precision, we want to truncate from the left of the number,
Packit fcad23
             * not the right, so someone printing the year 1972 with 2 digit 
Packit fcad23
             * precision gets "72" not "19".
Packit fcad23
             */
Packit fcad23
        case CHR_CUR_YEAR:
Packit fcad23
        case CHR_UP_YEAR:
Packit fcad23
            sprintf(safe_bfr, "%d", parsed_time->tm_year + 1900);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * output month 
Packit fcad23
             */
Packit fcad23
        case CHR_CUR_MONTH:
Packit fcad23
        case CHR_UP_MONTH:
Packit fcad23
            sprintf(safe_bfr, "%d", parsed_time->tm_mon + 1);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * output day of month 
Packit fcad23
             */
Packit fcad23
        case CHR_CUR_MDAY:
Packit fcad23
        case CHR_UP_MDAY:
Packit fcad23
            sprintf(safe_bfr, "%d", parsed_time->tm_mday);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * output hour 
Packit fcad23
             */
Packit fcad23
        case CHR_CUR_HOUR:
Packit fcad23
        case CHR_UP_HOUR:
Packit fcad23
            sprintf(safe_bfr, "%d", parsed_time->tm_hour);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * output minute 
Packit fcad23
             */
Packit fcad23
        case CHR_CUR_MIN:
Packit fcad23
        case CHR_UP_MIN:
Packit fcad23
            sprintf(safe_bfr, "%d", parsed_time->tm_min);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * output second 
Packit fcad23
             */
Packit fcad23
        case CHR_CUR_SEC:
Packit fcad23
        case CHR_UP_SEC:
Packit fcad23
            sprintf(safe_bfr, "%d", parsed_time->tm_sec);
Packit fcad23
            break;
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * unknown format command - just output the character 
Packit fcad23
             */
Packit fcad23
        default:
Packit fcad23
            sprintf(safe_bfr, "%c", fmt_cmd);
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Output with correct justification, leading zeroes, etc.  
Packit fcad23
     */
Packit fcad23
    return realloc_output_temp_bfr(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                                   (u_char **) & safe_bfr, options);
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
static int
Packit fcad23
realloc_handle_ip_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
Packit fcad23
                      int allow_realloc,
Packit fcad23
                      options_type * options, netsnmp_pdu *pdu,
Packit fcad23
                      netsnmp_transport *transport)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *     Handle a format command that deals with an IP address 
Packit fcad23
      * or host name.  Append the information to the buffer subject to
Packit fcad23
      * the buffer's length limit.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    buf, buf_len, out_len, allow_realloc - standard relocatable
Packit fcad23
      *                                           buffer parameters
Packit fcad23
      *    options   - options governing how to write the field
Packit fcad23
      *    pdu       - information about this trap 
Packit fcad23
      *    transport - the transport descriptor
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    struct in_addr *agent_inaddr = (struct in_addr *) pdu->agent_addr;
Packit fcad23
    struct hostent *host = NULL;       /* corresponding host name */
Packit fcad23
    char            fmt_cmd = options->cmd;     /* what we're formatting */
Packit fcad23
    u_char         *temp_buf = NULL;
Packit fcad23
    size_t          temp_buf_len = 64, temp_out_len = 0;
Packit fcad23
    char           *tstr;
Packit fcad23
    unsigned int    oflags;
Packit fcad23
Packit fcad23
    if ((temp_buf = (u_char*)calloc(temp_buf_len, 1)) == NULL) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Decide exactly what to output.  
Packit fcad23
     */
Packit fcad23
    switch (fmt_cmd) {
Packit fcad23
    case CHR_AGENT_IP:
Packit fcad23
        /*
Packit fcad23
         * Write a numerical address.  
Packit fcad23
         */
Packit fcad23
        if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len, 1,
Packit fcad23
                         (u_char *)inet_ntoa(*agent_inaddr))) {
Packit fcad23
            if (temp_buf != NULL) {
Packit fcad23
                free(temp_buf);
Packit fcad23
            }
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case CHR_AGENT_NAME:
Packit fcad23
        /*
Packit fcad23
         * Try to resolve the agent_addr field as a hostname; fall back
Packit fcad23
         * to numerical address.  
Packit fcad23
         */
Packit fcad23
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
                                    NETSNMP_DS_APP_NUMERIC_IP)) {
Packit fcad23
            host = netsnmp_gethostbyaddr((char *) pdu->agent_addr, 4, AF_INET);
Packit fcad23
        }
Packit fcad23
        if (host != NULL) {
Packit fcad23
            if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len, 1,
Packit fcad23
                             (const u_char *)host->h_name)) {
Packit fcad23
                if (temp_buf != NULL) {
Packit fcad23
                    free(temp_buf);
Packit fcad23
                }
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
        } else {
Packit fcad23
            if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len, 1,
Packit fcad23
                             (u_char *)inet_ntoa(*agent_inaddr))) {
Packit fcad23
                if (temp_buf != NULL) {
Packit fcad23
                    free(temp_buf);
Packit fcad23
                }
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case CHR_PDU_IP:
Packit fcad23
        /*
Packit fcad23
         * Write the numerical transport information.  
Packit fcad23
         */
Packit fcad23
        if (transport != NULL && transport->f_fmtaddr != NULL) {
Packit fcad23
            oflags = transport->flags;
Packit fcad23
            transport->flags &= ~NETSNMP_TRANSPORT_FLAG_HOSTNAME;
Packit fcad23
            tstr = transport->f_fmtaddr(transport, pdu->transport_data,
Packit fcad23
                                        pdu->transport_data_length);
Packit fcad23
            transport->flags = oflags;
Packit fcad23
          
Packit fcad23
            if (!tstr) goto noip;
Packit fcad23
            if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len,
Packit fcad23
                             1, (u_char *)tstr)) {
Packit fcad23
                SNMP_FREE(temp_buf);
Packit fcad23
                SNMP_FREE(tstr);
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
            SNMP_FREE(tstr);
Packit fcad23
        } else {
Packit fcad23
noip:
Packit fcad23
            if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len, 1,
Packit fcad23
                             (const u_char*)"<UNKNOWN>")) {
Packit fcad23
                SNMP_FREE(temp_buf);
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case CHR_PDU_NAME:
Packit fcad23
        /*
Packit fcad23
         * Try to convert the numerical transport information
Packit fcad23
         *  into a hostname.  Or rather, have the transport-specific
Packit fcad23
         *  address formatting routine do this.
Packit fcad23
         * Otherwise falls back to the numeric address format.
Packit fcad23
         */
Packit fcad23
        if (transport != NULL && transport->f_fmtaddr != NULL) {
Packit fcad23
            oflags = transport->flags;
Packit fcad23
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
                                        NETSNMP_DS_APP_NUMERIC_IP))
Packit fcad23
                transport->flags |= NETSNMP_TRANSPORT_FLAG_HOSTNAME;
Packit fcad23
            tstr = transport->f_fmtaddr(transport, pdu->transport_data,
Packit fcad23
                                        pdu->transport_data_length);
Packit fcad23
            transport->flags = oflags;
Packit fcad23
          
Packit fcad23
            if (!tstr) goto nohost;
Packit fcad23
            if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len,
Packit fcad23
                             1, (u_char *)tstr)) {
Packit fcad23
                SNMP_FREE(temp_buf);
Packit fcad23
                SNMP_FREE(tstr);
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
            SNMP_FREE(tstr);
Packit fcad23
        } else {
Packit fcad23
nohost:
Packit fcad23
            if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len, 1,
Packit fcad23
                             (const u_char*)"<UNKNOWN>")) {
Packit fcad23
                SNMP_FREE(temp_buf);
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * Don't know how to handle this command - write the character itself.  
Packit fcad23
         */
Packit fcad23
    default:
Packit fcad23
        temp_buf[0] = fmt_cmd;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Output with correct justification, leading zeroes, etc.  
Packit fcad23
     */
Packit fcad23
    return realloc_output_temp_bfr(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                                   &temp_buf, options);
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
static int
Packit fcad23
realloc_handle_ent_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
Packit fcad23
                       int allow_realloc,
Packit fcad23
                       options_type * options, netsnmp_pdu *pdu)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *     Handle a format command that deals with OID strings. 
Packit fcad23
      * Append the information to the buffer subject to the
Packit fcad23
      * buffer's length limit.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    buf, buf_len, out_len, allow_realloc - standard relocatable
Packit fcad23
      *                                           buffer parameters
Packit fcad23
      *    options - options governing how to write the field
Packit fcad23
      *    pdu     - information about this trap 
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    char            fmt_cmd = options->cmd;     /* what we're formatting */
Packit fcad23
    u_char         *temp_buf = NULL;
Packit fcad23
    size_t          temp_buf_len = 64, temp_out_len = 0;
Packit fcad23
Packit fcad23
    if ((temp_buf = (u_char *) calloc(temp_buf_len, 1)) == NULL) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Decide exactly what to output.  
Packit fcad23
     */
Packit fcad23
    switch (fmt_cmd) {
Packit fcad23
    case CHR_PDU_ENT:
Packit fcad23
        /*
Packit fcad23
         * Write the enterprise oid.  
Packit fcad23
         */
Packit fcad23
        if (!sprint_realloc_objid
Packit fcad23
            (&temp_buf, &temp_buf_len, &temp_out_len, 1, pdu->enterprise,
Packit fcad23
             pdu->enterprise_length)) {
Packit fcad23
            free(temp_buf);
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case CHR_TRAP_CONTEXTID:
Packit fcad23
        /*
Packit fcad23
         * Write the context oid.  
Packit fcad23
         */
Packit fcad23
        if (!sprint_realloc_hexstring
Packit fcad23
            (&temp_buf, &temp_buf_len, &temp_out_len, 1, pdu->contextEngineID,
Packit fcad23
             pdu->contextEngineIDLen)) {
Packit fcad23
            free(temp_buf);
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * Don't know how to handle this command - write the character itself.  
Packit fcad23
         */
Packit fcad23
    default:
Packit fcad23
        temp_buf[0] = fmt_cmd;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Output with correct justification, leading zeroes, etc.  
Packit fcad23
     */
Packit fcad23
    return realloc_output_temp_bfr(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                                   &temp_buf, options);
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
static int
Packit fcad23
realloc_handle_trap_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
Packit fcad23
                        int allow_realloc,
Packit fcad23
                        options_type * options, netsnmp_pdu *pdu)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *     Handle a format command that deals with the trap itself. 
Packit fcad23
      * Append the information to the buffer subject to the buffer's 
Packit fcad23
      * length limit.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    buf, buf_len, out_len, allow_realloc - standard relocatable
Packit fcad23
      *                                           buffer parameters
Packit fcad23
      *    options - options governing how to write the field
Packit fcad23
      *    pdu     - information about this trap 
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list *vars;        /* variables assoc with trap */
Packit fcad23
    char            fmt_cmd = options->cmd;     /* what we're outputting */
Packit fcad23
    u_char         *temp_buf = NULL;
Packit fcad23
    size_t          tbuf_len = 64, tout_len = 0;
Packit fcad23
    const char           *sep = separator;
Packit fcad23
    const char           *default_sep = "\t";
Packit fcad23
    const char           *default_alt_sep = ", ";
Packit fcad23
Packit fcad23
    if ((temp_buf = (u_char *) calloc(tbuf_len, 1)) == NULL) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Decide exactly what to output.  
Packit fcad23
     */
Packit fcad23
    switch (fmt_cmd) {
Packit fcad23
    case CHR_TRAP_NUM:
Packit fcad23
        /*
Packit fcad23
         * Write the trap's number.  
Packit fcad23
         */
Packit fcad23
        tout_len = sprintf((char*)temp_buf, "%ld", pdu->trap_type);
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case CHR_TRAP_DESC:
Packit fcad23
        /*
Packit fcad23
         * Write the trap's description.  
Packit fcad23
         */
Packit fcad23
        tout_len =
Packit fcad23
            sprintf((char*)temp_buf, "%s", trap_description(pdu->trap_type));
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case CHR_TRAP_STYPE:
Packit fcad23
        /*
Packit fcad23
         * Write the trap's subtype.  
Packit fcad23
         */
Packit fcad23
        if (pdu->trap_type != SNMP_TRAP_ENTERPRISESPECIFIC) {
Packit fcad23
            tout_len = sprintf((char*)temp_buf, "%ld", pdu->specific_type);
Packit fcad23
        } else {
Packit fcad23
            /*
Packit fcad23
             * Get object ID for the trap.  
Packit fcad23
             */
Packit fcad23
            size_t          obuf_len = 64, oout_len = 0, trap_oid_len = 0;
Packit fcad23
            oid             trap_oid[MAX_OID_LEN + 2] = { 0 };
Packit fcad23
            u_char         *obuf = NULL;
Packit fcad23
            char           *ptr = NULL;
Packit fcad23
Packit fcad23
            if ((obuf = (u_char *) calloc(obuf_len, 1)) == NULL) {
Packit fcad23
                free(temp_buf);
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
Packit fcad23
            trap_oid_len = pdu->enterprise_length;
Packit fcad23
            memcpy(trap_oid, pdu->enterprise, trap_oid_len * sizeof(oid));
Packit fcad23
            if (trap_oid[trap_oid_len - 1] != 0) {
Packit fcad23
                trap_oid[trap_oid_len] = 0;
Packit fcad23
                trap_oid_len++;
Packit fcad23
            }
Packit fcad23
            trap_oid[trap_oid_len] = pdu->specific_type;
Packit fcad23
            trap_oid_len++;
Packit fcad23
Packit fcad23
            /*
Packit fcad23
             * Find the element after the last dot.  
Packit fcad23
             */
Packit fcad23
            if (!sprint_realloc_objid(&obuf, &obuf_len, &oout_len, 1,
Packit fcad23
                                      trap_oid, trap_oid_len)) {
Packit fcad23
                if (obuf != NULL) {
Packit fcad23
                    free(obuf);
Packit fcad23
                }
Packit fcad23
                free(temp_buf);
Packit fcad23
		return 0;
Packit fcad23
            }
Packit fcad23
Packit fcad23
            ptr = strrchr((char *) obuf, '.');
Packit fcad23
            if (ptr != NULL) {
Packit fcad23
                if (!snmp_strcat
Packit fcad23
                    (&temp_buf, &tbuf_len, &tout_len, 1, (u_char *) ptr)) {
Packit fcad23
                    free(obuf);
Packit fcad23
                    if (temp_buf != NULL) {
Packit fcad23
                        free(temp_buf);
Packit fcad23
                    }
Packit fcad23
                    return 0;
Packit fcad23
                }
Packit fcad23
                free(obuf);
Packit fcad23
            } else {
Packit fcad23
                free(temp_buf);
Packit fcad23
                temp_buf = obuf;
Packit fcad23
                tbuf_len = obuf_len;
Packit fcad23
                tout_len = oout_len;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case CHR_TRAP_VARS:
Packit fcad23
        /*
Packit fcad23
         * Write the trap's variables.  
Packit fcad23
         */
Packit fcad23
        if (!sep || !*sep)
Packit fcad23
            sep = (options->alt_format ? default_alt_sep : default_sep);
Packit fcad23
        for (vars = pdu->variables; vars != NULL;
Packit fcad23
             vars = vars->next_variable) {
Packit fcad23
            /*
Packit fcad23
             * Print a separator between variables,
Packit fcad23
             *   (plus beforehand if the alt format is used)
Packit fcad23
             */
Packit fcad23
            if (options->alt_format ||
Packit fcad23
                vars != pdu->variables ) {
Packit fcad23
                if (!snmp_strcat(&temp_buf, &tbuf_len, &tout_len, 1, (const u_char *)sep)) {
Packit fcad23
                    if (temp_buf != NULL) {
Packit fcad23
                        free(temp_buf);
Packit fcad23
                    }
Packit fcad23
                    return 0;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
            if (!sprint_realloc_variable
Packit fcad23
                (&temp_buf, &tbuf_len, &tout_len, 1, vars->name,
Packit fcad23
                 vars->name_length, vars)) {
Packit fcad23
                if (temp_buf != NULL) {
Packit fcad23
                    free(temp_buf);
Packit fcad23
                }
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    default:
Packit fcad23
        /*
Packit fcad23
         * Don't know how to handle this command - write the character itself.  
Packit fcad23
         */
Packit fcad23
        temp_buf[0] = fmt_cmd;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Output with correct justification, leading zeroes, etc.  
Packit fcad23
     */
Packit fcad23
    return realloc_output_temp_bfr(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                                   &temp_buf, options);
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
realloc_handle_auth_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
Packit fcad23
                        int allow_realloc,
Packit fcad23
                        options_type * options, netsnmp_pdu *pdu)
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *     Handle a format command that deals with authentication
Packit fcad23
      * information.
Packit fcad23
      * Append the information to the buffer subject to the buffer's 
Packit fcad23
      * length limit.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    buf, buf_len, out_len, allow_realloc - standard relocatable
Packit fcad23
      *                                           buffer parameters
Packit fcad23
      *    options - options governing how to write the field
Packit fcad23
      *    pdu     - information about this trap 
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    char            fmt_cmd = options->cmd;     /* what we're outputting */
Packit fcad23
    u_char         *temp_buf = NULL;
Packit fcad23
    size_t          tbuf_len = 64;
Packit fcad23
    unsigned int    i;
Packit fcad23
Packit fcad23
    if ((temp_buf = (u_char*)calloc(tbuf_len, 1)) == NULL) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    switch (fmt_cmd) {
Packit fcad23
Packit fcad23
    case CHR_SNMP_VERSION:
Packit fcad23
        snprintf((char*)temp_buf, tbuf_len, "%ld", pdu->version);
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case CHR_SNMP_SECMOD:
Packit fcad23
        snprintf((char*)temp_buf, tbuf_len, "%d", pdu->securityModel);
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    case CHR_SNMP_USER:
Packit fcad23
        switch ( pdu->version ) {
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
        case SNMP_VERSION_1:
Packit fcad23
#endif
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV2C
Packit fcad23
        case SNMP_VERSION_2c:
Packit fcad23
#endif
Packit fcad23
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
Packit fcad23
            while ((*out_len + pdu->community_len + 1) >= *buf_len) {
Packit fcad23
                if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                    if (temp_buf)
Packit fcad23
                        free(temp_buf);
Packit fcad23
                    return 0;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
Packit fcad23
            for (i = 0; i < pdu->community_len; i++) {
Packit fcad23
                if (isprint(pdu->community[i])) {
Packit fcad23
                    *(*buf + *out_len) = pdu->community[i];
Packit fcad23
                } else {
Packit fcad23
                    *(*buf + *out_len) = '.';
Packit fcad23
                }
Packit fcad23
                (*out_len)++;
Packit fcad23
            }
Packit fcad23
            *(*buf + *out_len) = '\0';
Packit fcad23
            break;
Packit fcad23
#endif
Packit fcad23
        default:
Packit fcad23
            snprintf((char*)temp_buf, tbuf_len, "%s", pdu->securityName);
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
Packit fcad23
    default:
Packit fcad23
        /*
Packit fcad23
         * Don't know how to handle this command - write the character itself.  
Packit fcad23
         */
Packit fcad23
        temp_buf[0] = fmt_cmd;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Output with correct justification, leading zeroes, etc.  
Packit fcad23
     */
Packit fcad23
    return realloc_output_temp_bfr(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                                   &temp_buf, options);
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
realloc_handle_wrap_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
Packit fcad23
                        int allow_realloc, netsnmp_pdu *pdu)
Packit fcad23
{
Packit fcad23
    size_t          i = 0;
Packit fcad23
Packit fcad23
    switch (pdu->command) {
Packit fcad23
    case SNMP_MSG_TRAP:
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) "TRAP")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
    case SNMP_MSG_TRAP2:
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) "TRAP2")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
    case SNMP_MSG_INFORM:
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) "INFORM")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    switch (pdu->version) {
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
    case SNMP_VERSION_1:
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) ", SNMP v1")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
#endif
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV2C
Packit fcad23
    case SNMP_VERSION_2c:
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) ", SNMP v2c")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
#endif
Packit fcad23
    case SNMP_VERSION_3:
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) ", SNMP v3")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        break;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    switch (pdu->version) {
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV1
Packit fcad23
    case SNMP_VERSION_1:
Packit fcad23
#endif
Packit fcad23
#ifndef NETSNMP_DISABLE_SNMPV2C
Packit fcad23
    case SNMP_VERSION_2c:
Packit fcad23
#endif
Packit fcad23
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) ", community ")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        while ((*out_len + pdu->community_len + 1) >= *buf_len) {
Packit fcad23
            if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
Packit fcad23
        for (i = 0; i < pdu->community_len; i++) {
Packit fcad23
            if (isprint(pdu->community[i])) {
Packit fcad23
                *(*buf + *out_len) = pdu->community[i];
Packit fcad23
            } else {
Packit fcad23
                *(*buf + *out_len) = '.';
Packit fcad23
            }
Packit fcad23
            (*out_len)++;
Packit fcad23
        }
Packit fcad23
        *(*buf + *out_len) = '\0';
Packit fcad23
        break;
Packit fcad23
#endif
Packit fcad23
    case SNMP_VERSION_3:
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) ", user ")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        while ((*out_len + pdu->securityNameLen + 1) >= *buf_len) {
Packit fcad23
            if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
Packit fcad23
        for (i = 0; i < pdu->securityNameLen; i++) {
Packit fcad23
            if (isprint((unsigned char)(pdu->securityName[i]))) {
Packit fcad23
                *(*buf + *out_len) = pdu->securityName[i];
Packit fcad23
            } else {
Packit fcad23
                *(*buf + *out_len) = '.';
Packit fcad23
            }
Packit fcad23
            (*out_len)++;
Packit fcad23
        }
Packit fcad23
        *(*buf + *out_len) = '\0';
Packit fcad23
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) ", context ")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        while ((*out_len + pdu->contextNameLen + 1) >= *buf_len) {
Packit fcad23
            if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
        }
Packit fcad23
Packit fcad23
        for (i = 0; i < pdu->contextNameLen; i++) {
Packit fcad23
            if (isprint((unsigned char)(pdu->contextName[i]))) {
Packit fcad23
                *(*buf + *out_len) = pdu->contextName[i];
Packit fcad23
            } else {
Packit fcad23
                *(*buf + *out_len) = '.';
Packit fcad23
            }
Packit fcad23
            (*out_len)++;
Packit fcad23
        }
Packit fcad23
        *(*buf + *out_len) = '\0';
Packit fcad23
    }
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
static int
Packit fcad23
realloc_dispatch_format_cmd(u_char ** buf, size_t * buf_len,
Packit fcad23
                            size_t * out_len, int allow_realloc,
Packit fcad23
                            options_type * options, netsnmp_pdu *pdu,
Packit fcad23
                            netsnmp_transport *transport)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *     Dispatch a format command to the appropriate command handler.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    buf, buf_len, out_len, allow_realloc - standard relocatable
Packit fcad23
      *                                           buffer parameters
Packit fcad23
      *    options   - options governing how to write the field
Packit fcad23
      *    pdu       - information about this trap
Packit fcad23
      *    transport - the transport descriptor
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    char            fmt_cmd = options->cmd;     /* for speed */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * choose the appropriate command handler 
Packit fcad23
     */
Packit fcad23
Packit fcad23
    if (is_cur_time_cmd(fmt_cmd) || is_up_time_cmd(fmt_cmd)) {
Packit fcad23
        return realloc_handle_time_fmt(buf, buf_len, out_len,
Packit fcad23
                                       allow_realloc, options, pdu);
Packit fcad23
    } else if (is_agent_cmd(fmt_cmd) || is_pdu_ip_cmd(fmt_cmd)) {
Packit fcad23
        return realloc_handle_ip_fmt(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                                     options, pdu, transport);
Packit fcad23
    } else if (is_trap_cmd(fmt_cmd)) {
Packit fcad23
        return realloc_handle_trap_fmt(buf, buf_len, out_len,
Packit fcad23
                                       allow_realloc, options, pdu);
Packit fcad23
    } else if (is_auth_cmd(fmt_cmd)) {
Packit fcad23
        return realloc_handle_auth_fmt(buf, buf_len, out_len,
Packit fcad23
                                       allow_realloc, options, pdu);
Packit fcad23
    } else if (fmt_cmd == CHR_PDU_ENT || fmt_cmd == CHR_TRAP_CONTEXTID) {
Packit fcad23
        return realloc_handle_ent_fmt(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                                      options, pdu);
Packit fcad23
    } else if (fmt_cmd == CHR_PDU_WRAP) {
Packit fcad23
        return realloc_handle_wrap_fmt(buf, buf_len, out_len,
Packit fcad23
                                       allow_realloc, pdu);
Packit fcad23
    } else {
Packit fcad23
        /*
Packit fcad23
         * unknown format command - just output the character 
Packit fcad23
         */
Packit fcad23
        char            fmt_cmd_string[2] = { 0, 0 };
Packit fcad23
        fmt_cmd_string[0] = fmt_cmd;
Packit fcad23
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) fmt_cmd_string);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
static int
Packit fcad23
realloc_handle_backslash(u_char ** buf, size_t * buf_len, size_t * out_len,
Packit fcad23
                         int allow_realloc, char fmt_cmd)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *     Handle a character following a backslash. Append the resulting 
Packit fcad23
      * character to the buffer subject to the buffer's length limit.
Packit fcad23
      *     This routine currently isn't sophisticated enough to handle
Packit fcad23
      * \nnn or \xhh formats.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    buf, buf_len, out_len, allow_realloc - standard relocatable
Packit fcad23
      *                                           buffer parameters
Packit fcad23
      *    fmt_cmd - the character after the backslash
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    char            temp_bfr[3];        /* for bulding temporary strings */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * select the proper output character(s) 
Packit fcad23
     */
Packit fcad23
    switch (fmt_cmd) {
Packit fcad23
    case 'a':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "\a");
Packit fcad23
    case 'b':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "\b");
Packit fcad23
    case 'f':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "\f");
Packit fcad23
    case 'n':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "\n");
Packit fcad23
    case 'r':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "\r");
Packit fcad23
    case 't':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "\t");
Packit fcad23
    case 'v':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "\v");
Packit fcad23
    case '\\':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "\\");
Packit fcad23
    case '?':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "?");
Packit fcad23
    case '%':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "%");
Packit fcad23
    case '\'':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "\'");
Packit fcad23
    case '"':
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) "\"");
Packit fcad23
    default:
Packit fcad23
        sprintf(temp_bfr, "\\%c", fmt_cmd);
Packit fcad23
        return snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                           (const u_char *) temp_bfr);
Packit fcad23
    }
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
int
Packit fcad23
realloc_format_plain_trap(u_char ** buf, size_t * buf_len,
Packit fcad23
                          size_t * out_len, int allow_realloc,
Packit fcad23
                          netsnmp_pdu *pdu, netsnmp_transport *transport)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Format the trap information in the default way and put the results
Packit fcad23
      * into the buffer, truncating at the buffer's length limit. This
Packit fcad23
      * routine returns 1 if the output was completed successfully or
Packit fcad23
      * 0 if it is truncated due to a memory allocation failure.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    buf, buf_len, out_len, allow_realloc - standard relocatable
Packit fcad23
      *                                           buffer parameters
Packit fcad23
      *    pdu       - the pdu information
Packit fcad23
      *    transport - the transport descriptor
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    time_t          now;        /* the current time */
Packit fcad23
    struct tm      *now_parsed; /* time in struct format */
Packit fcad23
    char            safe_bfr[200];      /* holds other strings */
Packit fcad23
    struct in_addr *agent_inaddr = (struct in_addr *) pdu->agent_addr;
Packit fcad23
    struct hostent *host = NULL;       /* host name */
Packit fcad23
    netsnmp_variable_list *vars;        /* variables assoc with trap */
Packit fcad23
Packit fcad23
    if (buf == NULL) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Print the current time. Since we don't know how long the buffer is,
Packit fcad23
     * and snprintf isn't yet standard, build the timestamp in a separate
Packit fcad23
     * buffer of guaranteed length and then copy it to the output buffer.
Packit fcad23
     */
Packit fcad23
    time(&now;;
Packit fcad23
    now_parsed = localtime(&now;;
Packit fcad23
    sprintf(safe_bfr, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d ",
Packit fcad23
            now_parsed->tm_year + 1900, now_parsed->tm_mon + 1,
Packit fcad23
            now_parsed->tm_mday, now_parsed->tm_hour,
Packit fcad23
            now_parsed->tm_min, now_parsed->tm_sec);
Packit fcad23
    if (!snmp_strcat
Packit fcad23
        (buf, buf_len, out_len, allow_realloc,
Packit fcad23
         (const u_char *) safe_bfr)) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Get info about the sender.  
Packit fcad23
     */
Packit fcad23
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
Packit fcad23
                                NETSNMP_DS_APP_NUMERIC_IP)) {
Packit fcad23
        host = netsnmp_gethostbyaddr((char *) pdu->agent_addr, 4, AF_INET);
Packit fcad23
    }
Packit fcad23
    if (host != (struct hostent *) NULL) {
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) host->h_name)) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) " [")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                         (const u_char *) inet_ntoa(*agent_inaddr))) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) "] ")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
    } else {
Packit fcad23
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                         (const u_char *) inet_ntoa(*agent_inaddr))) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Append PDU transport info.  
Packit fcad23
     */
Packit fcad23
    if (transport != NULL && transport->f_fmtaddr != NULL) {
Packit fcad23
        char           *tstr =
Packit fcad23
            transport->f_fmtaddr(transport, pdu->transport_data,
Packit fcad23
                                 pdu->transport_data_length);
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) "(via ")) {
Packit fcad23
            if (tstr != NULL) {
Packit fcad23
                free(tstr);
Packit fcad23
            }
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, (u_char *)tstr)) {
Packit fcad23
            if (tstr != NULL) {
Packit fcad23
                free(tstr);
Packit fcad23
            }
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        if (tstr != NULL) {
Packit fcad23
            free(tstr);
Packit fcad23
        }
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) ") ")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Add security wrapper information.  
Packit fcad23
     */
Packit fcad23
    if (!realloc_handle_wrap_fmt
Packit fcad23
        (buf, buf_len, out_len, allow_realloc, pdu)) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (!snmp_strcat
Packit fcad23
        (buf, buf_len, out_len, allow_realloc, (const u_char *) "\n\t")) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Add enterprise information.  
Packit fcad23
     */
Packit fcad23
    if (!sprint_realloc_objid(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                              pdu->enterprise, pdu->enterprise_length)) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (!snmp_strcat
Packit fcad23
        (buf, buf_len, out_len, allow_realloc, (const u_char *) " ")) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                     (const u_char *)trap_description(pdu->trap_type))) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
    if (!snmp_strcat
Packit fcad23
        (buf, buf_len, out_len, allow_realloc,
Packit fcad23
         (const u_char *) " Trap (")) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Handle enterprise specific traps.  
Packit fcad23
     */
Packit fcad23
    if (pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) {
Packit fcad23
        size_t          obuf_len = 64, oout_len = 0, trap_oid_len = 0;
Packit fcad23
        oid             trap_oid[MAX_OID_LEN + 2] = { 0 };
Packit fcad23
        char           *ent_spec_code = NULL;
Packit fcad23
        u_char         *obuf = NULL;
Packit fcad23
Packit fcad23
        if ((obuf = (u_char *) calloc(obuf_len, 1)) == NULL) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * Get object ID for the trap.  
Packit fcad23
         */
Packit fcad23
        trap_oid_len = pdu->enterprise_length;
Packit fcad23
        memcpy(trap_oid, pdu->enterprise, trap_oid_len * sizeof(oid));
Packit fcad23
        if (trap_oid[trap_oid_len - 1] != 0) {
Packit fcad23
            trap_oid[trap_oid_len] = 0;
Packit fcad23
            trap_oid_len++;
Packit fcad23
        }
Packit fcad23
        trap_oid[trap_oid_len] = pdu->specific_type;
Packit fcad23
        trap_oid_len++;
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * Find the element after the last dot.  
Packit fcad23
         */
Packit fcad23
        if (!sprint_realloc_objid(&obuf, &obuf_len, &oout_len, 1,
Packit fcad23
                                  trap_oid, trap_oid_len)) {
Packit fcad23
            if (obuf != NULL) {
Packit fcad23
                free(obuf);
Packit fcad23
            }
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        ent_spec_code = strrchr((char *) obuf, '.');
Packit fcad23
        if (ent_spec_code != NULL) {
Packit fcad23
            ent_spec_code++;
Packit fcad23
        } else {
Packit fcad23
            ent_spec_code = (char *) obuf;
Packit fcad23
        }
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * Print trap info.  
Packit fcad23
         */
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) ent_spec_code)) {
Packit fcad23
            free(obuf);
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        free(obuf);
Packit fcad23
    } else {
Packit fcad23
        /*
Packit fcad23
         * Handle traps that aren't enterprise specific.  
Packit fcad23
         */
Packit fcad23
        sprintf(safe_bfr, "%ld", pdu->specific_type);
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) safe_bfr)) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Finish the line.  
Packit fcad23
     */
Packit fcad23
    if (!snmp_strcat
Packit fcad23
        (buf, buf_len, out_len, allow_realloc,
Packit fcad23
         (const u_char *) ") Uptime: ")) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
    if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                     (const u_char *) uptime_string(pdu->time,
Packit fcad23
                                                    safe_bfr))) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
    if (!snmp_strcat
Packit fcad23
        (buf, buf_len, out_len, allow_realloc, (const u_char *) "\n")) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Finally, output the PDU variables. 
Packit fcad23
     */
Packit fcad23
    for (vars = pdu->variables; vars != NULL; vars = vars->next_variable) {
Packit fcad23
        if (!snmp_strcat
Packit fcad23
            (buf, buf_len, out_len, allow_realloc,
Packit fcad23
             (const u_char *) "\t")) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
        if (!sprint_realloc_variable(buf, buf_len, out_len, allow_realloc,
Packit fcad23
                                     vars->name, vars->name_length,
Packit fcad23
                                     vars)) {
Packit fcad23
            return 0;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
    if (!snmp_strcat
Packit fcad23
        (buf, buf_len, out_len, allow_realloc, (const u_char *) "\n")) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * String is already null-terminated.  That's all folks!  
Packit fcad23
     */
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
int
Packit fcad23
realloc_format_trap(u_char ** buf, size_t * buf_len, size_t * out_len,
Packit fcad23
                    int allow_realloc, const char *format_str,
Packit fcad23
                    netsnmp_pdu *pdu, netsnmp_transport *transport)
Packit fcad23
Packit fcad23
     /*
Packit fcad23
      * Function:
Packit fcad23
      *    Format the trap information for display in a log. Place the results
Packit fcad23
      *    in the specified buffer (truncating to the length of the buffer).
Packit fcad23
      *    Returns the number of characters it put in the buffer.
Packit fcad23
      *
Packit fcad23
      * Input Parameters:
Packit fcad23
      *    buf, buf_len, out_len, allow_realloc - standard relocatable
Packit fcad23
      *                                           buffer parameters
Packit fcad23
      *    format_str - specifies how to format the trap info
Packit fcad23
      *    pdu        - the pdu information
Packit fcad23
      *    transport  - the transport descriptor
Packit fcad23
      */
Packit fcad23
{
Packit fcad23
    unsigned long   fmt_idx = 0;        /* index into the format string */
Packit fcad23
    options_type    options;    /* formatting options */
Packit fcad23
    parse_state_type state = PARSE_NORMAL;      /* state of the parser */
Packit fcad23
    char            next_chr;   /* for speed */
Packit fcad23
    int             reset_options = TRUE;       /* reset opts on next NORMAL state */
Packit fcad23
Packit fcad23
    if (buf == NULL) {
Packit fcad23
        return 0;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    memset(separator, 0, sizeof(separator));
Packit fcad23
    /*
Packit fcad23
     * Go until we reach the end of the format string:  
Packit fcad23
     */
Packit fcad23
    for (fmt_idx = 0; format_str[fmt_idx] != '\0'; fmt_idx++) {
Packit fcad23
        next_chr = format_str[fmt_idx];
Packit fcad23
        switch (state) {
Packit fcad23
        case PARSE_NORMAL:
Packit fcad23
            /*
Packit fcad23
             * Looking for next character.  
Packit fcad23
             */
Packit fcad23
            if (reset_options) {
Packit fcad23
                init_options(&options);
Packit fcad23
                reset_options = FALSE;
Packit fcad23
            }
Packit fcad23
            if (next_chr == '\\') {
Packit fcad23
                state = PARSE_BACKSLASH;
Packit fcad23
            } else if (next_chr == CHR_FMT_DELIM) {
Packit fcad23
                state = PARSE_IN_FORMAT;
Packit fcad23
            } else {
Packit fcad23
                if ((*out_len + 1) >= *buf_len) {
Packit fcad23
                    if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                        return 0;
Packit fcad23
                    }
Packit fcad23
                }
Packit fcad23
                *(*buf + *out_len) = next_chr;
Packit fcad23
                (*out_len)++;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case PARSE_GET_SEPARATOR:
Packit fcad23
            /*
Packit fcad23
             * Parse the separator character
Packit fcad23
             * XXX - Possibly need to handle quoted strings ??
Packit fcad23
             */
Packit fcad23
	    {   char *sep = separator;
Packit fcad23
		size_t i, j;
Packit fcad23
		i = sizeof(separator);
Packit fcad23
		j = 0;
Packit fcad23
		memset(separator, 0, i);
Packit fcad23
		while (j < i && next_chr && next_chr != CHR_FMT_DELIM) {
Packit fcad23
		    if (next_chr == '\\') {
Packit fcad23
			/*
Packit fcad23
			 * Handle backslash interpretation
Packit fcad23
			 * Print to "separator" string rather than the output buffer
Packit fcad23
			 *    (a bit of a hack, but it should work!)
Packit fcad23
			 */
Packit fcad23
			next_chr = format_str[++fmt_idx];
Packit fcad23
			if (!realloc_handle_backslash
Packit fcad23
			    ((u_char **)&sep, &i, &j, 0, next_chr)) {
Packit fcad23
			    return 0;
Packit fcad23
			}
Packit fcad23
		    } else {
Packit fcad23
			separator[j++] = next_chr;
Packit fcad23
		    }
Packit fcad23
		    next_chr = format_str[++fmt_idx];
Packit fcad23
		}
Packit fcad23
	    }
Packit fcad23
            state = PARSE_IN_FORMAT;
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case PARSE_BACKSLASH:
Packit fcad23
            /*
Packit fcad23
             * Found a backslash.  
Packit fcad23
             */
Packit fcad23
            if (!realloc_handle_backslash
Packit fcad23
                (buf, buf_len, out_len, allow_realloc, next_chr)) {
Packit fcad23
                return 0;
Packit fcad23
            }
Packit fcad23
            state = PARSE_NORMAL;
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case PARSE_IN_FORMAT:
Packit fcad23
            /*
Packit fcad23
             * In a format command.  
Packit fcad23
             */
Packit fcad23
            reset_options = TRUE;
Packit fcad23
            if (next_chr == CHR_LEFT_JUST) {
Packit fcad23
                options.left_justify = TRUE;
Packit fcad23
            } else if (next_chr == CHR_LEAD_ZERO) {
Packit fcad23
                options.leading_zeroes = TRUE;
Packit fcad23
            } else if (next_chr == CHR_ALT_FORM) {
Packit fcad23
                options.alt_format = TRUE;
Packit fcad23
            } else if (next_chr == CHR_FIELD_SEP) {
Packit fcad23
                state = PARSE_GET_PRECISION;
Packit fcad23
            } else if (next_chr == CHR_TRAP_VARSEP) {
Packit fcad23
                state = PARSE_GET_SEPARATOR;
Packit fcad23
            } else if ((next_chr >= '1') && (next_chr <= '9')) {
Packit fcad23
                options.width =
Packit fcad23
                    ((unsigned long) next_chr) - ((unsigned long) '0');
Packit fcad23
                state = PARSE_GET_WIDTH;
Packit fcad23
            } else if (is_fmt_cmd(next_chr)) {
Packit fcad23
                options.cmd = next_chr;
Packit fcad23
                if (!realloc_dispatch_format_cmd
Packit fcad23
                    (buf, buf_len, out_len, allow_realloc, &options, pdu,
Packit fcad23
                     transport)) {
Packit fcad23
                    return 0;
Packit fcad23
                }
Packit fcad23
                state = PARSE_NORMAL;
Packit fcad23
            } else {
Packit fcad23
                if ((*out_len + 1) >= *buf_len) {
Packit fcad23
                    if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                        return 0;
Packit fcad23
                    }
Packit fcad23
                }
Packit fcad23
                *(*buf + *out_len) = next_chr;
Packit fcad23
                (*out_len)++;
Packit fcad23
                state = PARSE_NORMAL;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case PARSE_GET_WIDTH:
Packit fcad23
            /*
Packit fcad23
             * Parsing a width field.  
Packit fcad23
             */
Packit fcad23
            reset_options = TRUE;
Packit fcad23
            if (isdigit((unsigned char)(next_chr))) {
Packit fcad23
                options.width *= 10;
Packit fcad23
                options.width +=
Packit fcad23
                    (unsigned long) next_chr - (unsigned long) '0';
Packit fcad23
            } else if (next_chr == CHR_FIELD_SEP) {
Packit fcad23
                state = PARSE_GET_PRECISION;
Packit fcad23
            } else if (is_fmt_cmd(next_chr)) {
Packit fcad23
                options.cmd = next_chr;
Packit fcad23
                if (!realloc_dispatch_format_cmd
Packit fcad23
                    (buf, buf_len, out_len, allow_realloc, &options, pdu,
Packit fcad23
                     transport)) {
Packit fcad23
                    return 0;
Packit fcad23
                }
Packit fcad23
                state = PARSE_NORMAL;
Packit fcad23
            } else {
Packit fcad23
                if ((*out_len + 1) >= *buf_len) {
Packit fcad23
                    if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                        return 0;
Packit fcad23
                    }
Packit fcad23
                }
Packit fcad23
                *(*buf + *out_len) = next_chr;
Packit fcad23
                (*out_len)++;
Packit fcad23
                state = PARSE_NORMAL;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case PARSE_GET_PRECISION:
Packit fcad23
            /*
Packit fcad23
             * Parsing a precision field.  
Packit fcad23
             */
Packit fcad23
            reset_options = TRUE;
Packit fcad23
            if (isdigit((unsigned char)(next_chr))) {
Packit fcad23
                if (options.precision == UNDEF_PRECISION) {
Packit fcad23
                    options.precision =
Packit fcad23
                        (unsigned long) next_chr - (unsigned long) '0';
Packit fcad23
                } else {
Packit fcad23
                    options.precision *= 10;
Packit fcad23
                    options.precision +=
Packit fcad23
                        (unsigned long) next_chr - (unsigned long) '0';
Packit fcad23
                }
Packit fcad23
            } else if (is_fmt_cmd(next_chr)) {
Packit fcad23
                options.cmd = next_chr;
Packit fcad23
                if ((options.precision != UNDEF_PRECISION) &&
Packit fcad23
                    (options.width < (size_t)options.precision)) {
Packit fcad23
                    options.width = (size_t)options.precision;
Packit fcad23
                }
Packit fcad23
                if (!realloc_dispatch_format_cmd
Packit fcad23
                    (buf, buf_len, out_len, allow_realloc, &options, pdu,
Packit fcad23
                     transport)) {
Packit fcad23
                    return 0;
Packit fcad23
                }
Packit fcad23
                state = PARSE_NORMAL;
Packit fcad23
            } else {
Packit fcad23
                if ((*out_len + 1) >= *buf_len) {
Packit fcad23
                    if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                        return 0;
Packit fcad23
                    }
Packit fcad23
                }
Packit fcad23
                *(*buf + *out_len) = next_chr;
Packit fcad23
                (*out_len)++;
Packit fcad23
                state = PARSE_NORMAL;
Packit fcad23
            }
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        default:
Packit fcad23
            /*
Packit fcad23
             * Unknown state.  
Packit fcad23
             */
Packit fcad23
            reset_options = TRUE;
Packit fcad23
            if ((*out_len + 1) >= *buf_len) {
Packit fcad23
                if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
Packit fcad23
                    return 0;
Packit fcad23
                }
Packit fcad23
            }
Packit fcad23
            *(*buf + *out_len) = next_chr;
Packit fcad23
            (*out_len)++;
Packit fcad23
            state = PARSE_NORMAL;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    *(*buf + *out_len) = '\0';
Packit fcad23
    return 1;
Packit fcad23
}