summaryrefslogtreecommitdiff
path: root/vendor/github.com/apparentlymart/go-openvpn-mgmt
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/apparentlymart/go-openvpn-mgmt')
-rw-r--r--vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer.go63
-rw-r--r--vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer_test.go218
-rw-r--r--vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/doc.go12
-rw-r--r--vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/client.go303
-rw-r--r--vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/error.go11
-rw-r--r--vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event.go299
-rw-r--r--vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event_test.go346
-rw-r--r--vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/server.go172
8 files changed, 0 insertions, 1424 deletions
diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer.go
deleted file mode 100644
index c57964e..0000000
--- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package demux
-
-import (
- "bufio"
- "io"
-)
-
-var readErrSynthEvent = []byte("FATAL:Error reading from OpenVPN")
-
-// Demultiplex reads from the given io.Reader, assumed to be the client
-// end of an OpenVPN Management Protocol connection, and splits it into
-// distinct messages from OpenVPN.
-//
-// It then writes the raw message buffers into either replyCh or eventCh
-// depending on whether each message is a reply to a client command or
-// an asynchronous event notification.
-//
-// The buffers written to replyCh are entire raw message lines (without the
-// trailing newlines), while the buffers written to eventCh are the raw
-// event strings with the prototcol's leading '>' indicator omitted.
-//
-// The caller should usually provide buffered channels of sufficient buffer
-// depth so that the reply channel will not be starved by slow event
-// processing.
-//
-// Once the io.Reader signals EOF, eventCh will be closed, then replyCh
-// will be closed, and then this function will return.
-//
-// As a special case, if a non-EOF error occurs while reading from the
-// io.Reader then a synthetic "FATAL" event will be written to eventCh
-// before the two buffers are closed and the function returns. This
-// synthetic message will have the error message "Error reading from OpenVPN".
-func Demultiplex(r io.Reader, replyCh, eventCh chan<- []byte) {
- scanner := bufio.NewScanner(r)
- for scanner.Scan() {
- buf := scanner.Bytes()
-
- if len(buf) < 1 {
- // Should never happen but we'll be robust and ignore this,
- // rather than crashing below.
- continue
- }
-
- // Asynchronous messages always start with > to differentiate
- // them from replies.
- if buf[0] == '>' {
- // Trim off the > when we post the message, since it's
- // redundant after we've demuxed.
- eventCh <- buf[1:]
- } else {
- replyCh <- buf
- }
- }
-
- if err := scanner.Err(); err != nil {
- // Generate a synthetic FATAL event so that the caller can
- // see that the connection was not gracefully closed.
- eventCh <- readErrSynthEvent
- }
-
- close(eventCh)
- close(replyCh)
-}
diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer_test.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer_test.go
deleted file mode 100644
index 45edac6..0000000
--- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/demuxer_test.go
+++ /dev/null
@@ -1,218 +0,0 @@
-package demux
-
-import (
- "bytes"
- "fmt"
- "io"
- "reflect"
- "testing"
-)
-
-func TestDemultiplex(t *testing.T) {
- type TestCase struct {
- Input []string
- ExpectedReplies []string
- ExpectedEvents []string
- }
-
- testCases := []TestCase{
- {
- Input: []string{},
- ExpectedReplies: []string{},
- ExpectedEvents: []string{},
- },
- {
- Input: []string{
- "SUCCESS: foo bar baz",
- },
- ExpectedReplies: []string{
- "SUCCESS: foo bar baz",
- },
- ExpectedEvents: []string{},
- },
- {
- Input: []string{
- ">STATE:1234,ASSIGN_IP,,10.0.0.1,",
- },
- ExpectedReplies: []string{},
- ExpectedEvents: []string{
- "STATE:1234,ASSIGN_IP,,10.0.0.1,",
- },
- },
- {
- Input: []string{
- ">STATE:1234,ASSIGN_IP,,10.0.0.1,",
- ">STATE:5678,ASSIGN_IP,,10.0.0.1,",
- ">STATE:9012,ASSIGN_IP,,10.0.0.1,",
- },
- ExpectedReplies: []string{},
- ExpectedEvents: []string{
- "STATE:1234,ASSIGN_IP,,10.0.0.1,",
- "STATE:5678,ASSIGN_IP,,10.0.0.1,",
- "STATE:9012,ASSIGN_IP,,10.0.0.1,",
- },
- },
- {
- Input: []string{
- ">STATE:1234,ASSIGN_IP,,10.0.0.1,",
- "SUCCESS: foo bar baz",
- ">STATE:5678,ASSIGN_IP,,10.0.0.1,",
- },
- ExpectedReplies: []string{
- "SUCCESS: foo bar baz",
- },
- ExpectedEvents: []string{
- "STATE:1234,ASSIGN_IP,,10.0.0.1,",
- "STATE:5678,ASSIGN_IP,,10.0.0.1,",
- },
- },
- {
- Input: []string{
- "SUCCESS: foo bar baz",
- ">STATE:1234,ASSIGN_IP,,10.0.0.1,",
- "SUCCESS: baz bar foo",
- },
- ExpectedReplies: []string{
- "SUCCESS: foo bar baz",
- "SUCCESS: baz bar foo",
- },
- ExpectedEvents: []string{
- "STATE:1234,ASSIGN_IP,,10.0.0.1,",
- },
- },
- }
-
- for i, testCase := range testCases {
- r := mockReader(testCase.Input)
- gotReplies, gotEvents := captureMsgs(r)
-
- if !reflect.DeepEqual(gotReplies, testCase.ExpectedReplies) {
- t.Errorf(
- "test %d returned incorrect replies\ngot %#v\nwant %#v",
- i, gotReplies, testCase.ExpectedReplies,
- )
- }
-
- if !reflect.DeepEqual(gotEvents, testCase.ExpectedEvents) {
- t.Errorf(
- "test %d returned incorrect events\ngot %#v\nwant %#v",
- i, gotEvents, testCase.ExpectedEvents,
- )
- }
- }
-}
-
-func TestDemultiplex_error(t *testing.T) {
- r := &alwaysErroringReader{}
-
- gotReplies, gotEvents := captureMsgs(r)
-
- expectedReplies := []string{}
- expectedEvents := []string{
- "FATAL:Error reading from OpenVPN",
- }
-
- if !reflect.DeepEqual(gotReplies, expectedReplies) {
- t.Errorf(
- "incorrect replies\ngot %#v\nwant %#v",
- gotReplies, expectedReplies,
- )
- }
-
- if !reflect.DeepEqual(gotEvents, expectedEvents) {
- t.Errorf(
- "incorrect events\ngot %#v\nwant %#v",
- gotEvents, expectedEvents,
- )
- }
-}
-
-func mockReader(msgs []string) io.Reader {
- var buf []byte
- for _, msg := range msgs {
- buf = append(buf, []byte(msg)...)
- buf = append(buf, '\n')
- }
- return bytes.NewReader(buf)
-}
-
-func captureMsgs(r io.Reader) (replies, events []string) {
- replyCh := make(chan []byte)
- eventCh := make(chan []byte)
-
- replies = make([]string, 0)
- events = make([]string, 0)
-
- go Demultiplex(r, replyCh, eventCh)
-
- for replyCh != nil || eventCh != nil {
- select {
-
- case msg, ok := <-replyCh:
- if ok {
- replies = append(replies, string(msg))
- } else {
- replyCh = nil
- }
-
- case msg, ok := <-eventCh:
- if ok {
- events = append(events, string(msg))
- } else {
- eventCh = nil
- }
-
- }
-
- }
-
- return replies, events
-}
-
-type alwaysErroringReader struct{}
-
-func (r *alwaysErroringReader) Read(buf []byte) (int, error) {
- return 0, fmt.Errorf("mock error")
-}
-
-// Somewhat-contrived example of blocking for a reply while concurrently
-// processing asynchronous events.
-func ExampleDemultiplex() {
- // In a real caller we would have a net.IPConn as our reader,
- // but we'll use a bytes reader here as a test.
- r := bytes.NewReader([]byte(
- // A reply to a hypothetical command interspersed between
- // two asynchronous events.
- ">HOLD:Waiting for hold release\nSUCCESS: foo\n>FATAL:baz\n",
- ))
-
- // No strong need for buffering on this channel because usually
- // a message sender will immediately block waiting for the
- // associated response message.
- replyCh := make(chan []byte)
-
- // Make sure the event channel buffer is deep enough that slow event
- // processing won't significantly delay synchronous replies. If you
- // process events quickly, or if you aren't sending any commands
- // concurrently with acting on events, then this is not so important.
- eventCh := make(chan []byte, 10)
-
- // Start demultiplexing the message stream in the background.
- // This goroutine will exit once the reader signals EOF.
- go Demultiplex(r, replyCh, eventCh)
-
- // Some coroutine has sent a hypothetical message to OpenVPN,
- // and it can directly block until the associated reply arrives.
- // The events will be concurrently handled by our event loop
- // below while we wait for the reply to show up.
- go func() {
- replyMsgBuf := <-replyCh
- fmt.Printf("Command reply: %s\n", string(replyMsgBuf))
- }()
-
- // Main event loop deals with the async events as they arrive,
- // independently of any commands that are pending.
- for msgBuf := range eventCh {
- fmt.Printf("Event: %s\n", string(msgBuf))
- }
-}
diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/doc.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/doc.go
deleted file mode 100644
index 263a267..0000000
--- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/demux/doc.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Package demux implements low-level demultiplexing of the stream of
-// messages sent from OpenVPN on the management channel.
-//
-// OpenVPN's protocol includes two different kinds of message from the OpenVPN
-// process: replies to commands sent by the management client, and asynchronous
-// event notifications.
-//
-// This package's purpose is to split these messages into two separate streams,
-// so that functions executing command/response sequences can just block
-// on the reply channel while an event loop elsewhere deals with any async
-// events that might show up.
-package demux
diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/client.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/client.go
deleted file mode 100644
index 7768004..0000000
--- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/client.go
+++ /dev/null
@@ -1,303 +0,0 @@
-package openvpn
-
-import (
- "bytes"
- "fmt"
- "io"
- "net"
- "strconv"
- "time"
-
- "github.com/apparentlymart/go-openvpn-mgmt/demux"
-)
-
-var newline = []byte{'\n'}
-var successPrefix = []byte("SUCCESS: ")
-var errorPrefix = []byte("ERROR: ")
-var endMessage = []byte("END")
-
-type MgmtClient struct {
- wr io.Writer
- replies <-chan []byte
-}
-
-// NewClient creates a new MgmtClient that communicates via the given
-// io.ReadWriter and emits events on the given channel.
-//
-// eventCh should be a buffered channel with a sufficient buffer depth
-// such that it cannot be filled under the expected event volume. Event
-// volume depends on which events are enabled and how they are configured;
-// some of the event-enabling functions have further discussion how frequently
-// events are likely to be emitted, but the caller should also factor in
-// how long its own event *processing* will take, since slow event
-// processing will create back-pressure that could cause this buffer to
-// fill faster.
-//
-// It probably goes without saying given the previous paragraph, but the
-// caller *must* constantly read events from eventCh to avoid its buffer
-// becoming full. Events and replies are received on the same channel
-// from OpenVPN, so if writing to eventCh blocks then this will also block
-// responses from the client's various command methods.
-//
-// eventCh will be closed to signal the closing of the client connection,
-// whether due to graceful shutdown or to an error. In the case of error,
-// a FatalEvent will be emitted on the channel as the last event before it
-// is closed. Connection errors may also concurrently surface as error
-// responses from the client's various command methods, should an error
-// occur while we await a reply.
-func NewClient(conn io.ReadWriter, eventCh chan<- Event) *MgmtClient {
- replyCh := make(chan []byte)
- rawEventCh := make(chan []byte) // not buffered because eventCh should be
-
- go demux.Demultiplex(conn, replyCh, rawEventCh)
-
- // Get raw events and upgrade them into proper event types before
- // passing them on to the caller's event channel.
- go func() {
- for raw := range rawEventCh {
- eventCh <- upgradeEvent(raw)
- }
- close(eventCh)
- }()
-
- return &MgmtClient{
- // replyCh acts as the reader for our ReadWriter, so we only
- // need to retain the io.Writer for it, so we can send commands.
- wr: conn,
- replies: replyCh,
- }
-}
-
-// Dial is a convenience wrapper around NewClient that handles the common
-// case of opening an TCP/IP socket to an OpenVPN management port and creating
-// a client for it.
-//
-// See the NewClient docs for discussion about the requirements for eventCh.
-//
-// OpenVPN will create a suitable management port if launched with the
-// following command line option:
-//
-// --management <ipaddr> <port>
-//
-// Address may an IPv4 address, an IPv6 address, or a hostname that resolves
-// to either of these, followed by a colon and then a port number.
-//
-// When running on Unix systems it's possible to instead connect to a Unix
-// domain socket. To do this, pass an absolute path to the socket as
-// the target address, having run OpenVPN with the following options:
-//
-// --management /path/to/socket unix
-//
-func Dial(addr string, eventCh chan<- Event) (*MgmtClient, error) {
- proto := "tcp"
- if len(addr) > 0 && addr[0] == '/' {
- proto = "unix"
- }
- conn, err := net.Dial(proto, addr)
- if err != nil {
- return nil, err
- }
-
- return NewClient(conn, eventCh), nil
-}
-
-// HoldRelease instructs OpenVPN to release any management hold preventing
-// it from proceeding, but to retain the state of the hold flag such that
-// the daemon will hold again if it needs to reconnect for any reason.
-//
-// OpenVPN can be instructed to activate a management hold on startup by
-// running it with the following option:
-//
-// --management-hold
-//
-// Instructing OpenVPN to hold gives your client a chance to connect and
-// do any necessary configuration before a connection proceeds, thus avoiding
-// the problem of missed events.
-//
-// When OpenVPN begins holding, or when a new management client connects while
-// a hold is already in effect, a HoldEvent will be emitted on the event
-// channel.
-func (c *MgmtClient) HoldRelease() error {
- _, err := c.simpleCommand("hold release")
- return err
-}
-
-// SetStateEvents either enables or disables asynchronous events for changes
-// in the OpenVPN connection state.
-//
-// When enabled, a StateEvent will be emitted from the event channel each
-// time the connection state changes. See StateEvent for more information
-// on the event structure.
-func (c *MgmtClient) SetStateEvents(on bool) error {
- var err error
- if on {
- _, err = c.simpleCommand("state on")
- } else {
- _, err = c.simpleCommand("state off")
- }
- return err
-}
-
-// SetEchoEvents either enables or disables asynchronous events for "echo"
-// commands sent from a remote server to our managed OpenVPN client.
-//
-// When enabled, an EchoEvent will be emitted from the event channel each
-// time the server sends an echo command. See EchoEvent for more information.
-func (c *MgmtClient) SetEchoEvents(on bool) error {
- var err error
- if on {
- _, err = c.simpleCommand("echo on")
- } else {
- _, err = c.simpleCommand("echo off")
- }
- return err
-}
-
-// SetByteCountEvents either enables or disables ongoing asynchronous events
-// for information on OpenVPN bandwidth usage.
-//
-// When enabled, a ByteCountEvent will be emitted at given time interval,
-// (which may only be whole seconds) describing how many bytes have been
-// transferred in each direction See ByteCountEvent for more information.
-//
-// Set the time interval to zero in order to disable byte count events.
-func (c *MgmtClient) SetByteCountEvents(interval time.Duration) error {
- msg := fmt.Sprintf("bytecount %d", int(interval.Seconds()))
- _, err := c.simpleCommand(msg)
- return err
-}
-
-// SendSignal sends a signal to the OpenVPN process via the management
-// channel. In effect this causes the OpenVPN process to send a signal to
-// itself on our behalf.
-//
-// OpenVPN accepts a subset of the usual UNIX signal names, including
-// "SIGHUP", "SIGTERM", "SIGUSR1" and "SIGUSR2". See the OpenVPN manual
-// page for the meaning of each.
-//
-// Behavior is undefined if the given signal name is not entirely uppercase
-// letters. In particular, including newlines in the string is likely to
-// cause very unpredictable behavior.
-func (c *MgmtClient) SendSignal(name string) error {
- msg := fmt.Sprintf("signal %q", name)
- _, err := c.simpleCommand(msg)
- return err
-}
-
-// LatestState retrieves the most recent StateEvent from the server. This
-// can either be used to poll the state or it can be used to determine the
-// initial state after calling SetStateEvents(true) but before the first
-// state event is delivered.
-func (c *MgmtClient) LatestState() (*StateEvent, error) {
- err := c.sendCommand([]byte("state"))
- if err != nil {
- return nil, err
- }
-
- payload, err := c.readCommandResponsePayload()
- if err != nil {
- return nil, err
- }
-
- if len(payload) != 1 {
- return nil, fmt.Errorf("Malformed OpenVPN 'state' response")
- }
-
- return &StateEvent{
- body: payload[0],
- }, nil
-}
-
-// Pid retrieves the process id of the connected OpenVPN process.
-func (c *MgmtClient) Pid() (int, error) {
- raw, err := c.simpleCommand("pid")
- if err != nil {
- return 0, err
- }
-
- if !bytes.HasPrefix(raw, []byte("pid=")) {
- return 0, fmt.Errorf("malformed response from OpenVPN")
- }
-
- pid, err := strconv.Atoi(string(raw[4:]))
- if err != nil {
- return 0, fmt.Errorf("error parsing pid from OpenVPN: %s", err)
- }
-
- return pid, nil
-}
-
-func (c *MgmtClient) sendCommand(cmd []byte) error {
- _, err := c.wr.Write(cmd)
- if err != nil {
- return err
- }
- _, err = c.wr.Write(newline)
- return err
-}
-
-// sendCommandPayload can be called after sendCommand for
-// commands that expect a multi-line input payload.
-//
-// The buffer given in 'payload' *must* end with a newline,
-// or else the protocol will be broken.
-func (c *MgmtClient) sendCommandPayload(payload []byte) error {
- _, err := c.wr.Write(payload)
- if err != nil {
- return err
- }
- _, err = c.wr.Write(endMessage)
- if err != nil {
- return err
- }
- _, err = c.wr.Write(newline)
- return err
-}
-
-func (c *MgmtClient) readCommandResult() ([]byte, error) {
- reply, ok := <-c.replies
- if !ok {
- return nil, fmt.Errorf("connection closed while awaiting result")
- }
-
- if bytes.HasPrefix(reply, successPrefix) {
- result := reply[len(successPrefix):]
- return result, nil
- }
-
- if bytes.HasPrefix(reply, errorPrefix) {
- message := reply[len(errorPrefix):]
- return nil, ErrorFromServer(message)
- }
-
- return nil, fmt.Errorf("malformed result message")
-}
-
-func (c *MgmtClient) readCommandResponsePayload() ([][]byte, error) {
- lines := make([][]byte, 0, 10)
-
- for {
- line, ok := <-c.replies
- if !ok {
- // We'll give the caller whatever we got before the connection
- // closed, in case it's useful for debugging.
- return lines, fmt.Errorf("connection closed before END recieved")
- }
-
- if bytes.Equal(line, endMessage) {
- break
- }
-
- lines = append(lines, line)
- }
-
- return lines, nil
-}
-
-func (c *MgmtClient) simpleCommand(cmd string) ([]byte, error) {
- err := c.sendCommand([]byte(cmd))
- if err != nil {
- return nil, err
- }
- return c.readCommandResult()
-}
diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/error.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/error.go
deleted file mode 100644
index 554e2ef..0000000
--- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/error.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package openvpn
-
-type ErrorFromServer []byte
-
-func (err ErrorFromServer) Error() string {
- return string(err)
-}
-
-func (err ErrorFromServer) String() string {
- return string(err)
-}
diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event.go
deleted file mode 100644
index 66625f3..0000000
--- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event.go
+++ /dev/null
@@ -1,299 +0,0 @@
-package openvpn
-
-import (
- "bytes"
- "fmt"
- "strconv"
-)
-
-var eventSep = []byte(":")
-var fieldSep = []byte(",")
-var byteCountEventKW = []byte("BYTECOUNT")
-var byteCountCliEventKW = []byte("BYTECOUNT_CLI")
-var clientEventKW = []byte("CLIENT")
-var echoEventKW = []byte("ECHO")
-var fatalEventKW = []byte("FATAL")
-var holdEventKW = []byte("HOLD")
-var infoEventKW = []byte("INFO")
-var logEventKW = []byte("LOG")
-var needOkEventKW = []byte("NEED-OK")
-var needStrEventKW = []byte("NEED-STR")
-var passwordEventKW = []byte("PASSWORD")
-var stateEventKW = []byte("STATE")
-
-type Event interface {
- String() string
-}
-
-// UnknownEvent represents an event of a type that this package doesn't
-// know about.
-//
-// Future versions of this library may learn about new event types, so a
-// caller should exercise caution when making use of events of this type
-// to access unsupported behavior. Backward-compatibility is *not*
-// guaranteed for events of this type.
-type UnknownEvent struct {
- keyword []byte
- body []byte
-}
-
-func (e *UnknownEvent) Type() string {
- return string(e.keyword)
-}
-
-func (e *UnknownEvent) Body() string {
- return string(e.body)
-}
-
-func (e *UnknownEvent) String() string {
- return fmt.Sprintf("%s: %s", e.keyword, e.body)
-}
-
-// MalformedEvent represents a message from the OpenVPN process that is
-// presented as an event but does not comply with the expected event syntax.
-//
-// Events of this type should never be seen but robust callers will accept
-// and ignore them, possibly generating some kind of debugging message.
-//
-// One reason for potentially seeing events of this type is when the target
-// program is actually not an OpenVPN process at all, but in fact this client
-// has been connected to a different sort of server by mistake.
-type MalformedEvent struct {
- raw []byte
-}
-
-func (e *MalformedEvent) String() string {
- return fmt.Sprintf("Malformed Event %q", e.raw)
-}
-
-// HoldEvent is a notification that the OpenVPN process is in a management
-// hold and will not continue connecting until the hold is released, e.g.
-// by calling client.HoldRelease()
-type HoldEvent struct {
- body []byte
-}
-
-func (e *HoldEvent) String() string {
- return string(e.body)
-}
-
-// StateEvent is a notification of a change of connection state. It can be
-// used, for example, to detect if the OpenVPN connection has been interrupted
-// and the OpenVPN process is attempting to reconnect.
-type StateEvent struct {
- body []byte
-
- // bodyParts is populated only on first request, giving us the
- // separate comma-separated elements of the message. Not all
- // fields are populated for all states.
- bodyParts [][]byte
-}
-
-func (e *StateEvent) RawTimestamp() string {
- parts := e.parts()
- return string(parts[0])
-}
-
-func (e *StateEvent) NewState() string {
- parts := e.parts()
- return string(parts[1])
-}
-
-func (e *StateEvent) Description() string {
- parts := e.parts()
- return string(parts[2])
-}
-
-// LocalTunnelAddr returns the IP address of the local interface within
-// the tunnel, as a string that can be parsed using net.ParseIP.
-//
-// This field is only populated for events whose NewState returns
-// either ASSIGN_IP or CONNECTED.
-func (e *StateEvent) LocalTunnelAddr() string {
- parts := e.parts()
- return string(parts[3])
-}
-
-// RemoteAddr returns the non-tunnel IP address of the remote
-// system that has connected to the local OpenVPN process.
-//
-// This field is only populated for events whose NewState returns
-// CONNECTED.
-func (e *StateEvent) RemoteAddr() string {
- parts := e.parts()
- return string(parts[4])
-}
-
-func (e *StateEvent) String() string {
- newState := e.NewState()
- switch newState {
- case "ASSIGN_IP":
- return fmt.Sprintf("%s: %s", newState, e.LocalTunnelAddr())
- case "CONNECTED":
- return fmt.Sprintf("%s: %s", newState, e.RemoteAddr())
- default:
- desc := e.Description()
- if desc != "" {
- return fmt.Sprintf("%s: %s", newState, desc)
- } else {
- return newState
- }
- }
-}
-
-func (e *StateEvent) parts() [][]byte {
- if e.bodyParts == nil {
- // State messages currently have only five segments, but
- // we'll ask for 5 so any additional fields that might show
- // up in newer versions will gather in an element we're
- // not actually using.
- e.bodyParts = bytes.SplitN(e.body, fieldSep, 6)
-
- // Prevent crash if the server has sent us a malformed
- // status message. This should never actually happen if
- // the server is behaving itself.
- if len(e.bodyParts) < 5 {
- expanded := make([][]byte, 5)
- copy(expanded, e.bodyParts)
- e.bodyParts = expanded
- }
- }
- return e.bodyParts
-}
-
-// EchoEvent is emitted by an OpenVPN process running in client mode when
-// an "echo" command is pushed to it by the server it has connected to.
-//
-// The format of the echo message is free-form, since this message type is
-// intended to pass application-specific data from the server-side config
-// into whatever client is consuming the management prototcol.
-//
-// This event is emitted only if the management client has turned on events
-// of this type using client.SetEchoEvents(true)
-type EchoEvent struct {
- body []byte
-}
-
-func (e *EchoEvent) RawTimestamp() string {
- sepIndex := bytes.Index(e.body, fieldSep)
- if sepIndex == -1 {
- return ""
- }
- return string(e.body[:sepIndex])
-}
-
-func (e *EchoEvent) Message() string {
- sepIndex := bytes.Index(e.body, fieldSep)
- if sepIndex == -1 {
- return ""
- }
- return string(e.body[sepIndex+1:])
-}
-
-func (e *EchoEvent) String() string {
- return fmt.Sprintf("ECHO: %s", e.Message())
-}
-
-// ByteCountEvent represents a periodic snapshot of data transfer in bytes
-// on a VPN connection.
-//
-// For OpenVPN *servers*, events are emitted for each client and the method
-// ClientId identifies thet client.
-//
-// For other OpenVPN modes, events are emitted only once per interval for the
-// single connection managed by the target process, and ClientId returns
-// the empty string.
-type ByteCountEvent struct {
- hasClient bool
- body []byte
-
- // populated on first call to parts()
- bodyParts [][]byte
-}
-
-func (e *ByteCountEvent) ClientId() string {
- if !e.hasClient {
- return ""
- }
-
- return string(e.parts()[0])
-}
-
-func (e *ByteCountEvent) BytesIn() int {
- index := 0
- if e.hasClient {
- index = 1
- }
- str := string(e.parts()[index])
- val, _ := strconv.Atoi(str)
- // Ignore error, since this should never happen if OpenVPN is
- // behaving itself.
- return val
-}
-
-func (e *ByteCountEvent) BytesOut() int {
- index := 1
- if e.hasClient {
- index = 2
- }
- str := string(e.parts()[index])
- val, _ := strconv.Atoi(str)
- // Ignore error, since this should never happen if OpenVPN is
- // behaving itself.
- return val
-}
-
-func (e *ByteCountEvent) String() string {
- if e.hasClient {
- return fmt.Sprintf("Client %s: %d in, %d out", e.ClientId(), e.BytesIn(), e.BytesOut())
- } else {
- return fmt.Sprintf("%d in, %d out", e.BytesIn(), e.BytesOut())
- }
-}
-
-func (e *ByteCountEvent) parts() [][]byte {
- if e.bodyParts == nil {
- e.bodyParts = bytes.SplitN(e.body, fieldSep, 4)
-
- wantCount := 2
- if e.hasClient {
- wantCount = 3
- }
-
- // Prevent crash if the server has sent us a malformed
- // message. This should never actually happen if the
- // server is behaving itself.
- if len(e.bodyParts) < wantCount {
- expanded := make([][]byte, wantCount)
- copy(expanded, e.bodyParts)
- e.bodyParts = expanded
- }
- }
- return e.bodyParts
-}
-
-func upgradeEvent(raw []byte) Event {
- splitIdx := bytes.Index(raw, eventSep)
- if splitIdx == -1 {
- // Should never happen, but we'll handle it robustly if it does.
- return &MalformedEvent{raw}
- }
-
- keyword := raw[:splitIdx]
- body := raw[splitIdx+1:]
-
- switch {
- case bytes.Equal(keyword, stateEventKW):
- return &StateEvent{body: body}
- case bytes.Equal(keyword, holdEventKW):
- return &HoldEvent{body}
- case bytes.Equal(keyword, echoEventKW):
- return &EchoEvent{body}
- case bytes.Equal(keyword, byteCountEventKW):
- return &ByteCountEvent{hasClient: false, body: body}
- case bytes.Equal(keyword, byteCountCliEventKW):
- return &ByteCountEvent{hasClient: true, body: body}
- default:
- return &UnknownEvent{keyword, body}
- }
-}
diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event_test.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event_test.go
deleted file mode 100644
index 81a02e1..0000000
--- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/event_test.go
+++ /dev/null
@@ -1,346 +0,0 @@
-package openvpn
-
-import (
- "fmt"
- "testing"
-)
-
-// A key requirement of our event parsing is that it must never cause a
-// panic, even if the OpenVPN process sends us malformed garbage.
-//
-// Therefore most of the tests in here are testing various tortured error
-// cases, which are all expected to produce an event object, though the
-// contents of that event object will be nonsensical if the OpenVPN server
-// sends something nonsensical.
-
-func TestMalformedEvent(t *testing.T) {
- testCases := [][]byte{
- []byte(""),
- []byte("HTTP/1.1 200 OK"),
- []byte(" "),
- []byte("\x00"),
- }
-
- for i, testCase := range testCases {
- event := upgradeEvent(testCase)
-
- var malformed *MalformedEvent
- var ok bool
- if malformed, ok = event.(*MalformedEvent); !ok {
- t.Errorf("test %d got %T; want %T", i, event, malformed)
- continue
- }
-
- wantString := fmt.Sprintf("Malformed Event %q", testCase)
- if gotString := malformed.String(); gotString != wantString {
- t.Errorf("test %d String returned %q; want %q", i, gotString, wantString)
- }
- }
-}
-
-func TestUnknownEvent(t *testing.T) {
- type TestCase struct {
- Input []byte
- WantType string
- WantBody string
- }
- testCases := []TestCase{
- {
- Input: []byte("DUMMY:baz"),
- WantType: "DUMMY",
- WantBody: "baz",
- },
- {
- Input: []byte("DUMMY:"),
- WantType: "DUMMY",
- WantBody: "",
- },
- {
- Input: []byte("DUMMY:abc,123,456"),
- WantType: "DUMMY",
- WantBody: "abc,123,456",
- },
- }
-
- for i, testCase := range testCases {
- event := upgradeEvent(testCase.Input)
-
- var unk *UnknownEvent
- var ok bool
- if unk, ok = event.(*UnknownEvent); !ok {
- t.Errorf("test %d got %T; want %T", i, event, unk)
- continue
- }
-
- if got, want := unk.Type(), testCase.WantType; got != want {
- t.Errorf("test %d Type returned %q; want %q", i, got, want)
- }
- if got, want := unk.Body(), testCase.WantBody; got != want {
- t.Errorf("test %d Body returned %q; want %q", i, got, want)
- }
- }
-}
-
-func TestHoldEvent(t *testing.T) {
- testCases := [][]byte{
- []byte("HOLD:"),
- []byte("HOLD:waiting for hold release"),
- }
-
- for i, testCase := range testCases {
- event := upgradeEvent(testCase)
-
- var hold *HoldEvent
- var ok bool
- if hold, ok = event.(*HoldEvent); !ok {
- t.Errorf("test %d got %T; want %T", i, event, hold)
- continue
- }
- }
-}
-
-func TestEchoEvent(t *testing.T) {
- type TestCase struct {
- Input []byte
- WantTimestamp string
- WantMessage string
- }
- testCases := []TestCase{
- {
- Input: []byte("ECHO:123,foo"),
- WantTimestamp: "123",
- WantMessage: "foo",
- },
- {
- Input: []byte("ECHO:123,"),
- WantTimestamp: "123",
- WantMessage: "",
- },
- {
- Input: []byte("ECHO:,foo"),
- WantTimestamp: "",
- WantMessage: "foo",
- },
- {
- Input: []byte("ECHO:,"),
- WantTimestamp: "",
- WantMessage: "",
- },
- {
- Input: []byte("ECHO:"),
- WantTimestamp: "",
- WantMessage: "",
- },
- }
-
- for i, testCase := range testCases {
- event := upgradeEvent(testCase.Input)
-
- var echo *EchoEvent
- var ok bool
- if echo, ok = event.(*EchoEvent); !ok {
- t.Errorf("test %d got %T; want %T", i, event, echo)
- continue
- }
-
- if got, want := echo.RawTimestamp(), testCase.WantTimestamp; got != want {
- t.Errorf("test %d RawTimestamp returned %q; want %q", i, got, want)
- }
- if got, want := echo.Message(), testCase.WantMessage; got != want {
- t.Errorf("test %d Message returned %q; want %q", i, got, want)
- }
- }
-}
-
-func TestStateEvent(t *testing.T) {
- type TestCase struct {
- Input []byte
- WantTimestamp string
- WantState string
- WantDesc string
- WantLocalAddr string
- WantRemoteAddr string
- }
- testCases := []TestCase{
- {
- Input: []byte("STATE:"),
- WantTimestamp: "",
- WantState: "",
- WantDesc: "",
- WantLocalAddr: "",
- WantRemoteAddr: "",
- },
- {
- Input: []byte("STATE:,"),
- WantTimestamp: "",
- WantState: "",
- WantDesc: "",
- WantLocalAddr: "",
- WantRemoteAddr: "",
- },
- {
- Input: []byte("STATE:,,,,"),
- WantTimestamp: "",
- WantState: "",
- WantDesc: "",
- WantLocalAddr: "",
- WantRemoteAddr: "",
- },
- {
- Input: []byte("STATE:123,CONNECTED,good,172.16.0.1,192.168.4.1"),
- WantTimestamp: "123",
- WantState: "CONNECTED",
- WantDesc: "good",
- WantLocalAddr: "172.16.0.1",
- WantRemoteAddr: "192.168.4.1",
- },
- {
- Input: []byte("STATE:123,RECONNECTING,SIGHUP,,"),
- WantTimestamp: "123",
- WantState: "RECONNECTING",
- WantDesc: "SIGHUP",
- WantLocalAddr: "",
- WantRemoteAddr: "",
- },
- {
- Input: []byte("STATE:123,RECONNECTING,SIGHUP,,,extra"),
- WantTimestamp: "123",
- WantState: "RECONNECTING",
- WantDesc: "SIGHUP",
- WantLocalAddr: "",
- WantRemoteAddr: "",
- },
- }
-
- for i, testCase := range testCases {
- event := upgradeEvent(testCase.Input)
-
- var st *StateEvent
- var ok bool
- if st, ok = event.(*StateEvent); !ok {
- t.Errorf("test %d got %T; want %T", i, event, st)
- continue
- }
-
- if got, want := st.RawTimestamp(), testCase.WantTimestamp; got != want {
- t.Errorf("test %d RawTimestamp returned %q; want %q", i, got, want)
- }
- if got, want := st.NewState(), testCase.WantState; got != want {
- t.Errorf("test %d NewState returned %q; want %q", i, got, want)
- }
- if got, want := st.Description(), testCase.WantDesc; got != want {
- t.Errorf("test %d Description returned %q; want %q", i, got, want)
- }
- if got, want := st.LocalTunnelAddr(), testCase.WantLocalAddr; got != want {
- t.Errorf("test %d LocalTunnelAddr returned %q; want %q", i, got, want)
- }
- if got, want := st.RemoteAddr(), testCase.WantRemoteAddr; got != want {
- t.Errorf("test %d RemoteAddr returned %q; want %q", i, got, want)
- }
- }
-}
-
-func TestByteCountEvent(t *testing.T) {
- type TestCase struct {
- Input []byte
- WantClientId string
- WantBytesIn int
- WantBytesOut int
- }
- testCases := []TestCase{
- {
- Input: []byte("BYTECOUNT:"),
- WantClientId: "",
- WantBytesIn: 0,
- WantBytesOut: 0,
- },
- {
- Input: []byte("BYTECOUNT:123,456"),
- WantClientId: "",
- WantBytesIn: 123,
- WantBytesOut: 456,
- },
- {
- Input: []byte("BYTECOUNT:,"),
- WantClientId: "",
- WantBytesIn: 0,
- WantBytesOut: 0,
- },
- {
- Input: []byte("BYTECOUNT:5,"),
- WantClientId: "",
- WantBytesIn: 5,
- WantBytesOut: 0,
- },
- {
- Input: []byte("BYTECOUNT:,6"),
- WantClientId: "",
- WantBytesIn: 0,
- WantBytesOut: 6,
- },
- {
- Input: []byte("BYTECOUNT:6"),
- WantClientId: "",
- WantBytesIn: 6,
- WantBytesOut: 0,
- },
- {
- Input: []byte("BYTECOUNT:wrong,bad"),
- WantClientId: "",
- WantBytesIn: 0,
- WantBytesOut: 0,
- },
- {
- Input: []byte("BYTECOUNT:1,2,3"),
- WantClientId: "",
- WantBytesIn: 1,
- WantBytesOut: 2,
- },
- {
- // Intentionally malformed BYTECOUNT event sent as BYTECOUNT_CLI
- Input: []byte("BYTECOUNT_CLI:123,456"),
- WantClientId: "123",
- WantBytesIn: 456,
- WantBytesOut: 0,
- },
- {
- Input: []byte("BYTECOUNT_CLI:"),
- WantClientId: "",
- WantBytesIn: 0,
- WantBytesOut: 0,
- },
- {
- Input: []byte("BYTECOUNT_CLI:abc123,123,456"),
- WantClientId: "abc123",
- WantBytesIn: 123,
- WantBytesOut: 456,
- },
- {
- Input: []byte("BYTECOUNT_CLI:abc123,123"),
- WantClientId: "abc123",
- WantBytesIn: 123,
- WantBytesOut: 0,
- },
- }
-
- for i, testCase := range testCases {
- event := upgradeEvent(testCase.Input)
-
- var bc *ByteCountEvent
- var ok bool
- if bc, ok = event.(*ByteCountEvent); !ok {
- t.Errorf("test %d got %T; want %T", i, event, bc)
- continue
- }
-
- if got, want := bc.ClientId(), testCase.WantClientId; got != want {
- t.Errorf("test %d ClientId returned %q; want %q", i, got, want)
- }
- if got, want := bc.BytesIn(), testCase.WantBytesIn; got != want {
- t.Errorf("test %d BytesIn returned %d; want %d", i, got, want)
- }
- if got, want := bc.BytesOut(), testCase.WantBytesOut; got != want {
- t.Errorf("test %d BytesOut returned %d; want %d", i, got, want)
- }
- }
-}
diff --git a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/server.go b/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/server.go
deleted file mode 100644
index d7defd4..0000000
--- a/vendor/github.com/apparentlymart/go-openvpn-mgmt/openvpn/server.go
+++ /dev/null
@@ -1,172 +0,0 @@
-package openvpn
-
-import (
- "net"
- "time"
-)
-
-// MgmtListener accepts incoming connections from OpenVPN.
-//
-// The primary way to instantiate this type is via the function Listen.
-// See its documentation for more information.
-type MgmtListener struct {
- l net.Listener
-}
-
-// NewMgmtListener constructs a MgmtListener from an already-established
-// net.Listener. In most cases it will be more convenient to use
-// the function Listen.
-func NewMgmtListener(l net.Listener) *MgmtListener {
- return &MgmtListener{l}
-}
-
-// Listen opens a listen port and awaits incoming connections from OpenVPN
-// processes.
-//
-// OpenVPN will behave in this manner when launched with the following options:
-//
-// --management ipaddr port --management-client
-//
-// Note that in this case the terminology is slightly confusing, since from
-// the standpoint of TCP/IP it is OpenVPN that is the client and our program
-// that is the server, but once the connection is established the channel
-// is indistinguishable from the situation where OpenVPN exposed a management
-// *server* and we connected to it. Thus we still refer to our program as
-// the "client" and OpenVPN as the "server" once the connection is established.
-//
-// When running on Unix systems it's possible to instead listen on a Unix
-// domain socket. To do this, pass an absolute path to the socket as
-// the listen address, and then run OpenVPN with the following options:
-//
-// --management /path/to/socket unix --management-client
-//
-func Listen(laddr string) (*MgmtListener, error) {
- proto := "tcp"
- if len(laddr) > 0 && laddr[0] == '/' {
- proto = "unix"
- }
- listener, err := net.Listen(proto, laddr)
- if err != nil {
- return nil, err
- }
-
- return NewMgmtListener(listener), nil
-}
-
-// Accept waits for and returns the next connection.
-func (l *MgmtListener) Accept() (*IncomingConn, error) {
- conn, err := l.l.Accept()
- if err != nil {
- return nil, err
- }
-
- return &IncomingConn{conn}, nil
-}
-
-// Close closes the listener. Any blocked Accept operations
-// will be blocked and each will return an error.
-func (l *MgmtListener) Close() error {
- return l.l.Close()
-}
-
-// Addr returns the listener's network address.
-func (l *MgmtListener) Addr() net.Addr {
- return l.l.Addr()
-}
-
-// Serve will await new connections and call the given handler
-// for each.
-//
-// Serve does not return unless the listen port is closed; a non-nil
-// error is always returned.
-func (l *MgmtListener) Serve(handler IncomingConnHandler) error {
- defer l.Close()
-
- var tempDelay time.Duration
-
- for {
- incoming, err := l.Accept()
- if err != nil {
- if ne, ok := err.(net.Error); ok && ne.Temporary() {
- if tempDelay == 0 {
- tempDelay = 5 * time.Millisecond
- } else {
- tempDelay *= 2
- }
- if max := 1 * time.Second; tempDelay > max {
- tempDelay = max
- }
-
- // Wait a while before we try again.
- time.Sleep(tempDelay)
- continue
- } else {
- // Listen socket is permanently closed or errored,
- // so it's time for us to exit.
- return err
- }
- }
-
- // always reset our retry delay once we successfully read
- tempDelay = 0
-
- go handler.ServeOpenVPNMgmt(*incoming)
- }
-}
-
-type IncomingConn struct {
- conn net.Conn
-}
-
-// Open initiates communication with the connected OpenVPN process,
-// and establishes the channel on which events will be delivered.
-//
-// See the documentation for NewClient for discussion about the requirements
-// for eventCh.
-func (ic IncomingConn) Open(eventCh chan<- Event) *MgmtClient {
- return NewClient(ic.conn, eventCh)
-}
-
-// Close abruptly closes the socket connected to the OpenVPN process.
-//
-// This is a rather abrasive way to close the channel, intended for rejecting
-// unwanted incoming clients that may or may not speak the OpenVPN protocol.
-//
-// Once communication is accepted and established, it is generally better
-// to close the connection gracefully using commands on the client returned
-// from Open.
-func (ic IncomingConn) Close() error {
- return ic.conn.Close()
-}
-
-type IncomingConnHandler interface {
- ServeOpenVPNMgmt(IncomingConn)
-}
-
-// IncomingConnHandlerFunc is an adapter to allow the use of ordinary
-// functions as connection handlers.
-//
-// Given a function with the appropriate signature, IncomingConnHandlerFunc(f)
-// is an IncomingConnHandler that calls f.
-type IncomingConnHandlerFunc func(IncomingConn)
-
-func (f IncomingConnHandlerFunc) ServeOpenVPNMgmt(i IncomingConn) {
- f(i)
-}
-
-// ListenAndServe creates a MgmtListener for the given listen address
-// and then calls AcceptAndServe on it.
-//
-// This is just a convenience wrapper. See the AcceptAndServe method for
-// more details. Just as with AcceptAndServe, this function does not return
-// except on error; in addition to the error cases handled by AcceptAndServe,
-// this function may also fail if the listen socket cannot be established
-// in the first place.
-func ListenAndServe(laddr string, handler IncomingConnHandler) error {
- listener, err := Listen(laddr)
- if err != nil {
- return err
- }
-
- return listener.Serve(handler)
-}