I've finished patching Samba 2.2.3a to enable SMB connections over IPv6. The patch is quite lengthy, almost 3000 lines, so I have not included it here. It may be retrieved from <http://v6web.litech.org/samba/>.
Below is a description of the changes that were made in the code. I encourage developers to review this description and offer suggestions and improvements for the patch, so that I may adapt the patch to CVS HEAD for inclusion in the official source tree. -Nathan Overview -------- Architecturally, the biggest modification necessary was the support for address lists. Since servers may have both IPv6 and IPv4 addresses and the IPv6 address isn't necessarily reachable to all clients, hosts to which an SMB connection are to be made are now represented by a linked list of sockaddr structs. The resolve_name() function was broken into one function to support NetBIOS and one to support sockaddr lists, and the cli_connect() function and friends were changed to take sockaddr lists. Also, a few changes were made in smbd access control to handle PF_INET6 sockets and sockaddr_in6 endpoints. Name resolution --------------- Since NetBIOS still relies heavily on IPv4, the parts of the source that talk NetBIOS still use IPv4 addresses exclusively, but code that talks TCP and may use direct-hosted SMB was modified. This required breaking out name resolution into two sets of functions: instead of resolve_name() we have resolve_name_netbios(), which functions like the old resolve_name(), and resolve_name_smb() which returns a sockaddr list. The new resolve_name_smb() function will still perform 0x20 lookups in wins, broadcast, etc, but will also look for AAAA and A6 DNS records using the getaddrinfo() libc function. Additionally, since sockaddrs contain a port number, resolve_name_smb() takes a port number as an argument that it will include with returned addresses. If the passed port number is 0, it will return two sockaddrs for each IPv4 address; one with port 445 and one with port 139, causing both ports to be tried during connection attempts. Obviously, only port 445 is used for IPv6 addresses. Client functions ---------------- To accomodate the new sockaddr lists, the cli_connect() and cli_establish_connection() functions were updated to take an address list rather than a struct in_addr. As with passing in ipzero before, passing in a NULL will cause the functions to perform a resolve_name_smb() on the server name. On the back end, open_socket_out takes a sockaddr list of addresses to attempt to connect to, and it tries each one in order until one succeeds. Errors during connecting that indicate that IPv6 is being attempted but is not available, such as "host unreachable" or "protocol not available", are merely logged at a high debugging level and otherwise ignored, unless the attempt was to the last (or only) address in the list. This behavior allows clients with only IPv4 connectivity to connect to servers with both types of addresses without the client complaining or failing. Client configuration -------------------- The libsmb client structure was modified to store the destination address as a sockaddr list, with a member pointer "connected_addr" pointing at the sockaddr element in the destination sockaddr list to which the client is actually connected. Since the TCP port number is built into the name resolution now, the usage of the cli_set_port() function has changed. The only reason cli_set_port() should be called now is if we are connecting to a *non-standard* port, and we intend to call cli_connect() with a NULL sockaddr list. The default is to connect to port 445 followed by 139, and to erroneously call cli_set_port() with 139 would cause connections to *only* go to port 139, which is probably not what we want, and is completely broken for IPv6 hosts. SMBD ---- Surprisingly few changes were necessary to prepare smbd for incoming IPv6 connections. Many improvements to the get_socket_name() and get_socket_addr() functions were necessary to add support for struct sockaddr_in6 endpoints, but the interface and behavior of the functions did not change. The masked_match() function for implementing IP address prefix matching was broken into an IPv4 version and an IPv6 version. The IPv4 version functions as it did before, taking tokens like 192.2.0.0/255.255.255.0, whereas the IPv6 version takes standard IPv6 prefixes like 3ffe:ffff::/32. As with unpatched Samba, accepting connections on port 445 with either IPv4 or IPv6 requires starting smbd from inetd or a work-alike. Of course, accepting IPv6 connections requires an IPv6-enabled daemon like xinetd or rlinetd. Unfinished business ------------------- There are a number of places in the code where ismyip() is called to determine if we're attempting to connect to ourselves and create a loop. I don't know the best (portable) way to determine whether IPv6 addresses belong to us, so these sections of code are wrapped in #if 0. configure.in ------------ The parts of the code that require an IPv6-capable API on the host are wrapped in #ifdef HAVE_INET6, which is defined by the configure script if the user specifies --with-ipv6. If this flag is present, some specific checks are made to make sure the correct structures and functions are present. I've tried to write the code to minimize use of features that are found to be broken or incorrectly implemented in many places, so configure only checks for a few things. The code is written so that the --with-ipv6 flag doesn't change the apparent behavior of the applications. On most sane systems, --with-ipv6 may be used even by users who are unaware of IPv6, but it's best to err on the side of caution since some getaddrinfo() implementations, particularly the one currently shipping in Mac OSX, aren't extensively tested and may not be relied upon to perform correctly. -- +-------------------+---------------------+------------------------+ | Nathan Lutchansky | [EMAIL PROTECTED] | Lithium Technologies | +------------------------------------------------------------------+ | I dread success. To have succeeded is to have finished one's | | business on earth... I like a state of continual becoming, | | with a goal in front and not behind. - George Bernard Shaw | +------------------------------------------------------------------+
msg00264/pgp00000.pgp
Description: PGP signature
