mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 05:40:42 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			74 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
		
			2.1 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
 | |
| 	}
 | |
| 	// Calling File() above results in the connection becoming blocking, we must fix that.
 | |
| 	// See https://github.com/miekg/dns/issues/279
 | |
| 	err = syscall.SetNonblock(int(file.Fd()), true)
 | |
| 	if 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
 | |
| 	}
 | |
| 	err = syscall.SetNonblock(int(file.Fd()), true)
 | |
| 	if 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()))
 | |
| }
 |