diff options
author | Robert Mustacchi <rm@joyent.com> | 2017-04-28 21:22:39 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2017-05-01 18:30:08 +0000 |
commit | 0d296521ece3a5b488e6054f1d0af661aef90046 (patch) | |
tree | 3677c72342646417c1d448a512113f032e51a1ee | |
parent | 50ee30c219b9dac9fd4709209da6f16acc8da831 (diff) | |
download | illumos-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-- | manifest | 2 | ||||
-rw-r--r-- | usr/src/cmd/Makefile | 2 | ||||
-rw-r--r-- | usr/src/cmd/dlutil/Makefile (renamed from usr/src/cmd/dltraninfo/Makefile) | 7 | ||||
-rw-r--r-- | usr/src/cmd/dlutil/dlrecv.c | 237 | ||||
-rw-r--r-- | usr/src/cmd/dlutil/dlsend.c | 163 | ||||
-rw-r--r-- | usr/src/cmd/dlutil/dlsend.h | 45 | ||||
-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
@@ -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 |