mirror of
				https://github.com/miekg/dns.git
				synced 2025-11-04 12:41:01 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			64 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			64 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build linux
 | 
						|
 | 
						|
package dns
 | 
						|
 | 
						|
// See:
 | 
						|
// * http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket and
 | 
						|
// * http://blog.powerdns.com/2012/10/08/on-binding-datagram-udp-sockets-to-the-any-addresses/
 | 
						|
//
 | 
						|
// Why do we need this: When listening on 0.0.0.0 with UDP so kernel decides what is the outgoing
 | 
						|
// interface, this might not always be the correct one. This code will make sure the egress
 | 
						|
// packet's interface matched the ingress' one.
 | 
						|
 | 
						|
import (
 | 
						|
	"net"
 | 
						|
	"syscall"
 | 
						|
)
 | 
						|
 | 
						|
// setUDPSocketOptions4 prepares the v4 socket for sessions.
 | 
						|
func setUDPSocketOptions4(conn *net.UDPConn) error {
 | 
						|
	file, err := conn.File()
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IP, syscall.IP_PKTINFO, 1); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// setUDPSocketOptions6 prepares the v6 socket for sessions.
 | 
						|
func setUDPSocketOptions6(conn *net.UDPConn) error {
 | 
						|
	file, err := conn.File()
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	if err := syscall.SetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_RECVPKTINFO, 1); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// getUDPSocketOption6Only return true if the socket is v6 only and false when it is v4/v6 combined
 | 
						|
// (dualstack).
 | 
						|
func getUDPSocketOptions6Only(conn *net.UDPConn) (bool, error) {
 | 
						|
	file, err := conn.File()
 | 
						|
	if err != nil {
 | 
						|
		return false, err
 | 
						|
	}
 | 
						|
	// dual stack. See http://stackoverflow.com/questions/1618240/how-to-support-both-ipv4-and-ipv6-connections
 | 
						|
	v6only, err := syscall.GetsockoptInt(int(file.Fd()), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY)
 | 
						|
	if err != nil {
 | 
						|
		return false, err
 | 
						|
	}
 | 
						|
	return v6only == 1, nil
 | 
						|
}
 | 
						|
 | 
						|
func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
 | 
						|
	file, err := conn.File()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return syscall.Getsockname(int(file.Fd()))
 | 
						|
}
 |