1*4d210590SRobert Mustacchi /*
2*4d210590SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*4d210590SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*4d210590SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*4d210590SRobert Mustacchi * 1.0 of the CDDL.
6*4d210590SRobert Mustacchi *
7*4d210590SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*4d210590SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*4d210590SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*4d210590SRobert Mustacchi */
11*4d210590SRobert Mustacchi
12*4d210590SRobert Mustacchi /*
13*4d210590SRobert Mustacchi * Copyright (c) 2017, Joyent, Inc.
14*4d210590SRobert Mustacchi */
15*4d210590SRobert Mustacchi
16*4d210590SRobert Mustacchi /*
17*4d210590SRobert Mustacchi * Private utility to get and set LED information on NICs. This should really
18*4d210590SRobert Mustacchi * all be integrated into FM. Until we have figured out that plumbing, this
19*4d210590SRobert Mustacchi * allows us to have a little something that we can use to drive work.
20*4d210590SRobert Mustacchi */
21*4d210590SRobert Mustacchi
22*4d210590SRobert Mustacchi #include <unistd.h>
23*4d210590SRobert Mustacchi #include <stdio.h>
24*4d210590SRobert Mustacchi #include <stdarg.h>
25*4d210590SRobert Mustacchi #include <libgen.h>
26*4d210590SRobert Mustacchi #include <string.h>
27*4d210590SRobert Mustacchi #include <stdlib.h>
28*4d210590SRobert Mustacchi #include <errno.h>
29*4d210590SRobert Mustacchi #include <strings.h>
30*4d210590SRobert Mustacchi
31*4d210590SRobert Mustacchi #include <libdladm.h>
32*4d210590SRobert Mustacchi #include <libdllink.h>
33*4d210590SRobert Mustacchi #include <sys/mac.h>
34*4d210590SRobert Mustacchi #include <sys/dld.h>
35*4d210590SRobert Mustacchi #include <sys/dld_ioc.h>
36*4d210590SRobert Mustacchi
37*4d210590SRobert Mustacchi static const char *dlled_progname;
38*4d210590SRobert Mustacchi static dladm_handle_t dlled_hdl;
39*4d210590SRobert Mustacchi static char dlled_dlerrmsg[DLADM_STRSIZE];
40*4d210590SRobert Mustacchi
41*4d210590SRobert Mustacchi typedef struct dlled_led_map {
42*4d210590SRobert Mustacchi const char *dlm_name;
43*4d210590SRobert Mustacchi mac_led_mode_t dlm_bits;
44*4d210590SRobert Mustacchi } dlled_led_map_t;
45*4d210590SRobert Mustacchi
46*4d210590SRobert Mustacchi static dlled_led_map_t dlled_map[] = {
47*4d210590SRobert Mustacchi { "default", MAC_LED_DEFAULT },
48*4d210590SRobert Mustacchi { "off", MAC_LED_OFF },
49*4d210590SRobert Mustacchi { "on", MAC_LED_ON },
50*4d210590SRobert Mustacchi { "ident", MAC_LED_IDENT }
51*4d210590SRobert Mustacchi };
52*4d210590SRobert Mustacchi
53*4d210590SRobert Mustacchi #define DLLED_MAP_NENTRIES \
54*4d210590SRobert Mustacchi (sizeof (dlled_map) / sizeof (dlled_led_map_t))
55*4d210590SRobert Mustacchi
56*4d210590SRobert Mustacchi static void
dlled_usage(const char * fmt,...)57*4d210590SRobert Mustacchi dlled_usage(const char *fmt, ...)
58*4d210590SRobert Mustacchi {
59*4d210590SRobert Mustacchi if (fmt != NULL) {
60*4d210590SRobert Mustacchi va_list ap;
61*4d210590SRobert Mustacchi
62*4d210590SRobert Mustacchi (void) fprintf(stderr, "%s: ", dlled_progname);
63*4d210590SRobert Mustacchi va_start(ap, fmt);
64*4d210590SRobert Mustacchi (void) vfprintf(stderr, fmt, ap);
65*4d210590SRobert Mustacchi va_end(ap);
66*4d210590SRobert Mustacchi }
67*4d210590SRobert Mustacchi
68*4d210590SRobert Mustacchi (void) fprintf(stderr, "Usage: %s [-s mode] [link]\n"
69*4d210590SRobert Mustacchi "\n"
70*4d210590SRobert Mustacchi "\t-s mode set LED to mode\n",
71*4d210590SRobert Mustacchi dlled_progname);
72*4d210590SRobert Mustacchi }
73*4d210590SRobert Mustacchi
74*4d210590SRobert Mustacchi static mac_led_mode_t
dlled_parse_mode(const char * orig)75*4d210590SRobert Mustacchi dlled_parse_mode(const char *orig)
76*4d210590SRobert Mustacchi {
77*4d210590SRobert Mustacchi char *mode;
78*4d210590SRobert Mustacchi char *part;
79*4d210590SRobert Mustacchi mac_led_mode_t m = 0;
80*4d210590SRobert Mustacchi
81*4d210590SRobert Mustacchi mode = strdup(orig);
82*4d210590SRobert Mustacchi if (mode == NULL) {
83*4d210590SRobert Mustacchi fprintf(stderr, "failed to allocate memory to dup led "
84*4d210590SRobert Mustacchi "mode: %s\n", strerror(errno));
85*4d210590SRobert Mustacchi exit(1);
86*4d210590SRobert Mustacchi }
87*4d210590SRobert Mustacchi
88*4d210590SRobert Mustacchi part = strtok(mode, ",");
89*4d210590SRobert Mustacchi while (part != NULL) {
90*4d210590SRobert Mustacchi int i;
91*4d210590SRobert Mustacchi
92*4d210590SRobert Mustacchi for (i = 0; i < DLLED_MAP_NENTRIES; i++) {
93*4d210590SRobert Mustacchi if (strcmp(dlled_map[i].dlm_name, part) == 0) {
94*4d210590SRobert Mustacchi m |= dlled_map[i].dlm_bits;
95*4d210590SRobert Mustacchi break;
96*4d210590SRobert Mustacchi }
97*4d210590SRobert Mustacchi }
98*4d210590SRobert Mustacchi
99*4d210590SRobert Mustacchi if (i == DLLED_MAP_NENTRIES) {
100*4d210590SRobert Mustacchi fprintf(stderr, "unknown LED mode: %s\n", part);
101*4d210590SRobert Mustacchi exit(1);
102*4d210590SRobert Mustacchi }
103*4d210590SRobert Mustacchi
104*4d210590SRobert Mustacchi part = strtok(NULL, ",");
105*4d210590SRobert Mustacchi }
106*4d210590SRobert Mustacchi
107*4d210590SRobert Mustacchi free(mode);
108*4d210590SRobert Mustacchi if (m == 0) {
109*4d210590SRobert Mustacchi fprintf(stderr, "failed to parse %s: no valid modes "
110*4d210590SRobert Mustacchi "specified\n", orig);
111*4d210590SRobert Mustacchi exit(1);
112*4d210590SRobert Mustacchi }
113*4d210590SRobert Mustacchi
114*4d210590SRobert Mustacchi return (m);
115*4d210590SRobert Mustacchi }
116*4d210590SRobert Mustacchi
117*4d210590SRobert Mustacchi static void
dlled_mode2str(mac_led_mode_t mode,char * buf,size_t len)118*4d210590SRobert Mustacchi dlled_mode2str(mac_led_mode_t mode, char *buf, size_t len)
119*4d210590SRobert Mustacchi {
120*4d210590SRobert Mustacchi int i;
121*4d210590SRobert Mustacchi boolean_t first = B_TRUE;
122*4d210590SRobert Mustacchi mac_led_mode_t orig = mode;
123*4d210590SRobert Mustacchi
124*4d210590SRobert Mustacchi for (i = 0; i < DLLED_MAP_NENTRIES; i++) {
125*4d210590SRobert Mustacchi if ((mode & dlled_map[i].dlm_bits) != 0) {
126*4d210590SRobert Mustacchi if (first) {
127*4d210590SRobert Mustacchi first = B_FALSE;
128*4d210590SRobert Mustacchi } else {
129*4d210590SRobert Mustacchi (void) strlcat(buf, ",", len);
130*4d210590SRobert Mustacchi }
131*4d210590SRobert Mustacchi (void) strlcat(buf, dlled_map[i].dlm_name, len);
132*4d210590SRobert Mustacchi mode &= ~dlled_map[i].dlm_bits;
133*4d210590SRobert Mustacchi }
134*4d210590SRobert Mustacchi }
135*4d210590SRobert Mustacchi
136*4d210590SRobert Mustacchi if (mode != 0) {
137*4d210590SRobert Mustacchi (void) snprintf(buf, len, "unknown mode: 0x%x\n", orig);
138*4d210590SRobert Mustacchi }
139*4d210590SRobert Mustacchi }
140*4d210590SRobert Mustacchi
141*4d210590SRobert Mustacchi
142*4d210590SRobert Mustacchi static int
dlled_set(const char * link,mac_led_mode_t mode)143*4d210590SRobert Mustacchi dlled_set(const char *link, mac_led_mode_t mode)
144*4d210590SRobert Mustacchi {
145*4d210590SRobert Mustacchi datalink_id_t linkid;
146*4d210590SRobert Mustacchi dladm_status_t status;
147*4d210590SRobert Mustacchi dld_ioc_led_t dil;
148*4d210590SRobert Mustacchi
149*4d210590SRobert Mustacchi if ((status = dladm_name2info(dlled_hdl, link, &linkid, NULL, NULL,
150*4d210590SRobert Mustacchi NULL)) != DLADM_STATUS_OK) {
151*4d210590SRobert Mustacchi (void) fprintf(stderr, "failed to get link "
152*4d210590SRobert Mustacchi "id for link %s: %s\n", link,
153*4d210590SRobert Mustacchi dladm_status2str(status, dlled_dlerrmsg));
154*4d210590SRobert Mustacchi return (1);
155*4d210590SRobert Mustacchi }
156*4d210590SRobert Mustacchi
157*4d210590SRobert Mustacchi bzero(&dil, sizeof (dil));
158*4d210590SRobert Mustacchi dil.dil_linkid = linkid;
159*4d210590SRobert Mustacchi dil.dil_active = mode;
160*4d210590SRobert Mustacchi
161*4d210590SRobert Mustacchi if (ioctl(dladm_dld_fd(dlled_hdl), DLDIOC_SETLED, &dil) != 0) {
162*4d210590SRobert Mustacchi (void) fprintf(stderr, "failed to set LED on "
163*4d210590SRobert Mustacchi "device %s: %s\n", link, strerror(errno));
164*4d210590SRobert Mustacchi return (1);
165*4d210590SRobert Mustacchi }
166*4d210590SRobert Mustacchi
167*4d210590SRobert Mustacchi return (0);
168*4d210590SRobert Mustacchi }
169*4d210590SRobert Mustacchi
170*4d210590SRobert Mustacchi static int
dlled_get_led(dladm_handle_t hdl,datalink_id_t linkid,void * arg)171*4d210590SRobert Mustacchi dlled_get_led(dladm_handle_t hdl, datalink_id_t linkid, void *arg)
172*4d210590SRobert Mustacchi {
173*4d210590SRobert Mustacchi dladm_status_t status;
174*4d210590SRobert Mustacchi char name[MAXLINKNAMELEN];
175*4d210590SRobert Mustacchi char supported[128], active[128];
176*4d210590SRobert Mustacchi dld_ioc_led_t dil;
177*4d210590SRobert Mustacchi
178*4d210590SRobert Mustacchi if ((status = dladm_datalink_id2info(hdl, linkid, NULL, NULL, NULL,
179*4d210590SRobert Mustacchi name, sizeof (name))) != DLADM_STATUS_OK) {
180*4d210590SRobert Mustacchi (void) fprintf(stderr, "failed to get datalink name for link "
181*4d210590SRobert Mustacchi "%d: %s", linkid, dladm_status2str(status,
182*4d210590SRobert Mustacchi dlled_dlerrmsg));
183*4d210590SRobert Mustacchi return (DLADM_WALK_CONTINUE);
184*4d210590SRobert Mustacchi }
185*4d210590SRobert Mustacchi
186*4d210590SRobert Mustacchi
187*4d210590SRobert Mustacchi
188*4d210590SRobert Mustacchi bzero(&dil, sizeof (dil));
189*4d210590SRobert Mustacchi dil.dil_linkid = linkid;
190*4d210590SRobert Mustacchi
191*4d210590SRobert Mustacchi if (ioctl(dladm_dld_fd(hdl), DLDIOC_GETLED, &dil) != 0) {
192*4d210590SRobert Mustacchi (void) fprintf(stderr, "failed to get LED information for "
193*4d210590SRobert Mustacchi "device %s: %s\n", name, strerror(errno));
194*4d210590SRobert Mustacchi return (DLADM_WALK_CONTINUE);
195*4d210590SRobert Mustacchi }
196*4d210590SRobert Mustacchi
197*4d210590SRobert Mustacchi active[0] = '\0';
198*4d210590SRobert Mustacchi supported[0] = '\0';
199*4d210590SRobert Mustacchi dlled_mode2str(dil.dil_active, active, sizeof (active));
200*4d210590SRobert Mustacchi dlled_mode2str(dil.dil_supported, supported, sizeof (supported));
201*4d210590SRobert Mustacchi
202*4d210590SRobert Mustacchi printf("%-20s %-12s %s\n", name, active, supported);
203*4d210590SRobert Mustacchi
204*4d210590SRobert Mustacchi return (DLADM_WALK_CONTINUE);
205*4d210590SRobert Mustacchi }
206*4d210590SRobert Mustacchi
207*4d210590SRobert Mustacchi int
main(int argc,char * argv[])208*4d210590SRobert Mustacchi main(int argc, char *argv[])
209*4d210590SRobert Mustacchi {
210*4d210590SRobert Mustacchi int c, ret;
211*4d210590SRobert Mustacchi boolean_t opt_s = B_FALSE;
212*4d210590SRobert Mustacchi mac_led_mode_t set_mode = 0;
213*4d210590SRobert Mustacchi dladm_status_t status;
214*4d210590SRobert Mustacchi
215*4d210590SRobert Mustacchi dlled_progname = basename(argv[0]);
216*4d210590SRobert Mustacchi
217*4d210590SRobert Mustacchi while ((c = getopt(argc, argv, ":s:")) != -1) {
218*4d210590SRobert Mustacchi switch (c) {
219*4d210590SRobert Mustacchi case 's':
220*4d210590SRobert Mustacchi opt_s = B_TRUE;
221*4d210590SRobert Mustacchi set_mode = dlled_parse_mode(optarg);
222*4d210590SRobert Mustacchi break;
223*4d210590SRobert Mustacchi case ':':
224*4d210590SRobert Mustacchi dlled_usage("option -%c requires an operand\n", optopt);
225*4d210590SRobert Mustacchi return (2);
226*4d210590SRobert Mustacchi case '?':
227*4d210590SRobert Mustacchi default:
228*4d210590SRobert Mustacchi dlled_usage("unknown option: -%c\n", optopt);
229*4d210590SRobert Mustacchi return (2);
230*4d210590SRobert Mustacchi }
231*4d210590SRobert Mustacchi }
232*4d210590SRobert Mustacchi
233*4d210590SRobert Mustacchi argc -= optind;
234*4d210590SRobert Mustacchi argv += optind;
235*4d210590SRobert Mustacchi
236*4d210590SRobert Mustacchi if (opt_s && argc > 1) {
237*4d210590SRobert Mustacchi dlled_usage("-s only operates on a single datalink\n");
238*4d210590SRobert Mustacchi return (2);
239*4d210590SRobert Mustacchi }
240*4d210590SRobert Mustacchi
241*4d210590SRobert Mustacchi if (opt_s && argc <= 0) {
242*4d210590SRobert Mustacchi dlled_usage("-s requires a datalink\n");
243*4d210590SRobert Mustacchi return (2);
244*4d210590SRobert Mustacchi }
245*4d210590SRobert Mustacchi
246*4d210590SRobert Mustacchi if ((status = dladm_open(&dlled_hdl)) != DLADM_STATUS_OK) {
247*4d210590SRobert Mustacchi (void) fprintf(stderr, "failed to open /dev/dld: %s\n",
248*4d210590SRobert Mustacchi dladm_status2str(status, dlled_dlerrmsg));
249*4d210590SRobert Mustacchi return (1);
250*4d210590SRobert Mustacchi }
251*4d210590SRobert Mustacchi
252*4d210590SRobert Mustacchi if (opt_s) {
253*4d210590SRobert Mustacchi return (dlled_set(argv[0], set_mode));
254*4d210590SRobert Mustacchi }
255*4d210590SRobert Mustacchi
256*4d210590SRobert Mustacchi (void) printf("%-20s %-12s %s\n", "LINK", "ACTIVE", "SUPPORTED");
257*4d210590SRobert Mustacchi
258*4d210590SRobert Mustacchi ret = 0;
259*4d210590SRobert Mustacchi if (argc == 0) {
260*4d210590SRobert Mustacchi (void) dladm_walk_datalink_id(dlled_get_led, dlled_hdl, NULL,
261*4d210590SRobert Mustacchi DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE,
262*4d210590SRobert Mustacchi DLADM_OPT_ACTIVE);
263*4d210590SRobert Mustacchi } else {
264*4d210590SRobert Mustacchi int i, dlret;
265*4d210590SRobert Mustacchi datalink_id_t linkid;
266*4d210590SRobert Mustacchi
267*4d210590SRobert Mustacchi for (i = 0; i < argc; i++) {
268*4d210590SRobert Mustacchi if ((status = dladm_name2info(dlled_hdl, argv[i],
269*4d210590SRobert Mustacchi &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) {
270*4d210590SRobert Mustacchi (void) fprintf(stderr, "failed to get link "
271*4d210590SRobert Mustacchi "id for link %s: %s\n", link,
272*4d210590SRobert Mustacchi dladm_status2str(status, dlled_dlerrmsg));
273*4d210590SRobert Mustacchi return (1);
274*4d210590SRobert Mustacchi }
275*4d210590SRobert Mustacchi
276*4d210590SRobert Mustacchi dlret = dlled_get_led(dlled_hdl, linkid, NULL);
277*4d210590SRobert Mustacchi if (dlret != DLADM_WALK_CONTINUE) {
278*4d210590SRobert Mustacchi ret = 1;
279*4d210590SRobert Mustacchi break;
280*4d210590SRobert Mustacchi }
281*4d210590SRobert Mustacchi }
282*4d210590SRobert Mustacchi }
283*4d210590SRobert Mustacchi
284*4d210590SRobert Mustacchi return (ret);
285*4d210590SRobert Mustacchi }
286