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) 35 36type ServerListener struct { 37 listenerID int 38 listener *zbxcomms.Listener 39 scheduler scheduler.Scheduler 40 options *agent.AgentOptions 41 tlsConfig *tls.Config 42 allowedPeers *AllowedPeers 43 bindIP string 44} 45 46func (sl *ServerListener) processConnection(conn *zbxcomms.Connection) (err error) { 47 defer func() { 48 if err != nil { 49 conn.Close() 50 } 51 }() 52 53 var data []byte 54 if data, err = conn.Read(); err != nil { 55 return 56 } 57 58 log.Debugf("received passive check request: '%s' from '%s'", string(data), conn.RemoteIP()) 59 60 response := passiveCheck{conn: &passiveConnection{conn: conn}, scheduler: sl.scheduler} 61 go response.handleCheck(data) 62 63 return nil 64} 65 66func (sl *ServerListener) run() { 67 defer log.PanicHook() 68 log.Debugf("[%d] starting listener for '%s:%d'", sl.listenerID, sl.bindIP, sl.options.ListenPort) 69 70 for { 71 conn, err := sl.listener.Accept(time.Second*time.Duration(sl.options.Timeout), 72 zbxcomms.TimeoutModeShift) 73 74 if err == nil { 75 if !sl.allowedPeers.CheckPeer(net.ParseIP(conn.RemoteIP())) { 76 conn.Close() 77 log.Warningf("cannot accept incoming connection for peer: %s", conn.RemoteIP()) 78 } else if err := sl.processConnection(conn); err != nil { 79 log.Warningf("cannot process incoming connection: %s", err.Error()) 80 } 81 } else { 82 if nerr, ok := err.(net.Error); ok && nerr.Temporary() { 83 log.Errf("cannot accept incoming connection: %s", err.Error()) 84 continue 85 } 86 break 87 } 88 } 89 90 log.Debugf("listener has been stopped") 91 monitor.Unregister(monitor.Input) 92 93} 94 95func New(listenerID int, s scheduler.Scheduler, bindIP string, options *agent.AgentOptions) (sl *ServerListener) { 96 sl = &ServerListener{listenerID: listenerID, scheduler: s, bindIP: bindIP, options: options} 97 return 98} 99 100func (sl *ServerListener) Start() (err error) { 101 if sl.tlsConfig, err = agent.GetTLSConfig(sl.options); err != nil { 102 return 103 } 104 if sl.allowedPeers, err = GetAllowedPeers(sl.options); err != nil { 105 return 106 } 107 if sl.listener, err = zbxcomms.Listen(fmt.Sprintf("[%s]:%d", sl.bindIP, sl.options.ListenPort), sl.tlsConfig); err != nil { 108 return 109 } 110 monitor.Register(monitor.Input) 111 go sl.run() 112 return 113} 114 115func (sl *ServerListener) Stop() { 116 if sl.listener != nil { 117 sl.listener.Close() 118 } 119} 120 121// ParseListenIP validate ListenIP value 122func ParseListenIP(options *agent.AgentOptions) (ips []string, err error) { 123 if 0 == len(options.ListenIP) || options.ListenIP == "0.0.0.0" { 124 return []string{"0.0.0.0"}, nil 125 } 126 lips := getListLocalIP() 127 opts := strings.Split(options.ListenIP, ",") 128 for _, o := range opts { 129 addr := strings.Trim(o, " \t") 130 if err = validateLocalIP(addr, lips); nil != err { 131 return nil, err 132 } 133 ips = append(ips, addr) 134 } 135 return ips, nil 136} 137 138func validateLocalIP(addr string, lips *[]net.IP) (err error) { 139 if ip := net.ParseIP(addr); nil != ip { 140 if ip.IsLoopback() || 0 == len(*lips) { 141 return nil 142 } 143 for _, lip := range *lips { 144 if lip.Equal(ip) { 145 return nil 146 } 147 } 148 } else { 149 return fmt.Errorf("incorrect value of ListenIP: \"%s\"", addr) 150 } 151 return fmt.Errorf("value of ListenIP not present on the host: \"%s\"", addr) 152} 153 154func getListLocalIP() *[]net.IP { 155 var ips []net.IP 156 157 ifaces, err := net.Interfaces() 158 if nil != err { 159 return &ips 160 } 161 162 for _, i := range ifaces { 163 addrs, err := i.Addrs() 164 if nil != err { 165 return &ips 166 } 167 168 for _, addr := range addrs { 169 var ip net.IP 170 switch v := addr.(type) { 171 case *net.IPNet: 172 ip = v.IP 173 case *net.IPAddr: 174 ip = v.IP 175 } 176 ips = append(ips, ip) 177 } 178 } 179 180 return &ips 181} 182