From 2076885612f784f9ddfc09282d62518d0f9b2c4d Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Tue, 6 Feb 2018 19:17:04 +0000 Subject: [PATCH] 9093 want basic utility for Ethernet level pong Reviewed by: Ryan Zezeski Reviewed by: Jerry Jelinek Reviewed by: Yuri Pankov Approved by: Richard Lowe --- usr/src/cmd/dlutil/Makefile | 7 +- usr/src/cmd/dlutil/dlrecv.c | 229 ++++++++++++++++++++++++++++++++ usr/src/cmd/dlutil/dlsend.c | 154 +++++++++++++++++++++ usr/src/cmd/dlutil/dlsend.h | 45 +++++++ usr/src/pkg/manifests/system-network.mf | 2 + 5 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 usr/src/cmd/dlutil/dlrecv.c create mode 100644 usr/src/cmd/dlutil/dlsend.c create mode 100644 usr/src/cmd/dlutil/dlsend.h 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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, "", 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 -- 2.11.4.GIT