summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/miekg/dns/udp_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/miekg/dns/udp_linux.go')
-rw-r--r--vendor/github.com/miekg/dns/udp_linux.go220
1 files changed, 0 insertions, 220 deletions
diff --git a/vendor/github.com/miekg/dns/udp_linux.go b/vendor/github.com/miekg/dns/udp_linux.go
deleted file mode 100644
index 13747ed34..000000000
--- a/vendor/github.com/miekg/dns/udp_linux.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// +build linux,!appengine
-
-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"
- "unsafe"
-
- "github.com/miekg/dns/internal/socket"
-)
-
-const (
- sizeofInet6Pktinfo = 0x14
- sizeofInetPktinfo = 0xc
- protocolIP = 0
- protocolIPv6 = 41
-)
-
-type inetPktinfo struct {
- Ifindex int32
- Spec_dst [4]byte /* in_addr */
- Addr [4]byte /* in_addr */
-}
-
-type inet6Pktinfo struct {
- Addr [16]byte /* in6_addr */
- Ifindex int32
-}
-
-type inetControlMessage struct {
- Src net.IP // source address, specifying only
- Dst net.IP // destination address, receiving only
-}
-
-// setUDPSocketOptions sets the UDP socket options.
-// This function is implemented on a per platform basis. See udp_*.go for more details
-func setUDPSocketOptions(conn *net.UDPConn) error {
- sa, err := getUDPSocketName(conn)
- if err != nil {
- return err
- }
- switch sa.(type) {
- case *syscall.SockaddrInet6:
- v6only, err := getUDPSocketOptions6Only(conn)
- if err != nil {
- return err
- }
- setUDPSocketOptions6(conn)
- if !v6only {
- setUDPSocketOptions4(conn)
- }
- case *syscall.SockaddrInet4:
- setUDPSocketOptions4(conn)
- }
- return nil
-}
-
-// 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 {
- file.Close()
- 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 {
- file.Close()
- return err
- }
- file.Close()
- 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 {
- file.Close()
- return err
- }
- err = syscall.SetNonblock(int(file.Fd()), true)
- if err != nil {
- file.Close()
- return err
- }
- file.Close()
- 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 {
- file.Close()
- return false, err
- }
- file.Close()
- return v6only == 1, nil
-}
-
-func getUDPSocketName(conn *net.UDPConn) (syscall.Sockaddr, error) {
- file, err := conn.File()
- if err != nil {
- return nil, err
- }
- defer file.Close()
- return syscall.Getsockname(int(file.Fd()))
-}
-
-// marshalInetPacketInfo marshals a ipv4 control message, returning
-// the byte slice for the next marshal, if any
-func marshalInetPacketInfo(b []byte, cm *inetControlMessage) []byte {
- m := socket.ControlMessage(b)
- m.MarshalHeader(protocolIP, syscall.IP_PKTINFO, sizeofInetPktinfo)
- if cm != nil {
- pi := (*inetPktinfo)(unsafe.Pointer(&m.Data(sizeofInetPktinfo)[0]))
- if ip := cm.Src.To4(); ip != nil {
- copy(pi.Spec_dst[:], ip)
- }
- }
- return m.Next(sizeofInetPktinfo)
-}
-
-// marshalInet6PacketInfo marshals a ipv6 control message, returning
-// the byte slice for the next marshal, if any
-func marshalInet6PacketInfo(b []byte, cm *inetControlMessage) []byte {
- m := socket.ControlMessage(b)
- m.MarshalHeader(protocolIPv6, syscall.IPV6_PKTINFO, sizeofInet6Pktinfo)
- if cm != nil {
- pi := (*inet6Pktinfo)(unsafe.Pointer(&m.Data(sizeofInet6Pktinfo)[0]))
- if ip := cm.Src.To16(); ip != nil && ip.To4() == nil {
- copy(pi.Addr[:], ip)
- }
- }
- return m.Next(sizeofInet6Pktinfo)
-}
-
-func parseInetPacketInfo(cm *inetControlMessage, b []byte) {
- pi := (*inetPktinfo)(unsafe.Pointer(&b[0]))
- if len(cm.Dst) < net.IPv4len {
- cm.Dst = make(net.IP, net.IPv4len)
- }
- copy(cm.Dst, pi.Addr[:])
-}
-
-func parseInet6PacketInfo(cm *inetControlMessage, b []byte) {
- pi := (*inet6Pktinfo)(unsafe.Pointer(&b[0]))
- if len(cm.Dst) < net.IPv6len {
- cm.Dst = make(net.IP, net.IPv6len)
- }
- copy(cm.Dst, pi.Addr[:])
-}
-
-// parseUDPSocketDst takes out-of-band data from ReadMsgUDP and parses it for
-// the Dst address
-func parseUDPSocketDst(oob []byte) (net.IP, error) {
- cm := new(inetControlMessage)
- ms, err := socket.ControlMessage(oob).Parse()
- if err != nil {
- return nil, err
- }
- for _, m := range ms {
- lvl, typ, l, err := m.ParseHeader()
- if err != nil {
- return nil, err
- }
- if lvl == protocolIPv6 { // IPv6
- if typ == syscall.IPV6_PKTINFO && l >= sizeofInet6Pktinfo {
- parseInet6PacketInfo(cm, m.Data(l))
- }
- } else if lvl == protocolIP { // IPv4
- if typ == syscall.IP_PKTINFO && l >= sizeofInetPktinfo {
- parseInetPacketInfo(cm, m.Data(l))
- }
- }
- }
- return cm.Dst, nil
-}
-
-// marshalUDPSocketSrc takes the given src address and returns out-of-band data
-// to give to WriteMsgUDP
-func marshalUDPSocketSrc(src net.IP) []byte {
- var oob []byte
- // If the dst is definitely an ipv6, then use ipv6 control to respond
- // otherwise use ipv4 because the ipv6 marshal ignores ipv4 messages.
- // See marshalInet6PacketInfo
- cm := new(inetControlMessage)
- cm.Src = src
- if src.To4() == nil {
- oob = make([]byte, socket.ControlMessageSpace(sizeofInet6Pktinfo))
- marshalInet6PacketInfo(oob, cm)
- } else {
- oob = make([]byte, socket.ControlMessageSpace(sizeofInetPktinfo))
- marshalInetPacketInfo(oob, cm)
- }
- return oob
-}