]> Cypherpunks.ru repositories - govpn.git/blobdiff - src/cypherpunks.ru/govpn/cmd/govpn-client/main.go
Refactor govpn-client.
[govpn.git] / src / cypherpunks.ru / govpn / cmd / govpn-client / main.go
index 36ff72a113e6ac0db3e809e90af6954fb57f9f6c..df426ba8820c45bac23d84d83a21e814cf6e5540 100644 (file)
@@ -23,46 +23,41 @@ import (
        "flag"
        "fmt"
        "log"
-       "net"
        "os"
        "os/signal"
        "time"
 
        "cypherpunks.ru/govpn"
-)
-
-var (
-       remoteAddr  = flag.String("remote", "", "Remote server address")
-       proto       = flag.String("proto", "udp", "Protocol to use: udp or tcp")
-       ifaceName   = flag.String("iface", "tap0", "TUN/TAP network interface")
-       verifierRaw = flag.String("verifier", "", "Verifier")
-       keyPath     = flag.String("key", "", "Path to passphrase file")
-       upPath      = flag.String("up", "", "Path to up-script")
-       downPath    = flag.String("down", "", "Path to down-script")
-       stats       = flag.String("stats", "", "Enable stats retrieving on host:port")
-       proxyAddr   = flag.String("proxy", "", "Use HTTP proxy on host:port")
-       proxyAuth   = flag.String("proxy-auth", "", "user:password Basic proxy auth")
-       mtu         = flag.Int("mtu", govpn.MTUDefault, "MTU of TUN/TAP interface")
-       timeoutP    = flag.Int("timeout", 60, "Timeout seconds")
-       timeSync    = flag.Int("timesync", 0, "Time synchronization requirement")
-       noreconnect = flag.Bool("noreconnect", false, "Disable reconnection after timeout")
-       noisy       = flag.Bool("noise", false, "Enable noise appending")
-       encless     = flag.Bool("encless", false, "Encryptionless mode")
-       cpr         = flag.Int("cpr", 0, "Enable constant KiB/sec out traffic rate")
-       egdPath     = flag.String("egd", "", "Optional path to EGD socket")
-       syslog      = flag.Bool("syslog", false, "Enable logging to syslog")
-       version     = flag.Bool("version", false, "Print version information")
-       warranty    = flag.Bool("warranty", false, "Print warranty information")
-
-       conf        *govpn.PeerConf
-       tap         *govpn.TAP
-       timeout     int
-       firstUpCall bool = true
-       knownPeers  govpn.KnownPeers
-       idsCache    *govpn.MACCache
+       "cypherpunks.ru/govpn/client"
 )
 
 func main() {
+       var (
+               remoteAddr  = flag.String("remote", "", "Remote server address")
+               proto       = flag.String("proto", "udp", "Protocol to use: udp or tcp")
+               ifaceName   = flag.String("iface", "tap0", "TUN/TAP network interface")
+               verifierRaw = flag.String("verifier", "", "Verifier")
+               keyPath     = flag.String("key", "", "Path to passphrase file")
+               upPath      = flag.String("up", "", "Path to up-script")
+               downPath    = flag.String("down", "", "Path to down-script")
+               stats       = flag.String("stats", "", "Enable stats retrieving on host:port")
+               proxyAddr   = flag.String("proxy", "", "Use HTTP proxy on host:port")
+               proxyAuth   = flag.String("proxy-auth", "", "user:password Basic proxy auth")
+               mtu         = flag.Int("mtu", govpn.MTUDefault, "MTU of TUN/TAP interface")
+               timeoutP    = flag.Int("timeout", 60, "Timeout seconds")
+               timeSync    = flag.Int("timesync", 0, "Time synchronization requirement")
+               noreconnect = flag.Bool("noreconnect", false, "Disable reconnection after timeout")
+               noisy       = flag.Bool("noise", false, "Enable noise appending")
+               encless     = flag.Bool("encless", false, "Encryptionless mode")
+               cpr         = flag.Int("cpr", 0, "Enable constant KiB/sec out traffic rate")
+               egdPath     = flag.String("egd", "", "Optional path to EGD socket")
+               syslog      = flag.Bool("syslog", false, "Enable logging to syslog")
+               version     = flag.Bool("version", false, "Print version information")
+               warranty    = flag.Bool("warranty", false, "Print warranty information")
+               protocol client.Protocol
+               err error
+       )
+
        flag.Parse()
        if *warranty {
                fmt.Println(govpn.Warranty)
@@ -72,72 +67,78 @@ func main() {
                fmt.Println(govpn.VersionGet())
                return
        }
-       timeout = *timeoutP
-       var err error
        log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
 
-       if *mtu > govpn.MTUMax {
-               log.Fatalln("Maximum allowable MTU is", govpn.MTUMax)
-       }
        if *egdPath != "" {
                log.Println("Using", *egdPath, "EGD")
                govpn.EGDInit(*egdPath)
        }
 
-       if *proxyAddr != "" {
-               *proto = "tcp"
-       }
-       if !(*proto == "udp" || *proto == "tcp") {
+       switch *proto {
+       case "udp":
+               protocol = client.ProtocolUDP
+       case "tcp":
+               protocol = client.ProtocolTCP
+       default:
                log.Fatalln("Unknown protocol specified")
        }
+
+       if *proxyAddr != "" && protocol == client.ProtocolUDP {
+               log.Println("Proxy is supported for TCP only, switch")
+               protocol = client.ProtocolTCP
+       }
+
        if *verifierRaw == "" {
-               log.Fatalln("No verifier specified")
+               log.Fatalln("-verifier is required")
        }
        verifier, err := govpn.VerifierFromString(*verifierRaw)
        if err != nil {
-               log.Fatalln(err)
+               log.Fatalln("Invalid -verifier:", err)
        }
        key, err := govpn.KeyRead(*keyPath)
        if err != nil {
-               log.Fatalln("Unable to read the key", err)
+               log.Fatalln("Invalid -key:", err)
        }
        priv := verifier.PasswordApply(key)
        if *encless {
-               if *proto != "tcp" {
+               if protocol != client.ProtocolTCP {
                        log.Fatalln("Currently encryptionless mode works only with TCP")
                }
-               *noisy = true
+               if !*noisy {
+                       log.Println("-encless is on, force -noisy mode")
+                       *noisy = true
+               }
        }
-       conf = &govpn.PeerConf{
-               Id:       verifier.Id,
-               Iface:    *ifaceName,
-               MTU:      *mtu,
-               Timeout:  time.Second * time.Duration(timeout),
-               TimeSync: *timeSync,
-               Noise:    *noisy,
-               CPR:      *cpr,
-               Encless:  *encless,
-               Verifier: verifier,
-               DSAPriv:  priv,
+       conf := client.Configuration{
+               PrivateKey: priv,
+               Peer: &govpn.PeerConf{
+                       Id:       verifier.Id,
+                       Iface:    *ifaceName,
+                       MTU:      *mtu,
+                       Timeout:  time.Second * time.Duration(*timeoutP),
+                       TimeSync: *timeSync,
+                       Noise:    *noisy,
+                       CPR:      *cpr,
+                       Encless:  *encless,
+                       Verifier: verifier,
+                       DSAPriv:  priv,
+               },
+               Protocol: protocol,
+               InterfaceName: *ifaceName,
+               ProxyAddress: *proxyAddr,
+               ProxyAuthentication: *proxyAuth,
+               RemoteAddress: *remoteAddr,
+               UpPath: *upPath,
+               DownPath: *downPath,
+               StatsAddress: *stats,
+               NoReconnect: *noreconnect,
+               MTU: *mtu,
        }
-       idsCache = govpn.NewMACCache()
-       confs := map[govpn.PeerId]*govpn.PeerConf{*verifier.Id: conf}
-       idsCache.Update(&confs)
-       log.Println(govpn.VersionGet())
-
-       tap, err = govpn.TAPListen(*ifaceName, *mtu)
-       if err != nil {
-               log.Fatalln("Can not listen on TUN/TAP interface:", err)
+       if err = conf.Validate(); err != nil {
+               log.Fatalln("Invalid settings:", err)
        }
 
-       if *stats != "" {
-               log.Println("Stats are going to listen on", *stats)
-               statsPort, err := net.Listen("tcp", *stats)
-               if err != nil {
-                       log.Fatalln("Can not listen on stats port:", err)
-               }
-               go govpn.StatsProcessor(statsPort, &knownPeers)
-       }
+       log.Println(govpn.VersionGet())
 
        if *syslog {
                govpn.SyslogEnable()
@@ -145,38 +146,11 @@ func main() {
 
        termSignal := make(chan os.Signal, 1)
        signal.Notify(termSignal, os.Interrupt, os.Kill)
-
-MainCycle:
-       for {
-               timeouted := make(chan struct{})
-               rehandshaking := make(chan struct{})
-               termination := make(chan struct{})
-               switch *proto {
-               case "udp":
-                       go startUDP(timeouted, rehandshaking, termination)
-               case "tcp":
-                       if *proxyAddr != "" {
-                               go proxyTCP(timeouted, rehandshaking, termination)
-                       } else {
-                               go startTCP(timeouted, rehandshaking, termination)
-                       }
-               }
-               select {
-               case <-termSignal:
-                       govpn.BothPrintf(`[finish remote="%s"]`, *remoteAddr)
-                       termination <- struct{}{}
-                       break MainCycle
-               case <-timeouted:
-                       if *noreconnect {
-                               break MainCycle
-                       }
-                       govpn.BothPrintf(`[sleep seconds="%d"]`, timeout)
-                       time.Sleep(time.Second * time.Duration(timeout))
-               case <-rehandshaking:
-               }
-               close(timeouted)
-               close(rehandshaking)
-               close(termination)
+       c := client.NewClient(conf, verifier, termSignal)
+       go c.MainCycle()
+       if err := <-c.Error; err != nil {
+               log.Fatalln(err)
+       } else {
+               log.Println("Closed VPN tunnel")
        }
-       govpn.ScriptCall(*downPath, *ifaceName, *remoteAddr)
 }