rtnl_message.cc revision ad576bffebd92b9adf42ea6b9e43515169787cee
1f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart// Use of this source code is governed by a BSD-style license that can be 3dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart// found in the LICENSE file. 4dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 58d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/rtnl_message.h" 6dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 7dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart#include <linux/netlink.h> 8dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart#include <linux/rtnetlink.h> 93ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu#include <netinet/in.h> 10a41ab517725d036b63420f8445550246f8f50b99Alex Vakulenko#include <sys/socket.h> 11dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 128d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include <base/logging.h> 138d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu 148d6b59704591ba9fad57751858835dc332dbdd37Peter Qiu#include "shill/net/ndisc.h" 15b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley 16dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartnamespace shill { 17dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 18dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartstruct RTNLHeader { 19dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart RTNLHeader() { 20dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart memset(this, 0, sizeof(*this)); 21dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 22dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct nlmsghdr hdr; 23dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart union { 24dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct ifinfomsg ifi; 25dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct ifaddrmsg ifa; 26dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct rtmsg rtm; 27dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct rtgenmsg gen; 283ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu struct nduseroptmsg nd_user_opt; 29ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly struct ndmsg ndm; 30dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart }; 31dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}; 32dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 33dd7df792d2401741183a954f3f6e97d4c6de1e22Paul StewartRTNLMessage::RTNLMessage() 349a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart : type_(kTypeUnknown), 359a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart mode_(kModeUnknown), 36dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart flags_(0), 37e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov seq_(0), 38e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov pid_(0), 39dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_(0), 407355ce1937c504d836a303ac809bd436272212b3Paul Stewart family_(IPAddress::kFamilyUnknown) {} 41dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 429a908080fc2a72dbf06f995b878fc8a3693b725aPaul StewartRTNLMessage::RTNLMessage(Type type, 439a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 44dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart unsigned int flags, 457fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t seq, 467fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t pid, 47dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int interface_index, 48dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart IPAddress::Family family) 49dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart : type_(type), 50dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_(mode), 51dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart flags_(flags), 52dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart seq_(seq), 53dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart pid_(pid), 54dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_(interface_index), 55dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_(family) {} 56dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 57dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::Decode(const ByteString &msg) { 58dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart bool ret = DecodeInternal(msg); 59dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!ret) { 60f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart Reset(); 61dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 62dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return ret; 63dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 64dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 65dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeInternal(const ByteString &msg) { 66dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart const RTNLHeader *hdr = 67dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart reinterpret_cast<const RTNLHeader *>(msg.GetConstData()); 68dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 69dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (msg.GetLength() < sizeof(hdr->hdr) || 70dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart msg.GetLength() < hdr->hdr.nlmsg_len) 71dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 72dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 739a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode = kModeUnknown; 74dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart switch (hdr->hdr.nlmsg_type) { 75dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWLINK: 76dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWADDR: 77dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWROUTE: 783ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu case RTM_NEWNDUSEROPT: 79ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case RTM_NEWNEIGH: 809a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart mode = kModeAdd; 81dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 82dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 83dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELLINK: 84dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELADDR: 85dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELROUTE: 86ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case RTM_DELNEIGH: 879a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart mode = kModeDelete; 88dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 89dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 90dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart default: 91dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 92dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 93dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 94cc225ef3b77b5e098cc12c661a947e1737480777Ben Chan rtattr *attr_data = nullptr; 95dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int attr_length = 0; 96dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 97dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart switch (hdr->hdr.nlmsg_type) { 98dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWLINK: 99dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELLINK: 100dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!DecodeLink(hdr, mode, &attr_data, &attr_length)) 101dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 102dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 103dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 104dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWADDR: 105dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELADDR: 106dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!DecodeAddress(hdr, mode, &attr_data, &attr_length)) 107dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 108dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 109dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 110dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWROUTE: 111dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELROUTE: 112dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!DecodeRoute(hdr, mode, &attr_data, &attr_length)) 113dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 114dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 115dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 1163ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu case RTM_NEWNDUSEROPT: 1173ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (!DecodeNdUserOption(hdr, mode, &attr_data, &attr_length)) 1183ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 1193ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu break; 1203ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 121ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case RTM_NEWNEIGH: 122ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case RTM_DELNEIGH: 123ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly if (!DecodeNeighbor(hdr, mode, &attr_data, &attr_length)) 124ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return false; 125ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly break; 126ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 127dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart default: 128dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart NOTREACHED(); 129dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 130dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 131dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart flags_ = hdr->hdr.nlmsg_flags; 132dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart seq_ = hdr->hdr.nlmsg_seq; 133dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart pid_ = hdr->hdr.nlmsg_pid; 134dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 135dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart while (attr_data && RTA_OK(attr_data, attr_length)) { 136dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart SetAttribute( 137dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_data->rta_type, 138dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString(reinterpret_cast<unsigned char *>(RTA_DATA(attr_data)), 139dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart RTA_PAYLOAD(attr_data))); 140dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_data = RTA_NEXT(attr_data, attr_length); 141dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 142dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 143dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (attr_length) { 144dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart // We hit a parse error while going through the attributes 145dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attributes_.clear(); 146dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 147dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 148dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 149dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 150dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 151dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 152dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeLink(const RTNLHeader *hdr, 1539a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 154dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart rtattr **attr_data, 155dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int *attr_length) { 156dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifi))) { 157dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 158dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 159dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 160dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_ = mode; 161dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_data = IFLA_RTA(NLMSG_DATA(&hdr->hdr)); 162dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_length = IFLA_PAYLOAD(&hdr->hdr); 163dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 1649a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ = kTypeLink; 165dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_ = hdr->ifi.ifi_family; 166dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_ = hdr->ifi.ifi_index; 167dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart set_link_status(LinkStatus(hdr->ifi.ifi_type, 168dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_flags, 169dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_change)); 170dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 171dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 172dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 173dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeAddress(const RTNLHeader *hdr, 1749a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 175dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart rtattr **attr_data, 176dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int *attr_length) { 177dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifa))) { 178dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 179dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 180dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_ = mode; 181dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_data = IFA_RTA(NLMSG_DATA(&hdr->hdr)); 182dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_length = IFA_PAYLOAD(&hdr->hdr); 183dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 1849a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ = kTypeAddress; 185dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_ = hdr->ifa.ifa_family; 186dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_ = hdr->ifa.ifa_index; 187dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart set_address_status(AddressStatus(hdr->ifa.ifa_prefixlen, 188dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_flags, 189dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_scope)); 190dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 191dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 192dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 193dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeRoute(const RTNLHeader *hdr, 1949a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 195dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart rtattr **attr_data, 196dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int *attr_length) { 197dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->rtm))) { 198dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 199dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 200dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_ = mode; 201dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr)); 202dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_length = RTM_PAYLOAD(&hdr->hdr); 203dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 2049a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ = kTypeRoute; 205dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_ = hdr->rtm.rtm_family; 206dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart set_route_status(RouteStatus(hdr->rtm.rtm_dst_len, 207dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_src_len, 208dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_table, 209dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_protocol, 210dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_scope, 211dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_type, 212dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_flags)); 213dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 214dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 215dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 2163ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiubool RTNLMessage::DecodeNdUserOption(const RTNLHeader *hdr, 2173ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu Mode mode, 2183ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu rtattr **attr_data, 2193ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu int *attr_length) { 2203ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->nd_user_opt))) { 2213ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2223ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2233ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2243ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu mode_ = mode; 2253ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu interface_index_ = hdr->nd_user_opt.nduseropt_ifindex; 2263ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu family_ = hdr->nd_user_opt.nduseropt_family; 2273ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2283ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Verify IP family. 2293ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (family_ != IPAddress::kFamilyIPv6) { 2303ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2313ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2323ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Verify message must at-least contain the option header. 2333ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (hdr->nd_user_opt.nduseropt_opts_len < sizeof(NDUserOptionHeader)) { 2343ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2353ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2363ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2373ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Parse the option header. 2383ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu const NDUserOptionHeader *nd_user_option_header = 2393ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu reinterpret_cast<const NDUserOptionHeader *>( 2407fab89734d88724a288e96a9996b15548c5294c7Ben Chan reinterpret_cast<const uint8_t *>(&hdr->nd_user_opt) + 2413ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu sizeof(struct nduseroptmsg)); 2427fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t lifetime = ntohl(nd_user_option_header->lifetime); 2433ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2443ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Verify option length. 2453ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // The length field in the header is in units of 8 octets. 2463ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu int opt_len = static_cast<int>(nd_user_option_header->length) * 8; 2473ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (opt_len != hdr->nd_user_opt.nduseropt_opts_len) { 2483ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2493ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2503ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2513ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Determine option data pointer and data length. 2527fab89734d88724a288e96a9996b15548c5294c7Ben Chan const uint8_t *option_data = 2537fab89734d88724a288e96a9996b15548c5294c7Ben Chan reinterpret_cast<const uint8_t *>(nd_user_option_header + 1); 2543ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu int data_len = opt_len - sizeof(NDUserOptionHeader); 2553ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2563ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (nd_user_option_header->type == ND_OPT_DNSSL) { 2573ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // TODO(zqiu): Parse DNSSL (DNS Search List) option. 2583ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu type_ = kTypeDnssl; 2593ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return true; 2603ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } else if (nd_user_option_header->type == ND_OPT_RDNSS) { 2613ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Parse RNDSS (Recursive DNS Server) option. 2623ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu type_ = kTypeRdnss; 2633ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return ParseRdnssOption(option_data, data_len, lifetime); 2643ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2653ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2663ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2673ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu} 2683ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2697fab89734d88724a288e96a9996b15548c5294c7Ben Chanbool RTNLMessage::ParseRdnssOption(const uint8_t *data, 2703ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu int length, 2717fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint32_t lifetime) { 2723ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu const int addr_length = IPAddress::GetAddressLength(IPAddress::kFamilyIPv6); 2733ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2743ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Verify data size are multiple of individual address size. 2753ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu if (length % addr_length != 0) { 2763ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return false; 2773ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2783ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 2793ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu // Parse the DNS server addresses. 2803ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu std::vector<IPAddress> dns_server_addresses; 2813ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu while (length > 0) { 2823ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu dns_server_addresses.push_back( 2833ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu IPAddress(IPAddress::kFamilyIPv6, 2843ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu ByteString(data, addr_length))); 2853ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu length -= addr_length; 2863ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu data += addr_length; 2873ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu } 2883ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu set_rdnss_option(RdnssOption(lifetime, dns_server_addresses)); 2893ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu return true; 2903ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu} 2913ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu 292ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kellybool RTNLMessage::DecodeNeighbor(const RTNLHeader *hdr, 293ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly Mode mode, 294ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly rtattr **attr_data, 295ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly int *attr_length) { 296ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ndm))) { 297ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return false; 298ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly } 299ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 300ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly mode_ = mode; 301ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly interface_index_ = hdr->ndm.ndm_ifindex; 302ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly family_ = hdr->ndm.ndm_family; 303ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly type_ = kTypeNeighbor; 304ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 305ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr)); 306ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly *attr_length = RTM_PAYLOAD(&hdr->hdr); 307ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 308ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly set_neighbor_status(NeighborStatus(hdr->ndm.ndm_state, 309ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_flags, 310ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_type)); 311ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return true; 312ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly} 313ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 314f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul StewartByteString RTNLMessage::Encode() const { 3159a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (type_ != kTypeLink && 3169a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ != kTypeAddress && 317ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly type_ != kTypeRoute && 318ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly type_ != kTypeNeighbor) { 319dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return ByteString(); 320dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 321dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 322dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart RTNLHeader hdr; 323dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_flags = flags_; 324dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_seq = seq_; 325dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_pid = pid_; 326dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 3279a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (mode_ == kModeGet) { 3289a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (type_ == kTypeLink) { 329dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_type = RTM_GETLINK; 3309a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (type_ == kTypeAddress) { 331dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_type = RTM_GETADDR; 3329a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (type_ == kTypeRoute) { 333dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_type = RTM_GETROUTE; 334ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly } else if (type_ == kTypeNeighbor) { 335ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr.hdr.nlmsg_type = RTM_GETNEIGH; 336f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } else { 337f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 338f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 339dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 340dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr.gen)); 3419a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart hdr.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; 342dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.gen.rtgen_family = family_; 343dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } else { 344dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart switch (type_) { 3459a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart case kTypeLink: 346f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart if (!EncodeLink(&hdr)) { 347f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 348f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 349dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 350dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 3519a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart case kTypeAddress: 352f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart if (!EncodeAddress(&hdr)) { 353f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 354f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 355dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 356dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 3579a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart case kTypeRoute: 358f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart if (!EncodeRoute(&hdr)) { 359f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 360f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 361dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 362dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 363ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case kTypeNeighbor: 364ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly if (!EncodeNeighbor(&hdr)) { 365ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return ByteString(); 366ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly } 367ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly break; 368ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 369dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart default: 370dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart NOTREACHED(); 371dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 372dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 373dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 374dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart size_t header_length = hdr.hdr.nlmsg_len; 375dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString attributes; 376dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 3778a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko for (auto attr = attributes_.begin(); attr != attributes_.end(); ++attr) { 378dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart size_t len = RTA_LENGTH(attr->second.GetLength()); 379dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_len = NLMSG_ALIGN(hdr.hdr.nlmsg_len) + RTA_ALIGN(len); 380dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 3818a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko struct rtattr rt_attr = { 3828a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko static_cast<unsigned short>(len), // NOLINT(runtime/int) 3838a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko attr->first 3848a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko }; 385dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString attr_header(reinterpret_cast<unsigned char *>(&rt_attr), 386dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart sizeof(rt_attr)); 387dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_header.Resize(RTA_ALIGN(attr_header.GetLength())); 388dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attributes.Append(attr_header); 389dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 390dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString attr_data(attr->second); 391dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_data.Resize(RTA_ALIGN(attr_data.GetLength())); 392dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attributes.Append(attr_data); 393dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 394dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 395dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString packet(reinterpret_cast<unsigned char *>(&hdr), header_length); 396dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart packet.Append(attributes); 397dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 398dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return packet; 399dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 400dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 401f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartbool RTNLMessage::EncodeLink(RTNLHeader *hdr) const { 402f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart switch (mode_) { 403f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeAdd: 404f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_NEWLINK; 405f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 406f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeDelete: 407f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_DELLINK; 408f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 409f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeQuery: 410f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_GETLINK; 411f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 412f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart default: 413f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 414f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return false; 415f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 416dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifi)); 417dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_family = family_; 418cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart hdr->ifi.ifi_index = interface_index_; 419dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_type = link_status_.type; 420dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_flags = link_status_.flags; 421dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_change = link_status_.change; 422f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return true; 423dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 424dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 425f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartbool RTNLMessage::EncodeAddress(RTNLHeader *hdr) const { 426f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart switch (mode_) { 427f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeAdd: 428f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_NEWADDR; 429f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 430f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeDelete: 431f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_DELADDR; 432f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 433f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeQuery: 434f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_GETADDR; 435f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 436f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart default: 437f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 438f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return false; 439f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 440dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifa)); 441dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_family = family_; 442dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_prefixlen = address_status_.prefix_len; 443dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_flags = address_status_.flags; 444dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_scope = address_status_.scope; 445dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_index = interface_index_; 446f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return true; 447dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 448dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 449f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartbool RTNLMessage::EncodeRoute(RTNLHeader *hdr) const { 450f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart switch (mode_) { 451f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeAdd: 452f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_NEWROUTE; 453f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 454f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeDelete: 455f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_DELROUTE; 456f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 457f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeQuery: 458f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_GETROUTE; 459f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 460f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart default: 461f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 462f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return false; 463f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 464dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->rtm)); 465dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_family = family_; 466dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_dst_len = route_status_.dst_prefix; 467dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_src_len = route_status_.src_prefix; 468dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_table = route_status_.table; 469dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_protocol = route_status_.protocol; 470dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_scope = route_status_.scope; 471dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_type = route_status_.type; 472dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_flags = route_status_.flags; 473f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return true; 474f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart} 475f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart 476ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kellybool RTNLMessage::EncodeNeighbor(RTNLHeader *hdr) const { 477ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly switch (mode_) { 478ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case kModeAdd: 479ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->hdr.nlmsg_type = RTM_NEWNEIGH; 480ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly break; 481ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case kModeDelete: 482ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->hdr.nlmsg_type = RTM_DELNEIGH; 483ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly break; 484ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly case kModeQuery: 485ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->hdr.nlmsg_type = RTM_GETNEIGH; 486ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly break; 487ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly default: 488ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly NOTIMPLEMENTED(); 489ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return false; 490ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly } 491ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ndm)); 492ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_family = family_; 493ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_ifindex = interface_index_; 494ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_state = neighbor_status_.state; 495ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_flags = neighbor_status_.flags; 496ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly hdr->ndm.ndm_type = neighbor_status_.type; 497ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly return true; 498ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly} 499ad576bffebd92b9adf42ea6b9e43515169787ceeGarret Kelly 500f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartvoid RTNLMessage::Reset() { 501f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart mode_ = kModeUnknown; 502f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart type_ = kTypeUnknown; 503f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart flags_ = 0; 504f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart seq_ = 0; 505e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov pid_ = 0; 506f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart interface_index_ = 0; 507f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart family_ = IPAddress::kFamilyUnknown; 508f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart link_status_ = LinkStatus(); 509f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart address_status_ = AddressStatus(); 510f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart route_status_ = RouteStatus(); 511f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart attributes_.clear(); 512dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 513dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 514dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} // namespace shill 515