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// +build aix darwin dragonfly freebsd hurd linux netbsd openbsd solaris 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 ipv4AddrToInterface(ip IP) (*Interface, error) {
24	ift, err := Interfaces()
25	if err != nil {
26		return nil, err
27	}
28	for _, ifi := range ift {
29		ifat, err := ifi.Addrs()
30		if err != nil {
31			return nil, err
32		}
33		for _, ifa := range ifat {
34			switch v := ifa.(type) {
35			case *IPAddr:
36				if ip.Equal(v.IP) {
37					return &ifi, nil
38				}
39			case *IPNet:
40				if ip.Equal(v.IP) {
41					return &ifi, nil
42				}
43			}
44		}
45	}
46	if ip.Equal(IPv4zero) {
47		return nil, nil
48	}
49	return nil, errNoSuchInterface
50}
51
52func interfaceToIPv4Addr(ifi *Interface) (IP, error) {
53	if ifi == nil {
54		return IPv4zero, nil
55	}
56	ifat, err := ifi.Addrs()
57	if err != nil {
58		return nil, err
59	}
60	for _, ifa := range ifat {
61		switch v := ifa.(type) {
62		case *IPAddr:
63			if v.IP.To4() != nil {
64				return v.IP, nil
65			}
66		case *IPNet:
67			if v.IP.To4() != nil {
68				return v.IP, nil
69			}
70		}
71	}
72	return nil, errNoSuchInterface
73}
74
75func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error {
76	if ifi == nil {
77		return nil
78	}
79	ifat, err := ifi.Addrs()
80	if err != nil {
81		return err
82	}
83	for _, ifa := range ifat {
84		switch v := ifa.(type) {
85		case *IPAddr:
86			if a := v.IP.To4(); a != nil {
87				copy(mreq.Interface[:], a)
88				goto done
89			}
90		case *IPNet:
91			if a := v.IP.To4(); a != nil {
92				copy(mreq.Interface[:], a)
93				goto done
94			}
95		}
96	}
97done:
98	if bytealg.Equal(mreq.Multiaddr[:], IPv4zero.To4()) {
99		return errNoSuchMulticastInterface
100	}
101	return nil
102}
103
104func setReadBuffer(fd *netFD, bytes int) error {
105	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
106	runtime.KeepAlive(fd)
107	return wrapSyscallError("setsockopt", err)
108}
109
110func setWriteBuffer(fd *netFD, bytes int) error {
111	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes)
112	runtime.KeepAlive(fd)
113	return wrapSyscallError("setsockopt", err)
114}
115
116func setKeepAlive(fd *netFD, keepalive bool) error {
117	err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, boolint(keepalive))
118	runtime.KeepAlive(fd)
119	return wrapSyscallError("setsockopt", err)
120}
121
122func setLinger(fd *netFD, sec int) error {
123	var l syscall.Linger
124	if sec >= 0 {
125		l.Onoff = 1
126		l.Linger = int32(sec)
127	} else {
128		l.Onoff = 0
129		l.Linger = 0
130	}
131	err := fd.pfd.SetsockoptLinger(syscall.SOL_SOCKET, syscall.SO_LINGER, &l)
132	runtime.KeepAlive(fd)
133	return wrapSyscallError("setsockopt", err)
134}
135