9093 want basic utility for Ethernet level pong
[unleashed.git] / usr / src / cmd / dlutil / dlrecv.c
blobd24bc6f360b4f34f5996f582ac2ef3a5f044a9bb
1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright (c) 2018, Joyent, Inc.
17 * Receive a raw Ethernet frame from dlsend.
20 #include <stdio.h>
21 #include <errno.h>
22 #include <strings.h>
23 #include <unistd.h>
24 #include <stdarg.h>
25 #include <libgen.h>
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <netdb.h>
30 #include <libdlpi.h>
31 #include <stddef.h>
32 #include <stdint.h>
33 #include <endian.h>
34 #include <ctype.h>
35 #include <err.h>
37 #include "dlsend.h"
40 static uint_t dlrecv_sap = DLSEND_SAP;
41 static const char *dlrecv_prog;
43 static void
44 dlrecv_usage(const char *fmt, ...)
46 if (fmt != NULL) {
47 va_list ap;
49 (void) fprintf(stderr, "%s: ", dlrecv_prog);
50 va_start(ap, fmt);
51 (void) vfprintf(stderr, fmt, ap);
52 va_end(ap);
55 (void) fprintf(stderr, "Usage: %s [-s sap] device\n"
56 "\t-s sap\tspecify SAP to send on\n",
57 dlrecv_prog);
60 static boolean_t
61 dlrecv_isvalid(dlsend_msg_t *msg)
63 uint_t i;
64 boolean_t nul;
66 nul = B_FALSE;
67 for (i = 0; i < sizeof (msg->dm_host); i++) {
68 if (!isprint(msg->dm_host[i]) &&
69 msg->dm_host[i] != '\0') {
70 warnx("Encountered bad byte in dm_host[%d]\n",
71 i);
72 return (B_FALSE);
75 if (msg->dm_host[i] == '\0')
76 nul = B_TRUE;
79 if (!nul) {
80 warnx("Missing NUL in dm_host\n");
81 return (B_FALSE);
84 nul = B_FALSE;
85 for (i = 0; i < sizeof (msg->dm_mesg); i++) {
86 if (!isprint(msg->dm_mesg[i]) &&
87 msg->dm_mesg[i] != '\0') {
88 warnx("Encountered bad byte in dm_mesg[%d]\n",
89 i);
90 return (B_FALSE);
93 if (msg->dm_mesg[i] == '\0')
94 nul = B_TRUE;
97 if (!nul) {
98 warnx("Missing NUL in dm_mesg\n");
99 return (B_FALSE);
102 if (strcmp(msg->dm_mesg, DLSEND_MSG) != 0) {
103 warnx("Missing expected message (%s)\n", DLSEND_MSG);
104 return (B_FALSE);
107 return (B_TRUE);
110 static void
111 dlrecv_print(dlsend_msg_t *msg, dlpi_recvinfo_t *rinfo, boolean_t invalid)
113 uint_t i;
115 (void) printf("Received %s from ", invalid ?
116 "invalid message" : "Elbereth");
118 for (i = 0; i < rinfo->dri_destaddrlen; i++) {
119 (void) printf("%02x", rinfo->dri_destaddr[i]);
120 if (i + 1 != rinfo->dri_destaddrlen)
121 (void) putchar(':');
124 if (invalid) {
125 return;
128 (void) printf(" seq=%" PRIu64 " host=%s\n", betoh64(msg->dm_count),
129 msg->dm_host);
133 main(int argc, char *argv[])
135 int c, ret;
136 char *eptr;
137 unsigned long sap;
138 uint_t bind_sap;
139 dlpi_handle_t dh;
141 dlrecv_prog = basename(argv[0]);
143 while ((c = getopt(argc, argv, ":s:")) != -1) {
144 switch (c) {
145 case 's':
146 errno = 0;
147 sap = strtoul(optarg, &eptr, 10);
148 if (errno != 0 || sap == 0 || sap >= UINT16_MAX ||
149 *eptr != '\0') {
150 dlrecv_usage("Invalid value for sap (-s): %s\n",
151 optarg);
152 return (2);
154 dlrecv_sap = sap;
155 break;
156 case ':':
157 dlrecv_usage("Option -%c requires an operand\n",
158 optopt);
159 return (2);
160 case '?':
161 dlrecv_usage("Unknown option: -%c\n", optopt);
162 return (2);
166 argc -= optind;
167 argv += optind;
169 if (argc != 1) {
170 dlrecv_usage("missing required operands\n");
171 return (2);
174 if ((ret = dlpi_open(argv[0], &dh, 0)) != DLPI_SUCCESS) {
175 warnx("failed to open %s: %s\n", argv[0],
176 dlpi_strerror(ret));
177 exit(1);
180 if ((ret = dlpi_bind(dh, dlrecv_sap, &bind_sap)) != DLPI_SUCCESS) {
181 warnx("failed to bind to sap 0x%x: %s\n", dlrecv_sap,
182 dlpi_strerror(ret));
183 exit(1);
186 if (bind_sap != dlrecv_sap) {
187 warnx("failed to bind to requested sap 0x%x, bound to "
188 "0x%x\n", dlrecv_sap, bind_sap);
189 exit(1);
192 for (;;) {
193 dlpi_recvinfo_t rinfo;
194 dlsend_msg_t msg;
195 size_t msglen;
196 boolean_t invalid = B_FALSE;
198 msglen = sizeof (msg);
199 ret = dlpi_recv(dh, NULL, NULL, &msg, &msglen, -1, &rinfo);
200 if (ret != DLPI_SUCCESS) {
201 warnx("failed to receive data: %s\n",
202 dlpi_strerror(ret));
203 continue;
206 if (msglen != rinfo.dri_totmsglen) {
207 warnx("message truncated: expected %ld bytes, "
208 "got %ld\n", sizeof (dlsend_msg_t),
209 rinfo.dri_totmsglen);
210 invalid = B_TRUE;
213 if (msglen != sizeof (msg)) {
214 warnx("message too short: expected %ld bytes, "
215 "got %ld\n", sizeof (dlsend_msg_t),
216 msglen);
217 invalid = B_TRUE;
220 if (!invalid) {
221 invalid = !dlrecv_isvalid(&msg);
224 dlrecv_print(&msg, &rinfo, invalid);
227 /* LINTED: E_STMT_NOT_REACHED */
228 return (0);