summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2017-04-28 21:22:39 +0000
committerRobert Mustacchi <rm@joyent.com>2017-05-01 18:30:08 +0000
commit0d296521ece3a5b488e6054f1d0af661aef90046 (patch)
tree3677c72342646417c1d448a512113f032e51a1ee
parent50ee30c219b9dac9fd4709209da6f16acc8da831 (diff)
downloadillumos-joyent-0d296521ece3a5b488e6054f1d0af661aef90046.tar.gz
OS-6089 want basic utility for Ethernet level 'pong'
Reviewed by: Ryan Zezeski <ryan.zeseski@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r--manifest2
-rw-r--r--usr/src/cmd/Makefile2
-rw-r--r--usr/src/cmd/dlutil/Makefile (renamed from usr/src/cmd/dltraninfo/Makefile)7
-rw-r--r--usr/src/cmd/dlutil/dlrecv.c237
-rw-r--r--usr/src/cmd/dlutil/dlsend.c163
-rw-r--r--usr/src/cmd/dlutil/dlsend.h45
-rw-r--r--usr/src/cmd/dlutil/dltraninfo.c (renamed from usr/src/cmd/dltraninfo/dltraninfo.c)0
7 files changed, 453 insertions, 3 deletions
diff --git a/manifest b/manifest
index 8d707578b7..3453406ad8 100644
--- a/manifest
+++ b/manifest
@@ -5177,6 +5177,8 @@ f usr/lib/devfsadm/linkmod/SUNW_zut_link.so 0755 root sys
f usr/lib/diff3prog 0555 root bin
f usr/lib/diffh 0555 root bin
d usr/lib/dl 0755 root sys
+f usr/lib/dl/dlrecv 0555 root bin
+f usr/lib/dl/dlsend 0555 root bin
f usr/lib/dl/dltraninfo 0555 root bin
f usr/lib/dscfglockd 0555 root bin
d usr/lib/dtrace 0755 root bin
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index ff21feeb89..af4ef3fb09 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -136,7 +136,7 @@ COMMON_SUBDIRS= \
dispadmin \
dladm \
dlstat \
- dltraninfo \
+ dlutil \
dmesg \
dodatadm \
dtrace \
diff --git a/usr/src/cmd/dltraninfo/Makefile b/usr/src/cmd/dlutil/Makefile
index d873ca3671..65382e3f91 100644
--- a/usr/src/cmd/dltraninfo/Makefile
+++ b/usr/src/cmd/dlutil/Makefile
@@ -13,13 +13,16 @@
# Copyright (c) 2017, Joyent, Inc.
#
-PROG= dltraninfo
+PROG= dltraninfo dlsend dlrecv
include ../Makefile.cmd
ROOTCMDDIR = $(ROOTLIB)/dl
CFLAGS += $(CCVERBOSE)
-LDLIBS += -ldladm
+
+dltraninfo := LDLIBS += -ldladm
+dlsend := LDLIBS += -ldlpi -lsocket -lmd
+dlrecv := LDLIBS += -ldlpi
ROOTLIBDLFILES = $(PROG:%=$(ROOTLIB)/dl/%)
diff --git a/usr/src/cmd/dlutil/dlrecv.c b/usr/src/cmd/dlutil/dlrecv.c
new file mode 100644
index 0000000000..4464baced9
--- /dev/null
+++ b/usr/src/cmd/dlutil/dlrecv.c
@@ -0,0 +1,237 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2017, Joyent, Inc.
+ */
+
+/*
+ * Receive a raw Ethernet frame from dlsend.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <strings.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <libdlpi.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <endian.h>
+#include <ctype.h>
+
+#include "dlsend.h"
+
+
+static uint_t dlrecv_sap = DLSEND_SAP;
+static const char *dlrecv_prog;
+
+static void
+dlrecv_warn(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void) fprintf(stderr, "%s: ", dlrecv_prog);
+ va_start(ap, fmt);
+ (void) vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+static void
+dlrecv_usage(const char *fmt, ...)
+{
+ if (fmt != NULL) {
+ va_list ap;
+
+ (void) fprintf(stderr, "%s: ", dlrecv_prog);
+ va_start(ap, fmt);
+ (void) vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
+
+ (void) fprintf(stderr, "Usage: %s [-s sap] device\n"
+ "\t-s sap\tspecify SAP to send on\n",
+ dlrecv_prog);
+}
+
+static boolean_t
+dlrecv_isvalid(dlsend_msg_t *msg)
+{
+ uint_t i;
+ boolean_t nul;
+
+ nul = B_FALSE;
+ for (i = 0; i < sizeof (msg->dm_host); i++) {
+ if (!isprint(msg->dm_host[i]) &&
+ msg->dm_host[i] != '\0') {
+ dlrecv_warn("Encountered bad byte in dm_host[%d]\n",
+ i);
+ return (B_FALSE);
+ }
+
+ if (msg->dm_host[i] == '\0')
+ nul = B_TRUE;
+ }
+
+ if (!nul) {
+ dlrecv_warn("Missing NUL in dm_host\n");
+ return (B_FALSE);
+ }
+
+ nul = B_FALSE;
+ for (i = 0; i < sizeof (msg->dm_mesg); i++) {
+ if (!isprint(msg->dm_mesg[i]) &&
+ msg->dm_mesg[i] != '\0') {
+ dlrecv_warn("Encountered bad byte in dm_mesg[%d]\n",
+ i);
+ return (B_FALSE);
+ }
+
+ if (msg->dm_mesg[i] == '\0')
+ nul = B_TRUE;
+ }
+
+ if (!nul) {
+ dlrecv_warn("Missing NUL in dm_mesg\n");
+ return (B_FALSE);
+ }
+
+ if (strcmp(msg->dm_mesg, DLSEND_MSG) != 0) {
+ dlrecv_warn("Missing expected message (%s)\n", DLSEND_MSG);
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
+static void
+dlrecv_print(dlsend_msg_t *msg, dlpi_recvinfo_t *rinfo, boolean_t invalid)
+{
+ uint_t i;
+
+ printf("Received %s from ", invalid ? "invalid message" : "Elbereth");
+
+ for (i = 0; i < rinfo->dri_destaddrlen; i++) {
+ (void) printf("%02x", rinfo->dri_destaddr[i]);
+ if (i + 1 != rinfo->dri_destaddrlen)
+ (void) putchar(':');
+ }
+
+ if (invalid) {
+ return;
+ }
+
+ printf(" seq=%" PRIu64 " host=%s\n", betoh64(msg->dm_count),
+ msg->dm_host);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c, ret;
+ char *eptr;
+ unsigned long sap;
+ uint_t bind_sap;
+ dlpi_handle_t dh;
+
+ dlrecv_prog = basename(argv[0]);
+
+ while ((c = getopt(argc, argv, ":s:")) != -1) {
+ switch (c) {
+ case 's':
+ errno = 0;
+ sap = strtoul(optarg, &eptr, 10);
+ if (errno != 0 || sap == 0 || sap >= UINT16_MAX ||
+ *eptr != '\0') {
+ dlrecv_usage("Invalid value for sap (-s): %s\n",
+ optarg);
+ return (2);
+ }
+ dlrecv_sap = sap;
+ break;
+ case ':':
+ dlrecv_usage("Option -%c requires an operand\n",
+ optopt);
+ return (2);
+ case '?':
+ dlrecv_usage("Unknown option: -%c\n", optopt);
+ return (2);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1) {
+ dlrecv_usage("missing required operands\n");
+ return (2);
+ }
+
+ if ((ret = dlpi_open(argv[0], &dh, 0)) != DLPI_SUCCESS) {
+ dlrecv_warn("failed to open %s: %s\n", argv[0],
+ dlpi_strerror(ret));
+ exit(1);
+ }
+
+ if ((ret = dlpi_bind(dh, dlrecv_sap, &bind_sap)) != DLPI_SUCCESS) {
+ dlrecv_warn("failed to bind to sap 0x%x: %s\n", dlrecv_sap,
+ dlpi_strerror(ret));
+ exit(1);
+ }
+
+ if (bind_sap != dlrecv_sap) {
+ dlrecv_warn("failed to bind to requested sap 0x%x, bound to "
+ "0x%x\n", dlrecv_sap, bind_sap);
+ exit(1);
+ }
+
+ for (;;) {
+ dlpi_recvinfo_t rinfo;
+ dlsend_msg_t msg;
+ size_t msglen;
+ boolean_t invalid = B_FALSE;
+
+ msglen = sizeof (msg);
+ ret = dlpi_recv(dh, NULL, NULL, &msg, &msglen, -1, &rinfo);
+ if (ret != DLPI_SUCCESS) {
+ dlrecv_warn("failed to receive data: %s\n",
+ dlpi_strerror(ret));
+ continue;
+ }
+
+ if (msglen != rinfo.dri_totmsglen) {
+ dlrecv_warn("message truncated: expected %ld bytes, "
+ "got %ld\n", sizeof (dlsend_msg_t),
+ rinfo.dri_totmsglen);
+ invalid = B_TRUE;
+ }
+
+ if (msglen != sizeof (msg)) {
+ dlrecv_warn("message too short: expected %ld bytes, "
+ "got %ld\n", sizeof (dlsend_msg_t),
+ msglen);
+ invalid = B_TRUE;
+ }
+
+ if (!invalid) {
+ invalid = !dlrecv_isvalid(&msg);
+ }
+
+ dlrecv_print(&msg, &rinfo, invalid);
+ }
+
+ return (0);
+}
diff --git a/usr/src/cmd/dlutil/dlsend.c b/usr/src/cmd/dlutil/dlsend.c
new file mode 100644
index 0000000000..e77d157f53
--- /dev/null
+++ b/usr/src/cmd/dlutil/dlsend.c
@@ -0,0 +1,163 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2017, Joyent, Inc.
+ */
+
+/*
+ * Send a raw Ethernet frame once a second to a specified MAC address.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <strings.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <libdlpi.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <endian.h>
+
+#include "dlsend.h"
+
+static uint_t dlsend_sap = DLSEND_SAP;
+static const char *dlsend_msg = DLSEND_MSG;
+static const char *dlsend_prog;
+
+static void
+dlsend_warn(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void) fprintf(stderr, "%s: ", dlsend_prog);
+ va_start(ap, fmt);
+ (void) vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+static void
+dlsend_usage(const char *fmt, ...)
+{
+ if (fmt != NULL) {
+ va_list ap;
+
+ (void) fprintf(stderr, "%s: ", dlsend_prog);
+ va_start(ap, fmt);
+ (void) vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ }
+
+ (void) fprintf(stderr, "Usage: %s [-s sap] device target-mac\n"
+ "\t-s sap\tspecify SAP to send on\n",
+ dlsend_prog);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int c, maclen, ret;
+ unsigned long sap;
+ char *eptr;
+ uchar_t *mac;
+ char host[MAXHOSTNAMELEN];
+ uint_t bind_sap;
+ dlpi_handle_t dh;
+ uint64_t count;
+
+ dlsend_prog = basename(argv[0]);
+
+ while ((c = getopt(argc, argv, ":s:")) != -1) {
+ switch (c) {
+ case 's':
+ errno = 0;
+ sap = strtoul(optarg, &eptr, 10);
+ if (errno != 0 || sap == 0 || sap >= UINT16_MAX ||
+ *eptr != '\0') {
+ dlsend_usage("Invalid value for sap (-s): %s\n",
+ optarg);
+ return (2);
+ }
+ dlsend_sap = sap;
+ break;
+ case ':':
+ dlsend_usage("Option -%c requires an operand\n",
+ optopt);
+ return (2);
+ case '?':
+ dlsend_usage("Unknown option: -%c\n", optopt);
+ return (2);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2) {
+ dlsend_usage("missing required operands\n");
+ return (2);
+ }
+
+ if ((mac = _link_aton(argv[1], &maclen)) == NULL) {
+ dlsend_warn("failed to convert target address %s\n", argv[1]);
+ return (1);
+ }
+
+ if (gethostname(host, sizeof (host)) != 0) {
+ dlsend_warn("failed to obtain the system hostname: %s\n",
+ strerror(errno));
+ (void) strlcpy(host, "<unknown host>", sizeof (host));
+ }
+
+ if ((ret = dlpi_open(argv[0], &dh, 0)) != DLPI_SUCCESS) {
+ dlsend_warn("failed to open %s: %s\n", argv[0],
+ dlpi_strerror(ret));
+ exit(1);
+ }
+
+ if ((ret = dlpi_bind(dh, dlsend_sap, &bind_sap)) != DLPI_SUCCESS) {
+ dlsend_warn("failed to bind to sap 0x%x: %s\n", dlsend_sap,
+ dlpi_strerror(ret));
+ exit(1);
+ }
+
+ if (bind_sap != dlsend_sap) {
+ dlsend_warn("failed to bind to requested sap 0x%x, bound to "
+ "0x%x\n", dlsend_sap, bind_sap);
+ exit(1);
+ }
+
+ count = 0;
+ for (;;) {
+ dlsend_msg_t msg;
+
+ count++;
+ bzero(&msg, sizeof (msg));
+ msg.dm_count = htobe64(count);
+ (void) strlcpy(msg.dm_host, host, sizeof (msg.dm_host));
+ (void) strlcpy(msg.dm_mesg, dlsend_msg, sizeof (msg.dm_mesg));
+ ret = dlpi_send(dh, mac, maclen, &msg, sizeof (msg), NULL);
+ if (ret != DLPI_SUCCESS) {
+ dlsend_warn("failed to send message: %s\n",
+ dlpi_strerror(ret));
+ exit(1);
+ }
+
+ sleep(1);
+ }
+
+ return (0);
+}
diff --git a/usr/src/cmd/dlutil/dlsend.h b/usr/src/cmd/dlutil/dlsend.h
new file mode 100644
index 0000000000..5674ff0b78
--- /dev/null
+++ b/usr/src/cmd/dlutil/dlsend.h
@@ -0,0 +1,45 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2017, Joyent, Inc.
+ */
+
+#ifndef _DLSEND_H
+#define _DLSEND_H
+
+/*
+ * A common header file for things that dlsend and dlrecv need.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * We need to pick an arbitrary Ethertype to squat on for the purposes of this
+ * testing program. As such we use one with a recongizable string. If someone
+ * comes along and uses this, then we should get off of it.
+ */
+#define DLSEND_SAP 0xdeed
+#define DLSEND_MSG "A Elbereth Gilthoniel"
+
+typedef struct dlsend_msg {
+ uint64_t dm_count;
+ char dm_host[MAXHOSTNAMELEN];
+ char dm_mesg[32];
+} dlsend_msg_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DLSEND_H */
diff --git a/usr/src/cmd/dltraninfo/dltraninfo.c b/usr/src/cmd/dlutil/dltraninfo.c
index 2e6f7ee2e1..2e6f7ee2e1 100644
--- a/usr/src/cmd/dltraninfo/dltraninfo.c
+++ b/usr/src/cmd/dlutil/dltraninfo.c