Răsfoiți Sursa

Changes to "common" to support new "tun" package

Rod Hynes 8 ani în urmă
părinte
comite
1d623f59d6
3 a modificat fișierele cu 98 adăugiri și 37 ștergeri
  1. 44 0
      psiphon/common/logger.go
  2. 38 33
      psiphon/common/networkInterface.go
  3. 16 4
      psiphon/controller.go

+ 44 - 0
psiphon/common/logger.go

@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, Psiphon Inc.
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package common
+
+// Logger exposes a logging interface that's compatible with
+// psiphon/server.ContextLogger. This interface allows packages
+// to implement logging that will integrate with psiphon/server
+// without importing that package. Other implementations of
+// Logger may also be provided.
+type Logger interface {
+	WithContext() LogContext
+	WithContextFields(fields LogFields) LogContext
+	LogMetric(metric string, fields LogFields)
+}
+
+// LogContext is interface-compatible with the return values from
+// psiphon/server.ContextLogger.WithContext/WithContextFields.
+type LogContext interface {
+	Debug(message string)
+	Info(message string)
+	Warning(message string)
+	Error(message string)
+}
+
+// LogFields is type-compatible with psiphon/server.LogFields
+// and logrus.LogFields.
+type LogFields map[string]interface{}

+ 38 - 33
psiphon/common/networkInterface.go

@@ -20,48 +20,53 @@
 package common
 
 import (
-	"errors"
+	"fmt"
 	"net"
 )
 
-// Take in an interface name ("lo", "eth0", "any") passed from either
-// a config setting, by using the -listenInterface flag on client or
-// -interface flag on server from the command line and return the IP
-// address associated with it.
-// If no interface is provided use the default loopback interface (127.0.0.1).
-// If "any" is passed then listen on 0.0.0.0 for client (invalid with server)
-func GetInterfaceIPAddress(listenInterface string) (string, error) {
-	var ip net.IP
-	if listenInterface == "" {
-		ip = net.ParseIP("127.0.0.1")
-		return ip.String(), nil
-	} else if listenInterface == "any" {
-		ip = net.ParseIP("0.0.0.0")
-		return ip.String(), nil
-	} else {
-		availableInterfaces, err := net.InterfaceByName(listenInterface)
-		if err != nil {
-			return "", ContextError(err)
-		}
+// GetInterfaceIPAddress takes an interface name, such as "eth0", and returns
+// the first IPv4 and IPv6 addresses associated with it. Either of the IPv4 or
+// IPv6 address may be nil. If neither type of address is found, an error
+// is returned.
+func GetInterfaceIPAddresses(interfaceName string) (net.IP, net.IP, error) {
+
+	var IPv4Address, IPv6Address net.IP
+
+	availableInterfaces, err := net.InterfaceByName(interfaceName)
+	if err != nil {
+		return nil, nil, ContextError(err)
+	}
+
+	addrs, err := availableInterfaces.Addrs()
+	if err != nil {
+		return nil, nil, ContextError(err)
+	}
 
-		addrs, err := availableInterfaces.Addrs()
-		if err != nil {
-			return "", ContextError(err)
+	for _, addr := range addrs {
+
+		ipNet := addr.(*net.IPNet)
+		if ipNet == nil {
+			continue
 		}
-		for _, addr := range addrs {
-			iptype := addr.(*net.IPNet)
-			if iptype == nil {
-				continue
+
+		if ipNet.IP.To4() != nil {
+			if IPv4Address == nil {
+				IPv4Address = ipNet.IP
 			}
-			// TODO: IPv6 support
-			ip = iptype.IP.To4()
-			if ip == nil {
-				continue
+		} else {
+			if IPv6Address == nil {
+				IPv6Address = ipNet.IP
 			}
-			return ip.String(), nil
+		}
+
+		if IPv4Address != nil && IPv6Address != nil {
+			break
 		}
 	}
 
-	return "", ContextError(errors.New("Could not find IP address of specified interface"))
+	if IPv4Address != nil || IPv6Address != nil {
+		return IPv4Address, IPv6Address, nil
+	}
 
+	return nil, nil, ContextError(fmt.Errorf("Could not find any IP address for interface %s", interfaceName))
 }

+ 16 - 4
psiphon/controller.go

@@ -159,10 +159,22 @@ func (controller *Controller) Run(shutdownBroadcast <-chan struct{}) {
 
 	// Start components
 
-	listenIP, err := common.GetInterfaceIPAddress(controller.config.ListenInterface)
-	if err != nil {
-		NoticeError("error getting listener IP: %s", err)
-		return
+	// TODO: IPv6 support
+	var listenIP string
+	if controller.config.ListenInterface == "" {
+		listenIP = "127.0.0.1"
+	} else if controller.config.ListenInterface == "any" {
+		listenIP = "0.0.0.0"
+	} else {
+		IPv4Address, IPv6Address, err := common.GetInterfaceIPAddresses(controller.config.ListenInterface)
+		if err == nil && IPv4Address == nil {
+			err = fmt.Errorf("no IPv4 address for interface %s", controller.config.ListenInterface)
+		}
+		if err != nil {
+			NoticeError("error getting listener IP: %s", err)
+			return
+		}
+		listenIP = IPv4Address.String()
 	}
 
 	socksProxy, err := NewSocksProxy(controller.config, controller, listenIP)