1 /* 2 * Copyright (C) 2017 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 "router.h" 18 19 #include <linux/rtnetlink.h> 20 #include <stddef.h> 21 #include <string.h> 22 23 #include "address.h" 24 #include "log.h" 25 26 template<class Request> 27 static void addRouterAttribute(Request& r, 28 int type, 29 const void* data, 30 size_t size) { 31 // Calculate the offset into the character buffer where the RTA data lives 32 // We use offsetof on the buffer to get it. This avoids undefined behavior 33 // by casting the buffer (which is safe because it's char) instead of the 34 // Request struct.(which is undefined because of aliasing) 35 size_t offset = NLMSG_ALIGN(r.hdr.nlmsg_len) - offsetof(Request, buf); 36 auto attr = reinterpret_cast<struct rtattr*>(r.buf + offset); 37 attr->rta_type = type; 38 attr->rta_len = RTA_LENGTH(size); 39 memcpy(RTA_DATA(attr), data, size); 40 41 // Update the message length to include the router attribute. 42 r.hdr.nlmsg_len = NLMSG_ALIGN(r.hdr.nlmsg_len) + RTA_ALIGN(attr->rta_len); 43 } 44 45 bool Router::init() { 46 // Create a netlink socket to the router 47 Result res = mSocket.open(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 48 if (!res) { 49 loge("Unable to open netlink socket: %s\n", res.c_str()); 50 return false; 51 } 52 return true; 53 } 54 55 bool Router::addNeighbor(const struct in6_addr& address, 56 unsigned int interfaceIndex) { 57 struct Request { 58 struct nlmsghdr hdr; 59 struct ndmsg msg; 60 char buf[256]; 61 } request; 62 63 memset(&request, 0, sizeof(request)); 64 65 unsigned short msgLen = NLMSG_LENGTH(sizeof(request.msg)); 66 // Set up a request to create a new neighbor 67 request.hdr.nlmsg_len = msgLen; 68 request.hdr.nlmsg_type = RTM_NEWNEIGH; 69 request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; 70 71 // The neighbor is a permanent IPv6 proxy 72 request.msg.ndm_family = AF_INET6; 73 request.msg.ndm_state = NUD_PERMANENT; 74 request.msg.ndm_flags = NTF_PROXY; 75 request.msg.ndm_ifindex = interfaceIndex; 76 77 addRouterAttribute(request, NDA_DST, &address, sizeof(address)); 78 79 return sendNetlinkMessage(&request, request.hdr.nlmsg_len); 80 } 81 82 bool Router::addRoute(const struct in6_addr& address, 83 uint8_t bits, 84 uint32_t ifaceIndex) { 85 struct Request { 86 struct nlmsghdr hdr; 87 struct rtmsg msg; 88 char buf[256]; 89 } request; 90 91 memset(&request, 0, sizeof(request)); 92 93 // Set up a request to create a new route 94 request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg)); 95 request.hdr.nlmsg_type = RTM_NEWROUTE; 96 request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; 97 98 request.msg.rtm_family = AF_INET6; 99 request.msg.rtm_dst_len = bits; 100 request.msg.rtm_table = RT_TABLE_MAIN; 101 request.msg.rtm_protocol = RTPROT_RA; 102 request.msg.rtm_scope = RT_SCOPE_UNIVERSE; 103 request.msg.rtm_type = RTN_UNICAST; 104 105 addRouterAttribute(request, RTA_DST, &address, sizeof(address)); 106 addRouterAttribute(request, RTA_OIF, &ifaceIndex, sizeof(ifaceIndex)); 107 108 return sendNetlinkMessage(&request, request.hdr.nlmsg_len); 109 } 110 111 bool Router::setDefaultGateway(const struct in6_addr& address, 112 unsigned int ifaceIndex) { 113 struct Request { 114 struct nlmsghdr hdr; 115 struct rtmsg msg; 116 char buf[256]; 117 } request; 118 119 memset(&request, 0, sizeof(request)); 120 121 // Set up a request to create a new route 122 request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg)); 123 request.hdr.nlmsg_type = RTM_NEWROUTE; 124 request.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; 125 126 request.msg.rtm_family = AF_INET6; 127 request.msg.rtm_dst_len = 0; 128 request.msg.rtm_src_len = 0; 129 request.msg.rtm_table = RT_TABLE_MAIN; 130 request.msg.rtm_protocol = RTPROT_RA; 131 request.msg.rtm_scope = RT_SCOPE_UNIVERSE; 132 request.msg.rtm_type = RTN_UNICAST; 133 134 struct in6_addr anyAddress; 135 memset(&anyAddress, 0, sizeof(anyAddress)); 136 addRouterAttribute(request, RTA_GATEWAY, &address, sizeof(address)); 137 addRouterAttribute(request, RTA_OIF, &ifaceIndex, sizeof(ifaceIndex)); 138 addRouterAttribute(request, RTA_SRC, &anyAddress, sizeof(anyAddress)); 139 140 return sendNetlinkMessage(&request, request.hdr.nlmsg_len); 141 } 142 143 bool Router::sendNetlinkMessage(const void* data, size_t size) { 144 struct sockaddr_nl netlinkAddress; 145 memset(&netlinkAddress, 0, sizeof(netlinkAddress)); 146 netlinkAddress.nl_family = AF_NETLINK; 147 Result res = mSocket.sendTo(netlinkAddress, data, size); 148 if (!res) { 149 loge("Unable to send on netlink socket: %s\n", res.c_str()); 150 return false; 151 } 152 return true; 153 } 154 155