On Thu, Oct 26, 2017 at 07:36:10PM -0400, H. William Welliver III wrote:
> Apologies for the cross-post; I think this is potentially useful for
> SmartOS users despite the fact that I’m using Triton:

You might find the attached patch useful:

(1) Default to serial console for boot ISO
(2) Adjust dhcpcd client defaults for use with SmartOS
(3) Provide mdata hooks

Essentially, build a release ISO and just boot from it, attach to the
console and follow the normal sysinst process. Enable dhcpcd afterwards
for network. Patch is against the netbsd-8 branch.

Joerg

diff -r 01e60b2f69c4 distrib/amd64/cdroms/bootcd/boot.cfg.in
--- a/distrib/amd64/cdroms/bootcd/boot.cfg.in   Mon Oct 02 13:37:05 2017 +0000
+++ b/distrib/amd64/cdroms/bootcd/boot.cfg.in   Fri Oct 27 15:13:22 2017 +0200
@@ -13,3 +13,4 @@
 menu=Install NetBSD (no ACPI, no SMP):boot netbsd -12
 menu=Drop to boot prompt:prompt
 timeout=30
+consdev=com0
diff -r 01e60b2f69c4 distrib/amd64/cdroms/installcd/boot.cfg.in
--- a/distrib/amd64/cdroms/installcd/boot.cfg.in        Mon Oct 02 13:37:05 
2017 +0000
+++ b/distrib/amd64/cdroms/installcd/boot.cfg.in        Fri Oct 27 15:13:22 
2017 +0200
@@ -9,3 +9,4 @@
 menu=Install NetBSD (no ACPI, no SMP):boot netbsd -12
 menu=Drop to boot prompt:prompt
 timeout=30
+consdev=com0
diff -r 01e60b2f69c4 distrib/amd64/installimage/boot.cfg.in
--- a/distrib/amd64/installimage/boot.cfg.in    Mon Oct 02 13:37:05 2017 +0000
+++ b/distrib/amd64/installimage/boot.cfg.in    Fri Oct 27 15:13:22 2017 +0200
@@ -10,3 +10,4 @@
 menu=Drop to boot prompt:prompt
 timeout=30
 clear=1
+consdev=com0
diff -r 01e60b2f69c4 distrib/amd64/uefi-installimage/boot.cfg.in
--- a/distrib/amd64/uefi-installimage/boot.cfg.in       Mon Oct 02 13:37:05 
2017 +0000
+++ b/distrib/amd64/uefi-installimage/boot.cfg.in       Fri Oct 27 15:13:22 
2017 +0200
@@ -10,3 +10,4 @@
 menu=Drop to boot prompt:prompt
 timeout=30
 clear=1
+consdev=com0
diff -r 01e60b2f69c4 distrib/sets/lists/base/mi
--- a/distrib/sets/lists/base/mi        Mon Oct 02 13:37:05 2017 +0000
+++ b/distrib/sets/lists/base/mi        Fri Oct 27 15:13:22 2017 +0200
@@ -1741,6 +1741,10 @@
 ./usr/sbin/makemap                             base-obsolete           obsolete
 ./usr/sbin/map-mbone                           base-netutil-bin
 ./usr/sbin/mbrlabel                            base-obsolete           obsolete
+./usr/sbin/mdata-delete                                base-mdata-bin
+./usr/sbin/mdata-get                           base-mdata-bin
+./usr/sbin/mdata-list                          base-mdata-bin
+./usr/sbin/mdata-put                           base-mdata-bin
 ./usr/sbin/mdconfig                            base-sysutil-bin
 ./usr/sbin/mdnsd                               base-mdns-bin           mdns
 ./usr/sbin/mdsetimage                          base-sysutil-bin        binutils
diff -r 01e60b2f69c4 distrib/sets/lists/etc/mi
--- a/distrib/sets/lists/etc/mi Mon Oct 02 13:37:05 2017 +0000
+++ b/distrib/sets/lists/etc/mi Fri Oct 27 15:13:22 2017 +0200
@@ -231,6 +231,7 @@
 ./etc/rc.d/lpd                                 etc-lpr-rc
 ./etc/rc.d/lvm                                 etc-sys-rc
 ./etc/rc.d/makemandb                           etc-man-rc
+./etc/rc.d/mdata                               etc-mdata-rc
 ./etc/rc.d/mdnsd                               etc-mdns-rc
 ./etc/rc.d/mixerctl                            etc-audio-rc
 ./etc/rc.d/modules                             etc-sys-rc
diff -r 01e60b2f69c4 distrib/sets/lists/man/mi
--- a/distrib/sets/lists/man/mi Mon Oct 02 13:37:05 2017 +0000
+++ b/distrib/sets/lists/man/mi Fri Oct 27 15:13:22 2017 +0200
@@ -2686,6 +2686,10 @@
 ./usr/share/man/cat8/master.0                  man-postfix-catman      
postfix,.cat
 ./usr/share/man/cat8/mbr.0                     man-obsolete            obsolete
 ./usr/share/man/cat8/mbrlabel.0                        man-sysutil-catman      
.cat
+./usr/share/man/cat8/mdata-delete.0            man-sysutil-catman      .cat
+./usr/share/man/cat8/mdata-get.0               man-sysutil-catman      .cat
+./usr/share/man/cat8/mdata-list.0              man-sysutil-catman      .cat
+./usr/share/man/cat8/mdata-put.0               man-sysutil-catman      .cat
 ./usr/share/man/cat8/mdconfig.0                        man-sysutil-catman      
.cat
 ./usr/share/man/cat8/mdnsd.0                   man-mdns-catman         
mdns,.cat
 ./usr/share/man/cat8/mdsetimage.0              man-sysutil-catman      
binutils,.cat
@@ -5601,6 +5605,10 @@
 ./usr/share/man/html8/map-mbone.html           man-netutil-htmlman     html
 ./usr/share/man/html8/master.html              man-postfix-htmlman     
postfix,html
 ./usr/share/man/html8/mbrlabel.html            man-sysutil-htmlman     html
+./usr/share/man/html8/mdata-delete.html                man-sysutil-htmlman     
html
+./usr/share/man/html8/mdata-get.html           man-sysutil-htmlman     html
+./usr/share/man/html8/mdata-list.html          man-sysutil-htmlman     html
+./usr/share/man/html8/mdata-put.html           man-sysutil-htmlman     html
 ./usr/share/man/html8/mdconfig.html            man-sysutil-htmlman     html
 ./usr/share/man/html8/mdnsd.html               man-mdns-htmlman        
mdns,html
 ./usr/share/man/html8/mdsetimage.html          man-sysutil-htmlman     
binutils,html
@@ -8688,6 +8696,10 @@
 ./usr/share/man/man8/master.8                  man-postfix-man         
postfix,.man
 ./usr/share/man/man8/mbr.8                     man-obsolete            obsolete
 ./usr/share/man/man8/mbrlabel.8                        man-sysutil-man         
.man
+./usr/share/man/man8/mdata-delete.8            man-sysutil-man         .man
+./usr/share/man/man8/mdata-get.8               man-sysutil-man         .man
+./usr/share/man/man8/mdata-list.8              man-sysutil-man         .man
+./usr/share/man/man8/mdata-put.8               man-sysutil-man         .man
 ./usr/share/man/man8/mdconfig.8                        man-sysutil-man         
.man
 ./usr/share/man/man8/mdnsd.8                   man-mdns-man            
mdns,.man
 ./usr/share/man/man8/mdsetimage.8              man-sysutil-man         
binutils,.man
diff -r 01e60b2f69c4 etc/etc.amd64/boot.cfg
--- a/etc/etc.amd64/boot.cfg    Mon Oct 02 13:37:05 2017 +0000
+++ b/etc/etc.amd64/boot.cfg    Fri Oct 27 15:13:22 2017 +0200
@@ -6,3 +6,4 @@
 default=1
 timeout=5
 clear=1
+consdev=com0
diff -r 01e60b2f69c4 etc/rc.d/Makefile
--- a/etc/rc.d/Makefile Mon Oct 02 13:37:05 2017 +0000
+++ b/etc/rc.d/Makefile Fri Oct 27 15:13:22 2017 +0200
@@ -26,7 +26,7 @@
                ipsec irdaattach iscsi_target iscsid isdnd isibootd \
                kdc \
                ldconfig ldpd local lpd lvm \
-               makemandb mdnsd mixerctl modules mopd motd mountall \
+               makemandb mdata mdnsd mixerctl modules mopd motd mountall \
                mountcritlocal mountcritremote mountd moused mrouted \
                named ndbootd network newsyslog nfsd nfslocking npf npfd ntpd \
                ntpdate \
diff -r 01e60b2f69c4 etc/rc.d/mdata
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/rc.d/mdata    Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,72 @@
+#!/bin/sh
+#
+# $NetBSD$
+#
+
+# PROVIDE: mdata
+# REQUIRE: mountcritremote
+# BEFORE:  SERVERS
+
+# The mdata service is run early to allow customisation of most services.
+
+# Enable this service by default iff running on SmartOS.
+if [ "$(sysctl -n machdep.dmi.system-vendor 2> /dev/null)" = "Joyent" ] && \
+   [ "$(sysctl -n machdep.dmi.system-product 2> /dev/null)" = "SmartDC HVM" ]; 
then
+       mdata=YES
+else
+       mdata=NO
+fi
+
+$_rc_subr_loaded . /etc/rc.subr
+
+
+name="mdata"
+rcvar=$name
+
+start_cmd="mdata_start"
+stop_cmd=":"
+
+mdata_start()
+{
+       cmd=$(/usr/sbin/mdata-get user-script)
+       eval "$cmd"
+}
+
+load_rc_config $name
+run_rc_command "$1"
+#!/bin/sh
+#
+# $NetBSD$
+#
+
+# PROVIDE: mdata
+# REQUIRE: mountcritremote
+# BEFORE:  SERVERS
+
+# The mdata service is run early to allow customisation of most services.
+
+# Enable this service by default iff running on SmartOS.
+if [ "$(sysctl -n machdep.dmi.system-vendor 2> /dev/null)" = "Joyent" ] && \
+   [ "$(sysctl -n machdep.dmi.system-product 2> /dev/null)" = "SmartDC HVM" ]; 
then
+       mdata=YES
+else
+       mdata=NO
+fi
+
+$_rc_subr_loaded . /etc/rc.subr
+
+
+name="mdata"
+rcvar=$name
+
+start_cmd="mdata_start"
+stop_cmd=":"
+
+mdata_start()
+{
+       cmd=$(/usr/sbin/mdata-get user-script)
+       eval "$cmd"
+}
+
+load_rc_config $name
+run_rc_command "$1"
diff -r 01e60b2f69c4 external/bsd/dhcpcd/dist/src/dhcpcd.conf
--- a/external/bsd/dhcpcd/dist/src/dhcpcd.conf  Mon Oct 02 13:37:05 2017 +0000
+++ b/external/bsd/dhcpcd/dist/src/dhcpcd.conf  Fri Oct 27 15:13:22 2017 +0200
@@ -8,12 +8,12 @@
 hostname
 
 # Use the hardware address of the interface for the Client ID.
-#clientid
+clientid
 # or
 # Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
 # Some non-RFC compliant DHCP servers do not reply with this set.
 # In this case, comment out duid and enable clientid above.
-duid
+# duid
 
 # Persist interface configuration when dhcpcd exits.
 persistent
@@ -36,4 +36,5 @@
 require dhcp_server_identifier
 
 # Generate Stable Private IPv6 Addresses instead of hardware based ones
-slaac private
+# slaac private
+slaac hwaddr
diff -r 01e60b2f69c4 external/mit/Makefile
--- a/external/mit/Makefile     Mon Oct 02 13:37:05 2017 +0000
+++ b/external/mit/Makefile     Fri Oct 27 15:13:22 2017 +0200
@@ -2,7 +2,7 @@
 
 .include <bsd.own.mk>
 
-SUBDIR+=       expat lua
+SUBDIR+=       expat lua mdata-client
 
 .if ${MKX11} != "no"
 SUBDIR+=       xorg
