github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/nfqdatapath/afinetrawsocket/afinetrawsocket.go (about) 1 // +build linux 2 3 package afinetrawsocket 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "strconv" 9 "strings" 10 "syscall" 11 12 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/packet" 13 ) 14 15 type socketv4 struct { 16 fd int 17 insock *syscall.SockaddrInet4 18 } 19 20 type socketv6 struct { 21 fd int 22 insock *syscall.SockaddrInet6 23 } 24 25 type rawsocket struct { 26 insockv4 *socketv4 27 insockv6 *socketv6 28 } 29 30 const ( 31 // RawSocketMark is the mark asserted on all packet sent out of this socket 32 RawSocketMark = 0x63 33 // NetworkRawSocketMark is the mark on packet egressing 34 //the raw socket coming in from network 35 NetworkRawSocketMark = 0x40000063 36 //ApplicationRawSocketMark is the mark on packet egressing 37 //the raw socket coming from application 38 ApplicationRawSocketMark = 0x40000062 39 ) 40 41 // SocketWriter interface exposes an interface to write and close sockets 42 type SocketWriter interface { 43 WriteSocket(buf []byte, version packet.IPver, data packet.PlatformMetadata) error 44 } 45 46 // CreateSocket returns a handle to SocketWriter interface 47 func CreateSocket(mark int, deviceName string) (SocketWriter, error) { 48 var sockv6 *socketv6 49 var sockv4 *socketv4 50 var err error 51 createSocketv4 := func() (*socketv4, error) { 52 53 fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_UDP) 54 if err != nil { 55 return nil, fmt.Errorf("received error %s while open ipv4 socket", err) 56 } 57 58 if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, mark); err != nil { 59 syscall.Close(fd) // nolint: errcheck 60 return nil, fmt.Errorf("received error %s while setting socket Option SO_MARK", err) 61 } 62 63 if err := syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_HDRINCL, 0); err != nil { 64 syscall.Close(fd) // nolint: errcheck 65 return nil, fmt.Errorf("received error %s while setting socket Option IP_HDRINCL", err) 66 } 67 68 if err := syscall.SetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_MTU_DISCOVER, syscall.IP_PMTUDISC_DONT); err != nil { 69 syscall.Close(fd) // nolint: errcheck 70 return nil, fmt.Errorf("received error %s while setting socket Option IP_PMTUDISC_DONT", err) 71 } 72 73 return &socketv4{ 74 fd: fd, 75 insock: &syscall.SockaddrInet4{ 76 Port: 0, 77 }, 78 }, nil 79 } 80 81 createSocketv6 := func() (*socketv6, error) { 82 83 fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_RAW, syscall.IPPROTO_UDP) 84 if err != nil { 85 return nil, fmt.Errorf("received error %s while open ipv6 socket", err) 86 } 87 88 if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, mark); err != nil { 89 syscall.Close(fd) // nolint: errcheck 90 return nil, fmt.Errorf("received error %s while setting socket Option SO_MARK", err) 91 } 92 93 if err := syscall.SetsockoptInt(fd, syscall.IPPROTO_IPV6, syscall.IP_HDRINCL, 0); err != nil { 94 syscall.Close(fd) // nolint: errcheck 95 return nil, fmt.Errorf("received error %s while setting socket Option IP_HDRINCL", err) 96 } 97 98 if err := syscall.SetsockoptInt(fd, syscall.IPPROTO_IPV6, syscall.IPV6_MTU_DISCOVER, syscall.IPV6_PMTUDISC_DONT); err != nil { 99 syscall.Close(fd) // nolint: errcheck 100 return nil, fmt.Errorf("received error %s while setting socket Option IP_PMTUDISC_DONT ipv6", err) 101 } 102 103 return &socketv6{ 104 fd: fd, 105 insock: &syscall.SockaddrInet6{ 106 Port: 0, 107 }, 108 }, nil 109 } 110 111 sockv4, err = createSocketv4() 112 if err != nil { 113 return nil, err 114 } 115 if IsIpv6Supported() { 116 sockv6, err = createSocketv6() 117 if err != nil { 118 return nil, err 119 } 120 } 121 return &rawsocket{ 122 insockv4: sockv4, 123 insockv6: sockv6, 124 }, nil 125 } 126 127 func (sock *rawsocket) WriteSocket(buf []byte, version packet.IPver, data packet.PlatformMetadata) error { 128 // copy the dest addr 129 if version == packet.V4 { 130 copy(sock.insockv4.insock.Addr[:], buf[16:20]) 131 if err := syscall.Sendto(sock.insockv4.fd, buf[20:], 0, sock.insockv4.insock); err != nil { 132 return fmt.Errorf("received error %s while sending to socket", err) 133 } 134 } else if sock.insockv6 != nil { 135 136 copy(sock.insockv6.insock.Addr[:], buf[24:40]) 137 if err := syscall.Sendto(sock.insockv6.fd, buf[40:], 0, sock.insockv6.insock); err != nil { 138 return fmt.Errorf("received error %s while sending to socket", err) 139 } 140 141 } 142 143 return nil 144 } 145 146 // IsIpv6Supported returns true if the system supports ipv6 else returns false 147 func IsIpv6Supported() bool { 148 ipv6ConfPath := "/proc/sys/net/ipv6/conf/all/disable_ipv6" 149 data, err := ioutil.ReadFile(ipv6ConfPath) 150 if err != nil { 151 return false 152 } 153 val, err := strconv.Atoi(strings.Trim(string(data), "\n")) 154 if err != nil { 155 return false 156 } 157 if val == 1 { 158 return false 159 } 160 return true 161 }