rtnl_message.cc revision 7fab89734d88724a288e96a9996b15548c5294c7
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 <linux/netlink.h>
8dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart#include <linux/rtnetlink.h>
93ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu#include <netinet/in.h>
10a41ab517725d036b63420f8445550246f8f50b99Alex Vakulenko#include <sys/socket.h>
11dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
12b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley#include "shill/logging.h"
133ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu#include "shill/ndisc.h"
14b691efd71561246065eae3cdd73a96ca1b8a528dChristopher Wiley
15dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartnamespace shill {
16dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
17dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartstruct RTNLHeader {
18dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  RTNLHeader() {
19dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    memset(this, 0, sizeof(*this));
20dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
21dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  struct nlmsghdr hdr;
22dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  union {
23dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    struct ifinfomsg ifi;
24dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    struct ifaddrmsg ifa;
25dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    struct rtmsg rtm;
26dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    struct rtgenmsg gen;
273ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    struct nduseroptmsg nd_user_opt;
28dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  };
29dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart};
30dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
31dd7df792d2401741183a954f3f6e97d4c6de1e22Paul StewartRTNLMessage::RTNLMessage()
329a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart    : type_(kTypeUnknown),
339a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart      mode_(kModeUnknown),
34dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      flags_(0),
35e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov      seq_(0),
36e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov      pid_(0),
37dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      interface_index_(0),
387355ce1937c504d836a303ac809bd436272212b3Paul Stewart      family_(IPAddress::kFamilyUnknown) {}
39dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
409a908080fc2a72dbf06f995b878fc8a3693b725aPaul StewartRTNLMessage::RTNLMessage(Type type,
419a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart                         Mode mode,
42dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                         unsigned int flags,
437fab89734d88724a288e96a9996b15548c5294c7Ben Chan                         uint32_t seq,
447fab89734d88724a288e96a9996b15548c5294c7Ben Chan                         uint32_t pid,
45dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                         int interface_index,
46dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                         IPAddress::Family family)
47dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    : type_(type),
48dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      mode_(mode),
49dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      flags_(flags),
50dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      seq_(seq),
51dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      pid_(pid),
52dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      interface_index_(interface_index),
53dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      family_(family) {}
54dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
55dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::Decode(const ByteString &msg) {
56dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  bool ret = DecodeInternal(msg);
57dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  if (!ret) {
58f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    Reset();
59dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
60dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  return ret;
61dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}
62dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
63dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeInternal(const ByteString &msg) {
64dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  const RTNLHeader *hdr =
65dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      reinterpret_cast<const RTNLHeader *>(msg.GetConstData());
66dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
67dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  if (msg.GetLength() < sizeof(hdr->hdr) ||
68dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      msg.GetLength() < hdr->hdr.nlmsg_len)
69dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    return false;
70dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
719a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart  Mode mode = kModeUnknown;
72dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  switch (hdr->hdr.nlmsg_type) {
73dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_NEWLINK:
74dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_NEWADDR:
75dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_NEWROUTE:
763ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  case RTM_NEWNDUSEROPT:
779a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart    mode = kModeAdd;
78dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    break;
79dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
80dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_DELLINK:
81dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_DELADDR:
82dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_DELROUTE:
839a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart    mode = kModeDelete;
84dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    break;
85dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
86dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  default:
87dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    return false;
88dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
89dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
90dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  rtattr *attr_data = NULL;
91dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  int attr_length = 0;
92dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
93dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  switch (hdr->hdr.nlmsg_type) {
94dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_NEWLINK:
95dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_DELLINK:
96dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    if (!DecodeLink(hdr, mode, &attr_data, &attr_length))
97dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      return false;
98dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    break;
99dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
100dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_NEWADDR:
101dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_DELADDR:
102dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    if (!DecodeAddress(hdr, mode, &attr_data, &attr_length))
103dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      return false;
104dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    break;
105dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
106dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_NEWROUTE:
107dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  case RTM_DELROUTE:
108dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    if (!DecodeRoute(hdr, mode, &attr_data, &attr_length))
109dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      return false;
110dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    break;
111dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
1123ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  case RTM_NEWNDUSEROPT:
1133ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    if (!DecodeNdUserOption(hdr, mode, &attr_data, &attr_length))
1143ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu      return false;
1153ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    break;
1163ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
117dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  default:
118dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    NOTREACHED();
119dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
120dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
121dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  flags_ = hdr->hdr.nlmsg_flags;
122dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  seq_ = hdr->hdr.nlmsg_seq;
123dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  pid_ = hdr->hdr.nlmsg_pid;
124dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
125dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  while (attr_data && RTA_OK(attr_data, attr_length)) {
126dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    SetAttribute(
127dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart        attr_data->rta_type,
128dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart        ByteString(reinterpret_cast<unsigned char *>(RTA_DATA(attr_data)),
129dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                   RTA_PAYLOAD(attr_data)));
130dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    attr_data = RTA_NEXT(attr_data, attr_length);
131dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
132dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
133dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  if (attr_length) {
134dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    // We hit a parse error while going through the attributes
135dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    attributes_.clear();
136dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    return false;
137dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
138dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
139dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  return true;
140dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}
141dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
142dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeLink(const RTNLHeader *hdr,
1439a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart                             Mode mode,
144dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                             rtattr **attr_data,
145dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                             int *attr_length) {
146dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifi))) {
147dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    return false;
148dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
149dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
150dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  mode_ = mode;
151dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  *attr_data = IFLA_RTA(NLMSG_DATA(&hdr->hdr));
152dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  *attr_length = IFLA_PAYLOAD(&hdr->hdr);
153dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
1549a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart  type_ = kTypeLink;
155dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  family_ = hdr->ifi.ifi_family;
156dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  interface_index_ = hdr->ifi.ifi_index;
157dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  set_link_status(LinkStatus(hdr->ifi.ifi_type,
158dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                             hdr->ifi.ifi_flags,
159dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                             hdr->ifi.ifi_change));
160dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  return true;
161dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}
162dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
163dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeAddress(const RTNLHeader *hdr,
1649a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart                                Mode mode,
165dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                                rtattr **attr_data,
166dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                                int *attr_length) {
167dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifa))) {
168dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    return false;
169dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
170dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  mode_ = mode;
171dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  *attr_data = IFA_RTA(NLMSG_DATA(&hdr->hdr));
172dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  *attr_length = IFA_PAYLOAD(&hdr->hdr);
173dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
1749a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart  type_ = kTypeAddress;
175dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  family_ = hdr->ifa.ifa_family;
176dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  interface_index_ = hdr->ifa.ifa_index;
177dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  set_address_status(AddressStatus(hdr->ifa.ifa_prefixlen,
178dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                                   hdr->ifa.ifa_flags,
179dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                                   hdr->ifa.ifa_scope));
180dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  return true;
181dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}
182dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
183dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewartbool RTNLMessage::DecodeRoute(const RTNLHeader *hdr,
1849a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart                              Mode mode,
185dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                              rtattr **attr_data,
186dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                              int *attr_length) {
187dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->rtm))) {
188dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    return false;
189dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
190dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  mode_ = mode;
191dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr));
192dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  *attr_length = RTM_PAYLOAD(&hdr->hdr);
193dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
1949a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart  type_ = kTypeRoute;
195dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  family_ = hdr->rtm.rtm_family;
196dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  set_route_status(RouteStatus(hdr->rtm.rtm_dst_len,
197dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                               hdr->rtm.rtm_src_len,
198dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                               hdr->rtm.rtm_table,
199dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                               hdr->rtm.rtm_protocol,
200dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                               hdr->rtm.rtm_scope,
201dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                               hdr->rtm.rtm_type,
202dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                               hdr->rtm.rtm_flags));
203dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  return true;
204dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}
205dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
2063ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiubool RTNLMessage::DecodeNdUserOption(const RTNLHeader *hdr,
2073ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu                                     Mode mode,
2083ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu                                     rtattr **attr_data,
2093ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu                                     int *attr_length) {
2103ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->nd_user_opt))) {
2113ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    return false;
2123ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  }
2133ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
2143ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  mode_ = mode;
2153ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  interface_index_ = hdr->nd_user_opt.nduseropt_ifindex;
2163ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  family_ = hdr->nd_user_opt.nduseropt_family;
2173ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
2183ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  // Verify IP family.
2193ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  if (family_ != IPAddress::kFamilyIPv6) {
2203ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    return false;
2213ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  }
2223ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  // Verify message must at-least contain the option header.
2233ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  if (hdr->nd_user_opt.nduseropt_opts_len < sizeof(NDUserOptionHeader)) {
2243ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    return false;
2253ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  }
2263ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
2273ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  // Parse the option header.
2283ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  const NDUserOptionHeader *nd_user_option_header =
2293ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu      reinterpret_cast<const NDUserOptionHeader *>(
2307fab89734d88724a288e96a9996b15548c5294c7Ben Chan          reinterpret_cast<const uint8_t *>(&hdr->nd_user_opt) +
2313ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu          sizeof(struct nduseroptmsg));
2327fab89734d88724a288e96a9996b15548c5294c7Ben Chan  uint32_t lifetime = ntohl(nd_user_option_header->lifetime);
2333ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
2343ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  // Verify option length.
2353ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  // The length field in the header is in units of 8 octets.
2363ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  int opt_len = static_cast<int>(nd_user_option_header->length) * 8;
2373ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  if (opt_len != hdr->nd_user_opt.nduseropt_opts_len) {
2383ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    return false;
2393ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  }
2403ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
2413ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  // Determine option data pointer and data length.
2427fab89734d88724a288e96a9996b15548c5294c7Ben Chan  const uint8_t *option_data =
2437fab89734d88724a288e96a9996b15548c5294c7Ben Chan      reinterpret_cast<const uint8_t *>(nd_user_option_header + 1);
2443ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  int data_len = opt_len - sizeof(NDUserOptionHeader);
2453ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
2463ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  if (nd_user_option_header->type == ND_OPT_DNSSL) {
2473ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    // TODO(zqiu): Parse DNSSL (DNS Search List) option.
2483ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    type_ = kTypeDnssl;
2493ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    return true;
2503ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  } else if (nd_user_option_header->type == ND_OPT_RDNSS) {
2513ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    // Parse RNDSS (Recursive DNS Server) option.
2523ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    type_ = kTypeRdnss;
2533ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    return ParseRdnssOption(option_data, data_len, lifetime);
2543ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  }
2553ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
2563ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  return false;
2573ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu}
2583ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
2597fab89734d88724a288e96a9996b15548c5294c7Ben Chanbool RTNLMessage::ParseRdnssOption(const uint8_t *data,
2603ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu                                   int length,
2617fab89734d88724a288e96a9996b15548c5294c7Ben Chan                                   uint32_t lifetime) {
2623ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  const int addr_length = IPAddress::GetAddressLength(IPAddress::kFamilyIPv6);
2633ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
2643ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  // Verify data size are multiple of individual address size.
2653ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  if (length % addr_length != 0) {
2663ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    return false;
2673ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  }
2683ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
2693ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  // Parse the DNS server addresses.
2703ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  std::vector<IPAddress> dns_server_addresses;
2713ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  while (length > 0) {
2723ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    dns_server_addresses.push_back(
2733ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu        IPAddress(IPAddress::kFamilyIPv6,
2743ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu                  ByteString(data, addr_length)));
2753ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    length -= addr_length;
2763ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu    data += addr_length;
2773ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  }
2783ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  set_rdnss_option(RdnssOption(lifetime, dns_server_addresses));
2793ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu  return true;
2803ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu}
2813ef4f53096a10056a26ea38ad85b8a9a12845a9dPeter Qiu
282f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul StewartByteString RTNLMessage::Encode() const {
2839a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart  if (type_ != kTypeLink &&
2849a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart      type_ != kTypeAddress &&
2859a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart      type_ != kTypeRoute) {
286dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    return ByteString();
287dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
288dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
289dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  RTNLHeader hdr;
290dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr.hdr.nlmsg_flags = flags_;
291dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr.hdr.nlmsg_seq = seq_;
292dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr.hdr.nlmsg_pid = pid_;
293dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
2949a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart  if (mode_ == kModeGet) {
2959a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart    if (type_ == kTypeLink) {
296dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      hdr.hdr.nlmsg_type = RTM_GETLINK;
2979a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart    } else if (type_ == kTypeAddress) {
298dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      hdr.hdr.nlmsg_type = RTM_GETADDR;
2999a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart    } else if (type_ == kTypeRoute) {
300dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      hdr.hdr.nlmsg_type = RTM_GETROUTE;
301f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    } else {
302f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      NOTIMPLEMENTED();
303f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      return ByteString();
304dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    }
305dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    hdr.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr.gen));
3069a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart    hdr.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
307dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    hdr.gen.rtgen_family = family_;
308dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  } else {
309dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    switch (type_) {
3109a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart    case kTypeLink:
311f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      if (!EncodeLink(&hdr)) {
312f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart        return ByteString();
313f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      }
314dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      break;
315dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
3169a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart    case kTypeAddress:
317f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      if (!EncodeAddress(&hdr)) {
318f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart        return ByteString();
319f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      }
320dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      break;
321dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
3229a908080fc2a72dbf06f995b878fc8a3693b725aPaul Stewart    case kTypeRoute:
323f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      if (!EncodeRoute(&hdr)) {
324f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart        return ByteString();
325f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      }
326dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      break;
327dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
328dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    default:
329dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart      NOTREACHED();
330dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    }
331dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
332dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
333dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  size_t header_length = hdr.hdr.nlmsg_len;
334dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  ByteString attributes;
335dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
3368a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko  for (auto attr = attributes_.begin(); attr != attributes_.end(); ++attr) {
337dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    size_t len = RTA_LENGTH(attr->second.GetLength());
338dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    hdr.hdr.nlmsg_len = NLMSG_ALIGN(hdr.hdr.nlmsg_len) + RTA_ALIGN(len);
339dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
3408a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko    struct rtattr rt_attr = {
3418a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko      static_cast<unsigned short>(len),  // NOLINT(runtime/int)
3428a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko      attr->first
3438a5322984f2d81bcbfd8d44c59747a11bd9b904bAlex Vakulenko    };
344dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    ByteString attr_header(reinterpret_cast<unsigned char *>(&rt_attr),
345dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart                           sizeof(rt_attr));
346dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    attr_header.Resize(RTA_ALIGN(attr_header.GetLength()));
347dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    attributes.Append(attr_header);
348dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
349dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    ByteString attr_data(attr->second);
350dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    attr_data.Resize(RTA_ALIGN(attr_data.GetLength()));
351dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart    attributes.Append(attr_data);
352dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  }
353dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
354dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  ByteString packet(reinterpret_cast<unsigned char *>(&hdr), header_length);
355dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  packet.Append(attributes);
356dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
357dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  return packet;
358dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}
359dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
360f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartbool RTNLMessage::EncodeLink(RTNLHeader *hdr) const {
361f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  switch (mode_) {
362f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    case kModeAdd:
363f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      hdr->hdr.nlmsg_type = RTM_NEWLINK;
364f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      break;
365f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    case kModeDelete:
366f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      hdr->hdr.nlmsg_type = RTM_DELLINK;
367f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      break;
368f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    case kModeQuery:
369f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      hdr->hdr.nlmsg_type = RTM_GETLINK;
370f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      break;
371f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    default:
372f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      NOTIMPLEMENTED();
373f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      return false;
374f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  }
375dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifi));
376dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->ifi.ifi_family = family_;
377cba0f7f604b28b1fe85a16b16b0731860dfff753Paul Stewart  hdr->ifi.ifi_index = interface_index_;
378dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->ifi.ifi_type = link_status_.type;
379dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->ifi.ifi_flags = link_status_.flags;
380dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->ifi.ifi_change = link_status_.change;
381f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  return true;
382dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}
383dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
384f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartbool RTNLMessage::EncodeAddress(RTNLHeader *hdr) const {
385f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  switch (mode_) {
386f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    case kModeAdd:
387f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      hdr->hdr.nlmsg_type = RTM_NEWADDR;
388f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      break;
389f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    case kModeDelete:
390f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      hdr->hdr.nlmsg_type = RTM_DELADDR;
391f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      break;
392f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    case kModeQuery:
393f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      hdr->hdr.nlmsg_type = RTM_GETADDR;
394f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      break;
395f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    default:
396f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      NOTIMPLEMENTED();
397f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      return false;
398f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  }
399dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifa));
400dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->ifa.ifa_family = family_;
401dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->ifa.ifa_prefixlen = address_status_.prefix_len;
402dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->ifa.ifa_flags = address_status_.flags;
403dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->ifa.ifa_scope = address_status_.scope;
404dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->ifa.ifa_index = interface_index_;
405f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  return true;
406dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}
407dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
408f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartbool RTNLMessage::EncodeRoute(RTNLHeader *hdr) const {
409f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  switch (mode_) {
410f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    case kModeAdd:
411f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      hdr->hdr.nlmsg_type = RTM_NEWROUTE;
412f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      break;
413f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    case kModeDelete:
414f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      hdr->hdr.nlmsg_type = RTM_DELROUTE;
415f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      break;
416f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    case kModeQuery:
417f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      hdr->hdr.nlmsg_type = RTM_GETROUTE;
418f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      break;
419f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart    default:
420f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      NOTIMPLEMENTED();
421f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart      return false;
422f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  }
423dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->rtm));
424dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->rtm.rtm_family = family_;
425dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->rtm.rtm_dst_len = route_status_.dst_prefix;
426dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->rtm.rtm_src_len = route_status_.src_prefix;
427dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->rtm.rtm_table = route_status_.table;
428dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->rtm.rtm_protocol = route_status_.protocol;
429dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->rtm.rtm_scope = route_status_.scope;
430dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->rtm.rtm_type = route_status_.type;
431dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart  hdr->rtm.rtm_flags = route_status_.flags;
432f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  return true;
433f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart}
434f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart
435f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewartvoid RTNLMessage::Reset() {
436f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  mode_ = kModeUnknown;
437f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  type_ = kTypeUnknown;
438f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  flags_ = 0;
439f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  seq_ = 0;
440e636c6945299da860b360c4ed83c318e3ec41edeDarin Petkov  pid_ = 0;
441f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  interface_index_ = 0;
442f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  family_ = IPAddress::kFamilyUnknown;
443f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  link_status_ = LinkStatus();
444f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  address_status_ = AddressStatus();
445f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  route_status_ = RouteStatus();
446f748a36f2cde2b1ac7fc543cc710c81cb431cc2fPaul Stewart  attributes_.clear();
447dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}
448dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart
449dd7df792d2401741183a954f3f6e97d4c6de1e22Paul Stewart}  // namespace shill
450