Home | History | Annotate | Download | only in dhcp_client
      1 //
      2 // Copyright (C) 2015 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 "dhcp_client/device_info.h"
     18 
     19 #include <net/if.h>
     20 #include <netinet/in.h>
     21 #include <sys/ioctl.h>
     22 
     23 #include <memory>
     24 #include <string>
     25 
     26 #include <base/logging.h>
     27 
     28 using shill::ByteString;
     29 using shill::Sockets;
     30 using shill::RTNLHandler;
     31 using std::unique_ptr;
     32 
     33 namespace {
     34 
     35 base::LazyInstance<dhcp_client::DeviceInfo> g_dhcp_device_info
     36     = LAZY_INSTANCE_INITIALIZER;
     37 
     38 }  // namespace
     39 
     40 namespace dhcp_client {
     41 
     42 DeviceInfo::DeviceInfo()
     43     : sockets_(new Sockets()),
     44       rtnl_handler_(RTNLHandler::GetInstance()) {
     45 }
     46 
     47 DeviceInfo::~DeviceInfo() {}
     48 
     49 DeviceInfo* DeviceInfo::GetInstance() {
     50   return g_dhcp_device_info.Pointer();
     51 }
     52 
     53 bool DeviceInfo::GetDeviceInfo(const std::string& interface_name,
     54                                ByteString* mac_address,
     55                                unsigned int* interface_index ) {
     56   struct ifreq ifr;
     57   size_t if_name_len = interface_name.size();
     58   if (if_name_len > IFNAMSIZ) {
     59     LOG(ERROR) << "Interface name is too long.";
     60     return false;
     61   }
     62   memcpy(ifr.ifr_name, interface_name.c_str(), if_name_len);
     63   ifr.ifr_name[if_name_len] = 0;
     64   int fd = sockets_->Socket(AF_INET, SOCK_DGRAM, 0);
     65   if (fd == -1) {
     66     PLOG(ERROR) << "Failed to create socket.";
     67     return false;
     68   }
     69 
     70   shill::ScopedSocketCloser socket_closer(sockets_.get(), fd);
     71   // Get interface hardware address
     72   if (sockets_->Ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
     73     PLOG(ERROR) << "Failed to get interface hardware address.";
     74     return false;
     75   }
     76   int if_index = rtnl_handler_->GetInterfaceIndex(interface_name);
     77   if (if_index == -1) {
     78     LOG(ERROR) << "Unable to get interface index.";
     79     return false;
     80   }
     81   *interface_index = if_index;
     82   *mac_address = ByteString(ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
     83 
     84   return true;
     85 }
     86 
     87 }  // namespace dhcp_client
     88 
     89