Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit e76df40

Browse files
committedMar 22, 2025·
Make sockopt.interface work with UDP on Darwin
1 parent 607c2a6 commit e76df40

File tree

2 files changed

+36
-39
lines changed

2 files changed

+36
-39
lines changed
 

‎transport/internet/sockopt_darwin.go

+35-38
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package internet
22

33
import (
4-
network "net"
4+
gonet "net"
55
"os"
66
"syscall"
77
"unsafe"
@@ -108,14 +108,6 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
108108
return err
109109
}
110110
}
111-
if config.Interface != "" {
112-
InterfaceIndex := getInterfaceIndexByName(config.Interface)
113-
if InterfaceIndex != 0 {
114-
if err := unix.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_BOUND_IF, InterfaceIndex); err != nil {
115-
return errors.New("failed to set Interface").Base(err)
116-
}
117-
}
118-
}
119111

120112
if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 {
121113
if config.TcpKeepAliveIdle > 0 {
@@ -138,6 +130,23 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
138130
}
139131
}
140132

133+
if config.Interface != "" {
134+
iface, err := gonet.InterfaceByName(config.Interface)
135+
136+
if err != nil {
137+
return errors.New("failed to get interface ", config.Interface).Base(err)
138+
}
139+
if network == "tcp6" || network == "udp6" {
140+
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, iface.Index); err != nil {
141+
return errors.New("failed to set IPV6_BOUND_IF").Base(err)
142+
}
143+
} else {
144+
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index); err != nil {
145+
return errors.New("failed to set IP_BOUND_IF").Base(err)
146+
}
147+
}
148+
}
149+
141150
return nil
142151
}
143152

@@ -152,14 +161,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
152161
return err
153162
}
154163
}
155-
if config.Interface != "" {
156-
InterfaceIndex := getInterfaceIndexByName(config.Interface)
157-
if InterfaceIndex != 0 {
158-
if err := unix.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_BOUND_IF, InterfaceIndex); err != nil {
159-
return errors.New("failed to set Interface").Base(err)
160-
}
161-
}
162-
}
163164

164165
if config.TcpKeepAliveIdle > 0 || config.TcpKeepAliveInterval > 0 {
165166
if config.TcpKeepAliveIdle > 0 {
@@ -182,6 +183,23 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
182183
}
183184
}
184185

186+
if config.Interface != "" {
187+
iface, err := gonet.InterfaceByName(config.Interface)
188+
189+
if err != nil {
190+
return errors.New("failed to get interface ", config.Interface).Base(err)
191+
}
192+
if network == "tcp6" || network == "udp6" {
193+
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, iface.Index); err != nil {
194+
return errors.New("failed to set IPV6_BOUND_IF").Base(err)
195+
}
196+
} else {
197+
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index); err != nil {
198+
return errors.New("failed to set IP_BOUND_IF").Base(err)
199+
}
200+
}
201+
}
202+
185203
return nil
186204
}
187205

@@ -224,24 +242,3 @@ func setReusePort(fd uintptr) error {
224242
}
225243
return nil
226244
}
227-
func getInterfaceIndexByName(name string) int {
228-
ifaces, err := network.Interfaces()
229-
if err == nil {
230-
for _, iface := range ifaces {
231-
if (iface.Flags&network.FlagUp == network.FlagUp) && (iface.Flags&network.FlagLoopback != network.FlagLoopback) {
232-
addrs, _ := iface.Addrs()
233-
for _, addr := range addrs {
234-
if ipnet, ok := addr.(*network.IPNet); ok && !ipnet.IP.IsLoopback() {
235-
if ipnet.IP.To4() != nil {
236-
if iface.Name == name {
237-
return iface.Index
238-
}
239-
}
240-
}
241-
}
242-
}
243-
244-
}
245-
}
246-
return 0
247-
}

‎transport/internet/system_dialer.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func hasBindAddr(sockopt *SocketConfig) bool {
5151
func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
5252
errors.LogDebug(ctx, "dialing to "+dest.String())
5353

54-
if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) {
54+
if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) && sockopt.Interface == "" {
5555
srcAddr := resolveSrcAddr(net.Network_UDP, src)
5656
if srcAddr == nil {
5757
srcAddr = &net.UDPAddr{

0 commit comments

Comments
 (0)
Please sign in to comment.