summaryrefslogtreecommitdiffstats
path: root/src/vnet/map/examples/health_check.c
blob: 5f0d85fec0814283861a34a8804fc7e895ec1318 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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);
}
818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884