summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2018-02-06 19:17:04 +0000
committerRobert Mustacchi <rm@joyent.com>2018-09-10 17:02:19 +0000
commit2076885612f784f9ddfc09282d62518d0f9b2c4d (patch)
tree4f9568b84e176dea837753b80e9f5c8bc9397edc /usr/src
parent56a20711c16596906185d9bfb85f8a4b02e93fc6 (diff)
downloadillumos-gate-2076885612f784f9ddfc09282d62518d0f9b2c4d.tar.gz
9093 want basic utility for Ethernet level pong
Reviewed by: Ryan Zezeski <ryan.zeseski@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Yuri Pankov <yuripv@yuripv.net> Approved by: Richard Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/dlutil/Makefile7
-rw-r--r--usr/src/cmd/dlutil/dlrecv.c229
-rw-r--r--usr/src/cmd/dlutil/dlsend.c154
-rw-r--r--usr/src/cmd/dlutil/dlsend.h45
-rw-r--r--usr/src/pkg/manifests/system-network.mf2
5 files changed, 436 insertions, 1 deletions
diff --git a/usr/src/cmd/dlutil/Makefile b/usr/src/cmd/dlutil/Makefile
index afbaf3a40d..4c0563474d 100644
--- a/usr/src/cmd/dlutil/Makefile
+++ b/usr/src/cmd/dlutil/Makefile
@@ -13,7 +13,7 @@
# Copyright (c) 2017, Joyent, Inc.
#
-PROG= dltraninfo dlled
+PROG= dltraninfo dlsend dlrecv dlled
LINTPROGS= $(PROG:%=%.ln)
include ../Makefile.cmd
@@ -23,8 +23,13 @@ CFLAGS += $(CCVERBOSE)
dltraninfo := LDLIBS += -ldladm -lsff -lnvpair
dlled := LDLIBS += -ldladm
+dlsend := LDLIBS += -ldlpi -lsocket
+dlrecv := LDLIBS += -ldlpi
+
dltraninfo.ln := LDLIBS += -ldladm -lsff -lnvpair
dlled.ln := LDLIBS += -ldladm
+dlsend.ln := LDLIBS += -ldlpi -lsocket
+dlrecv.ln := 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..d24bc6f360
--- /dev/null
+++ b/usr/src/cmd/dlutil/dlrecv.c
@@ -0,0 +1,229 @@
+/*
+ * 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) 2018, 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 <err.h>
+
+#include "dlsend.h"
+
+
+static uint_t dlrecv_sap = DLSEND_SAP;
+static const char *dlrecv_prog;
+
+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') {
+ warnx("Encountered bad byte in dm_host[%d]\n",
+ i);
+ return (B_FALSE);
+ }
+
+ if (msg->dm_host[i] == '\0')
+ nul = B_TRUE;
+ }
+
+ if (!nul) {
+ warnx("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') {
+ warnx("Encountered bad byte in dm_mesg[%d]\n",
+ i);
+ return (B_FALSE);
+ }
+
+ if (msg->dm_mesg[i] == '\0')
+ nul = B_TRUE;
+ }
+
+ if (!nul) {
+ warnx("Missing NUL in dm_mesg\n");
+ return (B_FALSE);
+ }
+
+ if (strcmp(msg->dm_mesg, DLSEND_MSG) != 0) {
+ warnx("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;
+
+ (void) 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;
+ }
+
+ (void) 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) {
+ warnx("failed to open %s: %s\n", argv[0],
+ dlpi_strerror(ret));
+ exit(1);
+ }
+
+ if ((ret = dlpi_bind(dh, dlrecv_sap, &bind_sap)) != DLPI_SUCCESS) {
+ warnx("failed to bind to sap 0x%x: %s\n", dlrecv_sap,
+ dlpi_strerror(ret));
+ exit(1);
+ }
+
+ if (bind_sap != dlrecv_sap) {
+ warnx("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) {
+ warnx("failed to receive data: %s\n",
+ dlpi_strerror(ret));
+ continue;
+ }
+
+ if (msglen != rinfo.dri_totmsglen) {
+ warnx("message truncated: expected %ld bytes, "
+ "got %ld\n", sizeof (dlsend_msg_t),
+ rinfo.dri_totmsglen);
+ invalid = B_TRUE;
+ }
+
+ if (msglen != sizeof (msg)) {
+ warnx("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);
+ }
+
+ /* LINTED: E_STMT_NOT_REACHED */
+ return (0);
+}
diff --git a/usr/src/cmd/dlutil/dlsend.c b/usr/src/cmd/dlutil/dlsend.c
new file mode 100644
index 0000000000..995ba45eee
--- /dev/null
+++ b/usr/src/cmd/dlutil/dlsend.c
@@ -0,0 +1,154 @@
+/*
+ * 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) 2018, 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 <err.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_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) {
+ warnx("failed to convert target address %s\n", argv[1]);
+ return (1);
+ }
+
+ if (gethostname(host, sizeof (host)) != 0) {
+ warnx("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) {
+ warnx("failed to open %s: %s\n", argv[0],
+ dlpi_strerror(ret));
+ exit(1);
+ }
+
+ if ((ret = dlpi_bind(dh, dlsend_sap, &bind_sap)) != DLPI_SUCCESS) {
+ warnx("failed to bind to sap 0x%x: %s\n", dlsend_sap,
+ dlpi_strerror(ret));
+ exit(1);
+ }
+
+ if (bind_sap != dlsend_sap) {
+ warnx("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) {
+ warnx("failed to send message: %s\n",
+ dlpi_strerror(ret));
+ exit(1);
+ }
+
+ (void) sleep(1);
+ }
+
+ /* LINTED: E_STMT_NOT_REACHED */
+ 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/pkg/manifests/system-network.mf b/usr/src/pkg/manifests/system-network.mf
index 4f7a8978ff..61c8bd345f 100644
--- a/usr/src/pkg/manifests/system-network.mf
+++ b/usr/src/pkg/manifests/system-network.mf
@@ -84,6 +84,8 @@ file path=sbin/flowadm mode=0555
file path=sbin/flowstat mode=0555
file path=sbin/ipadm mode=0555
file path=usr/lib/dl/dlled mode=0555
+file path=usr/lib/dl/dlrecv mode=0555
+file path=usr/lib/dl/dlsend mode=0555
file path=usr/lib/dl/dltraninfo mode=0555
file path=usr/share/man/man1m/dladm.1m
file path=usr/share/man/man1m/flowadm.1m