diff options
author | root <root@test1n1.VSOFS1.COM> | 2008-12-05 10:33:38 +1100 |
---|---|---|
committer | root <root@test1n1.VSOFS1.COM> | 2008-12-05 10:33:38 +1100 |
commit | bf6715340258a5cf3b49aa05c38b1fc02a78a2da (patch) | |
tree | e7aae5693a772bac9bd1746b59811ec2975d00d9 /ctdb/tcp | |
parent | 9f2de14fb8a1568b88063fe2ee3b1141c6ee885d (diff) | |
download | samba-bf6715340258a5cf3b49aa05c38b1fc02a78a2da.tar.gz |
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)
Diffstat (limited to 'ctdb/tcp')
-rw-r--r-- | ctdb/tcp/tcp_connect.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index bd8af57e08a..cd0693cc383 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -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; } |