mirror of
https://github.com/samba-team/samba.git
synced 2025-08-08 13:49:29 +03:00
some platforms are very picky about the third argument passed to bind().
and would complain if sa.family is AF_INET and the third argument is not exactly the size of a sockaddr_in. We used to pass a union containing both a sockaddr_in and a sockaddr_in6 which would mean that on those platforms bind() would fail since the passed structure for AF_INET would be too big. Thus we need to set and pass the appropriate size to bind. At the same time for thos eplatforms we can also set sin[6]_size to the expected size. (bind() on those platforms were isurprisingly perfectly ok with sin_len was "too big") (This used to be ctdb commit 5d3018c37179966f75183d9a98790eaaaf1d2cfc)
This commit is contained in:
@ -2,6 +2,7 @@
|
||||
ctdb over TCP
|
||||
|
||||
Copyright (C) Andrew Tridgell 2006
|
||||
Copyright (C) Ronnie Sahlberg 2008
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -127,6 +128,7 @@ void ctdb_tcp_node_connect(struct event_context *ev, struct timed_event *te,
|
||||
struct ctdb_tcp_node);
|
||||
struct ctdb_context *ctdb = node->ctdb;
|
||||
ctdb_sock_addr sock_in;
|
||||
int sockin_size;
|
||||
ctdb_sock_addr sock_out;
|
||||
|
||||
ctdb_tcp_stop_connection(node);
|
||||
@ -151,7 +153,7 @@ void ctdb_tcp_node_connect(struct event_context *ev, struct timed_event *te,
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG(DEBUG_ERR,("create socket...\n"));
|
||||
DEBUG(DEBUG_ERR,("create socket...\n"));
|
||||
tnode->fd = socket(sock_out.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
set_nonblocking(tnode->fd);
|
||||
set_close_on_exec(tnode->fd);
|
||||
@ -163,13 +165,25 @@ DEBUG(DEBUG_ERR,("create socket...\n"));
|
||||
* a dedicated non-routeable network.
|
||||
*/
|
||||
ZERO_STRUCT(sock_in);
|
||||
#ifdef HAVE_SOCK_SIN_LEN
|
||||
sock_in.ip.sin_len = sizeof(sock_in);
|
||||
#endif
|
||||
if (ctdb_tcp_get_address(ctdb, ctdb->address.address, &sock_in) != 0) {
|
||||
return;
|
||||
}
|
||||
bind(tnode->fd, (struct sockaddr *)&sock_in, sizeof(sock_in));
|
||||
switch (sock_in.sa.sa_family) {
|
||||
case AF_INET:
|
||||
sockin_size = sizeof(sock_in.ip);
|
||||
break;
|
||||
case AF_INET6:
|
||||
sockin_size = sizeof(sock_in.ip6);
|
||||
break;
|
||||
default:
|
||||
DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n",
|
||||
sock_in.sa.sa_family));
|
||||
return;
|
||||
}
|
||||
#ifdef HAVE_SOCK_SIN_LEN
|
||||
sock_in.ip.sin_len = sockin_size;
|
||||
#endif
|
||||
bind(tnode->fd, (struct sockaddr *)&sock_in, sockin_size);
|
||||
|
||||
if (connect(tnode->fd, (struct sockaddr *)&sock_out, sizeof(sock_out)) != 0 &&
|
||||
errno != EINPROGRESS) {
|
||||
@ -249,6 +263,7 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb)
|
||||
const char *lock_path = "/tmp/.ctdb_socket_lock";
|
||||
struct flock lock;
|
||||
int one = 1;
|
||||
int sock_size;
|
||||
|
||||
/* in order to ensure that we don't get two nodes with the
|
||||
same adddress, we must make the bind() and listen() calls
|
||||
@ -283,9 +298,6 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb)
|
||||
}
|
||||
|
||||
ZERO_STRUCT(sock);
|
||||
#ifdef HAVE_SOCK_SIN_LEN
|
||||
sock.ip.sin_len = sizeof(sock);
|
||||
#endif
|
||||
if (ctdb_tcp_get_address(ctdb,
|
||||
ctdb->nodes[i]->address.address,
|
||||
&sock) != 0) {
|
||||
@ -295,15 +307,20 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb)
|
||||
switch (sock.sa.sa_family) {
|
||||
case AF_INET:
|
||||
sock.ip.sin_port = htons(ctdb->nodes[i]->address.port);
|
||||
sock_size = sizeof(sock.ip);
|
||||
break;
|
||||
case AF_INET6:
|
||||
sock.ip6.sin6_port = htons(ctdb->nodes[i]->address.port);
|
||||
sock_size = sizeof(sock.ip6);
|
||||
break;
|
||||
default:
|
||||
DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n",
|
||||
sock.sa.sa_family));
|
||||
continue;
|
||||
}
|
||||
#ifdef HAVE_SOCK_SIN_LEN
|
||||
sock.ip.sin_len = sock_size;
|
||||
#endif
|
||||
|
||||
ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (ctcp->listen_fd == -1) {
|
||||
@ -315,8 +332,8 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb)
|
||||
|
||||
setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
|
||||
|
||||
if (bind(ctcp->listen_fd, (struct sockaddr * )&sock,
|
||||
sizeof(sock)) == 0) {
|
||||
if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size) == 0) {
|
||||
DEBUG(DEBUG_ERR,(__location__ " Failed to bind() to socket. %s(%d)\n", strerror(errno), errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -368,6 +385,7 @@ int ctdb_tcp_listen(struct ctdb_context *ctdb)
|
||||
struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data,
|
||||
struct ctdb_tcp);
|
||||
ctdb_sock_addr sock;
|
||||
int sock_size;
|
||||
int one = 1;
|
||||
|
||||
/* we can either auto-bind to the first available address, or we can
|
||||
@ -377,9 +395,6 @@ int ctdb_tcp_listen(struct ctdb_context *ctdb)
|
||||
}
|
||||
|
||||
ZERO_STRUCT(sock);
|
||||
#ifdef HAVE_SOCK_SIN_LEN
|
||||
sock.ip.sin_len = sizeof(sock);
|
||||
#endif
|
||||
if (ctdb_tcp_get_address(ctdb, ctdb->address.address,
|
||||
&sock) != 0) {
|
||||
goto failed;
|
||||
@ -388,15 +403,20 @@ int ctdb_tcp_listen(struct ctdb_context *ctdb)
|
||||
switch (sock.sa.sa_family) {
|
||||
case AF_INET:
|
||||
sock.ip.sin_port = htons(ctdb->address.port);
|
||||
sock_size = sizeof(sock.ip);
|
||||
break;
|
||||
case AF_INET6:
|
||||
sock.ip6.sin6_port = htons(ctdb->address.port);
|
||||
sock_size = sizeof(sock.ip6);
|
||||
break;
|
||||
default:
|
||||
DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n",
|
||||
sock.sa.sa_family));
|
||||
goto failed;
|
||||
}
|
||||
#ifdef HAVE_SOCK_SIN_LEN
|
||||
sock.ip.sin_len = sock_size;
|
||||
#endif
|
||||
|
||||
ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (ctcp->listen_fd == -1) {
|
||||
@ -408,7 +428,8 @@ int ctdb_tcp_listen(struct ctdb_context *ctdb)
|
||||
|
||||
setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
|
||||
|
||||
if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sizeof(sock)) != 0) {
|
||||
if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size) != 0) {
|
||||
DEBUG(DEBUG_ERR,(__location__ " Failed to bind() to socket. %s(%d)\n", strerror(errno), errno));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user