Skip to content

Commit

Permalink
some platforms are very picky about the third argument passed to bind().
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
root authored and root committed Dec 4, 2008
1 parent 9f2de14 commit bf67153
Showing 1 changed file with 35 additions and 14 deletions.
49 changes: 35 additions & 14 deletions ctdb/tcp/tcp_connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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) {
Expand All @@ -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;
}

Expand Down

0 comments on commit bf67153

Please sign in to comment.