xref: /illumos-gate/usr/src/cmd/dlutil/dlrecv.c (revision 6b1325cf)
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