blob: 3ab70057a51078370e0d5181f5a19d8f6bd9c77a [file] [log] [blame]
Ningyuan Wangbf215782015-12-04 09:55:39 -08001//
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>
Ningyuan Wangbf215782015-12-04 09:55:39 -080027
Ningyuan Wang63aa9b52016-01-19 10:24:59 -080028using shill::ByteString;
Ningyuan Wangbf215782015-12-04 09:55:39 -080029using shill::Sockets;
Ningyuan Wang88c688a2015-12-09 17:59:01 -080030using shill::RTNLHandler;
Ningyuan Wangbf215782015-12-04 09:55:39 -080031using std::unique_ptr;
32
33namespace {
34
35base::LazyInstance<dhcp_client::DeviceInfo> g_dhcp_device_info
36 = LAZY_INSTANCE_INITIALIZER;
37
38} // namespace
39
40namespace dhcp_client {
41
42DeviceInfo::DeviceInfo()
Ningyuan Wang88c688a2015-12-09 17:59:01 -080043 : sockets_(new Sockets()),
44 rtnl_handler_(RTNLHandler::GetInstance()) {
Ningyuan Wangbf215782015-12-04 09:55:39 -080045}
46
47DeviceInfo::~DeviceInfo() {}
48
49DeviceInfo* DeviceInfo::GetInstance() {
50 return g_dhcp_device_info.Pointer();
51}
52
53bool DeviceInfo::GetDeviceInfo(const std::string& interface_name,
Ningyuan Wang63aa9b52016-01-19 10:24:59 -080054 ByteString* mac_address,
Ningyuan Wangbf215782015-12-04 09:55:39 -080055 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 }
Ningyuan Wang88c688a2015-12-09 17:59:01 -080076 int if_index = rtnl_handler_->GetInterfaceIndex(interface_name);
Ningyuan Wangbf215782015-12-04 09:55:39 -080077 if (if_index == -1) {
78 LOG(ERROR) << "Unable to get interface index.";
79 return false;
80 }
81 *interface_index = if_index;
Ningyuan Wang63aa9b52016-01-19 10:24:59 -080082 *mac_address = ByteString(ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
Ningyuan Wangbf215782015-12-04 09:55:39 -080083
84 return true;
85}
86
87} // namespace dhcp_client
88