diff --git a/client/src/components/App/index.css b/client/src/components/App/index.css index 990f13e438d..fa8ca78899b 100644 --- a/client/src/components/App/index.css +++ b/client/src/components/App/index.css @@ -52,7 +52,7 @@ body { .modal-body--medium { max-height: 20rem; - overflow-y: scroll; + overflow-y: auto; } .modal-body__item:not(:first-child) { diff --git a/client/src/components/Logs/Cells/IconTooltip.css b/client/src/components/Logs/Cells/IconTooltip.css index 811c7623392..ff3f492651c 100644 --- a/client/src/components/Logs/Cells/IconTooltip.css +++ b/client/src/components/Logs/Cells/IconTooltip.css @@ -6,7 +6,7 @@ pointer-events: auto !important; background-color: var(--white); z-index: 102; - overflow-y: scroll; + overflow-y: auto; max-height: 100%; } diff --git a/client/src/components/Logs/Logs.css b/client/src/components/Logs/Logs.css index 76b955450f1..25015461ea7 100644 --- a/client/src/components/Logs/Logs.css +++ b/client/src/components/Logs/Logs.css @@ -388,7 +388,7 @@ border-collapse: collapse; contain: layout; overflow-x: hidden; - overflow-y: scroll; + overflow-y: auto; will-change: scroll-position; } diff --git a/go.mod b/go.mod index 198bba1ef88..fb1a886db49 100644 --- a/go.mod +++ b/go.mod @@ -32,4 +32,5 @@ require ( howett.net/plist v0.0.0-20201203080718-1454fab16a06 ) +// TODO(e.burkov): Get rid of the fork in v0.108.0. replace github.com/insomniacslk/dhcp => github.com/AdguardTeam/dhcp v0.0.0-20210519141215-51808c73c0bf diff --git a/internal/aghnet/dhcp_unix.go b/internal/aghnet/dhcp_unix.go index a4a3820dee4..479d9926eae 100644 --- a/internal/aghnet/dhcp_unix.go +++ b/internal/aghnet/dhcp_unix.go @@ -112,12 +112,12 @@ func discover4(iface *net.Interface, dstAddr *net.UDPAddr, hostname string) (ok // It's also known that listening on the specified interface's address // ignores broadcasted packets when reading. var c net.PacketConn - if c, err = net.ListenPacket("udp4", ":68"); err != nil { + if c, err = listenPacketReusable(iface.Name, "udp4", ":68"); err != nil { return false, fmt.Errorf("couldn't listen on :68: %w", err) } defer func() { err = errors.WithDeferred(err, c.Close()) }() - // Send to resolved broadcast. + // Send to broadcast. if _, err = c.WriteTo(req.ToBytes(), dstAddr); err != nil { return false, fmt.Errorf("couldn't send a packet to %s: %w", dstAddr, err) } @@ -154,9 +154,6 @@ func tryConn4(req *dhcpv4.DHCPv4, c net.PacketConn, iface *net.Interface) (ok, n b := make([]byte, 1500) n, _, err := c.ReadFrom(b) - if n > 0 { - log.Debug("received %d bytes: %v", n, b) - } if err != nil { if isTimeout(err) { log.Debug("dhcpv4: didn't receive dhcp response") diff --git a/internal/aghnet/interfaces_linux.go b/internal/aghnet/interfaces_linux.go new file mode 100644 index 00000000000..a3cda5fa765 --- /dev/null +++ b/internal/aghnet/interfaces_linux.go @@ -0,0 +1,24 @@ +//go:build linux +// +build linux + +package aghnet + +import ( + "net" + + "github.com/AdguardTeam/golibs/netutil" + "github.com/insomniacslk/dhcp/dhcpv4/nclient4" +) + +// listenPacketReusable announces on the local network address additionally +// configuring the socket to have a reusable binding. +func listenPacketReusable(ifaceName, network, address string) (c net.PacketConn, err error) { + var port int + _, port, err = netutil.SplitHostPort(address) + if err != nil { + return nil, err + } + + // TODO(e.burkov): Inspect nclient4.NewRawUDPConn and implement here. + return nclient4.NewRawUDPConn(ifaceName, port) +} diff --git a/internal/aghnet/interfaces_unix.go b/internal/aghnet/interfaces_unix.go new file mode 100644 index 00000000000..529b0d9cb73 --- /dev/null +++ b/internal/aghnet/interfaces_unix.go @@ -0,0 +1,51 @@ +//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd || solaris +// +build aix darwin dragonfly freebsd netbsd openbsd solaris + +package aghnet + +import ( + "context" + "fmt" + "net" + "os" + "syscall" + + "github.com/AdguardTeam/golibs/errors" + "golang.org/x/sys/unix" +) + +// reuseAddrCtrl is the function to be set to net.ListenConfig.Control. It +// configures the socket to have a reusable port binding. +func reuseAddrCtrl(_, _ string, c syscall.RawConn) (err error) { + cerr := c.Control(func(fd uintptr) { + // TODO(e.burkov): Consider using SO_REUSEPORT. + err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1) + if err != nil { + err = os.NewSyscallError("setsockopt", err) + } + }) + + const ( + errMsg = "setting control options" + errMsgFmt = errMsg + ": %w" + ) + + if err != nil && cerr != nil { + err = errors.List(errMsg, err, cerr) + } else if err != nil { + err = fmt.Errorf(errMsgFmt, err) + } else if cerr != nil { + err = fmt.Errorf(errMsgFmt, cerr) + } + + return err +} + +// listenPacketReusable announces on the local network address additionally +// configuring the socket to have a reusable binding. +func listenPacketReusable(_, network, address string) (c net.PacketConn, err error) { + var lc net.ListenConfig + lc.Control = reuseAddrCtrl + + return lc.ListenPacket(context.Background(), network, address) +} diff --git a/internal/aghnet/interfaces_windows.go b/internal/aghnet/interfaces_windows.go new file mode 100644 index 00000000000..e483c350372 --- /dev/null +++ b/internal/aghnet/interfaces_windows.go @@ -0,0 +1,18 @@ +//go:build windows +// +build windows + +package aghnet + +import ( + "net" + + "github.com/AdguardTeam/AdGuardHome/internal/aghos" +) + +// listenPacketReusable announces on the local network address additionally +// configuring the socket to have a reusable binding. +func listenPacketReusable(_, _, _ string) (c net.PacketConn, err error) { + // TODO(e.burkov): Check if we are able to control sockets on Windows + // in the same way as on Unix. + return nil, aghos.Unsupported("listening packet reusable") +} diff --git a/internal/aghnet/net_openbsd.go b/internal/aghnet/net_openbsd.go index d2604005775..a2b5e6e62a1 100644 --- a/internal/aghnet/net_openbsd.go +++ b/internal/aghnet/net_openbsd.go @@ -31,11 +31,11 @@ func hostnameIfStaticConfig(r io.Reader) (_ []string, ok bool, err error) { line := strings.TrimSpace(s.Text()) fields := strings.Fields(line) if len(fields) >= 2 && fields[0] == "inet" && net.ParseIP(fields[1]) != nil { - return nil, true, s.Err() + return nil, false, s.Err() } } - return nil, false, s.Err() + return nil, true, s.Err() } func ifaceSetStaticIP(string) (err error) {