rtnl_message.cc revision b691efd71561246065eae3cdd73a96ca1b8a528d
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 5dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart#include "shill/rtnl_message.h" 6dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 7dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart#include <sys/socket.h> 8dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart#include <linux/netlink.h> 9dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart#include <linux/rtnetlink.h> 10dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 11b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h" 12b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley 13dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartnamespace shill { 14dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 15dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartstruct RTNLHeader { 16dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart RTNLHeader() { 17dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart memset(this, 0, sizeof(*this)); 18dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 19dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct nlmsghdr hdr; 20dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart union { 21dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct ifinfomsg ifi; 22dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct ifaddrmsg ifa; 23dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct rtmsg rtm; 24dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart struct rtgenmsg gen; 25dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart }; 26dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}; 27dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 28dd7df792d2401741183a954f3f6e97d4c6de1e22Paul StewartRTNLMessage::RTNLMessage() 299a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart : type_(kTypeUnknown), 309a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart mode_(kModeUnknown), 31dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart flags_(0), 32e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov seq_(0), 33e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov pid_(0), 34dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_(0), 357355ce1937c504d836a303ac809bd436272212b3Paul Stewart family_(IPAddress::kFamilyUnknown) {} 36dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 379a908080fc2a72dbf06f995b878fc8a3693b725aPaul StewartRTNLMessage::RTNLMessage(Type type, 389a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 39dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart unsigned int flags, 40dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart uint32 seq, 41dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart uint32 pid, 42dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int interface_index, 43dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart IPAddress::Family family) 44dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart : type_(type), 45dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_(mode), 46dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart flags_(flags), 47dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart seq_(seq), 48dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart pid_(pid), 49dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_(interface_index), 50dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_(family) {} 51dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 52dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::Decode(const ByteString &msg) { 53dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart bool ret = DecodeInternal(msg); 54dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!ret) { 55f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart Reset(); 56dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 57dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return ret; 58dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 59dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 60dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeInternal(const ByteString &msg) { 61dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart const RTNLHeader *hdr = 62dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart reinterpret_cast<const RTNLHeader *>(msg.GetConstData()); 63dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 64dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (msg.GetLength() < sizeof(hdr->hdr) || 65dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart msg.GetLength() < hdr->hdr.nlmsg_len) 66dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 67dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 689a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode = kModeUnknown; 69dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart switch (hdr->hdr.nlmsg_type) { 70dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWLINK: 71dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWADDR: 72dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWROUTE: 739a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart mode = kModeAdd; 74dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 75dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 76dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELLINK: 77dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELADDR: 78dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELROUTE: 799a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart mode = kModeDelete; 80dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 81dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 82dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart default: 83dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 84dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 85dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 86dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart rtattr *attr_data = NULL; 87dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int attr_length = 0; 88dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 89dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart switch (hdr->hdr.nlmsg_type) { 90dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWLINK: 91dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELLINK: 92dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!DecodeLink(hdr, mode, &attr_data, &attr_length)) 93dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 94dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 95dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 96dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWADDR: 97dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELADDR: 98dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!DecodeAddress(hdr, mode, &attr_data, &attr_length)) 99dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 100dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 101dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 102dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_NEWROUTE: 103dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart case RTM_DELROUTE: 104dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (!DecodeRoute(hdr, mode, &attr_data, &attr_length)) 105dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 106dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 107dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 108dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart default: 109dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart NOTREACHED(); 110dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 111dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 112dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart flags_ = hdr->hdr.nlmsg_flags; 113dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart seq_ = hdr->hdr.nlmsg_seq; 114dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart pid_ = hdr->hdr.nlmsg_pid; 115dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 116dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart while (attr_data && RTA_OK(attr_data, attr_length)) { 117dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart SetAttribute( 118dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_data->rta_type, 119dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString(reinterpret_cast<unsigned char *>(RTA_DATA(attr_data)), 120dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart RTA_PAYLOAD(attr_data))); 121dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_data = RTA_NEXT(attr_data, attr_length); 122dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 123dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 124dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (attr_length) { 125dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart // We hit a parse error while going through the attributes 126dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attributes_.clear(); 127dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 128dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 129dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 130dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 131dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 132dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 133dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeLink(const RTNLHeader *hdr, 1349a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 135dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart rtattr **attr_data, 136dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int *attr_length) { 137dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifi))) { 138dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 139dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 140dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 141dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_ = mode; 142dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_data = IFLA_RTA(NLMSG_DATA(&hdr->hdr)); 143dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_length = IFLA_PAYLOAD(&hdr->hdr); 144dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 1459a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ = kTypeLink; 146dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_ = hdr->ifi.ifi_family; 147dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_ = hdr->ifi.ifi_index; 148dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart set_link_status(LinkStatus(hdr->ifi.ifi_type, 149dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_flags, 150dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_change)); 151dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 152dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 153dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 154dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeAddress(const RTNLHeader *hdr, 1559a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 156dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart rtattr **attr_data, 157dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int *attr_length) { 158dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifa))) { 159dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 160dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 161dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_ = mode; 162dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_data = IFA_RTA(NLMSG_DATA(&hdr->hdr)); 163dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_length = IFA_PAYLOAD(&hdr->hdr); 164dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 1659a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ = kTypeAddress; 166dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_ = hdr->ifa.ifa_family; 167dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart interface_index_ = hdr->ifa.ifa_index; 168dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart set_address_status(AddressStatus(hdr->ifa.ifa_prefixlen, 169dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_flags, 170dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_scope)); 171dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 172dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 173dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 174dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeRoute(const RTNLHeader *hdr, 1759a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart Mode mode, 176dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart rtattr **attr_data, 177dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart int *attr_length) { 178dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->rtm))) { 179dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return false; 180dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 181dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart mode_ = mode; 182dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr)); 183dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart *attr_length = RTM_PAYLOAD(&hdr->hdr); 184dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 1859a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ = kTypeRoute; 186dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart family_ = hdr->rtm.rtm_family; 187dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart set_route_status(RouteStatus(hdr->rtm.rtm_dst_len, 188dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_src_len, 189dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_table, 190dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_protocol, 191dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_scope, 192dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_type, 193dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_flags)); 194dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return true; 195dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 196dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 197f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul StewartByteString RTNLMessage::Encode() const { 1989a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (type_ != kTypeLink && 1999a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ != kTypeAddress && 2009a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart type_ != kTypeRoute) { 201dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return ByteString(); 202dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 203dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 204dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart RTNLHeader hdr; 205dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_flags = flags_; 206dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_seq = seq_; 207dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_pid = pid_; 208dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 2099a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (mode_ == kModeGet) { 2109a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart if (type_ == kTypeLink) { 211dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_type = RTM_GETLINK; 2129a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (type_ == kTypeAddress) { 213dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_type = RTM_GETADDR; 2149a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart } else if (type_ == kTypeRoute) { 215dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_type = RTM_GETROUTE; 216f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } else { 217f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 218f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 219dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 220dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr.gen)); 2219a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart hdr.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; 222dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.gen.rtgen_family = family_; 223dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } else { 224dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart switch (type_) { 2259a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart case kTypeLink: 226f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart if (!EncodeLink(&hdr)) { 227f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 228f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 229dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 230dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 2319a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart case kTypeAddress: 232f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart if (!EncodeAddress(&hdr)) { 233f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 234f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 235dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 236dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 2379a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart case kTypeRoute: 238f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart if (!EncodeRoute(&hdr)) { 239f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return ByteString(); 240f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 241dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart break; 242dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 243dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart default: 244dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart NOTREACHED(); 245dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 246dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 247dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 248dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart size_t header_length = hdr.hdr.nlmsg_len; 249dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString attributes; 250dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 251f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart base::hash_map<uint16, ByteString>::const_iterator attr; 252dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart for (attr = attributes_.begin(); attr != attributes_.end(); ++attr) { 253dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart size_t len = RTA_LENGTH(attr->second.GetLength()); 254dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr.hdr.nlmsg_len = NLMSG_ALIGN(hdr.hdr.nlmsg_len) + RTA_ALIGN(len); 255dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 256b970b8fa6d18145234ee243a7b6e7d77b411b88aHan Shen struct rtattr rt_attr = { static_cast<unsigned short>(len), attr->first }; 257dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString attr_header(reinterpret_cast<unsigned char *>(&rt_attr), 258dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart sizeof(rt_attr)); 259dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_header.Resize(RTA_ALIGN(attr_header.GetLength())); 260dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attributes.Append(attr_header); 261dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 262dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString attr_data(attr->second); 263dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attr_data.Resize(RTA_ALIGN(attr_data.GetLength())); 264dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart attributes.Append(attr_data); 265dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart } 266dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 267dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart ByteString packet(reinterpret_cast<unsigned char *>(&hdr), header_length); 268dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart packet.Append(attributes); 269dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 270dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart return packet; 271dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 272dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 273f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartbool RTNLMessage::EncodeLink(RTNLHeader *hdr) const { 274f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart switch (mode_) { 275f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeAdd: 276f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_NEWLINK; 277f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 278f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeDelete: 279f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_DELLINK; 280f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 281f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeQuery: 282f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_GETLINK; 283f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 284f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart default: 285f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 286f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return false; 287f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 288dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifi)); 289dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_family = family_; 290cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart hdr->ifi.ifi_index = interface_index_; 291dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_type = link_status_.type; 292dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_flags = link_status_.flags; 293dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifi.ifi_change = link_status_.change; 294f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return true; 295dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 296dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 297f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartbool RTNLMessage::EncodeAddress(RTNLHeader *hdr) const { 298f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart switch (mode_) { 299f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeAdd: 300f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_NEWADDR; 301f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 302f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeDelete: 303f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_DELADDR; 304f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 305f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeQuery: 306f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_GETADDR; 307f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 308f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart default: 309f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 310f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return false; 311f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 312dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifa)); 313dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_family = family_; 314dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_prefixlen = address_status_.prefix_len; 315dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_flags = address_status_.flags; 316dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_scope = address_status_.scope; 317dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->ifa.ifa_index = interface_index_; 318f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return true; 319dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 320dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 321f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartbool RTNLMessage::EncodeRoute(RTNLHeader *hdr) const { 322f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart switch (mode_) { 323f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeAdd: 324f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_NEWROUTE; 325f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 326f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeDelete: 327f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_DELROUTE; 328f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 329f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart case kModeQuery: 330f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart hdr->hdr.nlmsg_type = RTM_GETROUTE; 331f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart break; 332f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart default: 333f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart NOTIMPLEMENTED(); 334f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return false; 335f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart } 336dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->rtm)); 337dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_family = family_; 338dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_dst_len = route_status_.dst_prefix; 339dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_src_len = route_status_.src_prefix; 340dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_table = route_status_.table; 341dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_protocol = route_status_.protocol; 342dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_scope = route_status_.scope; 343dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_type = route_status_.type; 344dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart hdr->rtm.rtm_flags = route_status_.flags; 345f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart return true; 346f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart} 347f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart 348f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartvoid RTNLMessage::Reset() { 349f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart mode_ = kModeUnknown; 350f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart type_ = kTypeUnknown; 351f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart flags_ = 0; 352f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart seq_ = 0; 353e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov pid_ = 0; 354f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart interface_index_ = 0; 355f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart family_ = IPAddress::kFamilyUnknown; 356f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart link_status_ = LinkStatus(); 357f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart address_status_ = AddressStatus(); 358f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart route_status_ = RouteStatus(); 359f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart attributes_.clear(); 360dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} 361dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart 362dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart} // namespace shill 363