]> Cypherpunks.ru repositories - govpn.git/blob - cmd/govpn-server/udp.go
Raise copyright years
[govpn.git] / cmd / govpn-server / udp.go
1 /*
2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2020 Sergey Matveev <stargrave@stargrave.org>
4
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, version 3 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 package main
19
20 import (
21         "log"
22         "net"
23
24         "go.cypherpunks.ru/govpn/v7"
25 )
26
27 type UDPSender struct {
28         conn *net.UDPConn
29         addr *net.UDPAddr
30 }
31
32 func (c UDPSender) Write(data []byte) (int, error) {
33         return c.conn.WriteToUDP(data, c.addr)
34 }
35
36 var (
37         // Buffers for UDP parallel processing
38         udpBufs = make(chan []byte, 1<<8)
39 )
40
41 func startUDP() {
42         bind, err := net.ResolveUDPAddr("udp", *bindAddr)
43         if err != nil {
44                 log.Fatalln("Can not resolve bind address:", err)
45         }
46         conn, err := net.ListenUDP("udp", bind)
47         if err != nil {
48                 log.Fatalln("Can not listen on UDP:", err)
49         }
50         govpn.BothPrintf(`[udp-listen bind="%s"]`, *bindAddr)
51
52         udpBufs <- make([]byte, govpn.MTUMax)
53         go func() {
54                 var buf []byte
55                 var raddr *net.UDPAddr
56                 var addr string
57                 var n int
58                 var err error
59                 var exists bool
60                 var psI interface{}
61                 var ps *PeerState
62                 var hsI interface{}
63                 var hs *govpn.Handshake
64                 var addrPrevI interface{}
65                 var addrPrev string
66                 var peerPrevI interface{}
67                 var peerPrev *PeerState
68                 var peerID *govpn.PeerID
69                 var conf *govpn.PeerConf
70                 for {
71                         buf = <-udpBufs
72                         n, raddr, err = conn.ReadFromUDP(buf)
73                         if err != nil {
74                                 govpn.Printf(`[receive-failed bind="%s" err="%s"]`, *bindAddr, err)
75                                 break
76                         }
77                         addr = raddr.String()
78
79                         psI, exists = peers.Load(addr)
80                         if exists {
81                                 ps = psI.(*PeerState)
82                                 go func(peer *govpn.Peer, tap *govpn.TAP, buf []byte, n int) {
83                                         peer.PktProcess(buf[:n], tap, true)
84                                         udpBufs <- buf
85                                 }(ps.peer, ps.tap, buf, n)
86                                 continue
87                         }
88
89                         hsI, exists = handshakes.Load(addr)
90                         if !exists {
91                                 peerID = idsCache.Find(buf[:n])
92                                 if peerID == nil {
93                                         govpn.Printf(`[identity-unknown bind="%s" addr="%s"]`, *bindAddr, addr)
94                                         udpBufs <- buf
95                                         continue
96                                 }
97                                 conf = confs[*peerID]
98                                 if conf == nil {
99                                         govpn.Printf(
100                                                 `[conf-get-failed bind="%s" peer="%s"]`,
101                                                 *bindAddr, peerID.String(),
102                                         )
103                                         udpBufs <- buf
104                                         continue
105                                 }
106                                 hs := govpn.NewHandshake(
107                                         addr,
108                                         UDPSender{conn: conn, addr: raddr},
109                                         conf,
110                                 )
111                                 hs.Server(buf[:n])
112                                 udpBufs <- buf
113                                 handshakes.Store(addr, hs)
114                                 continue
115                         }
116
117                         hs = hsI.(*govpn.Handshake)
118                         peer := hs.Server(buf[:n])
119                         if peer == nil {
120                                 udpBufs <- buf
121                                 continue
122                         }
123                         govpn.Printf(
124                                 `[handshake-completed bind="%s" addr="%s" peer="%s"]`,
125                                 *bindAddr, addr, peerID.String(),
126                         )
127                         hs.Zero()
128                         handshakes.Delete(addr)
129
130                         go func() {
131                                 udpBufs <- make([]byte, govpn.MTUMax)
132                                 udpBufs <- make([]byte, govpn.MTUMax)
133                         }()
134                         addrPrevI, exists = peersByID.Load(*peer.ID)
135                         if exists {
136                                 addrPrev = addrPrevI.(string)
137                                 peerPrevI, exists = peers.Load(addrPrev)
138                                 if exists {
139                                         peerPrev = peerPrevI.(*PeerState)
140                                         exists = peerPrev == nil
141                                 }
142                         }
143                         if exists {
144                                 peerPrev.terminator <- struct{}{}
145                                 psNew := &PeerState{
146                                         peer:       peer,
147                                         tap:        peerPrev.tap,
148                                         terminator: make(chan struct{}),
149                                 }
150                                 go func(peer *govpn.Peer, tap *govpn.TAP, terminator chan struct{}) {
151                                         govpn.PeerTapProcessor(peer, tap, terminator)
152                                         <-udpBufs
153                                         <-udpBufs
154                                 }(psNew.peer, psNew.tap, psNew.terminator)
155                                 peers.Delete(addrPrev)
156                                 peers.Store(addr, psNew)
157                                 knownPeers.Delete(addrPrev)
158                                 knownPeers.Store(addr, &peer)
159                                 peersByID.Store(*peer.ID, addr)
160                                 govpn.Printf(
161                                         `[rehandshake-completed bind="%s" peer="%s"]`,
162                                         *bindAddr, peer.ID.String(),
163                                 )
164                         } else {
165                                 go func(addr string, peer *govpn.Peer) {
166                                         ifaceName, err := callUp(peer.ID, peer.Addr)
167                                         if err != nil {
168                                                 return
169                                         }
170                                         tap, err := govpn.TAPListen(ifaceName, peer.MTU)
171                                         if err != nil {
172                                                 govpn.Printf(
173                                                         `[tap-failed bind="%s" peer="%s" err="%s"]`,
174                                                         *bindAddr, peer.ID.String(), err,
175                                                 )
176                                                 return
177                                         }
178                                         psNew := &PeerState{
179                                                 peer:       peer,
180                                                 tap:        tap,
181                                                 terminator: make(chan struct{}),
182                                         }
183                                         go func(peer *govpn.Peer, tap *govpn.TAP, terminator chan struct{}) {
184                                                 govpn.PeerTapProcessor(peer, tap, terminator)
185                                                 <-udpBufs
186                                                 <-udpBufs
187                                         }(psNew.peer, psNew.tap, psNew.terminator)
188                                         peers.Store(addr, psNew)
189                                         knownPeers.Store(addr, &peer)
190                                         peersByID.Store(*peer.ID, addr)
191                                         govpn.Printf(
192                                                 `[peer-created bind="%s" peer="%s"]`,
193                                                 *bindAddr,
194                                                 peer.ID.String(),
195                                         )
196                                 }(addr, peer)
197                         }
198                         udpBufs <- buf
199                 }
200         }()
201 }