MAP: Move MAP-E/T to a plugin.
[vpp.git] / src / plugins / examples / health_check.c
1 #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
13 static void
14 usage (void) {
15   fprintf(stderr,
16           "Usage: health_check"
17           " -d debug"
18           " -I interface"
19           "\n");
20   exit(2);
21 }
22
23 int
24 main (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 }