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