1 /*
2  * Copyright (C) 2023 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 "BindToDeviceSocketMutator.h"
18 
19 #include <android-base/logging.h>
20 #include <errno.h>
21 #include <src/core/lib/iomgr/socket_mutator.h>
22 #include <sys/socket.h>
23 
24 #include <memory>
25 
26 namespace android::hardware::automotive::remoteaccess {
27 namespace {
28 
29 struct BindToDeviceMutator : grpc_socket_mutator {
30     std::string ifname;
31 };
32 
MutateFd(int fd,grpc_socket_mutator * mutator)33 bool MutateFd(int fd, grpc_socket_mutator* mutator) {
34     auto* bdm = static_cast<BindToDeviceMutator*>(mutator);
35     int ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, bdm->ifname.c_str(), bdm->ifname.size());
36     if (ret != 0) {
37         PLOG(ERROR) << "Can't bind socket to interface " << bdm->ifname;
38         return false;
39     }
40     return true;
41 }
42 
Compare(grpc_socket_mutator * a,grpc_socket_mutator * b)43 int Compare(grpc_socket_mutator* a, grpc_socket_mutator* b) {
44     return ((a) < (b) ? -1 : ((a) > (b) ? 1 : 0));
45 }
46 
Destroy(grpc_socket_mutator * mutator)47 void Destroy(grpc_socket_mutator* mutator) {
48     auto* bdm = static_cast<BindToDeviceMutator*>(mutator);
49     delete bdm;
50 }
51 
52 constexpr grpc_socket_mutator_vtable kMutatorVtable = {
53         .mutate_fd = MutateFd,
54         .compare = Compare,
55         .destroy = Destroy,
56 };
57 
58 }  // namespace
59 
MakeBindToDeviceSocketMutator(std::string_view interface_name)60 grpc_socket_mutator* MakeBindToDeviceSocketMutator(std::string_view interface_name) {
61     auto* bdm = new BindToDeviceMutator;
62     grpc_socket_mutator_init(bdm, &kMutatorVtable);
63     bdm->ifname = interface_name;
64     return bdm;
65 }
66 
67 }  // namespace android::hardware::automotive::remoteaccess
68