snmptrapd_log.cpp 56 KB

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