1 // 2 // Copyright (C) 2013 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 #ifndef SHILL_NET_NETLINK_MESSAGE_MATCHERS_H_ 18 #define SHILL_NET_NETLINK_MESSAGE_MATCHERS_H_ 19 20 #include <base/logging.h> 21 #include <gmock/gmock.h> 22 23 #include "shill/net/netlink_message.h" 24 #include "shill/net/nl80211_message.h" 25 26 namespace shill { 27 28 // Given a netlink message, verifies that it is an Nl80211Message and verifies, 29 // further that it is the specified command. 30 MATCHER_P2(IsNl80211Command, nl80211_message_type, command, "") { 31 if (!arg) { 32 LOG(INFO) << "Null message"; 33 return false; 34 } 35 if (arg->message_type() != nl80211_message_type) { 36 LOG(INFO) << "Not an nl80211 message"; 37 return false; 38 } 39 const Nl80211Message* msg = static_cast<const Nl80211Message*>(arg); 40 if (msg->command() != command) { 41 LOG(INFO) << "Not a message of type " << command 42 << " (it's a " << +msg->command() << ")"; 43 return false; 44 } 45 return true; 46 } 47 48 // Given a netlink message, verifies that it is configured to disable 49 // wake on WiFi functionality of the NIC. 50 MATCHER(IsDisableWakeOnWiFiMsg, "") { 51 if (!arg) { 52 LOG(INFO) << "Null message"; 53 return false; 54 } 55 const Nl80211Message* msg = static_cast<const Nl80211Message*>(arg); 56 if (msg->command() != NL80211_CMD_SET_WOWLAN) { 57 LOG(INFO) << "Not a NL80211_CMD_SET_WOWLAN message"; 58 return false; 59 } 60 uint32_t wiphy; 61 if (!msg->const_attributes()->GetU32AttributeValue(NL80211_ATTR_WIPHY, 62 &wiphy)) { 63 LOG(INFO) << "Wiphy index not set"; 64 return false; 65 } 66 AttributeListConstRefPtr triggers; 67 if (msg->const_attributes()->ConstGetNestedAttributeList( 68 NL80211_ATTR_WOWLAN_TRIGGERS, &triggers)) { 69 LOG(INFO) << "Message contains NL80211_ATTR_WOWLAN_TRIGGERS"; 70 return false; 71 } 72 return true; 73 } 74 75 // Verifies that a NetlinkMessage is an NL80211_CMD_TRIGGER_SCAN message that 76 // contains exactly one SSID along with the requisite empty one. 77 MATCHER_P(HasHiddenSSID, nl80211_message_type, "") { 78 if (!arg) { 79 LOG(INFO) << "Null message"; 80 return false; 81 } 82 if (arg->message_type() != nl80211_message_type) { 83 LOG(INFO) << "Not an nl80211 message"; 84 return false; 85 } 86 const Nl80211Message* msg = reinterpret_cast<const Nl80211Message*>(arg); 87 if (msg->command() != NL80211_CMD_TRIGGER_SCAN) { 88 LOG(INFO) << "Not a NL80211_CMD_TRIGGER_SCAN message"; 89 return false; 90 } 91 AttributeListConstRefPtr ssids; 92 if (!msg->const_attributes()->ConstGetNestedAttributeList( 93 NL80211_ATTR_SCAN_SSIDS, &ssids)) { 94 LOG(INFO) << "No SSID list in message"; 95 return false; 96 } 97 ByteString ssid; 98 AttributeIdIterator ssid_iter(*ssids); 99 if (!ssids->GetRawAttributeValue(ssid_iter.GetId(), &ssid)) { 100 LOG(INFO) << "SSID list contains no (hidden) SSIDs"; 101 return false; 102 } 103 104 // A valid Scan containing a single hidden SSID should contain 105 // two SSID entries: one containing the SSID we are looking for, 106 // and an empty entry, signifying that we also want to do a 107 // broadcast probe request for all non-hidden APs as well. 108 ByteString empty_ssid; 109 if (ssid_iter.AtEnd()) { 110 LOG(INFO) << "SSID list doesn't contain an empty SSIDs (but should)"; 111 return false; 112 } 113 ssid_iter.Advance(); 114 if (!ssids->GetRawAttributeValue(ssid_iter.GetId(), &empty_ssid) || 115 !empty_ssid.IsEmpty()) { 116 LOG(INFO) << "SSID list doesn't contain an empty SSID (but should)"; 117 return false; 118 } 119 120 return true; 121 } 122 123 // Verifies that a NetlinkMessage is an NL80211_CMD_TRIGGER_SCAN message that 124 // contains no SSIDs. 125 MATCHER_P(HasNoHiddenSSID, nl80211_message_type, "") { 126 if (!arg) { 127 LOG(INFO) << "Null message"; 128 return false; 129 } 130 if (arg->message_type() != nl80211_message_type) { 131 LOG(INFO) << "Not an nl80211 message"; 132 return false; 133 } 134 const Nl80211Message* msg = reinterpret_cast<const Nl80211Message*>(arg); 135 if (msg->command() != NL80211_CMD_TRIGGER_SCAN) { 136 LOG(INFO) << "Not a NL80211_CMD_TRIGGER_SCAN message"; 137 return false; 138 } 139 AttributeListConstRefPtr ssids; 140 if (!msg->const_attributes()->ConstGetNestedAttributeList( 141 NL80211_ATTR_SCAN_SSIDS, &ssids)) { 142 return true; 143 } 144 AttributeIdIterator ssid_iter(*ssids); 145 if (ssid_iter.AtEnd()) { 146 return true; 147 } 148 149 LOG(INFO) << "SSID list contains at least one (hidden) SSID"; 150 return false; 151 } 152 153 } // namespace shill 154 155 #endif // SHILL_NET_NETLINK_MESSAGE_MATCHERS_H_ 156