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