Fixed additional comments
[collectd.git] / src / network.c
1 diff -Naur src/network.c src/network.c
2 --- src/network.c       2018-06-14 06:29:51.000000000 +0300
3 +++ src/network.c       2018-06-19 21:27:22.432241000 +0300
4 @@ -113,6 +113,7 @@
5  #endif
6    cdtime_t next_resolve_reconnect;
7    cdtime_t resolve_interval;
8 +  struct sockaddr_storage *bind_addr;
9  };
10  
11  struct sockent_server {
12 @@ -1501,6 +1502,7 @@
13      sec->fd = -1;
14    }
15    sfree(sec->addr);
16 +  sfree(sec->bind_addr);
17  #if HAVE_GCRYPT_H
18    sfree(sec->username);
19    sfree(sec->password);
20 @@ -1683,6 +1685,35 @@
21    return 0;
22  } /* }}} network_set_interface */
23  
24 +static int network_bind_socket_to_addr(sockent_t *se, const struct addrinfo *ai) {
25 +
26 +  if (se->data.client.bind_addr == NULL)
27 +    return 0;
28 +
29 +  DEBUG("network_plugin: fd %i: bind socket to address", se->data.client.fd);
30 +  char pbuffer[64];
31 +
32 +  if (ai->ai_family == AF_INET) {
33 +    struct sockaddr_in *addr = (struct sockaddr_in *)(se->data.client.bind_addr);
34 +    inet_ntop(AF_INET, &(addr->sin_addr), pbuffer, 64);
35 +    DEBUG("network_plugin: binding client socket to ipv4 address: %s", pbuffer);
36 +    if (bind(se->data.client.fd, (struct sockaddr*)addr, sizeof(*addr)) == -1) {
37 +      ERROR("network_plugin: failed to bind client socket (ipv4): %s", STRERRNO);
38 +      return -1;
39 +    }
40 +  } else if (ai->ai_family == AF_INET6) {
41 +    struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(se->data.client.bind_addr);
42 +    inet_ntop(AF_INET, &(addr->sin6_addr), pbuffer, 64);
43 +    DEBUG("network_plugin: binding client socket to ipv6 address: %s", pbuffer);
44 +    if (bind(se->data.client.fd, (struct sockaddr*)addr, sizeof(*addr)) == -1) {
45 +      ERROR("network_plugin: failed to bind client socket (ipv6): %s", STRERRNO);
46 +      return -1;
47 +    }
48 +  }
49 +
50 +  return 0;
51 +} /* int network_bind_socket_to_addr */
52 +
53  static int network_bind_socket(int fd, const struct addrinfo *ai,
54                                 const int interface_idx) {
55  #if KERNEL_SOLARIS
56 @@ -1834,6 +1865,7 @@
57    } else {
58      se->data.client.fd = -1;
59      se->data.client.addr = NULL;
60 +    se->data.client.bind_addr = NULL;
61      se->data.client.resolve_interval = 0;
62      se->data.client.next_resolve_reconnect = 0;
63  #if HAVE_GCRYPT_H
64 @@ -1989,6 +2021,7 @@
65  
66      network_set_ttl(se, ai_ptr);
67      network_set_interface(se, ai_ptr);
68 +    network_bind_socket_to_addr(se, ai_ptr);
69  
70      /* We don't open more than one write-socket per
71       * node/service pair.. */
72 @@ -2684,6 +2717,48 @@
73    return 0;
74  } /* }}} int network_config_set_interface */
75  
76 +static int network_config_set_bind_address(const oconfig_item_t *ci,
77 +                                        struct sockaddr_storage **bind_address) {
78 +  if ((*bind_address) != NULL) {
79 +      ERROR("network_plugin: only a single bind address is allowed");
80 +      return -1;    
81 +  }
82 +
83 +  char addr_text[256];
84 +
85 +  if (cf_util_get_string_buffer(ci, addr_text, sizeof(addr_text)) != 0)
86 +    return -1;
87 +
88 +  int ret;
89 +  struct addrinfo hint, *res = NULL;
90 +
91 +  memset(&hint, '\0', sizeof hint);
92 +  hint.ai_family = PF_UNSPEC;
93 +  hint.ai_flags = AI_NUMERICHOST;
94 +
95 +  ret = getaddrinfo(addr_text, NULL, &hint, &res);
96 +  if (ret) {
97 +    ERROR("network plugin: Bind address option has invalid address set: %s", gai_strerror(ret));
98 +    return -1;
99 +  }
100 +
101 +  *bind_address = malloc(sizeof(**bind_address));
102 +  (*bind_address)->ss_family = res->ai_family;
103 +  if(res->ai_family == AF_INET) {
104 +    struct sockaddr_in* addr = (struct sockaddr_in*)(*bind_address);
105 +    inet_pton(AF_INET, addr_text, &(addr->sin_addr));
106 +  } else if (res->ai_family == AF_INET6) {
107 +    struct sockaddr_in6* addr = (struct sockaddr_in6*)(*bind_address);
108 +    inet_pton(AF_INET6, addr_text, &(addr->sin6_addr));
109 +  } else {
110 +    ERROR("network plugin: %s is an unknown address format %d\n",addr_text,res->ai_family);
111 +    sfree(*bind_address);
112 +    return -1;
113 +  }
114 +
115 +  return 0;
116 +} /* int network_config_set_bind_address */
117 +
118  static int network_config_set_buffer_size(const oconfig_item_t *ci) /* {{{ */
119  {
120    int tmp = 0;
121 @@ -2843,6 +2918,8 @@
122  #endif /* HAVE_GCRYPT_H */
123          if (strcasecmp("Interface", child->key) == 0)
124        network_config_set_interface(child, &se->interface);
125 +    else if (strcasecmp("BindAddress", child->key) == 0)
126 +      network_config_set_bind_address(child, &se->data.client.bind_addr);
127      else if (strcasecmp("ResolveInterval", child->key) == 0)
128        cf_util_get_cdtime(child, &se->data.client.resolve_interval);
129      else {