Home | History | Annotate | Download | only in net
      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 {
     31   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 
     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 
     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 
     69 bool RTNLMessage::Decode(const ByteString& msg) {
     70   bool ret = DecodeInternal(msg);
     71   if (!ret) {
     72     Reset();
     73   }
     74   return ret;
     75 }
     76 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    326 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 
    413 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 
    437 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 
    461 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 
    488 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 
    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