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