summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/wiggin77/srslog
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/wiggin77/srslog')
-rw-r--r--vendor/github.com/wiggin77/srslog/.gitignore1
-rw-r--r--vendor/github.com/wiggin77/srslog/.travis.yml15
-rw-r--r--vendor/github.com/wiggin77/srslog/CODE_OF_CONDUCT.md50
-rw-r--r--vendor/github.com/wiggin77/srslog/LICENSE27
-rw-r--r--vendor/github.com/wiggin77/srslog/README.md147
-rw-r--r--vendor/github.com/wiggin77/srslog/constants.go68
-rw-r--r--vendor/github.com/wiggin77/srslog/dialer.go104
-rw-r--r--vendor/github.com/wiggin77/srslog/formatter.go58
-rw-r--r--vendor/github.com/wiggin77/srslog/framer.go24
-rw-r--r--vendor/github.com/wiggin77/srslog/go.mod3
-rw-r--r--vendor/github.com/wiggin77/srslog/logger.go13
-rw-r--r--vendor/github.com/wiggin77/srslog/net_conn.go76
-rw-r--r--vendor/github.com/wiggin77/srslog/srslog.go125
-rw-r--r--vendor/github.com/wiggin77/srslog/srslog_unix.go54
-rw-r--r--vendor/github.com/wiggin77/srslog/writer.go201
15 files changed, 966 insertions, 0 deletions
diff --git a/vendor/github.com/wiggin77/srslog/.gitignore b/vendor/github.com/wiggin77/srslog/.gitignore
new file mode 100644
index 00000000..ebf0f2e4
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/.gitignore
@@ -0,0 +1 @@
+.cover
diff --git a/vendor/github.com/wiggin77/srslog/.travis.yml b/vendor/github.com/wiggin77/srslog/.travis.yml
new file mode 100644
index 00000000..921150e9
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/.travis.yml
@@ -0,0 +1,15 @@
+sudo: required
+dist: trusty
+group: edge
+language: go
+go:
+- 1.5
+before_install:
+ - pip install --user codecov
+script:
+- |
+ go get ./...
+ go test -v -coverprofile=coverage.txt -covermode=atomic
+ go vet
+after_success:
+ - codecov
diff --git a/vendor/github.com/wiggin77/srslog/CODE_OF_CONDUCT.md b/vendor/github.com/wiggin77/srslog/CODE_OF_CONDUCT.md
new file mode 100644
index 00000000..18ac49fc
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/CODE_OF_CONDUCT.md
@@ -0,0 +1,50 @@
+# Contributor Code of Conduct
+
+As contributors and maintainers of this project, and in the interest of
+fostering an open and welcoming community, we pledge to respect all people who
+contribute through reporting issues, posting feature requests, updating
+documentation, submitting pull requests or patches, and other activities.
+
+We are committed to making participation in this project a harassment-free
+experience for everyone, regardless of level of experience, gender, gender
+identity and expression, sexual orientation, disability, personal appearance,
+body size, race, ethnicity, age, religion, or nationality.
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery
+* Personal attacks
+* Trolling or insulting/derogatory comments
+* Public or private harassment
+* Publishing other's private information, such as physical or electronic
+ addresses, without explicit permission
+* Other unethical or unprofessional conduct
+
+Project maintainers have the right and responsibility to remove, edit, or
+reject comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any contributor for other behaviors that they deem inappropriate,
+threatening, offensive, or harmful.
+
+By adopting this Code of Conduct, project maintainers commit themselves to
+fairly and consistently applying these principles to every aspect of managing
+this project. Project maintainers who do not follow or enforce the Code of
+Conduct may be permanently removed from the project team.
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community.
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting a project maintainer at [sirsean@gmail.com]. All
+complaints will be reviewed and investigated and will result in a response that
+is deemed necessary and appropriate to the circumstances. Maintainers are
+obligated to maintain confidentiality with regard to the reporter of an
+incident.
+
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 1.3.0, available at
+[http://contributor-covenant.org/version/1/3/0/][version]
+
+[homepage]: http://contributor-covenant.org
+[version]: http://contributor-covenant.org/version/1/3/0/
diff --git a/vendor/github.com/wiggin77/srslog/LICENSE b/vendor/github.com/wiggin77/srslog/LICENSE
new file mode 100644
index 00000000..9269338f
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2015 Rackspace. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/wiggin77/srslog/README.md b/vendor/github.com/wiggin77/srslog/README.md
new file mode 100644
index 00000000..dcacc348
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/README.md
@@ -0,0 +1,147 @@
+[![Build Status](https://travis-ci.org/RackSec/srslog.svg?branch=master)](https://travis-ci.org/RackSec/srslog)
+
+# srslog
+
+Go has a `syslog` package in the standard library, but it has the following
+shortcomings:
+
+1. It doesn't have TLS support
+2. [According to bradfitz on the Go team, it is no longer being maintained.](https://github.com/golang/go/issues/13449#issuecomment-161204716)
+
+I agree that it doesn't need to be in the standard library. So, I've
+followed Brad's suggestion and have made a separate project to handle syslog.
+
+This code was taken directly from the Go project as a base to start from.
+
+However, this _does_ have TLS support.
+
+# Usage
+
+Basic usage retains the same interface as the original `syslog` package. We
+only added to the interface where required to support new functionality.
+
+Switch from the standard library:
+
+```
+import(
+ //"log/syslog"
+ syslog "github.com/RackSec/srslog"
+)
+```
+
+You can still use it for local syslog:
+
+```
+w, err := syslog.Dial("", "", syslog.LOG_ERR, "testtag")
+```
+
+Or to unencrypted UDP:
+
+```
+w, err := syslog.Dial("udp", "192.168.0.50:514", syslog.LOG_ERR, "testtag")
+```
+
+Or to unencrypted TCP:
+
+```
+w, err := syslog.Dial("tcp", "192.168.0.51:514", syslog.LOG_ERR, "testtag")
+```
+
+But now you can also send messages via TLS-encrypted TCP:
+
+```
+w, err := syslog.DialWithTLSCertPath("tcp+tls", "192.168.0.52:514", syslog.LOG_ERR, "testtag", "/path/to/servercert.pem")
+```
+
+And if you need more control over your TLS configuration :
+
+```
+pool := x509.NewCertPool()
+serverCert, err := ioutil.ReadFile("/path/to/servercert.pem")
+if err != nil {
+ return nil, err
+}
+pool.AppendCertsFromPEM(serverCert)
+config := tls.Config{
+ RootCAs: pool,
+}
+
+w, err := DialWithTLSConfig(network, raddr, priority, tag, &config)
+```
+
+(Note that in both TLS cases, this uses a self-signed certificate, where the
+remote syslog server has the keypair and the client has only the public key.)
+
+And then to write log messages, continue like so:
+
+```
+if err != nil {
+ log.Fatal("failed to connect to syslog:", err)
+}
+defer w.Close()
+
+w.Alert("this is an alert")
+w.Crit("this is critical")
+w.Err("this is an error")
+w.Warning("this is a warning")
+w.Notice("this is a notice")
+w.Info("this is info")
+w.Debug("this is debug")
+w.Write([]byte("these are some bytes"))
+```
+
+If you need further control over connection attempts, you can use the DialWithCustomDialer
+function. To continue with the DialWithTLSConfig example:
+
+```
+netDialer := &net.Dialer{Timeout: time.Second*5} // easy timeouts
+realNetwork := "tcp" // real network, other vars your dail func can close over
+dial := func(network, addr string) (net.Conn, error) {
+ // cannot use "network" here as it'll simply be "custom" which will fail
+ return tls.DialWithDialer(netDialer, realNetwork, addr, &config)
+}
+
+w, err := DialWithCustomDialer("custom", "192.168.0.52:514", syslog.LOG_ERR, "testtag", dial)
+```
+
+Your custom dial func can set timeouts, proxy connections, and do whatever else it needs before returning a net.Conn.
+
+# Generating TLS Certificates
+
+We've provided a script that you can use to generate a self-signed keypair:
+
+```
+pip install cryptography
+python script/gen-certs.py
+```
+
+That outputs the public key and private key to standard out. Put those into
+`.pem` files. (And don't put them into any source control. The certificate in
+the `test` directory is used by the unit tests, and please do not actually use
+it anywhere else.)
+
+# Running Tests
+
+Run the tests as usual:
+
+```
+go test
+```
+
+But we've also provided a test coverage script that will show you which
+lines of code are not covered:
+
+```
+script/coverage --html
+```
+
+That will open a new browser tab showing coverage information.
+
+# License
+
+This project uses the New BSD License, the same as the Go project itself.
+
+# Code of Conduct
+
+Please note that this project is released with a Contributor Code of Conduct.
+By participating in this project you agree to abide by its terms.
diff --git a/vendor/github.com/wiggin77/srslog/constants.go b/vendor/github.com/wiggin77/srslog/constants.go
new file mode 100644
index 00000000..600801ee
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/constants.go
@@ -0,0 +1,68 @@
+package srslog
+
+import (
+ "errors"
+)
+
+// Priority is a combination of the syslog facility and
+// severity. For example, LOG_ALERT | LOG_FTP sends an alert severity
+// message from the FTP facility. The default severity is LOG_EMERG;
+// the default facility is LOG_KERN.
+type Priority int
+
+const severityMask = 0x07
+const facilityMask = 0xf8
+
+const (
+ // Severity.
+
+ // From /usr/include/sys/syslog.h.
+ // These are the same on Linux, BSD, and OS X.
+ LOG_EMERG Priority = iota
+ LOG_ALERT
+ LOG_CRIT
+ LOG_ERR
+ LOG_WARNING
+ LOG_NOTICE
+ LOG_INFO
+ LOG_DEBUG
+)
+
+const (
+ // Facility.
+
+ // From /usr/include/sys/syslog.h.
+ // These are the same up to LOG_FTP on Linux, BSD, and OS X.
+ LOG_KERN Priority = iota << 3
+ LOG_USER
+ LOG_MAIL
+ LOG_DAEMON
+ LOG_AUTH
+ LOG_SYSLOG
+ LOG_LPR
+ LOG_NEWS
+ LOG_UUCP
+ LOG_CRON
+ LOG_AUTHPRIV
+ LOG_FTP
+ _ // unused
+ _ // unused
+ _ // unused
+ _ // unused
+ LOG_LOCAL0
+ LOG_LOCAL1
+ LOG_LOCAL2
+ LOG_LOCAL3
+ LOG_LOCAL4
+ LOG_LOCAL5
+ LOG_LOCAL6
+ LOG_LOCAL7
+)
+
+func validatePriority(p Priority) error {
+ if p < 0 || p > LOG_LOCAL7|LOG_DEBUG {
+ return errors.New("log/syslog: invalid priority")
+ } else {
+ return nil
+ }
+}
diff --git a/vendor/github.com/wiggin77/srslog/dialer.go b/vendor/github.com/wiggin77/srslog/dialer.go
new file mode 100644
index 00000000..1ecf29b2
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/dialer.go
@@ -0,0 +1,104 @@
+package srslog
+
+import (
+ "crypto/tls"
+ "net"
+)
+
+// dialerFunctionWrapper is a simple object that consists of a dialer function
+// and its name. This is primarily for testing, so we can make sure that the
+// getDialer method returns the correct dialer function. However, if you ever
+// find that you need to check which dialer function you have, this would also
+// be useful for you without having to use reflection.
+type dialerFunctionWrapper struct {
+ Name string
+ Dialer func() (serverConn, string, error)
+}
+
+// Call the wrapped dialer function and return its return values.
+func (df dialerFunctionWrapper) Call() (serverConn, string, error) {
+ return df.Dialer()
+}
+
+// getDialer returns a "dialer" function that can be called to connect to a
+// syslog server.
+//
+// Each dialer function is responsible for dialing the remote host and returns
+// a serverConn, the hostname (or a default if the Writer has not specified a
+// hostname), and an error in case dialing fails.
+//
+// The reason for separate dialers is that different network types may need
+// to dial their connection differently, yet still provide a net.Conn interface
+// that you can use once they have dialed. Rather than an increasingly long
+// conditional, we have a map of network -> dialer function (with a sane default
+// value), and adding a new network type is as easy as writing the dialer
+// function and adding it to the map.
+func (w *Writer) getDialer() dialerFunctionWrapper {
+ dialers := map[string]dialerFunctionWrapper{
+ "": dialerFunctionWrapper{"unixDialer", w.unixDialer},
+ "tcp+tls": dialerFunctionWrapper{"tlsDialer", w.tlsDialer},
+ "custom": dialerFunctionWrapper{"customDialer", w.customDialer},
+ }
+ dialer, ok := dialers[w.network]
+ if !ok {
+ dialer = dialerFunctionWrapper{"basicDialer", w.basicDialer}
+ }
+ return dialer
+}
+
+// unixDialer uses the unixSyslog method to open a connection to the syslog
+// daemon running on the local machine.
+func (w *Writer) unixDialer() (serverConn, string, error) {
+ sc, err := unixSyslog()
+ hostname := w.hostname
+ if hostname == "" {
+ hostname = "localhost"
+ }
+ return sc, hostname, err
+}
+
+// tlsDialer connects to TLS over TCP, and is used for the "tcp+tls" network
+// type.
+func (w *Writer) tlsDialer() (serverConn, string, error) {
+ c, err := tls.Dial("tcp", w.raddr, w.tlsConfig)
+ var sc serverConn
+ hostname := w.hostname
+ if err == nil {
+ sc = newNetConn(c)
+ if hostname == "" {
+ hostname = c.LocalAddr().String()
+ }
+ }
+ return sc, hostname, err
+}
+
+// basicDialer is the most common dialer for syslog, and supports both TCP and
+// UDP connections.
+func (w *Writer) basicDialer() (serverConn, string, error) {
+ c, err := net.Dial(w.network, w.raddr)
+ var sc serverConn
+ hostname := w.hostname
+ if err == nil {
+ sc = newNetConn(c)
+ if hostname == "" {
+ hostname = c.LocalAddr().String()
+ }
+ }
+ return sc, hostname, err
+}
+
+// customDialer uses the custom dialer when the Writer was created
+// giving developers total control over how connections are made and returned.
+// Note it does not check if cdialer is nil, as it should only be referenced from getDialer.
+func (w *Writer) customDialer() (serverConn, string, error) {
+ c, err := w.customDial(w.network, w.raddr)
+ var sc serverConn
+ hostname := w.hostname
+ if err == nil {
+ sc = newNetConn(c)
+ if hostname == "" {
+ hostname = c.LocalAddr().String()
+ }
+ }
+ return sc, hostname, err
+}
diff --git a/vendor/github.com/wiggin77/srslog/formatter.go b/vendor/github.com/wiggin77/srslog/formatter.go
new file mode 100644
index 00000000..e306fd67
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/formatter.go
@@ -0,0 +1,58 @@
+package srslog
+
+import (
+ "fmt"
+ "os"
+ "time"
+)
+
+const appNameMaxLength = 48 // limit to 48 chars as per RFC5424
+
+// Formatter is a type of function that takes the consituent parts of a
+// syslog message and returns a formatted string. A different Formatter is
+// defined for each different syslog protocol we support.
+type Formatter func(p Priority, hostname, tag, content string) string
+
+// DefaultFormatter is the original format supported by the Go syslog package,
+// and is a non-compliant amalgamation of 3164 and 5424 that is intended to
+// maximize compatibility.
+func DefaultFormatter(p Priority, hostname, tag, content string) string {
+ timestamp := time.Now().Format(time.RFC3339)
+ msg := fmt.Sprintf("<%d> %s %s %s[%d]: %s",
+ p, timestamp, hostname, tag, os.Getpid(), content)
+ return msg
+}
+
+// UnixFormatter omits the hostname, because it is only used locally.
+func UnixFormatter(p Priority, hostname, tag, content string) string {
+ timestamp := time.Now().Format(time.Stamp)
+ msg := fmt.Sprintf("<%d>%s %s[%d]: %s",
+ p, timestamp, tag, os.Getpid(), content)
+ return msg
+}
+
+// RFC3164Formatter provides an RFC 3164 compliant message.
+func RFC3164Formatter(p Priority, hostname, tag, content string) string {
+ timestamp := time.Now().Format(time.Stamp)
+ msg := fmt.Sprintf("<%d>%s %s %s[%d]: %s",
+ p, timestamp, hostname, tag, os.Getpid(), content)
+ return msg
+}
+
+// if string's length is greater than max, then use the last part
+func truncateStartStr(s string, max int) string {
+ if (len(s) > max) {
+ return s[len(s) - max:]
+ }
+ return s
+}
+
+// RFC5424Formatter provides an RFC 5424 compliant message.
+func RFC5424Formatter(p Priority, hostname, tag, content string) string {
+ timestamp := time.Now().Format(time.RFC3339)
+ pid := os.Getpid()
+ appName := truncateStartStr(os.Args[0], appNameMaxLength)
+ msg := fmt.Sprintf("<%d>%d %s %s %s %d %s - %s",
+ p, 1, timestamp, hostname, appName, pid, tag, content)
+ return msg
+}
diff --git a/vendor/github.com/wiggin77/srslog/framer.go b/vendor/github.com/wiggin77/srslog/framer.go
new file mode 100644
index 00000000..ab46f0de
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/framer.go
@@ -0,0 +1,24 @@
+package srslog
+
+import (
+ "fmt"
+)
+
+// Framer is a type of function that takes an input string (typically an
+// already-formatted syslog message) and applies "message framing" to it. We
+// have different framers because different versions of the syslog protocol
+// and its transport requirements define different framing behavior.
+type Framer func(in string) string
+
+// DefaultFramer does nothing, since there is no framing to apply. This is
+// the original behavior of the Go syslog package, and is also typically used
+// for UDP syslog.
+func DefaultFramer(in string) string {
+ return in
+}
+
+// RFC5425MessageLengthFramer prepends the message length to the front of the
+// provided message, as defined in RFC 5425.
+func RFC5425MessageLengthFramer(in string) string {
+ return fmt.Sprintf("%d %s", len(in), in)
+}
diff --git a/vendor/github.com/wiggin77/srslog/go.mod b/vendor/github.com/wiggin77/srslog/go.mod
new file mode 100644
index 00000000..393b0761
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/go.mod
@@ -0,0 +1,3 @@
+module github.com/wiggin77/srslog
+
+go 1.14
diff --git a/vendor/github.com/wiggin77/srslog/logger.go b/vendor/github.com/wiggin77/srslog/logger.go
new file mode 100644
index 00000000..3a738565
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/logger.go
@@ -0,0 +1,13 @@
+package srslog
+
+import (
+ "io/ioutil"
+ "log"
+)
+
+var Logger log.Logger
+
+func init() {
+ Logger = log.Logger{}
+ Logger.SetOutput(ioutil.Discard)
+}
diff --git a/vendor/github.com/wiggin77/srslog/net_conn.go b/vendor/github.com/wiggin77/srslog/net_conn.go
new file mode 100644
index 00000000..f3cfeb60
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/net_conn.go
@@ -0,0 +1,76 @@
+package srslog
+
+import (
+ "io"
+ "net"
+ "time"
+)
+
+// netConn has an internal net.Conn and adheres to the serverConn interface,
+// allowing us to send syslog messages over the network.
+type netConn struct {
+ conn net.Conn
+ done chan interface{}
+}
+
+// newNetConn creates a netConn instance that is monitored for unexpected socket closure.
+func newNetConn(conn net.Conn) *netConn {
+ nc := &netConn{conn: conn, done: make(chan interface{})}
+ go monitor(nc.conn, nc.done)
+ return nc
+}
+
+// writeString formats syslog messages using time.RFC3339 and includes the
+// hostname, and sends the message to the connection.
+func (n *netConn) writeString(framer Framer, formatter Formatter, p Priority, hostname, tag, msg string) error {
+ if framer == nil {
+ framer = DefaultFramer
+ }
+ if formatter == nil {
+ formatter = DefaultFormatter
+ }
+ formattedMessage := framer(formatter(p, hostname, tag, msg))
+ _, err := n.conn.Write([]byte(formattedMessage))
+ return err
+}
+
+// close the network connection
+func (n *netConn) close() error {
+ // signal monitor goroutine to exit
+ close(n.done)
+ // wake up monitor blocked on read (close usually is enough)
+ _ = n.conn.SetReadDeadline(time.Now())
+ // close the connection
+ return n.conn.Close()
+}
+
+// monitor continuously tries to read from the connection to detect socket close.
+// This is needed because syslog server uses a write only socket and Linux systems
+// take a long time to detect a loss of connectivity on a socket when only writing;
+// the writes simply fail without an error returned.
+func monitor(conn net.Conn, done chan interface{}) {
+ defer Logger.Println("monitor exit")
+
+ buf := make([]byte, 1)
+ for {
+ Logger.Println("monitor loop")
+
+ select {
+ case <-done:
+ return
+ case <-time.After(1 * time.Second):
+ }
+
+ err := conn.SetReadDeadline(time.Now().Add(time.Second * 30))
+ if err != nil {
+ continue
+ }
+
+ _, err = conn.Read(buf)
+ Logger.Println("monitor -- ", err)
+ if err == io.EOF {
+ Logger.Println("monitor close conn")
+ conn.Close()
+ }
+ }
+}
diff --git a/vendor/github.com/wiggin77/srslog/srslog.go b/vendor/github.com/wiggin77/srslog/srslog.go
new file mode 100644
index 00000000..b47ad72d
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/srslog.go
@@ -0,0 +1,125 @@
+package srslog
+
+import (
+ "crypto/tls"
+ "crypto/x509"
+ "errors"
+ "io/ioutil"
+ "log"
+ "net"
+ "os"
+)
+
+// This interface allows us to work with both local and network connections,
+// and enables Solaris support (see syslog_unix.go).
+type serverConn interface {
+ writeString(framer Framer, formatter Formatter, p Priority, hostname, tag, s string) error
+ close() error
+}
+
+// DialFunc is the function signature to be used for a custom dialer callback
+// with DialWithCustomDialer
+type DialFunc func(string, string) (net.Conn, error)
+
+// New establishes a new connection to the system log daemon. Each
+// write to the returned Writer sends a log message with the given
+// priority and prefix.
+func New(priority Priority, tag string) (w *Writer, err error) {
+ return Dial("", "", priority, tag)
+}
+
+// Dial establishes a connection to a log daemon by connecting to
+// address raddr on the specified network. Each write to the returned
+// Writer sends a log message with the given facility, severity and
+// tag.
+// If network is empty, Dial will connect to the local syslog server.
+func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) {
+ return DialWithTLSConfig(network, raddr, priority, tag, nil)
+}
+
+// ErrNilDialFunc is returned from DialWithCustomDialer when a nil DialFunc is passed,
+// avoiding a nil pointer deference panic.
+var ErrNilDialFunc = errors.New("srslog: nil DialFunc passed to DialWithCustomDialer")
+
+// DialWithCustomDialer establishes a connection by calling customDial.
+// Each write to the returned Writer sends a log message with the given facility, severity and tag.
+// Network must be "custom" in order for this package to use customDial.
+// While network and raddr will be passed to customDial, it is allowed for customDial to ignore them.
+// If customDial is nil, this function returns ErrNilDialFunc.
+func DialWithCustomDialer(network, raddr string, priority Priority, tag string, customDial DialFunc) (*Writer, error) {
+ if customDial == nil {
+ return nil, ErrNilDialFunc
+ }
+ return dialAllParameters(network, raddr, priority, tag, nil, customDial)
+}
+
+// DialWithTLSCertPath establishes a secure connection to a log daemon by connecting to
+// address raddr on the specified network. It uses certPath to load TLS certificates and configure
+// the secure connection.
+func DialWithTLSCertPath(network, raddr string, priority Priority, tag, certPath string) (*Writer, error) {
+ serverCert, err := ioutil.ReadFile(certPath)
+ if err != nil {
+ return nil, err
+ }
+
+ return DialWithTLSCert(network, raddr, priority, tag, serverCert)
+}
+
+// DialWIthTLSCert establishes a secure connection to a log daemon by connecting to
+// address raddr on the specified network. It uses serverCert to load a TLS certificate
+// and configure the secure connection.
+func DialWithTLSCert(network, raddr string, priority Priority, tag string, serverCert []byte) (*Writer, error) {
+ pool := x509.NewCertPool()
+ pool.AppendCertsFromPEM(serverCert)
+ config := tls.Config{
+ RootCAs: pool,
+ }
+
+ return DialWithTLSConfig(network, raddr, priority, tag, &config)
+}
+
+// DialWithTLSConfig establishes a secure connection to a log daemon by connecting to
+// address raddr on the specified network. It uses tlsConfig to configure the secure connection.
+func DialWithTLSConfig(network, raddr string, priority Priority, tag string, tlsConfig *tls.Config) (*Writer, error) {
+ return dialAllParameters(network, raddr, priority, tag, tlsConfig, nil)
+}
+
+// implementation of the various functions above
+func dialAllParameters(network, raddr string, priority Priority, tag string, tlsConfig *tls.Config, customDial DialFunc) (*Writer, error) {
+ if err := validatePriority(priority); err != nil {
+ return nil, err
+ }
+
+ if tag == "" {
+ tag = os.Args[0]
+ }
+ hostname, _ := os.Hostname()
+
+ w := &Writer{
+ priority: priority,
+ tag: tag,
+ hostname: hostname,
+ network: network,
+ raddr: raddr,
+ tlsConfig: tlsConfig,
+ customDial: customDial,
+ }
+
+ _, err := w.connect()
+ if err != nil {
+ return nil, err
+ }
+ return w, err
+}
+
+// NewLogger creates a log.Logger whose output is written to
+// the system log service with the specified priority. The logFlag
+// argument is the flag set passed through to log.New to create
+// the Logger.
+func NewLogger(p Priority, logFlag int) (*log.Logger, error) {
+ s, err := New(p, "")
+ if err != nil {
+ return nil, err
+ }
+ return log.New(s, "", logFlag), nil
+}
diff --git a/vendor/github.com/wiggin77/srslog/srslog_unix.go b/vendor/github.com/wiggin77/srslog/srslog_unix.go
new file mode 100644
index 00000000..a04d9396
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/srslog_unix.go
@@ -0,0 +1,54 @@
+package srslog
+
+import (
+ "errors"
+ "io"
+ "net"
+)
+
+// unixSyslog opens a connection to the syslog daemon running on the
+// local machine using a Unix domain socket. This function exists because of
+// Solaris support as implemented by gccgo. On Solaris you can not
+// simply open a TCP connection to the syslog daemon. The gccgo
+// sources have a syslog_solaris.go file that implements unixSyslog to
+// return a type that satisfies the serverConn interface and simply calls the C
+// library syslog function.
+func unixSyslog() (conn serverConn, err error) {
+ logTypes := []string{"unixgram", "unix"}
+ logPaths := []string{"/dev/log", "/var/run/syslog", "/var/run/log"}
+ for _, network := range logTypes {
+ for _, path := range logPaths {
+ conn, err := net.Dial(network, path)
+ if err != nil {
+ continue
+ } else {
+ return &localConn{conn: conn}, nil
+ }
+ }
+ }
+ return nil, errors.New("Unix syslog delivery error")
+}
+
+// localConn adheres to the serverConn interface, allowing us to send syslog
+// messages to the local syslog daemon over a Unix domain socket.
+type localConn struct {
+ conn io.WriteCloser
+}
+
+// writeString formats syslog messages using time.Stamp instead of time.RFC3339,
+// and omits the hostname (because it is expected to be used locally).
+func (n *localConn) writeString(framer Framer, formatter Formatter, p Priority, hostname, tag, msg string) error {
+ if framer == nil {
+ framer = DefaultFramer
+ }
+ if formatter == nil {
+ formatter = UnixFormatter
+ }
+ _, err := n.conn.Write([]byte(framer(formatter(p, hostname, tag, msg))))
+ return err
+}
+
+// close the (local) network connection
+func (n *localConn) close() error {
+ return n.conn.Close()
+}
diff --git a/vendor/github.com/wiggin77/srslog/writer.go b/vendor/github.com/wiggin77/srslog/writer.go
new file mode 100644
index 00000000..86bccba1
--- /dev/null
+++ b/vendor/github.com/wiggin77/srslog/writer.go
@@ -0,0 +1,201 @@
+package srslog
+
+import (
+ "crypto/tls"
+ "strings"
+ "sync"
+)
+
+// A Writer is a connection to a syslog server.
+type Writer struct {
+ priority Priority
+ tag string
+ hostname string
+ network string
+ raddr string
+ tlsConfig *tls.Config
+ framer Framer
+ formatter Formatter
+
+ //non-nil if custom dialer set, used in getDialer
+ customDial DialFunc
+
+ mu sync.RWMutex // guards conn
+ conn serverConn
+}
+
+// getConn provides access to the internal conn, protected by a mutex. The
+// conn is threadsafe, so it can be used while unlocked, but we want to avoid
+// race conditions on grabbing a reference to it.
+func (w *Writer) getConn() serverConn {
+ w.mu.RLock()
+ conn := w.conn
+ w.mu.RUnlock()
+ return conn
+}
+
+// setConn updates the internal conn, protected by a mutex.
+func (w *Writer) setConn(c serverConn) {
+ w.mu.Lock()
+ w.conn = c
+ w.mu.Unlock()
+}
+
+// connect makes a connection to the syslog server.
+func (w *Writer) connect() (serverConn, error) {
+ conn := w.getConn()
+ if conn != nil {
+ // ignore err from close, it makes sense to continue anyway
+ conn.close()
+ w.setConn(nil)
+ }
+
+ var hostname string
+ var err error
+ dialer := w.getDialer()
+ conn, hostname, err = dialer.Call()
+ if err == nil {
+ w.setConn(conn)
+ w.hostname = hostname
+
+ return conn, nil
+ } else {
+ return nil, err
+ }
+}
+
+// SetFormatter changes the formatter function for subsequent messages.
+func (w *Writer) SetFormatter(f Formatter) {
+ w.formatter = f
+}
+
+// SetFramer changes the framer function for subsequent messages.
+func (w *Writer) SetFramer(f Framer) {
+ w.framer = f
+}
+
+// SetHostname changes the hostname for syslog messages if needed.
+func (w *Writer) SetHostname(hostname string) {
+ w.hostname = hostname
+}
+
+// Write sends a log message to the syslog daemon using the default priority
+// passed into `srslog.New` or the `srslog.Dial*` functions.
+func (w *Writer) Write(b []byte) (int, error) {
+ return w.writeAndRetry(w.priority, string(b))
+}
+
+// WriteWithPriority sends a log message with a custom priority.
+func (w *Writer) WriteWithPriority(p Priority, b []byte) (int, error) {
+ return w.writeAndRetryWithPriority(p, string(b))
+}
+
+// Close closes a connection to the syslog daemon.
+func (w *Writer) Close() error {
+ conn := w.getConn()
+ if conn != nil {
+ err := conn.close()
+ w.setConn(nil)
+ return err
+ }
+ return nil
+}
+
+// Emerg logs a message with severity LOG_EMERG; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Emerg(m string) (err error) {
+ _, err = w.writeAndRetry(LOG_EMERG, m)
+ return err
+}
+
+// Alert logs a message with severity LOG_ALERT; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Alert(m string) (err error) {
+ _, err = w.writeAndRetry(LOG_ALERT, m)
+ return err
+}
+
+// Crit logs a message with severity LOG_CRIT; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Crit(m string) (err error) {
+ _, err = w.writeAndRetry(LOG_CRIT, m)
+ return err
+}
+
+// Err logs a message with severity LOG_ERR; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Err(m string) (err error) {
+ _, err = w.writeAndRetry(LOG_ERR, m)
+ return err
+}
+
+// Warning logs a message with severity LOG_WARNING; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Warning(m string) (err error) {
+ _, err = w.writeAndRetry(LOG_WARNING, m)
+ return err
+}
+
+// Notice logs a message with severity LOG_NOTICE; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Notice(m string) (err error) {
+ _, err = w.writeAndRetry(LOG_NOTICE, m)
+ return err
+}
+
+// Info logs a message with severity LOG_INFO; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Info(m string) (err error) {
+ _, err = w.writeAndRetry(LOG_INFO, m)
+ return err
+}
+
+// Debug logs a message with severity LOG_DEBUG; this overrides the default
+// priority passed to `srslog.New` and the `srslog.Dial*` functions.
+func (w *Writer) Debug(m string) (err error) {
+ _, err = w.writeAndRetry(LOG_DEBUG, m)
+ return err
+}
+
+// writeAndRetry takes a severity and the string to write. Any facility passed to
+// it as part of the severity Priority will be ignored.
+func (w *Writer) writeAndRetry(severity Priority, s string) (int, error) {
+ pr := (w.priority & facilityMask) | (severity & severityMask)
+
+ return w.writeAndRetryWithPriority(pr, s)
+}
+
+// writeAndRetryWithPriority differs from writeAndRetry in that it allows setting
+// of both the facility and the severity.
+func (w *Writer) writeAndRetryWithPriority(p Priority, s string) (int, error) {
+ conn := w.getConn()
+ if conn != nil {
+ if n, err := w.write(conn, p, s); err == nil {
+ return n, err
+ }
+ }
+
+ var err error
+ if conn, err = w.connect(); err != nil {
+ return 0, err
+ }
+ return w.write(conn, p, s)
+}
+
+// write generates and writes a syslog formatted string. It formats the
+// message based on the current Formatter and Framer.
+func (w *Writer) write(conn serverConn, p Priority, msg string) (int, error) {
+ // ensure it ends in a \n
+ if !strings.HasSuffix(msg, "\n") {
+ msg += "\n"
+ }
+
+ err := conn.writeString(w.framer, w.formatter, p, w.hostname, w.tag, msg)
+ if err != nil {
+ return 0, err
+ }
+ // Note: return the length of the input, not the number of
+ // bytes printed by Fprintf, because this must behave like
+ // an io.Writer.
+ return len(msg), nil
+}