/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
import (
"io"
+
+ "github.com/Sirupsen/logrus"
+ "github.com/pkg/errors"
+)
+
+const (
+ interfaceTap = "tap"
+ interfaceTun = "tun"
)
// TAP is a TUN or a TAP interface.
+// TODO: rename to something more... generic?
type TAP struct {
Name string
Sink chan []byte
- dev io.ReadWriter
+ dev io.ReadWriteCloser
}
var (
- taps = make(map[string]*TAP)
+ taps = make(map[string]*TAP)
+ errUnsupportedInterface = errors.New("Unsupported interface")
)
// NewTAP creates a new TUN/TAP virtual interface
func NewTAP(ifaceName string, mtu int) (*TAP, error) {
- tapRaw, err := newTAPer(ifaceName)
+ tapRaw, err := newTAPer(&ifaceName)
if err != nil {
- return nil, err
+ return nil, errors.Wrap(err, "newTAPer")
}
tap := TAP{
Name: ifaceName,
bufZ = !bufZ
n, err = tap.dev.Read(buf)
if err != nil {
- panic("Reading TUN/TAP:" + err.Error())
+ logger.WithError(err).WithFields(logrus.Fields{
+ "func": logFuncPrefix + "TAP read sink loop",
+ "name": tap.Name,
+ "mtu": mtu,
+ }).Error("Can't read interface")
+ return
+ // TODO: need a way to warn consumer that something is wrong
+ // TODO: to force peer to just disconnect
+ // TODO: use the client/server error channel?
}
tap.Sink <- buf[:n]
}
return &tap, nil
}
-func (t *TAP) Write(data []byte) (n int, err error) {
- return t.dev.Write(data)
+func (t *TAP) Write(data []byte) (int, error) {
+ n, err := t.dev.Write(data)
+ return n, errors.Wrapf(err, "t.dev.Write %d", len(data))
+}
+
+// Close close TAP/TUN virtual network interface
+func (t *TAP) Close() error {
+ // TODO add chan to stop read loop
+ return t.dev.Close()
}
// TAPListen opens an existing TAP (creates if none exists)
}
tap, err := NewTAP(ifaceName, mtu)
if err != nil {
- return nil, err
+ return nil, errors.Wrap(err, "NewTAP")
}
taps[ifaceName] = tap
return tap, nil