/* Sync checkers activity with netlink kernel reflection */ void update_checker_activity(uint32_t address, int enable) { checker *checker_obj; element e; /* Display netlink operation */ if (debug & 32) log_message(LOG_INFO, "Netlink reflector reports IP %s %s", inet_ntop2(address), (enable) ? "added" : "removed"); /* Processing Healthcheckers queue */ if (!LIST_ISEMPTY(checkers_queue)) for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) { checker_obj = ELEMENT_DATA(e); if (CHECKER_VIP(checker_obj) == address && CHECKER_HA_SUSPEND(checker_obj)) { if (!CHECKER_ENABLED(checker_obj) && enable) log_message(LOG_INFO, "Activating healtchecker for service [%s:%d]", inet_ntop2(CHECKER_RIP(checker_obj)), ntohs(CHECKER_RPORT(checker_obj))); if (CHECKER_ENABLED(checker_obj) && !enable) log_message(LOG_INFO, "Suspending healtchecker for service [%s:%d]", inet_ntop2(CHECKER_RIP(checker_obj)), ntohs(CHECKER_RPORT(checker_obj))); checker_obj->enabled = enable; } } }
int tcp_check_thread(thread_t * thread) { SOCK *sock_obj = THREAD_ARG(thread); int ret = 1; sock_obj->status = tcp_socket_state(thread->u.fd, thread, req->addr_ip, req->addr_port, tcp_check_thread); switch (sock_obj->status) { case connect_error: DBG("Error connecting server [%s:%d].\n", inet_ntop2(req->addr_ip), ntohs(req->addr_port)); thread_add_terminate_event(thread->master); return -1; break; case connect_timeout: DBG("Timeout connecting server [%s:%d].\n", inet_ntop2(req->addr_ip), ntohs(req->addr_port)); thread_add_terminate_event(thread->master); return -1; break; case connect_success:{ if (req->ssl) ret = ssl_connect(thread); if (ret) { /* Remote WEB server is connected. * Unlock eventual locked socket. */ sock_obj->lock = 0; thread_add_event(thread->master, http_request_thread, sock_obj, 0); } else { DBG("Connection trouble to: [%s:%d].\n", inet_ntop2(req->addr_ip), ntohs(req->addr_port)); if (req->ssl) ssl_printerr(SSL_get_error (sock_obj->ssl, ret)); sock_obj->status = connect_error; return -1; } } break; } return 1; }
enum connect_result tcp_socket_state(int fd, thread * thread_obj, uint32_t addr_ip, uint16_t addr_port, int (*func) (struct _thread *)) { int status; socklen_t slen; int ret = 0; TIMEVAL timer_min; /* Handle connection timeout */ if (thread_obj->type == THREAD_WRITE_TIMEOUT) { DBG("TCP connection timeout to [%s:%d].", inet_ntop2(addr_ip), ntohs(addr_port)); close(thread_obj->u.fd); return connect_timeout; } /* Check file descriptor */ slen = sizeof (status); if (getsockopt (thread_obj->u.fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen) < 0) ret = errno; /* Connection failed !!! */ if (ret) { DBG("TCP connection failed to [%s:%d].", inet_ntop2(addr_ip), ntohs(addr_port)); close(thread_obj->u.fd); return connect_error; } /* If status = 0, TCP connection to remote host is established. * Otherwise register checker thread to handle connection in progress, * and other error code until connection is established. * Recompute the write timeout (or pending connection). */ if (status == EINPROGRESS) { DBG("TCP connection to [%s:%d] still IN_PROGRESS.", inet_ntop2(addr_ip), ntohs(addr_port)); timer_min = timer_sub_now(thread_obj->sands); thread_add_write(thread_obj->master, func, THREAD_ARG(thread_obj) , thread_obj->u.fd, TIMER_LONG(timer_min)); return connect_in_progress; } else if (status != 0) { close(thread_obj->u.fd); return connect_error; } return connect_success; }
static void address_print(FILE *file, void *data) { ip_address_t *ipaddr = data; char broadcast[INET_ADDRSTRLEN + 5] = ""; /* allow for " brd " */ char addr_str[INET6_ADDRSTRLEN] = ""; if (IP_IS6(ipaddr)) { inet_ntop(AF_INET6, &ipaddr->u.sin6_addr, addr_str, sizeof(addr_str)); } else { inet_ntop(AF_INET, &ipaddr->u.sin.sin_addr, addr_str, sizeof(addr_str)); if (ipaddr->u.sin.sin_brd.s_addr) snprintf(broadcast, sizeof(broadcast) - 1, " brd %s", inet_ntop2(ipaddr->u.sin.sin_brd.s_addr)); } fprintf(file, " %s/%d%s dev %s%s%s%s%s\n" , addr_str , ipaddr->ifa.ifa_prefixlen , broadcast , IF_NAME(ipaddr->ifp) , IP_IS4(ipaddr) ? " scope " : "" , IP_IS4(ipaddr) ? netlink_scope_n2a(ipaddr->ifa.ifa_scope) : "" , ipaddr->label ? " label " : "" , ipaddr->label ? ipaddr->label : ""); }
void address_print(FILE *file, void *data) { ip_address_t *ipaddr = data; char *broadcast = (char *) MALLOC(21); char *addr_str = (char *) MALLOC(41); if (IP_IS6(ipaddr)) { inet_ntop(AF_INET6, &ipaddr->u.sin6_addr, addr_str, 41); } else { inet_ntop(AF_INET, &ipaddr->u.sin.sin_addr, addr_str, 41); if (ipaddr->u.sin.sin_brd.s_addr) snprintf(broadcast, 20, " brd %s", inet_ntop2(ipaddr->u.sin.sin_brd.s_addr)); } fprintf(file, " %s/%d%s dev %s scope %s%s%s\n" , addr_str , ipaddr->ifa.ifa_prefixlen , broadcast , IF_NAME(ipaddr->ifp) , netlink_scope_n2a(ipaddr->ifa.ifa_scope) , ipaddr->label ? " label " : "" , ipaddr->label ? ipaddr->label : ""); FREE(broadcast); FREE(addr_str); }
/* Fill IPVS rule with root vs infos */ void ipvs_set_rule(int cmd, virtual_server * vs, real_server * rs) { /* Clean up target rule */ memset(urule, 0, sizeof (struct ip_vs_rule_user)); strncpy(urule->sched_name, vs->sched, IP_VS_SCHEDNAME_MAXLEN); urule->weight = 1; urule->conn_flags = vs->loadbalancing_kind; urule->netmask = ((u_int32_t) 0xffffffff); urule->protocol = vs->service_type; if (!parse_timeout(vs->timeout_persistence, &urule->timeout)) log_message(LOG_INFO, "IPVS : Virtual service [%s:%d] illegal timeout.", inet_ntop2(SVR_IP(vs)), ntohs(SVR_PORT(vs))); if (urule->timeout != 0 || vs->granularity_persistence) urule->vs_flags = IP_VS_SVC_F_PERSISTENT; if (cmd == IP_VS_SO_SET_ADD || cmd == IP_VS_SO_SET_DEL) if (vs->granularity_persistence) urule->netmask = vs->granularity_persistence; /* SVR specific */ if (rs) { if (cmd == IP_VS_SO_SET_ADDDEST || cmd == IP_VS_SO_SET_DELDEST || cmd == IP_VS_SO_SET_EDITDEST) { urule->weight = rs->weight; urule->daddr = SVR_IP(rs); urule->dport = SVR_PORT(rs); } } }
/* dump checker data */ static void dump_checker(void *data_obj) { checker *checker_obj = data_obj; log_message(LOG_INFO, " %s:%d", inet_ntop2(CHECKER_RIP(checker_obj)) , ntohs(CHECKER_RPORT(checker_obj))); (*checker_obj->dump_func) (checker_obj); }
void if_print(FILE *file, void * data) { tracked_if_t *tip = data; interface_t *ifp = tip->ifp; char addr_str[41]; int weight = tip->weight; fprintf(file, "------< NIC >------\n"); fprintf(file, " Name = %s\n", ifp->ifname); fprintf(file, " index = %d\n", ifp->ifindex); fprintf(file, " IPv4 address = %s\n", inet_ntop2(ifp->sin_addr.s_addr)); inet_ntop(AF_INET6, &ifp->sin6_addr, addr_str, 41); fprintf(file, " IPv6 address = %s\n", addr_str); /* FIXME: Harcoded for ethernet */ if (ifp->hw_type == ARPHRD_ETHER) fprintf(file, " MAC = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", ifp->hw_addr[0], ifp->hw_addr[1], ifp->hw_addr[2] , ifp->hw_addr[3], ifp->hw_addr[4], ifp->hw_addr[5]); if (ifp->flags & IFF_UP) fprintf(file, " is UP\n"); if (ifp->flags & IFF_RUNNING) fprintf(file, " is RUNNING\n"); if (!(ifp->flags & IFF_UP) && !(ifp->flags & IFF_RUNNING)) fprintf(file, " is DOWN\n"); if (weight) fprintf(file, " weight = %d\n", weight); fprintf(file, " MTU = %d\n", ifp->mtu); switch (ifp->hw_type) { case ARPHRD_LOOPBACK: fprintf(file, " HW Type = LOOPBACK\n"); break; case ARPHRD_ETHER: fprintf(file, " HW Type = ETHERNET\n"); break; default: fprintf(file, " HW Type = UNKNOWN\n"); break; } /* MII channel supported ? */ if (IF_MII_SUPPORTED(ifp)) fprintf(file, " NIC support MII regs\n"); else if (IF_ETHTOOL_SUPPORTED(ifp)) fprintf(file, " NIC support EHTTOOL GLINK interface\n"); else fprintf(file, " Enabling NIC ioctl refresh polling\n"); }
void dump_if(void *data) { interface_t *ifp = data; char addr_str[41]; log_message(LOG_INFO, "------< NIC >------"); log_message(LOG_INFO, " Name = %s", ifp->ifname); log_message(LOG_INFO, " index = %d", ifp->ifindex); log_message(LOG_INFO, " IPv4 address = %s", inet_ntop2(ifp->sin_addr.s_addr)); inet_ntop(AF_INET6, &ifp->sin6_addr, addr_str, 41); log_message(LOG_INFO, " IPv6 address = %s", addr_str); /* FIXME: Harcoded for ethernet */ if (ifp->hw_type == ARPHRD_ETHER) log_message(LOG_INFO, " MAC = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", ifp->hw_addr[0], ifp->hw_addr[1], ifp->hw_addr[2] , ifp->hw_addr[3], ifp->hw_addr[4], ifp->hw_addr[5]); if (ifp->flags & IFF_UP) log_message(LOG_INFO, " is UP"); if (ifp->flags & IFF_RUNNING) log_message(LOG_INFO, " is RUNNING"); if (!(ifp->flags & IFF_UP) && !(ifp->flags & IFF_RUNNING)) log_message(LOG_INFO, " is DOWN"); log_message(LOG_INFO, " MTU = %d", ifp->mtu); switch (ifp->hw_type) { case ARPHRD_LOOPBACK: log_message(LOG_INFO, " HW Type = LOOPBACK"); break; case ARPHRD_ETHER: log_message(LOG_INFO, " HW Type = ETHERNET"); break; default: log_message(LOG_INFO, " HW Type = UNKNOWN"); break; } /* MII channel supported ? */ if (IF_MII_SUPPORTED(ifp)) log_message(LOG_INFO, " NIC support MII regs"); else if (IF_ETHTOOL_SUPPORTED(ifp)) log_message(LOG_INFO, " NIC support EHTTOOL GLINK interface"); else log_message(LOG_INFO, " Enabling NIC ioctl refresh polling"); }
void tcp_connection_state(int fd, enum connect_result status, thread * thread_obj, int (*func) (struct _thread *) , long timeout) { checker *checker_obj; checker_obj = THREAD_ARG(thread_obj); switch (status) { case connect_error: DBG("TCP connection ERROR to [%s:%d].", inet_ntop2(SVR_IP(checker_obj->rs)), ntohs(SVR_PORT(checker_obj->rs))); close(fd); break; case connect_success: DBG("TCP connection SUCCESS to [%s:%d].", inet_ntop2(SVR_IP(checker_obj->rs)), ntohs(SVR_PORT(checker_obj->rs))); thread_add_write(thread_obj->master, func, checker_obj, fd, timeout); break; /* Checking non-blocking connect, we wait until socket is writable */ case connect_in_progress: DBG("TCP connection to [%s:%d] now IN_PROGRESS.", inet_ntop2(SVR_IP(checker_obj->rs)), ntohs(SVR_PORT(checker_obj->rs))); thread_add_write(thread_obj->master, func, checker_obj, fd, timeout); break; default: break; } }
/* Fill IPVS rule with root vs infos */ void ipvs_set_rule(int cmd, virtual_server * vs, real_server * rs) { /* Clean target rule */ memset(drule, 0, sizeof(ipvs_dest_t)); drule->weight = 1; drule->u_threshold = 0; drule->l_threshold = 0; drule->conn_flags = vs->loadbalancing_kind; strncpy(srule->sched_name, vs->sched, IP_VS_SCHEDNAME_MAXLEN); srule->netmask = (vs->addr.ss_family == AF_INET6) ? 128 : ((u_int32_t) 0xffffffff); srule->protocol = vs->service_type; if (!parse_timeout(vs->timeout_persistence, &srule->timeout)) log_message(LOG_INFO, "IPVS : Virtual service [%s]:%d illegal timeout." , inet_ntop2(inet_sockaddrip4(&vs->addr)) , ntohs(inet_sockaddrport(&vs->addr))); srule->est_timeout = atoi(vs->est_timeout); if (srule->timeout != 0 || vs->granularity_persistence) srule->flags = IP_VS_SVC_F_PERSISTENT; if (cmd == IP_VS_SO_SET_ADD || cmd == IP_VS_SO_SET_DEL) if (vs->granularity_persistence) srule->netmask = vs->granularity_persistence; if(vs->syn_proxy) srule->flags |= IP_VS_SVC_F_SYNPROXY; /* SVR specific */ if (rs) { if (cmd == IP_VS_SO_SET_ADDDEST || cmd == IP_VS_SO_SET_DELDEST || cmd == IP_VS_SO_SET_EDITDEST) { drule->af = rs->addr.ss_family; if (rs->addr.ss_family == AF_INET6) inet_sockaddrip6(&rs->addr, &drule->addr.in6); else drule->addr.ip = inet_sockaddrip4(&rs->addr); drule->port = inet_sockaddrport(&rs->addr); drule->weight = rs->weight; drule->u_threshold = rs->u_threshold; drule->l_threshold = rs->l_threshold; } } }
/* register checkers to the global I/O scheduler */ void register_checkers_thread(void) { checker *checker_obj; element e; for (e = LIST_HEAD(checkers_queue); e; ELEMENT_NEXT(e)) { checker_obj = ELEMENT_DATA(e); log_message(LOG_INFO, "Activating healtchecker for service [%s:%d]", inet_ntop2(CHECKER_RIP(checker_obj)), ntohs(CHECKER_RPORT(checker_obj))); CHECKER_ENABLE(checker_obj); if (checker_obj->launch) thread_add_timer(master, checker_obj->launch, checker_obj, BOOTSTRAP_DELAY); } }
/* Asynchronous HTTP stream reader */ int http_read_thread(thread_t * thread) { SOCK *sock_obj = THREAD_ARG(thread); int r = 0; /* Handle read timeout */ if (thread->type == THREAD_READ_TIMEOUT) return epilog(thread); /* read the HTTP stream */ memset(sock_obj->buffer, 0, MAX_BUFFER_LENGTH); r = read(thread->u.fd, sock_obj->buffer + sock_obj->size, MAX_BUFFER_LENGTH - sock_obj->size); DBG(" [l:%d,fd:%d]\n", r, sock_obj->fd); if (r == -1 || r == 0) { /* -1:error , 0:EOF */ if (r == -1) { /* We have encourred a real read error */ DBG("Read error with server [%s]:%d: %s\n", inet_ntop2(req->addr_ip), ntohs(req->addr_port), strerror(errno)); return epilog(thread); } /* All the HTTP stream has been parsed */ finalize(thread); } else { /* Handle the response stream */ http_process_stream(sock_obj, r); /* * Register next http stream reader. * Register itself to not perturbe global I/O multiplexer. */ thread_add_read(thread->master, http_read_thread, sock_obj, thread->u.fd, HTTP_CNX_TIMEOUT); } return 0; }
/* Send the gratuitous ARP message */ static int send_arp(ip_address_t *ipaddress) { struct sockaddr_ll sll; int len; /* Build the dst device */ memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; memcpy(sll.sll_addr, IF_HWADDR(ipaddress->ifp), ETH_ALEN); sll.sll_halen = ETHERNET_HW_LEN; sll.sll_ifindex = IF_INDEX(ipaddress->ifp); /* Send packet */ len = sendto(garp_fd, garp_buffer, sizeof(arphdr_t) + ETHER_HDR_LEN , 0, (struct sockaddr *)&sll, sizeof(sll)); if (len < 0) log_message(LOG_INFO, "Error sending gratuitous ARP on %s for %s", IF_NAME(ipaddress->ifp), inet_ntop2(ipaddress->u.sin.sin_addr.s_addr)); return len; }
void dump_ipaddress(void *if_data) { ip_address_t *ipaddr = if_data; char broadcast[INET_ADDRSTRLEN + 5] = ""; if (!IP_IS6(ipaddr) && ipaddr->u.sin.sin_brd.s_addr) { snprintf(broadcast, 21, " brd %s", inet_ntop2(ipaddr->u.sin.sin_brd.s_addr)); } log_message(LOG_INFO, " %s/%d%s dev %s scope %s%s%s" , ipaddresstos(NULL, ipaddr) , ipaddr->ifa.ifa_prefixlen , broadcast , IF_NAME(ipaddr->ifp) , get_rttables_scope(ipaddr->ifa.ifa_scope) , ipaddr->label ? " label " : "" , ipaddr->label ? ipaddr->label : ""); }
/* remote Web server is connected, send it the get url query. */ int http_request_thread(thread_t * thread) { SOCK *sock_obj = THREAD_ARG(thread); char *str_request; char *request_host; char *request_host_port; int ret = 0; /* Handle read timeout */ if (thread->type == THREAD_WRITE_TIMEOUT) return epilog(thread); /* Allocate & clean the GET string */ str_request = (char *) MALLOC(GET_BUFFER_LENGTH); memset(str_request, 0, GET_BUFFER_LENGTH); if (req->vhost) { /* If vhost was defined we don't need to override it's port */ request_host = req->vhost; request_host_port = (char*) MALLOC(1); *request_host_port = 0; } else { request_host = inet_ntop2(req->addr_ip); /* Allocate a buffer for the port string ( ":" [0-9][0-9][0-9][0-9][0-9] "\0" ) */ request_host_port = (char*) MALLOC(7); snprintf(request_host_port, 7, ":%d", ntohs(req->addr_port)); } snprintf(str_request, GET_BUFFER_LENGTH, REQUEST_TEMPLATE, req->url, request_host, request_host_port); FREE(request_host_port); /* Send the GET request to remote Web server */ DBG("Sending GET request [%s] on fd:%d\n", req->url, sock_obj->fd); if (req->ssl) ret = ssl_send_request(sock_obj->ssl, str_request, strlen(str_request)); else ret = (send(sock_obj->fd, str_request, strlen(str_request), 0) != -1) ? 1 : 0; FREE(str_request); if (!ret) { fprintf(stderr, "Cannot send get request to [%s]:%d.\n", inet_ntop2(req->addr_ip) , ntohs(req->addr_port)); return epilog(thread); } /* Register read timeouted thread */ thread_add_read(thread->master, http_response_thread, sock_obj, sock_obj->fd, HTTP_CNX_TIMEOUT); return 1; }
int ipvs_cmd(int cmd, list vs_group, virtual_server * vs, real_server * rs) { struct ip_masq_ctl ctl; int result = 0; int sockfd; memset(&ctl, 0, sizeof (struct ip_masq_ctl)); ctl.m_target = IP_MASQ_TARGET_VS; ctl.m_cmd = cmd; strncpy(ctl.m_tname, vs->sched, IP_MASQ_TNAME_MAX); ctl.u.vs_user.weight = -1; ctl.u.vs_user.masq_flags = vs->loadbalancing_kind; ctl.u.vs_user.netmask = ((u_int32_t) 0xffffffff); ctl.u.vs_user.protocol = vs->service_type; if (!parse_timeout(vs->timeout_persistence, &ctl.u.vs_user.timeout)) log_message(LOG_INFO, "IPVS : Virtual service [%s:%d] illegal timeout.", inet_ntop2(SVR_IP(vs)) , ntohs(SVR_PORT(vs))); if (ctl.u.vs_user.timeout != 0 || vs->granularity_persistence) ctl.u.vs_user.vs_flags = IP_VS_SVC_F_PERSISTENT; /* VS specific */ if (vs->vfwmark) { ctl.u.vs_user.vfwmark = vs->vfwmark; } else { ctl.u.vs_user.vaddr = SVR_IP(vs); ctl.u.vs_user.vport = SVR_PORT(vs); } if (ctl.m_cmd == IP_MASQ_CMD_ADD || ctl.m_cmd == IP_MASQ_CMD_DEL) if (vs->granularity_persistence) ctl.u.vs_user.netmask = vs->granularity_persistence; /* SVR specific */ if (ctl.m_cmd == IP_MASQ_CMD_ADD_DEST || ctl.m_cmd == IP_MASQ_CMD_DEL_DEST || ctl.m_cmd == IP_MASQ_CMD_SET_DEST) { ctl.u.vs_user.weight = rs->weight; ctl.u.vs_user.daddr = SVR_IP(rs); ctl.u.vs_user.dport = SVR_PORT(rs); } /* Does the service use inhibit flag ? */ if (ctl.m_cmd == IP_MASQ_CMD_DEL_DEST && rs->inhibit) { ctl.m_cmd = IP_MASQ_CMD_SET_DEST; ctl.u.vs_user.weight = 0; } if (ctl.m_cmd == IP_MASQ_CMD_ADD_DEST && rs->inhibit && !rs->alive) ctl.m_cmd = IP_MASQ_CMD_SET_DEST; sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (sockfd == -1) { log_message(LOG_INFO, "IPVS : Can not initialize SOCK_RAW descriptor."); return IPVS_ERROR; } result = setsockopt(sockfd, IPPROTO_IP, IP_FW_MASQ_CTL, (char *) &ctl, sizeof (ctl)); if (errno == ESRCH) { log_message(LOG_INFO, "IPVS : Virtual service [%s:%d] not defined.", inet_ntop2(SVR_IP(vs)) , ntohs(SVR_PORT(vs))); close(sockfd); return IPVS_ERROR; } else if (errno == EEXIST) { if (rs) log_message(LOG_INFO, "IPVS : Destination already exists [%s:%d].", inet_ntop2(SVR_IP(rs)) , ntohs(SVR_PORT(rs))); } else if (errno == ENOENT) { if (rs) log_message(LOG_INFO, "IPVS : No such destination [%s:%d].", inet_ntop2(SVR_IP(rs)) , ntohs(SVR_PORT(rs))); } close(sockfd); return IPVS_SUCCESS; }
static void dump_if(void *data) { interface_t *ifp = data; #ifdef _HAVE_VRRP_VMAC_ interface_t *ifp_u; #endif char addr_str[INET6_ADDRSTRLEN]; log_message(LOG_INFO, "------< NIC >------"); log_message(LOG_INFO, " Name = %s", ifp->ifname); log_message(LOG_INFO, " index = %d", ifp->ifindex); log_message(LOG_INFO, " IPv4 address = %s", inet_ntop2(ifp->sin_addr.s_addr)); inet_ntop(AF_INET6, &ifp->sin6_addr, addr_str, sizeof(addr_str)); log_message(LOG_INFO, " IPv6 address = %s", addr_str); /* FIXME: Hardcoded for ethernet */ if (ifp->hw_type == ARPHRD_ETHER) log_message(LOG_INFO, " MAC = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x", ifp->hw_addr[0], ifp->hw_addr[1], ifp->hw_addr[2] , ifp->hw_addr[3], ifp->hw_addr[4], ifp->hw_addr[5]); if (ifp->flags & IFF_UP) log_message(LOG_INFO, " is UP"); if (ifp->flags & IFF_RUNNING) log_message(LOG_INFO, " is RUNNING"); if (!(ifp->flags & IFF_UP) && !(ifp->flags & IFF_RUNNING)) log_message(LOG_INFO, " is DOWN"); log_message(LOG_INFO, " MTU = %d", ifp->mtu); switch (ifp->hw_type) { case ARPHRD_LOOPBACK: log_message(LOG_INFO, " HW Type = LOOPBACK"); break; case ARPHRD_ETHER: log_message(LOG_INFO, " HW Type = ETHERNET"); break; default: log_message(LOG_INFO, " HW Type = UNKNOWN"); break; } #ifdef _HAVE_VRRP_VMAC_ if (ifp->vmac && (ifp_u = if_get_by_ifindex(ifp->base_ifindex))) log_message(LOG_INFO, " VMAC underlying interface = %s", ifp_u->ifname); #endif /* MII channel supported ? */ if (IF_MII_SUPPORTED(ifp)) log_message(LOG_INFO, " NIC support MII regs"); else if (IF_ETHTOOL_SUPPORTED(ifp)) log_message(LOG_INFO, " NIC support EHTTOOL GLINK interface"); else log_message(LOG_INFO, " Enabling NIC ioctl refresh polling"); if (ifp->garp_delay) { if (ifp->garp_delay->have_garp_interval) log_message(LOG_INFO, " Gratuitous ARP interval %ldms", ifp->garp_delay->garp_interval.tv_sec * 100 + ifp->garp_delay->garp_interval.tv_usec / (TIMER_HZ / 100)); if (ifp->garp_delay->have_gna_interval) log_message(LOG_INFO, " Gratuitous NA interval %ldms", ifp->garp_delay->gna_interval.tv_sec * 100 + ifp->garp_delay->gna_interval.tv_usec / (TIMER_HZ / 100)); if (ifp->garp_delay->aggregation_group) log_message(LOG_INFO, " Gratuitous ARP aggregation group %d", ifp->garp_delay->aggregation_group); } }
int misc_check_child_thread(thread * thread_obj) { int wait_status; checker *checker_obj; misc_checker *misc_chk; checker_obj = THREAD_ARG(thread_obj); misc_chk = CHECKER_ARG(checker_obj); if (thread_obj->type == THREAD_CHILD_TIMEOUT) { pid_t pid; pid = THREAD_CHILD_PID(thread_obj); /* The child hasn't responded. Kill it off. */ if (svr_checker_up(checker_obj->id, checker_obj->rs)) { log_message(LOG_INFO, "Misc check to [%s] for [%s] timed out", inet_ntop2(CHECKER_RIP(checker_obj)), misc_chk->path); smtp_alert(checker_obj->rs, NULL, NULL, "DOWN", "=> MISC CHECK script timeout on service <="); update_svr_checker_state(DOWN, checker_obj->id , checker_obj->vs , checker_obj->rs); } kill(pid, SIGTERM); thread_add_child(thread_obj->master, misc_check_child_timeout_thread, checker_obj, pid, 2); return 0; } wait_status = THREAD_CHILD_STATUS(thread_obj); if (WIFEXITED(wait_status)) { int status; status = WEXITSTATUS(wait_status); if (status == 0 || (misc_chk->dynamic == 1 && status >= 2 && status <= 255)) { /* * The actual weight set when using misc_dynamic is two less than * the exit status returned. Effective range is 0..253. * Catch legacy case of status being 0 but misc_dynamic being set. */ if (misc_chk->dynamic == 1 && status != 0) update_svr_wgt(status - 2, checker_obj->vs, checker_obj->rs); /* everything is good */ if (!svr_checker_up(checker_obj->id, checker_obj->rs)) { log_message(LOG_INFO, "Misc check to [%s] for [%s] success.", inet_ntop2(CHECKER_RIP(checker_obj)), misc_chk->path); smtp_alert(checker_obj->rs, NULL, NULL, "UP", "=> MISC CHECK succeed on service <="); update_svr_checker_state(UP, checker_obj->id , checker_obj->vs , checker_obj->rs); } } else { if (svr_checker_up(checker_obj->id, checker_obj->rs)) { log_message(LOG_INFO, "Misc check to [%s] for [%s] failed.", inet_ntop2(CHECKER_RIP(checker_obj)), misc_chk->path); smtp_alert(checker_obj->rs, NULL, NULL, "DOWN", "=> MISC CHECK failed on service <="); update_svr_checker_state(DOWN, checker_obj->id , checker_obj->vs , checker_obj->rs); } } } return 0; }