1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2012 The Android Open Source Project 3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License. 6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at 7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software 11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and 14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License. 15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 16dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 178d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/rtnl_message.h" 18dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 19dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart#include <linux/netlink.h> 20dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart#include <linux/rtnetlink.h> 213ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu#include <netinet/in.h> 22a41ab517725d036b63420f8445550246f8f50b99Alex Vakulenko#include <sys/socket.h> 23dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 248d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include <base/logging.h> 258d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu 268d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/ndisc.h" 27b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley 28dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartnamespace shill { 29dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 30dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartstruct RTNLHeader { 31dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart RTNLHeader() { 32dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart memset(this, 0, sizeof(*this)); 33dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 34dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct nlmsghdr hdr; 35dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart union { 36dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct ifinfomsg ifi; 37dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct ifaddrmsg ifa; 38dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct rtmsg rtm; 39dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct rtgenmsg gen; 403ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu struct nduseroptmsg nd_user_opt; 41ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly struct ndmsg ndm; 42dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart }; 43dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}; 44dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 45dd7df792d2401741183a954f3f6e97d4c6de1e22Paul StewartRTNLMessage::RTNLMessage() 469a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart : type_(kTypeUnknown), 479a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart mode_(kModeUnknown), 48dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart flags_(0), 49e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov seq_(0), 50e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov pid_(0), 51dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_(0), 527355ce1937c504d836a303ac809bd436272212b3Paul Stewart family_(IPAddress::kFamilyUnknown) {} 53dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 549a908080fc2a72dbf06f995b878fc8a3693b725aPaul StewartRTNLMessage::RTNLMessage(Type type, 559a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 56dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart unsigned int flags, 577fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t seq, 587fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t pid, 59dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int interface_index, 60dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart IPAddress::Family family) 61dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart : type_(type), 62dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_(mode), 63dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart flags_(flags), 64dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart seq_(seq), 65dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart pid_(pid), 66dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_(interface_index), 67dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_(family) {} 68dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 69e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::Decode(const ByteString& msg) { 70dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart bool ret = DecodeInternal(msg); 71dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!ret) { 72f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart Reset(); 73dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 74dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return ret; 75dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 76dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 77e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::DecodeInternal(const ByteString& msg) { 78e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart const RTNLHeader* hdr = 79e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart reinterpret_cast<const RTNLHeader*>(msg.GetConstData()); 80dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 81dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (msg.GetLength() < sizeof(hdr->hdr) || 82dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart msg.GetLength() < hdr->hdr.nlmsg_len) 83dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 84dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 859a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode = kModeUnknown; 86dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart switch (hdr->hdr.nlmsg_type) { 87dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWLINK: 88dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWADDR: 89dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWROUTE: 903ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu case RTM_NEWNDUSEROPT: 91ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case RTM_NEWNEIGH: 929a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart mode = kModeAdd; 93dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 94dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 95dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELLINK: 96dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELADDR: 97dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELROUTE: 98ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case RTM_DELNEIGH: 999a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart mode = kModeDelete; 100dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 101dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 102dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart default: 103dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 104dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 105dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 106e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart rtattr* attr_data = nullptr; 107dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int attr_length = 0; 108dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 109dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart switch (hdr->hdr.nlmsg_type) { 110dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWLINK: 111dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELLINK: 112dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!DecodeLink(hdr, mode, &attr_data, &attr_length)) 113dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 114dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 115dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 116dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWADDR: 117dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELADDR: 118dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!DecodeAddress(hdr, mode, &attr_data, &attr_length)) 119dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 120dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 121dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 122dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWROUTE: 123dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELROUTE: 124dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!DecodeRoute(hdr, mode, &attr_data, &attr_length)) 125dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 126dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 127dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 1283ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu case RTM_NEWNDUSEROPT: 1293ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (!DecodeNdUserOption(hdr, mode, &attr_data, &attr_length)) 1303ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 1313ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu break; 1323ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 133ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case RTM_NEWNEIGH: 134ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case RTM_DELNEIGH: 135ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly if (!DecodeNeighbor(hdr, mode, &attr_data, &attr_length)) 136ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return false; 137ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly break; 138ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 139dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart default: 140dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart NOTREACHED(); 141dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 142dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 143dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart flags_ = hdr->hdr.nlmsg_flags; 144dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart seq_ = hdr->hdr.nlmsg_seq; 145dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart pid_ = hdr->hdr.nlmsg_pid; 146dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 147dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart while (attr_data && RTA_OK(attr_data, attr_length)) { 148dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart SetAttribute( 149dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_data->rta_type, 150e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart ByteString(reinterpret_cast<unsigned char*>(RTA_DATA(attr_data)), 151dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart RTA_PAYLOAD(attr_data))); 152dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_data = RTA_NEXT(attr_data, attr_length); 153dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 154dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 155dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (attr_length) { 156dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart // We hit a parse error while going through the attributes 157dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attributes_.clear(); 158dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 159dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 160dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 161dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 162dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 163dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 164e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::DecodeLink(const RTNLHeader* hdr, 1659a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 166e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart rtattr** attr_data, 167e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart int* attr_length) { 168dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifi))) { 169dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 170dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 171dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 172dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_ = mode; 173dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_data = IFLA_RTA(NLMSG_DATA(&hdr->hdr)); 174dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_length = IFLA_PAYLOAD(&hdr->hdr); 175dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 1769a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ = kTypeLink; 177dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_ = hdr->ifi.ifi_family; 178dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_ = hdr->ifi.ifi_index; 179dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart set_link_status(LinkStatus(hdr->ifi.ifi_type, 180dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_flags, 181dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_change)); 182dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 183dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 184dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 185e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::DecodeAddress(const RTNLHeader* hdr, 1869a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 187e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart rtattr** attr_data, 188e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart int* attr_length) { 189dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifa))) { 190dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 191dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 192dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_ = mode; 193dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_data = IFA_RTA(NLMSG_DATA(&hdr->hdr)); 194dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_length = IFA_PAYLOAD(&hdr->hdr); 195dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 1969a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ = kTypeAddress; 197dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_ = hdr->ifa.ifa_family; 198dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_ = hdr->ifa.ifa_index; 199dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart set_address_status(AddressStatus(hdr->ifa.ifa_prefixlen, 200dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_flags, 201dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_scope)); 202dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 203dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 204dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 205e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::DecodeRoute(const RTNLHeader* hdr, 2069a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 207e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart rtattr** attr_data, 208e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart int* attr_length) { 209dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->rtm))) { 210dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 211dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 212dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_ = mode; 213dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr)); 214dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_length = RTM_PAYLOAD(&hdr->hdr); 215dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 2169a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ = kTypeRoute; 217dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_ = hdr->rtm.rtm_family; 218dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart set_route_status(RouteStatus(hdr->rtm.rtm_dst_len, 219dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_src_len, 220dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_table, 221dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_protocol, 222dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_scope, 223dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_type, 224dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_flags)); 225dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 226dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 227dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 228e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::DecodeNdUserOption(const RTNLHeader* hdr, 2293ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu Mode mode, 230e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart rtattr** attr_data, 231e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart int* attr_length) { 2323ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->nd_user_opt))) { 2333ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2343ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2353ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2363ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu mode_ = mode; 2373ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu interface_index_ = hdr->nd_user_opt.nduseropt_ifindex; 2383ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu family_ = hdr->nd_user_opt.nduseropt_family; 2393ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2403ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Verify IP family. 2413ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (family_ != IPAddress::kFamilyIPv6) { 2423ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2433ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2443ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Verify message must at-least contain the option header. 2453ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (hdr->nd_user_opt.nduseropt_opts_len < sizeof(NDUserOptionHeader)) { 2463ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2473ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2483ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2493ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Parse the option header. 250e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart const NDUserOptionHeader* nd_user_option_header = 251e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart reinterpret_cast<const NDUserOptionHeader*>( 252e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart reinterpret_cast<const uint8_t*>(&hdr->nd_user_opt) + 2533ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu sizeof(struct nduseroptmsg)); 2547fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t lifetime = ntohl(nd_user_option_header->lifetime); 2553ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2563ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Verify option length. 2573ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // The length field in the header is in units of 8 octets. 2583ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu int opt_len = static_cast<int>(nd_user_option_header->length) * 8; 2593ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (opt_len != hdr->nd_user_opt.nduseropt_opts_len) { 2603ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2613ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2623ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2633ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Determine option data pointer and data length. 264e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart const uint8_t* option_data = 265e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart reinterpret_cast<const uint8_t*>(nd_user_option_header + 1); 2663ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu int data_len = opt_len - sizeof(NDUserOptionHeader); 2673ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2683ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (nd_user_option_header->type == ND_OPT_DNSSL) { 2693ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // TODO(zqiu): Parse DNSSL (DNS Search List) option. 2703ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu type_ = kTypeDnssl; 2713ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return true; 2723ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } else if (nd_user_option_header->type == ND_OPT_RDNSS) { 2733ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Parse RNDSS (Recursive DNS Server) option. 2743ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu type_ = kTypeRdnss; 2753ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return ParseRdnssOption(option_data, data_len, lifetime); 2763ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2773ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2783ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2793ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu} 2803ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 281e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::ParseRdnssOption(const uint8_t* data, 2823ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu int length, 2837fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t lifetime) { 2843ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu const int addr_length = IPAddress::GetAddressLength(IPAddress::kFamilyIPv6); 2853ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2863ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Verify data size are multiple of individual address size. 2873ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (length % addr_length != 0) { 2883ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2893ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2903ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2913ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Parse the DNS server addresses. 2923ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu std::vector<IPAddress> dns_server_addresses; 2933ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu while (length > 0) { 2943ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu dns_server_addresses.push_back( 2953ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu IPAddress(IPAddress::kFamilyIPv6, 2963ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu ByteString(data, addr_length))); 2973ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu length -= addr_length; 2983ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu data += addr_length; 2993ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 3003ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu set_rdnss_option(RdnssOption(lifetime, dns_server_addresses)); 3013ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return true; 3023ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu} 3033ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 304e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::DecodeNeighbor(const RTNLHeader* hdr, 305ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly Mode mode, 306e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart rtattr** attr_data, 307e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart int* attr_length) { 308ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ndm))) { 309ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return false; 310ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly } 311ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 312ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly mode_ = mode; 313ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly interface_index_ = hdr->ndm.ndm_ifindex; 314ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly family_ = hdr->ndm.ndm_family; 315ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly type_ = kTypeNeighbor; 316ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 317ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr)); 318ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly *attr_length = RTM_PAYLOAD(&hdr->hdr); 319ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 320ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly set_neighbor_status(NeighborStatus(hdr->ndm.ndm_state, 321ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_flags, 322ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_type)); 323ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return true; 324ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly} 325ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 326f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul StewartByteString RTNLMessage::Encode() const { 3279a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (type_ != kTypeLink && 3289a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ != kTypeAddress && 329ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly type_ != kTypeRoute && 330ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly type_ != kTypeNeighbor) { 331dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return ByteString(); 332dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 333dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 334dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart RTNLHeader hdr; 335dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_flags = flags_; 336dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_seq = seq_; 337dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_pid = pid_; 338dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 3399a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (mode_ == kModeGet) { 3409a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (type_ == kTypeLink) { 341dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_type = RTM_GETLINK; 3429a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (type_ == kTypeAddress) { 343dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_type = RTM_GETADDR; 3449a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (type_ == kTypeRoute) { 345dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_type = RTM_GETROUTE; 346ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly } else if (type_ == kTypeNeighbor) { 347ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr.hdr.nlmsg_type = RTM_GETNEIGH; 348f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } else { 349f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 350f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 351dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 352dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr.gen)); 3539a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart hdr.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; 354dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.gen.rtgen_family = family_; 355dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } else { 356dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart switch (type_) { 3579a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart case kTypeLink: 358f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart if (!EncodeLink(&hdr)) { 359f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 360f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 361dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 362dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 3639a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart case kTypeAddress: 364f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart if (!EncodeAddress(&hdr)) { 365f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 366f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 367dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 368dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 3699a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart case kTypeRoute: 370f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart if (!EncodeRoute(&hdr)) { 371f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 372f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 373dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 374dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 375ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case kTypeNeighbor: 376ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly if (!EncodeNeighbor(&hdr)) { 377ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return ByteString(); 378ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly } 379ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly break; 380ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 381dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart default: 382dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart NOTREACHED(); 383dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 384dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 385dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 386dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart size_t header_length = hdr.hdr.nlmsg_len; 387dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString attributes; 388dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 3898a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko for (auto attr = attributes_.begin(); attr != attributes_.end(); ++attr) { 390dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart size_t len = RTA_LENGTH(attr->second.GetLength()); 391dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_len = NLMSG_ALIGN(hdr.hdr.nlmsg_len) + RTA_ALIGN(len); 392dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 3938a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko struct rtattr rt_attr = { 3948a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko static_cast<unsigned short>(len), // NOLINT(runtime/int) 3958a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko attr->first 3968a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko }; 397e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart ByteString attr_header(reinterpret_cast<unsigned char*>(&rt_attr), 398dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart sizeof(rt_attr)); 399dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_header.Resize(RTA_ALIGN(attr_header.GetLength())); 400dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attributes.Append(attr_header); 401dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 402dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString attr_data(attr->second); 403dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_data.Resize(RTA_ALIGN(attr_data.GetLength())); 404dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attributes.Append(attr_data); 405dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 406dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 407e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewart ByteString packet(reinterpret_cast<unsigned char*>(&hdr), header_length); 408dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart packet.Append(attributes); 409dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 410dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return packet; 411dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 412dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 413e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::EncodeLink(RTNLHeader* hdr) const { 414f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart switch (mode_) { 415f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeAdd: 416f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_NEWLINK; 417f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 418f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeDelete: 419f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_DELLINK; 420f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 421f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeQuery: 422f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_GETLINK; 423f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 424f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart default: 425f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 426f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return false; 427f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 428dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifi)); 429dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_family = family_; 430cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart hdr->ifi.ifi_index = interface_index_; 431dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_type = link_status_.type; 432dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_flags = link_status_.flags; 433dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_change = link_status_.change; 434f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return true; 435dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 436dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 437e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::EncodeAddress(RTNLHeader* hdr) const { 438f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart switch (mode_) { 439f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeAdd: 440f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_NEWADDR; 441f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 442f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeDelete: 443f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_DELADDR; 444f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 445f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeQuery: 446f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_GETADDR; 447f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 448f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart default: 449f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 450f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return false; 451f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 452dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifa)); 453dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_family = family_; 454dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_prefixlen = address_status_.prefix_len; 455dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_flags = address_status_.flags; 456dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_scope = address_status_.scope; 457dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_index = interface_index_; 458f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return true; 459dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 460dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 461e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::EncodeRoute(RTNLHeader* hdr) const { 462f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart switch (mode_) { 463f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeAdd: 464f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_NEWROUTE; 465f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 466f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeDelete: 467f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_DELROUTE; 468f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 469f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeQuery: 470f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_GETROUTE; 471f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 472f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart default: 473f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 474f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return false; 475f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 476dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->rtm)); 477dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_family = family_; 478dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_dst_len = route_status_.dst_prefix; 479dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_src_len = route_status_.src_prefix; 480dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_table = route_status_.table; 481dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_protocol = route_status_.protocol; 482dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_scope = route_status_.scope; 483dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_type = route_status_.type; 484dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_flags = route_status_.flags; 485f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return true; 486f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart} 487f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart 488e67a78539a05ea7fc68ed5ca18f6d1de333a3086Paul Stewartbool RTNLMessage::EncodeNeighbor(RTNLHeader* hdr) const { 489ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly switch (mode_) { 490ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case kModeAdd: 491ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->hdr.nlmsg_type = RTM_NEWNEIGH; 492ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly break; 493ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case kModeDelete: 494ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->hdr.nlmsg_type = RTM_DELNEIGH; 495ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly break; 496ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case kModeQuery: 497ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->hdr.nlmsg_type = RTM_GETNEIGH; 498ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly break; 499ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly default: 500ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly NOTIMPLEMENTED(); 501ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return false; 502ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly } 503ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ndm)); 504ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_family = family_; 505ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_ifindex = interface_index_; 506ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_state = neighbor_status_.state; 507ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_flags = neighbor_status_.flags; 508ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_type = neighbor_status_.type; 509ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return true; 510ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly} 511ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 512f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartvoid RTNLMessage::Reset() { 513f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart mode_ = kModeUnknown; 514f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart type_ = kTypeUnknown; 515f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart flags_ = 0; 516f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart seq_ = 0; 517e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov pid_ = 0; 518f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart interface_index_ = 0; 519f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart family_ = IPAddress::kFamilyUnknown; 520f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart link_status_ = LinkStatus(); 521f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart address_status_ = AddressStatus(); 522f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart route_status_ = RouteStatus(); 523f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart attributes_.clear(); 524dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 525dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 526dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} // namespace shill 527