package govpn
import (
- "log"
- "os"
- "os/exec"
+ "encoding/hex"
+ "encoding/json"
"runtime"
+ "strings"
+ "time"
+
+ "github.com/pkg/errors"
)
const (
- TimeoutDefault = 60
- EtherSize = 14
+ // ProtocolUDP is UDP transport protocol
+ ProtocolUDP Protocol = iota
+ // ProtocolTCP is TCP transport protocol
+ ProtocolTCP
+ // ProtocolALL is TCP+UDP transport protocol
+ ProtocolALL
+
+ EtherSize = 14
// MTUMax is maximum MTU size of Ethernet packet
MTUMax = 9000 + EtherSize + 1
// MTUDefault is default MTU size of Ethernet packet
ENV_IFACE = "GOVPN_IFACE"
ENV_REMOTE = "GOVPN_REMOTE"
+
+ wrapNewProtocolFromString = "NewProtocolFromString"
)
var (
// Version holds release string set at build time
- Version string
+ Version string
+ protocolText = map[Protocol]string{
+ ProtocolUDP: "udp",
+ ProtocolTCP: "tcp",
+ ProtocolALL: "all",
+ }
+ // TimeoutDefault is default timeout value for various network operations
+ TimeoutDefault = 60 * time.Second
)
-// ScriptCall calls external program/script.
-// You have to specify path to it and (inteface name as a rule) something
-// that will be the first argument when calling it. Function will return
-// it's output and possible error.
-func ScriptCall(path, ifaceName, remoteAddr string) ([]byte, error) {
- if path == "" {
- return nil, nil
+// Protocol is a GoVPN supported protocol: either UDP, TCP or both
+type Protocol int
+
+// String converts a Protocol into a string
+func (p Protocol) String() string {
+ return protocolText[p]
+}
+
+// MarshalJSON returns a JSON string from a protocol
+func (p Protocol) MarshalJSON() ([]byte, error) {
+ str := p.String()
+ output, err := json.Marshal(&str)
+ return output, errors.Wrap(err, "json.Marshal")
+}
+
+// UnmarshalJSON converts a JSON string into a Protocol
+func (p *Protocol) UnmarshalJSON(encoded []byte) error {
+ var str string
+ if err := json.Unmarshal(encoded, &str); err != nil {
+ return errors.Wrapf(err, "Can't unmarshall to string %q", hex.EncodeToString(encoded))
}
- if _, err := os.Stat(path); err != nil && os.IsNotExist(err) {
- return nil, err
+ proto, err := NewProtocolFromString(str)
+ if err != nil {
+ return errors.Wrap(err, wrapNewProtocolFromString)
}
- cmd := exec.Command(path)
- cmd.Env = append(cmd.Env, ENV_IFACE+"="+ifaceName)
- cmd.Env = append(cmd.Env, ENV_REMOTE+"="+remoteAddr)
- out, err := cmd.CombinedOutput()
+ *p = proto
+ return nil
+}
+
+// UnmarshalYAML converts a YAML string into a Protocol
+func (p *Protocol) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var str string
+ err := unmarshal(&str)
if err != nil {
- log.Println("Script error", path, err, string(out))
+ return errors.Wrap(err, "unmarshall")
+ }
+
+ proto, err := NewProtocolFromString(str)
+ if err != nil {
+ return errors.Wrap(err, wrapNewProtocolFromString)
+ }
+ *p = proto
+ return nil
+}
+
+// NewProtocolFromString converts a string into a govpn.Protocol
+func NewProtocolFromString(p string) (Protocol, error) {
+ lowP := strings.ToLower(p)
+ for k, v := range protocolText {
+ if strings.ToLower(v) == lowP {
+ return k, nil
+ }
}
- return out, err
+
+ choices := make([]string, len(protocolText))
+ var index = 0
+ for k, v := range protocolText {
+ if v == p {
+ z := k
+ p = &z
+ return nil
+ }
+ choices[index] = v
+ index++
+ }
+
+ return Protocol(-1), errors.Errorf("Invalid protocol %q: %s", p, strings.Join(choices, ","))
}
-// Zero each byte.
+// SliceZero zeros each byte.
func SliceZero(data []byte) {
for i := 0; i < len(data); i++ {
data[i] = 0