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