2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 "github.com/pkg/errors"
28 "cypherpunks.ru/govpn"
31 func (c *Client) startUDP() {
32 l := c.logger.WithField("func", "startUDP")
34 // TODO move resolution into the loop, as the name might change over time
35 l.Debug("Resolve UDP address")
36 remote, err := net.ResolveUDPAddr("udp", c.config.RemoteAddress)
38 c.Error <- errors.Wrapf(err, "net.ResolveUDPAddr %s", c.config.RemoteAddress)
41 l.WithField("remote", remote.String()).Debug("dial")
42 conn, err := net.DialUDP("udp", nil, remote)
44 c.Error <- errors.Wrapf(err, "net.DialUDP %s", c.config.RemoteAddress)
47 l.WithFields(c.config.LogFields()).Info("Connected")
49 l.Debug("Handshake start")
50 hs, err := govpn.HandshakeStart(c.config.RemoteAddress, conn, c.config.Peer)
52 govpn.CloseLog(conn, c.logger, c.LogFields())
53 c.Error <- errors.Wrap(err, "govpn.HandshakeStart")
56 l.Debug("Handshake done")
58 buf := make([]byte, c.config.Peer.MTU*2)
62 var deadLine time.Time
63 var terminator chan struct{}
64 timeout := int(c.config.Peer.Timeout.Seconds())
75 deadLine = time.Now().Add(time.Second)
76 if err = conn.SetReadDeadline(deadLine); err != nil {
77 c.Error <- errors.Wrapf(err, "conn.SetReadDeadline %s", deadLine.String())
81 n, err = conn.Read(buf)
82 if timeouts >= timeout {
83 l.WithFields(c.LogFields()).Debug("Connection timeouted")
84 c.timeouted <- struct{}{}
88 l.WithError(err).WithFields(c.LogFields()).Debug("Can't read from connection")
93 c.logger.WithFields(c.LogFields()).Debug("No peer yet, process packet")
94 if peer.PktProcess(buf[:n], c.tap, true) {
95 l.WithFields(c.LogFields()).Debug("Packet processed")
98 l.WithFields(c.LogFields()).Debug("Packet unauthenticated")
101 if atomic.LoadUint64(&peer.BytesIn)+atomic.LoadUint64(&peer.BytesOut) > govpn.MaxBytesPerKey {
102 l.WithFields(c.LogFields()).Debug("Rehandshake required")
103 c.rehandshaking <- struct{}{}
108 if _, err = c.idsCache.Find(buf[:n]); err != nil {
109 l.WithError(err).WithFields(c.LogFields()).Debug("Identity invalid")
113 peer, err = hs.Client(buf[:n])
115 c.Error <- errors.Wrap(err, "hs.Client")
118 // no error, but handshake not yet completed
122 l.WithFields(c.LogFields()).Info("Handshake completed")
123 c.knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{c.config.RemoteAddress: &peer})
124 if err = c.postUpAction(); err != nil {
125 c.Error <- errors.Wrap(err, "c.postUpAction")
129 terminator = make(chan struct{})
130 go govpn.PeerTapProcessor(peer, c.tap, terminator)
132 if terminator != nil {
133 terminator <- struct{}{}
138 if err = conn.Close(); err != nil {
139 c.Error <- errors.Wrap(err, "conn.Close")
141 if err = c.tap.Close(); err != nil {
142 c.Error <- errors.Wrap(err, logFuncPrefix+"Client.tap.Close")