diff options
Diffstat (limited to 'usr/src/cmd/dlutil/dlsend.c')
-rw-r--r-- | usr/src/cmd/dlutil/dlsend.c | 154 |
1 files changed, 154 insertions, 0 deletions
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); +} |