1
#include "cilium/socket_option_cilium_mark.h"
2

            
3
#include <cerrno>
4
#include <cstdint>
5

            
6
#include "envoy/config/core/v3/socket_option.pb.h"
7
#include "envoy/network/socket.h"
8

            
9
#include "source/common/common/logger.h"
10
#include "source/common/common/utility.h"
11

            
12
#include "cilium/privileged_service_client.h"
13

            
14
namespace Envoy {
15
namespace Cilium {
16

            
17
6
CiliumMarkSocketOption::CiliumMarkSocketOption(uint32_t mark) : mark_(mark) {
18
6
  ENVOY_LOG(debug,
19
6
            "Cilium CiliumMarkSocketOption(): mark: {:x} (magic mark: {:x}, cluster: {}, ID: {})",
20
6
            mark_, mark & 0xff00, mark & 0xff, mark >> 16);
21
6
}
22

            
23
bool CiliumMarkSocketOption::setOption(
24
    Network::Socket& socket, envoy::config::core::v3::SocketOption::SocketState state) const {
25
  // Only set the option once per socket
26
  if (state != envoy::config::core::v3::SocketOption::STATE_PREBIND) {
27
    ENVOY_LOG(trace, "Skipping setting socket ({}) option SO_MARK, state != STATE_PREBIND",
28
              socket.ioHandle().fdDoNotUse());
29
    return true;
30
  }
31

            
32
  auto& cilium_calls = PrivilegedService::Singleton::get();
33
  auto status = cilium_calls.setsockopt(socket.ioHandle().fdDoNotUse(), SOL_SOCKET, SO_MARK, &mark_,
34
                                        sizeof(mark_));
35
  if (status.return_value_ < 0) {
36
    if (status.errno_ == EPERM) {
37
      // Do not assert out in this case so that we can run tests without
38
      // CAP_NET_ADMIN.
39
      ENVOY_LOG(critical,
40
                "Failed to set socket option SO_MARK to {}, capability "
41
                "CAP_NET_ADMIN needed: {}",
42
                mark_, Envoy::errorDetails(status.errno_));
43
    } else {
44
      ENVOY_LOG(critical, "Socket option failure. Failed to set SO_MARK to {}: {}", mark_,
45
                Envoy::errorDetails(status.errno_));
46
      return false;
47
    }
48
  }
49

            
50
  ENVOY_LOG(trace,
51
            "Set socket ({}) option SO_MARK to {:x} (magic mark: {:x}, id: "
52
            "{}, cluster: {})",
53
            socket.ioHandle().fdDoNotUse(), mark_, mark_ & 0xff00, mark_ >> 16, mark_ & 0xff);
54

            
55
  return true;
56
}
57

            
58
} // namespace Cilium
59
} // namespace Envoy