]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/cmd/govpn-server/conf.go
Refactor server
[govpn.git] / src / cypherpunks.ru / govpn / cmd / govpn-server / conf.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 main
20
21 import (
22         "io/ioutil"
23         "time"
24
25         "github.com/Sirupsen/logrus"
26         "github.com/pkg/errors"
27         "gopkg.in/yaml.v2"
28
29         "cypherpunks.ru/govpn"
30 )
31
32 const refreshRate = time.Minute
33
34 var (
35         confs    peerConfigurations
36         idsCache *govpn.MACCache
37         logger   *logrus.Logger
38 )
39
40 type peerConfigurations map[govpn.PeerID]*govpn.PeerConf
41
42 func (peerConfs peerConfigurations) Get(peerID govpn.PeerID) *govpn.PeerConf {
43         pc, exists := peerConfs[peerID]
44         if !exists {
45                 return nil
46         }
47         return pc
48 }
49
50 type peerConf struct {
51         Name        string `yaml:"name"`
52         Iface       string `yaml:"iface"`
53         MTU         int    `yaml:"mtu"`
54         Up          string `yaml:"up"`
55         Down        string `yaml:"down"`
56         TimeoutInt  int    `yaml:"timeout"`
57         Noise       bool   `yaml:"noise"`
58         CPR         int    `yaml:"cpr"`
59         Encless     bool   `yaml:"encless"`
60         TimeSync    int    `yaml:"timesync"`
61         VerifierRaw string `yaml:"verifier"`
62 }
63
64 func confRead() (*map[govpn.PeerID]*govpn.PeerConf, error) {
65         data, err := ioutil.ReadFile(*confPath)
66         if err != nil {
67                 return nil, errors.Wrap(err, "ioutil.ReadFile")
68         }
69         confsRaw := new(map[string]peerConf)
70         err = yaml.Unmarshal(data, confsRaw)
71         if err != nil {
72                 return nil, errors.Wrap(err, "yaml.Unmarshal")
73         }
74
75         confs := make(map[govpn.PeerID]*govpn.PeerConf, len(*confsRaw))
76         for name, pc := range *confsRaw {
77                 verifier, err := govpn.VerifierFromString(pc.VerifierRaw)
78                 if err != nil {
79                         return nil, errors.Wrap(err, "govpn.VerifierFromString")
80                 }
81                 if pc.Encless {
82                         pc.Noise = true
83                 }
84                 if pc.MTU == 0 {
85                         pc.MTU = govpn.MTUDefault
86                 }
87                 if pc.MTU > govpn.MTUMax {
88                         logger.WithFields(logrus.Fields{
89                                 "bind":         *bindAddr,
90                                 "previous_mtu": pc.MTU,
91                                 "new_mtu":      govpn.MTUMax,
92                         }).Warning("Overriden MTU")
93                         pc.MTU = govpn.MTUMax
94                 }
95                 conf := govpn.PeerConf{
96                         Verifier: verifier,
97                         ID:       verifier.ID,
98                         Name:     name,
99                         Iface:    pc.Iface,
100                         MTU:      pc.MTU,
101                         PreUp:    preUpAction(pc.Up),
102                         Down:     govpn.RunScriptAction(&pc.Down),
103                         Noise:    pc.Noise,
104                         CPR:      pc.CPR,
105                         Encless:  pc.Encless,
106                         TimeSync: pc.TimeSync,
107                 }
108                 if pc.TimeoutInt <= 0 {
109                         conf.Timeout = govpn.TimeoutDefault
110                 } else {
111                         conf.Timeout = time.Second * time.Duration(pc.TimeoutInt)
112                 }
113                 confs[*verifier.ID] = &conf
114         }
115         return &confs, nil
116 }
117
118 func confRefresh() error {
119         fields := logrus.Fields{
120                 "func": "confRefresh",
121         }
122         logger.WithFields(fields).Debug("Check configuration file")
123         newConfs, err := confRead()
124         if err != nil {
125                 return errors.Wrap(err, "confRead")
126         }
127         confs = *newConfs
128         logger.WithFields(fields).WithField("newConfs", len(confs)).Debug("idsCache.Update")
129         if err = idsCache.Update(newConfs); err != nil {
130                 return errors.Wrap(err, "idsCache.Update")
131         }
132         logger.WithFields(fields).Debug("Done")
133         return nil
134 }
135
136 func confInit() {
137         idsCache = govpn.NewMACCache()
138         err := confRefresh()
139         fields := logrus.Fields{"func": "confInit"}
140         if err != nil {
141                 logger.WithError(err).WithFields(fields).Fatal("Couldn't perform initial configuration read")
142         }
143         go func() {
144                 for {
145                         time.Sleep(refreshRate)
146                         if err = confRefresh(); err != nil {
147                                 logger.WithError(err).WithFields(fields).Error("Couldn't refresh configuration")
148                         }
149                 }
150         }()
151 }