diff --git a/pkg/baremetal/pxe/pxe.go b/pkg/baremetal/pxe/pxe.go index d7e609c202..cf126af2b7 100644 --- a/pkg/baremetal/pxe/pxe.go +++ b/pkg/baremetal/pxe/pxe.go @@ -117,7 +117,7 @@ func (s *Server) Serve() error { //tftpSrv.SetTimeout(5 * time.Second) log.Infof("DHCPServer Bind %s %d", s.Address, s.DHCPPort) - dhcpSrv, _, err := dhcp.NewDHCPServer2(s.Address, s.DHCPPort) + dhcpSrv, _, err := dhcp.NewDHCPServer2(s.Address, s.DHCPPort, false) if err != nil { return err } diff --git a/pkg/hostman/hostinfo/hostdhcp/dhcprelay.go b/pkg/hostman/hostinfo/hostdhcp/dhcprelay.go index 82d7c8d81e..1bc798e5d4 100644 --- a/pkg/hostman/hostinfo/hostdhcp/dhcprelay.go +++ b/pkg/hostman/hostinfo/hostdhcp/dhcprelay.go @@ -29,7 +29,8 @@ type SDHCPRelay struct { guestDHCPConn *dhcp.Conn - srcaddr string + srcaddr string + nicMasterIp net.IP destaddr net.IP destport int @@ -65,11 +66,12 @@ func (r *SDHCPRelay) Start() { }() } -func (r *SDHCPRelay) Setup(addr string) error { +func (r *SDHCPRelay) Setup(addr string, masterIp net.IP) error { var err error r.srcaddr = addr + r.nicMasterIp = masterIp log.Infof("DHCP Relay Server Bind addr %s port %d", r.srcaddr, DEFAULT_DHCP_RELAY_PORT) - r.server, r.conn, err = dhcp.NewDHCPServer2(r.srcaddr, DEFAULT_DHCP_RELAY_PORT) + r.server, r.conn, err = dhcp.NewDHCPServer2(r.srcaddr, DEFAULT_DHCP_RELAY_PORT, true) if err != nil { log.Errorln(err) return err @@ -79,6 +81,11 @@ func (r *SDHCPRelay) Setup(addr string) error { } func (r *SDHCPRelay) ServeDHCP(pkt dhcp.Packet, addr *net.UDPAddr, intf *net.Interface) (dhcp.Packet, error) { + // Prevent receiving packets that send by host dhcp server + if addr.IP.Equal(r.nicMasterIp) { + return nil, nil + } + log.Infof("Receive DHCP Relay Reply TO %s", pkt.CHAddr()) v, ok := r.cache.Load(pkt.TransactionID()) if ok { diff --git a/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go b/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go index f80fe655ae..ddd7a75fa1 100644 --- a/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go +++ b/pkg/hostman/hostinfo/hostdhcp/dhcpserver.go @@ -35,7 +35,7 @@ func NewGuestDHCPServer(iface string, relay []string) (*SGuestDHCPServer, error) log.Infof("DHCP Server Bind: %s %d", DEFAULT_DHCP_BIND_ADDR, options.HostOptions.DhcpServerPort) guestdhcp.server, guestdhcp.conn, err = dhcp.NewDHCPServer2( - DEFAULT_DHCP_BIND_ADDR, options.HostOptions.DhcpServerPort) + DEFAULT_DHCP_BIND_ADDR, options.HostOptions.DhcpServerPort, false) if err != nil { return nil, err } @@ -61,9 +61,9 @@ func (s *SGuestDHCPServer) Start() { }() } -func (s *SGuestDHCPServer) RelaySetup(addr string) error { +func (s *SGuestDHCPServer) RelaySetup(addr string, masterIp net.IP) error { if s.relay != nil { - return s.relay.Setup(addr) + return s.relay.Setup(addr, masterIp) } return nil } diff --git a/pkg/hostman/hostinfo/hostinfohelper.go b/pkg/hostman/hostinfo/hostinfohelper.go index 481a584303..aff17cd4e1 100644 --- a/pkg/hostman/hostinfo/hostinfohelper.go +++ b/pkg/hostman/hostinfo/hostinfohelper.go @@ -3,6 +3,7 @@ package hostinfo import ( "bufio" "context" + "net" "os" "regexp" "strconv" @@ -193,7 +194,7 @@ func (n *SNIC) EnableDHCPRelay() bool { func (n *SNIC) SetupDhcpRelay() error { if n.EnableDHCPRelay() { - if err := n.dhcpServer.RelaySetup(n.Ip); err != nil { + if err := n.dhcpServer.RelaySetup(n.Ip, net.ParseIP(hostInfo.GetMasterIp())); err != nil { return err } } diff --git a/pkg/util/dhcp/conn.go b/pkg/util/dhcp/conn.go index 44a3930eb2..43ba0223ab 100644 --- a/pkg/util/dhcp/conn.go +++ b/pkg/util/dhcp/conn.go @@ -70,15 +70,15 @@ type Conn struct { } // NewConn creates a Conn bound to the given UDP ip:port. -func NewConn(addr string) (*Conn, error) { - return newConn(addr, newPortableConn) +func NewConn(addr string, disableBroadcast bool) (*Conn, error) { + return newConn(addr, disableBroadcast, newPortableConn) } -func NewSocketConn(addr string) (*Conn, error) { - return newConn(addr, newSocketConn) +func NewSocketConn(addr string, disableBroadcast bool) (*Conn, error) { + return newConn(addr, disableBroadcast, newSocketConn) } -func newConn(addr string, n func(net.IP, int) (conn, error)) (*Conn, error) { +func newConn(addr string, disableBroadcast bool, n func(net.IP, int, bool) (conn, error)) (*Conn, error) { if addr == "" { addr = "0.0.0.0:67" } @@ -100,7 +100,7 @@ func newConn(addr string, n func(net.IP, int) (conn, error)) (*Conn, error) { } } - c, err := n(udpAddr.IP, udpAddr.Port) + c, err := n(udpAddr.IP, udpAddr.Port, disableBroadcast) if err != nil { return nil, err } @@ -224,7 +224,7 @@ type portableConn struct { conn *ipv4.PacketConn } -func newPortableConn(_ net.IP, port int) (conn, error) { +func newPortableConn(_ net.IP, port int, _ bool) (conn, error) { c, err := net.ListenPacket("udp4", fmt.Sprintf(":%d", port)) if err != nil { return nil, err @@ -273,15 +273,21 @@ type socketConn struct { sock int } -func newSocketConn(addr net.IP, port int) (conn, error) { +func newSocketConn(addr net.IP, port int, disableBroadcast bool) (conn, error) { + var broadcastOpt = 1 + if disableBroadcast { + broadcastOpt = 0 + } sock, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0) if err != nil { return nil, err } - if err = syscall.SetsockoptInt(sock, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { + err = syscall.SetsockoptInt(sock, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) + if err != nil { return nil, err } - if err = syscall.SetsockoptInt(sock, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1); err != nil { + err = syscall.SetsockoptInt(sock, syscall.SOL_SOCKET, syscall.SO_BROADCAST, broadcastOpt) + if err != nil { return nil, err } byteAddr := [4]byte{} @@ -296,6 +302,11 @@ func newSocketConn(addr net.IP, port int) (conn, error) { if err = syscall.SetNonblock(sock, false); err != nil { return nil, err } + + // Its equal syscall.CloseOnExec + // most file descriptors are getting set to close-on-exec + // apart from syscall open, socket etc. + syscall.Syscall(syscall.SYS_FCNTL, uintptr(sock), syscall.F_SETFD, syscall.FD_CLOEXEC) return &socketConn{sock}, nil } diff --git a/pkg/util/dhcp/conn_linux.go b/pkg/util/dhcp/conn_linux.go index 23da403aef..2c6435443e 100644 --- a/pkg/util/dhcp/conn_linux.go +++ b/pkg/util/dhcp/conn_linux.go @@ -37,10 +37,10 @@ type linuxConn struct { // Unlike NewConn, NewSnooperConn does not bind to the ip:port, // enabling the Conn to coexist with other services on the machine. func NewSnooperConn(addr string) (*Conn, error) { - return newConn(addr, newLinuxConn) + return newConn(addr, false, newLinuxConn) } -func newLinuxConn(_ net.IP, port int) (conn, error) { +func newLinuxConn(_ net.IP, port int, disableBroadcast bool) (conn, error) { if port == 0 { return nil, errors.New("must specify a listen port") } diff --git a/pkg/util/dhcp/server.go b/pkg/util/dhcp/server.go index 216de3b554..341f76b873 100644 --- a/pkg/util/dhcp/server.go +++ b/pkg/util/dhcp/server.go @@ -21,8 +21,8 @@ func NewDHCPServer(address string, port int) *DHCPServer { } } -func NewDHCPServer2(address string, port int) (*DHCPServer, *Conn, error) { - conn, err := NewSocketConn(fmt.Sprintf("%s:%d", address, port)) +func NewDHCPServer2(address string, port int, disableBroadcast bool) (*DHCPServer, *Conn, error) { + conn, err := NewSocketConn(fmt.Sprintf("%s:%d", address, port), disableBroadcast) if err != nil { return nil, nil, err } @@ -40,7 +40,7 @@ type DHCPHandler interface { func (s *DHCPServer) ListenAndServe(handler DHCPHandler) error { if s.conn == nil { dhcpAddr := fmt.Sprintf("%s:%d", s.Address, s.Port) - dhcpConn, err := NewConn(dhcpAddr) + dhcpConn, err := NewConn(dhcpAddr, false) if err != nil { return fmt.Errorf("Listen DHCP connection error: %v", err) } diff --git a/pkg/util/procutils/procutils.go b/pkg/util/procutils/procutils.go index af376dbb84..d15e0f6383 100644 --- a/pkg/util/procutils/procutils.go +++ b/pkg/util/procutils/procutils.go @@ -5,6 +5,7 @@ import ( "context" "os/exec" "strings" + "syscall" "time" "yunion.io/x/log" @@ -87,6 +88,9 @@ func RunCommandWithTimeout(name string, args ...string) ([]byte, error) { func RunCommandWithContext(ctx context.Context, name string, args ...string) ([]byte, error) { cmd := exec.CommandContext(ctx, name, args...) + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setsid: true, + } var buf bytes.Buffer cmd.Stdout = &buf