/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _CLATD_CONTROLLER_H
#define _CLATD_CONTROLLER_H

#include <map>
#include <mutex>
#include <string>

#include <linux/if.h>
#include <netinet/in.h>

#include <android-base/thread_annotations.h>

#include "Fwmark.h"
#include "NetdConstants.h"
#include "bpf/BpfMap.h"
#include "netdbpf/bpf_shared.h"
#include "netdutils/DumpWriter.h"

namespace android {
namespace net {

class NetworkController;

class ClatdController {
  public:
    explicit ClatdController(NetworkController* controller) EXCLUDES(mutex)
        : mNetCtrl(controller){};
    virtual ~ClatdController() EXCLUDES(mutex){};

    /* First thing init/startClatd/stopClatd/dump do is grab the mutex. */
    void init(void) EXCLUDES(mutex);

    int startClatd(const std::string& interface, const std::string& nat64Prefix,
                   std::string* v6Addr) EXCLUDES(mutex);
    int stopClatd(const std::string& interface) EXCLUDES(mutex);

    void dump(netdutils::DumpWriter& dw) EXCLUDES(mutex);

    static constexpr const char LOCAL_RAW_PREROUTING[] = "clat_raw_PREROUTING";

  private:
    struct ClatdTracker {
        pid_t pid = -1;
        unsigned ifIndex;
        char iface[IFNAMSIZ];
        unsigned v4ifIndex;
        char v4iface[IFNAMSIZ];
        Fwmark fwmark;
        char fwmarkString[UINT32_STRLEN];
        unsigned netId;
        char netIdString[UINT32_STRLEN];
        in_addr v4;
        char v4Str[INET_ADDRSTRLEN];
        in6_addr v6;
        char v6Str[INET6_ADDRSTRLEN];
        in6_addr pfx96;
        char pfx96String[INET6_ADDRSTRLEN];

        int init(unsigned networkId, const std::string& interface, const std::string& v4interface,
                 const std::string& nat64Prefix);
    };

    std::mutex mutex;

    const NetworkController* mNetCtrl GUARDED_BY(mutex);
    std::map<std::string, ClatdTracker> mClatdTrackers GUARDED_BY(mutex);
    ClatdTracker* getClatdTracker(const std::string& interface) REQUIRES(mutex);

    void resetEgressMap() REQUIRES(mutex);
    void resetIngressMap() REQUIRES(mutex);

    void dumpEgress(netdutils::DumpWriter& dw) REQUIRES(mutex);
    void dumpIngress(netdutils::DumpWriter& dw) REQUIRES(mutex);
    void dumpTrackers(netdutils::DumpWriter& dw) REQUIRES(mutex);

    static in_addr_t selectIpv4Address(const in_addr ip, int16_t prefixlen);
    static int generateIpv6Address(const char* iface, const in_addr v4, const in6_addr& nat64Prefix,
                                   in6_addr* v6);
    static void makeChecksumNeutral(in6_addr* v6, const in_addr v4, const in6_addr& nat64Prefix);

    enum eClatEbpfMode {
        ClatEbpfDisabled,  //  <4.9 kernel ||  <P api shipping level -- will not work
        ClatEbpfMaybe,     // >=4.9 kernel &&   P api shipping level -- might work
        ClatEbpfEnabled,   // >=4.9 kernel && >=Q api shipping level -- must work
    };
    eClatEbpfMode mClatEbpfMode GUARDED_BY(mutex);
    eClatEbpfMode getEbpfMode() EXCLUDES(mutex) {
        std::lock_guard guard(mutex);
        return mClatEbpfMode;
    }

    base::unique_fd mNetlinkFd GUARDED_BY(mutex);
    bpf::BpfMap<ClatEgressKey, ClatEgressValue> mClatEgressMap GUARDED_BY(mutex);
    bpf::BpfMap<ClatIngressKey, ClatIngressValue> mClatIngressMap GUARDED_BY(mutex);

    void maybeStartBpf(const ClatdTracker& tracker) REQUIRES(mutex);
    void maybeStopBpf(const ClatdTracker& tracker) REQUIRES(mutex);
    void setIptablesDropRule(bool add, const char* iface, const char* pfx96Str, const char* v6Str)
            REQUIRES(mutex);

    // For testing.
    friend class ClatdControllerTest;

    static bool (*isIpv4AddressFreeFunc)(in_addr_t);
    static bool isIpv4AddressFree(in_addr_t addr);
    static int (*iptablesRestoreFunction)(IptablesTarget target, const std::string& commands);
};

}  // namespace net
}  // namespace android

#endif
