FwmarkClient.cpp revision f4cfad361175a7f9ccf4d41e76a9b289c3c3da22
1f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran/* 2f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * Copyright (C) 2014 The Android Open Source Project 3f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * 4f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * Licensed under the Apache License, Version 2.0 (the "License"); 5f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * you may not use this file except in compliance with the License. 6f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * You may obtain a copy of the License at 7f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * 8f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * http://www.apache.org/licenses/LICENSE-2.0 9f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * 10f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * Unless required by applicable law or agreed to in writing, software 11f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * distributed under the License is distributed on an "AS IS" BASIS, 12f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * See the License for the specific language governing permissions and 14f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran * limitations under the License. 15f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran */ 16f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 17f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include "FwmarkClient.h" 18f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 19f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include <stdlib.h> 20f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include <sys/socket.h> 21f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include <sys/un.h> 22f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include <unistd.h> 23f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 24f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandrannamespace { 25f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 26f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandranconst sockaddr_un FWMARK_SERVER_PATH = {AF_UNIX, "/dev/socket/fwmarkd"}; 27f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 28f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} // namespace 29f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 30f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandranbool FwmarkClient::shouldSetFwmark(int sockfd, const sockaddr* addr) { 31f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran return sockfd >= 0 && addr && (addr->sa_family == AF_INET || addr->sa_family == AF_INET6) && 32f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran !getenv("ANDROID_NO_USE_FWMARK_CLIENT"); 33f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 34f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 35f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram RamachandranFwmarkClient::FwmarkClient() : mChannel(-1) { 36f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 37f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 38f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram RamachandranFwmarkClient::~FwmarkClient() { 39f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (mChannel >= 0) { 40f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran // We don't care about errors while closing the channel, so restore any previous error. 41f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran int error = errno; 42f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran close(mChannel); 43f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran errno = error; 44f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 45f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 46f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 47f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandranbool FwmarkClient::send(void* data, size_t len, int fd) { 48f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran mChannel = socket(AF_UNIX, SOCK_STREAM, 0); 49f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (mChannel == -1) { 50f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran return false; 51f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 52f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 53f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (TEMP_FAILURE_RETRY(connect(mChannel, reinterpret_cast<const sockaddr*>(&FWMARK_SERVER_PATH), 54f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran sizeof(FWMARK_SERVER_PATH))) == -1) { 55f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran // If we are unable to connect to the fwmark server, assume there's no error. This protects 56f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran // against future changes if the fwmark server goes away. 57f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran errno = 0; 58f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran return true; 59f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 60f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 61f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran iovec iov; 62f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran iov.iov_base = data; 63f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran iov.iov_len = len; 64f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 65f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran msghdr message; 66f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran memset(&message, 0, sizeof(message)); 67f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran message.msg_iov = &iov; 68f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran message.msg_iovlen = 1; 69f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 70f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran union { 71f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran cmsghdr cmh; 72f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran char cmsg[CMSG_SPACE(sizeof(fd))]; 73f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } cmsgu; 74f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 75f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran memset(cmsgu.cmsg, 0, sizeof(cmsgu.cmsg)); 76f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran message.msg_control = cmsgu.cmsg; 77f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran message.msg_controllen = sizeof(cmsgu.cmsg); 78f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 79f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran cmsghdr* const cmsgh = CMSG_FIRSTHDR(&message); 80f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran cmsgh->cmsg_len = CMSG_LEN(sizeof(fd)); 81f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran cmsgh->cmsg_level = SOL_SOCKET; 82f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran cmsgh->cmsg_type = SCM_RIGHTS; 83f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran memcpy(CMSG_DATA(cmsgh), &fd, sizeof(fd)); 84f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 85f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (TEMP_FAILURE_RETRY(sendmsg(mChannel, &message, 0)) == -1) { 86f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran return false; 87f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 88f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 89f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran int error = 0; 90f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (TEMP_FAILURE_RETRY(recv(mChannel, &error, sizeof(error), 0)) == -1) { 91f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran return false; 92f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 93f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 94f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran errno = error; 95f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran return !error; 96f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 97