blob: b838bf1d057349166251d0733e28b76c1d27522a [file] [log] [blame]
Wade Guthrie0d438532012-05-18 14:18:50 -07001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4//
5// This code is derived from the 'iw' source code. The copyright and license
6// of that code is as follows:
7//
8// Copyright (c) 2007, 2008 Johannes Berg
9// Copyright (c) 2007 Andy Lutomirski
10// Copyright (c) 2007 Mike Kershaw
11// Copyright (c) 2008-2009 Luis R. Rodriguez
12//
13// Permission to use, copy, modify, and/or distribute this software for any
14// purpose with or without fee is hereby granted, provided that the above
15// copyright notice and this permission notice appear in all copies.
16//
17// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
20// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
23// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25#include "shill/netlink_socket.h"
26
27#include <ctype.h>
28#include <errno.h>
Wade Guthrieb1ec8602012-10-18 17:26:14 -070029#include <string.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070030
31#include <net/if.h>
32#include <netlink/attr.h>
33#include <netlink/genl/ctrl.h>
34#include <netlink/genl/family.h>
35#include <netlink/genl/genl.h>
36#include <netlink/msg.h>
37#include <netlink/netlink.h>
38
39#include <iomanip>
repo syncdc085c82012-12-28 08:54:41 -080040#include <string>
41
42#include <base/eintr_wrapper.h>
43#include <base/logging.h>
44#include <base/stringprintf.h>
Wade Guthrie0d438532012-05-18 14:18:50 -070045
Christopher Wiley393b93f2012-11-08 17:30:58 -080046#include "shill/logging.h"
repo syncdc085c82012-12-28 08:54:41 -080047#include "shill/nl80211_message.h"
48
49using base::StringAppendF;
50using std::string;
Wade Guthrie0d438532012-05-18 14:18:50 -070051
52namespace shill {
53
Wade Guthrie0d438532012-05-18 14:18:50 -070054NetlinkSocket::~NetlinkSocket() {
55 if (nl_sock_) {
56 nl_socket_free(nl_sock_);
57 nl_sock_ = NULL;
58 }
59}
60
61bool NetlinkSocket::Init() {
62 nl_sock_ = nl_socket_alloc();
63 if (!nl_sock_) {
64 LOG(ERROR) << "Failed to allocate netlink socket.";
65 return false;
66 }
67
68 if (genl_connect(nl_sock_)) {
69 LOG(ERROR) << "Failed to connect to generic netlink.";
70 return false;
71 }
72
73 return true;
74}
75
repo syncdc085c82012-12-28 08:54:41 -080076bool NetlinkSocket::SendMessage(Nl80211Message *message) {
Wade Guthrie5d53d492012-11-07 09:53:31 -080077 if (!message) {
78 LOG(ERROR) << "NULL |message|.";
repo syncdc085c82012-12-28 08:54:41 -080079 return false;
Wade Guthrie5d53d492012-11-07 09:53:31 -080080 }
81
82 if (!nl_sock_) {
83 LOG(ERROR) << "Need to initialize the socket first.";
repo syncdc085c82012-12-28 08:54:41 -080084 return false;
Wade Guthrie5d53d492012-11-07 09:53:31 -080085 }
86
repo syncdc085c82012-12-28 08:54:41 -080087 ByteString out_msg = message->Encode(family_id());
Christopher Wiley393b93f2012-11-08 17:30:58 -080088
repo syncdc085c82012-12-28 08:54:41 -080089 if (SLOG_IS_ON(WiFi, 6)) {
90 SLOG(WiFi, 6) << "NL Message " << message->sequence_number() << " ===>";
91 SLOG(WiFi, 6) << " Sending (" << out_msg.GetLength() << " bytes) : "
92 << message->GenericToString();
93
94 const unsigned char *out_data = out_msg.GetConstData();
95 string output;
96 for (size_t i = 0; i < out_msg.GetLength(); ++i) {
97 StringAppendF(&output, " %02x", out_data[i]);
98 }
99 SLOG(WiFi, 6) << output;
Christopher Wiley393b93f2012-11-08 17:30:58 -0800100 }
101
repo syncdc085c82012-12-28 08:54:41 -0800102 int result = HANDLE_EINTR(send(GetFd(), out_msg.GetConstData(),
103 out_msg.GetLength(), 0));
104 if (!result) {
105 PLOG(ERROR) << "Send failed.";
106 return false;
Wade Guthrie5d53d492012-11-07 09:53:31 -0800107 }
repo syncdc085c82012-12-28 08:54:41 -0800108
109 return true;
Wade Guthrie5d53d492012-11-07 09:53:31 -0800110}
111
112
Wade Guthrie0d438532012-05-18 14:18:50 -0700113bool NetlinkSocket::DisableSequenceChecking() {
114 if (!nl_sock_) {
115 LOG(ERROR) << "NULL socket";
116 return false;
117 }
118
119 // NOTE: can't use nl_socket_disable_seq_check(); it's not in this version
120 // of the library.
121 int result = nl_socket_modify_cb(nl_sock_, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
122 NetlinkSocket::IgnoreSequenceCheck, NULL);
123 if (result) {
124 LOG(ERROR) << "Failed call to nl_socket_modify_cb: " << result;
125 return false;
126 }
127
128 return true;
129}
130
131int NetlinkSocket::GetFd() const {
132 if (!nl_sock_) {
133 LOG(ERROR) << "NULL socket";
134 return -1;
135 }
136 return nl_socket_get_fd(nl_sock_);
137}
138
Wade Guthrie5d3d6de2012-11-02 11:08:34 -0700139unsigned int NetlinkSocket::GetSequenceNumber() {
140 unsigned int number = nl_socket_use_seq(nl_sock_);
141 if (number == 0) {
142 number = nl_socket_use_seq(nl_sock_);
143 }
144 if (number == 0) {
145 LOG(WARNING) << "Couldn't get non-zero sequence number";
146 number = 1;
147 }
148 return number;
149}
150
Wade Guthrie0d438532012-05-18 14:18:50 -0700151int NetlinkSocket::IgnoreSequenceCheck(struct nl_msg *ignored_msg,
152 void *ignored_arg) {
153 return NL_OK; // Proceed.
154}
155
156} // namespace shill.