C++程序  |  121行  |  3.95 KB

/*
 * 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);

    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<ClatIngressKey, ClatIngressValue> mClatIngressMap GUARDED_BY(mutex);

    void maybeStartBpf(const ClatdTracker& tracker) REQUIRES(mutex);
    void maybeStopBpf(const ClatdTracker& tracker) REQUIRES(mutex);
    void maybeSetIptablesDropRule(bool add, 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