Browse Source

Added further IPv6 support. Also, revisions based on feedback.

Miro Kuratczyk 9 years ago
parent
commit
47666a9fd1
3 changed files with 44 additions and 27 deletions
  1. 30 12
      psiphon/LookupIP.go
  2. 4 0
      psiphon/TCPConn.go
  3. 10 15
      psiphon/TCPConn_bind.go

+ 30 - 12
psiphon/LookupIP.go

@@ -69,7 +69,28 @@ func bindLookupIP(host, dnsServer string, config *DialConfig) (addrs []net.IP, e
 		return []net.IP{ipAddr}, nil
 	}
 
-	socketFd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0)
+	// config.DnsServerGetter.GetDnsServers() must return IP addresses
+	ipAddr = net.ParseIP(dnsServer)
+	if ipAddr == nil {
+		return nil, common.ContextError(errors.New("invalid IP address"))
+	}
+
+	var ipv4 [4]byte
+	var ipv6 [16]byte
+	var domain int
+
+	// Get address type (IPv4 or IPv6)
+	if ipAddr.To4() != nil {
+		copy(ipv4[:], ipAddr.To4())
+		domain = syscall.AF_INET
+	} else if ipAddr.To16() != nil {
+		copy(ipv6[:], ipAddr.To16())
+		domain = syscall.AF_INET6
+	} else {
+		return nil, common.ContextError(fmt.Errorf("Got invalid IP address for dns server: %s", ipAddr.String()))
+	}
+
+	socketFd, err := syscall.Socket(domain, syscall.SOCK_DGRAM, 0)
 	if err != nil {
 		return nil, common.ContextError(err)
 	}
@@ -80,18 +101,15 @@ func bindLookupIP(host, dnsServer string, config *DialConfig) (addrs []net.IP, e
 		return nil, common.ContextError(fmt.Errorf("BindToDevice failed: %s", err))
 	}
 
-	// config.DnsServerGetter.GetDnsServers() must return IP addresses
-	ipAddr = net.ParseIP(dnsServer)
-	if ipAddr == nil {
-		return nil, common.ContextError(errors.New("invalid IP address"))
-	}
-
-	// TODO: IPv6 support
-	var ip [4]byte
-	copy(ip[:], ipAddr.To4())
-	sockAddr := syscall.SockaddrInet4{Addr: ip, Port: DNS_PORT}
+	// Connect socket to the server's IP address
 	// Note: no timeout or interrupt for this connect, as it's a datagram socket
-	err = syscall.Connect(socketFd, &sockAddr)
+	if domain == syscall.AF_INET {
+		sockAddr := syscall.SockaddrInet4{Addr: ipv4, Port: DNS_PORT}
+		err = syscall.Connect(socketFd, &sockAddr)
+	} else if domain == syscall.AF_INET6 {
+		sockAddr := syscall.SockaddrInet6{Addr: ipv6, Port: DNS_PORT}
+		err = syscall.Connect(socketFd, &sockAddr)
+	}
 	if err != nil {
 		return nil, common.ContextError(err)
 	}

+ 4 - 0
psiphon/TCPConn.go

@@ -118,6 +118,10 @@ func interruptibleTCPDial(addr string, config *DialConfig) (*TCPConn, error) {
 			ip := net.ParseIP(host)
 			if ip != nil && ip.To4() != nil {
 				synthesizedAddr := config.IPv6Synthesizer.IPv6Synthesize(host)
+				// If IPv6Synthesize fails we will try dialing with the
+				// original IPv4 address instead of logging an error. If
+				// the address is unreachable an error will be emitted
+				// from tcpDial.
 				if synthesizedAddr != "" {
 					addr = net.JoinHostPort(synthesizedAddr, port)
 				}

+ 10 - 15
psiphon/TCPConn_bind.go

@@ -78,21 +78,20 @@ func tcpDial(addr string, config *DialConfig, dialResult chan error) (net.Conn,
 		return nil, common.ContextError(err)
 	}
 
-	var ip []byte
+	var ipv4 [4]byte
+	var ipv6 [16]byte
 	var domain int
 	ipAddr := ipAddrs[index]
 
 	// Get address type (IPv4 or IPv6)
 	if ipAddr != nil && ipAddr.To4() != nil {
-		ip = make([]byte, 4)
-		copy(ip, ipAddr.To4())
+		copy(ipv4[:], ipAddr.To4())
 		domain = syscall.AF_INET
 	} else if ipAddr != nil && ipAddr.To16() != nil {
-		ip = make([]byte, 16)
-		copy(ip, ipAddr.To16())
+		copy(ipv6[:], ipAddr.To16())
 		domain = syscall.AF_INET6
 	} else {
-		return nil, common.ContextError(fmt.Errorf("Got invalid ip address: %s", ipAddr.String()))
+		return nil, common.ContextError(fmt.Errorf("Got invalid IP address: %s", ipAddr.String()))
 	}
 
 	// Create a socket and bind to device, when configured to do so
@@ -113,17 +112,13 @@ func tcpDial(addr string, config *DialConfig, dialResult chan error) (net.Conn,
 		}
 	}
 
-	// Connect socket fd to the address
+	// Connect socket to the server's IP address
 	if domain == syscall.AF_INET {
-		var inet4Addr [4]byte
-		copy(inet4Addr[:], ip)
-		servAddr := syscall.SockaddrInet4{Addr: inet4Addr, Port: port}
-		err = syscall.Connect(socketFd, &servAddr)
+		sockAddr := syscall.SockaddrInet4{Addr: ipv4, Port: port}
+		err = syscall.Connect(socketFd, &sockAddr)
 	} else if domain == syscall.AF_INET6 {
-		var inet6Addr [16]byte
-		copy(inet6Addr[:], ip)
-		servAddr := syscall.SockaddrInet6{Addr: inet6Addr, Port: port}
-		err = syscall.Connect(socketFd, &servAddr)
+		sockAddr := syscall.SockaddrInet6{Addr: ipv6, Port: port}
+		err = syscall.Connect(socketFd, &sockAddr)
 	}
 	if err != nil {
 		syscall.Close(socketFd)