changeset 252:953786a62e00

add a patch to fix this xtoa mess
author Louis Opter <kalessin@kalessin.fr>
date Sat, 15 Aug 2015 23:22:19 -0700
parents 0d981a9b602e
children aecc19ba45d9
files fix_sockaddrtoa_mess.patch implement_some_metadata_packet_types.patch series
diffstat 3 files changed, 645 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fix_sockaddrtoa_mess.patch	Sat Aug 15 23:22:19 2015 -0700
@@ -0,0 +1,634 @@
+# HG changeset patch
+# Parent  44e0729fda3081537c2615a458b8d403867ca9b4
+
+diff --git a/core/lightsd.h b/core/lightsd.h
+--- a/core/lightsd.h
++++ b/core/lightsd.h
+@@ -74,14 +74,15 @@
+ extern struct lgtd_opts lgtd_opts;
+ extern struct event_base *lgtd_ev_base;
+ 
+-const char *lgtd_addrtoa(const uint8_t *);
++char *lgtd_iee8023mactoa(const uint8_t *addr, char *buf, int buflen);
++#define LGTD_IEEE8023MACTOA(addr, buf) \
++    lgtd_iee8023mactoa((addr), (buf), sizeof(buf))
+ void lgtd_sockaddrtoa(const struct sockaddr_storage *, char *buf, int buflen);
+ short lgtd_sockaddrport(const struct sockaddr_storage *);
+ 
+-void lgtd_print_duration(uint64_t, char *, int);
+-#define LGTD_PRINT_DURATION(secs, arr) do {             \
+-    lgtd_print_duration((secs), (arr), sizeof((arr)));  \
+-} while (0)
++char *lgtd_print_duration(uint64_t, char *, int);
++#define LGTD_PRINT_DURATION(secs, arr) \
++    lgtd_print_duration((secs), (arr), sizeof((arr)))
+ 
+ void _lgtd_err(void (*)(int, const char *, ...), int, const char *, ...)
+     __attribute__((format(printf, 3, 4)));
+diff --git a/core/log.c b/core/log.c
+--- a/core/log.c
++++ b/core/log.c
+@@ -74,17 +74,18 @@
+     fprintf(stderr, "[%s] %s", loglvl, showprogname ? "lightsd: " : "");
+ }
+ 
+-const char *
+-lgtd_addrtoa(const uint8_t *addr)
++char *
++lgtd_iee8023mactoa(const uint8_t *addr, char *buf, int buflen)
+ {
+     assert(addr);
++    assert(buf);
++    assert(buflen >= 2 * 6 + 5 + 1);
+ 
+-    static char str[LGTD_LIFX_ADDR_LENGTH * 2 + LGTD_LIFX_ADDR_LENGTH - 1 + 1];
+     snprintf(
+-        str, sizeof(str), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
++        buf, buflen, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+         addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
+     );
+-    return str;
++    return buf;
+ }
+ 
+ void
+@@ -113,7 +114,7 @@
+     }
+ }
+ 
+-void
++char *
+ lgtd_print_duration(uint64_t secs, char *buf, int bufsz)
+ {
+     assert(buf);
+@@ -131,6 +132,7 @@
+         i = LGTD_MIN(i + n, bufsz);
+     }
+     snprintf(&buf[i], bufsz - i, "%02d:%02d", hours, minutes);
++    return buf;
+ }
+ 
+ void
+diff --git a/core/proto.c b/core/proto.c
+--- a/core/proto.c
++++ b/core/proto.c
+@@ -201,9 +201,16 @@
+     SLIST_FOREACH(device, devices, link) {
+         struct lgtd_lifx_bulb *bulb = device->device;
+ 
+-        char buf[2048];
++        char buf[2048],
++             gw_addr[LGTD_LIFX_ADDR_STRLEN],
++             site_addr[LGTD_LIFX_ADDR_STRLEN],
++             bulb_addr[LGTD_LIFX_ADDR_STRLEN];
+         int i = 0;
+ 
++        LGTD_IEEE8023MACTOA(bulb->addr, bulb_addr);
++        LGTD_IEEE8023MACTOA(bulb->gw->addr, gw_addr);
++        LGTD_IEEE8023MACTOA(bulb->gw->site.as_array, site_addr);
++
+         LGTD_SNPRINTF_APPEND(
+             buf, i, (int)sizeof(buf),
+             "{"
+@@ -215,9 +222,7 @@
+                         "\"url\":\"tcp://[%s]:%hu\","
+                         "\"latency\":%ju"
+                     "},",
+-            lgtd_addrtoa(bulb->addr),
+-            lgtd_addrtoa(bulb->gw->addr),
+-            lgtd_addrtoa(bulb->gw->site.as_array),
++            bulb_addr, gw_addr, site_addr,
+             bulb->gw->ip_addr, bulb->gw->port,
+             (uintmax_t)LGTD_LIFX_GATEWAY_LATENCY(bulb->gw)
+         );
+@@ -299,15 +304,14 @@
+             "\"tags\":[",
+             h, s, b, bulb->state.kelvin,
+             bulb->state.power == LGTD_LIFX_POWER_ON ? "true" : "false",
+-            bulb->state.label[0] ? bulb->state.label : lgtd_addrtoa(bulb->addr)
++            bulb->state.label[0] ? bulb->state.label : bulb_addr
+         );
+ 
+         if (i >= (int)sizeof(buf)) {
+             lgtd_warnx(
+                 "can't send state of bulb %s (%s) to client "
+                 "[%s]:%hu: output buffer to small",
+-                bulb->state.label, lgtd_addrtoa(bulb->addr),
+-                client->ip_addr, client->port
++                bulb->state.label, bulb_addr, client->ip_addr, client->port
+             );
+             continue;
+         }
+@@ -326,8 +330,7 @@
+                     "tag_id %d on bulb %.*s (%s) doesn't "
+                     "exist on gw [%s]:%hu (site %s)",
+                     tag_id, (int)sizeof(bulb->state.label), bulb->state.label,
+-                    lgtd_addrtoa(bulb->addr), bulb->gw->ip_addr, bulb->gw->port,
+-                    lgtd_addrtoa(bulb->gw->site.as_array)
++                    bulb_addr, bulb->gw->ip_addr, bulb->gw->port, site_addr
+                 );
+             }
+         }
+diff --git a/core/router.c b/core/router.c
+--- a/core/router.c
++++ b/core/router.c
+@@ -106,7 +106,9 @@
+         bulb->expected_power_on = payload->power;
+     }
+ 
+-    lgtd_info("sending %s to %s", pkt_info->name, lgtd_addrtoa(bulb->addr));
++    char addr[LGTD_LIFX_ADDR_STRLEN];
++    LGTD_IEEE8023MACTOA(bulb->addr, addr);
++    lgtd_info("sending %s to %s", pkt_info->name, addr);
+ }
+ 
+ void
+diff --git a/lifx/bulb.c b/lifx/bulb.c
+--- a/lifx/bulb.c
++++ b/lifx/bulb.c
+@@ -153,11 +153,12 @@
+         LGTD_STATS_ADD_AND_UPDATE_PROCTITLE(bulbs_powered_on, -1);
+     }
+     RB_REMOVE(lgtd_lifx_bulb_map, &lgtd_lifx_bulbs_table, bulb);
++    char addr[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_info(
+         "closed bulb \"%.*s\" (%s) on [%s]:%hu",
+         LGTD_LIFX_LABEL_SIZE,
+         bulb->state.label,
+-        lgtd_addrtoa(bulb->addr),
++        LGTD_IEEE8023MACTOA(bulb->addr, addr),
+         bulb->gw->ip_addr,
+         bulb->gw->port
+     );
+diff --git a/lifx/gateway.c b/lifx/gateway.c
+--- a/lifx/gateway.c
++++ b/lifx/gateway.c
+@@ -79,9 +79,10 @@
+         lgtd_lifx_gateway_remove_and_close_bulb(gw, bulb);
+     }
+ 
++    char site[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_info(
+         "connection with gateway bulb [%s]:%hu (site %s) closed",
+-        gw->ip_addr, gw->port, lgtd_addrtoa(gw->site.as_array)
++        gw->ip_addr, gw->port, LGTD_IEEE8023MACTOA(gw->site.as_array, site)
+     );
+     free(gw);
+ }
+@@ -200,9 +201,10 @@
+         gw, pkt_type, pkt, &pkt_info
+     );
+ 
++    char site[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_debug(
+         "sending %s to site %s",
+-        pkt_info->name, lgtd_addrtoa(gw->site.as_array)
++        pkt_info->name, LGTD_IEEE8023MACTOA(gw->site.as_array, site)
+     );
+ 
+     return rv; // FIXME, have real return values on the send paths...
+@@ -218,9 +220,10 @@
+         gw, pkt_type, pkt, &pkt_info
+     );
+ 
++    char site[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_info(
+         "sending %s to site %s",
+-        pkt_info->name, lgtd_addrtoa(gw->site.as_array)
++        pkt_info->name, LGTD_IEEE8023MACTOA(gw->site.as_array, site)
+     );
+ 
+     return rv; // FIXME, have real return values on the send paths...
+@@ -269,9 +272,10 @@
+         bulb = lgtd_lifx_bulb_open(gw, bulb_addr);
+         if (bulb) {
+             SLIST_INSERT_HEAD(&gw->bulbs, bulb, link_by_gw);
++            char addr[LGTD_LIFX_ADDR_STRLEN];
+             lgtd_info(
+                 "bulb %s on [%s]:%hu",
+-                lgtd_addrtoa(bulb_addr), gw->ip_addr, gw->port
++                LGTD_IEEE8023MACTOA(bulb->addr, addr), gw->ip_addr, gw->port
+             );
+         }
+     }
+@@ -362,9 +366,11 @@
+         goto error_allocate;
+     }
+ 
++    char site_addr[LGTD_LIFX_ADDR_STRLEN], addr[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_info(
+-        "gateway for site %s at [%s]:%hu",
+-        lgtd_addrtoa(gw->site.as_array), gw->ip_addr, gw->port
++        "gateway for site %s at [%s]:%hu (%s)",
++        LGTD_IEEE8023MACTOA(gw->site.as_array, site_addr),
++        gw->ip_addr, gw->port, LGTD_IEEE8023MACTOA(gw->addr, addr)
+     );
+     LIST_INSERT_HEAD(&lgtd_lifx_gateways, gw, link);
+ 
+@@ -478,10 +484,12 @@
+     LGTD_LIFX_WIRE_FOREACH_TAG_ID(tag_id, removed_tags) {
+         assert(gw->tag_refcounts[tag_id] > 0);
+         if (--gw->tag_refcounts[tag_id] == 0) {
++            char site[LGTD_LIFX_ADDR_STRLEN];
+             lgtd_info(
+                 "deleting unused tag [%s] (%d) from gw [%s]:%hu (site %s)",
+-                gw->tags[tag_id] ? gw->tags[tag_id]->label : NULL, tag_id,
+-                gw->ip_addr, gw->port, lgtd_addrtoa(gw->site.as_array)
++                gw->tags[tag_id] ? gw->tags[tag_id]->label : NULL,
++                tag_id, gw->ip_addr, gw->port,
++                LGTD_IEEE8023MACTOA(gw->site.as_array, site)
+             );
+             struct lgtd_lifx_packet_tag_labels pkt = {
+                 .tags = ~(gw->tag_ids & ~LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id))
+@@ -499,10 +507,12 @@
+ {
+     assert(gw && hdr && pkt);
+ 
++    char addr[LGTD_LIFX_ADDR_STRLEN], site[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_debug(
+         "SET_PAN_GATEWAY <-- [%s]:%hu - %s site=%s, service_type=%d",
+-        gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr),
+-        lgtd_addrtoa(hdr->site), pkt->service_type
++        gw->ip_addr, gw->port,
++        LGTD_IEEE8023MACTOA(hdr->target.device_addr, addr),
++        LGTD_IEEE8023MACTOA(hdr->site, site), pkt->service_type
+     );
+ }
+ 
+@@ -513,11 +523,13 @@
+ {
+     assert(gw && hdr && pkt);
+ 
++    char addr[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_debug(
+         "SET_LIGHT_STATE <-- [%s]:%hu - %s "
+         "hue=%#hx, saturation=%#hx, brightness=%#hx, "
+         "kelvin=%d, dim=%#hx, power=%#hx, label=%.*s, tags=%#jx",
+-        gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr),
++        gw->ip_addr, gw->port,
++        LGTD_IEEE8023MACTOA(hdr->target.device_addr, addr),
+         pkt->hue, pkt->saturation, pkt->brightness, pkt->kelvin,
+         pkt->dim, pkt->power, LGTD_LIFX_LABEL_SIZE, pkt->label,
+         (uintmax_t)pkt->tags
+@@ -584,9 +596,11 @@
+ {
+     assert(gw && hdr && pkt);
+ 
++    char addr[LGTD_LIFX_ADDR_LENGTH];
+     lgtd_debug(
+         "SET_POWER_STATE <-- [%s]:%hu - %s power=%#hx",
+-        gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr), pkt->power
++        gw->ip_addr, gw->port,
++        LGTD_IEEE8023MACTOA(hdr->target.device_addr, addr), pkt->power
+     );
+ 
+     LGTD_LIFX_GATEWAY_SET_BULB_ATTR(
+@@ -621,13 +635,15 @@
+     assert(tag_id >= -1);
+     assert(tag_id < LGTD_LIFX_GATEWAY_MAX_TAGS);
+ 
++    char site[LGTD_LIFX_ADDR_STRLEN];
++    LGTD_IEEE8023MACTOA(gw->site.as_array, site);
++
+     if (tag_id == -1) {
+         tag_id = lgtd_lifx_wire_bitscan64_forward(~gw->tag_ids);
+         if (tag_id == -1) {
+             lgtd_warnx(
+                 "no tag_id left for new tag [%s] on gw [%s]:%hu (site %s)",
+-                tag_label, gw->ip_addr, gw->port,
+-                lgtd_addrtoa(gw->site.as_array)
++                tag_label, gw->ip_addr, gw->port, site
+             );
+             return -1;
+         }
+@@ -639,14 +655,13 @@
+         if (!tag) {
+             lgtd_warn(
+                 "couldn't allocate a new reference to tag [%s] (site %s)",
+-                tag_label, lgtd_addrtoa(gw->site.as_array)
++                tag_label, site
+             );
+             return -1;
+         }
+         lgtd_debug(
+             "tag_id %d allocated for tag [%s] on gw [%s]:%hu (site %s)",
+-            tag_id, tag_label, gw->ip_addr, gw->port,
+-            lgtd_addrtoa(gw->site.as_array)
++            tag_id, tag_label, gw->ip_addr, gw->port, site
+         );
+         gw->tag_ids |= LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id);
+         gw->tags[tag_id] = tag;
+@@ -663,11 +678,12 @@
+     assert(tag_id < LGTD_LIFX_GATEWAY_MAX_TAGS);
+ 
+     if (gw->tag_ids & LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id)) {
++        char site[LGTD_LIFX_ADDR_STRLEN];
+         lgtd_debug(
+             "tag_id %d deallocated for tag [%s] on gw [%s]:%hu (site %s)",
+             tag_id, gw->tags[tag_id]->label,
+             gw->ip_addr, gw->port,
+-            lgtd_addrtoa(gw->site.as_array)
++            LGTD_IEEE8023MACTOA(gw->site.as_array, site)
+         );
+         lgtd_lifx_tagging_decref(gw->tags[tag_id], gw);
+         gw->tag_ids &= ~LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id);
+@@ -682,9 +698,11 @@
+ {
+     assert(gw && hdr && pkt);
+ 
++    char addr[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_debug(
+         "SET_TAG_LABELS <-- [%s]:%hu - %s label=%.*s, tags=%jx",
+-        gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr),
++        gw->ip_addr, gw->port,
++        LGTD_IEEE8023MACTOA(hdr->target.device_addr, addr),
+         LGTD_LIFX_LABEL_SIZE, pkt->label, (uintmax_t)pkt->tags
+     );
+ 
+@@ -705,15 +723,18 @@
+ {
+     assert(gw && hdr && pkt);
+ 
++    char addr[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_debug(
+         "SET_TAGS <-- [%s]:%hu - %s tags=%#jx",
+-        gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr),
++        gw->ip_addr, gw->port,
++        LGTD_IEEE8023MACTOA(hdr->target.device_addr, addr),
+         (uintmax_t)pkt->tags
+     );
+ 
+     struct lgtd_lifx_bulb *b;
+     LGTD_LIFX_GATEWAY_GET_BULB_OR_RETURN(b, gw, hdr->target.device_addr);
+ 
++    char bulb_addr[LGTD_LIFX_ADDR_STRLEN], site_addr[LGTD_LIFX_ADDR_STRLEN];
+     int tag_id;
+     LGTD_LIFX_WIRE_FOREACH_TAG_ID(tag_id, pkt->tags) {
+         if (!(gw->tag_ids & LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id))) {
+@@ -721,8 +742,9 @@
+                 "trying to set unknown tag_id %d (%#jx) "
+                 "on bulb %s (%.*s), gw [%s]:%hu (site %s)",
+                 tag_id, LGTD_LIFX_WIRE_TAG_ID_TO_VALUE(tag_id),
+-                lgtd_addrtoa(b->addr), LGTD_LIFX_LABEL_SIZE, b->state.label,
+-                gw->ip_addr, gw->port, lgtd_addrtoa(gw->site.as_array)
++                LGTD_IEEE8023MACTOA(b->addr, bulb_addr),
++                LGTD_LIFX_LABEL_SIZE, b->state.label, gw->ip_addr, gw->port,
++                LGTD_IEEE8023MACTOA(gw->site.as_array, site_addr)
+             );
+         }
+     }
+@@ -756,10 +778,12 @@
+         return;
+     }
+ 
++    char addr[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_debug(
+         "%s <-- [%s]:%hu - %s "
+         "signal_strength=%f, rx_bytes=%u, tx_bytes=%u, temperature=%hu",
+-        type, gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr),
++        type, gw->ip_addr, gw->port,
++        LGTD_IEEE8023MACTOA(hdr->target.device_addr, addr),
+         pkt->signal_strength, pkt->rx_bytes, pkt->tx_bytes, pkt->temperature
+     );
+ 
+@@ -776,10 +800,6 @@
+ {
+     assert(gw && hdr && pkt);
+ 
+-    char built_at[64], installed_at[64];
+-    LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(pkt->built_at, built_at);
+-    LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(pkt->installed_at, installed_at);
+-
+     const char  *type;
+     enum lgtd_lifx_bulb_ips ip_id;
+     switch (hdr->packet_type) {
+@@ -799,11 +819,15 @@
+         return;
+     }
+ 
++    char built_at[64], installed_at[64], addr[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_debug(
+         "%s <-- [%s]:%hu - %s "
+         "built_at=%s, installed_at=%s, version=%u",
+-        type, gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr),
+-        built_at, installed_at, pkt->version
++        type, gw->ip_addr, gw->port,
++        LGTD_IEEE8023MACTOA(hdr->target.device_addr, addr),
++        LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(pkt->built_at, built_at),
++        LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(pkt->installed_at, installed_at),
++        pkt->version
+     );
+ 
+     LGTD_LIFX_GATEWAY_SET_BULB_ATTR(
+@@ -819,10 +843,12 @@
+ {
+     assert(gw && hdr && pkt);
+ 
++    char addr[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_debug(
+         "PRODUCT_INFO <-- [%s]:%hu - %s "
+         "vendor_id=%#x, product_id=%#x, version=%u",
+-        gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr),
++        gw->ip_addr, gw->port,
++        LGTD_IEEE8023MACTOA(hdr->target.device_addr, addr),
+         pkt->vendor_id, pkt->product_id, pkt->version
+     );
+ 
+@@ -839,15 +865,14 @@
+ {
+     assert(gw && hdr && pkt);
+ 
+-    char device_time[64], uptime[64], downtime[64];
+-    LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(pkt->time, device_time);
+-    LGTD_PRINT_DURATION(LGTD_NSECS_TO_SECS(pkt->uptime), uptime);
+-    LGTD_PRINT_DURATION(LGTD_NSECS_TO_SECS(pkt->downtime), downtime);
+-
++    char device_time[64], uptime[64], downtime[64], addr[LGTD_LIFX_ADDR_STRLEN];
+     lgtd_debug(
+         "PRODUCT_INFO <-- [%s]:%hu - %s time=%s, uptime=%s, downtime=%s",
+-        gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr),
+-        device_time, uptime, downtime
++        gw->ip_addr, gw->port,
++        LGTD_IEEE8023MACTOA(hdr->target.device_addr, addr),
++        LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(pkt->time, device_time),
++        LGTD_PRINT_DURATION(LGTD_NSECS_TO_SECS(pkt->uptime), uptime),
++        LGTD_PRINT_DURATION(LGTD_NSECS_TO_SECS(pkt->downtime), downtime)
+     );
+ 
+     LGTD_LIFX_GATEWAY_SET_BULB_ATTR(
+diff --git a/lifx/tagging.c b/lifx/tagging.c
+--- a/lifx/tagging.c
++++ b/lifx/tagging.c
+@@ -123,10 +123,11 @@
+         if (dealloc_tag) {
+             lgtd_info("discovered tag [%s]", tag_label);
+         }
++        char site_addr[LGTD_LIFX_ADDR_STRLEN];
+         lgtd_info(
+             "tag [%s] added to gw [%s]:%hu (site %s) with tag_id %d",
+             tag_label, gw->ip_addr, gw->port,
+-            lgtd_addrtoa(gw->site.as_array), tag_id
++            LGTD_IEEE8023MACTOA(gw->site.as_array, site_addr), tag_id
+         );
+         site->gw = gw;
+         site->tag_id = tag_id;
+@@ -147,10 +148,11 @@
+     struct lgtd_lifx_site *site;
+     site = lgtd_lifx_tagging_find_site(&tag->sites, gw);
+     if (site) {
++        char site_addr[LGTD_LIFX_ADDR_STRLEN];
+         lgtd_debug(
+             "tag [%s] removed from gw [%s]:%hu (site %s)",
+             tag->label, gw->ip_addr, gw->port,
+-            lgtd_addrtoa(gw->site.as_array)
++            LGTD_IEEE8023MACTOA(gw->site.as_array, site_addr)
+         );
+         LIST_REMOVE(site, link);
+         free(site);
+diff --git a/lifx/wire_proto.c b/lifx/wire_proto.c
+--- a/lifx/wire_proto.c
++++ b/lifx/wire_proto.c
+@@ -465,7 +465,7 @@
+     return LGTD_LIFX_WAVEFORM_INVALID;
+ }
+ 
+-void
++char *
+ lgtd_lifx_wire_print_nsec_timestamp(uint64_t nsec_ts, char *buf, int bufsz)
+ {
+     assert(buf);
+@@ -477,10 +477,11 @@
+     if (gmtime_r(&ts, &tm_utc)) {
+         int64_t usecs = LGTD_NSECS_TO_USECS(nsec_ts - LGTD_SECS_TO_NSECS(ts));
+         LGTD_TM_TO_ISOTIME(&tm_utc, buf, bufsz, usecs);
+-        return;
++    } else {
++        buf[0] = '\0';
+     }
+ 
+-    buf[0] = '\0';
++    return buf;
+ }
+ 
+ static void
+diff --git a/lifx/wire_proto.h b/lifx/wire_proto.h
+--- a/lifx/wire_proto.h
++++ b/lifx/wire_proto.h
+@@ -44,6 +44,7 @@
+ enum { LGTD_LIFX_PROTOCOL_PORT = 56700 };
+ 
+ enum { LGTD_LIFX_ADDR_LENGTH = 6 };
++enum { LGTD_LIFX_ADDR_STRLEN = 32 };
+ 
+ #pragma pack(push, 1)
+ 
+@@ -355,10 +356,9 @@
+          (tag_id_varname) = lgtd_lifx_wire_next_tag_id((tag_id_varname), (tags)))
+ 
+ enum lgtd_lifx_waveform_type lgtd_lifx_wire_waveform_string_id_to_type(const char *, int);
+-void lgtd_lifx_wire_print_nsec_timestamp(uint64_t, char *, int);
+-#define LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(ts, arr) do {               \
+-    lgtd_lifx_wire_print_nsec_timestamp((ts), (arr), sizeof((arr)));    \
+-} while (0)
++char* lgtd_lifx_wire_print_nsec_timestamp(uint64_t, char *, int);
++#define LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(ts, arr) \
++    lgtd_lifx_wire_print_nsec_timestamp((ts), (arr), sizeof((arr)))
+ 
+ const struct lgtd_lifx_packet_info *lgtd_lifx_wire_get_packet_info(enum lgtd_lifx_packet_type);
+ void lgtd_lifx_wire_load_packet_info_map(void);
+diff --git a/tests/core/proto/test_proto_tag_create.c b/tests/core/proto/test_proto_tag_create.c
+--- a/tests/core/proto/test_proto_tag_create.c
++++ b/tests/core/proto/test_proto_tag_create.c
+@@ -33,10 +33,12 @@
+     }
+ 
+     uint8_t expected_addr[LGTD_LIFX_ADDR_LENGTH] = { 1, 2, 3, 4, 5 };
++    char addr[LGTD_LIFX_ADDR_STRLEN], expected[LGTD_LIFX_ADDR_STRLEN];
+     if (memcmp(bulb->addr, expected_addr, LGTD_LIFX_ADDR_LENGTH)) {
+         errx(
+             1, "got bulb with addr %s (expected %s)",
+-            lgtd_addrtoa(bulb->addr), lgtd_addrtoa(expected_addr)
++            LGTD_IEEE8023MACTOA(bulb->addr, addr),
++            LGTD_IEEE8023MACTOA(expected_addr, expected)
+         );
+     }
+ 
+diff --git a/tests/core/proto/test_proto_tag_update.c b/tests/core/proto/test_proto_tag_update.c
+--- a/tests/core/proto/test_proto_tag_update.c
++++ b/tests/core/proto/test_proto_tag_update.c
+@@ -35,10 +35,12 @@
+     }
+ 
+     uint8_t expected_addr[LGTD_LIFX_ADDR_LENGTH] = { 5, 4, 3, 2, 1 };
++    char addr[LGTD_LIFX_ADDR_STRLEN], expected[LGTD_LIFX_ADDR_STRLEN];
+     if (memcmp(bulb->addr, expected_addr, LGTD_LIFX_ADDR_LENGTH)) {
+         errx(
+             1, "got bulb with addr %s (expected %s)",
+-            lgtd_addrtoa(bulb->addr), lgtd_addrtoa(expected_addr)
++            LGTD_IEEE8023MACTOA(bulb->addr, addr),
++            LGTD_IEEE8023MACTOA(expected_addr, expected)
+         );
+     }
+ 
+diff --git a/tests/core/proto/test_proto_untag.c b/tests/core/proto/test_proto_untag.c
+--- a/tests/core/proto/test_proto_untag.c
++++ b/tests/core/proto/test_proto_untag.c
+@@ -103,10 +103,12 @@
+     }
+ 
+     uint8_t expected_addr[LGTD_LIFX_ADDR_LENGTH] = { 5, 4, 3, 2, 1 };
++    char addr[LGTD_LIFX_ADDR_STRLEN], expected[LGTD_LIFX_ADDR_STRLEN];
+     if (memcmp(bulb->addr, expected_addr, LGTD_LIFX_ADDR_LENGTH)) {
+         errx(
+             1, "got bulb with addr %s (expected %s)",
+-            lgtd_addrtoa(bulb->addr), lgtd_addrtoa(expected_addr)
++            LGTD_IEEE8023MACTOA(bulb->addr, addr),
++            LGTD_IEEE8023MACTOA(expected_addr, expected)
+         );
+     }
+ 
+diff --git a/tests/lifx/bulb/test_bulb_open.c b/tests/lifx/bulb/test_bulb_open.c
+--- a/tests/lifx/bulb/test_bulb_open.c
++++ b/tests/lifx/bulb/test_bulb_open.c
+@@ -16,10 +16,12 @@
+         errx(1, "lgtd_lifx_bulb_open didn't return any bulb");
+     }
+ 
++    char addr[LGTD_LIFX_ADDR_STRLEN], expected[LGTD_LIFX_ADDR_STRLEN];
+     if (memcmp(bulb->addr, bulb_addr, LGTD_LIFX_ADDR_LENGTH)) {
+         errx(
+             1, "got bulb addr %s (expected %s)",
+-            lgtd_addrtoa(bulb->addr), lgtd_addrtoa(bulb_addr)
++            LGTD_IEEE8023MACTOA(bulb->addr, addr),
++            LGTD_IEEE8023MACTOA(bulb_addr, expected)
+         );
+     }
+ 
+diff --git a/tests/lifx/wire_proto/test_wire_proto_encode_decode_header.c b/tests/lifx/wire_proto/test_wire_proto_encode_decode_header.c
+--- a/tests/lifx/wire_proto/test_wire_proto_encode_decode_header.c
++++ b/tests/lifx/wire_proto/test_wire_proto_encode_decode_header.c
+@@ -78,10 +78,13 @@
+     uint8_t expected_addr[LGTD_LIFX_ADDR_LENGTH] = {
+         0, 0, 44, 0, 0, 0
+     };
++    char expected_addr_buf[LGTD_LIFX_ADDR_STRLEN];
++    char dev_addr[LGTD_LIFX_ADDR_STRLEN];
+     if (memcmp(hdr.target.device_addr, expected_addr, LGTD_LIFX_ADDR_LENGTH)) {
+         lgtd_errx(
+             1, "device addr = %s (expected = %s)",
+-            lgtd_addrtoa(hdr.target.device_addr), lgtd_addrtoa(expected_addr)
++            LGTD_IEEE8023MACTOA(hdr.target.device_addr, dev_addr),
++            LGTD_IEEE8023MACTOA(expected_addr, expected_addr_buf)
+         );
+     }
+     if (le16toh(hdr.packet_type) != LGTD_LIFX_ECHO_REQUEST) {
+@@ -109,7 +112,8 @@
+     if (memcmp(hdr.target.device_addr, expected_addr, LGTD_LIFX_ADDR_LENGTH)) {
+         lgtd_errx(
+             1, "device addr = %s (expected = %s)",
+-            lgtd_addrtoa(hdr.target.device_addr), lgtd_addrtoa(expected_addr)
++            LGTD_IEEE8023MACTOA(hdr.target.device_addr, dev_addr),
++            LGTD_IEEE8023MACTOA(expected_addr, expected_addr_buf)
+         );
+     }
+     if (hdr.size != 42) {
--- a/implement_some_metadata_packet_types.patch	Sat Aug 15 16:37:19 2015 -0700
+++ b/implement_some_metadata_packet_types.patch	Sat Aug 15 23:22:19 2015 -0700
@@ -1,5 +1,5 @@
 # HG changeset patch
-# Parent  54b21b430e79df4954da6508b6ed793eccb30b5a
+# Parent  de1c6a01d9955785187b591d15ab41b516c7cb78
 Handle various informational packet types
 
 - MCU state & firmware info;
@@ -518,7 +518,7 @@
  #include <stdarg.h>
  #include <stdbool.h>
  #include <stdint.h>
-@@ -275,6 +278,27 @@
+@@ -275,6 +278,28 @@
      return bulb;
  }
  
@@ -536,6 +536,7 @@
 +    struct arpreq req;
 +    memset(&req, 0, sizeof(req));
 +    memcpy(&req.arp_pa, sin, sizeof(*sin));
++    memcpy(req.arp_dev, "br0", 4);
 +    if (!ioctl(socket, SIOCGARP, &req)) {
 +        memcpy(hw_addr, req.arp_ha.sa_data, LGTD_LIFX_ADDR_LENGTH);
 +        return true;
@@ -546,7 +547,7 @@
  struct lgtd_lifx_gateway *
  lgtd_lifx_gateway_open(const struct sockaddr_storage *peer,
                         ev_socklen_t addrlen,
-@@ -310,10 +334,20 @@
+@@ -310,10 +335,20 @@
      gw->refresh_ev = evtimer_new(
          lgtd_ev_base, lgtd_lifx_gateway_refresh_callback, gw
      );
@@ -567,7 +568,7 @@
      gw->last_req_at = received_at;
      gw->next_req_at = received_at;
      gw->last_pkt_at = received_at;
-@@ -489,12 +523,8 @@
+@@ -489,12 +524,8 @@
          (uintmax_t)pkt->tags
      );
  
@@ -582,7 +583,7 @@
  
      assert(sizeof(*pkt) == sizeof(b->state));
      lgtd_lifx_bulb_set_light_state(
-@@ -519,7 +549,7 @@
+@@ -519,7 +550,7 @@
          }
      }
  
@@ -591,7 +592,7 @@
      if (latency < LGTD_LIFX_GATEWAY_MIN_REFRESH_INTERVAL_MSECS) {
          if (!event_pending(gw->refresh_ev, EV_TIMEOUT, NULL)) {
              int timeout = LGTD_LIFX_GATEWAY_MIN_REFRESH_INTERVAL_MSECS - latency;
-@@ -559,14 +589,9 @@
+@@ -559,14 +590,9 @@
          gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr), pkt->power
      );
  
@@ -608,7 +609,7 @@
  }
  
  int
-@@ -673,9 +698,10 @@
+@@ -673,9 +699,10 @@
      }
  }
  
@@ -622,7 +623,7 @@
  {
      assert(gw && hdr && pkt);
  
-@@ -685,12 +711,8 @@
+@@ -685,12 +712,8 @@
          (uintmax_t)pkt->tags
      );
  
@@ -637,7 +638,7 @@
  
      int tag_id;
      LGTD_LIFX_WIRE_FOREACH_TAG_ID(tag_id, pkt->tags) {
-@@ -707,3 +729,129 @@
+@@ -707,3 +730,129 @@
  
      lgtd_lifx_bulb_set_tags(b, pkt->tags);
  }
--- a/series	Sat Aug 15 16:37:19 2015 -0700
+++ b/series	Sat Aug 15 23:22:19 2015 -0700
@@ -1,3 +1,4 @@
 add_start_stop_timer.patch
 implement_some_metadata_packet_types.patch
+fix_sockaddrtoa_mess.patch
 blublu