]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/common.go
002b1fbfd43a55ba72c8a6704b93abd550dbb86f
[govpn.git] / src / cypherpunks.ru / govpn / common.go
1 /*
2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2017 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, either version 3 of the License, or
8 (at your option) any later version.
9
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.
14
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/>.
17 */
18
19 package govpn
20
21 import (
22         "encoding/hex"
23         "encoding/json"
24         "io"
25         "os"
26         "os/signal"
27         "runtime"
28         "strings"
29         "time"
30
31         "github.com/Sirupsen/logrus"
32         "github.com/pkg/errors"
33 )
34
35 const (
36         // ProtocolUDP is UDP transport protocol
37         ProtocolUDP Protocol = iota
38         // ProtocolTCP is TCP transport protocol
39         ProtocolTCP
40         // ProtocolALL is TCP+UDP transport protocol
41         ProtocolALL
42
43         etherSize = 14
44         // MTUMax is maximum MTU size of Ethernet packet
45         MTUMax = 9000 + etherSize + 1
46         // MTUDefault is default MTU size of Ethernet packet
47         MTUDefault = 1500 + etherSize + 1
48
49         environmentKeyInterface = "GOVPN_IFACE"
50         environmentKeyRemote    = "GOVPN_REMOTE"
51
52         wrapIoReadFull            = "io.ReadFull %q"
53         wrapBlake2bNew256         = "blake2b.New256"
54         wrapEnclessDecode         = "EnclessDecode"
55         wrapEnclessEncode         = "EnclessEncode"
56         wrapNewProtocolFromString = "NewProtocolFromString"
57 )
58
59 var (
60         // Version holds release string set at build time
61         Version      string
62         protocolText = map[Protocol]string{
63                 ProtocolUDP: "udp",
64                 ProtocolTCP: "tcp",
65                 ProtocolALL: "all",
66         }
67         logger        = logrus.StandardLogger()
68         logFuncPrefix = "govpn."
69         // TimeoutDefault is default timeout value for various network operations
70         TimeoutDefault = 60 * time.Second
71 )
72
73 // Protocol is a GoVPN supported protocol: either UDP, TCP or both
74 type Protocol int
75
76 // String converts a Protocol into a string
77 func (p Protocol) String() string {
78         return protocolText[p]
79 }
80
81 // MarshalJSON returns a JSON string from a protocol
82 func (p Protocol) MarshalJSON() ([]byte, error) {
83         str := p.String()
84         output, err := json.Marshal(&str)
85         return output, errors.Wrap(err, "json.Marshal")
86 }
87
88 // UnmarshalJSON converts a JSON string into a Protocol
89 func (p *Protocol) UnmarshalJSON(encoded []byte) error {
90         var str string
91         if err := json.Unmarshal(encoded, &str); err != nil {
92                 return errors.Wrapf(err, "Can't unmarshall to string %q", hex.EncodeToString(encoded))
93         }
94         proto, err := NewProtocolFromString(str)
95         if err != nil {
96                 return errors.Wrap(err, wrapNewProtocolFromString)
97         }
98         *p = proto
99         return nil
100 }
101
102 // UnmarshalYAML converts a YAML string into a Protocol
103 func (p *Protocol) UnmarshalYAML(unmarshal func(interface{}) error) error {
104         var str string
105         err := unmarshal(&str)
106         if err != nil {
107                 return errors.Wrap(err, "unmarshall")
108         }
109
110         proto, err := NewProtocolFromString(str)
111         if err != nil {
112                 return errors.Wrap(err, wrapNewProtocolFromString)
113         }
114         *p = proto
115         return nil
116 }
117
118 // NewProtocolFromString converts a string into a govpn.Protocol
119 func NewProtocolFromString(p string) (Protocol, error) {
120         lowP := strings.ToLower(p)
121         for k, v := range protocolText {
122                 if strings.ToLower(v) == lowP {
123                         return k, nil
124                 }
125         }
126
127         choices := make([]string, len(protocolText))
128         var index = 0
129         for k, v := range protocolText {
130                 if v == p {
131                         z := k
132                         p = &z
133                         return nil
134                 }
135                 choices[index] = v
136                 index++
137         }
138
139         return Protocol(-1), errors.Errorf("Invalid protocol %q: %s", p, strings.Join(choices, ","))
140 }
141
142 // SliceZero zeros each byte.
143 func SliceZero(data []byte) {
144         for i := 0; i < len(data); i++ {
145                 data[i] = 0
146         }
147 }
148
149 // VersionGet returns version of GoVPN
150 func VersionGet() string {
151         return "GoVPN version " + Version + " built with " + runtime.Version()
152 }
153
154 // CatchSignalShutdown returns a channel.
155 // that channel will get a SIG_INT or SIG_KILL signal is received
156 // this is intended to be used to stop a client/server
157 func CatchSignalShutdown() chan interface{} {
158         shutdownChan := make(chan interface{}, 1)
159         go func() {
160                 termSignal := make(chan os.Signal, 1)
161                 signal.Notify(termSignal, os.Interrupt, os.Kill)
162                 sig := <-termSignal
163                 logger.WithFields(logrus.Fields{
164                         "func":   logFuncPrefix + "CatchSignalShutdown",
165                         "signal": sig.String(),
166                 }).Debug("Catch signal, shutting down")
167                 shutdownChan <- sig
168         }()
169         return shutdownChan
170 }
171
172 // SetLogger set the Logger used by this library.
173 // by default logrus StdLogger is used.
174 func SetLogger(l *logrus.Logger) {
175         logger = l
176 }
177
178 // CloseLog log an error if a io.Closer fail to Close
179 func CloseLog(c io.Closer, l *logrus.Logger, fields logrus.Fields) {
180         if err := c.Close(); err != nil {
181                 logrus.WithFields(fields).WithError(err).Error("Couldn't close connection")
182         }
183 }