diff options
| author | Lucas Castro <lucas@gnuabordo.com.br> | 2024-01-11 12:07:59 -0300 |
|---|---|---|
| committer | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2024-06-05 19:00:29 -0300 |
| commit | a4676d0e2e75ebcadfb2c947f7a1fa39b8aea246 (patch) | |
| tree | 635a07582f6f525318bfed44c38bda264f65f28c /lsm.c | |
| parent | ca0774165e52cc2c08a6bac98ed3f8622842930e (diff) | |
New upstream version 1.0.8
Diffstat (limited to 'lsm.c')
| -rw-r--r-- | lsm.c | 2162 |
1 files changed, 0 insertions, 2162 deletions
@@ -1,2162 +0,0 @@ -/* - -(C) 2009-2015 Mika Ilmaranta <ilmis@nullnet.fi> - -License: GPLv2 - -*/ - -#define _GNU_SOURCE - -#include <stdio.h> -#include <errno.h> -#include <time.h> -#include <signal.h> -#include <netinet/ip.h> -#include <netinet/ip_icmp.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <stddef.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <netinet/in_systm.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <sys/select.h> -#include <syslog.h> -#include <sys/wait.h> -#include <stdarg.h> -#include <fcntl.h> - -#include <sys/ioctl.h> -#include <linux/if.h> -#include <sys/uio.h> - -#include "icmp_t.h" -#include "icmp6_t.h" -#include "config.h" -#include "cksum.h" -#include "globals.h" -#include "signal_handler.h" -#include "forkexec.h" -#include "timecalc.h" -#include "lsm.h" -#ifndef NO_PLUGIN_EXPORT -#include "plugin_export.h" -#endif -#include "save_statuses.h" -#include "pidfile.h" -#include "cmdline.h" -#include "usage.h" - -typedef struct ping_data { - unsigned short id; /* target id */ - long ping_count; /* counts up to -c count or 1 */ - struct timeval ping_ts; /* time sent */ -} PING_DATA; - -static void update_stats(CONFIG *first); -static void dump_statuses(CONFIG *first); -static void decide(CONFIG *first); -static void groups_decide(GROUPS *firstg); -static int wait_for_replies(CONFIG **ctable); -static int ping_send(CONFIG *cur); -static int ping_rcv(CONFIG *first, char *buf, int len, struct sockaddr_in6 *saddr, unsigned int *slen, long usec, CONFIG **arp); -static int event_script_check(const char *path); -static int open_arp_sock(CONFIG *cur); -static int open_icmp_sock(CONFIG *cur); -static int probe_src_ip_addr(CONFIG *cur); -static void init_config_data(CONFIG *first, CONFIG *last, CONFIG ***ctable); -static void free_config_data(CONFIG *first); -#if defined(DEBUG) -static void dump_pkt(const void *buf, size_t len); -#endif - -static int num_hosts = 0; - -/* Main */ -int main(int argc, char *argv[]) { - TARGET *t = NULL; - CONFIG *first = NULL, *last = NULL, *cur; - GROUPS *firstg = NULL, *lastg = NULL; - CONFIG **ctable = NULL; - struct timeval last_sent_time = {0, 0}; - int start = 0; - - openlog("lsm", LOG_PID, LOG_DAEMON); - - cmdline_parse(argc, argv); - - init_config(); - - if(read_config(get_configfile(), &first, &last, &firstg, &lastg)) { - usage_and_exit(); - } - - if(cfg.debug >= 9) syslog(LOG_INFO, "my ident is %d\n", get_ident()); - - if(!first) { - syslog(LOG_ERR, "no targets found in config file"); - exit(1); - } - - if(cfg.debug >= 9) dump_config(&first, &last, &firstg, &lastg); - - /* check pid file */ - if(pidfile_open() != 0) exit(1); - - /* detach from controlling terminal if nodaemon global is not set */ - if(get_nodaemon() == 0) { - if(daemon(1, 0)) { - syslog(LOG_ERR, "daemon failed while trying to detach"); - return(1); - } - } - - if(pidfile_update() != 0) exit(1); - - set_ident(getpid() & 0xFFFF); - -#ifndef NO_PLUGIN_EXPORT - plugin_export_init(); -#endif - - init_config_data(first, last, &ctable); - - signal(SIGINT, signal_handler); - signal(SIGUSR1, signal_handler); - signal(SIGUSR2, signal_handler); - signal(SIGHUP, signal_handler); - - /* - Create the handler for child signals. This will clean up - any forked child after an event has occured. - */ - create_sigchld_hdl(); - - struct timeval last_decision = {0, 0}; - - /* the main loop */ - while(get_cont()) { - struct timeval tv = {0, 0}; - - if(get_reload_cfg()) { - - save_statuses(first); - - /* reload config */ - free(ctable); - free_config_data(first); - if(reload_config(get_configfile(), &first, &last, &firstg, &lastg)) { - syslog(LOG_ERR, "reload config failed"); - exit(2); - } - init_config_data(first, last, &ctable); - - restore_statuses(first); - - set_reload_cfg(0); - } - - for(cur = first; cur; cur = cur->next) { - struct timeval current_time = {0, 0}; - - if(start) - while(wait_for_replies(ctable)); - - if(gettimeofday(¤t_time, NULL) == -1) { - syslog(LOG_INFO, "gettimeofday failed \"%s\"", strerror(errno)); - sleep(1); - continue; - } - - t = cur->data; - - if(timeval_diff_cmp(¤t_time, &last_sent_time, TIMEVAL_DIFF_CMP_LT, MIN_PERHOST_INTERVAL / 1000000L, MIN_PERHOST_INTERVAL % 1000000L)) continue; - - if(cur->startup_burst_pkts && t->used <= cur->startup_burst_pkts && !timeval_diff_cmp(¤t_time, &(t->last_send_time), TIMEVAL_DIFF_CMP_LT, (cur->startup_burst_interval * 1000) / 1000000L, (cur->startup_burst_interval * 1000) % 1000000L)); - else if(timeval_diff_cmp(¤t_time, &(t->last_send_time), TIMEVAL_DIFF_CMP_LT, (cur->interval_ms * 1000) / 1000000L, (cur->interval_ms * 1000) % 1000000L)) continue; - - if(cur->check_arp) { - open_arp_sock(cur); - } else { - open_icmp_sock(cur); - } - - if(ping_send(cur)) { - if(cfg.debug >= 9) syslog(LOG_INFO, "ping_send failed to %s", cur->name); - } - else { - gettimeofday(&last_sent_time, NULL); - start = 1; - } - } - - gettimeofday(&tv, NULL); - if(timeval_diff_cmp(&tv, &last_decision, TIMEVAL_DIFF_CMP_GT, 1, 0)) { /* make decisions at 1s intervals */ - gettimeofday(&last_decision, NULL); - - update_stats(first); - decide(first); - dump_statuses(first); - - groups_decide(firstg); - -#if defined(DEBUG) - exec_queue_dump(); -#endif - exec_queue_process(); - -#ifndef NO_PLUGIN_EXPORT - plugin_export(first); -#endif - } - } /* while cont */ - - /* if we wrote pid file then close and remove it */ - pidfile_close(); - - free(ctable); - free_config_data(first); - free_config(&first, &last, &firstg, &lastg); - exec_queue_free(); - - closelog(); - - return(0); -} - -static void free_config_data(CONFIG *first) { - CONFIG *cur; - - for(cur = first; cur; cur = cur->next) { - TARGET *t; - - t = cur->data; - if(t->sock != -1) close(t->sock); - free(t); - } -} - -static void update_stats(CONFIG *first) { - struct timeval current_time = {0, 0}; - CONFIG *cur; - - gettimeofday(¤t_time, NULL); - - for(cur = first; cur; cur = cur->next) { - TARGET *t; - int i, seq, ind; - long rtt = 0; - - t = cur->data; - - t->timeout = 0; - t->replied = 0; - t->waiting = 0; - t->reply_late = 0; - t->consecutive_waiting = 0; - t->consecutive_missing = 0; - t->consecutive_rcvd = 0; - - /* check consecutive pkts */ - seq = t->seq % FOLLOWED_PKTS; - - for(i = (seq - 2); i > (seq - 2) - FOLLOWED_PKTS; i--) { - ind = (i >= 0) ? i : i + FOLLOWED_PKTS; - if(!t->sentpkts[ind].flags.used) break; - - if(t->sentpkts[ind].flags.waiting) t->consecutive_waiting++; - else break; - } - - for(i = (seq - 2); i > (seq - 2) - FOLLOWED_PKTS; i--) { - ind = (i >= 0) ? i : i + FOLLOWED_PKTS; - if(!t->sentpkts[ind].flags.used) break; - - if(t->sentpkts[ind].flags.timeout || t->sentpkts[ind].flags.waiting) t->consecutive_missing++; - else break; - } - - for(i = (seq - 2); i > (seq - 2) - FOLLOWED_PKTS; i--) { - ind = (i >= 0) ? i : i + FOLLOWED_PKTS; - if(!t->sentpkts[ind].flags.used) break; - - if(t->sentpkts[ind].flags.replied && !t->sentpkts[ind].flags.timeout) t->consecutive_rcvd++; - else break; - } - - /* count pkt states */ - for(i = 0; i < FOLLOWED_PKTS; i++) { - if(!t->sentpkts[i].flags.used) continue; - - if(timeval_diff_cmp(¤t_time, &t->sentpkts[i].sent_time, TIMEVAL_DIFF_CMP_GT, (cur->timeout_ms * 1000) / 1000000L, (cur->timeout_ms * 1000) % 1000000L) && t->sentpkts[i].flags.waiting) { - t->sentpkts[i].flags.timeout = 1; - } - - if(t->sentpkts[i].flags.replied && t->sentpkts[i].flags.timeout) t->reply_late++; - - if(t->sentpkts[i].flags.replied) { - t->replied++; - rtt += t->sentpkts[i].rtt; /* count rtt sum in usec from replied pkts rtt which is in usec */ - } - if(t->sentpkts[i].flags.timeout) t->timeout++; - if(t->sentpkts[i].flags.waiting) t->waiting++; - } - /* avg_rtt in usec */ - t->avg_rtt = rtt / (t->replied ? t->replied : 1); - - /* update loss max info */ - if(t->timeout > t->timeout_max) t->timeout_max = t->timeout; - if(t->consecutive_missing > t->consecutive_missing_max) t->consecutive_missing_max = t->consecutive_missing; - - if(cfg.debug >= 9) syslog(LOG_INFO, "name = %s, replied = %d, waiting = %d, timeout = %d, late reply = %d, cons rcvd = %d, cons wait = %d, cons miss = %d, avg_rtt = %.3f, seq = %d, status = %s", - cur->name, t->replied, t->waiting, t->timeout, t->reply_late, t->consecutive_rcvd, t->consecutive_waiting, t->consecutive_missing, t->avg_rtt / 1000.0, t->seq, get_status_str(t->status)); - - } -} - -static void dump_statuses(CONFIG *first) { - CONFIG *cur; - - for(cur = first; cur; cur = cur->next) { - TARGET *t; - - t = cur->data; - - if((t->status == DOWN || t->status == LONG_DOWN) && t->downseq == (t->seq % FOLLOWED_PKTS) && t->seq != t->downseqreported && !t->status_change) syslog(LOG_INFO, "link %s still down", cur->name); - - /* dump is controlled by SIGUSR1 and then we should show all statuses anyway */ - if(get_dump() || t->status_change || ((t->status == DOWN || t->status == LONG_DOWN) && t->downseq == (t->seq % FOLLOWED_PKTS) && t->seq != t->downseqreported && !t->status_change)) { - if(cfg.debug >= 6) syslog(LOG_INFO, "name = %s, replied = %d, waiting = %d, timeout = %d, timeout max = %d, late reply = %d, cons rcvd = %d, cons wait = %d, cons miss = %d, cons miss max = %d, avg_rtt = %.3f, seq = %d, status = %s", - cur->name, t->replied, t->waiting, t->timeout, t->timeout_max, t->reply_late, t->consecutive_rcvd, t->consecutive_waiting, t->consecutive_missing, t->consecutive_missing_max, t->avg_rtt / 1000.0, t->seq, get_status_str(t->status)); - - if(cfg.debug >= 7) { - /* 100 should be enough for the comments and such, but I don't care to count */ - char buf[FOLLOWED_PKTS + 100]; - int i, seq; - - seq = t->seq % FOLLOWED_PKTS; - - sprintf(buf, "seq "); - for(i = 0; i < FOLLOWED_PKTS; i++) { - if(i == seq) strcat(buf, "*"); - else strcat(buf, " "); - } - syslog(LOG_INFO, "%s", buf); - - sprintf(buf, "used "); - for(i = 0; i < FOLLOWED_PKTS; i++) { - sprintf(buf + strlen(buf), "%d", t->sentpkts[i].flags.used); - } - syslog(LOG_INFO, "%s", buf); - - sprintf(buf, "wait "); - for(i = 0; i < FOLLOWED_PKTS; i++) { - sprintf(buf + strlen(buf), "%d", t->sentpkts[i].flags.waiting); - } - syslog(LOG_INFO, "%s", buf); - - sprintf(buf, "replied "); - for(i = 0; i < FOLLOWED_PKTS; i++) { - sprintf(buf + strlen(buf), "%d", t->sentpkts[i].flags.replied); - } - syslog(LOG_INFO, "%s", buf); - - sprintf(buf, "timeout "); - for(i = 0; i < FOLLOWED_PKTS; i++) { - sprintf(buf + strlen(buf), "%d", t->sentpkts[i].flags.timeout); - } - syslog(LOG_INFO, "%s", buf); - - sprintf(buf, "error "); - for(i = 0; i < FOLLOWED_PKTS; i++) { - sprintf(buf + strlen(buf), "%d", t->sentpkts[i].flags.error); - } - syslog(LOG_INFO, "%s", buf); - - if(t->status == UP && t->status_change) { - t->timeout_max = 0; - t->consecutive_missing_max = 0; - } - } - - t->downseqreported = t->seq; - } - } - if(get_dump()) set_dump(0); /* if we just dumped then don't dump next time. flags don't change that frequently */ -} - -static void decide(CONFIG *first) { - struct timeval current_time = {0, 0}; - CONFIG *cur; - - gettimeofday(¤t_time, NULL); - - for(cur = first; cur; cur = cur->next) { - TARGET *t; - STATUS prevstatus; - - t = cur->data; - - /* reset any previous connection status_change state */ - t->status_change = 0; - - prevstatus = t->status; - - /* up or unknown */ - if(t->status == UP || t->status == UNKNOWN) { - if(t->timeout >= cur->max_packet_loss || t->consecutive_missing >= cur->max_successive_pkts_lost) { - /* change to down state */ - t->status_change = 1; - t->status = DOWN; - -#if !defined(NO_PLUGIN_EXPORT) && !defined(NO_PLUGIN_EXPORT_STATUS) - plugin_export_status(first); -#endif - - if(cfg.debug >= 8) syslog(LOG_INFO, "link %s down event", cur->name); - if(event_script_check(cur->eventscript)) { - char sbuf[INET6_ADDRSTRLEN]; - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - cur->eventscript, - get_status_str(t->status), - cur->name, - cur->checkip, - cur->device ? cur->device : "", - cur->warn_email ? cur->warn_email : "", - t->replied, - t->waiting, - t->timeout, - t->reply_late, - t->consecutive_rcvd, - t->consecutive_waiting, - t->consecutive_missing, - t->avg_rtt, - cur->dstinfo->ai_family == AF_INET ? inet_ntoa(t->src) : inet_ntop(AF_INET6, &t->src6, sbuf, INET6_ADDRSTRLEN), - get_status_str(prevstatus), - current_time.tv_sec); - envp = exec_queue_envp(); - - if(cur->queue && *cur->queue) { - exec_queue_add(cur->queue, argv, envp); - } else { - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - - if(event_script_check(cur->notifyscript)) { - char sbuf[INET6_ADDRSTRLEN]; - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - cur->notifyscript, - get_status_str(t->status), - cur->name, - cur->checkip, - cur->device ? cur->device : "", - cur->warn_email ? cur->warn_email : "", - t->replied, - t->waiting, - t->timeout, - t->reply_late, - t->consecutive_rcvd, - t->consecutive_waiting, - t->consecutive_missing, - t->avg_rtt, - cur->dstinfo->ai_family == AF_INET ? inet_ntoa(t->src) : inet_ntop(AF_INET6, &t->src6, sbuf, INET6_ADDRSTRLEN), - get_status_str(prevstatus), - current_time.tv_sec); - - envp = exec_queue_envp(); - - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - - if(gettimeofday(&t->down_timestamp, NULL) == -1) { - syslog(LOG_INFO, "gettimeofday failed \"%s\"", strerror(errno)); - } - t->downseq = t->seq % FOLLOWED_PKTS; - t->downseqreported = 0; - } - } - - /* has it been down long? */ - if(t->status == DOWN && cur->long_down_time) { - if(timeval_diff_cmp(¤t_time, &t->down_timestamp, TIMEVAL_DIFF_CMP_GT, cur->long_down_time, 0)) { - /* special, LONG_DOWN is considered DOWN thus no status_change */ - t->status = LONG_DOWN; - - if(cfg.debug >= 8) syslog(LOG_INFO, "link %s long down event", cur->name); - if(event_script_check(cur->long_down_eventscript)) { - char sbuf[INET6_ADDRSTRLEN]; - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - cur->long_down_eventscript, - get_status_str(t->status), - cur->name, - cur->checkip, - cur->device ? cur->device : "", - cur->long_down_email ? cur->long_down_email : "", - t->replied, - t->waiting, - t->timeout, - t->reply_late, - t->consecutive_rcvd, - t->consecutive_waiting, - t->consecutive_missing, - t->avg_rtt, - cur->dstinfo->ai_family == AF_INET ? inet_ntoa(t->src) : inet_ntop(AF_INET6, &t->src6, sbuf, INET6_ADDRSTRLEN), - get_status_str(prevstatus), - t->down_timestamp.tv_sec); - - envp = exec_queue_envp(); - - if(cur->queue && *cur->queue) { - exec_queue_add(cur->queue, argv, envp); - } else { - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - - if(event_script_check(cur->long_down_notifyscript)) { - char sbuf[INET6_ADDRSTRLEN]; - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - cur->long_down_notifyscript, - get_status_str(t->status), - cur->name, - cur->checkip, - cur->device ? cur->device : "", - cur->long_down_email ? cur->long_down_email : "", - t->replied, - t->waiting, - t->timeout, - t->reply_late, - t->consecutive_rcvd, - t->consecutive_waiting, - t->consecutive_missing, - t->avg_rtt, - cur->dstinfo->ai_family == AF_INET ? inet_ntoa(t->src) : inet_ntop(AF_INET6, &t->src6, sbuf, INET6_ADDRSTRLEN), - get_status_str(prevstatus), - t->down_timestamp.tv_sec); - - envp = exec_queue_envp(); - - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - } - - /* down, long down or unknown */ - if(t->status == DOWN || t->status == LONG_DOWN || t->status == UNKNOWN) { - if((cur->startup_acceleration && t->consecutive_rcvd >= cur->startup_acceleration && (t->consecutive_rcvd + 1) >= t->used) || (t->timeout <= cur->min_packet_loss && t->consecutive_rcvd >= cur->min_successive_pkts_rcvd)) { - - t->status_change = 1; - t->status = UP; - -#if !defined(NO_PLUGIN_EXPORT) && !defined(NO_PLUGIN_EXPORT_STATUS) - plugin_export_status(first); -#endif - - /* report long_down to up */ - if(prevstatus == LONG_DOWN) { - if(event_script_check(cur->long_down_eventscript)) { - char sbuf[INET6_ADDRSTRLEN]; - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - cur->long_down_eventscript, - get_status_str(t->status), - cur->name, - cur->checkip, - cur->device ? cur->device : "", - cur->long_down_email ? cur->long_down_email : "", - t->replied, - t->waiting, - t->timeout, - t->reply_late, - t->consecutive_rcvd, - t->consecutive_waiting, - t->consecutive_missing, - t->avg_rtt, - cur->dstinfo->ai_family == AF_INET ? inet_ntoa(t->src) : inet_ntop(AF_INET6, &t->src6, sbuf, INET6_ADDRSTRLEN), - get_status_str(prevstatus), - current_time.tv_sec); - - envp = exec_queue_envp(); - - if(cur->queue && *cur->queue) { - exec_queue_add(cur->queue, argv, envp); - } else { - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - - if(event_script_check(cur->long_down_notifyscript)) { - char sbuf[INET6_ADDRSTRLEN]; - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - cur->long_down_notifyscript, - get_status_str(t->status), - cur->name, - cur->checkip, - cur->device ? cur->device : "", - cur->long_down_email ? cur->long_down_email : "", - t->replied, - t->waiting, - t->timeout, - t->reply_late, - t->consecutive_rcvd, - t->consecutive_waiting, - t->consecutive_missing, - t->avg_rtt, - cur->dstinfo->ai_family == AF_INET ? inet_ntoa(t->src) : inet_ntop(AF_INET6, &t->src6, sbuf, INET6_ADDRSTRLEN), - get_status_str(prevstatus), - current_time.tv_sec); - - envp = exec_queue_envp(); - - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - - /* change to up state */ - if(cfg.debug >= 8) syslog(LOG_INFO, "link %s up event", cur->name); - if(event_script_check(cur->eventscript)) { - char sbuf[INET6_ADDRSTRLEN]; - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - cur->eventscript, - get_status_str(t->status), - cur->name, - cur->checkip, - cur->device ? cur->device : "", - cur->warn_email ? cur->warn_email : "", - t->replied, - t->waiting, - t->timeout, - t->reply_late, - t->consecutive_rcvd, - t->consecutive_waiting, - t->consecutive_missing, - t->avg_rtt, - cur->dstinfo->ai_family == AF_INET ? inet_ntoa(t->src) : inet_ntop(AF_INET6, &t->src6, sbuf, INET6_ADDRSTRLEN), - get_status_str(prevstatus), - current_time.tv_sec); - - envp = exec_queue_envp(); - - if(cur->queue && *cur->queue) { - exec_queue_add(cur->queue, argv, envp); - } else { - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - - if((cur->unknown_up_notify || t->status != UNKNOWN) && event_script_check(cur->notifyscript)) { - char sbuf[INET6_ADDRSTRLEN]; - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - cur->notifyscript, - get_status_str(t->status), - cur->name, - cur->checkip, - cur->device ? cur->device : "", - cur->warn_email ? cur->warn_email : "", - t->replied, - t->waiting, - t->timeout, - t->reply_late, - t->consecutive_rcvd, - t->consecutive_waiting, - t->consecutive_missing, - t->avg_rtt, - cur->dstinfo->ai_family == AF_INET ? inet_ntoa(t->src) : inet_ntop(AF_INET6, &t->src6, sbuf, INET6_ADDRSTRLEN), - get_status_str(prevstatus), - current_time.tv_sec); - - envp = exec_queue_envp(); - - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - } - } -} - -static void groups_decide(GROUPS *firstg){ - GROUPS *curg; - GROUP_MEMBERS *curgm; - TARGET *t; - STATUS prevstatus; - struct timeval current_time = {0, 0}; - - gettimeofday(¤t_time, NULL); - - curg = firstg; - while(curg) { - prevstatus = curg->status; - curg->status = curg->logic; - - curgm = curg->fgm; - while(curgm) { - if(!curgm->cfg_ptr) break; - - t = curgm->cfg_ptr->data; - - /* if any one group member is in unknown status, group is in unknown status */ - if(t->status == UNKNOWN) { - curg->status = UNKNOWN; - break; - } - - if(!curg->logic) { - curg->status |= (t->status == DOWN || t->status == LONG_DOWN) ? DOWN : t->status; - } else { - curg->status &= (t->status == DOWN || t->status == LONG_DOWN) ? DOWN : t->status; - } - - curgm = curgm->next; - } - if(curg->status != prevstatus) { - if(curg->status == UP) { - /* group up event */ - if(cfg.debug >= 8) syslog(LOG_INFO, "group %s up event", curg->name); - if(event_script_check(curg->eventscript)) { - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - curg->eventscript, - get_status_str(curg->status), - curg->name, - "", - "", - curg->warn_email ? curg->warn_email : "", - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - "", - get_status_str(prevstatus), - current_time.tv_sec); - envp = exec_queue_envp(); - - if(curg->queue && *curg->queue) { - exec_queue_add(curg->queue, argv, envp); - } else { - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - if((curg->unknown_up_notify || prevstatus != UNKNOWN) && event_script_check(curg->notifyscript)) { - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - curg->notifyscript, - get_status_str(curg->status), - curg->name, - "", - "", - curg->warn_email ? curg->warn_email : "", - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - "", - get_status_str(prevstatus), - current_time.tv_sec); - envp = exec_queue_envp(); - - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - - if(curg->status == DOWN) { - /* group down event */ - if(cfg.debug >= 8) syslog(LOG_INFO, "group %s down event", curg->name); - if(event_script_check(curg->eventscript)) { - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - curg->eventscript, - get_status_str(curg->status), - curg->name, - "", - "", - curg->warn_email ? curg->warn_email : "", - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - "", - get_status_str(prevstatus), - current_time.tv_sec); - envp = exec_queue_envp(); - - if(curg->queue && *curg->queue) { - exec_queue_add(curg->queue, argv, envp); - } else { - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - if(event_script_check(curg->notifyscript)) { - char **argv; - char **envp; - - argv = exec_queue_argv("%s %s %s %s %s %s %d %d %d %d %d %d %d %d %s %s %d", - curg->notifyscript, - get_status_str(curg->status), - curg->name, - "", - "", - curg->warn_email ? curg->warn_email : "", - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - "", - get_status_str(prevstatus), - current_time.tv_sec); - envp = exec_queue_envp(); - - forkexec(argv, envp); - - exec_queue_argv_free(argv); - exec_queue_envp_free(envp); - } - } - } - curg = curg->next; - } -} - -static int wait_for_replies(CONFIG **ctable) { - struct ip *ip; - int hlen = 0; - struct icmp *icp; - struct icmp6_hdr *icp6; - PING_DATA *pdp; - int this_count; - struct timeval sent_time = {0, 0}; - struct timeval current_time = {0, 0}; - long time_diff; - char buf[BUFSIZ]; - union { - struct sockaddr_in6 saddr6; - struct sockaddr_in saddr; - struct sockaddr_ll FROM; - } from_addr; - unsigned int slen; - int result; - TARGET *t; - int seq; - CONFIG *arp; - - slen = sizeof(from_addr); - result = ping_rcv(ctable[0], buf, BUFSIZ, (struct sockaddr_in6 *)&from_addr, &slen, DEFAULT_SELECT_WAIT, &arp); - - if(result <= 0) { - return(0); - } - - gettimeofday(¤t_time, NULL); - - if(arp) { - struct sockaddr_ll *FROM = &from_addr.FROM; - TARGET *t = arp->data; - struct arphdr *ah = (struct arphdr*)buf; - unsigned char *p = (unsigned char *)(ah+1); - struct in_addr src_ip, dst_ip; - int ind; - - /* Filter out wild packets */ - if(FROM->sll_pkttype != PACKET_HOST && - FROM->sll_pkttype != PACKET_BROADCAST && - FROM->sll_pkttype != PACKET_MULTICAST) - return(1); - - /* Only these types are recognised */ -#if 0 - if(ah->ar_op != htons(ARPOP_REQUEST) && - ah->ar_op != htons(ARPOP_REPLY)) - return(1); -#else - if(ah->ar_op != htons(ARPOP_REPLY)) - return(1); -#endif - - /* ARPHRD check and this darned FDDI hack here :-( */ - if(ah->ar_hrd != htons(FROM->sll_hatype) && - (FROM->sll_hatype != ARPHRD_FDDI || ah->ar_hrd != htons(ARPHRD_ETHER))) - return(1); - - /* Protocol must be IP. */ - if(ah->ar_pro != htons(ETH_P_IP)) - return(1); - if(ah->ar_pln != 4) - return(1); - if(ah->ar_hln != t->me.sll_halen) - return(1); - -#if defined(DEBUG) - for(ind = 0; ind < result; ind ++) { - fprintf(stderr, "%02x", (unsigned char)buf[ind]); - if(!((ind + 1) % 2)) fprintf(stderr, " "); - if(!((ind + 1) % 32)) fprintf(stderr, "\n"); - } - fprintf(stderr, "\n"); - for(ind = 0; ind < result; ind ++) { - fprintf(stderr, "%3u", (unsigned char)buf[ind]); - if(!((ind + 1) % 32)) fprintf(stderr, "\n"); - else fprintf(stderr, ","); - } - fprintf(stderr, "\n"); -#endif - - if(result < sizeof(*ah) + 2*(4 + ah->ar_hln)) - return(1); - - memcpy(&src_ip, p+ah->ar_hln, 4); - memcpy(&dst_ip, p+ah->ar_hln+4+ah->ar_hln, 4); - - if(src_ip.s_addr != t->dst.s_addr) - return(1); - if(t->src.s_addr != dst_ip.s_addr) - return(1); - if(memcmp(p+ah->ar_hln+4, &t->me.sll_addr, ah->ar_hln)) - return(1); - - /* update packet log here */ - /* there are no sequence numbers in arp replies so just mark seq - 1 replied */ - ind = ((t->seq - 1) >= 0 ? (t->seq - 1) : (FOLLOWED_PKTS + (t->seq - 1))) % FOLLOWED_PKTS; - t->sentpkts[ind].flags.replied = 1; - t->sentpkts[ind].flags.waiting = 0; - t->sentpkts[ind].replied_time = current_time; - t->sentpkts[ind].rtt = timeval_diff(¤t_time, &t->sentpkts[ind].sent_time); - - return(1); - } - -#if defined(DEBUG) - if(cfg.debug >= 9) { - char sbuf[INET6_ADDRSTRLEN]; - - syslog(LOG_INFO, "not arp: family = %d, AF_INET = %d, AF_INET6 = %d, inet_ntop addr = %s, inet_ntoa addr = %s", from_addr.saddr6.sin6_family, AF_INET, AF_INET6, inet_ntop(from_addr.saddr6.sin6_family, &from_addr.saddr6.sin6_addr, sbuf, INET6_ADDRSTRLEN), inet_ntoa(from_addr.saddr.sin_addr)); - } -#endif - - switch(from_addr.saddr6.sin6_family) { - case AF_INET: -#if defined(DEBUG) - syslog(LOG_INFO, "%s: %s: AF_INET reply", __FILE__, __FUNCTION__); -#endif - ip = (struct ip *)buf; - hlen = ip->ip_hl << 2; - - icp = (struct icmp *)(buf + hlen); - - if(icp->icmp_type == ICMP_ECHO) { - return(1); - } - - if(icp->icmp_type == ICMP_ECHOREPLY) { - if(icp->icmp_id != get_ident()) { - /* fprintf(stderr, "icmp_id = %d funny, got reply from %s to something else ...\n", icp->icmp_id, inet_ntoa(saddr.sin_addr)); */ - return(1); - } - - if(result < sizeof(struct icmp) + sizeof(PING_DATA)) { - /* fprintf(stderr, "too short ping reply\n"); */ - return(1); - } - - pdp = (PING_DATA *)(buf + hlen + sizeof(struct icmp)); - - this_count = pdp->ping_count; - sent_time = pdp->ping_ts; - time_diff = timeval_diff(¤t_time, &sent_time); - - if(pdp->id >= num_hosts) { -#if defined(DEBUG) - syslog(LOG_INFO, "out of range: pdp->id = %d >= num_hosts = %d from %s", pdp->id, num_hosts, inet_ntoa(from_addr.saddr.sin_addr)); - dump_pkt(buf, sizeof(struct ip) + sizeof(struct icmp) + sizeof(PING_DATA)); - set_dump(1); -#endif - return(1); - } - - t = ctable[pdp->id]->data; - - if(memcmp(&ip->ip_src, &t->dst, sizeof(struct in_addr) != 0)) { - return(1); - } - - seq = icp->icmp_seq % FOLLOWED_PKTS; - if(t->sentpkts[seq].seq == icp->icmp_seq) { - t->sentpkts[seq].flags.replied = 1; - t->sentpkts[seq].flags.waiting = 0; - t->sentpkts[seq].replied_time = current_time; - t->sentpkts[seq].rtt = timeval_diff(¤t_time, &t->sentpkts[seq].sent_time); - } - else - if(cfg.debug >= 9) syslog(LOG_INFO, "sentpkts seq != icmp_seq"); - - if(cfg.debug >= 9) syslog(LOG_INFO, "received seq = %d from %s, id = %d, num_sent = %d, target id = %u, time_diff = %ld", icp->icmp_seq, inet_ntoa(from_addr.saddr.sin_addr), icp->icmp_id, this_count, pdp->id, time_diff); - - return(1); - - } else { - struct icmpmsg *msg; - - msg = stricmp(icp->icmp_type, icp->icmp_code); - - if(cfg.debug >= 9) syslog(LOG_INFO, "got odd reply from %s, icmp_type = %d %s, icmp_code = %d %s", inet_ntoa(from_addr.saddr.sin_addr), icp->icmp_type, msg->type_msg, icp->icmp_code, msg->code_msg); - - return(1); - } - break; - case AF_INET6: -#if defined(DEBUG) - syslog(LOG_INFO, "%s: %s: AF_INET6 reply", __FILE__, __FUNCTION__); -#endif - icp6 = (struct icmp6_hdr *)buf; - - if(icp6->icmp6_type == ICMP6_ECHO_REQUEST) { - return(1); - } - - if (icp6->icmp6_type == ICMP6_ECHO_REPLY) { /* v6 reply */ - char sbuf[INET6_ADDRSTRLEN]; -#if defined(DEBUG) - dump_pkt(buf, sizeof(struct icmp6_hdr) + sizeof(PING_DATA)); -#endif - /* syslog(LOG_INFO, "sizeof struct icmp6_hdr = %ld\n", sizeof(struct icmp6_hdr)); */ - - if(icp6->icmp6_id != get_ident()) { - return(1); - } - - if(result < sizeof(struct icmp6_hdr) + sizeof(PING_DATA)) { - return(1); - } - - /* pdp = (PING_DATA *)(buf + hlen + sizeof(struct icmp6_hdr)); */ - /* pdp = (PING_DATA *)(buf + sizeof(struct icmp6_hdr)); */ - pdp = (PING_DATA *)(buf + sizeof(struct icmp6_hdr)); - - this_count = pdp->ping_count; - sent_time = pdp->ping_ts; - time_diff = timeval_diff(¤t_time, &sent_time); - -#if defined(DEBUG) - syslog(LOG_INFO, "%s: %s: this_count = %d, sent_time = %ld,%ld, pdp->id = %d", __FILE__, __FUNCTION__, this_count, sent_time.tv_sec, sent_time.tv_usec, pdp->id); -#endif - - if(pdp->id >= num_hosts) { -#if defined(DEBUG) - syslog(LOG_INFO, "out of range: pdp->id = %d >= num_hosts = %d from %s", pdp->id, num_hosts, inet_ntop(AF_INET6, &from_addr.saddr6.sin6_addr, sbuf, INET6_ADDRSTRLEN)); - dump_pkt(buf, sizeof(struct icmp6_hdr) + sizeof(PING_DATA)); - set_dump(1); -#endif - return(1); - } - - t = ctable[pdp->id]->data; - - if(memcmp(&from_addr.saddr6.sin6_addr, &t->dst6, sizeof(struct in6_addr)) != 0) { - return(1); - } - - seq = ntohs(icp6->icmp6_seq) % FOLLOWED_PKTS; - if(t->sentpkts[seq].seq == ntohs(icp6->icmp6_seq)) { - t->sentpkts[seq].flags.replied = 1; - t->sentpkts[seq].flags.waiting = 0; - t->sentpkts[seq].replied_time = current_time; - t->sentpkts[seq].rtt = timeval_diff(¤t_time, &t->sentpkts[seq].sent_time); - } - else - if (cfg.debug >= 9) syslog(LOG_INFO, "sentpkts seq != icmp_seq"); - - if(cfg.debug >= 9) syslog(LOG_INFO, "received seq = %d from %s, id = %d, num_sent = %d, target id = %u, time_diff = %ld", ntohs(icp6->icmp6_seq), inet_ntop(AF_INET6, &from_addr.saddr6.sin6_addr, sbuf, INET6_ADDRSTRLEN), icp6->icmp6_id, this_count, pdp->id, time_diff); - - return(1); - } else { - char sbuf[INET6_ADDRSTRLEN]; - struct icmp6msg *msg; - - msg = stricmp6(icp6->icmp6_type, icp6->icmp6_code); - - if(cfg.debug >= 9) syslog(LOG_INFO, "got odd reply from %s, icmp_type = %d %s, icmp_code = %d %s", inet_ntop(from_addr.saddr6.sin6_family, &from_addr.saddr6.sin6_addr, sbuf, INET6_ADDRSTRLEN), icp6->icmp6_type, msg->type_msg, icp6->icmp6_code, msg->code_msg); - - return(1); - } - break; - default: - syslog(LOG_INFO, "%s: %s: unknown family reply", __FILE__, __FUNCTION__); - break; - } - - return(1); -} - -static int ping_rcv(CONFIG *first, char *buf, int len, struct sockaddr_in6 *saddr, unsigned int *slen, long usec, CONFIG **arp) { - int nfound, n; - fd_set readset; - struct timeval to = {0, 0}; - int max; - CONFIG *cur; - TARGET *t; - int cnt_targets = 0; - - FD_ZERO(&readset); - max = 0; - - for(cur = first; cur; cur = cur->next) { - t = cur->data; - if(t->sock == -1) continue; - if(t->sock > max) max = t->sock; - FD_SET(t->sock, &readset); - cnt_targets++; - } - - /* no point in calling select if we didn't find any open sockets. so sleep and return ... */ - if(cnt_targets == 0) { - sleep(1); - return(0); - } - - to.tv_sec = usec / 1000000; - to.tv_usec = (usec - (to.tv_sec * 1000000)); - -#if defined(DEBUG) - printf("to.tv_sec = %ld, to.tv_usec = %ld\n", to.tv_sec, to.tv_usec); -#endif - - nfound = select(max + 1, &readset, NULL, NULL, &to); - - if(nfound < 0) { - if(errno != EINTR) syslog(LOG_INFO, "select failed \"%s\"", strerror(errno)); - return(0); - } - - if(nfound == 0) return(-1); - - for(cur = first; cur; cur = cur->next) { - t = cur->data; - if(t->sock == -1) continue; - if(FD_ISSET(t->sock, &readset)) { - if(!cur->check_arp) { - *arp = (CONFIG *)NULL; - } else { - *arp = cur; - } - - n = recvfrom(t->sock, buf, len, 0, (struct sockaddr *)saddr, slen); - - if(n < 0) { - syslog(LOG_INFO, "recvfrom failed with %s \"%s\"\n", cur->name, strerror(errno)); - close(t->sock); - t->sock = -1; - return(0); - } - - return(n); - } - } - return(0); -} - -static int ping_send(CONFIG *cur) { - char buf[BUFSIZ]; - struct icmp *icp; - PING_DATA *pdp; - TARGET *t; - int n; - int ping_pkt_size; - - t = cur->data; - - gettimeofday(&t->last_send_time, NULL); - - if(cur->check_arp) { - int err; - unsigned char buf[256]; - struct arphdr *ah = (struct arphdr*)buf; - unsigned char *p = (unsigned char *)(ah+1); - - if(cur->dstinfo->ai_family == AF_INET6) { - syslog(LOG_ERR, "%s: %s: ipv6 arping not supported", __FILE__, __FUNCTION__); - return(-1); - } - - ah->ar_hrd = htons(t->me.sll_hatype); - if(ah->ar_hrd == htons(ARPHRD_FDDI)) - ah->ar_hrd = htons(ARPHRD_ETHER); - ah->ar_pro = htons(ETH_P_IP); - ah->ar_hln = t->me.sll_halen; - ah->ar_pln = 4; - ah->ar_op = htons(ARPOP_REQUEST); - - memcpy(p, &t->me.sll_addr, ah->ar_hln); - p += t->me.sll_halen; - - memcpy(p, &t->src, 4); - p += 4; - - memcpy(p, &t->he.sll_addr, ah->ar_hln); - p += ah->ar_hln; - - memcpy(p, &t->dst, 4); - p += 4; - -#if defined(DEBUG) - { - int ind; - for(ind = 0; ind < p - buf; ind ++) { - fprintf(stderr, "%02x", (unsigned char)buf[ind]); - if(!((ind + 1) % 2)) fprintf(stderr, " "); - if(!((ind + 1) % 32)) fprintf(stderr, "\n"); - } - fprintf(stderr, "\n"); - for(ind = 0; ind < p - buf; ind ++) { - fprintf(stderr, "%3u", (unsigned char)buf[ind]); - if(!((ind + 1) % 32)) fprintf(stderr, "\n"); - else fprintf(stderr, ","); - } - fprintf(stderr, "\n"); - } -#endif - - if(t->sock != -1) { - err = sendto(t->sock, buf, p - buf, 0, (struct sockaddr*)&t->he, sizeof(t->he)); - if(err < 0) { - if(cfg.debug >= 9) syslog(LOG_ERR, "arping sendto failed to %s on %s reason \"%s\"", cur->name, cur->device, strerror(errno)); - close(t->sock); - t->sock = -1; - } - } else { - if(cfg.debug >= 9) syslog(LOG_INFO, "arping sendto socket not open for %s", cur->name); - err = -1; - } - - { /* we don't care what the error was just advance with seq */ - int seq; - - seq = t->seq % FOLLOWED_PKTS; - t->sentpkts[seq].seq = t->seq; - t->sentpkts[seq].sent_time = t->last_send_time; - t->sentpkts[seq].flags.replied = 0; - t->sentpkts[seq].flags.timeout = 0; - t->sentpkts[seq].flags.waiting = 1; - if(t->sentpkts[seq].flags.used == 0) t->used++; - t->sentpkts[seq].flags.used = 1; - t->sentpkts[seq].flags.error = (err == -1) ? 1 : 0; - - t->seq = (t->seq + 1) % SEQ_LIMITER; /* limit seq so that consecutive missing and received pkt counting doesn't get confused when seq "overflows" */ - t->num_sent++; - - } - if(err == (p - buf)) { - return(0); - } - return(err); - } - - if(cur->dstinfo->ai_family == AF_INET6) { - struct icmp6_hdr *icp6; - - ping_pkt_size = sizeof(struct icmp6_hdr) + sizeof(PING_DATA); - - memset(buf, 0, ping_pkt_size); - - icp6 = (struct icmp6_hdr *)buf; - - icp6->icmp6_type = ICMP6_ECHO_REQUEST; - icp6->icmp6_code = 0; - icp6->icmp6_seq = htons(t->seq); /* I saw a tcpdump suggesting that there is something wrong with seq thus htons() */ - icp6->icmp6_id = get_ident(); - - pdp = (PING_DATA *)(buf + sizeof(struct icmp6_hdr)); - pdp->ping_count = t->num_sent; - pdp->ping_ts = t->last_send_time; - pdp->id = t->id; - - icp6->icmp6_cksum = 0; /* the ipv6 stack calculates the checksum for us */ - - if(t->sock != -1) { - if(cfg.debug >= 9) syslog(LOG_INFO, "cmsglen = %d", t->cmsglen); - - if(t->cmsglen == 0) { - n = sendto(t->sock, buf, ping_pkt_size, 0, (struct sockaddr *)&t->dst_addr6, sizeof(t->dst_addr6)); - if(n < 0) { - if(errno == ENODEV) { - if(cfg.debug >= 9) syslog(LOG_ERR, "connection %s no such device %s \"%s\"", cur->name, cur->device, strerror(errno)); - } else - if (cfg.debug >= 9) syslog(LOG_ERR, "ping6 sendto failed to %s on %s reason \"%s\"", cur->name, cur->device, strerror(errno)); - - if(t->sock != -1) { - close(t->sock); - t->sock = -1; - } - } - } else { - struct msghdr mhdr; - struct iovec iov; - int confirm = 0; - - iov.iov_len = ping_pkt_size; - iov.iov_base = buf; - - mhdr.msg_name = &t->dst_addr6; - mhdr.msg_namelen = sizeof(struct sockaddr_in6); - mhdr.msg_iov = &iov; - mhdr.msg_iovlen = 1; - mhdr.msg_control = t->cmsgbuf; - mhdr.msg_controllen = t->cmsglen; - - n = sendmsg(t->sock, &mhdr, confirm); - if(cfg.debug >= 9 && n < 0) syslog(LOG_INFO, "sendmsg failed for %s %s", cur->name, strerror(errno)); - if(n < 0) { - close(t->sock); - t->sock = -1; - } - } - } else { - if(cfg.debug >= 9) syslog(LOG_INFO, "ping sendto socket not open for %s", cur->name); - n = -1; - } - { - /* we don't care what the error was just advance with seq */ - int seq; - - seq = t->seq % FOLLOWED_PKTS; -#if defined(DEBUG) - fprintf(stderr, "ping_send seq = %ld to %s, num_sent = %ld, %ld, pkt_size = %d\n", t->seq, inet_ntoa(t->saddr.sin_addr), t->num_sent, pdp->ping_count, ping_pkt_size); -#endif - t->sentpkts[seq].seq = t->seq; - t->sentpkts[seq].sent_time = t->last_send_time; - t->sentpkts[seq].flags.replied = 0; - t->sentpkts[seq].flags.timeout = 0; - t->sentpkts[seq].flags.waiting = 1; - if(t->sentpkts[seq].flags.used == 0) t->used++; - t->sentpkts[seq].flags.used = 1; - t->sentpkts[seq].flags.error = (n < 1) ? 1 : 0; - - t->seq = (t->seq + 1) % SEQ_LIMITER; - /* limit seq so that consecutive missing and received pkt counting doesn't get confused when seq "overflows" */ - t->num_sent++; - } - if(n == ping_pkt_size) { - return(0); - } - - return(n); - } - - /* send a ping packet */ - ping_pkt_size = sizeof(struct icmp) + sizeof(PING_DATA); - - memset(buf, 0, ping_pkt_size); - - icp = (struct icmp *)buf; - - icp->icmp_type = ICMP_ECHO; - icp->icmp_code = 0; - icp->icmp_cksum = 0; - icp->icmp_seq = t->seq; - icp->icmp_id = get_ident(); - - pdp = (PING_DATA *)(buf + sizeof(struct icmp)); - pdp->ping_count = t->num_sent; - pdp->ping_ts = t->last_send_time; - pdp->id = t->id; - - icp->icmp_cksum = in_cksum((u_short *)icp, ping_pkt_size); - - if(t->sock != -1) { - n = sendto(t->sock, buf, ping_pkt_size, 0, (struct sockaddr *)&t->dst_addr, sizeof(struct sockaddr)); - - if(n < 0) { - if(errno == ENODEV) { - if(cfg.debug >= 9) syslog(LOG_ERR, "connection %s no such device %s \"%s\"", cur->name, cur->device, strerror(errno)); - /* exit(2); */ /* commented out. handle this situation like the packet had been sent. see below. */ - } - else - if(cfg.debug >= 9) syslog(LOG_ERR, "ping sendto failed to %s on %s reason \"%s\"", cur->name, cur->device, strerror(errno)); - - if(t->sock != -1) { - close(t->sock); - t->sock = -1; - } - } - } else { - if(cfg.debug >= 9) syslog(LOG_INFO, "ping sendto socket not open for %s", cur->name); - n = -1; - } - - { /* we don't care what the error was just advance with seq */ - int seq; - - seq = t->seq % FOLLOWED_PKTS; -#if defined(DEBUG) - fprintf(stderr, "ping_send seq = %ld to %s, num_sent = %ld, %ld, pkt_size = %d\n", t->seq, inet_ntoa(t->saddr.sin_addr), t->num_sent, pdp->ping_count, ping_pkt_size); -#endif - t->sentpkts[seq].seq = t->seq; - t->sentpkts[seq].sent_time = t->last_send_time; - t->sentpkts[seq].flags.replied = 0; - t->sentpkts[seq].flags.timeout = 0; - t->sentpkts[seq].flags.waiting = 1; - if(t->sentpkts[seq].flags.used == 0) t->used++; - t->sentpkts[seq].flags.used = 1; - t->sentpkts[seq].flags.error = (n < 1) ? 1 : 0; - - t->seq = (t->seq + 1) % SEQ_LIMITER; /* limit seq so that consecutive missing and received pkt counting doesn't get confused when seq "overflows" */ - t->num_sent++; - } - - if(n == ping_pkt_size) { - return(0); - } - return(n); -} - -static int event_script_check(const char *path) -{ - struct stat statbuf; - - if(!path) { - if(cfg.debug >= 9) syslog(LOG_ERR, "NULL pointer event script"); - return(0); - } - - if(!*path) { - if(cfg.debug >= 9) syslog(LOG_ERR, "null string event script"); - return(0); - } - - /* check that the script is owner executable */ - if(stat(path, &statbuf) == -1) { - syslog(LOG_ERR, "failed to stat event script \"%s\" reason \"%s\"", path, strerror(errno)); - return(0); - } - - if((statbuf.st_mode & S_IXUSR) == 0) { - syslog(LOG_ERR, "event script \"%s\" is not executable by owner, please check permissions", path); - return(0); - } - - return(1); -} - -static void init_config_data(CONFIG *first, CONFIG *last, CONFIG ***ctable) -{ - int i; - CONFIG *cur; - TARGET *t = NULL; - - /* initialize config->data */ - for(cur = first, num_hosts = 0; cur; cur = cur->next, num_hosts++) { - u_int ipaddress; - - if((t = malloc(sizeof(TARGET))) == NULL) { - syslog(LOG_ERR, "main: initializing targets failed to malloc"); - exit(1); - } - memset(t, 0, sizeof(TARGET)); - - cur->data = t; - - /* protocol family independent init */ - t->seq = 0; - t->downseq = 0; - t->downseqreported = 0; - t->last_send_time.tv_sec = 0; - t->last_send_time.tv_usec = 0; - t->num_sent = 0; - t->timeout_max = 0; - t->consecutive_missing_max = 0; - t->used = 0; - - memset(t->cmsgbuf, 0, sizeof(t->cmsgbuf)); - t->cmsglen = 0; - - t->id = num_hosts; - - /* get initial connection state assumption from config */ - t->status = cur->status; - - t->sock = -1; - - if(cur->dstinfo->ai_family == AF_INET6) { - /* ipv6 init */ - if(cur->srcinfo) { - if(inet_pton(AF_INET6, cur->sourceip, &t->src6) != 1) { - syslog(LOG_ERR, "%s: %s: src6 inet_pton failed for %s", __FILE__, __FUNCTION__, cur->name); - } - - t->src_addr6.sin6_family = cur->srcinfo->ai_family; - if(inet_pton(AF_INET6, cur->sourceip, &t->src_addr6.sin6_addr) != 1) { - syslog(LOG_ERR, "%s: %s: src6 inet_pton failed for %s", __FILE__, __FUNCTION__, cur->name); - } - } - - if(inet_pton(AF_INET6, cur->checkip, &t->dst6) != 1) { - syslog(LOG_ERR, "%s: %s: dst6 inet_pton failed for %s", __FILE__, __FUNCTION__, cur->name); - } - - t->dst_addr6.sin6_family = cur->dstinfo->ai_family; - if(inet_pton(AF_INET6, cur->checkip, &t->dst_addr6.sin6_addr) != 1) { - syslog(LOG_ERR, "%s: %s: dst6 inet_pton failed for %s", __FILE__, __FUNCTION__, cur->name); - } - } else { - /* ipv4 init */ - ipaddress = inet_addr(cur->checkip); - t->dst_addr.sin_family = AF_INET; - t->dst_addr.sin_addr = *((struct in_addr *)&ipaddress); - t->dst = *((struct in_addr *)&ipaddress); - } - } - - if(((*ctable) = (CONFIG **)malloc(sizeof(CONFIG *) * num_hosts)) == NULL) { - syslog(LOG_ERR, "main: can't malloc for ctable"); - exit(1); - } - - /* create pointer table */ - for(cur = first, i = 0; cur; cur = cur->next, i++) { - (*ctable)[i] = cur; - } - -} - -static int open_arp_sock(CONFIG *cur) -{ - int ifindex = 0; - TARGET *t = (TARGET *)cur->data; - - if(t->sock != -1) return(0); - - if(cur->dstinfo->ai_family == AF_INET6) { - syslog(LOG_ERR, "%s: %s: protocol family is ipv6?", __FILE__, __FUNCTION__); - return(1); - } - - t->sock = socket(PF_PACKET, SOCK_DGRAM, 0); - if(t->sock < 0) { - syslog(LOG_ERR, "could not open socket for %s arp ping \"%s\"", cur->name, strerror(errno)); - t->sock = -1; - return(1); - } - if(fcntl(t->sock, F_SETFD, FD_CLOEXEC) == -1) { - syslog(LOG_ERR, "failed to set close on exec on socket %s reason \"%s\"", cur->name, strerror(errno)); - } - - if(cur->device && *cur->device) { - struct ifreq ifr; - - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, cur->device, IFNAMSIZ-1); - if(ioctl(t->sock, SIOCGIFINDEX, &ifr) < 0) { - syslog(LOG_ERR, "unknown iface \"%s\"", cur->device); - close(t->sock); - t->sock = -1; - return(2); - } - ifindex = ifr.ifr_ifindex; - - if(ioctl(t->sock, SIOCGIFFLAGS, (char*)&ifr)) { - syslog(LOG_ERR, "ioctl(SIOCGIFFLAGS) \"%s\"", strerror(errno)); - close(t->sock); - t->sock = -1; - return(2); - } - if(!(ifr.ifr_flags&IFF_UP)) { - syslog(LOG_ERR, "Interface \"%s\" is down", cur->device); - close(t->sock); - t->sock = -1; - return(2); - } - if(ifr.ifr_flags&(IFF_NOARP|IFF_LOOPBACK)) { - syslog(LOG_ERR, "Interface \"%s\" is not ARPable", cur->device); - close(t->sock); - t->sock = -1; - return(2); - } - } - - if(inet_aton(cur->checkip, &t->dst) != 1) { - struct hostent *hp; - hp = gethostbyname2(cur->checkip, AF_INET); - if(!hp) { - syslog(LOG_ERR, "unknown host %s\n", cur->checkip); - close(t->sock); - t->sock = -1; - return(2); - } - memcpy(&t->dst, hp->h_addr, 4); - } - - if(cur->sourceip && *cur->sourceip) - if(inet_aton(cur->sourceip, &t->src) != 1) { - syslog(LOG_ERR, "invalid source %s\n", cur->sourceip); - close(t->sock); - t->sock = -1; - return(2); - } - - if(probe_src_ip_addr(cur) != 0) { - close(t->sock); - t->sock = -1; - return(2); - } - - t->me.sll_family = AF_PACKET; - t->me.sll_ifindex = ifindex; - t->me.sll_protocol = htons(ETH_P_ARP); - if(bind(t->sock, (struct sockaddr*)&t->me, sizeof(t->me)) == -1) { - syslog(LOG_ERR, "bind \"%s\"", strerror(errno)); - close(t->sock); - t->sock = -1; - return(2); - } - - { - int alen = sizeof(t->me); - if(getsockname(t->sock, (struct sockaddr*)&t->me, (socklen_t*)&alen) == -1) { - syslog(LOG_ERR, "getsockname \"%s\"", strerror(errno)); - close(t->sock); - t->sock = -1; - return(2); - } - } - if(t->me.sll_halen == 0) { - syslog(LOG_ERR, "Interface \"%s\" is not ARPable (no ll address)", cur->device); - close(t->sock); - t->sock = -1; - return(2); - } - - t->he = t->me; - memset(t->he.sll_addr, -1, min(t->he.sll_halen, sizeof t->he.sll_addr)); - -#if 0 - printf("ARPING %s ", inet_ntoa(t->dst)); - printf("from %s %s\n", inet_ntoa(t->src), cur->device ? : ""); -#endif - - if(!t->src.s_addr) { - syslog(LOG_ERR, "no source address for %s", cur->name); - close(t->sock); - t->sock = -1; - return(2); - } - if(cur->ttl) { - int ittl = cur->ttl; - if(setsockopt(t->sock, IPPROTO_IP, IP_MULTICAST_TTL, - &cur->ttl, 1) == -1) { - syslog(LOG_ERR, "can't set multicast time-to-live \"%s\"", strerror(errno)); - close(t->sock); - t->sock = -1; - return(2); - } - if(setsockopt(t->sock, IPPROTO_IP, IP_TTL, - &ittl, sizeof(ittl)) == -1) { - syslog(LOG_ERR, "can't set unicast time-to-live \"%s\"", strerror(errno)); - close(t->sock); - t->sock = -1; - return(2); - } - } - - return(0); -} - -static int open_icmp_sock(CONFIG *cur) -{ - TARGET *t = (TARGET *)cur->data; - struct protoent *proto; - int pf = cur->dstinfo->ai_family; - - if(t->sock != -1) return(0); - - if(pf == AF_INET6) { - if((proto = getprotobyname("ipv6-icmp")) == NULL) { - syslog(LOG_ERR, "no ipv6-icmp proto found"); - return(1); - } - } else { - if((proto = getprotobyname("icmp")) == NULL) { - syslog(LOG_ERR, "no icmp proto found"); - return(1); - } - } - - t->sock = socket(pf, SOCK_RAW, proto->p_proto); - - if(t->sock < 0) { - syslog(LOG_ERR, "could not open socket for ping target \"%s\" reason \"%s\"\n", cur->name, strerror(errno)); - t->sock = -1; - return(1); - } - if(fcntl(t->sock, F_SETFD, FD_CLOEXEC) == -1) { - syslog(LOG_ERR, "failed to set close on exec on socket %s reason \"%s\"", cur->name, strerror(errno)); - } - - if(pf == AF_INET6) { - int opton = 1; - -#ifdef IPV6_RECVHOPOPTS - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_RECVHOPOPTS)"); - close(t->sock); - t->sock = -1; - return(2); - } -#else /* old adv. API */ - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_HOPOPTS, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_HOPOPTS)"); - close(t->sock); - t->sock = -1; - return(s); - } -#endif -#ifdef IPV6_RECVDSTOPTS - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_RECVDSTOPTS)"); - close(t->sock); - t->sock = -1; - return(2); - } -#else /* old adv. API */ - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_DSTOPTS, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_DSTOPTS)"); - close(t->sock); - t->sock = -1; - return(2); - } -#endif -#ifdef IPV6_RECVRTHDRDSTOPTS - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_RECVRTHDRDSTOPTS)"); - close(t->sock); - t->sock = -1; - return(2); - } -#endif -#ifdef IPV6_RECVRTHDR - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_RECVRTHDR)"); - close(t->sock); - t->sock = -1; - return(2); - } -#else /* old adv. API */ - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_RTHDR, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_RTHDR)"); - close(t->sock); - t->sock = -1; - return(2); - } -#endif -#ifndef USE_SIN6_SCOPE_ID -#ifdef IPV6_RECVPKTINFO - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_RECVPKTINFO)"); - close(t->sock); - t->sock = -1; - return(2); - } -#else /* old adv. API */ - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_PKTINFO, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_PKTINFO)"); - close(t->sock); - t->sock = -1; - return(2); - } -#endif -#endif /* USE_SIN6_SCOPE_ID */ -#ifdef IPV6_RECVHOPLIMIT - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_RECVHOPLIMIT)"); - close(t->sock); - t->sock = -1; - return(2); - } -#else /* old adv. API */ - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_HOPLIMIT, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(IPV6_HOPLIMIT)"); - close(t->sock); - t->sock = -1; - return(2); - } -#endif -#ifdef IPV6_CHECKSUM -#ifndef SOL_RAW -#define SOL_RAW IPPROTO_IPV6 -#endif - opton = 2; - - if(setsockopt(t->sock, SOL_RAW, IPV6_CHECKSUM, &opton, - sizeof(opton))) { - syslog(LOG_ERR, "setsockopt(SOL_RAW,IPV6_CHECKSUM)"); - close(t->sock); - t->sock = -1; - return(2); - } -#endif - } - - if(pf == AF_INET6) { - int hold = 1; - - ICMP6_FILTER_SETBLOCKALL(&t->filter); - - if (setsockopt(t->sock, SOL_IPV6, IPV6_RECVERR, (char *)&hold, sizeof(hold))) { - syslog(LOG_INFO, "WARNING: your kernel is veeery old. No problems."); - - ICMP6_FILTER_SETPASS(ICMP6_DST_UNREACH, &t->filter); - ICMP6_FILTER_SETPASS(ICMP6_PACKET_TOO_BIG, &t->filter); - ICMP6_FILTER_SETPASS(ICMP6_TIME_EXCEEDED, &t->filter); - ICMP6_FILTER_SETPASS(ICMP6_PARAM_PROB, &t->filter); - } - - ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &t->filter); - - if(setsockopt(t->sock, IPPROTO_ICMPV6, ICMP6_FILTER, &t->filter, sizeof(struct icmp6_filter)) < 0) { - syslog(LOG_ERR, "setsockopt(ICMP6_FILTER)"); - return(2); - } - } - - if(cur->ttl) { - if(pf == AF_INET6) { - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, - &cur->ttl, sizeof(cur->ttl)) == -1) { - syslog(LOG_ERR, "can't set multicast hop limit \"%s\"", strerror(errno)); - close(t->sock); - t->sock = -1; - return(2); - } - if(setsockopt(t->sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, - &cur->ttl, sizeof(cur->ttl)) == -1) { - syslog(LOG_ERR, "can't set unicast hop limit \"%s\"", strerror(errno)); - close(t->sock); - t->sock = -1; - return(2); - } - } else if(pf == AF_INET) { /* AF_INET */ - int ittl = cur->ttl; - if(setsockopt(t->sock, IPPROTO_IP, IP_MULTICAST_TTL, - &cur->ttl, 1) == -1) { - syslog(LOG_ERR, "can't set multicast time-to-live \"%s\"", strerror(errno)); - close(t->sock); - t->sock = -1; - return(2); - } - if(setsockopt(t->sock, IPPROTO_IP, IP_TTL, - &ittl, sizeof(ittl)) == -1) { - syslog(LOG_ERR, "can't set unicast time-to-live \"%s\"", strerror(errno)); - close(t->sock); - t->sock = -1; - return(2); - } - } - } - - if(pf == AF_INET && cur->device && *cur->device) { - if(setsockopt(t->sock, SOL_SOCKET, SO_BINDTODEVICE, cur->device, strlen(cur->device) + 1) == -1) { - syslog(LOG_INFO, "failed to bind to ping interface device \"%s\", \"%s\"", cur->device, strerror(errno)); - close(t->sock); - t->sock = -1; - return(2); - } - } - -#if defined(DEBUG) - if(cfg.debug >= 9) syslog(LOG_INFO, "%s: %s: probing for src ip for %s", __FILE__, __FUNCTION__, cur->name); -#endif - if(probe_src_ip_addr(cur) != 0) { - close(t->sock); - t->sock = -1; - return(2); - } -#if defined(DEBUG) - if(cfg.debug >= 9) syslog(LOG_INFO, "%s: %s: probing for src ip for %s done", __FILE__, __FUNCTION__, cur->name); -#endif - if(cur->sourceip && *cur->sourceip) { - if(cur->srcinfo->ai_family == AF_INET) { - struct sockaddr_in addr; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr(cur->sourceip); - - if(bind(t->sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) { - syslog(LOG_ERR, "ping can't bind \"%s\"", strerror(errno)); - return(1); - } - } else { - struct sockaddr_in6 addr; -#if defined(DEBUG) - if(cfg.debug >= 9) syslog(LOG_INFO, "%s: %s: setting v6 src addr", __FILE__, __FUNCTION__); -#endif - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - if(inet_pton(AF_INET6, cur->sourceip, &addr.sin6_addr) != 1) { - syslog(LOG_ERR, "ping6 failed to convert connection %s address %s", cur->name, cur->sourceip); - return(1); - } - if(bind(t->sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) { - syslog(LOG_ERR, "ping6 can't bind %s to %s, \"%s\"", cur->name, cur->sourceip, strerror(errno)); - return(1); - } -#if defined(DEBUG) - if(cfg.debug >= 9) syslog(LOG_INFO, "%s: %s: setting v6 src addr done", __FILE__, __FUNCTION__); -#endif - } - } - - if(pf == AF_INET6 && cur->device && *cur->device) { - struct ifreq ifr; - struct cmsghdr *cmsg; - struct in6_pktinfo *ipi; - - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, cur->device, IFNAMSIZ-1); - if(ioctl(t->sock, SIOCGIFINDEX, &ifr) < 0) { - syslog(LOG_ERR, "ping6 unknown iface %s", cur->device); - return(2); - } - - memset(&t->cmsgbuf, 0, sizeof(t->cmsgbuf)); - t->cmsglen = 0; - - cmsg = (struct cmsghdr *)t->cmsgbuf; - t->cmsglen += CMSG_SPACE(sizeof(*ipi)); - cmsg->cmsg_len = CMSG_LEN(sizeof(*ipi)); - cmsg->cmsg_level = SOL_IPV6; - cmsg->cmsg_type = IPV6_PKTINFO; - - ipi = (struct in6_pktinfo *)CMSG_DATA(cmsg); - memset(ipi, 0, sizeof(*ipi)); - ipi->ipi6_ifindex = ifr.ifr_ifindex; - } - - return(0); -} - -static int probe_src_ip_addr(CONFIG *cur) -{ /* probe for src ip address */ - TARGET *t = (TARGET *)cur->data; - int probe_fd; - int pf = cur->dstinfo->ai_family; - - probe_fd = socket(pf, SOCK_DGRAM, 0); - - if(probe_fd < 0) { - syslog(LOG_ERR, "ping probe socket for %s failed \"%s\"", cur->name, strerror(errno)); - return(2); - } - if(fcntl(t->sock, F_SETFD, FD_CLOEXEC) == -1) { - syslog(LOG_ERR, "ping probe failed to set close on exec on probe socket for %s reason \"%s\"", cur->name, strerror(errno)); - } - - if(cur->device && *cur->device) { - if(setsockopt(probe_fd, SOL_SOCKET, SO_BINDTODEVICE, cur->device, strlen(cur->device) + 1) == -1) - syslog(LOG_INFO, "WARNING: ping probe interface \"%s\" is ignored for %s reason \"%s\"", cur->device, cur->name, strerror(errno)); - } - - if(pf == AF_INET) { - struct sockaddr_in saddr; - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - if(t->src.s_addr) { - saddr.sin_addr = t->src; - if(bind(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { - syslog(LOG_ERR, "ping probe bind failed for %s \"%s\"", cur->name, strerror(errno)); - close(probe_fd); - /* earlier probed src addr is not usable, wipe it */ - memset(&t->src, 0, sizeof(t->src)); - return(2); - } - } - else { - int on = 1; - int alen = sizeof(saddr); - - saddr.sin_port = htons(1025); - saddr.sin_addr = t->dst; - - if(setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char*)&on, sizeof(on)) == -1) - syslog(LOG_INFO, "WARNING: ping probe setsockopt(SO_DONTROUTE) \"%s\"", strerror(errno)); - if(connect(probe_fd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) { - syslog(LOG_ERR, "ping probe connect for %s failed \"%s\"", cur->name, strerror(errno)); - close(probe_fd); - return(2); - } - if(getsockname(probe_fd, (struct sockaddr*)&saddr, (socklen_t*)&alen) == -1) { - syslog(LOG_ERR, "ping probe getsockname for %s failed \"%s\"", cur->name, strerror(errno)); - close(probe_fd); - return(2); - } - t->src = saddr.sin_addr; - } - } else if (pf == AF_INET6) { /* not AF_INET */ - struct sockaddr_in6 saddr; - unsigned char nulladdr[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - - memset(&saddr, 0, sizeof(saddr)); - saddr.sin6_family = AF_INET6; - if(memcmp(&t->src6, nulladdr, sizeof(t->src6)) != 0) { /* is not null addr */ - memcpy(&saddr.sin6_addr, &t->src6, sizeof(t->src6)); - if(bind(probe_fd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) { - syslog(LOG_ERR, "ping6 probe bind failed for %s \"%s\"", cur->name,strerror(errno)); - close(probe_fd); - /* earlier probed src addr is not usable, wipe it */ - memset(&t->src6, 0, sizeof(t->src6)); - return(2); - } - } else { /* is null addr */ - socklen_t alen = sizeof(saddr); - - saddr.sin6_port = htons(1025); - saddr.sin6_family = cur->dstinfo->ai_family; - memcpy(&saddr.sin6_addr, &t->dst6, sizeof(t->dst6)); -#if 0 - if(setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, (char *)&on, sizeof(on)) == -1) - syslog(LOG_INFO, "WARNING: ping6 probe setsockopt(SO_DONTROUTE) for %s \"%s\"", cur->name, strerror(errno)); -#endif - if(connect(probe_fd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1) { - syslog(LOG_ERR, "ping6 probe connect for %s failed \"%s\"", cur->name, strerror(errno)); - close(probe_fd); - return(2); - } - if(getsockname(probe_fd, (struct sockaddr *)&saddr, &alen) == -1) { - syslog(LOG_ERR, "ping6 probe getsockname for %s failed \"%s\"", cur->name, strerror(errno)); - close(probe_fd); - return(2); - } - memcpy(&t->src6, &saddr.sin6_addr, sizeof(saddr.sin6_addr)); - } - } /* if AF_INET */ - - close(probe_fd); - - return(0); -} - -#if defined(DEBUG) -static void dump_pkt(const void *buf, size_t len) -{ - int i; - unsigned char *s; - char obuf[BUFSIZ]; - char *pad; - - memset(obuf, 0, BUFSIZ); - - s = (unsigned char *)buf; - pad = ""; - for(i = 0; i < len && i < BUFSIZ; i++) { - snprintf(obuf + strlen(obuf), BUFSIZ, "%s%02x", pad, s[i]); - pad = " "; - } - - syslog(LOG_INFO, "%s: %s: hexdump %s", __FILE__, __FUNCTION__, obuf); - - memset(obuf, 0, BUFSIZ); - - s = (unsigned char *)buf; - pad = ""; - for(i = 0; i < len && i < BUFSIZ; i++) { - snprintf(obuf + strlen(obuf), BUFSIZ, "%s%03d", pad, s[i]); - pad = " "; - } - - syslog(LOG_INFO, "%s: %s: decdump %s", __FILE__, __FUNCTION__, obuf); -} -#endif - -/* EOF */ |
