120768856SRobert Mustacchi /*
220768856SRobert Mustacchi * This file and its contents are supplied under the terms of the
320768856SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
420768856SRobert Mustacchi * You may only use this file in accordance with the terms of version
520768856SRobert Mustacchi * 1.0 of the CDDL.
620768856SRobert Mustacchi *
720768856SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
820768856SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
920768856SRobert Mustacchi * http://www.illumos.org/license/CDDL.
1020768856SRobert Mustacchi */
1120768856SRobert Mustacchi
1220768856SRobert Mustacchi /*
1320768856SRobert Mustacchi * Copyright (c) 2018, Joyent, Inc.
1420768856SRobert Mustacchi */
1520768856SRobert Mustacchi
1620768856SRobert Mustacchi /*
1720768856SRobert Mustacchi * Receive a raw Ethernet frame from dlsend.
1820768856SRobert Mustacchi */
1920768856SRobert Mustacchi
2020768856SRobert Mustacchi #include <stdio.h>
2120768856SRobert Mustacchi #include <errno.h>
2220768856SRobert Mustacchi #include <strings.h>
2320768856SRobert Mustacchi #include <unistd.h>
2420768856SRobert Mustacchi #include <stdarg.h>
2520768856SRobert Mustacchi #include <libgen.h>
2620768856SRobert Mustacchi #include <limits.h>
2720768856SRobert Mustacchi #include <stdlib.h>
2820768856SRobert Mustacchi #include <unistd.h>
2920768856SRobert Mustacchi #include <netdb.h>
3020768856SRobert Mustacchi #include <libdlpi.h>
3120768856SRobert Mustacchi #include <stddef.h>
3220768856SRobert Mustacchi #include <stdint.h>
3320768856SRobert Mustacchi #include <endian.h>
3420768856SRobert Mustacchi #include <ctype.h>
3520768856SRobert Mustacchi #include <err.h>
3620768856SRobert Mustacchi
3720768856SRobert Mustacchi #include "dlsend.h"
3820768856SRobert Mustacchi
3920768856SRobert Mustacchi
4020768856SRobert Mustacchi static uint_t dlrecv_sap = DLSEND_SAP;
4120768856SRobert Mustacchi static const char *dlrecv_prog;
4220768856SRobert Mustacchi
4320768856SRobert Mustacchi static void
dlrecv_usage(const char * fmt,...)4420768856SRobert Mustacchi dlrecv_usage(const char *fmt, ...)
4520768856SRobert Mustacchi {
4620768856SRobert Mustacchi if (fmt != NULL) {
4720768856SRobert Mustacchi va_list ap;
4820768856SRobert Mustacchi
4920768856SRobert Mustacchi (void) fprintf(stderr, "%s: ", dlrecv_prog);
5020768856SRobert Mustacchi va_start(ap, fmt);
5120768856SRobert Mustacchi (void) vfprintf(stderr, fmt, ap);
5220768856SRobert Mustacchi va_end(ap);
5320768856SRobert Mustacchi }
5420768856SRobert Mustacchi
5520768856SRobert Mustacchi (void) fprintf(stderr, "Usage: %s [-s sap] device\n"
5620768856SRobert Mustacchi "\t-s sap\tspecify SAP to send on\n",
5720768856SRobert Mustacchi dlrecv_prog);
5820768856SRobert Mustacchi }
5920768856SRobert Mustacchi
6020768856SRobert Mustacchi static boolean_t
dlrecv_isvalid(dlsend_msg_t * msg)6120768856SRobert Mustacchi dlrecv_isvalid(dlsend_msg_t *msg)
6220768856SRobert Mustacchi {
6320768856SRobert Mustacchi uint_t i;
6420768856SRobert Mustacchi boolean_t nul;
6520768856SRobert Mustacchi
6620768856SRobert Mustacchi nul = B_FALSE;
6720768856SRobert Mustacchi for (i = 0; i < sizeof (msg->dm_host); i++) {
6820768856SRobert Mustacchi if (!isprint(msg->dm_host[i]) &&
6920768856SRobert Mustacchi msg->dm_host[i] != '\0') {
70*6b1325cfSRobert Mustacchi warnx("Encountered bad byte in dm_host[%d]",
7120768856SRobert Mustacchi i);
7220768856SRobert Mustacchi return (B_FALSE);
7320768856SRobert Mustacchi }
7420768856SRobert Mustacchi
7520768856SRobert Mustacchi if (msg->dm_host[i] == '\0')
7620768856SRobert Mustacchi nul = B_TRUE;
7720768856SRobert Mustacchi }
7820768856SRobert Mustacchi
7920768856SRobert Mustacchi if (!nul) {
80*6b1325cfSRobert Mustacchi warnx("Missing NUL in dm_host");
8120768856SRobert Mustacchi return (B_FALSE);
8220768856SRobert Mustacchi }
8320768856SRobert Mustacchi
8420768856SRobert Mustacchi nul = B_FALSE;
8520768856SRobert Mustacchi for (i = 0; i < sizeof (msg->dm_mesg); i++) {
8620768856SRobert Mustacchi if (!isprint(msg->dm_mesg[i]) &&
8720768856SRobert Mustacchi msg->dm_mesg[i] != '\0') {
88*6b1325cfSRobert Mustacchi warnx("Encountered bad byte in dm_mesg[%d]",
8920768856SRobert Mustacchi i);
9020768856SRobert Mustacchi return (B_FALSE);
9120768856SRobert Mustacchi }
9220768856SRobert Mustacchi
9320768856SRobert Mustacchi if (msg->dm_mesg[i] == '\0')
9420768856SRobert Mustacchi nul = B_TRUE;
9520768856SRobert Mustacchi }
9620768856SRobert Mustacchi
9720768856SRobert Mustacchi if (!nul) {
98*6b1325cfSRobert Mustacchi warnx("Missing NUL in dm_mesg");
9920768856SRobert Mustacchi return (B_FALSE);
10020768856SRobert Mustacchi }
10120768856SRobert Mustacchi
10220768856SRobert Mustacchi if (strcmp(msg->dm_mesg, DLSEND_MSG) != 0) {
103*6b1325cfSRobert Mustacchi warnx("Missing expected message (%s)", DLSEND_MSG);
10420768856SRobert Mustacchi return (B_FALSE);
10520768856SRobert Mustacchi }
10620768856SRobert Mustacchi
10720768856SRobert Mustacchi return (B_TRUE);
10820768856SRobert Mustacchi }
10920768856SRobert Mustacchi
11020768856SRobert Mustacchi static void
dlrecv_print(dlsend_msg_t * msg,dlpi_recvinfo_t * rinfo,boolean_t invalid)11120768856SRobert Mustacchi dlrecv_print(dlsend_msg_t *msg, dlpi_recvinfo_t *rinfo, boolean_t invalid)
11220768856SRobert Mustacchi {
11320768856SRobert Mustacchi uint_t i;
11420768856SRobert Mustacchi
11520768856SRobert Mustacchi (void) printf("Received %s from ", invalid ?
11620768856SRobert Mustacchi "invalid message" : "Elbereth");
11720768856SRobert Mustacchi
11820768856SRobert Mustacchi for (i = 0; i < rinfo->dri_destaddrlen; i++) {
11920768856SRobert Mustacchi (void) printf("%02x", rinfo->dri_destaddr[i]);
12020768856SRobert Mustacchi if (i + 1 != rinfo->dri_destaddrlen)
12120768856SRobert Mustacchi (void) putchar(':');
12220768856SRobert Mustacchi }
12320768856SRobert Mustacchi
12420768856SRobert Mustacchi if (invalid) {
12520768856SRobert Mustacchi return;
12620768856SRobert Mustacchi }
12720768856SRobert Mustacchi
12820768856SRobert Mustacchi (void) printf(" seq=%" PRIu64 " host=%s\n", betoh64(msg->dm_count),
12920768856SRobert Mustacchi msg->dm_host);
13020768856SRobert Mustacchi }
13120768856SRobert Mustacchi
13220768856SRobert Mustacchi int
main(int argc,char * argv[])13320768856SRobert Mustacchi main(int argc, char *argv[])
13420768856SRobert Mustacchi {
13520768856SRobert Mustacchi int c, ret;
13620768856SRobert Mustacchi char *eptr;
13720768856SRobert Mustacchi unsigned long sap;
13820768856SRobert Mustacchi uint_t bind_sap;
13920768856SRobert Mustacchi dlpi_handle_t dh;
14020768856SRobert Mustacchi
14120768856SRobert Mustacchi dlrecv_prog = basename(argv[0]);
14220768856SRobert Mustacchi
14320768856SRobert Mustacchi while ((c = getopt(argc, argv, ":s:")) != -1) {
14420768856SRobert Mustacchi switch (c) {
14520768856SRobert Mustacchi case 's':
14620768856SRobert Mustacchi errno = 0;
14720768856SRobert Mustacchi sap = strtoul(optarg, &eptr, 10);
14820768856SRobert Mustacchi if (errno != 0 || sap == 0 || sap >= UINT16_MAX ||
14920768856SRobert Mustacchi *eptr != '\0') {
15020768856SRobert Mustacchi dlrecv_usage("Invalid value for sap (-s): %s\n",
15120768856SRobert Mustacchi optarg);
15220768856SRobert Mustacchi return (2);
15320768856SRobert Mustacchi }
15420768856SRobert Mustacchi dlrecv_sap = sap;
15520768856SRobert Mustacchi break;
15620768856SRobert Mustacchi case ':':
15720768856SRobert Mustacchi dlrecv_usage("Option -%c requires an operand\n",
15820768856SRobert Mustacchi optopt);
15920768856SRobert Mustacchi return (2);
16020768856SRobert Mustacchi case '?':
16120768856SRobert Mustacchi dlrecv_usage("Unknown option: -%c\n", optopt);
16220768856SRobert Mustacchi return (2);
16320768856SRobert Mustacchi }
16420768856SRobert Mustacchi }
16520768856SRobert Mustacchi
16620768856SRobert Mustacchi argc -= optind;
16720768856SRobert Mustacchi argv += optind;
16820768856SRobert Mustacchi
16920768856SRobert Mustacchi if (argc != 1) {
17020768856SRobert Mustacchi dlrecv_usage("missing required operands\n");
17120768856SRobert Mustacchi return (2);
17220768856SRobert Mustacchi }
17320768856SRobert Mustacchi
17420768856SRobert Mustacchi if ((ret = dlpi_open(argv[0], &dh, 0)) != DLPI_SUCCESS) {
175*6b1325cfSRobert Mustacchi warnx("failed to open %s: %s", argv[0],
17620768856SRobert Mustacchi dlpi_strerror(ret));
17720768856SRobert Mustacchi exit(1);
17820768856SRobert Mustacchi }
17920768856SRobert Mustacchi
18020768856SRobert Mustacchi if ((ret = dlpi_bind(dh, dlrecv_sap, &bind_sap)) != DLPI_SUCCESS) {
181*6b1325cfSRobert Mustacchi warnx("failed to bind to sap 0x%x: %s", dlrecv_sap,
18220768856SRobert Mustacchi dlpi_strerror(ret));
18320768856SRobert Mustacchi exit(1);
18420768856SRobert Mustacchi }
18520768856SRobert Mustacchi
18620768856SRobert Mustacchi if (bind_sap != dlrecv_sap) {
18720768856SRobert Mustacchi warnx("failed to bind to requested sap 0x%x, bound to "
188*6b1325cfSRobert Mustacchi "0x%x", dlrecv_sap, bind_sap);
18920768856SRobert Mustacchi exit(1);
19020768856SRobert Mustacchi }
19120768856SRobert Mustacchi
19220768856SRobert Mustacchi for (;;) {
19320768856SRobert Mustacchi dlpi_recvinfo_t rinfo;
19420768856SRobert Mustacchi dlsend_msg_t msg;
19520768856SRobert Mustacchi size_t msglen;
19620768856SRobert Mustacchi boolean_t invalid = B_FALSE;
19720768856SRobert Mustacchi
19820768856SRobert Mustacchi msglen = sizeof (msg);
19920768856SRobert Mustacchi ret = dlpi_recv(dh, NULL, NULL, &msg, &msglen, -1, &rinfo);
20020768856SRobert Mustacchi if (ret != DLPI_SUCCESS) {
201*6b1325cfSRobert Mustacchi warnx("failed to receive data: %s", dlpi_strerror(ret));
20220768856SRobert Mustacchi continue;
20320768856SRobert Mustacchi }
20420768856SRobert Mustacchi
20520768856SRobert Mustacchi if (msglen != rinfo.dri_totmsglen) {
206*6b1325cfSRobert Mustacchi warnx("message truncated: expected %zu bytes, "
207*6b1325cfSRobert Mustacchi "got %zu", sizeof (dlsend_msg_t),
20820768856SRobert Mustacchi rinfo.dri_totmsglen);
20920768856SRobert Mustacchi invalid = B_TRUE;
21020768856SRobert Mustacchi }
21120768856SRobert Mustacchi
21220768856SRobert Mustacchi if (msglen != sizeof (msg)) {
213*6b1325cfSRobert Mustacchi warnx("message too short: expected %zu bytes, "
214*6b1325cfSRobert Mustacchi "got %zu", sizeof (dlsend_msg_t), msglen);
21520768856SRobert Mustacchi invalid = B_TRUE;
21620768856SRobert Mustacchi }
21720768856SRobert Mustacchi
21820768856SRobert Mustacchi if (!invalid) {
21920768856SRobert Mustacchi invalid = !dlrecv_isvalid(&msg);
22020768856SRobert Mustacchi }
22120768856SRobert Mustacchi
22220768856SRobert Mustacchi dlrecv_print(&msg, &rinfo, invalid);
22320768856SRobert Mustacchi }
22420768856SRobert Mustacchi
22520768856SRobert Mustacchi /* LINTED: E_STMT_NOT_REACHED */
22620768856SRobert Mustacchi return (0);
22720768856SRobert Mustacchi }
228