mirror of
https://github.com/eclipse/mosquitto.git
synced 2025-05-09 01:01:11 +08:00
parent
28c28fe707
commit
886ee6cd0c
@ -8,6 +8,7 @@ Broker:
|
||||
- Fix apparmor incorrectly denying access to
|
||||
/var/lib/mosquitto/mosquitto.db.new. Closes #1978.
|
||||
- Fix potential intermittent initial bridge connections when using poll().
|
||||
- Fix `bind_interface` option. Closes #1999.
|
||||
|
||||
Apps:
|
||||
- Disallow control characters in mosquitto_passwd usernames.
|
||||
|
@ -1035,21 +1035,13 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
|
||||
<option>bind_address</option> option but is useful
|
||||
when an interface has multiple addresses or the
|
||||
address may change.</para>
|
||||
<para>It is valid to use this option together with
|
||||
<para>If used at the same time as the
|
||||
<option>bind_address</option> for the default
|
||||
listener, or the <replaceable>bind
|
||||
address/host</replaceable> part of the
|
||||
<option>listener</option> definition. Care should
|
||||
be taken to ensure that the address being bound to
|
||||
is on the interface being bound to. If you set the
|
||||
<option>bind_interface</option> to be
|
||||
<replaceable>eth0</replaceable>, and
|
||||
<option>bind_address</option> to
|
||||
<replaceable>127.0.0.1</replaceable>, then the
|
||||
broker will start correctly but you will be unable
|
||||
to connect.</para>
|
||||
<para>This option is currently only available on
|
||||
Linux, and requires elevated privileges.</para>
|
||||
address/host</replaceable> part of the
|
||||
<option>listener</option>, then <option>bind_interface</option>
|
||||
will take priority.</para>
|
||||
<para>This option is not available on Windows.</para>
|
||||
<para>Not reloaded on reload signal.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -229,11 +229,10 @@
|
||||
|
||||
# Bind the listener to a specific interface. This is similar to
|
||||
# the [ip address/host name] part of the listener definition, but is useful
|
||||
# when an interface has multiple addresses or the address may change. It is
|
||||
# valid to use this with the [ip address/host name] part of the listener
|
||||
# definition, but take care that the interface you are binding to contains the
|
||||
# address you are binding to, otherwise you will not be able to connect.
|
||||
# Only available on Linux and requires elevated privileges.
|
||||
# when an interface has multiple addresses or the address may change. If used
|
||||
# with the [ip address/host name] part of the listener definition, then the
|
||||
# bind_interface option will take priority.
|
||||
# Not available on Windows.
|
||||
#
|
||||
# Example: bind_interface eth0
|
||||
#bind_interface
|
||||
|
60
src/net.c
60
src/net.c
@ -24,7 +24,7 @@ Contributors:
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <net/if.h>
|
||||
#include <ifaddrs.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
@ -607,6 +607,52 @@ int net__tls_load_verify(struct mosquitto__listener *listener)
|
||||
}
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
static int net__bind_interface(struct mosquitto__listener *listener, mosq_sock_t sock, struct addrinfo *rp)
|
||||
{
|
||||
/*
|
||||
* This binds the listener sock to a network interface.
|
||||
* The use of SO_BINDTODEVICE requires root access, which we don't have, so instead
|
||||
* use getifaddrs to find the interface addresses, and attempt to bind to
|
||||
* the IP of the matching interface.
|
||||
*/
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
if(getifaddrs(&ifaddr) < 0){
|
||||
net__print_error(MOSQ_LOG_ERR, "Error: %s");
|
||||
return MOSQ_ERR_ERRNO;
|
||||
}
|
||||
|
||||
for(ifa=ifaddr; ifa!=NULL; ifa=ifa->ifa_next){
|
||||
if(ifa->ifa_addr == NULL){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!strcasecmp(listener->bind_interface, ifa->ifa_name)
|
||||
&& ifa->ifa_addr->sa_family == rp->ai_addr->sa_family){
|
||||
|
||||
if(rp->ai_addr->sa_family == AF_INET){
|
||||
memcpy(&((struct sockaddr_in *)rp->ai_addr)->sin_addr,
|
||||
&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
|
||||
freeifaddrs(ifaddr);
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else if(rp->ai_addr->sa_family == AF_INET6){
|
||||
memcpy(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr,
|
||||
&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
freeifaddrs(ifaddr);
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifaddr);
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Interface %s not found.", listener->bind_interface);
|
||||
return MOSQ_ERR_NOT_FOUND;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int net__socket_listen_tcp(struct mosquitto__listener *listener)
|
||||
{
|
||||
mosq_sock_t sock = INVALID_SOCKET;
|
||||
@ -615,9 +661,6 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener)
|
||||
char service[10];
|
||||
int rc;
|
||||
int ss_opt = 1;
|
||||
#ifdef SO_BINDTODEVICE
|
||||
struct ifreq ifr;
|
||||
#endif
|
||||
|
||||
if(!listener) return MOSQ_ERR_INVAL;
|
||||
|
||||
@ -680,14 +723,9 @@ static int net__socket_listen_tcp(struct mosquitto__listener *listener)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef SO_BINDTODEVICE
|
||||
#ifndef WIN32
|
||||
if(listener->bind_interface){
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, listener->bind_interface, sizeof(ifr.ifr_name)-1);
|
||||
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
|
||||
log__printf(NULL, MOSQ_LOG_INFO, "Binding listener to interface \"%s\".", ifr.ifr_name);
|
||||
if(setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {
|
||||
net__print_error(MOSQ_LOG_ERR, "Error: %s");
|
||||
if(net__bind_interface(listener, sock, rp)){
|
||||
COMPAT_CLOSE(sock);
|
||||
freeaddrinfo(ainfo);
|
||||
mosquitto__free(listener->socks);
|
||||
|
Loading…
x
Reference in New Issue
Block a user