See also HowToEnableIpvSix .
The Rules
- Do not write code to create or parse sinful strings. Sinful strings are now weird and complex beasts and you will almost certainly miss important edge cases. Use the existing interfaces. You probably want condor_sockaddr::to_sinful or condor_sockaddr::from_sinful.
- Do not use sockaddr_in or sockaddr_in6. condor_sockaddr exists specifically to shield you from needing to worry about those. Functions which take sockaddr_in or sockaddr_in6 will generally have a condor_X version which takes a condor_sockaddr instead.
The Big Picture
condor_sockaddr
/src/condor_includes/condor_sockaddr.h
The data structure holding information about a IP address/port pair is condor_sockaddr
, which handles juggling sockaddr_in and sockaddr_in6. You shouldn't worry if a given address is IPv6 or IPv4, just use the condor_sockaddr opaquely. If you need a textual but still opaque representation, use condor_sockaddr::to_sinful and condor_sockaddr::from_sinful to create and parse sinful strings. Sinful string are human readable and thus appropriate to use in log messages.
IPv6 addresses require a scope id, identifying which network interface to use. This solves the problem of a single machine being part of two or more private ("link local") networks using the same address space. However, it just creates a new problem: if all you have is an IP address, how do you know which interface to use. The answer: we have no idea. Some tools allow the user to specify the scope ID in a variety of inconsistent ways. This is why NETWORK_INTERFACE is required for IPv6; we use the NETWORK_INTERFACE to identify the scope ID.
condor_netaddr
/src/condor_includes/condor_netaddr.h
condor_netaddr
exists to encapsulate the idea of a subnet. It's built on top of condor_sockaddr, adding a count for how many bits to mask off. At the moment it's only being used to validate that a subset string can be parsed, but should eventually be used in any situation where HTCondor is checking that a given address is within a given subset (ie security).
Conversions
All conversions should go through condor_sockaddr. Since you should be using condor_sockaddr internally whenever possible, direct conversion (eg hostname to IP address as a string) should be rare enough that direct functions are unnecessary.
hostname to condor_sockaddr
resolve_hostname() in /src/condor_includes/ipv6_hostname.h takes a hostname (MyString or const char *), and returns a std::vector<condor_sockaddr>.
Note that all of the returned condor_sockaddrs are correct! To be properly behaved, you should try them, in order, until you find one that works, or you run out of options.
sinful string to condor_sockaddr
condor_sockaddr::from_sinful() in /src/condor_includes/condor_sockaddr.h
IP address (as a string) to condor_sockaddr
resolve_hostname() in /src/condor_includes/ipv6_hostname.h can transform IPv4 and IPv6 addresses into condor_sockaddrs as well as looking up hostnames. Use these. This can not parse attached ports, square brackets around an IPv6 address, nor IPv4 addresses in any form other than dotted decimal.
in_addr, in6_addr, sockaddr_in, or sockaddr_in6 to condor_sockaddr
You probably shouldn't have one of these in the first place. Assuming you started with a hostname, an IP address, or a sinful string, you should have gone straight to a condor_sockaddr. But if you absolutely must, condor_sockaddr's constructors can take these. /src/condor_includes/condor_sockaddr.h
condor_sockaddr to hostname
get_hostname() in /src/condor_includes/ipv6_hostname.h takes a condor_sockaddr and returns a hostname (MyString). If you want aliases as well, get_hostname_with_alias will return a std::vector<MyString> of hostnames.
condor_sockaddr to sinful string
condor_sockaddr::to_sinful() in /src/condor_includes/condor_sockaddr.h
condor_sockaddr to IP address (as a string)
You almost certainly don't want this. If you're looking for something to pass between daemons, perhaps in a ClassAd or on a command line, use a sinful string. If you're looking for something to put into a log or error message, still use a sinful string. While officially opaque, they are also designed to be human readable enough to be useful in log messages, and using the sinful string ensures that no information is lost. If you absolutely must (perhaps to pass it to a non-HTCondor program) use condor_sockaddr::to_ip_string() and condor_sockaddr::to_ip_string() in /src/condor_includes/condor_sockaddr.h
condor_sockaddr to sockaddr_in or sockaddr_in6
You almost certainly don't want this. Any function you want to call with a sockaddr_in or sockaddr_in6 probably has a condor_X equivalent that takes a condor_sockaddr; use that instead. For example instead of bind() and accept(), use condor_bind() and condor_accept(). If a condor_X equivalent doesn't exist, consider adding one. If you absolutely must, look to condor_sockaddr::is_ipv4() and condor_sockaddr::is_ipv6() to identify what type of address it is, and condor_sockaddr::to_sin() and condor_sockaddr::to_sin6() to retrieve sockaddr_in and sockaddr_in6 resepectively. /src/condor_includes/condor_sockaddr.h