1/* 2** Zabbix 3** Copyright (C) 2001-2021 Zabbix SIA 4** 5** This program is free software; you can redistribute it and/or modify 6** it under the terms of the GNU General Public License as published by 7** the Free Software Foundation; either version 2 of the License, or 8** (at your option) any later version. 9** 10** This program is distributed in the hope that it will be useful, 11** but WITHOUT ANY WARRANTY; without even the implied warranty of 12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13** GNU General Public License for more details. 14** 15** You should have received a copy of the GNU General Public License 16** along with this program; if not, write to the Free Software 17** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18**/ 19 20package serverlistener 21 22import ( 23 "fmt" 24 "net" 25 "strings" 26 "time" 27 28 "zabbix.com/internal/agent" 29 "zabbix.com/internal/agent/scheduler" 30 "zabbix.com/internal/monitor" 31 "zabbix.com/pkg/log" 32 "zabbix.com/pkg/tls" 33 "zabbix.com/pkg/zbxcomms" 34 "zabbix.com/pkg/zbxnet" 35) 36 37type ServerListener struct { 38 listenerID int 39 listener *zbxcomms.Listener 40 scheduler scheduler.Scheduler 41 options *agent.AgentOptions 42 tlsConfig *tls.Config 43 allowedPeers *zbxnet.AllowedPeers 44 bindIP string 45} 46 47func (sl *ServerListener) processConnection(conn *zbxcomms.Connection) (err error) { 48 defer func() { 49 if err != nil { 50 conn.Close() 51 } 52 }() 53 54 var data []byte 55 if data, err = conn.Read(); err != nil { 56 return 57 } 58 59 log.Debugf("received passive check request: '%s' from '%s'", string(data), conn.RemoteIP()) 60 61 response := passiveCheck{conn: &passiveConnection{conn: conn}, scheduler: sl.scheduler} 62 go response.handleCheck(data) 63 64 return nil 65} 66 67func (sl *ServerListener) run() { 68 defer log.PanicHook() 69 log.Debugf("[%d] starting listener for '%s:%d'", sl.listenerID, sl.bindIP, sl.options.ListenPort) 70 71 for { 72 conn, err := sl.listener.Accept(time.Second*time.Duration(sl.options.Timeout), 73 zbxcomms.TimeoutModeShift) 74 75 if err == nil { 76 if !sl.allowedPeers.CheckPeer(net.ParseIP(conn.RemoteIP())) { 77 conn.Close() 78 log.Warningf("cannot accept incoming connection for peer: %s", conn.RemoteIP()) 79 } else if err := sl.processConnection(conn); err != nil { 80 log.Warningf("cannot process incoming connection: %s", err.Error()) 81 } 82 } else { 83 if nerr, ok := err.(net.Error); ok && nerr.Temporary() { 84 log.Errf("cannot accept incoming connection: %s", err.Error()) 85 continue 86 } 87 break 88 } 89 } 90 91 log.Debugf("listener has been stopped") 92 monitor.Unregister(monitor.Input) 93 94} 95 96func New(listenerID int, s scheduler.Scheduler, bindIP string, options *agent.AgentOptions) (sl *ServerListener) { 97 sl = &ServerListener{listenerID: listenerID, scheduler: s, bindIP: bindIP, options: options} 98 return 99} 100 101func (sl *ServerListener) Start() (err error) { 102 if sl.tlsConfig, err = agent.GetTLSConfig(sl.options); err != nil { 103 return 104 } 105 if sl.allowedPeers, err = zbxnet.GetAllowedPeers(sl.options.Server); err != nil { 106 return 107 } 108 if sl.listener, err = zbxcomms.Listen(fmt.Sprintf("[%s]:%d", sl.bindIP, sl.options.ListenPort), sl.tlsConfig); err != nil { 109 return 110 } 111 monitor.Register(monitor.Input) 112 go sl.run() 113 return 114} 115 116func (sl *ServerListener) Stop() { 117 if sl.listener != nil { 118 sl.listener.Close() 119 } 120} 121 122// ParseListenIP validate ListenIP value 123func ParseListenIP(options *agent.AgentOptions) (ips []string, err error) { 124 if 0 == len(options.ListenIP) || options.ListenIP == "0.0.0.0" { 125 return []string{"0.0.0.0"}, nil 126 } 127 lips := getListLocalIP() 128 opts := strings.Split(options.ListenIP, ",") 129 for _, o := range opts { 130 addr := strings.Trim(o, " \t") 131 if err = validateLocalIP(addr, lips); nil != err { 132 return nil, err 133 } 134 ips = append(ips, addr) 135 } 136 return ips, nil 137} 138 139func validateLocalIP(addr string, lips *[]net.IP) (err error) { 140 if ip := net.ParseIP(addr); nil != ip { 141 if ip.IsLoopback() || 0 == len(*lips) { 142 return nil 143 } 144 for _, lip := range *lips { 145 if lip.Equal(ip) { 146 return nil 147 } 148 } 149 } else { 150 return fmt.Errorf("incorrect value of ListenIP: \"%s\"", addr) 151 } 152 return fmt.Errorf("value of ListenIP not present on the host: \"%s\"", addr) 153} 154 155func getListLocalIP() *[]net.IP { 156 var ips []net.IP 157 158 ifaces, err := net.Interfaces() 159 if nil != err { 160 return &ips 161 } 162 163 for _, i := range ifaces { 164 addrs, err := i.Addrs() 165 if nil != err { 166 return &ips 167 } 168 169 for _, addr := range addrs { 170 var ip net.IP 171 switch v := addr.(type) { 172 case *net.IPNet: 173 ip = v.IP 174 case *net.IPAddr: 175 ip = v.IP 176 } 177 ips = append(ips, ip) 178 } 179 } 180 181 return &ips 182} 183