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
6 cdtime_t next_resolve_reconnect;
7 cdtime_t resolve_interval;
8 + struct sockaddr_storage *bind_addr;
11 struct sockent_server {
16 + sfree(sec->bind_addr);
20 @@ -1683,6 +1685,35 @@
22 } /* }}} network_set_interface */
24 +static int network_bind_socket_to_addr(sockent_t *se, const struct addrinfo *ai) {
26 + if (se->data.client.bind_addr == NULL)
29 + DEBUG("network_plugin: fd %i: bind socket to address", se->data.client.fd);
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);
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);
51 +} /* int network_bind_socket_to_addr */
53 static int network_bind_socket(int fd, const struct addrinfo *ai,
54 const int interface_idx) {
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;
66 network_set_ttl(se, ai_ptr);
67 network_set_interface(se, ai_ptr);
68 + network_bind_socket_to_addr(se, ai_ptr);
70 /* We don't open more than one write-socket per
71 * node/service pair.. */
72 @@ -2684,6 +2717,48 @@
74 } /* }}} int network_config_set_interface */
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");
83 + char addr_text[256];
85 + if (cf_util_get_string_buffer(ci, addr_text, sizeof(addr_text)) != 0)
89 + struct addrinfo hint, *res = NULL;
91 + memset(&hint, '\0', sizeof hint);
92 + hint.ai_family = PF_UNSPEC;
93 + hint.ai_flags = AI_NUMERICHOST;
95 + ret = getaddrinfo(addr_text, NULL, &hint, &res);
97 + ERROR("network plugin: Bind address option has invalid address set: %s", gai_strerror(ret));
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));
110 + ERROR("network plugin: %s is an unknown address format %d\n",addr_text,res->ai_family);
111 + sfree(*bind_address);
116 +} /* int network_config_set_bind_address */
118 static int network_config_set_buffer_size(const oconfig_item_t *ci) /* {{{ */
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);