shill: Hide netlink sequence numbers and headers from users

Hide details of the netlink protocol from creators of nl80211 messages
to simplify the process of sending messages to the kernel.  This changes
the process to send a message and set a callback from:

KernelBoundNlMessage message;
// ... populate message with fields
message.AddNetlinkHeader(&socket_, 0, NL_AUTO_SEQ, 0, 0, 0,
                         CTRL_CMD_GETFAMILY, 0));
Config80211::GetInstance()->SendMessage(&message, callback);

to:

KernelBoundNlMessage message(CTRL_CMD_GETFAMILY);
// ... populate message with fields
Config80211::GetInstance()->SendMessage(&message, callback);

BUG=chromium-os:36122
TEST=Unit tests

Change-Id: Id0bc931b6952fc0eafdf73499c1b48d550575fce
Reviewed-on: https://gerrit.chromium.org/gerrit/37724
Reviewed-by: Wade Guthrie <wdg@chromium.org>
Commit-Ready: Christopher Wiley <wiley@chromium.org>
Tested-by: Christopher Wiley <wiley@chromium.org>
diff --git a/netlink_socket.cc b/netlink_socket.cc
index 6b08920..87b200e 100644
--- a/netlink_socket.cc
+++ b/netlink_socket.cc
@@ -38,9 +38,7 @@
 
 #include <iomanip>
 
-#include <base/logging.h>
-
-#include "shill/scope_logger.h"
+#include "shill/logging.h"
 
 namespace shill {
 
@@ -113,23 +111,46 @@
   return true;
 }
 
-bool NetlinkSocket::Send(struct nl_msg *message) {
+uint32 NetlinkSocket::Send(struct nl_msg *message,
+                           uint8 command,
+                           int32 family_id) {
   if (!message) {
     LOG(ERROR) << "NULL |message|.";
-    return false;
+    return 0;
   }
 
   if (!nl_sock_) {
     LOG(ERROR) << "Need to initialize the socket first.";
-    return false;
+    return 0;
   }
 
+  // Parameters to genlmsg_put:
+  //  @message: a pointer to a struct nl_msg *message.
+  //  @pid: netlink pid the message is addressed to.
+  //  @seq: sequence number.
+  //  @family: netlink socket family (NETLINK_GENERIC for us)
+  //  @flags netlink message flags.
+  //  @hdrlen: Length of a user header (which we don't use)
+  //  @cmd: netlink command.
+  //  @version: version of communication protocol.
+  // genlmsg_put returns a void * pointing to the user header but we don't
+  // want to encourage its use outside of this object.
+
+  uint32 sequence_number = GetSequenceNumber();
+  if (genlmsg_put(message, NL_AUTO_PID, sequence_number, family_id,
+                  0, 0, command, 0) == NULL) {
+    LOG(ERROR) << "genlmsg_put returned a NULL pointer.";
+    return 0;
+  }
+
+  SLOG(WiFi, 6) << "NL Message " << sequence_number << " ===>";
+
   int result = nl_send_auto_complete(nl_sock_, message);
   if (result < 0) {
     LOG(ERROR) << "Failed call to 'nl_send_auto_complete': " << result;
-    return false;
+    return 0;
   }
-  return true;
+  return sequence_number;
 }