summaryrefslogtreecommitdiff
path: root/source3/lib/util_sock.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib/util_sock.c')
-rw-r--r--source3/lib/util_sock.c206
1 files changed, 162 insertions, 44 deletions
diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c
index c6b1311cf5..2d784717b2 100644
--- a/source3/lib/util_sock.c
+++ b/source3/lib/util_sock.c
@@ -63,6 +63,27 @@ bool is_ipaddress(const char *str)
return is_ipaddress_v4(str);
}
+/****************************************************************************
+ Is a sockaddr_storage a broadcast address ?
+****************************************************************************/
+
+bool is_broadcast_addr(const struct sockaddr_storage *pss)
+{
+#if defined(HAVE_IPV6)
+ if (pss->ss_family == AF_INET6) {
+ const struct in6_addr *sin6 =
+ &((const struct sockaddr_in6 *)pss)->sin6_addr;
+ return IN6_IS_ADDR_MULTICAST(sin6);
+ }
+#endif
+ if (pss->ss_family == AF_INET) {
+ uint32_t addr =
+ ntohl(((const struct sockaddr_in *)pss)->sin_addr.s_addr);
+ return addr == INADDR_BROADCAST;
+ }
+ return false;
+}
+
/*******************************************************************
Wrap getaddrinfo...
******************************************************************/
@@ -181,7 +202,7 @@ bool interpret_string_addr(struct sockaddr_storage *pss,
{
struct addrinfo *res = NULL;
- memset(pss,'\0', sizeof(*pss));
+ zero_addr(pss, AF_INET);
if (!interpret_string_addr_internal(&res, str, flags|AI_ADDRCONFIG)) {
return false;
@@ -275,6 +296,17 @@ void zero_ip_v4(struct in_addr *ip)
}
/*******************************************************************
+ Set an address to INADDR_ANY, or IN6ADDR_ANY.
+******************************************************************/
+
+void zero_addr(struct sockaddr_storage *pss, int family)
+{
+ memset(pss, '\0', sizeof(*pss));
+ /* Ensure we're at least a valid sockaddr-storage. */
+ pss->ss_family = family;
+}
+
+/*******************************************************************
Are two IPs on the same subnet - IPv4 version ?
********************************************************************/
@@ -385,7 +417,6 @@ bool addr_equal(const struct sockaddr_storage *ip1,
return false;
}
-
/****************************************************************************
Is an IP address the INADDR_ANY or in6addr_any value ?
****************************************************************************/
@@ -417,7 +448,7 @@ bool is_address_any(const struct sockaddr_storage *psa)
Print out an IPv4 or IPv6 address from a struct sockaddr_storage.
****************************************************************************/
-char *print_sockaddr(char *dest,
+char *print_sockaddr_len(char *dest,
size_t destlen,
const struct sockaddr_storage *psa,
socklen_t psalen)
@@ -434,6 +465,75 @@ char *print_sockaddr(char *dest,
}
/****************************************************************************
+ Print out an IPv4 or IPv6 address from a struct sockaddr_storage.
+****************************************************************************/
+
+char *print_sockaddr(char *dest,
+ size_t destlen,
+ const struct sockaddr_storage *psa)
+{
+ return print_sockaddr_len(dest, destlen, psa, sizeof(*psa));
+}
+
+/****************************************************************************
+ Print out a canonical IPv4 or IPv6 address from a struct sockaddr_storage.
+****************************************************************************/
+
+char *print_canonical_sockaddr(TALLOC_CTX *ctx,
+ const struct sockaddr_storage *pss)
+{
+ char addr[INET6_ADDRSTRLEN];
+ char *dest = NULL;
+ int ret;
+
+ ret = getnameinfo((const struct sockaddr *)pss,
+ sizeof(struct sockaddr_storage),
+ addr, sizeof(addr),
+ NULL, 0,
+ NI_NUMERICHOST);
+ if (ret) {
+ return NULL;
+ }
+ if (pss->ss_family != AF_INET) {
+#if defined(HAVE_IPV6)
+ /* IPv6 */
+ const struct sockaddr_in6 *sa6 =
+ (const struct sockaddr_in6 *)pss;
+ uint16_t port = ntohs(sa6->sin6_port);
+
+ if (port) {
+ dest = talloc_asprintf(ctx,
+ "[%s]:%d",
+ addr,
+ (unsigned int)port);
+ } else {
+ dest = talloc_asprintf(ctx,
+ "[%s]",
+ addr);
+ }
+#else
+ return NULL;
+#endif
+ } else {
+ const struct sockaddr_in *sa =
+ (const struct sockaddr_in *)pss;
+ uint16_t port = ntohs(sa->sin_port);
+
+ if (port) {
+ dest = talloc_asprintf(ctx,
+ "%s:%d",
+ addr,
+ (unsigned int)port);
+ } else {
+ dest = talloc_asprintf(ctx,
+ "%s",
+ addr);
+ }
+ }
+ return dest;
+}
+
+/****************************************************************************
Set the global client_fd variable.
****************************************************************************/
@@ -472,7 +572,7 @@ static const char *get_socket_addr(int fd)
return addr_buf;
}
- return print_sockaddr(addr_buf, sizeof(addr_buf), &sa, length);
+ return print_sockaddr_len(addr_buf, sizeof(addr_buf), &sa, length);
}
/****************************************************************************
@@ -1274,24 +1374,26 @@ bool send_smb(int fd, char *buffer)
****************************************************************************/
int open_socket_in(int type,
- int port,
+ uint16_t port,
int dlevel,
- uint32 socket_addr, /* NETWORK BYTE ORDER */
- bool rebind )
+ const struct sockaddr_storage *psock,
+ bool rebind)
{
- struct sockaddr_in sock;
+ struct sockaddr_storage sock;
int res;
- memset( (char *)&sock, '\0', sizeof(sock) );
+ sock = *psock;
-#ifdef HAVE_SOCK_SIN_LEN
- sock.sin_len = sizeof(sock);
+#if defined(HAVE_IPV6)
+ if (sock.ss_family == AF_INET6) {
+ ((struct sockaddr_in6 *)&sock)->sin6_port = htons(port);
+ }
#endif
- sock.sin_port = htons( port );
- sock.sin_family = AF_INET;
- sock.sin_addr.s_addr = socket_addr;
+ if (sock.ss_family == AF_INET) {
+ ((struct sockaddr_in *)&sock)->sin_port = htons(port);
+ }
- res = socket( AF_INET, type, 0 );
+ res = socket(sock.ss_family, type, 0 );
if( res == -1 ) {
if( DEBUGLVL(0) ) {
dbgtext( "open_socket_in(): socket() call failed: " );
@@ -1319,9 +1421,9 @@ int open_socket_in(int type,
if( DEBUGLVL( dlevel ) ) {
dbgtext( "open_socket_in(): setsockopt: ");
dbgtext( "SO_REUSEPORT = %s ",
- val?"true":"false" );
- dbgtext( "on port %d failed ", port );
- dbgtext( "with error = %s\n", strerror(errno) );
+ val?"true":"false");
+ dbgtext( "on port %d failed ", port);
+ dbgtext( "with error = %s\n", strerror(errno));
}
}
#endif /* SO_REUSEPORT */
@@ -1331,17 +1433,18 @@ int open_socket_in(int type,
if( bind( res, (struct sockaddr *)&sock, sizeof(sock) ) == -1 ) {
if( DEBUGLVL(dlevel) && (port == SMB_PORT1 ||
port == SMB_PORT2 || port == NMB_PORT) ) {
- dbgtext( "bind failed on port %d ", port );
- dbgtext( "socket_addr = %s.\n",
- inet_ntoa( sock.sin_addr ) );
- dbgtext( "Error = %s\n", strerror(errno) );
+ char addr[INET6_ADDRSTRLEN];
+ print_sockaddr(addr, sizeof(addr),
+ &sock);
+ dbgtext( "bind failed on port %d ", port);
+ dbgtext( "socket_addr = %s.\n", addr);
+ dbgtext( "Error = %s\n", strerror(errno));
}
- close( res );
+ close(res);
return -1;
}
DEBUG( 10, ( "bind succeeded on port %d\n", port ) );
-
return( res );
}
@@ -1349,33 +1452,46 @@ int open_socket_in(int type,
Create an outgoing socket. timeout is in milliseconds.
**************************************************************************/
-int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
+int open_socket_out(int type,
+ const struct sockaddr_storage *pss,
+ uint16_t port,
+ int timeout)
{
- struct sockaddr_in sock_out;
+ char addr[INET6_ADDRSTRLEN];
+ struct sockaddr_storage sock_out = *pss;
int res,ret;
int connect_loop = 10;
int increment = 10;
/* create a socket to write to */
- res = socket(PF_INET, type, 0);
+ res = socket(pss->ss_family, type, 0);
if (res == -1) {
DEBUG(0,("socket error (%s)\n", strerror(errno)));
return -1;
}
- if (type != SOCK_STREAM)
- return(res);
-
- memset((char *)&sock_out,'\0',sizeof(sock_out));
- putip((char *)&sock_out.sin_addr,(char *)addr);
+ if (type != SOCK_STREAM) {
+ return res;
+ }
- sock_out.sin_port = htons( port );
- sock_out.sin_family = PF_INET;
+#if defined(HAVE_IPV6)
+ if (pss->ss_family == AF_INET6) {
+ struct sockaddr_in6 *psa6 = (struct sockaddr_in6 *)&sock_out;
+ psa6->sin6_port = htons(port);
+ }
+#endif
+ if (pss->ss_family == AF_INET) {
+ struct sockaddr_in *psa = (struct sockaddr_in *)&sock_out;
+ psa->sin_port = htons(port);
+ }
/* set it non-blocking */
set_blocking(res,false);
- DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
+ print_sockaddr(addr, sizeof(addr), &sock_out);
+ DEBUG(3,("Connecting to %s at port %u\n",
+ addr,
+ (unsigned int)port));
/* and connect it to the destination */
connect_again:
@@ -1397,8 +1513,9 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
errno == EAGAIN)) {
- DEBUG(1,("timeout connecting to %s:%d\n",
- inet_ntoa(*addr),port));
+ DEBUG(1,("timeout connecting to %s:%u\n",
+ addr,
+ (unsigned int)port));
close(res);
return -1;
}
@@ -1412,7 +1529,9 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
if (ret < 0) {
DEBUG(2,("error connecting to %s:%d (%s)\n",
- inet_ntoa(*addr),port,strerror(errno)));
+ addr,
+ (unsigned int)port,
+ strerror(errno)));
close(res);
return -1;
}
@@ -1429,7 +1548,7 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
of DC's all of which are equivalent for our purposes.
**************************************************************************/
-bool open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
+bool open_any_socket_out(struct sockaddr_storage *addrs, int num_addrs,
int timeout, int *fd_index, int *fd)
{
int i, resulting_index, res;
@@ -1455,7 +1574,7 @@ bool open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
sockets[i] = -1;
for (i=0; i<num_addrs; i++) {
- sockets[i] = socket(PF_INET, SOCK_STREAM, 0);
+ sockets[i] = socket(addrs[i].ss_family, SOCK_STREAM, 0);
if (sockets[i] < 0)
goto done;
set_blocking(sockets[i], false);
@@ -1639,7 +1758,7 @@ static const char *get_peer_addr_internal(int fd,
return addr_buf;
}
- print_sockaddr(addr_buf,
+ print_sockaddr_len(addr_buf,
sizeof(addr_buf),
pss,
*plength);
@@ -1705,7 +1824,7 @@ static bool matchname(const char *remotehost,
*/
DEBUG(0,("matchname: host name/address mismatch: %s != %s\n",
- print_sockaddr(addr_buf,
+ print_sockaddr_len(addr_buf,
sizeof(addr_buf),
pss,
len),
@@ -2004,8 +2123,7 @@ bool is_myname_or_ipaddr(const char *s)
if (interpret_string_addr(&ss, servername,0)) {
print_sockaddr(name,
sizeof(name),
- &ss,
- sizeof(ss));
+ &ss);
servername = name;
}
}