Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1b21c5c authored by Sreeram Ramachandran's avatar Sreeram Ramachandran
Browse files

Move netd_client into netd.

Change-Id: Ie4b6b303225c93f2448a503d6ea9cebb552cbad5
parent e14b37eb
Loading
Loading
Loading
Loading
+0 −29
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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 NETD_CLIENT_FWMARK_COMMANDS_H
#define NETD_CLIENT_FWMARK_COMMANDS_H

#include <stdint.h>

// Commands sent from clients to the fwmark server to mark sockets (i.e., set their SO_MARK).
const uint8_t FWMARK_COMMAND_ON_CREATE        = 0;
const uint8_t FWMARK_COMMAND_ON_CONNECT       = 1;
const uint8_t FWMARK_COMMAND_ON_ACCEPT        = 2;
const uint8_t FWMARK_COMMAND_SELECT_NETWORK   = 3;
const uint8_t FWMARK_COMMAND_PROTECT_FROM_VPN = 4;

#endif  // NETD_CLIENT_FWMARK_COMMANDS_H

libnetd_client/Android.mk

deleted100644 → 0
+0 −22
Original line number Diff line number Diff line
# Copyright (C) 2014 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.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := libnetd_client
LOCAL_SRC_FILES := FwmarkClient.cpp NetdClient.cpp

include $(BUILD_SHARED_LIBRARY)

libnetd_client/FwmarkClient.cpp

deleted100644 → 0
+0 −96
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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.
 */

#include "FwmarkClient.h"

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

namespace {

const sockaddr_un FWMARK_SERVER_PATH = {AF_UNIX, "/dev/socket/fwmarkd"};

}  // namespace

bool FwmarkClient::shouldSetFwmark(int sockfd, const sockaddr* addr) {
    return sockfd >= 0 && addr && (addr->sa_family == AF_INET || addr->sa_family == AF_INET6) &&
           !getenv("ANDROID_NO_USE_FWMARK_CLIENT");
}

FwmarkClient::FwmarkClient() : mChannel(-1) {
}

FwmarkClient::~FwmarkClient() {
    if (mChannel >= 0) {
        // We don't care about errors while closing the channel, so restore any previous error.
        int error = errno;
        close(mChannel);
        errno = error;
    }
}

bool FwmarkClient::send(void* data, size_t len, int fd) {
    mChannel = socket(AF_UNIX, SOCK_STREAM, 0);
    if (mChannel == -1) {
        return false;
    }

    if (TEMP_FAILURE_RETRY(connect(mChannel, reinterpret_cast<const sockaddr*>(&FWMARK_SERVER_PATH),
                                   sizeof(FWMARK_SERVER_PATH))) == -1) {
        // If we are unable to connect to the fwmark server, assume there's no error. This protects
        // against future changes if the fwmark server goes away.
        errno = 0;
        return true;
    }

    iovec iov;
    iov.iov_base = data;
    iov.iov_len = len;

    msghdr message;
    memset(&message, 0, sizeof(message));
    message.msg_iov = &iov;
    message.msg_iovlen = 1;

    union {
        cmsghdr cmh;
        char cmsg[CMSG_SPACE(sizeof(fd))];
    } cmsgu;

    memset(cmsgu.cmsg, 0, sizeof(cmsgu.cmsg));
    message.msg_control = cmsgu.cmsg;
    message.msg_controllen = sizeof(cmsgu.cmsg);

    cmsghdr* const cmsgh = CMSG_FIRSTHDR(&message);
    cmsgh->cmsg_len = CMSG_LEN(sizeof(fd));
    cmsgh->cmsg_level = SOL_SOCKET;
    cmsgh->cmsg_type = SCM_RIGHTS;
    memcpy(CMSG_DATA(cmsgh), &fd, sizeof(fd));

    if (TEMP_FAILURE_RETRY(sendmsg(mChannel, &message, 0)) == -1) {
        return false;
    }

    int error = 0;
    if (TEMP_FAILURE_RETRY(recv(mChannel, &error, sizeof(error), 0)) == -1) {
        return false;
    }

    errno = error;
    return !error;
}

libnetd_client/FwmarkClient.h

deleted100644 → 0
+0 −38
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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 NETD_CLIENT_FWMARK_CLIENT_H
#define NETD_CLIENT_FWMARK_CLIENT_H

#include <sys/socket.h>

class FwmarkClient {
public:
    // Returns true if |sockfd| should be sent to the fwmark server to have its SO_MARK set.
    static bool shouldSetFwmark(int sockfd, const sockaddr* addr);

    FwmarkClient();
    ~FwmarkClient();

    // Sends |data| to the fwmark server, along with |fd| as ancillary data using cmsg(3).
    // Returns true on success.
    bool send(void* data, size_t len, int fd);

private:
    int mChannel;
};

#endif  // NETD_CLIENT_INCLUDE_FWMARK_CLIENT_H

libnetd_client/NetdClient.cpp

deleted100644 → 0
+0 −84
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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.
 */

#include "FwmarkClient.h"
#include "netd_client/FwmarkCommands.h"

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

namespace {

int closeFdAndRestoreErrno(int fd) {
    int error = errno;
    close(fd);
    errno = error;
    return -1;
}

typedef int (*ConnectFunctionType)(int, const sockaddr*, socklen_t);
typedef int (*AcceptFunctionType)(int, sockaddr*, socklen_t*);

ConnectFunctionType libcConnect = 0;
AcceptFunctionType libcAccept = 0;

int netdClientConnect(int sockfd, const sockaddr* addr, socklen_t addrlen) {
    if (FwmarkClient::shouldSetFwmark(sockfd, addr)) {
        char data[] = {FWMARK_COMMAND_ON_CONNECT};
        if (!FwmarkClient().send(data, sizeof(data), sockfd)) {
            return -1;
        }
    }
    return libcConnect(sockfd, addr, addrlen);
}

int netdClientAccept(int sockfd, sockaddr* addr, socklen_t* addrlen) {
    int acceptedSocket = libcAccept(sockfd, addr, addrlen);
    if (acceptedSocket == -1) {
        return -1;
    }
    sockaddr socketAddress;
    if (!addr) {
        socklen_t socketAddressLen = sizeof(socketAddress);
        if (getsockname(acceptedSocket, &socketAddress, &socketAddressLen) == -1) {
            return closeFdAndRestoreErrno(acceptedSocket);
        }
        addr = &socketAddress;
    }
    if (FwmarkClient::shouldSetFwmark(acceptedSocket, addr)) {
        char data[] = {FWMARK_COMMAND_ON_ACCEPT};
        if (!FwmarkClient().send(data, sizeof(data), acceptedSocket)) {
            return closeFdAndRestoreErrno(acceptedSocket);
        }
    }
    return acceptedSocket;
}

}  // namespace

extern "C" void netdClientInitConnect(ConnectFunctionType* function) {
    if (function && *function) {
        libcConnect = *function;
        *function = netdClientConnect;
    }
}

extern "C" void netdClientInitAccept(AcceptFunctionType* function) {
    if (function && *function) {
        libcAccept = *function;
        *function = netdClientAccept;
    }
}