]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/common.go
fix copy-paste
[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(
93                         err,
94                         "Can't unmarshall to string %q",
95                         hex.EncodeToString(encoded),
96                 )
97         }
98         proto, err := NewProtocolFromString(str)
99         if err != nil {
100                 return errors.Wrap(err, wrapNewProtocolFromString)
101         }
102         *p = proto
103         return nil
104 }
105
106 // UnmarshalYAML converts a YAML string into a Protocol
107 func (p *Protocol) UnmarshalYAML(unmarshal func(interface{}) error) error {
108         var str string
109         err := unmarshal(&str)
110         if err != nil {
111                 return errors.Wrap(err, "unmarshall")
112         }
113
114         proto, err := NewProtocolFromString(str)
115         if err != nil {
116                 return errors.Wrap(err, wrapNewProtocolFromString)
117         }
118         *p = proto
119         return nil
120 }
121
122 // NewProtocolFromString converts a string into a govpn.Protocol
123 func NewProtocolFromString(p string) (Protocol, error) {
124         var (
125                 k Protocol
126                 v string
127                 lowP = strings.ToLower(p)
128         )
129         for k, v = range protocolText {
130                 if strings.ToLower(v) == lowP {
131                         return k, nil
132                 }
133         }
134
135         choices := make([]string, len(protocolText))
136         var index = 0
137         for k = range protocolText {
138                 choices[index] = protocolText[k]
139                 index++
140         }
141
142         return Protocol(-1), errors.Errorf(
143                 "Invalid protocol %q: %s", p, strings.Join(choices, ","),
144         )
145 }
146
147 // SliceZero zeros each byte.
148 func SliceZero(data []byte) {
149         for i := 0; i < len(data); i++ {
150                 data[i] = 0
151         }
152 }
153
154 // VersionGet returns version of GoVPN
155 func VersionGet() string {
156         return "GoVPN version " + Version + " built with " + runtime.Version()
157 }
158
159 // CatchSignalShutdown returns a channel.
160 // that channel will get a SIG_INT or SIG_KILL signal is received
161 // this is intended to be used to stop a client/server
162 func CatchSignalShutdown() chan interface{} {
163         shutdownChan := make(chan interface{}, 1)
164         go func() {
165                 termSignal := make(chan os.Signal, 1)
166                 signal.Notify(termSignal, os.Interrupt, os.Kill)
167                 sig := <-termSignal
168                 logger.WithFields(logrus.Fields{
169                         "func":   logFuncPrefix + "CatchSignalShutdown",
170                         "signal": sig.String(),
171                 }).Debug("Catch signal, shutting down")
172                 shutdownChan <- sig
173         }()
174         return shutdownChan
175 }
176
177 // SetLogger set the Logger used by this library.
178 // by default logrus StdLogger is used.
179 func SetLogger(l *logrus.Logger) {
180         logger = l
181 }
182
183 // CloseLog log an error if a io.Closer fail to Close
184 func CloseLog(c io.Closer, l *logrus.Logger, fields logrus.Fields) {
185         if err := c.Close(); err != nil {
186                 logrus.WithFields(fields).WithError(err).Error("Can't close connection")
187         }
188 }