diff options
author | Jaymin Patel <jem.patel@gmail.com> | 2022-07-06 15:15:59 +0530 |
---|---|---|
committer | Jaymin Patel <jem.patel@gmail.com> | 2022-07-12 12:27:05 +0530 |
commit | e4e3206f3283e673bfac717e00332deb8dd2c079 (patch) | |
tree | d3e9a2ed5670eafcf89e1fbad12c4774741325c4 /net/apinger/patches | |
parent | 797945dfaa0e7de8d6b0ada472bda63bb27f0cdc (diff) |
apinger: improve uci and procd support
- convert apinger into procd instances
- generate instance specific apinger.conf from uci
- hotplug handling for apinger alarms
- restart apinger interface instance on ifup action of interface
- don't exit on packet count mismatch, allows to use apinger as monitor
for multiple targets handling
- add srcip option to target configuration, allows specifying source ip
used to monitor target
- allow creating status file in script parseable format
Patches are ported against latest version of apinger and referenced from
https://git.pld-linux.org/?p=packages/apinger.git;a=summary
Signed-off-by: Jaymin Patel <jem.patel@gmail.com>
Diffstat (limited to 'net/apinger/patches')
-rw-r--r-- | net/apinger/patches/030-apinger-no_exit.patch | 34 | ||||
-rw-r--r-- | net/apinger/patches/040-srcip.patch | 564 | ||||
-rw-r--r-- | net/apinger/patches/050-statusformat.patch | 126 |
3 files changed, 724 insertions, 0 deletions
diff --git a/net/apinger/patches/030-apinger-no_exit.patch b/net/apinger/patches/030-apinger-no_exit.patch new file mode 100644 index 000000000..d058b3d12 --- /dev/null +++ b/net/apinger/patches/030-apinger-no_exit.patch @@ -0,0 +1,34 @@ +--- a/src/apinger.c ++++ b/src/apinger.c +@@ -786,7 +786,6 @@ struct alarm_cfg *a; + time_t tm; + int i,qp,really_lost; + char *buf1,*buf2; +-int err=0; + + if (config->status_file==NULL) return; + +@@ -849,12 +848,10 @@ int err=0; + } + } + buf2[i]=0; +- fprintf(f,"Received packets buffer: %s %s\n",buf2,buf1); + if (t->recently_lost!=really_lost){ +- fprintf(f," lost packet count mismatch (%i!=%i)!\n",t->recently_lost,really_lost); +- logit("%s: Lost packet count mismatch (%i!=%i)!",t->name,t->recently_lost,really_lost); +- logit("%s: Received packets buffer: %s %s\n",t->name,buf2,buf1); +- err=1; ++ logit("Target \"%s\": Lost packet count mismatch (%i(recently_lost) != %i(really_lost))!",t->name,t->recently_lost,really_lost); ++ logit("Target \"%s\": Received packets buffer: %s %s\n",t->name,buf2,buf1); ++ t->recently_lost = really_lost = 0; + } + free(buf1); + free(buf2); +@@ -862,7 +859,6 @@ int err=0; + fprintf(f,"\n"); + } + fclose(f); +- if (err) abort(); + } + + #ifdef FORKED_RECEIVER diff --git a/net/apinger/patches/040-srcip.patch b/net/apinger/patches/040-srcip.patch new file mode 100644 index 000000000..461201e6d --- /dev/null +++ b/net/apinger/patches/040-srcip.patch @@ -0,0 +1,564 @@ +--- a/src/apinger.c ++++ b/src/apinger.c +@@ -161,6 +161,9 @@ time_t tim; + case 't': + values[n]=t->name; + break; ++ case 'i': ++ values[n]=t->config->srcip; ++ break; + case 'T': + values[n]=t->description; + break; +@@ -276,6 +279,7 @@ time_t tm; + else + fprintf(f,"alarm canceled: %s\n",a->name); + fprintf(f,"Target: %s\n",t->name); ++ fprintf(f,"Source: %s\n",t->config->srcip); + fprintf(f,"Description: %s\n",t->description); + fprintf(f,"Probes sent: %i\n",t->last_sent+1); + fprintf(f,"Replies received: %i\n",t->received); +@@ -645,7 +649,7 @@ void configure_targets(void){ + struct target *t,*pt,*nt; + struct target_cfg *tc; + struct active_alarm_list *al,*nal; +-union addr addr; ++union addr addr, srcaddr; + int r; + int l; + +@@ -665,6 +669,8 @@ int l; + nal=al->next; + free(al); + } ++ if (t->socket) ++ close(t->socket); + free(t->queue); + free(t->rbuf); + free(t->name); +@@ -681,20 +687,16 @@ int l; + break; + if (t==NULL) { /* new target */ + memset(&addr,0,sizeof(addr)); ++ logit("Checking target IP %s", tc->srcip); + r=inet_pton(AF_INET,tc->name,&addr.addr4.sin_addr); + if (r){ +- if (icmp_sock<0){ +- logit("Sorry, IPv4 is not available\n"); +- logit("Ignoring target %s\n",tc->name); +- continue; +- } + addr.addr.sa_family=AF_INET; + }else{ + #ifdef HAVE_IPV6 + r=inet_pton(AF_INET6,tc->name,&addr.addr6.sin6_addr); + if (r==0){ + #endif +- logit("Bad host address: %s\n",tc->name); ++ logit("Bad target IP address: %s\n",tc->name); + logit("Ignoring target %s\n",tc->name); + continue; + #ifdef HAVE_IPV6 +@@ -707,12 +709,38 @@ int l; + addr.addr.sa_family=AF_INET6; + #endif + } ++ memset(&srcaddr,0,sizeof(srcaddr)); ++ logit("Checking source IP %s", tc->srcip); ++ r=inet_pton(AF_INET,tc->srcip,&srcaddr.addr4.sin_addr); ++ if (r){ ++ srcaddr.addr.sa_family=AF_INET; ++ }else{ ++#ifdef HAVE_IPV6 ++ r=inet_pton(AF_INET6,tc->srcip,&srcaddr.addr6.sin6_addr); ++ if (r==0){ ++#endif ++ logit("Bad source IP address %s for target %s\n", tc->srcip, tc->name); ++ logit("Ignoring target %s\n",tc->name); ++ continue; ++#ifdef HAVE_IPV6 ++ } ++ if (icmp6_sock<0){ ++ logit("Sorry, IPv6 is not available\n"); ++ logit("Ignoring target %s\n",tc->name); ++ continue; ++ } ++ srcaddr.addr.sa_family=AF_INET6; ++#endif ++ } + t=NEW(struct target,1); + memset(t,0,sizeof(struct target)); + t->name=strdup(tc->name); + t->description=strdup(tc->description); + t->addr=addr; ++ t->ifaddr=srcaddr; + t->next=targets; ++ if(t->addr.addr.sa_family==AF_INET) make_icmp_socket(t); ++ if(t->addr.addr.sa_family==AF_INET6) make_icmp6_socket(t); + targets=t; + } + t->config=tc; +@@ -752,6 +780,8 @@ struct active_alarm_list *al,*nal; + nal=al->next; + free(al); + } ++ if (t->socket) ++ close(t->socket); + free(t->queue); + free(t->rbuf); + free(t->name); +@@ -799,6 +829,7 @@ char *buf1,*buf2; + fprintf(f,"%s\n",ctime(&tm)); + for(t=targets;t;t=t->next){ + fprintf(f,"Target: %s\n",t->name); ++ fprintf(f,"Source: %s\n",t->config->srcip); + fprintf(f,"Description: %s\n",t->description); + fprintf(f,"Last reply received: #%i %s",t->last_received, + ctime(&t->last_received_tv.tv_sec)); +@@ -909,7 +940,7 @@ int i; + void main_loop(void){ + struct target *t; + struct timeval cur_time,next_status={0,0},tv,next_report={0,0},next_rrd_update={0,0}; +-struct pollfd pfd[2]; ++struct pollfd pfd[1024]; + int timeout; + int npfd=0; + int i; +@@ -946,18 +977,8 @@ struct piped_info pi; + pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL; + pfd[npfd].revents=0; + pfd[npfd++].fd=recv_pipe[0]; +-#else +- if (icmp_sock){ +- pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL; +- pfd[npfd].revents=0; +- pfd[npfd++].fd=icmp_sock; +- } +- if (icmp6_sock){ +- pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL; +- pfd[npfd++].fd=icmp6_sock; +- pfd[npfd].revents=0; +- } + #endif ++ memset(&pfd, '\0', sizeof pfd); + if (config->status_interval){ + gettimeofday(&cur_time,NULL); + tv.tv_sec=config->status_interval/1000; +@@ -965,10 +986,16 @@ struct piped_info pi; + timeradd(&cur_time,&tv,&next_status); + } + while(!interrupted_by){ ++ npfd = 0; + gettimeofday(&cur_time,NULL); + if ( !timercmp(&next_probe,&cur_time,>) ) + timerclear(&next_probe); + for(t=targets;t;t=t->next){ ++ if (t->socket){ ++ pfd[npfd].events=POLLIN|POLLERR|POLLHUP|POLLNVAL; ++ pfd[npfd].revents=0; ++ pfd[npfd++].fd=t->socket; ++ } + for(al=t->config->alarms;al;al=nal){ + a=al->alarm; + nal=al->next; +@@ -1051,8 +1078,20 @@ struct piped_info pi; + analyze_reply(pi.recv_timestamp,pi.icmp_seq,&pi.ti); + } + #else +- if (pfd[i].fd==icmp_sock) recv_icmp(); +- else if (pfd[i].fd==icmp6_sock) recv_icmp6(); ++ for(t=targets;t;t=t->next){ ++ if (t->addr.addr.sa_family==AF_INET) { ++ if (t->socket == pfd[i].fd) { ++ recv_icmp(t); ++ break; ++ } ++ } ++ if (t->addr.addr.sa_family==AF_INET6) { ++ if (t->socket == pfd[i].fd) { ++ recv_icmp6(t); ++ break; ++ } ++ } ++ } + #endif + pfd[i].revents=0; + } +--- a/src/apinger.conf ++++ b/src/apinger.conf +@@ -47,6 +47,7 @@ alarm default { + + ## Following "macros" may be used in options below: + ## %t - target name (address) ++ ## %i - source name (address) + ## %T - target description + ## %a - alarm name + ## %A - alarm type ("down"/"loss"/"delay") +--- a/src/apinger.h ++++ b/src/apinger.h +@@ -46,6 +46,8 @@ + #endif + #include "conf.h" + ++#include <ifaddrs.h> ++ + union addr { + struct sockaddr addr; + struct sockaddr_in addr4; +@@ -70,6 +72,7 @@ struct target { + char *queue; /* + contains info about recently sent packets + "1" means it was received */ ++ int socket; + int last_sent; /* sequence number of the last ping sent */ + int last_received; /* sequence number of the last ping received */ + struct timeval last_received_tv; /* timestamp of the last ping received */ +@@ -89,6 +92,7 @@ struct target { + struct target_cfg *config; + + struct target *next; ++ union addr ifaddr; /* iface address */ + }; + + #define AVG_DELAY_KNOWN(t) (t->upsent >= t->config->avg_delay_samples) +@@ -118,16 +122,16 @@ extern char *config_file; + + extern int icmp_sock; + extern int icmp6_sock; +-extern int ident; ++extern uint16_t ident; + + extern struct timeval next_probe; + +-int make_icmp_socket(void); +-void recv_icmp(void); ++int make_icmp_socket(struct target *t); ++void recv_icmp(struct target *t); + void send_icmp_probe(struct target *t,int seq); + +-int make_icmp6_socket(void); +-void recv_icmp6(void); ++int make_icmp6_socket(struct target *t); ++void recv_icmp6(struct target *t); + void send_icmp6_probe(struct target *t,int seq); + + #ifdef FORKED_RECEIVER +--- a/src/cfgparser1.y ++++ b/src/cfgparser1.y +@@ -96,6 +96,7 @@ struct target_cfg *cur_target; + %token DELAY_HIGH + + %token DESCRIPTION ++%token SRCIP + %token ALARMS + %token INTERVAL + %token AVG_DELAY_SAMPLES +@@ -247,6 +248,8 @@ target: TARGET getdeftarget DEFAULT '{' + targetcfg: /* */ + | DESCRIPTION string + { cur_target->description=$2; } ++ | SRCIP string ++ { cur_target->srcip = $2; } + | ALARMS alarmlist + { cur_target->alarms=$2; } + | ALARMS OVERRIDE alarmlist +--- a/src/cfgparser2.l ++++ b/src/cfgparser2.l +@@ -81,6 +81,7 @@ delay { LOC; LOCINC; return DELAY; } + delay_high { LOC; LOCINC; return DELAY_HIGH; } + delay_low { LOC; LOCINC; return DELAY_LOW; } + description { LOC; LOCINC; return DESCRIPTION; } ++srcip { LOC; LOCINC; return SRCIP; } + down { LOC; LOCINC; return DOWN; } + false { LOC; LOCINC; return FALSE; } + file { LOC; LOCINC; return FILE_; } +--- a/src/conf.c ++++ b/src/conf.c +@@ -174,6 +174,14 @@ int ret; + } + } + for(t=cur_config.targets;t;t=t->next){ ++ if (t->name==NULL || strlen(t->name)==0){ ++ logit("Target name can't be empty."); ++ return 1; ++ } ++ else if (t->srcip==NULL){ ++ logit("No source IP defined for target \"%s\".", t->name); ++ return 1; ++ } + if (t->description==NULL) + t->description=cur_config.target_defaults.description; + if (t->interval<=0) +--- a/src/conf.h ++++ b/src/conf.h +@@ -71,6 +71,7 @@ struct alarm_list { + struct target_cfg { + char *name; + char *description; ++ char *srcip; + int interval; + int avg_delay_samples; + int avg_loss_delay_samples; +--- a/src/icmp6.c ++++ b/src/icmp6.c +@@ -112,14 +112,14 @@ int ret; + memcpy(p+1,&ti,sizeof(ti)); + size=sizeof(*p)+sizeof(ti); + +- ret=sendto(icmp6_sock,p,size,MSG_DONTWAIT, ++ ret=sendto(t->socket,p,size,MSG_DONTWAIT, + (struct sockaddr *)&t->addr.addr6,sizeof(t->addr.addr6)); + if (ret<0){ + if (config->debug) myperror("sendto"); + } + } + +-void recv_icmp6(void){ ++void recv_icmp6(struct target *t){ + int len,icmplen,datalen; + char buf[1024]; + char abuf[100]; +@@ -133,6 +133,7 @@ char ans_data[4096]; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *c; ++reloophack6: + + iov.iov_base=buf; + iov.iov_len=1000; +@@ -142,12 +143,13 @@ struct cmsghdr *c; + msg.msg_iovlen=1; + msg.msg_control=ans_data; + msg.msg_controllen=sizeof(ans_data); +- len=recvmsg(icmp6_sock, &msg, MSG_DONTWAIT); ++ len=recvmsg(t->socket, &msg, MSG_DONTWAIT); + #else + socklen_t sl; ++reloophack6: + + sl=sizeof(from); +- len=recvfrom(icmp6_sock,buf,1024,0,(struct sockaddr *)&from,&sl); ++ len=recvfrom(t->socket,buf,1024,0,(struct sockaddr *)&from,&sl); + #endif + if (len<0){ + if (errno==EAGAIN) return; +@@ -169,7 +171,7 @@ socklen_t sl; + #endif + if (time_recvp==NULL){ + #ifdef SIOCGSTAMP +- if (!ioctl(icmp6_sock, SIOCGSTAMP, &time_recv)){ ++ if (!ioctl(t->socket, SIOCGSTAMP, &time_recv)){ + debug("Got timestamp from ioctl()"); + }else + #endif +@@ -182,8 +184,11 @@ socklen_t sl; + icmplen=len; + icmp=(struct icmp6_hdr *)buf; + if (icmp->icmp6_type != ICMP6_ECHO_REPLY) return; +- if (icmp->icmp6_id != ident) return; +- ++ if (icmp->icmp6_id != ident){ ++ debug("Alien echo-reply received from xxx. Expected %i, received %i", ident, icmp->icmp6_id); ++ goto reloophack6; ++ return; ++ } + name=inet_ntop(AF_INET6,&from.sin6_addr,abuf,100); + debug("Ping reply from %s",name); + datalen=icmplen-sizeof(*icmp); +@@ -199,33 +204,36 @@ socklen_t sl; + } + + +-int make_icmp6_socket(void){ ++int make_icmp6_socket(struct target *t){ + int opt; + +- icmp6_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); +- if (icmp6_sock<0) ++ t->socket = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); ++ if (t->socket <0) + myperror("socket"); + else { + opt=2; + #if defined(SOL_RAW) && defined(IPV6_CHECKSUM) +- if (setsockopt(icmp6_sock, SOL_RAW, IPV6_CHECKSUM, &opt, sizeof(int))) ++ if (setsockopt(t->socket, SOL_RAW, IPV6_CHECKSUM, &opt, sizeof(int))) + myperror("setsockopt(IPV6_CHECKSUM)"); + #endif + #ifdef SO_TIMESTAMP + opt=1; +- if (setsockopt(icmp6_sock, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) ++ if (setsockopt(t->socket, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt))) + myperror("setsockopt(SO_TIMESTAMP)"); + #endif + /*install_filter6();*/ + } +- return icmp6_sock; ++ if (bind(t->socket, (struct sockaddr *)&t->ifaddr.addr6, sizeof(t->ifaddr.addr6)) < 0) ++ myperror("bind socket"); ++ ++ return t->socket; + } + + #else /*HAVE_IPV6*/ + #include "apinger.h" + +-int make_icmp6_socket(void){ return -1; } +-void recv_icmp6(void){} ++int make_icmp6_socket(struct target *t){ return -1; } ++void recv_icmp6(struct target *t){} + void send_icmp6_probe(struct target *t,int seq){} + + #endif /*HAVE_IPV6*/ +--- a/src/icmp.c ++++ b/src/icmp.c +@@ -150,14 +150,14 @@ int ret; + size=sizeof(*p)+sizeof(ti); + + p->icmp_cksum = in_cksum((u_short *)p,size,0); +- ret=sendto(icmp_sock,p,size,MSG_DONTWAIT, ++ ret=sendto(t->socket,p,size,MSG_DONTWAIT, + (struct sockaddr *)&t->addr.addr4,sizeof(t->addr.addr4)); + if (ret<0){ + if (config->debug) myperror("sendto"); + } + } + +-void recv_icmp(void){ ++void recv_icmp(struct target *t){ + int len,hlen,icmplen,datalen; + char buf[1024]; + struct sockaddr_in from; +@@ -170,6 +170,7 @@ char ans_data[4096]; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *c; ++reloophack: + + iov.iov_base=buf; + iov.iov_len=1000; +@@ -179,12 +180,13 @@ struct cmsghdr *c; + msg.msg_iovlen=1; + msg.msg_control=ans_data; + msg.msg_controllen=sizeof(ans_data); +- len=recvmsg(icmp_sock, &msg, MSG_DONTWAIT); ++ len=recvmsg(t->socket, &msg, MSG_DONTWAIT); + #else + socklen_t sl; ++reloophack: + + sl=sizeof(from); +- len=recvfrom(icmp_sock,buf,1024,MSG_DONTWAIT,(struct sockaddr *)&from,&sl); ++ len=recvfrom(t->socket,buf,1024,MSG_DONTWAIT,(struct sockaddr *)&from,&sl); + #endif + if (len<0){ + if (errno==EAGAIN) return; +@@ -196,7 +198,7 @@ socklen_t sl; + debug("checking CMSG..."); + for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) { + debug("CMSG level: %i type: %i",c->cmsg_level,c->cmsg_type); +- if (c->cmsg_level != SOL_SOCKET || c->cmsg_type != SO_TIMESTAMP) ++ if (c->cmsg_level != SOL_SOCKET || c->cmsg_type != SCM_TIMESTAMP) + continue; + if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval))) + continue; +@@ -206,7 +208,7 @@ socklen_t sl; + #endif + if (time_recvp==NULL){ + #ifdef SIOCGSTAMP +- if (!ioctl(icmp_sock, SIOCGSTAMP, &time_recv)){ ++ if (!ioctl(t->socket, SIOCGSTAMP, &time_recv)){ + debug("Got timestampt from ioctl()"); + }else + #endif +@@ -226,7 +228,8 @@ socklen_t sl; + return; + } + if (icmp->icmp_id != ident){ +- debug("Alien echo-reply received"); ++ debug("Alien echo-reply received from %s. Expected %i, received %i",inet_ntoa(from.sin_addr), ident, icmp->icmp_id); ++ goto reloophack; + return; + } + debug("Ping reply from %s",inet_ntoa(from.sin_addr)); +@@ -242,19 +245,23 @@ socklen_t sl; + #endif + } + +-int make_icmp_socket(void){ ++int make_icmp_socket(struct target *t){ + int on; + +- icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); +- if (icmp_sock<0) ++ t->socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); ++ if (t->socket < 0) + myperror("socket"); + #ifdef SO_TIMESTAMP + else{ + on=1; +- if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) ++ if (setsockopt(t->socket, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) + myperror("setsockopt(SO_TIMESTAMP)"); + } + #endif +- return icmp_sock; ++ ++ if (bind(t->socket, (struct sockaddr *)&t->ifaddr.addr4, sizeof(t->ifaddr.addr4)) < 0) ++ myperror("bind socket"); ++ ++ return t->socket; + } + +--- a/src/main.c ++++ b/src/main.c +@@ -71,6 +71,7 @@ struct config default_config={ + { /* target defaults */ + "default", /* name */ + "", /* description */ ++ "", /* interface */ + 1000, /* interval */ + 20, /* avg_delay_samples */ + 5, /* avg_loss_delay_samples */ +@@ -95,7 +96,7 @@ char *config_file=CONFIG; + + int icmp_sock; + int icmp6_sock; +-int ident; ++uint16_t ident; + + struct timeval next_probe={0,0}; + +@@ -216,12 +217,6 @@ char *graph_location="/apinger/"; + } + } + +- make_icmp_socket(); +- make_icmp6_socket(); +- if (icmp6_sock<0 && icmp_sock<0){ +- return 1; +- } +- + pw=getpwnam(config->user); + if (!pw) { + debug("getpwnam(\"%s\") failed.",config->user); +@@ -276,7 +271,7 @@ char *graph_location="/apinger/"; + return 1; + } + +- ident=getpid(); ++ ident=getpid() & 0xFFFF; + signal(SIGTERM,signal_handler); + signal(SIGINT,signal_handler); + signal(SIGHUP,signal_handler); +@@ -285,9 +280,8 @@ char *graph_location="/apinger/"; + #ifdef FORKED_RECEIVER + signal(SIGCHLD,sigchld_handler); + #endif ++ logit("Starting Alarm Pinger, apinger(%i)", ident); + main_loop(); +- if (icmp_sock>=0) close(icmp_sock); +- if (icmp6_sock>=0) close(icmp6_sock); + + logit("Exiting on signal %i.",interrupted_by); + diff --git a/net/apinger/patches/050-statusformat.patch b/net/apinger/patches/050-statusformat.patch new file mode 100644 index 000000000..dee865b8a --- /dev/null +++ b/net/apinger/patches/050-statusformat.patch @@ -0,0 +1,126 @@ +--- a/src/apinger.c ++++ b/src/apinger.c +@@ -826,26 +826,49 @@ char *buf1,*buf2; + return; + } + tm=time(NULL); +- fprintf(f,"%s\n",ctime(&tm)); ++ if(!config->status_format) fprintf(f,"%s\n",ctime(&tm)); + for(t=targets;t;t=t->next){ +- fprintf(f,"Target: %s\n",t->name); +- fprintf(f,"Source: %s\n",t->config->srcip); +- fprintf(f,"Description: %s\n",t->description); +- fprintf(f,"Last reply received: #%i %s",t->last_received, +- ctime(&t->last_received_tv.tv_sec)); +- fprintf(f,"Average delay: %0.3fms\n",AVG_DELAY(t)); ++ if(config->status_format){ ++ fprintf(f,"%s|%s|%s|%i|%i|%u|",t->name, t->config->srcip, t->description, t->last_sent+1, ++ t->received, t->last_received_tv.tv_sec); ++ fprintf(f,"%0.3fms|", AVG_DELAY(t)); ++ } ++ else{ ++ fprintf(f,"Target: %s\n",t->name); ++ fprintf(f,"Source: %s\n",t->config->srcip); ++ fprintf(f,"Description: %s\n",t->description); ++ fprintf(f,"Last reply received: #%i %s",t->last_received, ++ ctime(&t->last_received_tv.tv_sec)); ++ fprintf(f,"Average delay: %0.3fms\n",AVG_DELAY(t)); ++ } + if (AVG_LOSS_KNOWN(t)){ +- fprintf(f,"Average packet loss: %0.1f%%\n",AVG_LOSS(t)); ++ if(config->status_format){ ++ fprintf(f,"%0.1f%%",AVG_LOSS(t)); ++ } ++ else{ ++ fprintf(f,"Average packet loss: %0.1f%%\n",AVG_LOSS(t)); ++ } ++ } ++ if(config->status_format){ ++ fprintf(f, "|"); ++ } ++ else{ ++ fprintf(f,"Active alarms: "); + } +- fprintf(f,"Active alarms:"); + if (t->active_alarms){ + for(al=t->active_alarms;al;al=al->next){ + a=al->alarm; +- fprintf(f," \"%s\"",a->name); ++ if(config->status_format){ ++ fprintf(f,"%s",a->name); ++ } ++ else{ ++ fprintf(f," \"%s\"",a->name); ++ } + } +- fprintf(f,"\n"); ++ if(!config->status_format) fprintf(f,"\n"); + } +- else fprintf(f," None\n"); ++ else fprintf(f,"none"); ++ if(!config->status_format) fprintf(f,"\n"); + + buf1=NEW(char,t->config->avg_loss_delay_samples+1); + buf2=NEW(char,t->config->avg_loss_samples+1); +--- a/src/apinger.conf ++++ b/src/apinger.conf +@@ -29,6 +29,10 @@ group "nogroup" + # ## Interval between file updates + # ## when 0 or not set, file is written only when SIGUSR1 is received + # interval 5m ++# ++# ## Create status file in script parseable format (on) or human ++# ## readable format (off) ++# scriptformat off + #} + + ######################################## +--- a/src/cfgparser1.y ++++ b/src/cfgparser1.y +@@ -104,6 +104,7 @@ struct target_cfg *cur_target; + %token AVG_LOSS_DELAY_SAMPLES + + %token FILE_ ++%token SCRIPTFORMAT + + %token ERROR + +@@ -282,6 +283,8 @@ statuscfg: /* */ + { cur_config.status_interval=$2; } + | INTERVAL TIME + { cur_config.status_interval=$2; } ++ | SCRIPTFORMAT boolean ++ { cur_config.status_format=$2; } + | statuscfg separator statuscfg + ; + +--- a/src/cfgparser2.l ++++ b/src/cfgparser2.l +@@ -85,6 +85,7 @@ srcip { LOC; LOCINC; return SRCIP; } + down { LOC; LOCINC; return DOWN; } + false { LOC; LOCINC; return FALSE; } + file { LOC; LOCINC; return FILE_; } ++scriptformat { LOC; LOCINC; return SCRIPTFORMAT; } + group { LOC; LOCINC; return GROUP; } + interval { LOC; LOCINC; return INTERVAL; } + loss { LOC; LOCINC; return LOSS; } +--- a/src/conf.h ++++ b/src/conf.h +@@ -97,6 +97,7 @@ struct config { + char *pid_file; + char *status_file; + int status_interval; ++ int status_format; + char *timestamp_format; + }; + +--- a/src/main.c ++++ b/src/main.c +@@ -88,6 +88,7 @@ struct config default_config={ + "/var/run/apinger.pid", /* pid file */ + NULL, /* status file */ + 0, /* status interval */ ++ 0, /* status format */ + "%b %d %H:%M:%S" /* timestamp format */ + }; + |