Home | History | Annotate | Download | only in net
      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