github.com/crowdsecurity/crowdsec@v1.6.1/pkg/acquisition/modules/syslog/internal/server/syslogserver.go (about) 1 package syslogserver 2 3 import ( 4 "fmt" 5 "net" 6 "strings" 7 "time" 8 9 log "github.com/sirupsen/logrus" 10 "gopkg.in/tomb.v2" 11 ) 12 13 type SyslogServer struct { 14 listenAddr string 15 port int 16 channel chan SyslogMessage 17 udpConn *net.UDPConn 18 Logger *log.Entry 19 MaxMessageLen int 20 } 21 22 type SyslogMessage struct { 23 Message []byte 24 Client string 25 } 26 27 func (s *SyslogServer) Listen(listenAddr string, port int) error { 28 29 s.listenAddr = listenAddr 30 s.port = port 31 udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", s.listenAddr, s.port)) 32 if err != nil { 33 return fmt.Errorf("could not resolve addr %s: %w", s.listenAddr, err) 34 } 35 udpConn, err := net.ListenUDP("udp", udpAddr) 36 if err != nil { 37 return fmt.Errorf("could not listen on port %d: %w", s.port, err) 38 } 39 s.Logger.Debugf("listening on %s:%d", s.listenAddr, s.port) 40 s.udpConn = udpConn 41 42 err = s.udpConn.SetReadDeadline(time.Now().UTC().Add(100 * time.Millisecond)) 43 if err != nil { 44 return fmt.Errorf("could not set read deadline on UDP socket: %w", err) 45 } 46 return nil 47 } 48 49 func (s *SyslogServer) SetChannel(c chan SyslogMessage) { 50 s.channel = c 51 } 52 53 func (s *SyslogServer) StartServer() *tomb.Tomb { 54 t := tomb.Tomb{} 55 56 t.Go(func() error { 57 for { 58 select { 59 case <-t.Dying(): 60 s.Logger.Info("Syslog server tomb is dying") 61 err := s.KillServer() 62 return err 63 default: 64 //RFC3164 says 1024 bytes max 65 //RFC5424 says 480 bytes minimum, and should support up to 2048 bytes 66 b := make([]byte, s.MaxMessageLen) 67 n, addr, err := s.udpConn.ReadFrom(b) 68 if err != nil && !strings.Contains(err.Error(), "i/o timeout") { 69 s.Logger.Errorf("error while reading from socket : %s", err) 70 s.udpConn.Close() 71 return err 72 } 73 if err == nil { 74 s.channel <- SyslogMessage{Message: b[:n], Client: strings.Split(addr.String(), ":")[0]} 75 } 76 err = s.udpConn.SetReadDeadline(time.Now().UTC().Add(100 * time.Millisecond)) 77 if err != nil { 78 return err 79 } 80 } 81 } 82 }) 83 return &t 84 } 85 86 func (s *SyslogServer) KillServer() error { 87 err := s.udpConn.Close() 88 if err != nil { 89 return fmt.Errorf("could not close UDP connection: %w", err) 90 } 91 close(s.channel) 92 return nil 93 }