/****************************************************************************** * * * Function: read_traps * * * * Purpose: read the traps and then parse them with parse_traps() * * * * Author: Rudolfs Kreicbergs * * * ******************************************************************************/ static int read_traps() { const char *__function_name = "read_traps"; int nbytes = 0; zabbix_log(LOG_LEVEL_DEBUG, "In %s() lastsize:%d", __function_name, trap_lastsize); if ((off_t)-1 == lseek(trap_fd, (off_t)trap_lastsize, SEEK_SET)) { zabbix_log(LOG_LEVEL_WARNING, "cannot set position to %d for \"%s\": %s", trap_lastsize, CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); goto exit; } if (-1 == (nbytes = read(trap_fd, buffer + offset, MAX_BUFFER_LEN - offset - 1))) { zabbix_log(LOG_LEVEL_WARNING, "cannot read from SNMP trapper file \"%s\": %s", CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); goto exit; } if (0 < nbytes) { if (ZBX_SNMP_TRAPFILE_MAX_SIZE <= (zbx_uint64_t)trap_lastsize + nbytes) { nbytes = 0; goto exit; } buffer[nbytes + offset] = '\0'; trap_lastsize += nbytes; DBupdate_lastsize(); parse_traps(0); } exit: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); return nbytes; }
/****************************************************************************** * * * Function: read_traps * * * * Purpose: read the traps and then parse them with parse_traps() * * * * Author: Rudolfs Kreicbergs * * * ******************************************************************************/ static void read_traps() { const char *__function_name = "read_traps"; int nbytes; char buffer[MAX_BUFFER_LEN]; zabbix_log(LOG_LEVEL_DEBUG, "In %s() lastsize:%d", __function_name, trap_lastsize); *buffer = '\0'; if ((off_t)-1 == lseek(trap_fd, (off_t)trap_lastsize, SEEK_SET)) { zabbix_log(LOG_LEVEL_WARNING, "cannot set position to [%d] for [%s]: %s", trap_lastsize, CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); goto exit; } if (-1 == (nbytes = read(trap_fd, buffer, sizeof(buffer) - 1))) { zabbix_log(LOG_LEVEL_WARNING, "cannot read from [%s]: %s", CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); goto exit; } if (0 < nbytes) { buffer[nbytes] = '\0'; zbx_rtrim(buffer + MAX(nbytes - 3, 0), " \r\n"); trap_lastsize += nbytes; DBupdate_lastsize(); parse_traps(buffer); } exit: zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name); }
/****************************************************************************** * * * Function: get_latest_data * * * * Purpose: Open the latest trap file. If the current file has been rotated, * * process that and then open the latest file. * * * * Return value: SUCCEED - there are new traps to be parsed * * FAIL - there are no new traps or trap file does not exist * * * * Author: Rudolfs Kreicbergs * * * ******************************************************************************/ static int get_latest_data() { zbx_stat_t file_buf; if (-1 != trap_fd) /* a trap file is already open */ { if (0 != zbx_stat(CONFIG_SNMPTRAP_FILE, &file_buf)) { /* file might have been renamed or deleted, process the current file */ if (ENOENT != errno) { zabbix_log(LOG_LEVEL_CRIT, "cannot stat SNMP trapper file \"%s\": %s", CONFIG_SNMPTRAP_FILE, zbx_strerror(errno)); } while (0 < read_traps()) ; if (0 != offset) parse_traps(1); close_trap_file(); } else if (ZBX_SNMP_TRAPFILE_MAX_SIZE <= (zbx_uint64_t)file_buf.st_size) { close_trap_file(); } else if (file_buf.st_ino != trap_ino || file_buf.st_size < trap_lastsize) { /* file has been rotated, process the current file */ while (0 < read_traps()) ; if (0 != offset) parse_traps(1); close_trap_file(); } else if (file_buf.st_size == trap_lastsize) { if (1 == force) { parse_traps(1); force = 0; } else if (0 != offset && 0 == force) { force = 1; } return FAIL; /* no new traps */ } } force = 0; if (-1 == trap_fd && -1 == open_trap_file()) return FAIL; return SUCCEED; }
/****************************************************************************** * * * Function: parse_traps * * * * Purpose: split traps and process them with process_trap() * * * * Author: Rudolfs Kreicbergs * * * ******************************************************************************/ static void parse_traps(int flag) { char *c, *line, *begin = NULL, *end = NULL, *addr = NULL, *pzbegin, *pzaddr = NULL, *pzdate = NULL; c = line = buffer; while ('\0' != *c) { if ('\n' == *c) { line = ++c; continue; } if (0 != strncmp(c, "ZBXTRAP", 7)) { c++; continue; } pzbegin = c; c += 7; /* c now points to the delimiter between "ZBXTRAP" and address */ while ('\0' != *c && NULL != strchr(ZBX_WHITESPACE, *c)) c++; /* c now points to the address */ /* process the previous trap */ if (NULL != begin) { *(line - 1) = '\0'; *pzdate = '\0'; *pzaddr = '\0'; process_trap(addr, begin, end); end = NULL; } /* parse the current trap */ begin = line; addr = c; pzdate = pzbegin; while ('\0' != *c && NULL == strchr(ZBX_WHITESPACE, *c)) c++; pzaddr = c; end = c + 1; /* the rest of the trap */ } if (0 == flag) { if (NULL == begin) offset = c - buffer; else offset = c - begin; if (offset == MAX_BUFFER_LEN - 1) { if (NULL != end) { zabbix_log(LOG_LEVEL_WARNING, "SNMP trapper buffer is full," " trap data might be truncated"); parse_traps(1); } else zabbix_log(LOG_LEVEL_WARNING, "failed to find trap in SNMP trapper file"); offset = 0; *buffer = '\0'; } else { if (NULL != begin && begin != buffer) memmove(buffer, begin, offset + 1); } } else { if (NULL != end) { *(line - 1) = '\0'; *pzdate = '\0'; *pzaddr = '\0'; process_trap(addr, begin, end); offset = 0; *buffer = '\0'; } else { zabbix_log(LOG_LEVEL_WARNING, "invalid trap data found \"%s\"", buffer); offset = 0; *buffer = '\0'; } } }