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 19d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen#include "FwmarkCommand.h" 20d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen 2127aacc0d49dbc5c3721ae5ca6f6033be6537c4c3Elliott Hughes#include <errno.h> 22f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include <stdlib.h> 23bb881e28e62bc5048f4a62d21104aa25da13b0f1Elliott Hughes#include <string.h> 24f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include <sys/socket.h> 25f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include <sys/un.h> 26f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran#include <unistd.h> 27f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 287d374533e2daadee5d7f01dd9aa3c98e42759d50Michal Karpinski#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) 297d374533e2daadee5d7f01dd9aa3c98e42759d50Michal Karpinski 30f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandrannamespace { 31f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 32f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandranconst sockaddr_un FWMARK_SERVER_PATH = {AF_UNIX, "/dev/socket/fwmarkd"}; 33f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 34e54b21279f58f50da2e42a4c009e467090152aebdimitry#if defined(NETD_CLIENT_DEBUGGABLE_BUILD) 35e54b21279f58f50da2e42a4c009e467090152aebdimitryconstexpr bool isBuildDebuggable = true; 36e54b21279f58f50da2e42a4c009e467090152aebdimitry#else 37e54b21279f58f50da2e42a4c009e467090152aebdimitryconstexpr bool isBuildDebuggable = false; 38e54b21279f58f50da2e42a4c009e467090152aebdimitry#endif 396028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski 406028b39ef140707c538d66586603f74dd8f222d6Michal Karpinskibool isOverriddenBy(const char *name) { 416028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski return isBuildDebuggable && getenv(name); 426028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski} 436028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski 449944ba87ad061fd6add45521044c3503771e43c2Chenbo Fengbool commandHasFd(int cmdId) { 459944ba87ad061fd6add45521044c3503771e43c2Chenbo Feng return (cmdId != FwmarkCommand::QUERY_USER_ACCESS) && 469944ba87ad061fd6add45521044c3503771e43c2Chenbo Feng (cmdId != FwmarkCommand::SET_COUNTERSET) && 479944ba87ad061fd6add45521044c3503771e43c2Chenbo Feng (cmdId != FwmarkCommand::DELETE_TAGDATA); 489944ba87ad061fd6add45521044c3503771e43c2Chenbo Feng} 499944ba87ad061fd6add45521044c3503771e43c2Chenbo Feng 50f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} // namespace 51f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 525fc275794ab41d110abbdb7683ed9db45918985fSreeram Ramachandranbool FwmarkClient::shouldSetFwmark(int family) { 536028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski if (isOverriddenBy(ANDROID_NO_USE_FWMARK_CLIENT)) { 546028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski return false; 556028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski } 566028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski return family == AF_INET || family == AF_INET6; 572cf561722c2661cc0d4db502a44a3021609f307eRobin Lee} 582cf561722c2661cc0d4db502a44a3021609f307eRobin Lee 592cf561722c2661cc0d4db502a44a3021609f307eRobin Leebool FwmarkClient::shouldReportConnectComplete(int family) { 606028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski if (isOverriddenBy(ANDROID_FWMARK_METRICS_ONLY)) { 616028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski return false; 626028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski } 636028b39ef140707c538d66586603f74dd8f222d6Michal Karpinski return shouldSetFwmark(family); 64f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 65f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 66f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram RamachandranFwmarkClient::FwmarkClient() : mChannel(-1) { 67f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 68f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 69f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram RamachandranFwmarkClient::~FwmarkClient() { 70f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (mChannel >= 0) { 71f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran close(mChannel); 72f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 73f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 74f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 757d374533e2daadee5d7f01dd9aa3c98e42759d50Michal Karpinskiint FwmarkClient::send(FwmarkCommand* data, int fd, FwmarkConnectInfo* connectInfo) { 7653ea9cadf6cc5f8be1c16b5b6b660cd7366fd3f0Nick Kralevich mChannel = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); 77f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (mChannel == -1) { 783a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran return -errno; 79f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 80f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 81f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (TEMP_FAILURE_RETRY(connect(mChannel, reinterpret_cast<const sockaddr*>(&FWMARK_SERVER_PATH), 82f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran sizeof(FWMARK_SERVER_PATH))) == -1) { 83f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran // If we are unable to connect to the fwmark server, assume there's no error. This protects 84f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran // against future changes if the fwmark server goes away. 859944ba87ad061fd6add45521044c3503771e43c2Chenbo Feng // TODO: This means that fd will very likely be misrouted. See if we can delete this in a 869944ba87ad061fd6add45521044c3503771e43c2Chenbo Feng // separate CL. 8731f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandran return 0; 88f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 89f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 907d374533e2daadee5d7f01dd9aa3c98e42759d50Michal Karpinski iovec iov[2] = { 917d374533e2daadee5d7f01dd9aa3c98e42759d50Michal Karpinski { data, sizeof(*data) }, 927d374533e2daadee5d7f01dd9aa3c98e42759d50Michal Karpinski { connectInfo, (connectInfo ? sizeof(*connectInfo) : 0) }, 937d374533e2daadee5d7f01dd9aa3c98e42759d50Michal Karpinski }; 94f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran msghdr message; 95f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran memset(&message, 0, sizeof(message)); 967d374533e2daadee5d7f01dd9aa3c98e42759d50Michal Karpinski message.msg_iov = iov; 977d374533e2daadee5d7f01dd9aa3c98e42759d50Michal Karpinski message.msg_iovlen = ARRAY_SIZE(iov); 98f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 99f86df5580e86c2405c71c708408eeee57b38c0d3Stephen Hines union { 100f86df5580e86c2405c71c708408eeee57b38c0d3Stephen Hines cmsghdr cmh; 101f86df5580e86c2405c71c708408eeee57b38c0d3Stephen Hines char cmsg[CMSG_SPACE(sizeof(fd))]; 102f86df5580e86c2405c71c708408eeee57b38c0d3Stephen Hines } cmsgu; 103d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen 1049944ba87ad061fd6add45521044c3503771e43c2Chenbo Feng if (commandHasFd(data->cmdId)) { 105d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen memset(cmsgu.cmsg, 0, sizeof(cmsgu.cmsg)); 106d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen message.msg_control = cmsgu.cmsg; 107d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen message.msg_controllen = sizeof(cmsgu.cmsg); 108d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen 109d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen cmsghdr* const cmsgh = CMSG_FIRSTHDR(&message); 110d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen cmsgh->cmsg_len = CMSG_LEN(sizeof(fd)); 111d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen cmsgh->cmsg_level = SOL_SOCKET; 112d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen cmsgh->cmsg_type = SCM_RIGHTS; 113d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen memcpy(CMSG_DATA(cmsgh), &fd, sizeof(fd)); 114d1df597001aadd5d83c9a3d1fe8bbde2bc9256caPaul Jensen } 115f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 116f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (TEMP_FAILURE_RETRY(sendmsg(mChannel, &message, 0)) == -1) { 1173a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran return -errno; 118f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 119f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 120f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran int error = 0; 12131f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandran 122f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran if (TEMP_FAILURE_RETRY(recv(mChannel, &error, sizeof(error), 0)) == -1) { 1233a069e6a76752a0ee73c60f276ae362d1c01467fSreeram Ramachandran return -errno; 124f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran } 125f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran 12631f4210e6fc5c9b749468a2af0bac94992352010Sreeram Ramachandran return error; 127f4cfad361175a7f9ccf4d41e76a9b289c3c3da22Sreeram Ramachandran} 128