/* KMSeccomp.h
 *
 * Copyright (C) 2023 OpenKylin, Inc
 *
 * @note : Encapsulation of seccomp library
 */

#ifndef __KMSECCOMP_H__
#define __KMSECCOMP_H__

#include "config.h"

#ifdef ENABLE_SECCOMP
#  include "KMCommonTypePrivate.h"
#  include "kmsyscallsprivate.h"

#  include <seccomp.h>
#  include <sys/ioctl.h>

#  include <memory>
#  include <vector>

#  include <sys/socket.h>
#  include <unistd.h>

/**
 * @brief pack seccomp api
 */
class KMSeccomp
{
public:
    typedef struct scmp_arg_cmp ScmpArgCmp;
    typedef struct scmp_arg_cmp *ScmpArgCmpPtr;

    struct SyscallBlock
    {
        SyscallBlock(int scall, int errnum, ScmpArgCmpPtr arg = nullptr);
        ~SyscallBlock();

        int m_scall;
        int m_errnum;
        std::shared_ptr<ScmpArgCmp> m_arg;
    };

    /* Blocklist all but unix, inet, inet6 and netlink */
    struct SocketFamily
    {
        SocketFamily(int family, KMRunFlags flagsMask);
        ~SocketFamily();

        int m_family;
        KMRunFlags m_flagsMask;
    };

public:
    KMSeccomp();
    ~KMSeccomp();

    bool seccompInit(unsigned int defaultFilterAction);

    bool empty() const { return m_seccomp == nullptr; }

    bool addArch2Filter(const std::string &arch, bool multiarch, std::string &errMsg);

    bool blockSyscall(const std::vector<SyscallBlock> &syscallBlocks, std::string &errMsg);

    void blockSocket(const std::vector<KMSeccomp::SocketFamily> &socketFamilyAllows, KMRunFlags runFlags);

    bool exportBpf(int fd, std::string &errMsg);

private:
    void destroy();

    static std::string strerror(int negativeErrno);

private:
    scmp_filter_ctx m_seccomp = nullptr;
};

#endif // !ENABLE_SECCOMP

#endif // !__KMSECCOMP_H__