diff -r 01e60b2f69c4 external/mit/mdata-client/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/Makefile        Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,30 @@
+# $NetBSD
+
+BINDIR=        /usr/sbin
+
+PROGS= mdata-get \
+       mdata-list \
+       mdata-put \
+       mdata-delete
+WARNS= 4
+
+COMMON_SRCS=   proto.c dynstr.c crc32.c base64.c common.c reqid.c
+COMMON_SRCS+=  bsd.c unix_common.c
+
+SRCS.mdata-get=                mdata_get.c ${COMMON_SRCS}
+SRCS.mdata-list=       mdata_list.c ${COMMON_SRCS}
+SRCS.mdata-put=                mdata_put.c ${COMMON_SRCS}
+SRCS.mdata-delete=     mdata_delete.c ${COMMON_SRCS}
+
+SRCDIR:=       ${.PARSEDIR}/dist
+CPPFLAGS+=     -I${SRCDIR}
+
+.PATH: ${SRCDIR} ${SRCDIR}/plat
+
+.for p in ${PROGS}
+MAN.${p}=      ${p}.8
+${p}.8: ${SRCDIR}/man/man1m/${p}.1m
+       ${TOOL_SED} s,__SECT__,8,g ${.ALLSRC} > ${.TARGET}
+.endfor
+
+.include <bsd.prog.mk>
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/.gitignore
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/.gitignore Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,2 @@
+/mdata-*
+/proto/
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/LICENSE
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/LICENSE    Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013, Joyent, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/Makefile   Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,191 @@
+
+VERSION = 0.0.1
+
+CC = gcc
+
+CTFMERGE = /bin/true
+CTFCONVERT = /bin/true
+
+GNUTAR = tar
+
+PWD := $(shell pwd)
+UNAME_S := $(shell uname -s)
+PLATFORM_OK = false
+
+CFILES = dynstr.c proto.c common.c base64.c crc32.c reqid.c
+OBJS = $(CFILES:%.c=%.o)
+HDRS = dynstr.h plat.h proto.h common.h base64.h crc32.h reqid.h
+CFLAGS = -I$(PWD) -Wall -Wextra -Werror -g -O2
+LDLIBS =
+
+BINDIR = /usr/sbin
+MANSECT = 1m
+MANDIR = /usr/share/man/man$(MANSECT)
+DESTDIR = $(PWD)/proto
+
+PROGS = \
+       mdata-get \
+       mdata-list \
+       mdata-put \
+       mdata-delete
+
+PROTO_PROGS = \
+       $(PROGS:%=$(DESTDIR)$(BINDIR)/%)
+
+PROTO_MANPAGES = \
+       $(PROGS:%=$(DESTDIR)$(MANDIR)/%.$(MANSECT))
+
+INSTALL_TARGETS = \
+       $(PROTO_PROGS) \
+       $(PROTO_MANPAGES)
+
+#
+# Platform-specific definitions
+#
+
+ifeq ($(UNAME_S),SunOS)
+CFLAGS += -D__HAVE_BOOLEAN_T
+CFILES += plat/sunos.c plat/unix_common.c
+HDRS += plat/unix_common.h
+LDLIBS += -lnsl -lsocket -lsmbios
+PLATFORM_OK = true
+GNUTAR = gtar
+endif
+
+ifeq ($(UNAME_S),Linux)
+CFILES += plat/linux.c plat/unix_common.c
+HDRS += plat/unix_common.h
+PLATFORM_OK = true
+MANSECT = 1
+INSTALL_TARGETS += $(DESTDIR)/lib/smartdc/mdata-get
+PKGNAME = joyent-mdata-client
+endif
+
+ifeq ($(UNAME_S),FreeBSD)
+CC = cc
+
+CTFMERGE = /usr/bin/true
+CTFCONVERT = /usr/bin/true
+
+CFLAGS += -Wno-typedef-redefinition
+CFILES += plat/bsd.c plat/unix_common.c
+HDRS += plat/unix_common.h
+PLATFORM_OK = true
+MANSECT = 1
+endif
+
+ifeq ($(UNAME_S),NetBSD)
+CC != if [ -x /usr/bin/clang ]; then echo /usr/bin/clang; else echo 
/usr/bin/gcc; fi
+
+CTFMERGE != if [ -x /usr/bin/ctfmerge ]; then echo /usr/bin/ctfmerge; else 
echo /usr/bin/true; fi
+CTFCONVERT != if [ -x /usr/bin/ctfconvert ]; then echo /usr/bin/ctfconvert; 
else echo /usr/bin/true; fi
+
+CFILES += plat/bsd.c plat/unix_common.c
+HDRS += plat/unix_common.h
+PLATFORM_OK = true
+MANSECT = 1
+endif
+
+ifeq ($(UNAME_S),OpenBSD)
+CC = cc
+
+CTFMERGE = /usr/bin/true
+CTFCONVERT = /usr/bin/true
+
+CFILES += plat/bsd.c plat/unix_common.c
+HDRS += plat/unix_common.h
+PLATFORM_OK = true
+MANSECT = 1
+endif
+
+ifeq ($(PLATFORM_OK),false)
+$(error Unknown platform: $(UNAME_S))
+endif
+
+#
+# Build Targets
+#
+
+.PHONY:        all world
+world: all
+all:   $(PROGS)
+
+%.o:   %.c
+       $(CC) -c $(CFLAGS) -o $@ $<
+       $(CTFCONVERT) -l mdata-client $@
+
+mdata-%:       $(OBJS) $(HDRS) mdata_%.o
+       $(CC) $(CFLAGS) $(LDLIBS) -o $@ $(@:mdata-%=mdata_%).o $(OBJS)
+       $(CTFMERGE) -l mdata-client -o $@ $(OBJS) $(@:mdata-%=mdata_%).o
+
+#
+# Install Targets
+#
+
+.PHONY:        install
+install:       $(INSTALL_TARGETS)
+
+$(DESTDIR)$(BINDIR)/%: %
+       @mkdir -p $(DESTDIR)$(BINDIR)
+       cp $< $@
+       touch $@
+
+$(DESTDIR)$(MANDIR)/%.$(MANSECT): man/man1m/%.1m
+       @mkdir -p $(DESTDIR)$(MANDIR)
+       sed 's/__SECT__/$(MANSECT)/g' < $< > $@
+
+$(DESTDIR)/lib/smartdc/mdata-%:
+       @mkdir -p $$(dirname $@)
+       @rm -f $@
+       ln -s $(BINDIR)/$$(basename $@) $@
+
+#
+# SmartOS (smartos-live) Package Manifest Targets
+#
+
+.PHONY: manifest
+manifest:
+       cp manifest $(DESTDIR)/$(DESTNAME)
+
+.PHONY: mancheck_conf
+mancheck_conf:
+
+.PHONY: update
+update:
+       git pull --rebase
+
+#
+# Debian Package Targets
+#
+#
+
+.PHONY: package-debian
+package-debian:
+       debuild -us -uc
+
+source-tarball:
+       if [ -z $(RELEASE_DIRECTORY) ]; then \
+               echo "error: define RELEASE_DIRECTORY" >&2; \
+               exit 1; \
+       fi
+       if [ -z $(PKGNAME) ]; then \
+               echo "error: define PKGNAME" >&2; \
+               exit 1; \
+       fi
+       $(GNUTAR) \
+               -zc -f $(RELEASE_DIRECTORY)/$(PKGNAME)_$(VERSION).orig.tar.gz \
+               --exclude=.git \
+               --transform 's,^,$(PKGNAME)_$(VERSION)/,' \
+               *
+
+#
+# Cleanup Targets
+#
+
+.PHONY:        clean
+clean:
+       rm -f $(PROGS) $(OBJS)
+
+.PHONY:        clobber
+clobber:       clean
+       rm -rf $(PWD)/proto
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/README.md
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/README.md  Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,55 @@
+# mdata-client
+
+This repository contains metadata retrieval and manipulation tools for use
+within guests of the SmartOS (and SDC) hypervisor.  These guests may be either
+SmartOS Zones or KVM virtual machines.
+
+This repository is part of the Joyent SmartDataCenter project (SDC).  For
+contribution guidelines, issues, and general documentation, visit the main
+[SDC](http://github.com/joyent/sdc) project page.
+
+# Commands
+
+There are four commands provided in this consolidation:
+
+* [mdata-list(1M)][mdata_list]; list custom metadata keys in the metadata store
+* [mdata-get(1M)][mdata_get]; get the value of a particular metadata key
+* [mdata-put(1M)][mdata_put]; set the value of a particular metadata key
+* [mdata-delete(1M)][mdata_delete]; remove a metadata key
+
+Manual pages for these tools are available in this repository, and are
+generally shipped with the OS (in the case of SmartOS) or in the package (e.g.
+[for Ubuntu][launchpad_pkg]).  They are also viewable on the web at the links
+above.
+
+# Protocol and Transport
+
+The Joyent Metadata Protocol [is documented online][protocol].  The programs in
+this repository are clients that communicate using this protocol.  The SmartOS
+(or SmartDataCenter) hypervisor provides a [common set][datadict] of supported
+base metadata keys for guests to consume, as well as the ability to support
+arbitrary additional user-provided metadata.
+
+In a SmartOS container/zone guest, a UNIX domain socket is used to communicate
+with the metadata server running in the hypervisor.  In a KVM guest, such as a
+Linux virtual machine, the client tools will make use of the second serial port
+(e.g.  `ttyb`, or `COM2`) to communicate with the hypervisor.
+
+# OS Support
+
+The tools currently build and function on SmartOS and various Linux
+distributions.  Support for other operating systems, such as \*BSD or Windows,
+is absolutely welcome.
+
+## License
+
+MIT (See _LICENSE_.)
+
+[mdata_docs]: http://eng.joyent.com/mdata/
+[protocol]: http://eng.joyent.com/mdata/protocol.html
+[datadict]: http://eng.joyent.com/mdata/datadict.html
+[mdata_get]: http://smartos.org/man/1M/mdata-get
+[mdata_delete]: http://smartos.org/man/1M/mdata-delete
+[mdata_put]: http://smartos.org/man/1M/mdata-put
+[mdata_list]: http://smartos.org/man/1M/mdata-list
+[launchpad_pkg]: https://launchpad.net/ubuntu/+source/joyent-mdata-client
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/base64.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/base64.c   Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ *
+ * Portions based on Public Domain work obtained from:
+ *  https://shell.franken.de/svn/sky/xmlstorage/trunk/c++/xmlrpc/base64.cpp
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "base64.h"
+#include "dynstr.h"
+
+static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+    "abcdefghijklmnopqrstuvwxyz0123456789+/";
+
+void
+base64_encode(const char *input_, size_t len, string_t *output)
+{
+       const uint8_t *input = (const uint8_t *)input_;
+       char tmp[5];
+       unsigned int i = 0;
+
+       tmp[4] = '\0';
+       dynstr_append(output, "");
+
+       while (i < len) {
+               uint32_t c = input[i++] << 16;
+               if (i < len)
+                       c |= input[i] << 8;
+               i++;
+               if (i < len)
+                       c |= input[i];
+               i++;
+
+               tmp[0] = base64[(c & 0x00fc0000) >> 18];
+               tmp[1] = base64[(c & 0x0003f000) >> 12];
+               tmp[2] = i > len + 1 ? '=' : base64[(c & 0x00000fc0) >> 6];
+               tmp[3] = i > len ? '=' : base64[c & 0x0000003f];
+
+               dynstr_append(output, tmp);
+       }
+}
+
+static int
+decode_one(char c)
+{
+       if (c >= 'A' && c <= 'Z')
+               return (c - 'A');
+       if (c >= 'a' && c <= 'z')
+               return (c - 'a' + 26);
+       if (c >= '0' && c <= '9')
+               return (c - '0' + 52);
+       if (c == '+')
+               return (62);
+       if (c == '/')
+               return (63);
+       if (c == '=')
+               return (-1);
+
+       return (-2);
+}
+
+int
+base64_decode(const char *input, size_t len, string_t *output)
+{
+       int typ[4];
+       uint8_t buf[4];
+       unsigned int i, j;
+
+       buf[3] = '\0';
+       dynstr_append(output, "");
+
+       /*
+        * Valid encoded strings are a multiple of 4 characters long:
+        */
+       if (len % 4 != 0)
+               return (-1);
+
+       for (i = 0; i < len; i += 4) {
+               for (j = 0; j < 4; j++)
+                       typ[j] = decode_one(input[i + j]);
+
+               /*
+                * Filler must be contiguous on the right of the input
+                * string, and at most two bytes:
+                */
+               if (typ[0] == -1 || typ[1] == -1)
+                       return (-1);
+               if (typ[2] == -1 && typ[3] != -1)
+                       return (-1);
+
+               buf[0] = (typ[0] << 2) | (typ[1] >> 4);
+               if (typ[2] != -1)
+                       buf[1] = ((typ[1] & 0x0f) << 4) | (typ[2] >>2);
+               else
+                       buf[1] = '\0';
+               if (typ[3] != -1)
+                       buf[2] = ((typ[2] & 0x03) << 6) | typ[3];
+               else
+                       buf[2] = '\0';
+
+               dynstr_append(output, (const char *) buf);
+       }
+
+       return (0);
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/base64.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/base64.h   Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#ifndef _BASE64_H
+#define        _BASE64_H
+
+#include "dynstr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void base64_encode(const char *, size_t, string_t *);
+int base64_decode(const char *, size_t, string_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BASE64_H */
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/common.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/common.c   Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "common.h"
+
+int
+print_and_abort(const char *message, const char *file, int line)
+{
+       (void) fprintf(stderr, "ASSERT: %s, file: %s @ line %d\n",
+           message, file, line);
+
+       abort();
+
+       return (0);
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/common.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/common.h   Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#ifndef _COMMON_H
+#define        _COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef        __HAVE_BOOLEAN_T
+typedef enum {
+       B_FALSE = 0,
+       B_TRUE = 1
+} boolean_t;
+#endif /* !__HAVE_BOOLEAN_T */
+
+#define        __UNUSED        __attribute__((unused))
+
+#define        VERIFY(EX)      ((void)((EX) || print_and_abort("EX", 
__FILE__,__LINE__)))
+#define        VERIFY0(EX)     ((void)((EX) && print_and_abort("EX", __FILE__, 
__LINE__)))
+
+#define        ABORT(MSG)      print_and_abort((MSG), __FILE__,__LINE__)
+
+int print_and_abort(const char *, const char *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _COMMON_H */
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/crc32.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/crc32.c    Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "crc32.h"
+#include "dynstr.h"
+
+/*
+ * Pre-generated CRC32 Table from Polynomial 0xEDB88320:
+ */
+static uint32_t crc32_table[] = {
+    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+    0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+    0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+    0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+    0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+    0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+    0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+    0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+    0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+    0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+    0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+    0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+    0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+    0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+    0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+    0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+    0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+    0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+uint32_t
+crc32_calc(const char *cstr, size_t len)
+{
+       uint32_t crc = 0xffffffff;
+       unsigned int i;
+
+       for (i = 0; i < len; i++) {
+               uint8_t b = (uint8_t) cstr[i];
+
+               crc = crc32_table[(crc ^ b) & 0xff] ^ ((crc) >> 8);
+       }
+
+       return (~crc);
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/crc32.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/crc32.h    Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#ifndef _CRC32_H
+#define        _CRC32_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+uint32_t crc32_calc(const char *, size_t);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CRC32_H */
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/debian/changelog
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/debian/changelog   Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,5 @@
+joyent-mdata-client (0.0.1-1); urgency=low
+
+  * Initial packaging for Joyent repository.
+
+ -- Joshua M. Clulow <[email protected]>  Wed, 06 Nov 2013 16:54:10 -0800
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/debian/compat
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/debian/compat      Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,1 @@
+8
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/debian/control
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/debian/control     Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,13 @@
+Source: joyent-mdata-client
+Maintainer: Joshua M. Clulow <[email protected]>
+Section: misc
+Priority: optional
+Standards-Version: 3.9.4
+Build-Depends: debhelper (>= 8)
+
+Package: joyent-mdata-client
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Homepage: https://github.com/joyent/mdata-client
+Description: Metadata client tools for use in guest virtual machines
+ hosted on a SmartOS hypervisor.
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/debian/copyright
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/debian/copyright   Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013, Joyent, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/debian/rules
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/debian/rules       Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,4 @@
+#!/usr/bin/make -f
+
+%:
+       dh $@
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/debian/source/format
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/debian/source/format       Fri Oct 27 
15:13:22 2017 +0200
@@ -0,0 +1,1 @@
+3.0 (quilt)
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/dynstr.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/dynstr.c   Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <err.h>
+#include <string.h>
+
+#include "dynstr.h"
+
+struct string {
+       size_t str_strlen;
+       size_t str_datalen;
+       char *str_data;
+};
+
+#define        STRING_CHUNK_SIZE       64
+
+void
+dynstr_reset(string_t *str)
+{
+       if (str->str_data == NULL)
+               return;
+
+       str->str_strlen = 0;
+       str->str_data[0] = '\0';
+}
+
+size_t
+dynstr_len(string_t *str)
+{
+       return (str->str_strlen);
+}
+
+const char *
+dynstr_cstr(string_t *str)
+{
+       return (str->str_data);
+}
+
+void
+dynstr_appendc(string_t *str, char newc)
+{
+       int chunksz = STRING_CHUNK_SIZE;
+
+       if (str->str_strlen + 1 >= str->str_datalen) {
+               str->str_datalen += chunksz;
+               str->str_data = realloc(str->str_data, str->str_datalen);
+               if (str->str_data == NULL)
+                       err(1, "could not allocate memory for string");
+       }
+       str->str_data[str->str_strlen++] = newc;
+       str->str_data[str->str_strlen] = '\0';
+}
+
+void
+dynstr_append(string_t *str, const char *news)
+{
+       int len = strlen(news);
+       int chunksz = STRING_CHUNK_SIZE;
+
+       while (chunksz < len)
+               chunksz *= 2;
+
+       if (len + str->str_strlen >= str->str_datalen) {
+               str->str_datalen += chunksz;
+               str->str_data = realloc(str->str_data, str->str_datalen);
+               if (str->str_data == NULL)
+                       err(1, "could not allocate memory for string");
+       }
+       strcpy(str->str_data + str->str_strlen, news);
+       str->str_strlen += len;
+}
+
+string_t *
+dynstr_new(void)
+{
+       string_t *ret = calloc(1, sizeof (string_t));
+
+       if (ret == NULL)
+               err(10, "could not allocate memory for string");
+
+       return (ret);
+}
+
+void
+dynstr_free(string_t *str)
+{
+       free(str->str_data);
+       free(str);
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/dynstr.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/dynstr.h   Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#ifndef _DYNSTR_H
+#define        _DYNSTR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct string string_t;
+
+string_t *dynstr_new(void);
+void dynstr_free(string_t *str);
+void dynstr_append(string_t *, const char *);
+void dynstr_appendc(string_t *, char);
+void dynstr_reset(string_t *str);
+size_t dynstr_len(string_t *str);
+const char *dynstr_cstr(string_t *str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DYNSTR_H */
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/man/man1m/mdata-delete.1m
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/man/man1m/mdata-delete.1m  Fri Oct 27 
15:13:22 2017 +0200
@@ -0,0 +1,81 @@
+.\" Copyright (c) 2013, Joyent, Inc.
+.\" See LICENSE file for copyright and license details.
+
+.TH "MDATA-DELETE" "__SECT__" "October 2013" "Joyent SmartDataCenter" 
"Metadata Commands"
+
+.SH "NAME"
+\fBmdata-delete\fR \-\- Delete a metadata key-value pair\.
+
+.SH "SYNOPSIS"
+.
+.nf
+\fB/usr/sbin/mdata-delete\fR \fIkeyname\fR
+.fi
+
+.SH "DESCRIPTION"
+.sp
+.LP
+The \fBmdata-delete\fR command allows the user (or a script) to modify the
+metadata for a guest instance running in a \fISmartDataCenter (SDC)\fR cloud.
+Metadata values are generally set programmatically via \fICloudAPI\fR, or
+during interactive provisioning via a Web Portal.  They may also be set from
+within the instance with the \fBmdata-put\fR command.
+.sp
+.LP
+The key-value pair for \fIkeyname\fR will be removed permanently from the
+metadata stored for this guest instance.  Deletion of a key which did not
+exist is not considered an error.
+.sp
+.LP
+If the metadata service is unavailable at the time of the request, this command
+will block waiting for it to become available.  Non-transient failures will
+cause the program to exit with a non-zero status.  Depending on the nature of
+the error, some diagnostic output may be printed to \fBstderr\fR.
+
+.SH "EXIT STATUS"
+.sp
+.LP
+The following exit values are returned:
+
+.sp
+.ne 2
+.na
+\fB0\fR
+.ad
+.RS 5n
+Successful completion.
+.sp
+The key-value pair named \fIkeyname\fR was removed from the instance metadata,
+or did not initially exist.
+.RE
+
+.sp
+.ne 2
+.na
+\fB2\fR
+.ad
+.RS 5n
+An error occurred.
+.sp
+An unexpected error condition occurred, which is believed to be a
+non-transient condition.  Retrying the request is not expected to
+resolve the error condition; either a software bug or misconfiguration
+exists.
+.RE
+
+.sp
+.ne 2
+.na
+\fB3\fR
+.ad
+.RS 5n
+A usage error occurred.
+.sp
+Malformed arguments were passed to the program.  Check the usage instructions
+to ensure valid arguments are supplied.
+.RE
+
+.SH "SEE ALSO"
+.sp
+.LP
+\fBmdata-get\fR(__SECT__), \fBmdata-list\fR(__SECT__), 
\fBmdata-put\fR(__SECT__)
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/man/man1m/mdata-get.1m
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/man/man1m/mdata-get.1m     Fri Oct 27 
15:13:22 2017 +0200
@@ -0,0 +1,90 @@
+.\" Copyright (c) 2013, Joyent, Inc.
+.\" See LICENSE file for copyright and license details.
+
+.TH "MDATA-GET" "__SECT__" "October 2013" "Joyent SmartDataCenter" "Metadata 
Commands"
+
+.SH "NAME"
+\fBmdata-get\fR \-\- Fetch the value of a metadata key-value pair\.
+
+.SH "SYNOPSIS"
+.
+.nf
+\fB/usr/sbin/mdata-get\fR \fIkeyname\fR
+.fi
+
+.SH "DESCRIPTION"
+.sp
+.LP
+The \fBmdata-get\fR command allows the user (or a script) to query the metadata
+for a guest instance running in a \fISmartDataCenter (SDC)\fR cloud.  Metadata
+values are generally set programmatically via \fICloudAPI\fR, or during
+interactive provisioning via a Web Portal.  They may also be set from within
+the instance with the \fBmdata-put\fR command.
+.sp
+.LP
+The value of the requested \fIkeyname\fR will be printed to \fBstdout\fR.  If
+the metadata service is unavailable at the time of the request, this command
+will block waiting for it to become available.  Non-transient failures, such
+as the non-existence of the requested \fIkeyname\fR, will cause the program
+to exit with a non-zero status.  Depending on the nature of the error, some
+diagnostic output may be printed to \fBstderr\fR.
+
+.SH "EXIT STATUS"
+.sp
+.LP
+The following exit values are returned:
+
+.sp
+.ne 2
+.na
+\fB0\fR
+.ad
+.RS 5n
+Successful completion.
+.sp
+The requested \fIkeyname\fR was available, and its value was emitted to
+\fBstdout\fR.
+.RE
+
+.sp
+.ne 2
+.na
+\fB1\fR
+.ad
+.RS 5n
+Metadata value not found.
+.sp
+The requested \fIkeyname\fR was not found in the metadata.
+.RE
+
+.sp
+.ne 2
+.na
+\fB2\fR
+.ad
+.RS 5n
+An error occurred.
+.sp
+An unexpected error condition occurred, which is believed to be a
+non-transient condition.  Retrying the request is not expected to
+resolve the error condition; either a software bug or misconfiguration
+exists.
+.RE
+
+.sp
+.ne 2
+.na
+\fB3\fR
+.ad
+.RS 5n
+A usage error occurred.
+.sp
+Malformed arguments were passed to the program.  Check the usage instructions
+to ensure valid arguments are supplied.
+.RE
+
+.SH "SEE ALSO"
+.sp
+.LP
+\fBmdata-delete\fR(__SECT__), \fBmdata-list\fR(__SECT__),
+\fBmdata-put\fR(__SECT__)
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/man/man1m/mdata-list.1m
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/man/man1m/mdata-list.1m    Fri Oct 27 
15:13:22 2017 +0200
@@ -0,0 +1,79 @@
+.\" Copyright (c) 2013, Joyent, Inc.
+.\" See LICENSE file for copyright and license details.
+
+.TH "MDATA-LIST" "__SECT__" "October 2013" "Joyent SmartDataCenter" "Metadata 
Commands"
+
+.SH "NAME"
+\fBmdata-list\fR \-\- Fetch the list of available metadata key-value pairs\.
+
+.SH "SYNOPSIS"
+.
+.nf
+\fB/usr/sbin/mdata-list\fR
+.fi
+
+.SH "DESCRIPTION"
+.sp
+.LP
+The \fBmdata-list\fR command allows the user (or a script) to query the 
metadata
+for a guest instance running in a \fISmartDataCenter (SDC)\fR cloud.  Metadata
+values are generally set programmatically via \fICloudAPI\fR, or during
+interactive provisioning via a Web Portal.  They may also be set from within
+the instance with the \fBmdata-put\fR command.  The value of a key-value pair
+may be obtained by passing its name to the \fBmdata-get\fR command.
+.sp
+.LP
+The list of all customer-provided metadata key-value pairs will be printed to
+\fBstdout\fR.  If the metadata service is unavailable at the time of the
+request, this command will block waiting for it to become available.
+Non-transient failures will cause the program to exit with a non-zero status.
+Depending on the nature of the error, some diagnostic output may be printed to
+\fBstderr\fR.
+
+.SH "EXIT STATUS"
+.sp
+.LP
+The following exit values are returned:
+
+.sp
+.ne 2
+.na
+\fB0\fR
+.ad
+.RS 5n
+Successful completion.
+.sp
+The list of key-value pairs was emitted to \fBstdout\fR.
+.RE
+
+.sp
+.ne 2
+.na
+\fB2\fR
+.ad
+.RS 5n
+An error occurred.
+.sp
+An unexpected error condition occurred, which is believed to be a
+non-transient condition.  Retrying the request is not expected to
+resolve the error condition; either a software bug or misconfiguration
+exists.
+.RE
+
+.sp
+.ne 2
+.na
+\fB3\fR
+.ad
+.RS 5n
+A usage error occurred.
+.sp
+Malformed arguments were passed to the program.  Check the usage instructions
+to ensure valid arguments are supplied.
+.RE
+
+.SH "SEE ALSO"
+.sp
+.LP
+\fBmdata-delete\fR(__SECT__), \fBmdata-get\fR(__SECT__),
+\fBmdata-put\fR(__SECT__)
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/man/man1m/mdata-put.1m
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/man/man1m/mdata-put.1m     Fri Oct 27 
15:13:22 2017 +0200
@@ -0,0 +1,83 @@
+.\" Copyright (c) 2013, Joyent, Inc.
+.\" See LICENSE file for copyright and license details.
+
+.TH "MDATA-PUT" "__SECT__" "October 2013" "Joyent SmartDataCenter" "Metadata 
Commands"
+
+.SH "NAME"
+\fBmdata-put\fR \-\- Set the value of a metadata key-value pair\.
+
+.SH "SYNOPSIS"
+.
+.nf
+\fB/usr/sbin/mdata-put\fR \fIkeyname\fR [ \fIvalue\fR ]
+.fi
+
+.SH "DESCRIPTION"
+.sp
+.LP
+The \fBmdata-put\fR command allows the user (or a script) to modify the 
metadata
+for a guest instance running in a \fISmartDataCenter (SDC)\fR cloud.  Metadata
+values are generally set programmatically via \fICloudAPI\fR, or during
+interactive provisioning via a Web Portal.  The value of a key-value pair
+may be obtained by passing its name to the \fBmdata-get\fR command.
+.sp
+.LP
+The key-value pair named \fIkeyname\fR will be updated in the metadata store
+for this instance.  If a \fIvalue\fR argument is provided on the command-line,
+then that value will be used.  Otherwise, if \fIstdin\fR is not a tty, the
+value will be read from \fIstdin\fR.
+.sp
+.LP
+If the metadata service is unavailable at the time of the request, this command
+will block waiting for it to become available.  Non-transient failures, such as
+the non-existence of the requested \fIkeyname\fR, will cause the program to
+exit with a non-zero status.  Depending on the nature of the error, some
+diagnostic output may be printed to \fBstderr\fR.
+
+.SH "EXIT STATUS"
+.sp
+.LP
+The following exit values are returned:
+
+.sp
+.ne 2
+.na
+\fB0\fR
+.ad
+.RS 5n
+Successful completion.
+.sp
+The requested \fIkeyname\fR was valid, and its value was updated.
+.RE
+
+.sp
+.ne 2
+.na
+\fB2\fR
+.ad
+.RS 5n
+An error occurred.
+.sp
+An unexpected error condition occurred, which is believed to be a
+non-transient condition.  Retrying the request is not expected to
+resolve the error condition; either a software bug or misconfiguration
+exists.
+.RE
+
+.sp
+.ne 2
+.na
+\fB3\fR
+.ad
+.RS 5n
+A usage error occurred.
+.sp
+Malformed arguments were passed to the program.  Check the usage instructions
+to ensure valid arguments are supplied.
+.RE
+
+.SH "SEE ALSO"
+.sp
+.LP
+\fBmdata-delete\fR(__SECT__), \fBmdata-get\fR(__SECT__),
+\fBmdata-list\fR(__SECT__)
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/manifest
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/manifest   Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,8 @@
+f usr/sbin/mdata-delete 0555 root bin
+f usr/sbin/mdata-get 0555 root bin
+f usr/sbin/mdata-list 0555 root bin
+f usr/sbin/mdata-put 0555 root bin
+f usr/share/man/man1m/mdata-delete.1m 0444 root bin
+f usr/share/man/man1m/mdata-get.1m 0444 root bin
+f usr/share/man/man1m/mdata-list.1m 0444 root bin
+f usr/share/man/man1m/mdata-put.1m 0444 root bin
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/mdata_delete.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/mdata_delete.c     Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+
+#include "common.h"
+#include "dynstr.h"
+#include "plat.h"
+#include "proto.h"
+
+typedef enum mdata_exit_codes {
+       MDEC_SUCCESS = 0,
+       MDEC_NOTFOUND = 1,
+       MDEC_ERROR = 2,
+       MDEC_USAGE_ERROR = 3,
+       MDEC_TRY_AGAIN = 10
+} mdata_exit_codes_t;
+
+static char *keyname;
+
+static int
+print_response(mdata_response_t mdr, string_t *data)
+{
+       switch (mdr) {
+       case MDR_SUCCESS:
+               return (MDEC_SUCCESS);
+       case MDR_NOTFOUND:
+               fprintf(stderr, "No metadata for '%s'\n", keyname);
+               return (MDEC_NOTFOUND);
+       case MDR_UNKNOWN:
+               fprintf(stderr, "Error deleting metadata key '%s': %s\n",
+                   keyname, dynstr_cstr(data));
+               return (MDEC_ERROR);
+       case MDR_INVALID_COMMAND:
+               fprintf(stderr, "ERROR: host does not support DELETE\n");
+               return (MDEC_ERROR);
+       default:
+               ABORT("print_response: UNKNOWN RESPONSE\n");
+               return (MDEC_ERROR);
+       }
+}
+
+int
+main(int argc, char **argv)
+{
+       mdata_proto_t *mdp;
+       mdata_response_t mdr;
+       string_t *data;
+       const char *errmsg = NULL;
+
+       if (argc < 2) {
+               errx(MDEC_USAGE_ERROR, "Usage: %s <keyname>", argv[0]);
+       }
+
+       if (proto_init(&mdp, &errmsg) != 0) {
+               fprintf(stderr, "ERROR: could not initialise protocol: %s\n",
+                   errmsg);
+               return (MDEC_ERROR);
+       }
+
+       if (proto_version(mdp) < 2) {
+               fprintf(stderr, "ERROR: host does not support DELETE\n");
+               return (MDEC_ERROR);
+       }
+
+       keyname = strdup(argv[1]);
+
+       if (proto_execute(mdp, "DELETE", keyname, &mdr, &data) != 0) {
+               fprintf(stderr, "ERROR: could not execute GET\n");
+               return (MDEC_ERROR);
+       }
+
+       return (print_response(mdr, data));
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/mdata_get.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/mdata_get.c        Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+
+#include "common.h"
+#include "dynstr.h"
+#include "plat.h"
+#include "proto.h"
+
+typedef enum mdata_exit_codes {
+       MDEC_SUCCESS = 0,
+       MDEC_NOTFOUND = 1,
+       MDEC_ERROR = 2,
+       MDEC_USAGE_ERROR = 3,
+       MDEC_TRY_AGAIN = 10
+} mdata_exit_codes_t;
+
+static char *keyname;
+
+static int
+print_response(mdata_response_t mdr, string_t *data)
+{
+       const char *cstr = dynstr_cstr(data);
+       size_t len = dynstr_len(data);
+
+       switch (mdr) {
+       case MDR_SUCCESS:
+               fprintf(stdout, "%s", cstr);
+               if (len < 1 || cstr[len - 1] != '\n')
+                       fprintf(stdout, "\n");
+               return (MDEC_SUCCESS);
+       case MDR_NOTFOUND:
+               fprintf(stderr, "No metadata for '%s'\n", keyname);
+               return (MDEC_NOTFOUND);
+       case MDR_UNKNOWN:
+               fprintf(stderr, "Error getting metadata for key '%s': %s\n",
+                   keyname, cstr);
+               return (MDEC_ERROR);
+       case MDR_INVALID_COMMAND:
+               fprintf(stderr, "ERROR: host does not support GET\n");
+               return (MDEC_ERROR);
+       default:
+               ABORT("print_response: UNKNOWN RESPONSE\n");
+               return (MDEC_ERROR);
+       }
+}
+
+int
+main(int argc, char **argv)
+{
+       mdata_proto_t *mdp;
+       mdata_response_t mdr;
+       string_t *data;
+       const char *errmsg = NULL;
+
+       if (argc < 2) {
+               errx(MDEC_USAGE_ERROR, "Usage: %s <keyname>", argv[0]);
+       }
+
+       if (proto_init(&mdp, &errmsg) != 0) {
+               fprintf(stderr, "ERROR: could not initialise protocol: %s\n",
+                   errmsg);
+               return (MDEC_ERROR);
+       }
+
+       keyname = strdup(argv[1]);
+
+       if (proto_execute(mdp, "GET", keyname, &mdr, &data) != 0) {
+               fprintf(stderr, "ERROR: could not execute GET\n");
+               return (MDEC_ERROR);
+       }
+
+       return (print_response(mdr, data));
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/mdata_list.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/mdata_list.c       Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+
+#include "common.h"
+#include "dynstr.h"
+#include "plat.h"
+#include "proto.h"
+
+typedef enum mdata_exit_codes {
+       MDEC_SUCCESS = 0,
+       MDEC_NOTFOUND = 1,
+       MDEC_ERROR = 2,
+       MDEC_USAGE_ERROR = 3,
+       MDEC_TRY_AGAIN = 10
+} mdata_exit_codes_t;
+
+static int
+print_response(mdata_response_t mdr, string_t *data)
+{
+       const char *cstr = dynstr_cstr(data);
+       size_t len = dynstr_len(data);
+
+       switch (mdr) {
+       case MDR_SUCCESS:
+               fprintf(stdout, "%s", cstr);
+               if (len >= 1 && cstr[len - 1] != '\n')
+                       fprintf(stdout, "\n");
+               return (MDEC_SUCCESS);
+       case MDR_NOTFOUND:
+               fprintf(stderr, "No metadata\n");
+               return (MDEC_NOTFOUND);
+       case MDR_UNKNOWN:
+               fprintf(stderr, "Error getting metadata: %s\n", cstr);
+               return (MDEC_ERROR);
+       case MDR_INVALID_COMMAND:
+               fprintf(stderr, "ERROR: host does not support KEYS\n");
+               return (MDEC_ERROR);
+       default:
+               ABORT("print_response: UNKNOWN RESPONSE\n");
+               return (MDEC_ERROR);
+       }
+}
+
+int
+main(int argc __UNUSED, char **argv __UNUSED)
+{
+       mdata_proto_t *mdp;
+       mdata_response_t mdr;
+       string_t *data;
+       const char *errmsg = NULL;
+
+       if (proto_init(&mdp, &errmsg) != 0) {
+               fprintf(stderr, "ERROR: could not initialise protocol: %s\n",
+                   errmsg);
+               return (MDEC_ERROR);
+       }
+
+       if (proto_execute(mdp, "KEYS", NULL, &mdr, &data) != 0) {
+               fprintf(stderr, "ERROR: could not execute KEYS\n");
+               return (MDEC_ERROR);
+       }
+
+       return (print_response(mdr, data));
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/mdata_put.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/mdata_put.c        Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+
+#include "common.h"
+#include "dynstr.h"
+#include "plat.h"
+#include "proto.h"
+#include "base64.h"
+
+typedef enum mdata_exit_codes {
+       MDEC_SUCCESS = 0,
+       MDEC_NOTFOUND = 1,
+       MDEC_ERROR = 2,
+       MDEC_USAGE_ERROR = 3,
+       MDEC_TRY_AGAIN = 10
+} mdata_exit_codes_t;
+
+static char *keyname;
+
+static int
+print_response(mdata_response_t mdr, string_t *data)
+{
+       switch (mdr) {
+       case MDR_SUCCESS:
+               return (MDEC_SUCCESS);
+       case MDR_NOTFOUND:
+               fprintf(stderr, "No metadata for '%s'\n", keyname);
+               return (MDEC_NOTFOUND);
+       case MDR_UNKNOWN:
+               fprintf(stderr, "Error putting metadata for key '%s': %s\n",
+                   keyname, dynstr_cstr(data));
+               return (MDEC_ERROR);
+       case MDR_INVALID_COMMAND:
+               fprintf(stderr, "ERROR: host does not support PUT\n");
+               return (MDEC_ERROR);
+       default:
+               ABORT("print_response: UNKNOWN RESPONSE\n");
+               return (MDEC_ERROR);
+       }
+}
+
+int
+main(int argc, char **argv)
+{
+       mdata_proto_t *mdp;
+       mdata_response_t mdr;
+       string_t *data;
+       const char *errmsg = NULL;
+       string_t *req = dynstr_new();
+
+       if (argc < 2) {
+               errx(MDEC_USAGE_ERROR, "Usage: %s <keyname> [ <value> ]",
+                   argv[0]);
+       }
+
+       if (proto_init(&mdp, &errmsg) != 0) {
+               fprintf(stderr, "ERROR: could not initialise protocol: %s\n",
+                   errmsg);
+               return (MDEC_ERROR);
+       }
+
+       if (proto_version(mdp) < 2) {
+               fprintf(stderr, "ERROR: host does not support PUT\n");
+               return (MDEC_ERROR);
+       }
+
+       keyname = strdup(argv[1]);
+
+       base64_encode(argv[1], strlen(argv[1]), req);
+       dynstr_appendc(req, ' ');
+       if (argc >= 3) {
+               /*
+                * Use second argument as the value to put.
+                */
+               base64_encode(argv[2], strlen(argv[2]), req);
+       } else {
+               int c;
+               string_t *stdinstr = dynstr_new();
+
+               dynstr_append(stdinstr, "");
+
+               if (plat_is_interactive()) {
+                       fprintf(stderr, "ERROR: either specify the metadata "
+                           "value as the second command-line argument, or "
+                           "pipe content to stdin.\n");
+                       return (MDEC_ERROR);
+               }
+
+               while ((c = fgetc(stdin)) != EOF) {
+                       dynstr_appendc(stdinstr, (char) c);
+               }
+               if (ferror(stdin)) {
+                       fprintf(stderr, "ERROR: could not read from stdin: "
+                           "%s\n", strerror(errno));
+                       return (MDEC_ERROR);
+               }
+
+               base64_encode(dynstr_cstr(stdinstr), dynstr_len(stdinstr),
+                   req);
+               dynstr_free(stdinstr);
+       }
+
+       if (proto_execute(mdp, "PUT", dynstr_cstr(req), &mdr, &data) != 0) {
+               fprintf(stderr, "ERROR: could not execute GET\n");
+               return (MDEC_ERROR);
+       }
+
+       dynstr_free(req);
+
+       return (print_response(mdr, data));
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/plat.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/plat.h     Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#ifndef _PLAT_H
+#define        _PLAT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "dynstr.h"
+
+typedef struct mdata_plat mdata_plat_t;
+
+int plat_is_interactive(void);
+
+/*int open_metadata_stream(FILE **fp, char **err);*/
+int plat_init(mdata_plat_t **, const char **er, int *);
+int plat_recv(mdata_plat_t *, string_t *, int);
+int plat_send(mdata_plat_t *, string_t *);
+void plat_fini(mdata_plat_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PLAT_H */
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/plat/bsd.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/plat/bsd.c Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <sys/event.h>
+
+#include "common.h"
+#include "plat.h"
+#include "dynstr.h"
+#include "plat/unix_common.h"
+
+#if defined(__NetBSD__)
+#define        SERIAL_DEVICE   "/dev/tty01"
+#elif defined(__OpenBSD__)
+#define        SERIAL_DEVICE   "/dev/cua01"
+#else
+#define        SERIAL_DEVICE   "/dev/cuau1"
+#endif
+
+typedef struct mdata_plat {
+       int mpl_kq;
+       int mpl_conn;
+
+       struct kevent mpl_ev;
+} mdata_plat_t;
+
+
+int
+plat_send(mdata_plat_t *mpl, string_t *data)
+{
+       int len = dynstr_len(data);
+
+       if (write(mpl->mpl_conn, dynstr_cstr(data), len) != len)
+               return (-1);
+
+       return (0);
+}
+
+int
+plat_recv(mdata_plat_t *mpl, string_t *data, int timeout_ms)
+{
+       struct timespec timeout = { (time_t)(timeout_ms/1000), 0 };
+
+       for (;;) {
+               struct kevent mpl_ch;
+               int nch;
+
+               nch = kevent(mpl->mpl_kq, &mpl->mpl_ev, 1, &mpl_ch, 1, 
&timeout);
+
+               if (nch == -1) {
+                       fprintf(stderr, "kqueue error: %d\n", errno);
+                       if (errno == EINTR) {
+                               return (-1);
+                       }
+                       err(1, "KQUEUE_WAIT ERROR");
+               }
+
+               if (nch == 0) {
+                       fprintf(stderr, "plat_recv timeout\n");
+                       return (-1);
+               }
+
+               if (mpl_ch.flags & EV_ERROR) {
+                       fprintf(stderr, "EV_ERROR\n");
+                       return (-1);
+               }
+               if (mpl_ch.flags & EV_EOF) {
+                       fprintf(stderr, "EV_EOF\n");
+                       return (-1);
+               }
+               if (nch > 0) {
+                       char buf[2];
+                       ssize_t sz;
+
+                       if ((sz = read(mpl->mpl_conn, buf, 1)) > 0) {
+                               if (buf[0] == '\n') {
+                                       return (0);
+                               } else {
+                                       buf[1] = '\0';
+                                       dynstr_append(data, buf);
+                               }
+                       }
+               }
+       }
+
+       return (-1);
+}
+
+void
+plat_fini(mdata_plat_t *mpl)
+{
+       if (mpl != NULL) {
+               if (mpl->mpl_kq != -1)
+                       (void) close(mpl->mpl_kq);
+               if (mpl->mpl_conn != -1)
+                       (void) close(mpl->mpl_conn);
+               free(mpl);
+       }
+}
+
+static int
+plat_send_reset(mdata_plat_t *mpl)
+{
+       int ret = -1;
+       string_t *str = dynstr_new();
+
+       dynstr_append(str, "\n");
+       if (plat_send(mpl, str) != 0)
+               goto bail;
+       dynstr_reset(str);
+
+       if (plat_recv(mpl, str, 2000) != 0)
+               goto bail;
+
+       if (strcmp(dynstr_cstr(str), "invalid command") != 0)
+               goto bail;
+
+       ret = 0;
+
+bail:
+       dynstr_free(str);
+       return (ret);
+}
+
+int
+plat_is_interactive(void)
+{
+       return (unix_is_interactive());
+}
+
+int
+plat_init(mdata_plat_t **mplout, const char **errmsg, int *permfail)
+{
+       mdata_plat_t *mpl = NULL;
+
+       if ((mpl = calloc(1, sizeof (*mpl))) == NULL) {
+               *errmsg = "Could not allocate memory.";
+               *permfail = 1;
+               goto bail;
+       }
+       mpl->mpl_kq = -1;
+       mpl->mpl_conn = -1;
+
+       if ((mpl->mpl_kq = kqueue()) == -1) {
+               *errmsg = "Could not create kqueue fd.";
+               *permfail = 1;
+               goto bail;
+       }
+
+       if (unix_open_serial(SERIAL_DEVICE, &mpl->mpl_conn, errmsg,
+           permfail) != 0) {
+               goto bail;
+       }
+
+       EV_SET(&mpl->mpl_ev, mpl->mpl_conn, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 
0, 0);
+
+       if (plat_send_reset(mpl) == -1) {
+               *errmsg = "Could not do active reset.";
+               goto bail;
+       }
+
+       *mplout = mpl;
+
+       return (0);
+
+bail:
+       plat_fini(mpl);
+       return (-1);
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/plat/linux.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/plat/linux.c       Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <termios.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <sys/epoll.h>
+
+#include "common.h"
+#include "plat.h"
+#include "dynstr.h"
+#include "plat/unix_common.h"
+
+#define        SERIAL_DEVICE   "/dev/ttyS1"
+
+struct mdata_plat {
+       int mpl_epoll;
+       int mpl_conn;
+};
+
+
+int
+plat_send(mdata_plat_t *mpl, string_t *data)
+{
+       int len = dynstr_len(data);
+
+       if (write(mpl->mpl_conn, dynstr_cstr(data), len) != len)
+               return (-1);
+
+       return (0);
+}
+
+int
+plat_recv(mdata_plat_t *mpl, string_t *data, int timeout_ms)
+{
+       for (;;) {
+               struct epoll_event event;
+
+               if (epoll_wait(mpl->mpl_epoll, &event, 1, timeout_ms) == -1) {
+                       fprintf(stderr, "epoll error: %d\n", errno);
+                       if (errno == EINTR) {
+                               return (-1);
+                       }
+                       err(1, "EPOLL_WAIT ERROR");
+               }
+
+               if (event.data.fd == 0 || event.events == 0) {
+                       fprintf(stderr, "plat_recv timeout\n");
+                       return (-1);
+               }
+
+               if (event.events & EPOLLIN) {
+                       char buf[2];
+                       ssize_t sz;
+
+                       if ((sz = read(mpl->mpl_conn, buf, 1)) > 0) {
+                               if (buf[0] == '\n') {
+                                       return (0);
+                               } else {
+                                       buf[1] = '\0';
+                                       dynstr_append(data, buf);
+                               }
+                       }
+               }
+               if (event.events & EPOLLERR) {
+                       fprintf(stderr, "POLLERR\n");
+                       return (-1);
+               }
+               if (event.events & EPOLLHUP) {
+                       fprintf(stderr, "POLLHUP\n");
+                       return (-1);
+               }
+       }
+
+       return (-1);
+}
+
+void
+plat_fini(mdata_plat_t *mpl)
+{
+       if (mpl != NULL) {
+               if (mpl->mpl_epoll != -1)
+                       (void) close(mpl->mpl_epoll);
+               if (mpl->mpl_conn != -1)
+                       (void) close(mpl->mpl_conn);
+               free(mpl);
+       }
+}
+
+static int
+plat_send_reset(mdata_plat_t *mpl)
+{
+       int ret = -1;
+       string_t *str = dynstr_new();
+
+       dynstr_append(str, "\n");
+       if (plat_send(mpl, str) != 0)
+               goto bail;
+       dynstr_reset(str);
+
+       if (plat_recv(mpl, str, 2000) != 0)
+               goto bail;
+
+       if (strcmp(dynstr_cstr(str), "invalid command") != 0)
+               goto bail;
+
+       ret = 0;
+
+bail:
+       dynstr_free(str);
+       return (ret);
+}
+
+int
+plat_is_interactive(void)
+{
+       return (unix_is_interactive());
+}
+
+int
+plat_init(mdata_plat_t **mplout, const char **errmsg, int *permfail)
+{
+       mdata_plat_t *mpl = NULL;
+       struct epoll_event event;
+
+       if ((mpl = calloc(1, sizeof (*mpl))) == NULL) {
+               *errmsg = "Could not allocate memory.";
+               *permfail = 1;
+               goto bail;
+       }
+       mpl->mpl_epoll = -1;
+       mpl->mpl_conn = -1;
+
+       if ((mpl->mpl_epoll = epoll_create(1)) == -1) {
+               *errmsg = "Could not create epoll fd.";
+               *permfail = 1;
+               goto bail;
+       }
+
+       if (unix_open_serial(SERIAL_DEVICE, &mpl->mpl_conn, errmsg,
+           permfail) != 0) {
+               goto bail;
+       }
+
+       event.data.fd = mpl->mpl_conn;
+       event.events = EPOLLIN | EPOLLERR | EPOLLHUP;
+
+       if (epoll_ctl(mpl->mpl_epoll, EPOLL_CTL_ADD, mpl->mpl_conn,
+           &event) == -1) {
+               *errmsg = "Could not add conn to epoll context.";
+               *permfail = 1;
+               goto bail;
+       }
+
+       if (plat_send_reset(mpl) == -1) {
+               *errmsg = "Could not do active reset.";
+               goto bail;
+       }
+
+       *mplout = mpl;
+
+       return (0);
+
+bail:
+       plat_fini(mpl);
+       return (-1);
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/plat/sunos.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/plat/sunos.c       Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2015, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <err.h>
+#include <smbios.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <termios.h>
+#include <zone.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/filio.h>
+#include <port.h>
+
+#include "common.h"
+#include "dynstr.h"
+#include "plat.h"
+#include "plat/unix_common.h"
+
+#define        IN_GLOBAL_DEVICE        "/dev/term/b"
+
+static char *zone_md_socket_paths[] = {
+       "/.zonecontrol/metadata.sock",          /* SDC7 */
+       "/native/.zonecontrol/metadata.sock",   /* SDC7+LX */
+       "/var/run/smartdc/metadata.sock",       /* SDC6 */
+       NULL
+};
+
+struct mdata_plat {
+       int mpl_port;
+       int mpl_conn;
+};
+
+static int
+find_product(smbios_hdl_t *shp, const smbios_struct_t *sp, void *arg)
+{
+       char **outputp = arg;
+       smbios_info_t info;
+
+       if (sp->smbstr_type != SMB_TYPE_SYSTEM)
+               return (0);
+
+       if (smbios_info_common(shp, sp->smbstr_id, &info) != 0)
+               return (0);
+
+       if (info.smbi_product[0] != '\0') {
+               *outputp = strdup(info.smbi_product);
+       }
+
+       return (0);
+}
+
+static char *
+get_product_string(void)
+{
+       char *output = NULL;
+       int e;
+       smbios_hdl_t *shp;
+
+       if ((shp = smbios_open(NULL, SMB_VERSION, 0, &e)) == NULL) {
+               return (NULL);
+       }
+
+       smbios_iter(shp, find_product, &output);
+
+       smbios_close(shp);
+
+       return (output);
+}
+
+static int
+find_md_ngz(const char **out, int *permfail)
+{
+       int i;
+       struct stat st;
+
+       /*
+        * The location of the metadata socket has changed between SDC6
+        * and SDC7.  Attempt to locate the one that exists in this instance:
+        */
+       for (i = 0; zone_md_socket_paths[i] != NULL; i++) {
+               if (lstat(zone_md_socket_paths[i], &st) == 0 &&
+                   S_ISSOCK(st.st_mode)) {
+                       *out = zone_md_socket_paths[i];
+                       return (0);
+               } else {
+                       /*
+                        * If we're not root, and we get an EACCES, it's
+                        * often a permissions problem.  Don't retry
+                        * forever:
+                        */
+                       if (geteuid() != 0 && (errno == EPERM ||
+                           errno == EACCES))
+                               *permfail = 1;
+               }
+       }
+
+       return (-1);
+}
+
+static int
+open_md_ngz(int *outfd, char **errmsg, int *permfail)
+{
+       /*
+        * We're in a non-global zone, so try and connect to the
+        * metadata socket:
+        */
+       long on = 1L;
+       int fd;
+       const char *sockpath;
+       struct sockaddr_un ua;
+
+       /*
+        * This is not always a permanent failure, because the metadata
+        * socket might not exist yet.  Keep trying and wait for it to
+        * appear.
+        */
+       if (find_md_ngz(&sockpath, permfail) == -1) {
+               *errmsg = "Could not find metadata socket.";
+               return (-1);
+       }
+
+       if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+               *errmsg = "Could not open metadata socket.";
+               *permfail = 1;
+               return (-1);
+       }
+
+       /*
+        * Enable non-blocking I/O on the socket so that we can time-out
+        * when we want to:
+        */
+       if (ioctl(fd, (int)FIONBIO, &on) != 0) {
+               *errmsg = "Could not set non-blocking I/O on socket.";
+               (void) close(fd);
+               *permfail = 1;
+               return (-1);
+       }
+
+       bzero(&ua, sizeof (ua));
+       ua.sun_family = AF_UNIX;
+       strcpy(ua.sun_path, sockpath);
+
+       if (connect(fd, (struct sockaddr *)&ua, sizeof (ua)) == -1) {
+               (void) close(fd);
+               *errmsg = "Could not connect metadata socket.";
+               return (-1);
+       }
+
+       *outfd = fd;
+
+       return (0);
+}
+
+static int
+open_md_gz(int *outfd, char **errmsg, int *permfail)
+{
+       /*
+        * We're in a global zone in a SmartOS KVM/QEMU instance, so
+        * try to use /dev/term/b for metadata.
+        */
+
+       return (unix_open_serial(IN_GLOBAL_DEVICE, outfd, errmsg, permfail));
+}
+
+int
+plat_send(mdata_plat_t *mpl, string_t *data)
+{
+       int len = dynstr_len(data);
+
+       if (write(mpl->mpl_conn, dynstr_cstr(data), len) != len)
+               return (-1);
+
+       return (0);
+}
+
+int
+plat_recv(mdata_plat_t *mpl, string_t *data, int timeout_ms)
+{
+       port_event_t pev;
+       timespec_t tv;
+
+       for (;;) {
+               if (port_associate(mpl->mpl_port, PORT_SOURCE_FD, mpl->mpl_conn,
+                   POLLIN | POLLERR | POLLHUP , NULL) != 0) {
+                       fprintf(stderr, "port_associate error: %s\n",
+                           strerror(errno));
+                       return (-1);
+               }
+
+               tv.tv_sec = timeout_ms / 1000;
+               timeout_ms -= tv.tv_sec * 1000;
+               tv.tv_nsec = timeout_ms * 1000 * 1000; /* 100ms */
+
+               if (port_get(mpl->mpl_port, &pev, &tv) == -1) {
+                       if (errno == ETIME) {
+                               fprintf(stderr, "plat_recv timeout\n");
+                               return (-1);
+                       }
+                       fprintf(stderr, "port_get error: %s\n",
+                           strerror(errno));
+                       return (-1);
+               }
+
+               if (pev.portev_events & POLLIN) {
+                       char buf[2];
+                       ssize_t sz;
+
+                       if ((sz = read(mpl->mpl_conn, buf, 1)) > 0) {
+                               if (buf[0] == '\n') {
+                                       return (0);
+                               } else {
+                                       buf[1] = '\0';
+                                       dynstr_append(data, buf);
+                               }
+                       }
+               }
+               if (pev.portev_events & POLLERR) {
+                       fprintf(stderr, "POLLERR\n");
+                       return (-1);
+               }
+               if (pev.portev_events & POLLHUP) {
+                       fprintf(stderr, "POLLHUP\n");
+                       return (-1);
+               }
+       }
+
+       return (-1);
+}
+
+void
+plat_fini(mdata_plat_t *mpl)
+{
+       if (mpl != NULL) {
+               if (mpl->mpl_port != -1)
+                       (void) close(mpl->mpl_port);
+               if (mpl->mpl_conn != -1)
+                       (void) close(mpl->mpl_conn);
+               free(mpl);
+       }
+}
+
+static int
+plat_send_reset(mdata_plat_t *mpl)
+{
+       int ret = -1;
+       string_t *str = dynstr_new();
+
+       dynstr_append(str, "\n");
+
+       if (plat_send(mpl, str) != 0)
+               goto bail;
+       dynstr_reset(str);
+
+       if (plat_recv(mpl, str, 2000) != 0)
+               goto bail;
+
+       if (strcmp(dynstr_cstr(str), "invalid command") != 0)
+               goto bail;
+
+       ret = 0;
+
+bail:
+       dynstr_free(str);
+       return (ret);
+}
+
+int
+plat_is_interactive(void)
+{
+       return (unix_is_interactive());
+}
+
+int
+plat_init(mdata_plat_t **mplout, const char **errmsg, int *permfail)
+{
+       char *product;
+       boolean_t smartdc_hvm_guest = B_FALSE;
+       mdata_plat_t *mpl = NULL;
+
+       if ((mpl = calloc(1, sizeof (*mpl))) == NULL) {
+               *errmsg = "Could not allocate memory.";
+               *permfail = 1;
+               goto bail;
+       }
+       mpl->mpl_port = -1;
+       mpl->mpl_conn = -1;
+
+       if ((mpl->mpl_port = port_create()) == -1) {
+               *errmsg = "Could not create event port.";
+               *permfail = 1;
+               goto bail;
+       }
+
+       if (getzoneid() != GLOBAL_ZONEID) {
+               if (open_md_ngz(&mpl->mpl_conn, errmsg, permfail) != 0)
+                       goto bail;
+               goto wrapfd;
+       }
+
+       /*
+        * Interrogate the SMBIOS data from the system to see if we're
+        * in a KVM/QEMU virtual machine:
+        */
+       product = get_product_string();
+       if (product != NULL && strcmp(product, "SmartDC HVM") == 0)
+               smartdc_hvm_guest = B_TRUE;
+       free(product);
+
+       if (smartdc_hvm_guest) {
+               if (open_md_gz(&mpl->mpl_conn, errmsg, permfail) != 0)
+                       goto bail;
+               goto wrapfd;
+       }
+
+       /*
+        * We have no idea.
+        */
+       *errmsg = "I don't know how to get metadata on this system.";
+       *permfail = 1;
+       goto bail;
+
+wrapfd:
+       if (plat_send_reset(mpl) == -1) {
+               *errmsg = "Could not do active reset.";
+               goto bail;
+       }
+
+       *mplout = mpl;
+
+       return (0);
+
+bail:
+       plat_fini(mpl);
+       return (-1);
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/plat/unix_common.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/plat/unix_common.c Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <err.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <termios.h>
+
+#include "common.h"
+#include "plat.h"
+#include "dynstr.h"
+#include "unix_common.h"
+
+int
+unix_is_interactive(void)
+{
+       return (isatty(STDIN_FILENO) == 1);
+}
+
+static int
+unix_raw_mode(int fd, const char **errmsg)
+{
+       struct termios tios;
+
+       if (tcgetattr(fd, &tios) == -1) {
+               *errmsg = "could not set raw mode on serial device";
+               return (-1);
+       }
+
+       tios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+       tios.c_oflag &= ~(OPOST);
+       tios.c_cflag |= (CS8);
+       tios.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
+
+       /*
+        * As described in "Case C: MIN = 0, TIME > 0" of termio(7I), this
+        * configuration will block waiting for at least one character, or
+        * the expiry of a 100 millisecond timeout:
+        */
+       tios.c_cc[VMIN] = 0;
+       tios.c_cc[VTIME] = 1;
+
+       if (tcsetattr(fd, TCSAFLUSH, &tios) == -1) {
+               *errmsg = "could not get attributes from serial device";
+               return (-1);
+       }
+
+       return (0);
+}
+
+int
+unix_open_serial(const char *devpath, int *outfd, const char **errmsg, int 
*permfail)
+{
+       int fd;
+       char scrap[100];
+       ssize_t sz;
+       struct flock l;
+
+       if ((fd = open(devpath, O_RDWR | O_EXCL |
+           O_NOCTTY)) == -1) {
+               *errmsg = "Could not open serial device.";
+               if (errno != EAGAIN && errno != EBUSY && errno != EINTR)
+                       *permfail = 1;
+               return (-1);
+       }
+
+       /*
+        * Lock the serial port for exclusive access:
+        */
+       l.l_type = F_WRLCK;
+       l.l_whence = SEEK_SET;
+       l.l_start = l.l_len = 0;
+       if (fcntl(fd, F_SETLKW, &l) == -1) {
+               *errmsg = "Could not lock serial device.";
+               return (-1);
+       }
+
+       /*
+        * Set raw mode on the serial port:
+        */
+       if (unix_raw_mode(fd, errmsg) == -1) {
+               (void) close(fd);
+               *permfail = 1;
+               return (-1);
+       }
+
+       /*
+        * Because this is a shared serial line, we may be part way through
+        * a response from the remote peer.  Read (and discard) data until we
+        * cannot do so anymore:
+        */
+       do {
+               sz = read(fd, &scrap, sizeof (scrap));
+
+               if (sz == -1 && errno != EAGAIN) {
+                       *errmsg = "Failed to flush serial port before use.";
+                       (void) close(fd);
+                       return (-1);
+               }
+
+       } while (sz > 0);
+
+       *outfd = fd;
+
+       return (0);
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/plat/unix_common.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/plat/unix_common.h Fri Oct 27 15:13:22 
2017 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#ifndef _UNIX_COMMON_H
+#define        _UNIX_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "plat.h"
+#include "dynstr.h"
+
+int unix_open_serial(const char *devpath, int *outfd, const char **errmsg, int 
*permfail);
+int unix_send_reset(mdata_plat_t *mpl);
+int unix_is_interactive(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UNIX_COMMON_H */
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/proto.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/proto.c    Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+
+#include "common.h"
+#include "dynstr.h"
+#include "plat.h"
+#include "proto.h"
+#include "reqid.h"
+#include "crc32.h"
+#include "base64.h"
+
+/*
+ * Receive timeout used prior to V2 negotiation:
+ */
+#define        RECV_TIMEOUT_MS         6000
+/*
+ * Receive timeout once we've successfully negotiated the V2 protocol with the
+ * host.  Some V2 operations, like PUT, can take longer than 6 seconds to
+ * complete.
+ */
+#define        RECV_TIMEOUT_MS_V2      45000
+
+typedef enum mdata_proto_state {
+       MDPS_MESSAGE_HEADER = 1,
+       MDPS_MESSAGE_DATA,
+       MDPS_MESSAGE_V2,
+       MDPS_READY,
+       MDPS_ERROR
+} mdata_proto_state_t;
+
+typedef enum mdata_proto_version {
+       MDPV_VERSION_1 = 1,
+       MDPV_VERSION_2 = 2
+} mdata_proto_version_t;
+
+typedef struct mdata_command {
+       char mdc_reqid[REQID_LEN];
+       string_t *mdc_request;
+       string_t *mdc_response_data;
+       mdata_response_t mdc_response;
+       int mdc_done;
+} mdata_command_t;
+
+struct mdata_proto {
+       mdata_plat_t *mdp_plat;
+       mdata_command_t *mdp_command;
+       mdata_proto_state_t mdp_state;
+       mdata_proto_version_t mdp_version;
+       boolean_t mdp_in_reset;
+       const char *mdp_errmsg;
+       const char *mdp_parse_errmsg;
+};
+
+static int proto_send(mdata_proto_t *mdp);
+static int proto_recv(mdata_proto_t *mdp);
+
+static int
+proto_negotiate(mdata_proto_t *mdp)
+{
+       mdata_command_t *mdcsave;
+       mdata_response_t mdr;
+       string_t *rdata = NULL;
+       int ret = -1;
+
+       mdcsave = mdp->mdp_command;
+       mdp->mdp_command = NULL;
+
+       /*
+        * Assume Protocol Version 1 until we negotiate up to Version 2.
+        */
+       mdp->mdp_version = MDPV_VERSION_1;
+
+       if (proto_execute(mdp, "NEGOTIATE", "V2", &mdr, &rdata) == 0) {
+               if (mdr == MDR_V2_OK)
+                       mdp->mdp_version = MDPV_VERSION_2;
+
+               ret = 0;
+       }
+
+       mdp->mdp_command = mdcsave;
+       if (rdata != NULL)
+               dynstr_free(rdata);
+       return (ret);
+}
+
+static int
+proto_reset(mdata_proto_t *mdp)
+{
+       int permfail = 0;
+
+       /*
+        * Prevent proto_execute() from calling back into proto_reset()
+        * while we're resetting:
+        */
+       mdp->mdp_in_reset = B_TRUE;
+
+retry:
+       mdp->mdp_errmsg = NULL;
+
+       /*
+        * Close our existing platform-specific code handle if we have
+        * one open:
+        */
+       if (mdp->mdp_plat != NULL) {
+               plat_fini(mdp->mdp_plat);
+               mdp->mdp_plat = NULL;
+       }
+
+       mdp->mdp_state = MDPS_READY;
+
+       /*
+        * Initialise the platform-specific code:
+        */
+       if (plat_init(&mdp->mdp_plat, &mdp->mdp_errmsg, &permfail) == -1) {
+               if (permfail) {
+                       return (-1);
+               } else {
+                       sleep(1);
+                       goto retry;
+               }
+       }
+
+       /*
+        * Determine what protocol our host supports:
+        */
+       if (proto_negotiate(mdp) == -1) {
+               sleep(1);
+               goto retry;
+       }
+
+       mdp->mdp_in_reset = B_FALSE;
+       mdp->mdp_errmsg = NULL;
+       return (0);
+}
+
+static int
+proto_parse_v2(mdata_proto_t *mdp, string_t *input, string_t *request_id,
+    string_t *command, string_t *response_data)
+{
+       const char *endp = dynstr_cstr(input);
+       char *endp2;
+       unsigned long clen;
+       uint32_t crc32;
+
+       mdp->mdp_parse_errmsg = NULL;
+
+       if (strstr(endp, "V2 ") != endp) {
+               mdp->mdp_parse_errmsg = "message did not start with V2";
+               return (-1);
+       }
+       endp += 3;
+
+       /*
+        * Read Content Length:
+        */
+       if ((clen = strtoul(endp, &endp2, 10)) == 0) {
+               mdp->mdp_parse_errmsg = "invalid content length";
+               return (-1);
+       }
+       endp = endp2;
+
+       /*
+        * Skip whitespace:
+        */
+       while (*endp == ' ')
+               endp++;
+
+       /*
+        * Read CRC32 checksum:
+        */
+       if ((crc32 = strtoul(endp, &endp2, 16)) == 0) {
+               mdp->mdp_parse_errmsg = "invalid crc32 in frame";
+               return (-1);
+       }
+       endp = endp2;
+
+       /*
+        * Skip whitespace:
+        */
+       while (*endp == ' ')
+               endp++;
+
+       /*
+        * Ensure Content Length and CRC32 values from header match
+        * reality:
+        */
+       if (strlen(endp) != clen || crc32_calc(endp, clen) != crc32) {
+               mdp->mdp_parse_errmsg = "clen/crc32 mismatch";
+               return (-1);
+       }
+
+       /*
+        * Read Request ID:
+        */
+       while (*endp != ' ' && *endp != '\0') {
+               dynstr_appendc(request_id, *endp++);
+       }
+       if (dynstr_len(request_id) == 0) {
+               mdp->mdp_parse_errmsg = "missing request id";
+               return (-1);
+       }
+
+       /*
+        * Skip whitespace:
+        */
+       while (*endp == ' ')
+               endp++;
+
+       /*
+        * Read Command/Code:
+        */
+       while (*endp != ' ' && *endp != '\0') {
+               dynstr_appendc(command, *endp++);
+       }
+       if (dynstr_len(command) == 0) {
+               mdp->mdp_parse_errmsg = "missing command/code";
+               return (-1);
+       }
+
+       /*
+        * Skip Whitespace:
+        */
+       while (*endp == ' ')
+               endp++;
+
+       /*
+        * Read the Response Data:
+        */
+       if (base64_decode(endp, strlen(endp), response_data) == -1) {
+               mdp->mdp_parse_errmsg = "base64 error";
+               return (-1);
+       }
+
+       return (0);
+}
+
+static void
+process_input(mdata_proto_t *mdp, string_t *input)
+{
+       const char *cstr = dynstr_cstr(input);
+       string_t *command, *request_id;
+
+       switch (mdp->mdp_state) {
+       case MDPS_MESSAGE_V2:
+               command = dynstr_new();
+               request_id = dynstr_new();
+
+               dynstr_reset(mdp->mdp_command->mdc_response_data);
+
+               if (proto_parse_v2(mdp, input, request_id, command,
+                   mdp->mdp_command->mdc_response_data) == -1) {
+                       /*
+                        * XXX Presently, drop frames that we can't
+                        * parse.
+                        */
+
+               } else if (strcmp(dynstr_cstr(request_id),
+                   mdp->mdp_command->mdc_reqid) != 0) {
+                       /*
+                        * XXX Presently, drop frames that are not for
+                        * the currently outstanding request.
+                        */
+
+               } else if (strcmp(dynstr_cstr(command), "NOTFOUND") == 0) {
+                       mdp->mdp_state = MDPS_READY;
+                       mdp->mdp_command->mdc_response = MDR_NOTFOUND;
+                       mdp->mdp_command->mdc_done = 1;
+
+               } else if (strcmp(dynstr_cstr(command), "SUCCESS") == 0) {
+                       mdp->mdp_state = MDPS_READY;
+                       mdp->mdp_command->mdc_response = MDR_SUCCESS;
+                       mdp->mdp_command->mdc_done = 1;
+
+               } else {
+                       mdp->mdp_state = MDPS_READY;
+                       mdp->mdp_command->mdc_response = MDR_UNKNOWN;
+                       mdp->mdp_command->mdc_done = 1;
+               }
+
+               dynstr_free(command);
+               dynstr_free(request_id);
+               break;
+
+       case MDPS_MESSAGE_HEADER:
+               if (strcmp(cstr, "NOTFOUND") == 0) {
+                       mdp->mdp_state = MDPS_READY;
+                       mdp->mdp_command->mdc_response = MDR_NOTFOUND;
+                       mdp->mdp_command->mdc_done = 1;
+
+               } else if (strcmp(cstr, "SUCCESS") == 0) {
+                       mdp->mdp_state = MDPS_MESSAGE_DATA;
+                       mdp->mdp_command->mdc_response = MDR_SUCCESS;
+
+               } else if (strcmp(cstr, "V2_OK") == 0) {
+                       mdp->mdp_state = MDPS_READY;
+                       mdp->mdp_command->mdc_response = MDR_V2_OK;
+                       mdp->mdp_command->mdc_done = 1;
+
+               } else if (strcmp(cstr, "invalid command") == 0) {
+                       mdp->mdp_state = MDPS_READY;
+                       mdp->mdp_command->mdc_response = MDR_INVALID_COMMAND;
+                       mdp->mdp_command->mdc_done = 1;
+
+               } else {
+                       mdp->mdp_state = MDPS_READY;
+                       dynstr_append(mdp->mdp_command->mdc_response_data, 
cstr);
+                       mdp->mdp_command->mdc_response = MDR_UNKNOWN;
+                       mdp->mdp_command->mdc_done = 1;
+
+               }
+               break;
+
+       case MDPS_MESSAGE_DATA:
+               if (strcmp(cstr, ".") == 0) {
+                       mdp->mdp_state = MDPS_READY;
+                       mdp->mdp_command->mdc_done = 1;
+               } else {
+                       string_t *respdata = 
mdp->mdp_command->mdc_response_data;
+                       int offs = cstr[0] == '.' ? 1 : 0;
+                       if (dynstr_len(respdata) > 0)
+                               dynstr_append(respdata, "\n");
+                       dynstr_append(respdata, cstr + offs);
+               }
+               break;
+
+       case MDPS_READY:
+       case MDPS_ERROR:
+               break;
+
+       default:
+               ABORT("process_input: UNKNOWN STATE\n");
+       }
+}
+
+static int
+proto_send(mdata_proto_t *mdp)
+{
+       VERIFY(mdp->mdp_command);
+
+       if (plat_send(mdp->mdp_plat, mdp->mdp_command->mdc_request) == -1) {
+               mdp->mdp_state = MDPS_ERROR;
+               return (-1);
+       }
+
+       /*
+        * Wait for response header from remote peer:
+        */
+       switch (mdp->mdp_version) {
+       case MDPV_VERSION_1:
+               mdp->mdp_state = MDPS_MESSAGE_HEADER;
+               break;
+       case MDPV_VERSION_2:
+               mdp->mdp_state = MDPS_MESSAGE_V2;
+               break;
+       default:
+               ABORT("unknown protocol version");
+       }
+
+       return (0);
+}
+
+static int
+proto_recv(mdata_proto_t *mdp)
+{
+       int ret = -1;
+       string_t *line = dynstr_new();
+
+       for (;;) {
+               int recv_timeout_ms = mdp->mdp_version == MDPV_VERSION_2 ?
+                   RECV_TIMEOUT_MS_V2 : RECV_TIMEOUT_MS;
+
+               if (plat_recv(mdp->mdp_plat, line, recv_timeout_ms) == -1) {
+                       mdp->mdp_state = MDPS_ERROR;
+                       goto bail;
+               }
+
+               process_input(mdp, line);
+               dynstr_reset(line);
+
+               if (mdp->mdp_command->mdc_done)
+                       break;
+       }
+
+       ret = 0;
+
+bail:
+       dynstr_free(line);
+       return (ret);
+}
+
+/*
+ * Version 2 of the Metadata Protocol is, after a fashion, a framed
+ * protocol.  Each 'frame' is really just a LF-terminated line of
+ * text.  Request and Response payloads are BASE64-encoded to allow the
+ * transmission of embedded LFs, and other potentially binary data.
+ *
+ * The line format is as follows:
+ *                                            ,- Body (CRC32/Length is of
+ *                  _____________________ <--/         this string)
+ *   V2 21 265ae1d8 dc4fae17 SUCCESS W10=\n
+ *    ^ ^  ^        ^        ^       ^   ^
+ *    | |  |        |        |       |   \--- Terminating Linefeed.
+ *    | |  |        |        |       \------- BASE64-encoded payload.
+ *    | |  |        |        \--------------- Request Command or Response Code
+ *    | |  |        \------------------------ Request ID (8 random hex digits)
+ *    | |  \--------------------------------- CRC32 of Body as 8 hex digits
+ *    | \------------------------------------ Content Length of Body, base 10
+ *    \-------------------------------------- So that this can be a V1 command
+ *                                            as well, we start with "V2".
+ *                                            This will be a FAILURE on a
+ *                                            host that only supports the
+ *                                            V1 protocol.
+ */
+static void
+proto_make_request_v2(const char *command, const char *argument,
+    string_t *output, char *reqidbuf)
+{
+       char strbuf[23 + 1 + 8 + 1]; /* strlen(UINT64_MAX) + ' ' + %08x + \0 */
+       string_t *body = dynstr_new();
+
+       /*
+        * Generate the BODY of the V2 message, which is the portion we
+        * use when generating the Content Length and CRC32 checksum for
+        * the message HEADER.
+        */
+       dynstr_append(body, reqid(reqidbuf));
+       dynstr_append(body, " ");
+       dynstr_append(body, command);
+       if (argument != NULL) {
+               dynstr_append(body, " ");
+               base64_encode(argument, strlen(argument), body);
+       }
+
+       /*
+        * Generate the HEADER directly into the output, and then
+        * append the BODY:
+        */
+       dynstr_append(output, "V2 ");
+       sprintf(strbuf, "%u %08x", (unsigned int) dynstr_len(body), crc32_calc(
+           dynstr_cstr(body), dynstr_len(body)));
+       dynstr_append(output, strbuf);
+       dynstr_append(output, " ");
+       dynstr_append(output, dynstr_cstr(body));
+       dynstr_append(output, "\n");
+
+       dynstr_free(body);
+}
+
+static void
+proto_make_request_v1(const char *command, const char *argument,
+    string_t *output)
+{
+       dynstr_append(output, command);
+       if (argument != NULL) {
+               dynstr_append(output, " ");
+               dynstr_append(output, argument);
+       }
+       dynstr_append(output, "\n");
+}
+
+int
+proto_execute(mdata_proto_t *mdp, const char *command, const char *argument,
+    mdata_response_t *response, string_t **response_data)
+{
+       mdata_command_t mdc;
+
+       /*
+        * Initialise new command structure:
+        */
+       bzero(&mdc, sizeof (mdc));
+       mdc.mdc_request = dynstr_new();
+       mdc.mdc_response_data = dynstr_new();
+       mdc.mdc_response = MDR_PENDING;
+       mdc.mdc_done = 0;
+
+       VERIFY0(mdp->mdp_command);
+       mdp->mdp_command = &mdc;
+
+retry:
+       /*
+        * (Re-)generate request string to send to remote peer:
+        */
+       dynstr_reset(mdc.mdc_request);
+       switch (mdp->mdp_version) {
+       case MDPV_VERSION_1:
+               proto_make_request_v1(command, argument, mdc.mdc_request);
+               break;
+       case MDPV_VERSION_2:
+               proto_make_request_v2(command, argument, mdc.mdc_request,
+                   mdc.mdc_reqid);
+               break;
+       default:
+               ABORT("unknown protocol version");
+       }
+
+       /*
+        * Attempt to send the request to the remote peer:
+        */
+       if (mdp->mdp_state == MDPS_ERROR || proto_send(mdp) != 0 ||
+           proto_recv(mdp) != 0) {
+               /*
+                * Discard existing response data and reset the command
+                * state:
+                */
+               dynstr_reset(mdp->mdp_command->mdc_response_data);
+               mdc.mdc_response = MDR_PENDING;
+
+               /*
+                * If the command we're trying to send is part of a
+                * protocol reset sequence, just fail immediately:
+                */
+               if (mdp->mdp_in_reset)
+                       goto bail;
+
+               /*
+                * We could not send the request, so reset the stream
+                * and try again:
+                */
+               fprintf(stderr, "receive timeout, resetting "
+                   "protocol...\n");
+               if (proto_reset(mdp) == -1) {
+                       /*
+                        * We could not do a reset, so abort the whole
+                        * thing.
+                        */
+                       fprintf(stderr, "ERROR: while resetting connection: "
+                           "%s\n", mdp->mdp_errmsg);
+                       goto bail;
+               } else {
+                       /*
+                        * We were able to reset OK, so keep trying.
+                        */
+                       goto retry;
+               }
+       }
+
+       if (mdp->mdp_state != MDPS_READY)
+               ABORT("proto state not MDPS_READY\n");
+
+       /*
+        * We were able to send a command and receive a response.
+        * Examine the response and decide what to do:
+        */
+       *response = mdc.mdc_response;
+       *response_data = mdc.mdc_response_data;
+       dynstr_free(mdc.mdc_request);
+       mdp->mdp_command = NULL;
+       return (0);
+
+bail:
+       dynstr_free(mdc.mdc_request);
+       dynstr_free(mdc.mdc_response_data);
+       mdp->mdp_command = NULL;
+       return (-1);
+}
+
+int
+proto_version(mdata_proto_t *mdp)
+{
+       return (mdp->mdp_version);
+}
+
+int
+proto_init(mdata_proto_t **out, const char **errmsg)
+{
+       mdata_proto_t *mdp;
+
+       reqid_init();
+
+       if ((mdp = calloc(1, sizeof (*mdp))) == NULL)
+               return (-1);
+
+       if (proto_reset(mdp) == -1) {
+               *errmsg = mdp->mdp_errmsg;
+               free(mdp);
+               return (-1);
+       }
+
+       *out = mdp;
+
+       return (0);
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/proto.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/proto.h    Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#ifndef _PROTO_H
+#define        _PROTO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum mdata_response {
+       MDR_UNKNOWN = 1,
+       MDR_NOTFOUND,
+       MDR_SUCCESS,
+       MDR_INVALID_COMMAND,
+       MDR_PENDING,
+       MDR_V2_OK
+} mdata_response_t;
+
+typedef struct mdata_proto mdata_proto_t;
+
+int proto_init(mdata_proto_t **, const char **);
+int proto_version(mdata_proto_t *);
+int proto_execute(mdata_proto_t *, const char *, const char *, 
mdata_response_t *,
+    string_t **);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PROTO_H */
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/reqid.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/reqid.c    Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/uio.h>
+#include <time.h>
+
+#include "common.h"
+#include "reqid.h"
+
+static int urandom_fd = -1;
+
+char *
+reqid(char *buf)
+{
+       int i;
+       static int seed = -1;
+       uint32_t tmp = 0;
+
+       VERIFY(buf != NULL);
+
+       /*
+        * If we were able to open it, try and read a random request ID
+        * from /dev/urandom:
+        */
+       if (urandom_fd != -1) {
+               if (read(urandom_fd, &tmp, sizeof (tmp)) == sizeof (tmp))
+                       goto out;
+       }
+
+       /*
+        * Otherwise, fall back to C rand():
+        */
+       if (seed == -1) {
+               seed = (int) time(NULL);
+               srand(seed);
+
+       }
+       for (i = 0; i < 4; i++) {
+               tmp |= (0xff & (rand())) << (i * 8);
+       }
+
+out:
+       sprintf(buf, "%08x", tmp);
+       return (buf);
+}
+
+int
+reqid_init(void)
+{
+       if (urandom_fd == -1)
+               urandom_fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK);
+
+       return (0);
+}
+
+void
+reqid_fini(void)
+{
+       if (urandom_fd == -1)
+               return;
+
+       (void) close(urandom_fd);
+       urandom_fd = -1;
+}
diff -r 01e60b2f69c4 external/mit/mdata-client/dist/reqid.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/mit/mdata-client/dist/reqid.h    Fri Oct 27 15:13:22 2017 +0200
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013, Joyent, Inc.
+ * See LICENSE file for copyright and license details.
+ */
+
+#ifndef _REQID_H
+#define        _REQID_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define        REQID_LEN       9
+
+int reqid_init(void);
+void reqid_fini(void);
+char * reqid(char *buf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _REQID_H */


-------------------------------------------
smartos-discuss
Archives: https://www.listbox.com/member/archive/184463/=now
RSS Feed: https://www.listbox.com/member/archive/rss/184463/25769125-55cfbc00
Modify Your Subscription: 
https://www.listbox.com/member/?member_id=25769125&id_secret=25769125-7688e9fb
Powered by Listbox: http://www.listbox.com

Reply via email to