blob: 5f0d85fec0814283861a34a8804fc7e895ec1318 [file] [log] [blame]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <stdbool.h>
#include <errno.h>
static void
usage (void) {
fprintf(stderr,
"Usage: health_check"
" -d debug"
" -I interface"
"\n");
exit(2);
}
int
main (int argc, char **argv)
{
int sd, ch;
uint8_t *opt, *pkt;
struct ifreq ifr;
char *interface = NULL;
bool debug = false;
while ((ch = getopt(argc, argv, "h?" "I:" "d")) != EOF) {
switch(ch) {
case 'I':
interface = optarg;
break;
case 'd':
debug = true;
break;
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
if (!interface)
usage();
/* Request a socket descriptor sd. */
if ((sd = socket (AF_INET6, SOCK_RAW, IPPROTO_IPIP)) < 0) {
perror ("Failed to get socket descriptor ");
exit (EXIT_FAILURE);
}
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", interface);
/* Bind socket to interface of this node. */
if (setsockopt (sd, SOL_SOCKET, SO_BINDTODEVICE, (void *) &ifr, sizeof (ifr)) < 0) {
perror ("SO_BINDTODEVICE failed");
exit (EXIT_FAILURE);
}
if (debug) printf("Binding to interface %s\n", interface);
while (1) {
struct sockaddr_in6 src_addr;
socklen_t addrlen = sizeof(src_addr);
char source[INET6_ADDRSTRLEN+1];
int len;
uint8_t inpack[IP_MAXPACKET];
if ((len = recvfrom(sd, inpack, sizeof(inpack), 0, (struct sockaddr *)&src_addr, &addrlen)) < 0) {
perror("recvfrom failed ");
}
if (inet_ntop(AF_INET6, &src_addr.sin6_addr, source, INET6_ADDRSTRLEN) == NULL) {
perror("inet_ntop() failed.");
exit(EXIT_FAILURE);
}
/* Reply */
struct iphdr *ip = (struct iphdr *)inpack;
uint32_t saddr;
struct icmphdr *icmp;
saddr = ip->saddr;
ip->saddr = ip->daddr;
ip->daddr = saddr;
switch (ip->protocol) {
case 1:
if (debug) printf ("ICMP Echo request from %s\n", source);
icmp = (struct icmphdr *)&ip[1];
icmp->type = ICMP_ECHOREPLY;
break;
default:
fprintf(stderr, "Unsupported protocol %d", ip->protocol);
}
if (len = sendto(sd, inpack, len, 0, (struct sockaddr *)&src_addr, addrlen) < 0) {
perror("sendto failed ");
}
}
close (sd);
return (EXIT_SUCCESS);
}