1*59596c01SRobert Mustacchi /*
2*59596c01SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*59596c01SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*59596c01SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*59596c01SRobert Mustacchi * 1.0 of the CDDL.
6*59596c01SRobert Mustacchi *
7*59596c01SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*59596c01SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*59596c01SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*59596c01SRobert Mustacchi */
11*59596c01SRobert Mustacchi
12*59596c01SRobert Mustacchi /*
13*59596c01SRobert Mustacchi * Copyright (c) 2017, Joyent, Inc.
14*59596c01SRobert Mustacchi */
15*59596c01SRobert Mustacchi
16*59596c01SRobert Mustacchi /*
17*59596c01SRobert Mustacchi * Private utility to dump transceiver information for each physical datalink.
18*59596c01SRobert Mustacchi * Something like this should eventually be a part of dladm or similar.
19*59596c01SRobert Mustacchi */
20*59596c01SRobert Mustacchi
21*59596c01SRobert Mustacchi #include <stdio.h>
22*59596c01SRobert Mustacchi #include <sys/types.h>
23*59596c01SRobert Mustacchi #include <sys/stat.h>
24*59596c01SRobert Mustacchi #include <fcntl.h>
25*59596c01SRobert Mustacchi #include <strings.h>
26*59596c01SRobert Mustacchi #include <errno.h>
27*59596c01SRobert Mustacchi #include <ctype.h>
28*59596c01SRobert Mustacchi #include <unistd.h>
29*59596c01SRobert Mustacchi #include <limits.h>
30*59596c01SRobert Mustacchi #include <stdarg.h>
31*59596c01SRobert Mustacchi #include <libgen.h>
32*59596c01SRobert Mustacchi
33*59596c01SRobert Mustacchi #include <libdladm.h>
34*59596c01SRobert Mustacchi #include <libdllink.h>
35*59596c01SRobert Mustacchi #include <sys/dld.h>
36*59596c01SRobert Mustacchi #include <sys/dld_ioc.h>
37*59596c01SRobert Mustacchi #include <sys/dls_mgmt.h>
38*59596c01SRobert Mustacchi #include <libsff.h>
39*59596c01SRobert Mustacchi
40*59596c01SRobert Mustacchi #define DLTRAN_KIND_LEN 64
41*59596c01SRobert Mustacchi
42*59596c01SRobert Mustacchi static dladm_handle_t dltran_hdl;
43*59596c01SRobert Mustacchi static char dltran_dlerrmsg[DLADM_STRSIZE];
44*59596c01SRobert Mustacchi static const char *dltran_progname;
45*59596c01SRobert Mustacchi static boolean_t dltran_verbose;
46*59596c01SRobert Mustacchi static boolean_t dltran_hex;
47*59596c01SRobert Mustacchi static boolean_t dltran_write;
48*59596c01SRobert Mustacchi static int dltran_outfd;
49*59596c01SRobert Mustacchi static int dltran_errors;
50*59596c01SRobert Mustacchi
51*59596c01SRobert Mustacchi /*
52*59596c01SRobert Mustacchi * This routine basically assumes that we'll have 16 byte aligned output to
53*59596c01SRobert Mustacchi * print out the human readable output.
54*59596c01SRobert Mustacchi */
55*59596c01SRobert Mustacchi static void
dltran_dump_page(uint8_t * buf,size_t nbytes,uint_t page)56*59596c01SRobert Mustacchi dltran_dump_page(uint8_t *buf, size_t nbytes, uint_t page)
57*59596c01SRobert Mustacchi {
58*59596c01SRobert Mustacchi size_t i;
59*59596c01SRobert Mustacchi static boolean_t first = B_TRUE;
60*59596c01SRobert Mustacchi
61*59596c01SRobert Mustacchi if (first) {
62*59596c01SRobert Mustacchi (void) printf("page %*s 0", 4, "");
63*59596c01SRobert Mustacchi for (i = 1; i < 16; i++) {
64*59596c01SRobert Mustacchi if (i % 4 == 0 && i % 16 != 0) {
65*59596c01SRobert Mustacchi (void) printf(" ");
66*59596c01SRobert Mustacchi }
67*59596c01SRobert Mustacchi
68*59596c01SRobert Mustacchi (void) printf("%2x", i);
69*59596c01SRobert Mustacchi }
70*59596c01SRobert Mustacchi (void) printf(" v123456789abcdef\n");
71*59596c01SRobert Mustacchi first = B_FALSE;
72*59596c01SRobert Mustacchi }
73*59596c01SRobert Mustacchi for (i = 0; i < nbytes; i++) {
74*59596c01SRobert Mustacchi
75*59596c01SRobert Mustacchi if (i % 16 == 0) {
76*59596c01SRobert Mustacchi (void) printf("0x%02x %04x: ", page, i);
77*59596c01SRobert Mustacchi }
78*59596c01SRobert Mustacchi
79*59596c01SRobert Mustacchi if (i % 4 == 0 && i % 16 != 0) {
80*59596c01SRobert Mustacchi (void) printf(" ");
81*59596c01SRobert Mustacchi }
82*59596c01SRobert Mustacchi
83*59596c01SRobert Mustacchi
84*59596c01SRobert Mustacchi (void) printf("%02x", buf[i]);
85*59596c01SRobert Mustacchi
86*59596c01SRobert Mustacchi if (i % 16 == 15) {
87*59596c01SRobert Mustacchi int j;
88*59596c01SRobert Mustacchi (void) printf(" ");
89*59596c01SRobert Mustacchi for (j = i - (i % 16); j <= i; j++) {
90*59596c01SRobert Mustacchi if (!isprint(buf[j])) {
91*59596c01SRobert Mustacchi (void) printf(".");
92*59596c01SRobert Mustacchi } else {
93*59596c01SRobert Mustacchi (void) printf("%c", buf[j]);
94*59596c01SRobert Mustacchi }
95*59596c01SRobert Mustacchi }
96*59596c01SRobert Mustacchi (void) printf("\n");
97*59596c01SRobert Mustacchi }
98*59596c01SRobert Mustacchi }
99*59596c01SRobert Mustacchi }
100*59596c01SRobert Mustacchi
101*59596c01SRobert Mustacchi static int
dltran_read_page(datalink_id_t link,uint_t tranid,uint_t page,uint8_t * bufp,size_t * buflen)102*59596c01SRobert Mustacchi dltran_read_page(datalink_id_t link, uint_t tranid, uint_t page, uint8_t *bufp,
103*59596c01SRobert Mustacchi size_t *buflen)
104*59596c01SRobert Mustacchi {
105*59596c01SRobert Mustacchi dld_ioc_tranio_t dti;
106*59596c01SRobert Mustacchi
107*59596c01SRobert Mustacchi bzero(bufp, *buflen);
108*59596c01SRobert Mustacchi bzero(&dti, sizeof (dti));
109*59596c01SRobert Mustacchi
110*59596c01SRobert Mustacchi dti.dti_linkid = link;
111*59596c01SRobert Mustacchi dti.dti_tran_id = tranid;
112*59596c01SRobert Mustacchi dti.dti_page = page;
113*59596c01SRobert Mustacchi dti.dti_nbytes = *buflen;
114*59596c01SRobert Mustacchi dti.dti_off = 0;
115*59596c01SRobert Mustacchi dti.dti_buf = (uintptr_t)(void *)bufp;
116*59596c01SRobert Mustacchi
117*59596c01SRobert Mustacchi if (ioctl(dladm_dld_fd(dltran_hdl), DLDIOC_READTRAN, &dti) != 0) {
118*59596c01SRobert Mustacchi (void) fprintf(stderr, "failed to read transceiver page "
119*59596c01SRobert Mustacchi "0x%2x: %s\n", page, strerror(errno));
120*59596c01SRobert Mustacchi return (1);
121*59596c01SRobert Mustacchi }
122*59596c01SRobert Mustacchi
123*59596c01SRobert Mustacchi *buflen = dti.dti_nbytes;
124*59596c01SRobert Mustacchi return (0);
125*59596c01SRobert Mustacchi }
126*59596c01SRobert Mustacchi
127*59596c01SRobert Mustacchi static boolean_t
dltran_is_8472(uint8_t * buf)128*59596c01SRobert Mustacchi dltran_is_8472(uint8_t *buf)
129*59596c01SRobert Mustacchi {
130*59596c01SRobert Mustacchi switch (buf[0]) {
131*59596c01SRobert Mustacchi case 0xc:
132*59596c01SRobert Mustacchi case 0xd:
133*59596c01SRobert Mustacchi case 0x11:
134*59596c01SRobert Mustacchi /*
135*59596c01SRobert Mustacchi * Catch cases that refer explicitly to QSFP and newer.
136*59596c01SRobert Mustacchi */
137*59596c01SRobert Mustacchi return (B_FALSE);
138*59596c01SRobert Mustacchi default:
139*59596c01SRobert Mustacchi break;
140*59596c01SRobert Mustacchi }
141*59596c01SRobert Mustacchi
142*59596c01SRobert Mustacchi /*
143*59596c01SRobert Mustacchi * Check the byte that indicates compliance with SFF 8472. Use this to
144*59596c01SRobert Mustacchi * know if we can read page 0xa2 or not.
145*59596c01SRobert Mustacchi */
146*59596c01SRobert Mustacchi if (buf[94] == 0)
147*59596c01SRobert Mustacchi return (B_FALSE);
148*59596c01SRobert Mustacchi
149*59596c01SRobert Mustacchi return (B_TRUE);
150*59596c01SRobert Mustacchi }
151*59596c01SRobert Mustacchi
152*59596c01SRobert Mustacchi static void
dltran_hex_dump(datalink_id_t linkid,uint_t tranid)153*59596c01SRobert Mustacchi dltran_hex_dump(datalink_id_t linkid, uint_t tranid)
154*59596c01SRobert Mustacchi {
155*59596c01SRobert Mustacchi uint8_t buf[256];
156*59596c01SRobert Mustacchi size_t buflen = sizeof (buf);
157*59596c01SRobert Mustacchi
158*59596c01SRobert Mustacchi if (dltran_read_page(linkid, tranid, 0xa0, buf, &buflen) != 0) {
159*59596c01SRobert Mustacchi dltran_errors++;
160*59596c01SRobert Mustacchi return;
161*59596c01SRobert Mustacchi }
162*59596c01SRobert Mustacchi
163*59596c01SRobert Mustacchi dltran_dump_page(buf, buflen, 0xa0);
164*59596c01SRobert Mustacchi
165*59596c01SRobert Mustacchi if (!dltran_is_8472(buf)) {
166*59596c01SRobert Mustacchi return;
167*59596c01SRobert Mustacchi }
168*59596c01SRobert Mustacchi
169*59596c01SRobert Mustacchi buflen = sizeof (buf);
170*59596c01SRobert Mustacchi if (dltran_read_page(linkid, tranid, 0xa2, buf, &buflen) != 0) {
171*59596c01SRobert Mustacchi dltran_errors++;
172*59596c01SRobert Mustacchi return;
173*59596c01SRobert Mustacchi }
174*59596c01SRobert Mustacchi
175*59596c01SRobert Mustacchi dltran_dump_page(buf, buflen, 0xa2);
176*59596c01SRobert Mustacchi }
177*59596c01SRobert Mustacchi
178*59596c01SRobert Mustacchi static void
dltran_write_page(datalink_id_t linkid,uint_t tranid)179*59596c01SRobert Mustacchi dltran_write_page(datalink_id_t linkid, uint_t tranid)
180*59596c01SRobert Mustacchi {
181*59596c01SRobert Mustacchi uint8_t buf[256];
182*59596c01SRobert Mustacchi size_t buflen = sizeof (buf);
183*59596c01SRobert Mustacchi off_t off;
184*59596c01SRobert Mustacchi
185*59596c01SRobert Mustacchi if (dltran_read_page(linkid, tranid, 0xa0, buf, &buflen) != 0) {
186*59596c01SRobert Mustacchi dltran_errors++;
187*59596c01SRobert Mustacchi return;
188*59596c01SRobert Mustacchi }
189*59596c01SRobert Mustacchi
190*59596c01SRobert Mustacchi off = 0;
191*59596c01SRobert Mustacchi while (buflen > 0) {
192*59596c01SRobert Mustacchi ssize_t ret;
193*59596c01SRobert Mustacchi
194*59596c01SRobert Mustacchi ret = write(dltran_outfd, buf + off, buflen);
195*59596c01SRobert Mustacchi if (ret == -1) {
196*59596c01SRobert Mustacchi (void) fprintf(stderr, "failed to write data "
197*59596c01SRobert Mustacchi "to output file: %s\n", strerror(errno));
198*59596c01SRobert Mustacchi dltran_errors++;
199*59596c01SRobert Mustacchi return;
200*59596c01SRobert Mustacchi }
201*59596c01SRobert Mustacchi
202*59596c01SRobert Mustacchi off += ret;
203*59596c01SRobert Mustacchi buflen -= ret;
204*59596c01SRobert Mustacchi }
205*59596c01SRobert Mustacchi }
206*59596c01SRobert Mustacchi
207*59596c01SRobert Mustacchi static void
dltran_verbose_dump(datalink_id_t linkid,uint_t tranid)208*59596c01SRobert Mustacchi dltran_verbose_dump(datalink_id_t linkid, uint_t tranid)
209*59596c01SRobert Mustacchi {
210*59596c01SRobert Mustacchi uint8_t buf[256];
211*59596c01SRobert Mustacchi size_t buflen = sizeof (buf);
212*59596c01SRobert Mustacchi int ret;
213*59596c01SRobert Mustacchi nvlist_t *nvl;
214*59596c01SRobert Mustacchi
215*59596c01SRobert Mustacchi if (dltran_read_page(linkid, tranid, 0xa0, buf, &buflen) != 0) {
216*59596c01SRobert Mustacchi dltran_errors++;
217*59596c01SRobert Mustacchi return;
218*59596c01SRobert Mustacchi }
219*59596c01SRobert Mustacchi
220*59596c01SRobert Mustacchi ret = libsff_parse(buf, buflen, 0xa0, &nvl);
221*59596c01SRobert Mustacchi if (ret == 0) {
222*59596c01SRobert Mustacchi dump_nvlist(nvl, 8);
223*59596c01SRobert Mustacchi nvlist_free(nvl);
224*59596c01SRobert Mustacchi } else {
225*59596c01SRobert Mustacchi fprintf(stderr, "failed to parse sfp data: %s\n",
226*59596c01SRobert Mustacchi strerror(ret));
227*59596c01SRobert Mustacchi dltran_errors++;
228*59596c01SRobert Mustacchi }
229*59596c01SRobert Mustacchi }
230*59596c01SRobert Mustacchi
231*59596c01SRobert Mustacchi static int
dltran_dump_transceivers(dladm_handle_t hdl,datalink_id_t linkid,void * arg)232*59596c01SRobert Mustacchi dltran_dump_transceivers(dladm_handle_t hdl, datalink_id_t linkid, void *arg)
233*59596c01SRobert Mustacchi {
234*59596c01SRobert Mustacchi dladm_status_t status;
235*59596c01SRobert Mustacchi char name[MAXLINKNAMELEN];
236*59596c01SRobert Mustacchi dld_ioc_gettran_t gt;
237*59596c01SRobert Mustacchi uint_t count, i, tranid = UINT_MAX;
238*59596c01SRobert Mustacchi boolean_t tran_found = B_FALSE;
239*59596c01SRobert Mustacchi uint_t *tranidp = arg;
240*59596c01SRobert Mustacchi
241*59596c01SRobert Mustacchi if (tranidp != NULL)
242*59596c01SRobert Mustacchi tranid = *tranidp;
243*59596c01SRobert Mustacchi
244*59596c01SRobert Mustacchi if ((status = dladm_datalink_id2info(hdl, linkid, NULL, NULL, NULL,
245*59596c01SRobert Mustacchi name, sizeof (name))) != DLADM_STATUS_OK) {
246*59596c01SRobert Mustacchi (void) fprintf(stderr, "failed to get datalink name for link "
247*59596c01SRobert Mustacchi "%d: %s", linkid, dladm_status2str(status,
248*59596c01SRobert Mustacchi dltran_dlerrmsg));
249*59596c01SRobert Mustacchi dltran_errors++;
250*59596c01SRobert Mustacchi return (DLADM_WALK_CONTINUE);
251*59596c01SRobert Mustacchi }
252*59596c01SRobert Mustacchi
253*59596c01SRobert Mustacchi bzero(>, sizeof (gt));
254*59596c01SRobert Mustacchi gt.dgt_linkid = linkid;
255*59596c01SRobert Mustacchi gt.dgt_tran_id = DLDIOC_GETTRAN_GETNTRAN;
256*59596c01SRobert Mustacchi
257*59596c01SRobert Mustacchi if (ioctl(dladm_dld_fd(hdl), DLDIOC_GETTRAN, >) != 0) {
258*59596c01SRobert Mustacchi if (errno != ENOTSUP) {
259*59596c01SRobert Mustacchi (void) fprintf(stderr, "failed to get transceiver "
260*59596c01SRobert Mustacchi "count for device %s: %s\n",
261*59596c01SRobert Mustacchi name, strerror(errno));
262*59596c01SRobert Mustacchi dltran_errors++;
263*59596c01SRobert Mustacchi }
264*59596c01SRobert Mustacchi return (DLADM_WALK_CONTINUE);
265*59596c01SRobert Mustacchi }
266*59596c01SRobert Mustacchi
267*59596c01SRobert Mustacchi count = gt.dgt_tran_id;
268*59596c01SRobert Mustacchi (void) printf("%s: discovered %d transceiver%s\n", name, count,
269*59596c01SRobert Mustacchi count > 1 ? "s" : "");
270*59596c01SRobert Mustacchi for (i = 0; i < count; i++) {
271*59596c01SRobert Mustacchi if (tranid != UINT_MAX && i != tranid)
272*59596c01SRobert Mustacchi continue;
273*59596c01SRobert Mustacchi if (tranid != UINT_MAX)
274*59596c01SRobert Mustacchi tran_found = B_TRUE;
275*59596c01SRobert Mustacchi bzero(>, sizeof (gt));
276*59596c01SRobert Mustacchi gt.dgt_linkid = linkid;
277*59596c01SRobert Mustacchi gt.dgt_tran_id = i;
278*59596c01SRobert Mustacchi
279*59596c01SRobert Mustacchi if (ioctl(dladm_dld_fd(hdl), DLDIOC_GETTRAN, >) != 0) {
280*59596c01SRobert Mustacchi (void) fprintf(stderr, "failed to get tran info for "
281*59596c01SRobert Mustacchi "%s: %s\n", name, strerror(errno));
282*59596c01SRobert Mustacchi dltran_errors++;
283*59596c01SRobert Mustacchi return (DLADM_WALK_CONTINUE);
284*59596c01SRobert Mustacchi }
285*59596c01SRobert Mustacchi
286*59596c01SRobert Mustacchi if (dltran_hex && !gt.dgt_present)
287*59596c01SRobert Mustacchi continue;
288*59596c01SRobert Mustacchi if (!dltran_hex && !dltran_write) {
289*59596c01SRobert Mustacchi (void) printf("\ttransceiver %d present: %s\n", i,
290*59596c01SRobert Mustacchi gt.dgt_present ? "yes" : "no");
291*59596c01SRobert Mustacchi if (!gt.dgt_present)
292*59596c01SRobert Mustacchi continue;
293*59596c01SRobert Mustacchi (void) printf("\ttransceiver %d usable: %s\n", i,
294*59596c01SRobert Mustacchi gt.dgt_usable ? "yes" : "no");
295*59596c01SRobert Mustacchi }
296*59596c01SRobert Mustacchi
297*59596c01SRobert Mustacchi if (dltran_verbose) {
298*59596c01SRobert Mustacchi dltran_verbose_dump(linkid, i);
299*59596c01SRobert Mustacchi }
300*59596c01SRobert Mustacchi
301*59596c01SRobert Mustacchi if (dltran_write) {
302*59596c01SRobert Mustacchi if (!gt.dgt_present) {
303*59596c01SRobert Mustacchi (void) fprintf(stderr, "warning: no "
304*59596c01SRobert Mustacchi "transceiver present in port %d, not "
305*59596c01SRobert Mustacchi "writing\n", i);
306*59596c01SRobert Mustacchi dltran_errors++;
307*59596c01SRobert Mustacchi continue;
308*59596c01SRobert Mustacchi }
309*59596c01SRobert Mustacchi dltran_write_page(linkid, i);
310*59596c01SRobert Mustacchi }
311*59596c01SRobert Mustacchi
312*59596c01SRobert Mustacchi if (dltran_hex) {
313*59596c01SRobert Mustacchi printf("transceiver %d data:\n", i);
314*59596c01SRobert Mustacchi dltran_hex_dump(linkid, i);
315*59596c01SRobert Mustacchi }
316*59596c01SRobert Mustacchi }
317*59596c01SRobert Mustacchi
318*59596c01SRobert Mustacchi if (tranid != UINT_MAX && !tran_found) {
319*59596c01SRobert Mustacchi dltran_errors++;
320*59596c01SRobert Mustacchi (void) fprintf(stderr, "failed to find transceiver %d on "
321*59596c01SRobert Mustacchi "link %s\n", tranid, name);
322*59596c01SRobert Mustacchi }
323*59596c01SRobert Mustacchi
324*59596c01SRobert Mustacchi return (DLADM_WALK_CONTINUE);
325*59596c01SRobert Mustacchi }
326*59596c01SRobert Mustacchi
327*59596c01SRobert Mustacchi
328*59596c01SRobert Mustacchi static void
dltran_usage(const char * fmt,...)329*59596c01SRobert Mustacchi dltran_usage(const char *fmt, ...)
330*59596c01SRobert Mustacchi {
331*59596c01SRobert Mustacchi if (fmt != NULL) {
332*59596c01SRobert Mustacchi va_list ap;
333*59596c01SRobert Mustacchi
334*59596c01SRobert Mustacchi (void) fprintf(stderr, "%s: ", dltran_progname);
335*59596c01SRobert Mustacchi va_start(ap, fmt);
336*59596c01SRobert Mustacchi (void) vfprintf(stderr, fmt, ap);
337*59596c01SRobert Mustacchi va_end(ap);
338*59596c01SRobert Mustacchi }
339*59596c01SRobert Mustacchi
340*59596c01SRobert Mustacchi (void) fprintf(stderr, "Usage: %s [-x | -v | -w file] [tran]...\n"
341*59596c01SRobert Mustacchi "\n"
342*59596c01SRobert Mustacchi "\t-v display all transceiver information\n"
343*59596c01SRobert Mustacchi "\t-w write transceiver data page 0xa0 to file\n"
344*59596c01SRobert Mustacchi "\t-x dump raw hexadecimal for transceiver\n",
345*59596c01SRobert Mustacchi dltran_progname);
346*59596c01SRobert Mustacchi }
347*59596c01SRobert Mustacchi
348*59596c01SRobert Mustacchi int
main(int argc,char * argv[])349*59596c01SRobert Mustacchi main(int argc, char *argv[])
350*59596c01SRobert Mustacchi {
351*59596c01SRobert Mustacchi int c;
352*59596c01SRobert Mustacchi dladm_status_t status;
353*59596c01SRobert Mustacchi const char *outfile = NULL;
354*59596c01SRobert Mustacchi uint_t count = 0;
355*59596c01SRobert Mustacchi
356*59596c01SRobert Mustacchi dltran_progname = basename(argv[0]);
357*59596c01SRobert Mustacchi
358*59596c01SRobert Mustacchi while ((c = getopt(argc, argv, ":xvw:")) != -1) {
359*59596c01SRobert Mustacchi switch (c) {
360*59596c01SRobert Mustacchi case 'v':
361*59596c01SRobert Mustacchi dltran_verbose = B_TRUE;
362*59596c01SRobert Mustacchi break;
363*59596c01SRobert Mustacchi case 'x':
364*59596c01SRobert Mustacchi dltran_hex = B_TRUE;
365*59596c01SRobert Mustacchi break;
366*59596c01SRobert Mustacchi case 'w':
367*59596c01SRobert Mustacchi dltran_write = B_TRUE;
368*59596c01SRobert Mustacchi outfile = optarg;
369*59596c01SRobert Mustacchi break;
370*59596c01SRobert Mustacchi case ':':
371*59596c01SRobert Mustacchi dltran_usage("option -%c requires an "
372*59596c01SRobert Mustacchi "operand\n", optopt);
373*59596c01SRobert Mustacchi return (2);
374*59596c01SRobert Mustacchi case '?':
375*59596c01SRobert Mustacchi default:
376*59596c01SRobert Mustacchi dltran_usage("unknown option: -%c\n", optopt);
377*59596c01SRobert Mustacchi return (2);
378*59596c01SRobert Mustacchi }
379*59596c01SRobert Mustacchi }
380*59596c01SRobert Mustacchi
381*59596c01SRobert Mustacchi argc -= optind;
382*59596c01SRobert Mustacchi argv += optind;
383*59596c01SRobert Mustacchi
384*59596c01SRobert Mustacchi if (dltran_verbose)
385*59596c01SRobert Mustacchi count++;
386*59596c01SRobert Mustacchi if (dltran_hex)
387*59596c01SRobert Mustacchi count++;
388*59596c01SRobert Mustacchi if (dltran_write)
389*59596c01SRobert Mustacchi count++;
390*59596c01SRobert Mustacchi if (count > 1) {
391*59596c01SRobert Mustacchi (void) fprintf(stderr, "only one of -v, -w, and -x may be "
392*59596c01SRobert Mustacchi "specified\n");
393*59596c01SRobert Mustacchi return (2);
394*59596c01SRobert Mustacchi }
395*59596c01SRobert Mustacchi
396*59596c01SRobert Mustacchi if (dltran_write) {
397*59596c01SRobert Mustacchi if ((dltran_outfd = open(outfile, O_RDWR | O_TRUNC | O_CREAT,
398*59596c01SRobert Mustacchi 0644)) < 0) {
399*59596c01SRobert Mustacchi (void) fprintf(stderr, "failed to open output file "
400*59596c01SRobert Mustacchi "%s: %s\n", outfile, strerror(errno));
401*59596c01SRobert Mustacchi return (1);
402*59596c01SRobert Mustacchi }
403*59596c01SRobert Mustacchi }
404*59596c01SRobert Mustacchi
405*59596c01SRobert Mustacchi if ((status = dladm_open(&dltran_hdl)) != DLADM_STATUS_OK) {
406*59596c01SRobert Mustacchi (void) fprintf(stderr, "failed to open /dev/dld: %s\n",
407*59596c01SRobert Mustacchi dladm_status2str(status, dltran_dlerrmsg));
408*59596c01SRobert Mustacchi return (1);
409*59596c01SRobert Mustacchi }
410*59596c01SRobert Mustacchi
411*59596c01SRobert Mustacchi if (argc == 0) {
412*59596c01SRobert Mustacchi (void) dladm_walk_datalink_id(dltran_dump_transceivers,
413*59596c01SRobert Mustacchi dltran_hdl, NULL, DATALINK_CLASS_PHYS,
414*59596c01SRobert Mustacchi DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
415*59596c01SRobert Mustacchi } else {
416*59596c01SRobert Mustacchi int i;
417*59596c01SRobert Mustacchi char *c;
418*59596c01SRobert Mustacchi
419*59596c01SRobert Mustacchi for (i = 0; i < argc; i++) {
420*59596c01SRobert Mustacchi uint_t tran;
421*59596c01SRobert Mustacchi uint_t *tranidp = NULL;
422*59596c01SRobert Mustacchi datalink_id_t linkid;
423*59596c01SRobert Mustacchi
424*59596c01SRobert Mustacchi if ((c = strrchr(argv[i], '/')) != NULL) {
425*59596c01SRobert Mustacchi unsigned long u;
426*59596c01SRobert Mustacchi char *eptr;
427*59596c01SRobert Mustacchi
428*59596c01SRobert Mustacchi c++;
429*59596c01SRobert Mustacchi errno = 0;
430*59596c01SRobert Mustacchi u = strtoul(c, &eptr, 10);
431*59596c01SRobert Mustacchi if (errno != 0 || *eptr != '\0' ||
432*59596c01SRobert Mustacchi u >= UINT_MAX) {
433*59596c01SRobert Mustacchi (void) fprintf(stderr, "failed to "
434*59596c01SRobert Mustacchi "parse link/transceiver: %s\n",
435*59596c01SRobert Mustacchi argv[i]);
436*59596c01SRobert Mustacchi return (1);
437*59596c01SRobert Mustacchi }
438*59596c01SRobert Mustacchi c--;
439*59596c01SRobert Mustacchi *c = '\0';
440*59596c01SRobert Mustacchi tran = (uint_t)u;
441*59596c01SRobert Mustacchi tranidp = &tran;
442*59596c01SRobert Mustacchi }
443*59596c01SRobert Mustacchi
444*59596c01SRobert Mustacchi if ((status = dladm_name2info(dltran_hdl, argv[i],
445*59596c01SRobert Mustacchi &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) {
446*59596c01SRobert Mustacchi (void) fprintf(stderr, "failed to get link "
447*59596c01SRobert Mustacchi "id for link %s: %s\n", argv[i],
448*59596c01SRobert Mustacchi dladm_status2str(status, dltran_dlerrmsg));
449*59596c01SRobert Mustacchi return (1);
450*59596c01SRobert Mustacchi }
451*59596c01SRobert Mustacchi
452*59596c01SRobert Mustacchi (void) dltran_dump_transceivers(dltran_hdl, linkid,
453*59596c01SRobert Mustacchi tranidp);
454*59596c01SRobert Mustacchi }
455*59596c01SRobert Mustacchi }
456*59596c01SRobert Mustacchi
457*59596c01SRobert Mustacchi return (dltran_errors != 0 ? 1 : 0);
458*59596c01SRobert Mustacchi }
459