/** * Validate a remote service. * @param s The remote service to validate * @return FALSE if there was an error otherwise TRUE */ int check_remote_host(Service_T s) { Port_T p = NULL; Icmp_T icmp = NULL; Icmp_T last_ping = NULL; ASSERT(s); /* Test each icmp type in the service's icmplist */ if (s->icmplist) { for (icmp = s->icmplist; icmp; icmp = icmp->next) { switch(icmp->type) { case ICMP_ECHO: icmp->response = icmp_echo(s->path, icmp->timeout, icmp->count); if (icmp->response == -2) { icmp->is_available = TRUE; DEBUG("'%s' icmp ping skipped -- the monit user has no permission to create raw socket, please run monit as root or add privilege for net_icmpaccess\n", s->name); } else if (icmp->response == -1) { icmp->is_available = FALSE; DEBUG("'%s' icmp ping failed\n", s->name); Event_post(s, Event_Icmp, STATE_FAILED, icmp->action, "failed ICMP test [%s]", icmpnames[icmp->type]); } else { icmp->is_available = TRUE; DEBUG("'%s' icmp ping succeeded [response time %.3fs]\n", s->name, icmp->response); Event_post(s, Event_Icmp, STATE_SUCCEEDED, icmp->action, "succeeded ICMP test [%s]", icmpnames[icmp->type]); } last_ping = icmp; break; default: LogError("'%s' error -- unknown ICMP type: [%d]\n", s->name, icmp->type); return FALSE; } } } /* If we could not ping the host we assume it's down and do not * continue to check any port connections */ if (last_ping && !last_ping->is_available) { DEBUG("'%s' icmp ping failed, skipping any port connection tests\n", s->name); return FALSE; } /* Test each host:port and protocol in the service's portlist */ if (s->portlist) for (p = s->portlist; p; p = p->next) check_connection(s, p); return TRUE; }
/** * Returns TRUE if the ICMP test succeeded otherwise FALSE. */ static int check_icmp_connection(Service_T s, Icmp_T i, char *report) { if(i->type == ICMP_ECHO && !icmp_echo(s->path, i->timeout)) { snprintf(report, STRLEN, "'%s' failed ICMP test [%s]", s->name, icmpnames[i->type]); return FALSE; } DEBUG("'%s' succeeded testing ICMP [%s]\n", s->name, icmpnames[i->type]); return TRUE; }
uint_t icmp_input (T_NET_BUF **inputp, uint_t *offp, uint_t *nextp) { T_NET_BUF *input = *inputp; T_ICMP4_HDR *icmp4h; T_IN4_ADDR addr; uint_t len, align; NET_COUNT_ICMP4(net_count_icmp4.in_octets, input->len - GET_IF_IP4_HDR_SIZE(input)); NET_COUNT_ICMP4(net_count_icmp4.in_packets, 1); /* ICMP ヘッダの長さをチェックする。*/ if (input->len < IF_IP4_ICMP4_HDR_SIZE) { NET_COUNT_ICMP4(net_count_icmp4.in_err_packets, 1); NET_COUNT_MIB(icmp_stats.icmpInErrors, 1); goto buf_rel; } icmp4h = (T_ICMP4_HDR *)(input->buf + *offp); /* 4 オクテット境界のデータ長 */ len = input->len - *offp; align = (len + 3) >> 2 << 2; /* 4 オクテット境界までパディングで埋める。*/ if (align > len) memset((uint8_t*)input->buf + input->len, 0, (size_t)(align - len)); /* チェックサムを計算する。*/ if (in_cksum(icmp4h, align) != 0) { NET_COUNT_ICMP4(net_count_icmp4.in_err_packets, 1); goto buf_rel; } /* メッセージの型により分岐する。*/ switch (icmp4h->type) { case ICMP4_ECHO_REQUEST: icmp_echo(input, *offp); return IPPROTO_DONE; break; case ICMP4_ECHO_REPLY: #ifdef ICMP_CFG_CALLBACK_ECHO_REPLY icmp_echo_reply(input, *offp); #endif /* of #ifdef ICMP_CFG_CALLBACK_ECHO_REPLY */ break; case ICMP4_UNREACH: icmp_unreach(input, *offp); break; case ICMP4_REDIRECT: #if NUM_REDIRECT_ROUTE_ENTRY > 0 addr = ntohl(icmp4h->data.addr); syslog(LOG_INFO, "[ICMP] redirect, addr: %s.", ip2str(NULL, &addr)); icmp_redirect(input, *offp); #else /* of #if NUM_REDIRECT_ROUTE_ENTRY > 0 */ addr = ntohl(icmp4h->data.addr); syslog(LOG_INFO, "[ICMP] redirect ignored, addr: %s.", ip2str(NULL, &addr)); #endif /* of #if NUM_REDIRECT_ROUTE_ENTRY > 0 */ break; default: syslog(LOG_INFO, "[ICMP] unknown type: %d.", icmp4h->type); NET_COUNT_ICMP4(net_count_icmp4.in_err_packets, 1); break; } buf_rel: syscall(rel_net_buf(input)); return IPPROTO_DONE; }