Skip to content

Commit

Permalink
support for no priority as specified in rfc3164 section 4.3.3 (#57)
Browse files Browse the repository at this point in the history
* support for no priority as specified in rfc3164 section 4.3.3

* set timestamp to now when no priority is specified
  • Loading branch information
glicht authored and mcuadros committed Aug 15, 2019
1 parent 277e703 commit 6b49a39
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 13 deletions.
26 changes: 16 additions & 10 deletions format/automatic.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package format
import (
"bufio"
"bytes"
"errors"
"strconv"

"gopkg.in/mcuadros/go-syslog.v2/internal/syslogparser/rfc3164"
Expand Down Expand Up @@ -31,33 +30,40 @@ const (
detectedRFC6587 = iota
)

func detect(data []byte) (detected int, err error) {
/*
* Will always fallback to rfc3164 (see section 4.3.3)
*/
func detect(data []byte) int {
// all formats have a sapce somewhere
if i := bytes.IndexByte(data, ' '); i > 0 {
pLength := data[0:i]
if _, err := strconv.Atoi(string(pLength)); err == nil {
return detectedRFC6587, nil
return detectedRFC6587
}
// are we starting with <
if data[0] != '<' {
return detectedRFC3164
}

// is there a close angle bracket before the ' '? there should be
angle := bytes.IndexByte(data, '>')
if (angle < 0) || (angle >= i) {
return detectedUnknown, errors.New("No close angle bracket before space")
return detectedRFC3164
}

// if a single digit immediately follows the angle bracket, then a space
// it is RFC5424, as RFC3164 must begin with a letter (month name)
if (angle+2 == i) && (data[angle+1] >= '0') && (data[angle+1] <= '9') {
return detectedRFC5424, nil
return detectedRFC5424
} else {
return detectedRFC3164, nil
return detectedRFC3164
}
}
return detectedUnknown, nil
// fallback to rfc 3164 section 4.3.3
return detectedRFC3164
}

func (f *Automatic) GetParser(line []byte) LogParser {
switch format, _ := detect(line); format {
switch format := detect(line); format {
case detectedRFC3164:
return &parserWrapper{rfc3164.NewParser(line)}
case detectedRFC5424:
Expand All @@ -82,7 +88,7 @@ func (f *Automatic) automaticScannerSplit(data []byte, atEOF bool) (advance int,
return 0, nil, nil
}

switch format, err := detect(data); format {
switch format := detect(data); format {
case detectedRFC6587:
return rfc6587ScannerSplit(data, atEOF)
case detectedRFC3164, detectedRFC5424:
Expand Down
14 changes: 12 additions & 2 deletions internal/syslogparser/rfc3164/rfc3164.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,22 @@ func (p *Parser) Location(location *time.Location) {
}

func (p *Parser) Parse() error {
tcursor := p.cursor
pri, err := p.parsePriority()
if err != nil {
return err
// RFC3164 sec 4.3.3
p.priority = syslogparser.Priority{13, syslogparser.Facility{Value: 1}, syslogparser.Severity{Value: 5}}
p.cursor = tcursor
content, err := p.parseContent()
p.header.timestamp = time.Now().Round(time.Second)
if err != syslogparser.ErrEOL {
return err
}
p.message = rfc3164message{content: content}
return nil
}

tcursor := p.cursor
tcursor = p.cursor
hdr, err := p.parseHeader()
if err == syslogparser.ErrTimestampUnknownFormat {
// RFC3164 sec 4.3.2.
Expand Down
49 changes: 49 additions & 0 deletions internal/syslogparser/rfc3164/rfc3164_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ func (s *Rfc3164TestSuite) TestParser_NoTimestamp(c *C) {
now := time.Now()

obtained := p.Dump()

obtainedTime := obtained["timestamp"].(time.Time)
s.assertTimeIsCloseToNow(c, obtainedTime)

obtained["timestamp"] = now // XXX: Need to mock out time to test this fully
expected := syslogparser.LogParts{
"timestamp": now,
Expand All @@ -121,6 +125,43 @@ func (s *Rfc3164TestSuite) TestParser_NoTimestamp(c *C) {
c.Assert(obtained, DeepEquals, expected)
}

// RFC 3164 section 4.3.3
func (s *Rfc3164TestSuite) TestParser_NoPriority(c *C) {
buff := []byte("Oct 11 22:14:15 Testing no priority")

p := NewParser(buff)
expectedP := &Parser{
buff: buff,
cursor: 0,
l: len(buff),
location: time.UTC,
}

c.Assert(p, DeepEquals, expectedP)

err := p.Parse()
c.Assert(err, IsNil)

now := time.Now()

obtained := p.Dump()
obtainedTime := obtained["timestamp"].(time.Time)
s.assertTimeIsCloseToNow(c, obtainedTime)

obtained["timestamp"] = now // XXX: Need to mock out time to test this fully
expected := syslogparser.LogParts{
"timestamp": now,
"hostname": "",
"tag": "",
"content": "Oct 11 22:14:15 Testing no priority",
"priority": 13,
"facility": 1,
"severity": 5,
}

c.Assert(obtained, DeepEquals, expected)
}

func (s *Rfc3164TestSuite) TestParseHeader_Valid(c *C) {
buff := []byte("Oct 11 22:14:15 mymachine ")
now := time.Now()
Expand Down Expand Up @@ -375,3 +416,11 @@ func (s *Rfc3164TestSuite) assertRfc3164message(c *C, msg rfc3164message, b []by
c.Assert(obtained, Equals, msg)
c.Assert(p.cursor, Equals, expC)
}

func (s *Rfc3164TestSuite) assertTimeIsCloseToNow(c *C, obtainedTime time.Time) {
now := time.Now()
timeStart := now.Add(-(time.Second * 5))
timeEnd := now.Add(time.Second)
c.Assert(obtainedTime.After(timeStart), Equals, true)
c.Assert(obtainedTime.Before(timeEnd), Equals, true)
}
2 changes: 1 addition & 1 deletion server.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ func (s *Server) parser(line []byte, client string, tlsPeer string) {

logParts := parser.Dump()
logParts["client"] = client
if logParts["hostname"] == "" && s.format == RFC3164 {
if logParts["hostname"] == "" && (s.format == RFC3164 || s.format == Automatic) {
if i := strings.Index(client, ":"); i > 1 {
logParts["hostname"] = client[:i]
} else {
Expand Down
19 changes: 19 additions & 0 deletions server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type ServerSuite struct {
var _ = Suite(&ServerSuite{})
var exampleSyslog = "<31>Dec 26 05:08:46 hostname tag[296]: content"
var exampleSyslogNoTSTagHost = "<14>INFO leaving (1) step postscripts"
var exampleSyslogNoPriority = "Dec 26 05:08:46 hostname test with no priority - see rfc 3164 section 4.3.3"
var exampleRFC5424Syslog = "<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - ID47 - 'su root' failed for lonvick on /dev/pts/8"

func (s *ServerSuite) TestTailFile(c *C) {
Expand Down Expand Up @@ -184,6 +185,24 @@ func (s *ServerSuite) TestUDP3164NoTag(c *C) {
c.Check(handler.LastError, IsNil)
}

func (s *ServerSuite) TestUDPAutomatic3164NoPriority(c *C) {
handler := new(HandlerMock)
server := NewServer()
server.SetFormat(Automatic)
server.SetHandler(handler)
server.SetTimeout(10)
server.goParseDatagrams()
server.datagramChannel <- DatagramMessage{[]byte(exampleSyslogNoPriority), "127.0.0.1:45789"}
close(server.datagramChannel)
server.Wait()
c.Check(handler.LastLogParts["hostname"], Equals, "127.0.0.1")
c.Check(handler.LastLogParts["tag"], Equals, "")
c.Check(handler.LastLogParts["priority"], Equals, 13)
c.Check(handler.LastLogParts["content"], Equals, exampleSyslogNoPriority)
c.Check(handler.LastMessageLength, Equals, int64(len(exampleSyslogNoPriority)))
c.Check(handler.LastError, IsNil)
}

func (s *ServerSuite) TestUDP6587(c *C) {
handler := new(HandlerMock)
server := NewServer()
Expand Down

0 comments on commit 6b49a39

Please sign in to comment.