diff options
Diffstat (limited to 'src/vnet/map/examples/health_check.c')
-rw-r--r-- | src/vnet/map/examples/health_check.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/vnet/map/examples/health_check.c b/src/vnet/map/examples/health_check.c new file mode 100644 index 00000000000..5f0d85fec08 --- /dev/null +++ b/src/vnet/map/examples/health_check.c @@ -0,0 +1,109 @@ +#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); +} |