snmptrapd_log.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:55k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /*
  2.  * snmptrapd_log.c - format SNMP trap information for logging
  3.  *
  4.  */
  5. /*****************************************************************
  6. Copyright 1989, 1991, 1992 by Carnegie Mellon University
  7.                       All Rights Reserved
  8. Permission to use, copy, modify, and distribute this software and its
  9. documentation for any purpose and without fee is hereby granted,
  10. provided that the above copyright notice appear in all copies and that
  11. both that copyright notice and this permission notice appear in
  12. supporting documentation, and that the name of CMU not be
  13. used in advertising or publicity pertaining to distribution of the
  14. software without specific, written prior permission.
  15. CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22. ******************************************************************/
  23. #include <net-snmp/net-snmp-config.h>
  24. #if HAVE_STDLIB_H
  25. #include <stdlib.h>
  26. #endif
  27. #if HAVE_UNISTD_H
  28. #include <unistd.h>
  29. #endif
  30. #if HAVE_STRING_H
  31. #include <string.h>
  32. #else
  33. #include <strings.h>
  34. #endif
  35. #include <sys/types.h>
  36. #if HAVE_SYS_WAIT_H
  37. #include <sys/wait.h>
  38. #endif
  39. #if HAVE_WINSOCK_H
  40. #include <winsock.h>
  41. #else
  42. #include <sys/socket.h>
  43. #endif
  44. #if HAVE_SYS_SOCKIO_H
  45. #include <sys/sockio.h>
  46. #endif
  47. #if HAVE_NETINET_IN_H
  48. #include <netinet/in.h>
  49. #endif
  50. #include <stdio.h>
  51. #include <ctype.h>
  52. #if HAVE_SYS_TIME_H
  53. # include <sys/time.h>
  54. # if TIME_WITH_SYS_TIME
  55. #  include <time.h>
  56. # endif
  57. #else
  58. # include <time.h>
  59. #endif
  60. #if HAVE_SYS_SELECT_H
  61. #include <sys/select.h>
  62. #endif
  63. #if HAVE_SYS_PARAM_H
  64. #include <sys/param.h>
  65. #endif
  66. #if HAVE_SYSLOG_H
  67. #include <syslog.h>
  68. #endif
  69. #if HAVE_SYS_IOCTL_H
  70. #include <sys/ioctl.h>
  71. #endif
  72. #if HAVE_NET_IF_H
  73. #include <net/if.h>
  74. #endif
  75. #if HAVE_NETDB_H
  76. #include <netdb.h>
  77. #endif
  78. #if HAVE_ARPA_INET_H
  79. #include <arpa/inet.h>
  80. #endif
  81. #if HAVE_FCNTL_H
  82. #include <fcntl.h>
  83. #endif
  84. #include <net-snmp/net-snmp-includes.h>
  85. #include "snmptrapd_log.h"
  86. #ifndef BSD4_3
  87. #define BSD4_2
  88. #endif
  89. /*
  90.  * These flags mark undefined values in the options structure 
  91.  */
  92. #define UNDEF_CMD '*'
  93. #define UNDEF_PRECISION -1
  94. /*
  95.  * This structure holds the options for a single format command 
  96.  */
  97. typedef struct {
  98.     char            cmd;        /* the format command itself */
  99.     size_t          width;      /* the field's minimum width */
  100.     size_t          precision;  /* the field's precision */
  101.     int             left_justify;       /* if true, left justify this field */
  102.     int             alt_format; /* if true, display in alternate format */
  103.     int             leading_zeroes;     /* if true, display with leading zeroes */
  104. } options_type;
  105. char            separator[32];
  106. /*
  107.  * These symbols define the characters that the parser recognizes.
  108.  * The rather odd choice of symbols comes from an attempt to avoid
  109.  * colliding with the ones that printf uses, so that someone could add
  110.  * printf functionality to this code and turn it into a library
  111.  * routine in the future.  
  112.  */
  113. typedef enum {
  114.     CHR_FMT_DELIM = '%',        /* starts a format command */
  115.     CHR_LEFT_JUST = '-',        /* left justify */
  116.     CHR_LEAD_ZERO = '0',        /* use leading zeroes */
  117.     CHR_ALT_FORM = '#',         /* use alternate format */
  118.     CHR_FIELD_SEP = '.',        /* separates width and precision fields */
  119.     CHR_CUR_TIME = 't',         /* current time, Unix format */
  120.     CHR_CUR_YEAR = 'y',         /* current year */
  121.     CHR_CUR_MONTH = 'm',        /* current month */
  122.     CHR_CUR_MDAY = 'l',         /* current day of month */
  123.     CHR_CUR_HOUR = 'h',         /* current hour */
  124.     CHR_CUR_MIN = 'j',          /* current minute */
  125.     CHR_CUR_SEC = 'k',          /* current second */
  126.     CHR_UP_TIME = 'T',          /* uptime, Unix format */
  127.     CHR_UP_YEAR = 'Y',          /* uptime year */
  128.     CHR_UP_MONTH = 'M',         /* uptime month */
  129.     CHR_UP_MDAY = 'L',          /* uptime day of month */
  130.     CHR_UP_HOUR = 'H',          /* uptime hour */
  131.     CHR_UP_MIN = 'J',           /* uptime minute */
  132.     CHR_UP_SEC = 'K',           /* uptime second */
  133.     CHR_AGENT_IP = 'a',         /* agent's IP address */
  134.     CHR_AGENT_NAME = 'A',       /* agent's host name if available */
  135.     CHR_PDU_IP = 'b',           /* PDU's IP address */
  136.     CHR_PDU_NAME = 'B',         /* PDU's host name if available */
  137.     CHR_PDU_ENT = 'N',          /* PDU's enterprise string */
  138.     CHR_PDU_WRAP = 'P',         /* PDU's wrapper info (community, security) */
  139.     CHR_TRAP_NUM = 'w',         /* trap number */
  140.     CHR_TRAP_DESC = 'W',        /* trap's description (textual) */
  141.     CHR_TRAP_STYPE = 'q',       /* trap's subtype */
  142.     CHR_TRAP_VARSEP = 'V',      /* character (or string) to separate variables */
  143.     CHR_TRAP_VARS = 'v'         /* tab-separated list of trap's variables */
  144. } parse_chr_type;
  145. /*
  146.  * These symbols define the states for the parser's state machine 
  147.  */
  148. typedef enum {
  149.     PARSE_NORMAL,               /* looking for next character */
  150.     PARSE_BACKSLASH,            /* saw a backslash */
  151.     PARSE_IN_FORMAT,            /* saw a % sign, in a format command */
  152.     PARSE_GET_WIDTH,            /* getting field width */
  153.     PARSE_GET_PRECISION,        /* getting field precision */
  154.     PARSE_GET_SEPARATOR         /* getting field separator */
  155. } parse_state_type;
  156. /*
  157.  * macros 
  158.  */
  159. #define is_cur_time_cmd(chr) ((((chr) == CHR_CUR_TIME)     
  160.        || ((chr) == CHR_CUR_YEAR)  
  161.        || ((chr) == CHR_CUR_MONTH) 
  162.        || ((chr) == CHR_CUR_MDAY)  
  163.        || ((chr) == CHR_CUR_HOUR)  
  164.        || ((chr) == CHR_CUR_MIN)   
  165.        || ((chr) == CHR_CUR_SEC)) ? TRUE : FALSE)
  166.      /*
  167.       * Function:
  168.       *    Returns true if the character is a format command that outputs
  169.       * some field that deals with the current time.
  170.       *
  171.       * Input Parameters:
  172.       *    chr - character to check
  173.       */
  174. #define is_up_time_cmd(chr) ((((chr) == CHR_UP_TIME)     
  175.       || ((chr) == CHR_UP_YEAR)  
  176.       || ((chr) == CHR_UP_MONTH) 
  177.       || ((chr) == CHR_UP_MDAY)  
  178.       || ((chr) == CHR_UP_HOUR)  
  179.       || ((chr) == CHR_UP_MIN)   
  180.       || ((chr) == CHR_UP_SEC)) ? TRUE : FALSE)
  181.      /*
  182.       * Function:
  183.       *    Returns true if the character is a format command that outputs
  184.       * some field that deals with up-time.
  185.       *
  186.       * Input Parameters:
  187.       *    chr - character to check
  188.       */
  189. #define is_agent_cmd(chr) ((((chr) == CHR_AGENT_IP) 
  190.     || ((chr) == CHR_AGENT_NAME)) ? TRUE : FALSE)
  191.      /*
  192.       * Function:
  193.       *    Returns true if the character outputs information about the
  194.       * agent.
  195.       *
  196.       * Input Parameters:
  197.       *    chr - the character to check
  198.       */
  199. #define is_pdu_ip_cmd(chr) ((((chr) == CHR_PDU_IP)   
  200.   || ((chr) == CHR_PDU_NAME)) ? TRUE : FALSE)
  201.      /*
  202.       * Function:
  203.       *    Returns true if the character outputs information about the PDU's
  204.       * host name or IP address.
  205.       *
  206.       * Input Parameters:
  207.       *    chr - the character to check
  208.       */
  209. #define is_trap_cmd(chr) ((((chr) == CHR_TRAP_NUM)      
  210.    || ((chr) == CHR_TRAP_DESC)  
  211.    || ((chr) == CHR_TRAP_STYPE) 
  212.    || ((chr) == CHR_TRAP_VARS)) ? TRUE : FALSE)
  213.      /*
  214.       * Function:
  215.       *    Returns true if the character outputs information about the trap.
  216.       *
  217.       * Input Parameters:
  218.       *    chr - the character to check
  219.       */
  220. #define is_fmt_cmd(chr) ((is_cur_time_cmd (chr)     
  221.   || is_up_time_cmd (chr)   
  222.   || is_agent_cmd (chr)     
  223.   || is_pdu_ip_cmd (chr)    
  224.                           || ((chr) == CHR_PDU_ENT) 
  225.                           || ((chr) == CHR_PDU_WRAP) 
  226.   || is_trap_cmd (chr)) ? TRUE : FALSE)
  227.      /*
  228.       * Function:
  229.       *    Returns true if the character is a format command.
  230.       * 
  231.       * Input Parameters:
  232.       *    chr - character to check
  233.       */
  234. #define is_numeric_cmd(chr) ((is_cur_time_cmd(chr)   
  235.       || is_up_time_cmd(chr) 
  236.       || (chr) == CHR_TRAP_NUM) ? TRUE : FALSE)
  237.      /*
  238.       * Function:
  239.       *    Returns true if this is a numeric format command.
  240.       *
  241.       * Input Parameters:
  242.       *    chr - character to check
  243.       */
  244. #define reference(var) ((var) == (var))
  245.      /*
  246.       * Function:
  247.       *    Some compiler options will tell the compiler to be picky and
  248.       * warn you if you pass a parameter to a function but don't use it.
  249.       * This macro lets you reference a parameter so that the compiler won't
  250.       * generate the warning. It has no other effect.
  251.       *
  252.       * Input Parameters:
  253.       *    var - the parameter to reference
  254.       */
  255. /*
  256.  * prototypes 
  257.  */
  258. extern const char *trap_description(int trap);
  259. static void
  260. init_options(options_type * options)
  261.      /*
  262.       * Function:
  263.       *    Initialize a structure that contains the option settings for
  264.       * a format command.
  265.       *
  266.       * Input Parameters:
  267.       *    options - points to the structure to initialize
  268.       */
  269. {
  270.     /*
  271.      * initialize the structure's fields 
  272.      */
  273.     options->cmd = '*';
  274.     options->width = 0;
  275.     options->precision = UNDEF_PRECISION;
  276.     options->left_justify = FALSE;
  277.     options->alt_format = FALSE;
  278.     options->leading_zeroes = FALSE;
  279.     return;
  280. }
  281. static int
  282. realloc_output_temp_bfr(u_char ** buf, size_t * buf_len, size_t * out_len,
  283.                         int allow_realloc,
  284.                         u_char ** temp_buf, options_type * options)
  285.      /*
  286.       * Function:
  287.       *    Append the contents of the temporary buffer to the specified
  288.       * buffer using the correct justification, leading zeroes, width,
  289.       * precision, and other characteristics specified in the options
  290.       * structure.
  291.       *
  292.       *    buf, buf_len, out_len, allow_realloc - standard relocatable
  293.       *                                           buffer parameters
  294.       *    temp_buf - pointer to string to append onto output buffer.  THIS
  295.       *               STRING IS free()d BY THIS FUNCTION.
  296.       *    options  - what options to use when appending string
  297.       */
  298. {
  299.     size_t          temp_len;   /* length of temporary buffer */
  300.     size_t          temp_to_write;      /* # of chars to write from temp bfr */
  301.     size_t          char_to_write;      /* # of other chars to write */
  302.     size_t          zeroes_to_write;    /* fill to precision with zeroes for numbers */
  303.     if (temp_buf == NULL || *temp_buf == NULL) {
  304.         return 1;
  305.     }
  306.     /*
  307.      * Figure out how many characters are in the temporary buffer now,
  308.      * and how many of them we'll write.
  309.      */
  310.     temp_len = strlen((char *) *temp_buf);
  311.     temp_to_write = temp_len;
  312.     if (options->precision != UNDEF_PRECISION &&
  313.         temp_to_write > options->precision) {
  314.         temp_to_write = options->precision;
  315.     }
  316.     /*
  317.      * Handle leading characters.  
  318.      */
  319.     if ((!options->left_justify) && (temp_to_write < options->width)) {
  320.         zeroes_to_write = options->precision - temp_to_write;
  321.         if (!is_numeric_cmd(options->cmd)) {
  322.             zeroes_to_write = 0;
  323.         }
  324.         for (char_to_write = options->width - temp_to_write;
  325.              char_to_write > 0; char_to_write--) {
  326.             if ((*out_len + 1) >= *buf_len) {
  327.                 if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
  328.                     *(*buf + *out_len) = '';
  329.                     free(*temp_buf);
  330.                     return 0;
  331.                 }
  332.             }
  333.             if (options->leading_zeroes || zeroes_to_write-- > 0) {
  334.                 *(*buf + *out_len) = '0';
  335.             } else {
  336.                 *(*buf + *out_len) = ' ';
  337.             }
  338.             (*out_len)++;
  339.         }
  340.     }
  341.     /*
  342.      * Truncate the temporary buffer and append its contents.  
  343.      */
  344.     *(*temp_buf + temp_to_write) = '';
  345.     if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, *temp_buf)) {
  346.         free(*temp_buf);
  347.         return 0;
  348.     }
  349.     /*
  350.      * Handle trailing characters.  
  351.      */
  352.     if ((options->left_justify) && (temp_to_write < options->width)) {
  353.         for (char_to_write = options->width - temp_to_write;
  354.              char_to_write > 0; char_to_write--) {
  355.             if ((*out_len + 1) >= *buf_len) {
  356.                 if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
  357.                     *(*buf + *out_len) = '';
  358.                     free(*temp_buf);
  359.                     return 0;
  360.                 }
  361.             }
  362.             *(*buf + *out_len) = '0';
  363.             (*out_len)++;
  364.         }
  365.     }
  366.     /*
  367.      * Slap on a trailing  for good measure.  
  368.      */
  369.     *(*buf + *out_len) = '';
  370.     free(*temp_buf);
  371.     *temp_buf = NULL;
  372.     return 1;
  373. }
  374. static int
  375. realloc_handle_time_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
  376.                         int allow_realloc,
  377.                         options_type * options, netsnmp_pdu *pdu)
  378.      /*
  379.       * Function:
  380.       *    Handle a format command that deals with the current or up-time.
  381.       * Append the correct time information to the buffer subject to the
  382.       * buffer's length limit.
  383.       *
  384.       * Input Parameters:
  385.       *    buf, buf_len, out_len, allow_realloc - standard relocatable
  386.       *                                           buffer parameters
  387.       *    options - options governing how to write the field
  388.       *    pdu     - information about this trap
  389.       */
  390. {
  391.     time_t          time_val;   /* the time value to output */
  392.     unsigned long   time_ul;    /* u_long time/timeticks */
  393.     struct tm      *parsed_time;        /* parsed version of current time */
  394.     char           *safe_bfr = NULL;
  395.     char            fmt_cmd = options->cmd;     /* the format command to use */
  396.     int             offset = 0; /* offset into string to display */
  397.     size_t          year_len;   /* length of year string */
  398.     if ((safe_bfr = (char *) calloc(30, 1)) == NULL) {
  399.         return 0;
  400.     }
  401.     /*
  402.      * Get the time field to output.  
  403.      */
  404.     if (is_up_time_cmd(fmt_cmd)) {
  405.         time_ul = pdu->time;
  406.     } else {
  407.         /*
  408.          * Note: a time_t is a signed long.  
  409.          */
  410.         time(&time_val);
  411.         time_ul = (unsigned long) time_val;
  412.     }
  413.     /*
  414.      * Handle output in Unix time format.  
  415.      */
  416.     if (fmt_cmd == CHR_CUR_TIME) {
  417.         sprintf(safe_bfr, "%lu", time_ul);
  418.     } else if (fmt_cmd == CHR_UP_TIME && !options->alt_format) {
  419.         sprintf(safe_bfr, "%lu", time_ul);
  420.     } else if (fmt_cmd == CHR_UP_TIME) {
  421.         unsigned int    centisecs, seconds, minutes, hours, days;
  422.         centisecs = time_ul % 100;
  423.         time_ul /= 100;
  424.         days = time_ul / (60 * 60 * 24);
  425.         time_ul %= (60 * 60 * 24);
  426.         hours = time_ul / (60 * 60);
  427.         time_ul %= (60 * 60);
  428.         minutes = time_ul / 60;
  429.         seconds = time_ul % 60;
  430.         switch (days) {
  431.         case 0:
  432.             sprintf(safe_bfr, "%u:%02u:%02u.%02u",
  433.                     hours, minutes, seconds, centisecs);
  434.             break;
  435.         case 1:
  436.             sprintf(safe_bfr, "1 day, %u:%02u:%02u.%02u",
  437.                     hours, minutes, seconds, centisecs);
  438.             break;
  439.         default:
  440.             sprintf(safe_bfr, "%u days, %u:%02u:%02u.%02u",
  441.                     days, hours, minutes, seconds, centisecs);
  442.         }
  443.     } else {
  444.         /*
  445.          * Handle other time fields.  
  446.          */
  447.         if (options->alt_format) {
  448.             parsed_time = gmtime(&time_val);
  449.         } else {
  450.             parsed_time = localtime(&time_val);
  451.         }
  452.         switch (fmt_cmd) {
  453.             /*
  454.              * Output year. The year field is unusual: if there's a restriction 
  455.              * on precision, we want to truncate from the left of the number,
  456.              * not the right, so someone printing the year 1972 with 2 digit 
  457.              * precision gets "72" not "19".
  458.              */
  459.         case CHR_CUR_YEAR:
  460.         case CHR_UP_YEAR:
  461.             sprintf(safe_bfr, "%d", parsed_time->tm_year + 1900);
  462.             if (options->precision != UNDEF_PRECISION) {
  463.                 year_len = (size_t) strlen(safe_bfr);
  464.                 if (year_len > options->precision)
  465.                     offset = year_len - options->precision;
  466.             }
  467.             break;
  468.             /*
  469.              * output month 
  470.              */
  471.         case CHR_CUR_MONTH:
  472.         case CHR_UP_MONTH:
  473.             sprintf(safe_bfr, "%d", parsed_time->tm_mon + 1);
  474.             break;
  475.             /*
  476.              * output day of month 
  477.              */
  478.         case CHR_CUR_MDAY:
  479.         case CHR_UP_MDAY:
  480.             sprintf(safe_bfr, "%d", parsed_time->tm_mday);
  481.             break;
  482.             /*
  483.              * output hour 
  484.              */
  485.         case CHR_CUR_HOUR:
  486.         case CHR_UP_HOUR:
  487.             sprintf(safe_bfr, "%d", parsed_time->tm_hour);
  488.             break;
  489.             /*
  490.              * output minute 
  491.              */
  492.         case CHR_CUR_MIN:
  493.         case CHR_UP_MIN:
  494.             sprintf(safe_bfr, "%d", parsed_time->tm_min);
  495.             break;
  496.             /*
  497.              * output second 
  498.              */
  499.         case CHR_CUR_SEC:
  500.         case CHR_UP_SEC:
  501.             sprintf(safe_bfr, "%d", parsed_time->tm_sec);
  502.             break;
  503.             /*
  504.              * unknown format command - just output the character 
  505.              */
  506.         default:
  507.             sprintf(safe_bfr, "%c", fmt_cmd);
  508.         }
  509.     }
  510.     /*
  511.      * Output with correct justification, leading zeroes, etc.  
  512.      */
  513.     return realloc_output_temp_bfr(buf, buf_len, out_len, allow_realloc,
  514.                                    (u_char **) & safe_bfr, options);
  515. }
  516. static int
  517. realloc_handle_ip_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
  518.                       int allow_realloc,
  519.                       options_type * options, netsnmp_pdu *pdu,
  520.                       netsnmp_transport *transport)
  521.      /*
  522.       * Function:
  523.       *     Handle a format command that deals with an IP address 
  524.       * or host name.  Append the information to the buffer subject to
  525.       * the buffer's length limit.
  526.       *
  527.       * Input Parameters:
  528.       *    buf, buf_len, out_len, allow_realloc - standard relocatable
  529.       *                                           buffer parameters
  530.       *    options   - options governing how to write the field
  531.       *    pdu       - information about this trap 
  532.       *    transport - the transport descriptor
  533.       */
  534. {
  535.     struct in_addr *agent_inaddr = (struct in_addr *) pdu->agent_addr;
  536.     struct hostent *host = NULL;       /* corresponding host name */
  537.     char            fmt_cmd = options->cmd;     /* what we're formatting */
  538.     u_char         *temp_buf = NULL;
  539.     size_t          temp_buf_len = 64, temp_out_len = 0;
  540.     if ((temp_buf = calloc(temp_buf_len, 1)) == NULL) {
  541.         return 0;
  542.     }
  543.     /*
  544.      * Decide exactly what to output.  
  545.      */
  546.     switch (fmt_cmd) {
  547.     case CHR_AGENT_IP:
  548.         /*
  549.          * Write a numerical address.  
  550.          */
  551.         if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len, 1,
  552.                          inet_ntoa(*agent_inaddr))) {
  553.             if (temp_buf != NULL) {
  554.                 free(temp_buf);
  555.             }
  556.             return 0;
  557.         }
  558.         break;
  559.     case CHR_AGENT_NAME:
  560.         /*
  561.          * Try to resolve the agent_addr field as a hostname; fall back
  562.          * to numerical address.  
  563.          */
  564.         if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
  565.                                     NETSNMP_DS_APP_NUMERIC_IP)) {
  566.             host = gethostbyaddr((char *) pdu->agent_addr, 4, AF_INET);
  567.         }
  568.         if (host != NULL) {
  569.             if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len, 1,
  570.                              host->h_name)) {
  571.                 if (temp_buf != NULL) {
  572.                     free(temp_buf);
  573.                 }
  574.                 return 0;
  575.             }
  576.         } else {
  577.             if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len, 1,
  578.                              inet_ntoa(*agent_inaddr))) {
  579.                 if (temp_buf != NULL) {
  580.                     free(temp_buf);
  581.                 }
  582.                 return 0;
  583.             }
  584.         }
  585.         break;
  586.     case CHR_PDU_IP:
  587.         /*
  588.          * Write the numerical transport information.  
  589.          */
  590.         if (transport != NULL && transport->f_fmtaddr != NULL) {
  591.             char           *tstr =
  592.                 transport->f_fmtaddr(transport, pdu->transport_data,
  593.                                      pdu->transport_data_length);
  594.             if (!snmp_strcat
  595.                 (&temp_buf, &temp_buf_len, &temp_out_len, 1, tstr)) {
  596.                 if (tstr != NULL) {
  597.                     free(tstr);
  598.                 }
  599.                 if (temp_buf != NULL) {
  600.                     free(temp_buf);
  601.                 }
  602.                 return 0;
  603.             }
  604.             if (tstr != NULL) {
  605.                 free(tstr);
  606.             }
  607.         } else {
  608.             if (!snmp_strcat
  609.                 (&temp_buf, &temp_buf_len, &temp_out_len, 1,
  610.                  "<UNKNOWN>")) {
  611.                 if (temp_buf != NULL) {
  612.                     free(temp_buf);
  613.                 }
  614.                 return 0;
  615.             }
  616.         }
  617.         break;
  618.         /*
  619.          * Write a host name.  
  620.          */
  621.     case CHR_PDU_NAME:
  622.         /*
  623.          * Right, apparently a name lookup is wanted.  This is only reasonable
  624.          * for the UDP and TCP transport domains (we don't want to try to be
  625.          * too clever here).  
  626.          */
  627. #ifdef SNMP_TRANSPORT_TCP_DOMAIN
  628.         if (transport != NULL && (transport->domain == netsnmpUDPDomain ||
  629.                                   transport->domain ==
  630.                                   netsnmp_snmpTCPDomain)) {
  631. #else
  632.         if (transport != NULL && transport->domain == netsnmpUDPDomain) {
  633. #endif
  634.             /*
  635.              * This is kind of bletcherous -- it breaks the opacity of
  636.              * transport_data but never mind -- the alternative is a lot of
  637.              * munging strings from f_fmtaddr.  
  638.              */
  639.             struct sockaddr_in *addr =
  640.                 (struct sockaddr_in *) pdu->transport_data;
  641.             if (addr != NULL
  642.                 && pdu->transport_data_length ==
  643.                 sizeof(struct sockaddr_in)) {
  644.                 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
  645.                                             NETSNMP_DS_APP_NUMERIC_IP)) {
  646.                     host =
  647.                         gethostbyaddr((char *) &(addr->sin_addr),
  648.                                       sizeof(struct in_addr), AF_INET);
  649.                 }
  650.                 if (host != NULL) {
  651.                     if (!snmp_strcat
  652.                         (&temp_buf, &temp_buf_len, &temp_out_len, 1,
  653.                          host->h_name)) {
  654.                         if (temp_buf != NULL) {
  655.                             free(temp_buf);
  656.                         }
  657.                         return 0;
  658.                     }
  659.                 } else {
  660.                     if (!snmp_strcat
  661.                         (&temp_buf, &temp_buf_len, &temp_out_len, 1,
  662.                          inet_ntoa(addr->sin_addr))) {
  663.                         if (temp_buf != NULL) {
  664.                             free(temp_buf);
  665.                         }
  666.                         return 0;
  667.                     }
  668.                 }
  669.             } else {
  670.                 if (!snmp_strcat
  671.                     (&temp_buf, &temp_buf_len, &temp_out_len, 1,
  672.                      "<UNKNOWN>")) {
  673.                     if (temp_buf != NULL) {
  674.                         free(temp_buf);
  675.                     }
  676.                     return 0;
  677.                 }
  678.             }
  679.         } else if (transport != NULL && transport->f_fmtaddr != NULL) {
  680.             /*
  681.              * Some other domain for which we do not know how to do a name
  682.              * lookup.  Fall back to the formatted transport address.  
  683.              */
  684.             char           *tstr =
  685.                 transport->f_fmtaddr(transport, pdu->transport_data,
  686.                                      pdu->transport_data_length);
  687.             if (!snmp_strcat
  688.                 (&temp_buf, &temp_buf_len, &temp_out_len, 1, tstr)) {
  689.                 if (tstr != NULL) {
  690.                     free(tstr);
  691.                 }
  692.                 if (temp_buf != NULL) {
  693.                     free(temp_buf);
  694.                 }
  695.                 return 0;
  696.             }
  697.             if (tstr != NULL) {
  698.                 free(tstr);
  699.             }
  700.         } else {
  701.             /*
  702.              * We are kind of stuck!  
  703.              */
  704.             if (!snmp_strcat(&temp_buf, &temp_buf_len, &temp_out_len, 1,
  705.                              "<UNKNOWN>")) {
  706.                 if (temp_buf != NULL) {
  707.                     free(temp_buf);
  708.                 }
  709.                 return 0;
  710.             }
  711.         }
  712.         break;
  713.         /*
  714.          * Don't know how to handle this command - write the character itself.  
  715.          */
  716.     default:
  717.         temp_buf[0] = fmt_cmd;
  718.     }
  719.     /*
  720.      * Output with correct justification, leading zeroes, etc.  
  721.      */
  722.     return realloc_output_temp_bfr(buf, buf_len, out_len, allow_realloc,
  723.                                    &temp_buf, options);
  724. }
  725. static int
  726. realloc_handle_ent_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
  727.                        int allow_realloc,
  728.                        options_type * options, netsnmp_pdu *pdu)
  729.      /*
  730.       * Function:
  731.       *     Handle a format command that deals with the enterprise 
  732.       * string.  Append the information to the buffer subject to the
  733.       * buffer's length limit.
  734.       *
  735.       * Input Parameters:
  736.       *    buf, buf_len, out_len, allow_realloc - standard relocatable
  737.       *                                           buffer parameters
  738.       *    options - options governing how to write the field
  739.       *    pdu     - information about this trap 
  740.       */
  741. {
  742.     char            fmt_cmd = options->cmd;     /* what we're formatting */
  743.     u_char         *temp_buf = NULL;
  744.     size_t          temp_buf_len = 64, temp_out_len = 0;
  745.     if ((temp_buf = (u_char *) calloc(temp_buf_len, 1)) == NULL) {
  746.         return 0;
  747.     }
  748.     /*
  749.      * Decide exactly what to output.  
  750.      */
  751.     switch (fmt_cmd) {
  752.     case CHR_PDU_ENT:
  753.         /*
  754.          * Write the enterprise oid.  
  755.          */
  756.         if (!sprint_realloc_objid
  757.             (&temp_buf, &temp_buf_len, &temp_out_len, 1, pdu->enterprise,
  758.              pdu->enterprise_length)) {
  759.             free(temp_buf);
  760.             return 0;
  761.         }
  762.         break;
  763.         /*
  764.          * Don't know how to handle this command - write the character itself.  
  765.          */
  766.     default:
  767.         temp_buf[0] = fmt_cmd;
  768.     }
  769.     /*
  770.      * Output with correct justification, leading zeroes, etc.  
  771.      */
  772.     return realloc_output_temp_bfr(buf, buf_len, out_len, allow_realloc,
  773.                                    &temp_buf, options);
  774. }
  775. static int
  776. realloc_handle_trap_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
  777.                         int allow_realloc,
  778.                         options_type * options, netsnmp_pdu *pdu)
  779.      /*
  780.       * Function:
  781.       *     Handle a format command that deals with the trap itself. 
  782.       * Append the information to the buffer subject to the buffer's 
  783.       * length limit.
  784.       *
  785.       * Input Parameters:
  786.       *    buf, buf_len, out_len, allow_realloc - standard relocatable
  787.       *                                           buffer parameters
  788.       *    options - options governing how to write the field
  789.       *    pdu     - information about this trap 
  790.       */
  791. {
  792.     netsnmp_variable_list *vars;        /* variables assoc with trap */
  793.     char            fmt_cmd = options->cmd;     /* what we're outputting */
  794.     u_char         *temp_buf = NULL;
  795.     size_t          tbuf_len = 64, tout_len = 0;
  796.     const char           *sep = separator;
  797.     const char           *default_sep = "t";
  798.     const char           *default_alt_sep = ", ";
  799.     if ((temp_buf = (u_char *) calloc(tbuf_len, 1)) == NULL) {
  800.         return 0;
  801.     }
  802.     /*
  803.      * Decide exactly what to output.  
  804.      */
  805.     switch (fmt_cmd) {
  806.     case CHR_TRAP_NUM:
  807.         /*
  808.          * Write the trap's number.  
  809.          */
  810.         tout_len = sprintf(temp_buf, "%ld", pdu->trap_type);
  811.         break;
  812.     case CHR_TRAP_DESC:
  813.         /*
  814.          * Write the trap's description.  
  815.          */
  816.         tout_len =
  817.             sprintf(temp_buf, "%s", trap_description(pdu->trap_type));
  818.         break;
  819.     case CHR_TRAP_STYPE:
  820.         /*
  821.          * Write the trap's subtype.  
  822.          */
  823.         if (pdu->trap_type != SNMP_TRAP_ENTERPRISESPECIFIC) {
  824.             tout_len = sprintf(temp_buf, "%ld", pdu->specific_type);
  825.         } else {
  826.             /*
  827.              * Get object ID for the trap.  
  828.              */
  829.             size_t          obuf_len = 64, oout_len = 0, trap_oid_len = 0;
  830.             oid             trap_oid[MAX_OID_LEN + 2] = { 0 };
  831.             u_char         *obuf = NULL;
  832.             char           *ptr = NULL;
  833.             if ((obuf = (u_char *) calloc(obuf_len, 1)) == NULL) {
  834.                 free(temp_buf);
  835.                 return 0;
  836.             }
  837.             trap_oid_len = pdu->enterprise_length;
  838.             memcpy(trap_oid, pdu->enterprise, trap_oid_len * sizeof(oid));
  839.             if (trap_oid[trap_oid_len - 1] != 0) {
  840.                 trap_oid[trap_oid_len] = 0;
  841.                 trap_oid_len++;
  842.             }
  843.             trap_oid[trap_oid_len] = pdu->specific_type;
  844.             trap_oid_len++;
  845.             /*
  846.              * Find the element after the last dot.  
  847.              */
  848.             if (!sprint_realloc_objid(&obuf, &obuf_len, &oout_len, 1,
  849.                                       trap_oid, trap_oid_len)) {
  850.                 if (obuf != NULL) {
  851.                     free(obuf);
  852.                 }
  853.                 free(temp_buf);
  854. return 0;
  855.             }
  856.             ptr = strrchr((char *) obuf, '.');
  857.             if (ptr != NULL) {
  858.                 if (!snmp_strcat
  859.                     (&temp_buf, &tbuf_len, &tout_len, 1, (u_char *) ptr)) {
  860.                     free(obuf);
  861.                     if (temp_buf != NULL) {
  862.                         free(temp_buf);
  863.                     }
  864.                     return 0;
  865.                 }
  866.                 free(obuf);
  867.             } else {
  868.                 free(temp_buf);
  869.                 temp_buf = obuf;
  870.                 tbuf_len = obuf_len;
  871.                 tout_len = oout_len;
  872.             }
  873.         }
  874.         break;
  875.     case CHR_TRAP_VARS:
  876.         /*
  877.          * Write the trap's variables.  
  878.          */
  879.         if (!sep || !*sep)
  880.             sep = (options->alt_format ? default_alt_sep : default_sep);
  881.         for (vars = pdu->variables; vars != NULL;
  882.              vars = vars->next_variable) {
  883.             /*
  884.              * Print a separator between variables,
  885.              *   (plus beforehand if the alt format is used)
  886.              */
  887.             if (options->alt_format ||
  888.                 vars != pdu->variables ) {
  889.                 if (!snmp_strcat(&temp_buf, &tbuf_len, &tout_len, 1, sep)) {
  890.                     if (temp_buf != NULL) {
  891.                         free(temp_buf);
  892.                     }
  893.                     return 0;
  894.                 }
  895.             }
  896.             if (!sprint_realloc_variable
  897.                 (&temp_buf, &tbuf_len, &tout_len, 1, vars->name,
  898.                  vars->name_length, vars)) {
  899.                 if (temp_buf != NULL) {
  900.                     free(temp_buf);
  901.                 }
  902.                 return 0;
  903.             }
  904.         }
  905.         break;
  906.     default:
  907.         /*
  908.          * Don't know how to handle this command - write the character itself.  
  909.          */
  910.         temp_buf[0] = fmt_cmd;
  911.     }
  912.     /*
  913.      * Output with correct justification, leading zeroes, etc.  
  914.      */
  915.     return realloc_output_temp_bfr(buf, buf_len, out_len, allow_realloc,
  916.                                    &temp_buf, options);
  917. }
  918. static int
  919. realloc_handle_wrap_fmt(u_char ** buf, size_t * buf_len, size_t * out_len,
  920.                         int allow_realloc, netsnmp_pdu *pdu)
  921. {
  922.     size_t          i = 0;
  923.     switch (pdu->command) {
  924.     case SNMP_MSG_TRAP:
  925.         if (!snmp_strcat
  926.             (buf, buf_len, out_len, allow_realloc,
  927.              (const u_char *) "TRAP")) {
  928.             return 0;
  929.         }
  930.         break;
  931.     case SNMP_MSG_TRAP2:
  932.         if (!snmp_strcat
  933.             (buf, buf_len, out_len, allow_realloc,
  934.              (const u_char *) "TRAP2")) {
  935.             return 0;
  936.         }
  937.         break;
  938.     case SNMP_MSG_INFORM:
  939.         if (!snmp_strcat
  940.             (buf, buf_len, out_len, allow_realloc,
  941.              (const u_char *) "INFORM")) {
  942.             return 0;
  943.         }
  944.         break;
  945.     }
  946.     switch (pdu->version) {
  947. #ifndef DISABLE_SNMPV1
  948.     case SNMP_VERSION_1:
  949.         if (!snmp_strcat
  950.             (buf, buf_len, out_len, allow_realloc,
  951.              (const u_char *) ", SNMP v1")) {
  952.             return 0;
  953.         }
  954.         break;
  955. #endif
  956. #ifndef DISABLE_SNMPV2C
  957.     case SNMP_VERSION_2c:
  958.         if (!snmp_strcat
  959.             (buf, buf_len, out_len, allow_realloc,
  960.              (const u_char *) ", SNMP v2c")) {
  961.             return 0;
  962.         }
  963.         break;
  964. #endif
  965.     case SNMP_VERSION_3:
  966.         if (!snmp_strcat
  967.             (buf, buf_len, out_len, allow_realloc,
  968.              (const u_char *) ", SNMP v3")) {
  969.             return 0;
  970.         }
  971.         break;
  972.     }
  973.     switch (pdu->version) {
  974. #if !defined(DISABLE_SNMPV1) || !defined(DISABLE_SNMPV2C)
  975.     case SNMP_VERSION_1:
  976.     case SNMP_VERSION_2c:
  977.         if (!snmp_strcat
  978.             (buf, buf_len, out_len, allow_realloc,
  979.              (const u_char *) ", community ")) {
  980.             return 0;
  981.         }
  982.         while ((*out_len + pdu->community_len + 1) >= *buf_len) {
  983.             if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
  984.                 return 0;
  985.             }
  986.         }
  987.         for (i = 0; i < pdu->community_len; i++) {
  988.             if (isprint(pdu->community[i])) {
  989.                 *(*buf + *out_len) = pdu->community[i];
  990.             } else {
  991.                 *(*buf + *out_len) = '.';
  992.             }
  993.             (*out_len)++;
  994.         }
  995.         *(*buf + *out_len) = '';
  996.         break;
  997. #endif
  998.     case SNMP_VERSION_3:
  999.         if (!snmp_strcat
  1000.             (buf, buf_len, out_len, allow_realloc,
  1001.              (const u_char *) ", user ")) {
  1002.             return 0;
  1003.         }
  1004.         while ((*out_len + pdu->securityNameLen + 1) >= *buf_len) {
  1005.             if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
  1006.                 return 0;
  1007.             }
  1008.         }
  1009.         for (i = 0; i < pdu->securityNameLen; i++) {
  1010.             if (isprint(pdu->securityName[i])) {
  1011.                 *(*buf + *out_len) = pdu->securityName[i];
  1012.             } else {
  1013.                 *(*buf + *out_len) = '.';
  1014.             }
  1015.             (*out_len)++;
  1016.         }
  1017.         *(*buf + *out_len) = '';
  1018.         if (!snmp_strcat
  1019.             (buf, buf_len, out_len, allow_realloc,
  1020.              (const u_char *) ", context ")) {
  1021.             return 0;
  1022.         }
  1023.         while ((*out_len + pdu->contextNameLen + 1) >= *buf_len) {
  1024.             if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
  1025.                 return 0;
  1026.             }
  1027.         }
  1028.         for (i = 0; i < pdu->contextNameLen; i++) {
  1029.             if (isprint(pdu->contextName[i])) {
  1030.                 *(*buf + *out_len) = pdu->contextName[i];
  1031.             } else {
  1032.                 *(*buf + *out_len) = '.';
  1033.             }
  1034.             (*out_len)++;
  1035.         }
  1036.         *(*buf + *out_len) = '';
  1037.     }
  1038.     return 1;
  1039. }
  1040. static int
  1041. realloc_dispatch_format_cmd(u_char ** buf, size_t * buf_len,
  1042.                             size_t * out_len, int allow_realloc,
  1043.                             options_type * options, netsnmp_pdu *pdu,
  1044.                             netsnmp_transport *transport)
  1045.      /*
  1046.       * Function:
  1047.       *     Dispatch a format command to the appropriate command handler.
  1048.       *
  1049.       * Input Parameters:
  1050.       *    buf, buf_len, out_len, allow_realloc - standard relocatable
  1051.       *                                           buffer parameters
  1052.       *    options   - options governing how to write the field
  1053.       *    pdu       - information about this trap
  1054.       *    transport - the transport descriptor
  1055.       */
  1056. {
  1057.     char            fmt_cmd = options->cmd;     /* for speed */
  1058.     /*
  1059.      * choose the appropriate command handler 
  1060.      */
  1061.     if (is_cur_time_cmd(fmt_cmd) || is_up_time_cmd(fmt_cmd)) {
  1062.         return realloc_handle_time_fmt(buf, buf_len, out_len,
  1063.                                        allow_realloc, options, pdu);
  1064.     } else if (is_agent_cmd(fmt_cmd) || is_pdu_ip_cmd(fmt_cmd)) {
  1065.         return realloc_handle_ip_fmt(buf, buf_len, out_len, allow_realloc,
  1066.                                      options, pdu, transport);
  1067.     } else if (is_trap_cmd(fmt_cmd)) {
  1068.         return realloc_handle_trap_fmt(buf, buf_len, out_len,
  1069.                                        allow_realloc, options, pdu);
  1070.     } else if (fmt_cmd == CHR_PDU_ENT) {
  1071.         return realloc_handle_ent_fmt(buf, buf_len, out_len, allow_realloc,
  1072.                                       options, pdu);
  1073.     } else if (fmt_cmd == CHR_PDU_WRAP) {
  1074.         return realloc_handle_wrap_fmt(buf, buf_len, out_len,
  1075.                                        allow_realloc, pdu);
  1076.     } else {
  1077.         /*
  1078.          * unknown format command - just output the character 
  1079.          */
  1080.         char            fmt_cmd_string[2] = { 0, 0 };
  1081.         fmt_cmd_string[0] = fmt_cmd;
  1082.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1083.                            (const u_char *) fmt_cmd_string);
  1084.     }
  1085. }
  1086. static int
  1087. realloc_handle_backslash(u_char ** buf, size_t * buf_len, size_t * out_len,
  1088.                          int allow_realloc, char fmt_cmd)
  1089.      /*
  1090.       * Function:
  1091.       *     Handle a character following a backslash. Append the resulting 
  1092.       * character to the buffer subject to the buffer's length limit.
  1093.       *     This routine currently isn't sophisticated enough to handle
  1094.       * nnn or xhh formats.
  1095.       *
  1096.       * Input Parameters:
  1097.       *    buf, buf_len, out_len, allow_realloc - standard relocatable
  1098.       *                                           buffer parameters
  1099.       *    fmt_cmd - the character after the backslash
  1100.       */
  1101. {
  1102.     char            temp_bfr[3];        /* for bulding temporary strings */
  1103.     /*
  1104.      * select the proper output character(s) 
  1105.      */
  1106.     switch (fmt_cmd) {
  1107.     case 'a':
  1108.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1109.                            (const u_char *) "a");
  1110.     case 'b':
  1111.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1112.                            (const u_char *) "b");
  1113.     case 'f':
  1114.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1115.                            (const u_char *) "f");
  1116.     case 'n':
  1117.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1118.                            (const u_char *) "n");
  1119.     case 'r':
  1120.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1121.                            (const u_char *) "r");
  1122.     case 't':
  1123.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1124.                            (const u_char *) "t");
  1125.     case 'v':
  1126.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1127.                            (const u_char *) "v");
  1128.     case '\':
  1129.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1130.                            (const u_char *) "\");
  1131.     case '?':
  1132.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1133.                            (const u_char *) "?");
  1134.     case '%':
  1135.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1136.                            (const u_char *) "%");
  1137.     case ''':
  1138.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1139.                            (const u_char *) "'");
  1140.     case '"':
  1141.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1142.                            (const u_char *) """);
  1143.     default:
  1144.         sprintf(temp_bfr, "\%c", fmt_cmd);
  1145.         return snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1146.                            (const u_char *) temp_bfr);
  1147.     }
  1148. }
  1149. int
  1150. realloc_format_plain_trap(u_char ** buf, size_t * buf_len,
  1151.                           size_t * out_len, int allow_realloc,
  1152.                           netsnmp_pdu *pdu, netsnmp_transport *transport)
  1153.      /*
  1154.       * Function:
  1155.       *    Format the trap information in the default way and put the results
  1156.       * into the buffer, truncating at the buffer's length limit. This
  1157.       * routine returns 1 if the output was completed successfully or
  1158.       * 0 if it is truncated due to a memory allocation failure.
  1159.       *
  1160.       * Input Parameters:
  1161.       *    buf, buf_len, out_len, allow_realloc - standard relocatable
  1162.       *                                           buffer parameters
  1163.       *    pdu       - the pdu information
  1164.       *    transport - the transport descriptor
  1165.       */
  1166. {
  1167.     time_t          now;        /* the current time */
  1168.     struct tm      *now_parsed; /* time in struct format */
  1169.     char            safe_bfr[200];      /* holds other strings */
  1170.     struct in_addr *agent_inaddr = (struct in_addr *) pdu->agent_addr;
  1171.     struct hostent *host = NULL;       /* host name */
  1172.     netsnmp_variable_list *vars;        /* variables assoc with trap */
  1173.     if (buf == NULL) {
  1174.         return 0;
  1175.     }
  1176.     /*
  1177.      * Print the current time. Since we don't know how long the buffer is,
  1178.      * and snprintf isn't yet standard, build the timestamp in a separate
  1179.      * buffer of guaranteed length and then copy it to the output buffer.
  1180.      */
  1181.     time(&now);
  1182.     now_parsed = localtime(&now);
  1183.     sprintf(safe_bfr, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d ",
  1184.             now_parsed->tm_year + 1900, now_parsed->tm_mon + 1,
  1185.             now_parsed->tm_mday, now_parsed->tm_hour,
  1186.             now_parsed->tm_min, now_parsed->tm_sec);
  1187.     if (!snmp_strcat
  1188.         (buf, buf_len, out_len, allow_realloc,
  1189.          (const u_char *) safe_bfr)) {
  1190.         return 0;
  1191.     }
  1192.     /*
  1193.      * Get info about the sender.  
  1194.      */
  1195.     if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
  1196.                                 NETSNMP_DS_APP_NUMERIC_IP)) {
  1197.         host = gethostbyaddr((char *) pdu->agent_addr, 4, AF_INET);
  1198.     }
  1199.     if (host != (struct hostent *) NULL) {
  1200.         if (!snmp_strcat
  1201.             (buf, buf_len, out_len, allow_realloc,
  1202.              (const u_char *) host->h_name)) {
  1203.             return 0;
  1204.         }
  1205.         if (!snmp_strcat
  1206.             (buf, buf_len, out_len, allow_realloc,
  1207.              (const u_char *) " [")) {
  1208.             return 0;
  1209.         }
  1210.         if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1211.                          (const u_char *) inet_ntoa(*agent_inaddr))) {
  1212.             return 0;
  1213.         }
  1214.         if (!snmp_strcat
  1215.             (buf, buf_len, out_len, allow_realloc,
  1216.              (const u_char *) "] ")) {
  1217.             return 0;
  1218.         }
  1219.     } else {
  1220.         if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1221.                          (const u_char *) inet_ntoa(*agent_inaddr))) {
  1222.             return 0;
  1223.         }
  1224.     }
  1225.     /*
  1226.      * Append PDU transport info.  
  1227.      */
  1228.     if (transport != NULL && transport->f_fmtaddr != NULL) {
  1229.         char           *tstr =
  1230.             transport->f_fmtaddr(transport, pdu->transport_data,
  1231.                                  pdu->transport_data_length);
  1232.         if (!snmp_strcat
  1233.             (buf, buf_len, out_len, allow_realloc,
  1234.              (const u_char *) "(via ")) {
  1235.             if (tstr != NULL) {
  1236.                 free(tstr);
  1237.             }
  1238.             return 0;
  1239.         }
  1240.         if (!snmp_strcat(buf, buf_len, out_len, allow_realloc, tstr)) {
  1241.             if (tstr != NULL) {
  1242.                 free(tstr);
  1243.             }
  1244.             return 0;
  1245.         }
  1246.         if (tstr != NULL) {
  1247.             free(tstr);
  1248.         }
  1249.         if (!snmp_strcat
  1250.             (buf, buf_len, out_len, allow_realloc,
  1251.              (const u_char *) ") ")) {
  1252.             return 0;
  1253.         }
  1254.     }
  1255.     /*
  1256.      * Add security wrapper information.  
  1257.      */
  1258.     if (!realloc_handle_wrap_fmt
  1259.         (buf, buf_len, out_len, allow_realloc, pdu)) {
  1260.         return 0;
  1261.     }
  1262.     if (!snmp_strcat
  1263.         (buf, buf_len, out_len, allow_realloc, (const u_char *) "nt")) {
  1264.         return 0;
  1265.     }
  1266.     /*
  1267.      * Add enterprise information.  
  1268.      */
  1269.     if (!sprint_realloc_objid(buf, buf_len, out_len, allow_realloc,
  1270.                               pdu->enterprise, pdu->enterprise_length)) {
  1271.         return 0;
  1272.     }
  1273.     if (!snmp_strcat
  1274.         (buf, buf_len, out_len, allow_realloc, (const u_char *) " ")) {
  1275.         return 0;
  1276.     }
  1277.     if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1278.                      trap_description(pdu->trap_type))) {
  1279.         return 0;
  1280.     }
  1281.     if (!snmp_strcat
  1282.         (buf, buf_len, out_len, allow_realloc,
  1283.          (const u_char *) " Trap (")) {
  1284.         return 0;
  1285.     }
  1286.     /*
  1287.      * Handle enterprise specific traps.  
  1288.      */
  1289.     if (pdu->trap_type == SNMP_TRAP_ENTERPRISESPECIFIC) {
  1290.         size_t          obuf_len = 64, oout_len = 0, trap_oid_len = 0;
  1291.         oid             trap_oid[MAX_OID_LEN + 2] = { 0 };
  1292.         char           *ent_spec_code = NULL;
  1293.         u_char         *obuf = NULL;
  1294.         if ((obuf = (u_char *) calloc(obuf_len, 1)) == NULL) {
  1295.             return 0;
  1296.         }
  1297.         /*
  1298.          * Get object ID for the trap.  
  1299.          */
  1300.         trap_oid_len = pdu->enterprise_length;
  1301.         memcpy(trap_oid, pdu->enterprise, trap_oid_len * sizeof(oid));
  1302.         if (trap_oid[trap_oid_len - 1] != 0) {
  1303.             trap_oid[trap_oid_len] = 0;
  1304.             trap_oid_len++;
  1305.         }
  1306.         trap_oid[trap_oid_len] = pdu->specific_type;
  1307.         trap_oid_len++;
  1308.         /*
  1309.          * Find the element after the last dot.  
  1310.          */
  1311.         if (!sprint_realloc_objid(&obuf, &obuf_len, &oout_len, 1,
  1312.                                   trap_oid, trap_oid_len)) {
  1313.             if (obuf != NULL) {
  1314.                 free(obuf);
  1315.             }
  1316.             return 0;
  1317.         }
  1318.         ent_spec_code = strrchr((char *) obuf, '.');
  1319.         if (ent_spec_code != NULL) {
  1320.             ent_spec_code++;
  1321.         } else {
  1322.             ent_spec_code = (char *) obuf;
  1323.         }
  1324.         /*
  1325.          * Print trap info.  
  1326.          */
  1327.         if (!snmp_strcat
  1328.             (buf, buf_len, out_len, allow_realloc,
  1329.              (const u_char *) ent_spec_code)) {
  1330.             free(obuf);
  1331.             return 0;
  1332.         }
  1333.         free(obuf);
  1334.     } else {
  1335.         /*
  1336.          * Handle traps that aren't enterprise specific.  
  1337.          */
  1338.         sprintf(safe_bfr, "%ld", pdu->specific_type);
  1339.         if (!snmp_strcat
  1340.             (buf, buf_len, out_len, allow_realloc,
  1341.              (const u_char *) safe_bfr)) {
  1342.             return 0;
  1343.         }
  1344.     }
  1345.     /*
  1346.      * Finish the line.  
  1347.      */
  1348.     if (!snmp_strcat
  1349.         (buf, buf_len, out_len, allow_realloc,
  1350.          (const u_char *) ") Uptime: ")) {
  1351.         return 0;
  1352.     }
  1353.     if (!snmp_strcat(buf, buf_len, out_len, allow_realloc,
  1354.                      (const u_char *) uptime_string(pdu->time,
  1355.                                                     safe_bfr))) {
  1356.         return 0;
  1357.     }
  1358.     if (!snmp_strcat
  1359.         (buf, buf_len, out_len, allow_realloc, (const u_char *) "n")) {
  1360.         return 0;
  1361.     }
  1362.     /*
  1363.      * Finally, output the PDU variables. 
  1364.      */
  1365.     for (vars = pdu->variables; vars != NULL; vars = vars->next_variable) {
  1366.         if (!snmp_strcat
  1367.             (buf, buf_len, out_len, allow_realloc,
  1368.              (const u_char *) "t")) {
  1369.             return 0;
  1370.         }
  1371.         if (!sprint_realloc_variable(buf, buf_len, out_len, allow_realloc,
  1372.                                      vars->name, vars->name_length,
  1373.                                      vars)) {
  1374.             return 0;
  1375.         }
  1376.     }
  1377.     if (!snmp_strcat
  1378.         (buf, buf_len, out_len, allow_realloc, (const u_char *) "n")) {
  1379.         return 0;
  1380.     }
  1381.     /*
  1382.      * String is already null-terminated.  That's all folks!  
  1383.      */
  1384.     return 1;
  1385. }
  1386. int
  1387. realloc_format_trap(u_char ** buf, size_t * buf_len, size_t * out_len,
  1388.                     int allow_realloc, const char *format_str,
  1389.                     netsnmp_pdu *pdu, netsnmp_transport *transport)
  1390.      /*
  1391.       * Function:
  1392.       *    Format the trap information for display in a log. Place the results
  1393.       *    in the specified buffer (truncating to the length of the buffer).
  1394.       *    Returns the number of characters it put in the buffer.
  1395.       *
  1396.       * Input Parameters:
  1397.       *    buf, buf_len, out_len, allow_realloc - standard relocatable
  1398.       *                                           buffer parameters
  1399.       *    format_str - specifies how to format the trap info
  1400.       *    pdu        - the pdu information
  1401.       *    transport  - the transport descriptor
  1402.       */
  1403. {
  1404.     unsigned long   fmt_idx = 0;        /* index into the format string */
  1405.     options_type    options;    /* formatting options */
  1406.     parse_state_type state = PARSE_NORMAL;      /* state of the parser */
  1407.     char            next_chr;   /* for speed */
  1408.     int             reset_options = TRUE;       /* reset opts on next NORMAL state */
  1409.     if (buf == NULL) {
  1410.         return 0;
  1411.     }
  1412.     memset(separator, 0, sizeof(separator));
  1413.     /*
  1414.      * Go until we reach the end of the format string:  
  1415.      */
  1416.     for (fmt_idx = 0; format_str[fmt_idx] != ''; fmt_idx++) {
  1417.         next_chr = format_str[fmt_idx];
  1418.         switch (state) {
  1419.         case PARSE_NORMAL:
  1420.             /*
  1421.              * Looking for next character.  
  1422.              */
  1423.             if (reset_options) {
  1424.                 init_options(&options);
  1425.                 reset_options = FALSE;
  1426.             }
  1427.             if (next_chr == '\') {
  1428.                 state = PARSE_BACKSLASH;
  1429.             } else if (next_chr == CHR_FMT_DELIM) {
  1430.                 state = PARSE_IN_FORMAT;
  1431.             } else {
  1432.                 if ((*out_len + 1) >= *buf_len) {
  1433.                     if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
  1434.                         return 0;
  1435.                     }
  1436.                 }
  1437.                 *(*buf + *out_len) = next_chr;
  1438.                 (*out_len)++;
  1439.             }
  1440.             break;
  1441.         case PARSE_GET_SEPARATOR:
  1442.             /*
  1443.              * Parse the separator character
  1444.              * XXX - Possibly need to handle quoted strings ??
  1445.              */
  1446.     {   char *sep = separator;
  1447. size_t i, j;
  1448. i = sizeof(separator);
  1449. j = 0;
  1450. memset(separator, 0, i);
  1451. while (j < i && next_chr && next_chr != CHR_FMT_DELIM) {
  1452.     if (next_chr == '\') {
  1453. /*
  1454.  * Handle backslash interpretation
  1455.  * Print to "separator" string rather than the output buffer
  1456.  *    (a bit of a hack, but it should work!)
  1457.  */
  1458. next_chr = format_str[++fmt_idx];
  1459. if (!realloc_handle_backslash
  1460.     ((u_char **)&sep, &i, &j, 0, next_chr)) {
  1461.     return 0;
  1462. }
  1463.     } else {
  1464. separator[j++] = next_chr;
  1465.     }
  1466.     next_chr = format_str[++fmt_idx];
  1467. }
  1468.     }
  1469.             state = PARSE_IN_FORMAT;
  1470.             break;
  1471.         case PARSE_BACKSLASH:
  1472.             /*
  1473.              * Found a backslash.  
  1474.              */
  1475.             if (!realloc_handle_backslash
  1476.                 (buf, buf_len, out_len, allow_realloc, next_chr)) {
  1477.                 return 0;
  1478.             }
  1479.             state = PARSE_NORMAL;
  1480.             break;
  1481.         case PARSE_IN_FORMAT:
  1482.             /*
  1483.              * In a format command.  
  1484.              */
  1485.             reset_options = TRUE;
  1486.             if (next_chr == CHR_LEFT_JUST) {
  1487.                 options.left_justify = TRUE;
  1488.             } else if (next_chr == CHR_LEAD_ZERO) {
  1489.                 options.leading_zeroes = TRUE;
  1490.             } else if (next_chr == CHR_ALT_FORM) {
  1491.                 options.alt_format = TRUE;
  1492.             } else if (next_chr == CHR_FIELD_SEP) {
  1493.                 state = PARSE_GET_PRECISION;
  1494.             } else if (next_chr == CHR_TRAP_VARSEP) {
  1495.                 state = PARSE_GET_SEPARATOR;
  1496.             } else if ((next_chr >= '1') && (next_chr <= '9')) {
  1497.                 options.width =
  1498.                     ((unsigned long) next_chr) - ((unsigned long) '0');
  1499.                 state = PARSE_GET_WIDTH;
  1500.             } else if (is_fmt_cmd(next_chr)) {
  1501.                 options.cmd = next_chr;
  1502.                 if (!realloc_dispatch_format_cmd
  1503.                     (buf, buf_len, out_len, allow_realloc, &options, pdu,
  1504.                      transport)) {
  1505.                     return 0;
  1506.                 }
  1507.                 state = PARSE_NORMAL;
  1508.             } else {
  1509.                 if ((*out_len + 1) >= *buf_len) {
  1510.                     if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
  1511.                         return 0;
  1512.                     }
  1513.                 }
  1514.                 *(*buf + *out_len) = next_chr;
  1515.                 (*out_len)++;
  1516.                 state = PARSE_NORMAL;
  1517.             }
  1518.             break;
  1519.         case PARSE_GET_WIDTH:
  1520.             /*
  1521.              * Parsing a width field.  
  1522.              */
  1523.             reset_options = TRUE;
  1524.             if (isdigit(next_chr)) {
  1525.                 options.width *= 10;
  1526.                 options.width +=
  1527.                     (unsigned long) next_chr - (unsigned long) '0';
  1528.             } else if (next_chr == CHR_FIELD_SEP) {
  1529.                 state = PARSE_GET_PRECISION;
  1530.             } else if (is_fmt_cmd(next_chr)) {
  1531.                 options.cmd = next_chr;
  1532.                 if (!realloc_dispatch_format_cmd
  1533.                     (buf, buf_len, out_len, allow_realloc, &options, pdu,
  1534.                      transport)) {
  1535.                     return 0;
  1536.                 }
  1537.                 state = PARSE_NORMAL;
  1538.             } else {
  1539.                 if ((*out_len + 1) >= *buf_len) {
  1540.                     if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
  1541.                         return 0;
  1542.                     }
  1543.                 }
  1544.                 *(*buf + *out_len) = next_chr;
  1545.                 (*out_len)++;
  1546.                 state = PARSE_NORMAL;
  1547.             }
  1548.             break;
  1549.         case PARSE_GET_PRECISION:
  1550.             /*
  1551.              * Parsing a precision field.  
  1552.              */
  1553.             reset_options = TRUE;
  1554.             if (isdigit(next_chr)) {
  1555.                 if (options.precision == UNDEF_PRECISION) {
  1556.                     options.precision =
  1557.                         (unsigned long) next_chr - (unsigned long) '0';
  1558.                 } else {
  1559.                     options.precision *= 10;
  1560.                     options.precision +=
  1561.                         (unsigned long) next_chr - (unsigned long) '0';
  1562.                 }
  1563.             } else if (is_fmt_cmd(next_chr)) {
  1564.                 options.cmd = next_chr;
  1565.                 if (options.width < options.precision) {
  1566.                     options.width = options.precision;
  1567.                 }
  1568.                 if (!realloc_dispatch_format_cmd
  1569.                     (buf, buf_len, out_len, allow_realloc, &options, pdu,
  1570.                      transport)) {
  1571.                     return 0;
  1572.                 }
  1573.                 state = PARSE_NORMAL;
  1574.             } else {
  1575.                 if ((*out_len + 1) >= *buf_len) {
  1576.                     if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
  1577.                         return 0;
  1578.                     }
  1579.                 }
  1580.                 *(*buf + *out_len) = next_chr;
  1581.                 (*out_len)++;
  1582.                 state = PARSE_NORMAL;
  1583.             }
  1584.             break;
  1585.         default:
  1586.             /*
  1587.              * Unknown state.  
  1588.              */
  1589.             reset_options = TRUE;
  1590.             if ((*out_len + 1) >= *buf_len) {
  1591.                 if (!(allow_realloc && snmp_realloc(buf, buf_len))) {
  1592.                     return 0;
  1593.                 }
  1594.             }
  1595.             *(*buf + *out_len) = next_chr;
  1596.             (*out_len)++;
  1597.             state = PARSE_NORMAL;
  1598.         }
  1599.     }
  1600.     *(*buf + *out_len) = '';
  1601.     return 1;
  1602. }