diff options
author | Jeremy Allison <jra@samba.org> | 2007-10-24 14:16:54 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2007-10-24 14:16:54 -0700 |
commit | f88b7a076be74a29a3bf876b4e2705f4a1ecf42b (patch) | |
tree | 2d5167540fcbe1ad245fce697924b18216b2d142 /source3/lib | |
parent | e01cbcb28e63abb0f681a5a168fc2445744eec93 (diff) | |
download | samba-f88b7a076be74a29a3bf876b4e2705f4a1ecf42b.tar.gz samba-f88b7a076be74a29a3bf876b4e2705f4a1ecf42b.tar.bz2 samba-f88b7a076be74a29a3bf876b4e2705f4a1ecf42b.zip |
This is a large patch (sorry). Migrate from struct in_addr
to struct sockaddr_storage in most places that matter (ie.
not the nmbd and NetBIOS lookups). This passes make test
on an IPv4 box, but I'll have to do more work/testing on
IPv6 enabled boxes. This should now give us a framework
for testing and finishing the IPv6 migration. It's at
the state where someone with a working IPv6 setup should
(theorecically) be able to type :
smbclient //ipv6-address/share
and have it work.
Jeremy.
(This used to be commit 98e154c3125d5732c37a72d74b0eb5cd7b6155fd)
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/interface.c | 14 | ||||
-rw-r--r-- | source3/lib/util_sock.c | 206 | ||||
-rw-r--r-- | source3/lib/util_str.c | 83 |
3 files changed, 227 insertions, 76 deletions
diff --git a/source3/lib/interface.c b/source3/lib/interface.c index 0696329fd6..49bbceceb7 100644 --- a/source3/lib/interface.c +++ b/source3/lib/interface.c @@ -269,7 +269,7 @@ const struct sockaddr_storage *iface_ip(const struct sockaddr_storage *ip) return True if a IP is directly reachable on one of our interfaces */ -bool iface_local(struct sockaddr_storage *ip) +bool iface_local(const struct sockaddr_storage *ip) { return iface_find(ip, True) ? true : false; } @@ -285,8 +285,7 @@ static void add_interface(const struct iface_struct *ifs) if (iface_find(&ifs->ip, False)) { DEBUG(3,("add_interface: not adding duplicate interface %s\n", - print_sockaddr(addr, sizeof(addr), - &ifs->ip, sizeof(struct sockaddr_storage)) )); + print_sockaddr(addr, sizeof(addr), &ifs->ip) )); return; } @@ -317,16 +316,13 @@ static void add_interface(const struct iface_struct *ifs) DEBUG(2,("added interface %s ip=%s ", iface->name, - print_sockaddr(addr, sizeof(addr), - &iface->ip, sizeof(struct sockaddr_storage)) )); + print_sockaddr(addr, sizeof(addr), &iface->ip) )); DEBUG(2,("bcast=%s ", print_sockaddr(addr, sizeof(addr), - &iface->bcast, - sizeof(struct sockaddr_storage)) )); + &iface->bcast) )); DEBUG(2,("netmask=%s\n", print_sockaddr(addr, sizeof(addr), - &iface->netmask, - sizeof(struct sockaddr_storage)) )); + &iface->netmask) )); } /**************************************************************************** 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; } } diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 2fd22280a4..226bf826fb 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -2270,27 +2270,54 @@ bool str_list_substitute(char **list, const char *pattern, const char *insert) * reallocated to new length **/ -char *ipstr_list_add(char **ipstr_list, const struct ip_service *service) +static char *ipstr_list_add(char **ipstr_list, const struct ip_service *service) { char *new_ipstr = NULL; + char addr_buf[INET6_ADDRSTRLEN]; /* arguments checking */ - if (!ipstr_list || !service) return NULL; + if (!ipstr_list || !service) { + return NULL; + } /* attempt to convert ip to a string and append colon separator to it */ if (*ipstr_list) { - asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP, - inet_ntoa(service->ip), service->port); + print_sockaddr(addr_buf, + sizeof(addr_buf), + &service->ss); + if (service->ss.ss_family == AF_INET) { + /* IPv4 */ + asprintf(&new_ipstr, "%s%s%s:%d", + *ipstr_list, + IPSTR_LIST_SEP, + addr_buf, + service->port); + } else { + /* IPv6 */ + asprintf(&new_ipstr, "%s%s[%s]:%d", + *ipstr_list, + IPSTR_LIST_SEP, + addr_buf, + service->port); + } SAFE_FREE(*ipstr_list); } else { - asprintf(&new_ipstr, "%s:%d", - inet_ntoa(service->ip), service->port); + if (service->ss.ss_family == AF_INET) { + /* IPv4 */ + asprintf(&new_ipstr, "%s:%d", + addr_buf, + service->port); + } else { + /* IPv6 */ + asprintf(&new_ipstr, "[%s]:%d", + addr_buf, + service->port); + } } *ipstr_list = new_ipstr; return *ipstr_list; } - /** * Allocate and initialise an ipstr list using ip adresses * passed as arguments. @@ -2302,18 +2329,22 @@ char *ipstr_list_add(char **ipstr_list, const struct ip_service *service) **/ char *ipstr_list_make(char **ipstr_list, - const struct ip_service * ip_list, int ip_count) + const struct ip_service *ip_list, + int ip_count) { int i; /* arguments checking */ - if (!ip_list || !ipstr_list) return 0; + if (!ip_list || !ipstr_list) { + return 0; + } *ipstr_list = NULL; /* process ip addresses given as arguments */ - for (i = 0; i < ip_count; i++) + for (i = 0; i < ip_count; i++) { *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]); + } return (*ipstr_list); } @@ -2322,7 +2353,7 @@ char *ipstr_list_make(char **ipstr_list, /** * Parse given ip string list into array of ip addresses * (as ip_service structures) - * e.g. 192.168.1.100:389,192.168.1.78, ... + * e.g. [IPv6]:port,192.168.1.100:389,192.168.1.78, ... * * @param ipstr ip string list to be parsed * @param ip_list pointer to array of ip addresses which is @@ -2330,7 +2361,7 @@ char *ipstr_list_make(char **ipstr_list, * @return number of succesfully parsed addresses **/ -int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list) +int ipstr_list_parse(const char *ipstr_list, struct ip_service **ip_list) { fstring token_str; size_t count; @@ -2348,27 +2379,34 @@ int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list) for ( i=0; next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && i<count; i++ ) { - struct in_addr addr; - unsigned port = 0; - char *p = strchr(token_str, ':'); + char *s = token_str; + char *p = strrchr(token_str, ':'); if (p) { *p = 0; - port = atoi(p+1); + (*ip_list)[i].port = atoi(p+1); } /* convert single token to ip address */ - if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE ) - break; - - (*ip_list)[i].ip = addr; - (*ip_list)[i].port = port; + if (token_str[0] == '[') { + /* IPv6 address. */ + s++; + p = strchr(token_str, ']'); + if (!p) { + continue; + } + *p = '\0'; + } + if (!interpret_string_addr(&(*ip_list)[i].ss, + s, + AI_NUMERICHOST)) { + continue; + } } return count; } - /** * Safely free ip string list * @@ -2380,7 +2418,6 @@ void ipstr_list_free(char* ipstr_list) SAFE_FREE(ipstr_list); } - /** Unescape a URL encoded string, in place. **/ |