blob: 5f0d85fec0814283861a34a8804fc7e895ec1318 [file] [log] [blame]
Ole Troan36de0382016-01-17 18:59:44 +01001#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <string.h>
5#include <netinet/in.h>
6#include <netinet/ip.h>
7#include <netinet/ip_icmp.h>
8#include <arpa/inet.h>
9#include <net/if.h>
10#include <stdbool.h>
11#include <errno.h>
12
13static void
14usage (void) {
15 fprintf(stderr,
16 "Usage: health_check"
17 " -d debug"
18 " -I interface"
19 "\n");
20 exit(2);
21}
22
23int
24main (int argc, char **argv)
25{
26 int sd, ch;
27 uint8_t *opt, *pkt;
28 struct ifreq ifr;
29 char *interface = NULL;
30 bool debug = false;
31
32 while ((ch = getopt(argc, argv, "h?" "I:" "d")) != EOF) {
33 switch(ch) {
34 case 'I':
35 interface = optarg;
36 break;
37 case 'd':
38 debug = true;
39 break;
40 default:
41 usage();
42 break;
43 }
44 }
45
46 argc -= optind;
47 argv += optind;
48
49 if (!interface)
50 usage();
51
52 /* Request a socket descriptor sd. */
53 if ((sd = socket (AF_INET6, SOCK_RAW, IPPROTO_IPIP)) < 0) {
54 perror ("Failed to get socket descriptor ");
55 exit (EXIT_FAILURE);
56 }
57
58 memset(&ifr, 0, sizeof(ifr));
59 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", interface);
60
61 /* Bind socket to interface of this node. */
62 if (setsockopt (sd, SOL_SOCKET, SO_BINDTODEVICE, (void *) &ifr, sizeof (ifr)) < 0) {
63 perror ("SO_BINDTODEVICE failed");
64 exit (EXIT_FAILURE);
65 }
66 if (debug) printf("Binding to interface %s\n", interface);
67
68 while (1) {
69 struct sockaddr_in6 src_addr;
70 socklen_t addrlen = sizeof(src_addr);
71 char source[INET6_ADDRSTRLEN+1];
72 int len;
73 uint8_t inpack[IP_MAXPACKET];
74
75 if ((len = recvfrom(sd, inpack, sizeof(inpack), 0, (struct sockaddr *)&src_addr, &addrlen)) < 0) {
76 perror("recvfrom failed ");
77 }
78 if (inet_ntop(AF_INET6, &src_addr.sin6_addr, source, INET6_ADDRSTRLEN) == NULL) {
79 perror("inet_ntop() failed.");
80 exit(EXIT_FAILURE);
81 }
82
83 /* Reply */
84 struct iphdr *ip = (struct iphdr *)inpack;
85 uint32_t saddr;
86 struct icmphdr *icmp;
87
88 saddr = ip->saddr;
89 ip->saddr = ip->daddr;
90 ip->daddr = saddr;
91
92 switch (ip->protocol) {
93 case 1:
94 if (debug) printf ("ICMP Echo request from %s\n", source);
95 icmp = (struct icmphdr *)&ip[1];
96 icmp->type = ICMP_ECHOREPLY;
97 break;
98 default:
99 fprintf(stderr, "Unsupported protocol %d", ip->protocol);
100 }
101 if (len = sendto(sd, inpack, len, 0, (struct sockaddr *)&src_addr, addrlen) < 0) {
102 perror("sendto failed ");
103 }
104 }
105
106 close (sd);
107
108 return (EXIT_SUCCESS);
109}