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