Virtual WIFI, stage 2: netlink commands and mac80211_hwsim header

NOTE: Some headers are not included in this CL. I've done this to split
a larger code review into smaller chunks.

Makefiles not included, either.

Change-Id: I976699e916db221cfee6545921888454bb975f9e
diff --git a/common/libs/wifi/cmd.cc b/common/libs/wifi/cmd.cc
new file mode 100644
index 0000000..762e7fb
--- /dev/null
+++ b/common/libs/wifi/cmd.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "host/commands/wifid/cmd.h"
+
+namespace avd {
+
+Cmd::Cmd() : msg_(nlmsg_alloc()) {}
+
+Cmd::~Cmd() {
+  for (auto& msg : responses_) {
+    nlmsg_free(msg);
+  }
+  nlmsg_free(msg_);
+}
+
+bool Cmd::OnResponse(nl_msg* msg) {
+  // nlmsg_get increases refcount on msg, but does not return the msg
+  // so we can't exactly use it as an argument to unique_ptr.
+  nlmsg_get(msg);
+  responses_.emplace_back(msg);
+  auto hdr = nlmsg_hdr(msg);
+
+  // Kernel documentation seems to be a bit misleading on this topic saying:
+  //
+  //     In multipart messages (multiple nlmsghdr headers with associated
+  //     payload in one byte stream) the first and all following headers have
+  //     the NLM_F_MULTI flag set, except for the last header which has the type
+  //     NLMSG_DONE.
+  //
+  // In theory, that would make processing multi-part messages simple, but in
+  // practice this does not seem to be true. Specifying exit criteria solely on
+  // NLM_F_MULTI flag setting will block some, if not all calls that dump
+  // NL80211 wifi interfaces for example.
+  if (!(hdr->nlmsg_flags & NLM_F_MULTI) || (hdr->nlmsg_type == NLMSG_DONE) ||
+      (hdr->nlmsg_type == NLMSG_ERROR)) {
+    std::lock_guard<std::mutex> lock(ready_mutex_);
+    ready_signal_.notify_all();
+    return true;
+  }
+
+  return false;
+}
+
+const std::vector<nl_msg*> Cmd::Responses() const {
+  std::unique_lock<std::mutex> lock(ready_mutex_);
+  ready_signal_.wait(lock, [this]() { return responses_.size() > 0; });
+  return responses_;
+}
+
+}  // namespace avd
diff --git a/common/libs/wifi/cmd.h b/common/libs/wifi/cmd.h
new file mode 100644
index 0000000..c4bc57b
--- /dev/null
+++ b/common/libs/wifi/cmd.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <condition_variable>
+#include <memory>
+#include <thread>
+#include <vector>
+
+#include <netlink/msg.h>
+
+namespace avd {
+constexpr int kWifiSimVersion = 1;
+
+class Cmd {
+ public:
+  Cmd();
+  ~Cmd();
+
+  // Cmd() creates netlink request to be sent to kernel.
+  // Returns netlink message header structure.
+  nl_msg* Msg() const { return msg_; }
+
+  // Responses() holds execution until netlink responds to this message.
+  // Returns all netlink replies.
+  const std::vector<nl_msg*> Responses() const;
+
+  // OnResponse() handles data response from netlink.
+  // Returns value indicating 'done' state:
+  // - false, if more data is expected, or
+  // - true, if processing is complete and instance can be disposed of.
+  bool OnResponse(nl_msg* msg);
+
+ private:
+  nl_msg* msg_;
+  std::vector<nl_msg*> responses_;
+
+  mutable std::mutex ready_mutex_;
+  mutable std::condition_variable ready_signal_;
+
+  Cmd(const Cmd&) = delete;
+  Cmd& operator=(const Cmd&) = delete;
+};
+
+}  // namespace avd
diff --git a/common/libs/wifi/mac80211.h b/common/libs/wifi/mac80211.h
new file mode 100644
index 0000000..c879174
--- /dev/null
+++ b/common/libs/wifi/mac80211.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <stdint.h>
+
+// The following definitions are required by uapi/mac80211_hwsim.h header.
+#define s8 int8_t
+#define u8 uint8_t
+#define BIT(x) (1 << (x))
+#define __packed __attribute__((packed))
+
+#include <uapi/mac80211_hwsim.h>
+
+#undef __packed
+#undef BIT
+#undef u8
+#undef s8