asus_hosts: reimplement for taxonomy as asustax.

ASUS Discovery Protocol can identify the device model for a variety
of ASUS devices. We haven't made good use of this so far. Revamp it
to log its responses for taxonomy of wired clients.

Change-Id: I5f98871e20e6b5e8a60c0528d179f727f87d56e0
diff --git a/cmds/Makefile b/cmds/Makefile
index ab3cb0b..134ca85 100644
--- a/cmds/Makefile
+++ b/cmds/Makefile
@@ -19,7 +19,6 @@
 TARGETS=\
 	$(PORTABLE_TARGETS) \
 	alivemonitor \
-	asus_hosts \
 	bsa2bluez \
 	burnin-flash \
 	buttonmon \
@@ -50,13 +49,17 @@
 LIB_TARGETS=\
 	stdoutline.so
 HOST_TEST_TARGETS=\
-	host-asus_hosts_test \
 	host-netusage_test \
 	host-utils_test
 SCRIPT_TARGETS=\
 	is-secure-boot
 ARCH_TARGETS=\
 
+ifeq ($(BUILD_ASUS),y)
+TARGETS += asustax
+HOST_TEST_TARGETS += host-asustax_test
+endif
+
 ifeq ($(BUILD_SSDP),y)
 TARGETS += ssdptax
 HOST_TEST_TARGETS += host-test-ssdptax.sh
@@ -192,6 +195,12 @@
 http_bouncer: LIBS+=-lcurl $(RT)
 http_bouncer: http_bouncer.o
 host-utils_test: host-utils_test.o host-utils.o
+asustax: asustax.o l2utils.o
+asustax: LIBS += -lnl-3 -lstdc++ -lm
+host-asustax: host-asustax.o host-l2utils.o
+host-asustax: LIBS += $(HOST_LIBS) -lnl-3 -lstdc++ -lm
+host-asustax_test: host-asustax_test.o
+host-asustax_test: LIBS += $(HOST_LIBS) -lstdc++ -lm
 ssdptax: ssdptax.o l2utils.o
 ssdptax: LIBS += -lcurl -lnl-3 -lstdc++ -lm
 host-ssdptax: host-ssdptax.o host-l2utils.o
diff --git a/cmds/asus_hosts.c b/cmds/asustax.cc
similarity index 88%
rename from cmds/asus_hosts.c
rename to cmds/asustax.cc
index 96ba81f..edbcd4f 100644
--- a/cmds/asus_hosts.c
+++ b/cmds/asustax.cc
@@ -24,6 +24,8 @@
 #include <sys/socket.h>
 #include <unistd.h>
 
+#include "l2utils.h"
+
 #define ASUS_DISCOVERY_PORT 9999
 #define PACKET_LENGTH       512
 
@@ -129,11 +131,17 @@
   return dst;
 }
 
-int receive_response(int s, char *response, int responselen)
+int receive_response(int s, L2Map *l2map, char *response, int responselen)
 {
   struct timeval tv;
   fd_set rfds;
 
+  if (l2map == NULL || response == NULL) {
+    fprintf(stderr, "%s: l2map=%p response=%p\n", __FUNCTION__,
+        l2map, response);
+    exit(1);
+  }
+
   memset(&tv, 0, sizeof(tv));
   tv.tv_sec = 1;
   tv.tv_usec = 0;
@@ -146,7 +154,8 @@
   }
   if (FD_ISSET(s, &rfds)) {
     uint8_t buf[PACKET_LENGTH + 64];
-    char addrbuf[16], namebuf[80];
+    char addrbuf[INET_ADDRSTRLEN], namebuf[80];
+    const char *mac;
     struct sockaddr_in from;
     socklen_t fromlen = sizeof(from);
     asus_discovery_packet_t *discovery = (asus_discovery_packet_t *)buf;
@@ -174,7 +183,13 @@
     id_len = strnlen((char *)discovery->product_id,
                      sizeof(discovery->product_id));
     replace_newlines(discovery->product_id, id_len, namebuf, sizeof(namebuf));
-    snprintf(response, responselen, "%s|%s", addrbuf, namebuf);
+    L2Map::iterator ii = l2map->find(std::string(addrbuf));
+    if (ii != l2map->end()) {
+      mac = ii->second.c_str();
+    } else {
+      mac = "00:00:00:00:00:00";
+    }
+    snprintf(response, responselen, "asus %s %s", mac, namebuf);
 
     return 0;
   } else {
@@ -193,7 +208,7 @@
 int main(int argc, char **argv)
 {
   int s, opt, i;
-  char *ifname = "br0";
+  const char *ifname = "br0";
 
   while ((opt = getopt(argc, argv, "i:")) != -1) {
     switch (opt) {
@@ -213,7 +228,9 @@
   send_discovery(s);
   for (i = 0; i < 128; i++) {
     char response[128];
-    int rc = receive_response(s, response, sizeof(response));
+    L2Map l2map;
+    get_l2_map(&l2map);
+    int rc = receive_response(s, &l2map, response, sizeof(response));
     if (rc < 0) {
       break;
     } else if (rc == 0) {
diff --git a/cmds/asus_hosts_test.c b/cmds/asustax_test.cc
similarity index 96%
rename from cmds/asus_hosts_test.c
rename to cmds/asustax_test.cc
index 2fe98a7..eab37bf 100644
--- a/cmds/asus_hosts_test.c
+++ b/cmds/asustax_test.cc
@@ -18,7 +18,7 @@
 #include <sys/socket.h>
 
 #define UNIT_TESTS
-#include "asus_hosts.c"
+#include "asustax.cc"
 
 /* Taken from a packet capture from an ASUS RT-68U */
 static const unsigned char asus_pkt_normal[] = {
@@ -233,8 +233,9 @@
 {
   int sv[2];
   char response[256];
-  char *expected;
+  const char *expected;
   ssize_t len;
+  L2Map l2map;
 
   if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv)) {
     perror("socketpair");
@@ -249,7 +250,7 @@
   }
 
   response[0] = '\0';
-  if (receive_response(sv[1], response, sizeof(response)) != 0) {
+  if (receive_response(sv[1], &l2map, response, sizeof(response)) != 0) {
     fprintf(stderr, "receive_response could not parse packet\n");
     exit(1);
   }
@@ -268,7 +269,7 @@
   }
 
   response[0] = '\0';
-  if (receive_response(sv[1], response, sizeof(response)) == 0) {
+  if (receive_response(sv[1], &l2map, response, sizeof(response)) == 0) {
     fprintf(stderr, "receive_response should not parse packet\n");
     exit(1);
   }
@@ -286,7 +287,7 @@
   }
 
   response[0] = '\0';
-  if (receive_response(sv[1], response, sizeof(response)) == 0) {
+  if (receive_response(sv[1], &l2map, response, sizeof(response)) == 0) {
     fprintf(stderr, "receive_response should not parse packet\n");
     exit(1);
   }
@@ -304,7 +305,7 @@
   }
 
   response[0] = '\0';
-  if (receive_response(sv[1], response, sizeof(response)) != 0) {
+  if (receive_response(sv[1], &l2map, response, sizeof(response)) != 0) {
     fprintf(stderr, "receive_response could not parse packet\n");
     exit(1);
   }
@@ -315,6 +316,5 @@
     exit(1);
   }
 
-
   exit(0);
 }