1// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build unix || windows
6
7package net
8
9import (
10	"internal/bytealg"
11	"runtime"
12	"syscall"
13)
14
15// Boolean to int.
16func boolint(b bool) int {
17	if b {
18		return 1
19	}
20	return 0
21}
22
23func interfaceToIPv4Addr(ifi *Interface) (IP, error) {
24	if ifi == nil {
25		return IPv4zero, nil
26	}
27	ifat, err := ifi.Addrs()
28	if err != nil {
29		return nil, err
30	}
31	for _, ifa := range ifat {
32		switch v := ifa.(type) {
33		case *IPAddr:
34			if v.IP.To4() != nil {
35				return v.IP, nil
36			}
37		case *IPNet:
38			if v.IP.To4() != nil {
39				return v.IP, nil
40			}
41		}
42	}
43	return nil, errNoSuchInterface
44}
45
46func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error {
47	if ifi == nil {
48		return nil
49	}
50	ifat, err := ifi.Addrs()
51	if err != nil {
52		return err
53	}
54	for _, ifa := range ifat {
55		switch v := ifa.(type) {
56		case *IPAddr:
57			if a := v.IP.To4(); a != nil {
58				copy(mreq.Interface[:], a)
59				goto done
60			}
61		case *IPNet:
62			if a := v.IP.To4(); a != nil {
63				copy(mreq.Interface[:], a)
64				goto done
65			}
66		}
67	}
68done:
69	if bytealg.Equal(mreq.Multiaddr[:], IPv4zero.To4()) {
70		return errNoSuchMulticastInterface
71	}
72	return nil
73}
74
75func setReadBuffer(fd *netFD, bytes int) error {
76	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
77	runtime.KeepAlive(fd)
78	return wrapSyscallError("setsockopt", err)
79}
80
81func setWriteBuffer(fd *netFD, bytes int) error {
82	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
83	runtime.KeepAlive(fd)
84	return wrapSyscallError("setsockopt", err)
85}
86
87func setKeepAlive(fd *netFD, keepalive bool) error {
88	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
89	runtime.KeepAlive(fd)
90	return wrapSyscallError("setsockopt", err)
91}
92
93func setLinger(fd *netFD, sec int) error {
94	var l syscall.Linger
95	if sec >= 0 {
96		l.Onoff = 1
97		l.Linger = int32(sec)
98	} else {
99		l.Onoff = 0
100		l.Linger = 0
101	}
102	err := fd.pfd.SetsockoptLinger(syscall.SOL_SOCKET, syscall.SO_LINGER, &l)
103	runtime.KeepAlive(fd)
104	return wrapSyscallError("setsockopt", err)
105}
106