 
 //When strict typing meets a crufty API...
 
-extension in6_addr : CustomStringConvertible {
+extension in6_addr : Equatable, CustomStringConvertible {
     public var description: String {
         var str = [CChar](repeating: 0, count: Int(INET6_ADDRSTRLEN))
         var mself = self
         inet_ntop(AF_INET6, &mself, &str, socklen_t(str.count))
         return String(cString: str)
+    }
+    
+    public static func ==(lhs: in6_addr, rhs: in6_addr) -> Bool {
+        return lhs.bytes == rhs.bytes
     }
 
     static let any = in6_addr(bytes: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])



///Extension to reduce the pain of working with sockaddr_in6
extension sockaddr_in6 : CustomDebugStringConvertible {

    public var debugDescription: String {
        return "\(sin6_addr) / \(self.port)"
    }

    ///Port number, reflecting sin6_port
    public var port: UInt16 {
        get { return sin6_port.bigEndian }
        set { sin6_port = newValue.bigEndian }
    }

    public var valid: Bool {

        switch ai.ai_family {
            case AF_INET6:
                guard Int(ai.ai_addrlen) == sizeof(sockaddr_in6.self) else { return nil }
                self.init()
                guard let sa6 = UnsafePointer<sockaddr_in6>(ai.ai_addr) else { return nil }
                self = sa6.pointee
                self.sin6_family = sa_family_t(AF_INET6)
                self.sin6_len = UInt8(sizeof(sockaddr_in6.self))

            case AF_INET:
                guard Int(ai.ai_addrlen) == sizeof(sockaddr_in.self) else { return nil }
