This file is indexed.

/usr/share/gocode/src/github.com/linuxkit/virtsock/cmd/vsudd/vsyslog.go is in golang-github-linuxkit-virtsock-dev 0.0~git20170720.0.0416e3d-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
* Functions in this file are used to forward syslog messages to the
* host and must be quite careful about their own logging. In general
* error messages should go via the console log.Logger defined in this
* file.
 */
package main

import (
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"strconv"
	"strings"

	"github.com/linuxkit/virtsock/pkg/hvsock"
	"github.com/linuxkit/virtsock/pkg/vsock"
)

var (
	console     *log.Logger
	currentConn vConn

	alreadyConnectedOnce bool

	/* When writing we don't discover e.g. EPIPE until the _next_
	 * attempt to write. Therefore we keep a copy of the last
	 * message sent such that we can repeat it after an error.
	 *
	 * Note that this is imperfect since their can be multiple
	 * messages in flight at the point a connection collapses
	 * which will then be lost. This only handles the delayed
	 * notification of such an error to this code.
	 */
	lastMessage []byte
)

/* rfc5425 like scheme, see section 4.3 */
func rfc5425Write(conn vConn, buf []byte) error {

	msglen := fmt.Sprintf("%d ", len(buf))

	_, err := conn.Write([]byte(msglen))
	/* XXX todo, check for serious vs retriable errors */
	if err != nil {
		console.Printf("Error in length write: %s", err)
		return err
	}

	_, err = conn.Write(buf)
	/* XXX todo, check for serious vs retriable errors */
	if err != nil {
		console.Printf("Error in buf write: %s", err)
	}

	return err
}

func forwardSyslogDatagram(buf []byte, portstr string) error {
	for try := 0; try < 2; try++ {
		conn := currentConn
		if conn == nil {
			if strings.Contains(portstr, "-") {
				svcid, err := hvsock.GUIDFromString(portstr)
				if err != nil {
					console.Fatalln("Failed to parse GUID", portstr, err)
				}

				conn, err = hvsock.Dial(hvsock.HypervAddr{VMID: hvsock.GUIDWildcard, ServiceID: svcid})
				if err != nil {
					console.Printf("Failed to dial hvsock port: %s", err)
					continue
				}
			} else {
				port, err := strconv.ParseUint(portstr, 10, 32)
				if err != nil {
					console.Fatalln("Can't convert %s to a uint.", portstr, err)
				}

				conn, err = vsock.Dial(vsock.CIDHost, uint32(port))
				if err != nil {
					console.Printf("Failed to dial vsock port %d: %s", port, err)
					continue
				}
			}

			conn.CloseRead()

			/*
			 * Only log on reconnection, not the initial connection since
			 * that is mostly uninteresting
			 */
			if alreadyConnectedOnce {
				console.Printf("Opened new conn to %s: %#v", portstr, conn)
			}
			alreadyConnectedOnce = true

			if lastMessage != nil {
				console.Printf("Replaying last message: %s", lastMessage)
				err := rfc5425Write(conn, lastMessage)
				if err != nil {
					conn.Close()
					continue
				}
				lastMessage = nil
			}

			currentConn = conn
		}

		err := rfc5425Write(conn, buf)
		if err != nil {
			currentConn.Close()
			currentConn = nil
			console.Printf("Failed to write: %s", string(buf))
			continue
		}

		if try > 0 {
			console.Printf("Forwarded on attempt %d: %s", try+1, string(buf))
		}

		// Keep a copy in case we get an EPIPE from the next write
		lastMessage = make([]byte, len(buf))
		copy(lastMessage, buf)

		return nil
	}

	lastMessage = nil // No point repeating this now
	return errors.New("Failed to send datagram, too many retries")
}

func handleSyslogForward(cfg string) {
	// logging to the default syslog while trying to do syslog
	// forwarding would result in infinite loops, so log all
	// messages in this callchain to the console instead.
	logFile, err := os.OpenFile("/dev/console", os.O_WRONLY, 0)
	if err != nil {
		/* What are the chances of this going anywhere useful... */
		log.Fatalln("Failed to open /dev/console for syslog forward logging", err)
	}

	console = log.New(logFile, "vsyslog: ", log.LstdFlags)

	s := strings.SplitN(cfg, ":", 2)
	if len(s) != 2 {
		console.Fatalf("Failed to parse: %s", cfg)
	}
	vsock := s[0]
	usock := s[1]

	err = os.Remove(usock)
	if err != nil && !os.IsNotExist(err) {
		console.Printf("Failed to remove %s: %s", usock, err)
		/* Try and carry on... */
	}

	l, err := net.ListenUnixgram("unixgram", &net.UnixAddr{Name: usock, Net: "unixgram"})
	if err != nil {
		console.Fatalf("Failed to listen to unixgram:%s: %s", usock, err)
	}

	var buf [4096]byte // Ugh, no way to peek at the next message's size in Go
	for {
		r, err := l.Read(buf[:])
		if err != nil {
			console.Fatalf("Failed to read: %s", err)
		}

		err = forwardSyslogDatagram(buf[:r], vsock)
		if err != nil {
			console.Printf("Failed to send log: %s: %s",
				err, string(buf[:r]))
		}
	}
}