#include "bpf.h"

#ifdef _linux_
#include <linux/filter.h>

namespace NSrvKernel {
    namespace NPrivate {
        static struct sock_filter CloseUsingBPFFilterCode[] = {
            { 0x30, 0, 0, 0x0000000d }, // (001) ldb  [13]
            { 0x45, 1, 0, 0x00000002 }, // (002) jset #0x2 jt 4 jf 3
            { 0x6,  0, 0, 0xffffffff }, // (003) ret  #-1
            { 0x6,  0, 0, 0x00000000 }, // (004) ret  #0
        };

        static const struct sock_fprog CloseUsingBPFFilter = {
            .len = Y_ARRAY_SIZE(CloseUsingBPFFilterCode),
            .filter = CloseUsingBPFFilterCode,
        };
    }

    TError CloseSocketUsingBPF(SOCKET s) noexcept {
        int ret = setsockopt(
            SOCKET(s), SOL_SOCKET, SO_ATTACH_FILTER, &NPrivate::CloseUsingBPFFilter, sizeof(NPrivate::CloseUsingBPFFilter)
        );
        if (ret < 0) {
            return MakeError<TSystemError>(TSystemError{LastSystemError()} << "close using bpf failed");
        }

        return {};
    }
}

#else
namespace NSrvKernel {
    TError CloseSocketUsingBPF(SOCKET) noexcept {
        return MakeError<TSystemError>(TSystemError{ENOSYS} << "bpf not supported");
    }
}
#endif
