• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "shill/net/rtnl_message.h"
18 
19 #include <linux/netlink.h>
20 #include <linux/rtnetlink.h>
21 #include <netinet/in.h>
22 #include <sys/socket.h>
23 
24 #include <base/logging.h>
25 
26 #include "shill/net/ndisc.h"
27 
28 namespace shill {
29 
30 struct RTNLHeader {
RTNLHeadershill::RTNLHeader31   RTNLHeader() {
32     memset(this, 0, sizeof(*this));
33   }
34   struct nlmsghdr hdr;
35   union {
36     struct ifinfomsg ifi;
37     struct ifaddrmsg ifa;
38     struct rtmsg rtm;
39     struct rtgenmsg gen;
40     struct nduseroptmsg nd_user_opt;
41     struct ndmsg ndm;
42   };
43 };
44 
RTNLMessage()45 RTNLMessage::RTNLMessage()
46     : type_(kTypeUnknown),
47       mode_(kModeUnknown),
48       flags_(0),
49       seq_(0),
50       pid_(0),
51       interface_index_(0),
52       family_(IPAddress::kFamilyUnknown) {}
53 
RTNLMessage(Type type,Mode mode,unsigned int flags,uint32_t seq,uint32_t pid,int interface_index,IPAddress::Family family)54 RTNLMessage::RTNLMessage(Type type,
55                          Mode mode,
56                          unsigned int flags,
57                          uint32_t seq,
58                          uint32_t pid,
59                          int interface_index,
60                          IPAddress::Family family)
61     : type_(type),
62       mode_(mode),
63       flags_(flags),
64       seq_(seq),
65       pid_(pid),
66       interface_index_(interface_index),
67       family_(family) {}
68 
Decode(const ByteString & msg)69 bool RTNLMessage::Decode(const ByteString& msg) {
70   bool ret = DecodeInternal(msg);
71   if (!ret) {
72     Reset();
73   }
74   return ret;
75 }
76 
DecodeInternal(const ByteString & msg)77 bool RTNLMessage::DecodeInternal(const ByteString& msg) {
78   const RTNLHeader* hdr =
79       reinterpret_cast<const RTNLHeader*>(msg.GetConstData());
80 
81   if (msg.GetLength() < sizeof(hdr->hdr) ||
82       msg.GetLength() < hdr->hdr.nlmsg_len)
83     return false;
84 
85   Mode mode = kModeUnknown;
86   switch (hdr->hdr.nlmsg_type) {
87   case RTM_NEWLINK:
88   case RTM_NEWADDR:
89   case RTM_NEWROUTE:
90   case RTM_NEWNDUSEROPT:
91   case RTM_NEWNEIGH:
92     mode = kModeAdd;
93     break;
94 
95   case RTM_DELLINK:
96   case RTM_DELADDR:
97   case RTM_DELROUTE:
98   case RTM_DELNEIGH:
99     mode = kModeDelete;
100     break;
101 
102   default:
103     return false;
104   }
105 
106   rtattr* attr_data = nullptr;
107   int attr_length = 0;
108 
109   switch (hdr->hdr.nlmsg_type) {
110   case RTM_NEWLINK:
111   case RTM_DELLINK:
112     if (!DecodeLink(hdr, mode, &attr_data, &attr_length))
113       return false;
114     break;
115 
116   case RTM_NEWADDR:
117   case RTM_DELADDR:
118     if (!DecodeAddress(hdr, mode, &attr_data, &attr_length))
119       return false;
120     break;
121 
122   case RTM_NEWROUTE:
123   case RTM_DELROUTE:
124     if (!DecodeRoute(hdr, mode, &attr_data, &attr_length))
125       return false;
126     break;
127 
128   case RTM_NEWNDUSEROPT:
129     if (!DecodeNdUserOption(hdr, mode, &attr_data, &attr_length))
130       return false;
131     break;
132 
133   case RTM_NEWNEIGH:
134   case RTM_DELNEIGH:
135     if (!DecodeNeighbor(hdr, mode, &attr_data, &attr_length))
136       return false;
137     break;
138 
139   default:
140     NOTREACHED();
141   }
142 
143   flags_ = hdr->hdr.nlmsg_flags;
144   seq_ = hdr->hdr.nlmsg_seq;
145   pid_ = hdr->hdr.nlmsg_pid;
146 
147   while (attr_data && RTA_OK(attr_data, attr_length)) {
148     SetAttribute(
149         attr_data->rta_type,
150         ByteString(reinterpret_cast<unsigned char*>(RTA_DATA(attr_data)),
151                    RTA_PAYLOAD(attr_data)));
152     attr_data = RTA_NEXT(attr_data, attr_length);
153   }
154 
155   if (attr_length) {
156     // We hit a parse error while going through the attributes
157     attributes_.clear();
158     return false;
159   }
160 
161   return true;
162 }
163 
DecodeLink(const RTNLHeader * hdr,Mode mode,rtattr ** attr_data,int * attr_length)164 bool RTNLMessage::DecodeLink(const RTNLHeader* hdr,
165                              Mode mode,
166                              rtattr** attr_data,
167                              int* attr_length) {
168   if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifi))) {
169     return false;
170   }
171 
172   mode_ = mode;
173   *attr_data = IFLA_RTA(NLMSG_DATA(&hdr->hdr));
174   *attr_length = IFLA_PAYLOAD(&hdr->hdr);
175 
176   type_ = kTypeLink;
177   family_ = hdr->ifi.ifi_family;
178   interface_index_ = hdr->ifi.ifi_index;
179   set_link_status(LinkStatus(hdr->ifi.ifi_type,
180                              hdr->ifi.ifi_flags,
181                              hdr->ifi.ifi_change));
182   return true;
183 }
184 
DecodeAddress(const RTNLHeader * hdr,Mode mode,rtattr ** attr_data,int * attr_length)185 bool RTNLMessage::DecodeAddress(const RTNLHeader* hdr,
186                                 Mode mode,
187                                 rtattr** attr_data,
188                                 int* attr_length) {
189   if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ifa))) {
190     return false;
191   }
192   mode_ = mode;
193   *attr_data = IFA_RTA(NLMSG_DATA(&hdr->hdr));
194   *attr_length = IFA_PAYLOAD(&hdr->hdr);
195 
196   type_ = kTypeAddress;
197   family_ = hdr->ifa.ifa_family;
198   interface_index_ = hdr->ifa.ifa_index;
199   set_address_status(AddressStatus(hdr->ifa.ifa_prefixlen,
200                                    hdr->ifa.ifa_flags,
201                                    hdr->ifa.ifa_scope));
202   return true;
203 }
204 
DecodeRoute(const RTNLHeader * hdr,Mode mode,rtattr ** attr_data,int * attr_length)205 bool RTNLMessage::DecodeRoute(const RTNLHeader* hdr,
206                               Mode mode,
207                               rtattr** attr_data,
208                               int* attr_length) {
209   if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->rtm))) {
210     return false;
211   }
212   mode_ = mode;
213   *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr));
214   *attr_length = RTM_PAYLOAD(&hdr->hdr);
215 
216   type_ = kTypeRoute;
217   family_ = hdr->rtm.rtm_family;
218   set_route_status(RouteStatus(hdr->rtm.rtm_dst_len,
219                                hdr->rtm.rtm_src_len,
220                                hdr->rtm.rtm_table,
221                                hdr->rtm.rtm_protocol,
222                                hdr->rtm.rtm_scope,
223                                hdr->rtm.rtm_type,
224                                hdr->rtm.rtm_flags));
225   return true;
226 }
227 
DecodeNdUserOption(const RTNLHeader * hdr,Mode mode,rtattr ** attr_data,int * attr_length)228 bool RTNLMessage::DecodeNdUserOption(const RTNLHeader* hdr,
229                                      Mode mode,
230                                      rtattr** attr_data,
231                                      int* attr_length) {
232   if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->nd_user_opt))) {
233     return false;
234   }
235 
236   mode_ = mode;
237   interface_index_ = hdr->nd_user_opt.nduseropt_ifindex;
238   family_ = hdr->nd_user_opt.nduseropt_family;
239 
240   // Verify IP family.
241   if (family_ != IPAddress::kFamilyIPv6) {
242     return false;
243   }
244   // Verify message must at-least contain the option header.
245   if (hdr->nd_user_opt.nduseropt_opts_len < sizeof(NDUserOptionHeader)) {
246     return false;
247   }
248 
249   // Parse the option header.
250   const NDUserOptionHeader* nd_user_option_header =
251       reinterpret_cast<const NDUserOptionHeader*>(
252           reinterpret_cast<const uint8_t*>(&hdr->nd_user_opt) +
253           sizeof(struct nduseroptmsg));
254   uint32_t lifetime = ntohl(nd_user_option_header->lifetime);
255 
256   // Verify option length.
257   // The length field in the header is in units of 8 octets.
258   int opt_len = static_cast<int>(nd_user_option_header->length) * 8;
259   if (opt_len != hdr->nd_user_opt.nduseropt_opts_len) {
260     return false;
261   }
262 
263   // Determine option data pointer and data length.
264   const uint8_t* option_data =
265       reinterpret_cast<const uint8_t*>(nd_user_option_header + 1);
266   int data_len = opt_len - sizeof(NDUserOptionHeader);
267 
268   if (nd_user_option_header->type == ND_OPT_DNSSL) {
269     // TODO(zqiu): Parse DNSSL (DNS Search List) option.
270     type_ = kTypeDnssl;
271     return true;
272   } else if (nd_user_option_header->type == ND_OPT_RDNSS) {
273     // Parse RNDSS (Recursive DNS Server) option.
274     type_ = kTypeRdnss;
275     return ParseRdnssOption(option_data, data_len, lifetime);
276   }
277 
278   return false;
279 }
280 
ParseRdnssOption(const uint8_t * data,int length,uint32_t lifetime)281 bool RTNLMessage::ParseRdnssOption(const uint8_t* data,
282                                    int length,
283                                    uint32_t lifetime) {
284   const int addr_length = IPAddress::GetAddressLength(IPAddress::kFamilyIPv6);
285 
286   // Verify data size are multiple of individual address size.
287   if (length % addr_length != 0) {
288     return false;
289   }
290 
291   // Parse the DNS server addresses.
292   std::vector<IPAddress> dns_server_addresses;
293   while (length > 0) {
294     dns_server_addresses.push_back(
295         IPAddress(IPAddress::kFamilyIPv6,
296                   ByteString(data, addr_length)));
297     length -= addr_length;
298     data += addr_length;
299   }
300   set_rdnss_option(RdnssOption(lifetime, dns_server_addresses));
301   return true;
302 }
303 
DecodeNeighbor(const RTNLHeader * hdr,Mode mode,rtattr ** attr_data,int * attr_length)304 bool RTNLMessage::DecodeNeighbor(const RTNLHeader* hdr,
305                                  Mode mode,
306                                  rtattr** attr_data,
307                                  int* attr_length) {
308   if (hdr->hdr.nlmsg_len < NLMSG_LENGTH(sizeof(hdr->ndm))) {
309     return false;
310   }
311 
312   mode_ = mode;
313   interface_index_ = hdr->ndm.ndm_ifindex;
314   family_ = hdr->ndm.ndm_family;
315   type_ = kTypeNeighbor;
316 
317   *attr_data = RTM_RTA(NLMSG_DATA(&hdr->hdr));
318   *attr_length = RTM_PAYLOAD(&hdr->hdr);
319 
320   set_neighbor_status(NeighborStatus(hdr->ndm.ndm_state,
321                                      hdr->ndm.ndm_flags,
322                                      hdr->ndm.ndm_type));
323   return true;
324 }
325 
Encode() const326 ByteString RTNLMessage::Encode() const {
327   if (type_ != kTypeLink &&
328       type_ != kTypeAddress &&
329       type_ != kTypeRoute &&
330       type_ != kTypeNeighbor) {
331     return ByteString();
332   }
333 
334   RTNLHeader hdr;
335   hdr.hdr.nlmsg_flags = flags_;
336   hdr.hdr.nlmsg_seq = seq_;
337   hdr.hdr.nlmsg_pid = pid_;
338 
339   if (mode_ == kModeGet) {
340     if (type_ == kTypeLink) {
341       hdr.hdr.nlmsg_type = RTM_GETLINK;
342     } else if (type_ == kTypeAddress) {
343       hdr.hdr.nlmsg_type = RTM_GETADDR;
344     } else if (type_ == kTypeRoute) {
345       hdr.hdr.nlmsg_type = RTM_GETROUTE;
346     } else if (type_ == kTypeNeighbor) {
347       hdr.hdr.nlmsg_type = RTM_GETNEIGH;
348     } else {
349       NOTIMPLEMENTED();
350       return ByteString();
351     }
352     hdr.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr.gen));
353     hdr.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
354     hdr.gen.rtgen_family = family_;
355   } else {
356     switch (type_) {
357     case kTypeLink:
358       if (!EncodeLink(&hdr)) {
359         return ByteString();
360       }
361       break;
362 
363     case kTypeAddress:
364       if (!EncodeAddress(&hdr)) {
365         return ByteString();
366       }
367       break;
368 
369     case kTypeRoute:
370       if (!EncodeRoute(&hdr)) {
371         return ByteString();
372       }
373       break;
374 
375     case kTypeNeighbor:
376       if (!EncodeNeighbor(&hdr)) {
377         return ByteString();
378       }
379       break;
380 
381     default:
382       NOTREACHED();
383     }
384   }
385 
386   size_t header_length = hdr.hdr.nlmsg_len;
387   ByteString attributes;
388 
389   for (auto attr = attributes_.begin(); attr != attributes_.end(); ++attr) {
390     size_t len = RTA_LENGTH(attr->second.GetLength());
391     hdr.hdr.nlmsg_len = NLMSG_ALIGN(hdr.hdr.nlmsg_len) + RTA_ALIGN(len);
392 
393     struct rtattr rt_attr = {
394       static_cast<unsigned short>(len),  // NOLINT(runtime/int)
395       attr->first
396     };
397     ByteString attr_header(reinterpret_cast<unsigned char*>(&rt_attr),
398                            sizeof(rt_attr));
399     attr_header.Resize(RTA_ALIGN(attr_header.GetLength()));
400     attributes.Append(attr_header);
401 
402     ByteString attr_data(attr->second);
403     attr_data.Resize(RTA_ALIGN(attr_data.GetLength()));
404     attributes.Append(attr_data);
405   }
406 
407   ByteString packet(reinterpret_cast<unsigned char*>(&hdr), header_length);
408   packet.Append(attributes);
409 
410   return packet;
411 }
412 
EncodeLink(RTNLHeader * hdr) const413 bool RTNLMessage::EncodeLink(RTNLHeader* hdr) const {
414   switch (mode_) {
415     case kModeAdd:
416       hdr->hdr.nlmsg_type = RTM_NEWLINK;
417       break;
418     case kModeDelete:
419       hdr->hdr.nlmsg_type = RTM_DELLINK;
420       break;
421     case kModeQuery:
422       hdr->hdr.nlmsg_type = RTM_GETLINK;
423       break;
424     default:
425       NOTIMPLEMENTED();
426       return false;
427   }
428   hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifi));
429   hdr->ifi.ifi_family = family_;
430   hdr->ifi.ifi_index = interface_index_;
431   hdr->ifi.ifi_type = link_status_.type;
432   hdr->ifi.ifi_flags = link_status_.flags;
433   hdr->ifi.ifi_change = link_status_.change;
434   return true;
435 }
436 
EncodeAddress(RTNLHeader * hdr) const437 bool RTNLMessage::EncodeAddress(RTNLHeader* hdr) const {
438   switch (mode_) {
439     case kModeAdd:
440       hdr->hdr.nlmsg_type = RTM_NEWADDR;
441       break;
442     case kModeDelete:
443       hdr->hdr.nlmsg_type = RTM_DELADDR;
444       break;
445     case kModeQuery:
446       hdr->hdr.nlmsg_type = RTM_GETADDR;
447       break;
448     default:
449       NOTIMPLEMENTED();
450       return false;
451   }
452   hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ifa));
453   hdr->ifa.ifa_family = family_;
454   hdr->ifa.ifa_prefixlen = address_status_.prefix_len;
455   hdr->ifa.ifa_flags = address_status_.flags;
456   hdr->ifa.ifa_scope = address_status_.scope;
457   hdr->ifa.ifa_index = interface_index_;
458   return true;
459 }
460 
EncodeRoute(RTNLHeader * hdr) const461 bool RTNLMessage::EncodeRoute(RTNLHeader* hdr) const {
462   switch (mode_) {
463     case kModeAdd:
464       hdr->hdr.nlmsg_type = RTM_NEWROUTE;
465       break;
466     case kModeDelete:
467       hdr->hdr.nlmsg_type = RTM_DELROUTE;
468       break;
469     case kModeQuery:
470       hdr->hdr.nlmsg_type = RTM_GETROUTE;
471       break;
472     default:
473       NOTIMPLEMENTED();
474       return false;
475   }
476   hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->rtm));
477   hdr->rtm.rtm_family = family_;
478   hdr->rtm.rtm_dst_len = route_status_.dst_prefix;
479   hdr->rtm.rtm_src_len = route_status_.src_prefix;
480   hdr->rtm.rtm_table = route_status_.table;
481   hdr->rtm.rtm_protocol = route_status_.protocol;
482   hdr->rtm.rtm_scope = route_status_.scope;
483   hdr->rtm.rtm_type = route_status_.type;
484   hdr->rtm.rtm_flags = route_status_.flags;
485   return true;
486 }
487 
EncodeNeighbor(RTNLHeader * hdr) const488 bool RTNLMessage::EncodeNeighbor(RTNLHeader* hdr) const {
489   switch (mode_) {
490     case kModeAdd:
491       hdr->hdr.nlmsg_type = RTM_NEWNEIGH;
492       break;
493     case kModeDelete:
494       hdr->hdr.nlmsg_type = RTM_DELNEIGH;
495       break;
496     case kModeQuery:
497       hdr->hdr.nlmsg_type = RTM_GETNEIGH;
498       break;
499     default:
500       NOTIMPLEMENTED();
501       return false;
502   }
503   hdr->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(hdr->ndm));
504   hdr->ndm.ndm_family = family_;
505   hdr->ndm.ndm_ifindex = interface_index_;
506   hdr->ndm.ndm_state = neighbor_status_.state;
507   hdr->ndm.ndm_flags = neighbor_status_.flags;
508   hdr->ndm.ndm_type = neighbor_status_.type;
509   return true;
510 }
511 
Reset()512 void RTNLMessage::Reset() {
513   mode_ = kModeUnknown;
514   type_ = kTypeUnknown;
515   flags_ = 0;
516   seq_ = 0;
517   pid_ = 0;
518   interface_index_ = 0;
519   family_ = IPAddress::kFamilyUnknown;
520   link_status_ = LinkStatus();
521   address_status_ = AddressStatus();
522   route_status_ = RouteStatus();
523   attributes_.clear();
524 }
525 
526 }  // namespace shill
527