1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2000,2002 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include "etheraddr.h" 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <stdio.h> 32*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 33*7c478bd9Sstevel@tonic-gate #include <string.h> 34*7c478bd9Sstevel@tonic-gate #include <strings.h> 35*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 36*7c478bd9Sstevel@tonic-gate #include <stropts.h> 37*7c478bd9Sstevel@tonic-gate #include <unistd.h> 38*7c478bd9Sstevel@tonic-gate #include <uuid/uuid.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/sockio.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #include <netdb.h> 43*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 44*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #include <sys/dlpi.h> 47*7c478bd9Sstevel@tonic-gate /* 48*7c478bd9Sstevel@tonic-gate * debugging flag 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate static int debug = 0; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate /* Timeout for DLPI acks */ 54*7c478bd9Sstevel@tonic-gate static int dlpi_timeout = DLPI_TIMEOUT; 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate /* 57*7c478bd9Sstevel@tonic-gate * Global functions 58*7c478bd9Sstevel@tonic-gate */ 59*7c478bd9Sstevel@tonic-gate int dlpi_get_address(char *, struct ether_addr *); 60*7c478bd9Sstevel@tonic-gate int get_net_if_names(char ***); 61*7c478bd9Sstevel@tonic-gate void free_net_if_names(char **); 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* 65*7c478bd9Sstevel@tonic-gate * local functions 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate static int dlpi_info_req(int, dl_info_ack_t *); 68*7c478bd9Sstevel@tonic-gate static int timed_getmsg(int, struct strbuf *, int *, int, char *, char *); 69*7c478bd9Sstevel@tonic-gate static int ifrm_num(char *, unsigned int *); 70*7c478bd9Sstevel@tonic-gate static int open_dev(dev_att_t *, int, int *, int); 71*7c478bd9Sstevel@tonic-gate static void pf_dev_att(dev_att_t *); 72*7c478bd9Sstevel@tonic-gate static void parse_ifname(dev_att_t *); 73*7c478bd9Sstevel@tonic-gate static int ifname_open(char *, dev_att_t *); 74*7c478bd9Sstevel@tonic-gate static int dlpi_open_attach(char *); 75*7c478bd9Sstevel@tonic-gate static int dlpi_attach(int, int, int); 76*7c478bd9Sstevel@tonic-gate static int dlpi_get_phys(int, uchar_t *); 77*7c478bd9Sstevel@tonic-gate static int dlpi_info_req(int, dl_info_ack_t *); 78*7c478bd9Sstevel@tonic-gate static int timed_getmsg(int, struct strbuf *, int *, int, char *, char *); 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* 81*7c478bd9Sstevel@tonic-gate * get an individual arp entry 82*7c478bd9Sstevel@tonic-gate */ 83*7c478bd9Sstevel@tonic-gate int 84*7c478bd9Sstevel@tonic-gate arp_get(uuid_node_t *node) 85*7c478bd9Sstevel@tonic-gate { 86*7c478bd9Sstevel@tonic-gate struct utsname name; 87*7c478bd9Sstevel@tonic-gate struct arpreq ar; 88*7c478bd9Sstevel@tonic-gate struct hostent *hp; 89*7c478bd9Sstevel@tonic-gate struct sockaddr_in *sin; 90*7c478bd9Sstevel@tonic-gate int s; 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate if (uname(&name) == -1) { 93*7c478bd9Sstevel@tonic-gate return (-1); 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate (void) memset(&ar, 0, sizeof (ar)); 96*7c478bd9Sstevel@tonic-gate ar.arp_pa.sa_family = AF_INET; 97*7c478bd9Sstevel@tonic-gate /* LINTED pointer */ 98*7c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *)&ar.arp_pa; 99*7c478bd9Sstevel@tonic-gate sin->sin_family = AF_INET; 100*7c478bd9Sstevel@tonic-gate sin->sin_addr.s_addr = inet_addr(name.nodename); 101*7c478bd9Sstevel@tonic-gate if (sin->sin_addr.s_addr == (in_addr_t)-1) { 102*7c478bd9Sstevel@tonic-gate hp = gethostbyname(name.nodename); 103*7c478bd9Sstevel@tonic-gate if (hp == NULL) { 104*7c478bd9Sstevel@tonic-gate return (-1); 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate (void) memcpy(&sin->sin_addr, hp->h_addr, 107*7c478bd9Sstevel@tonic-gate sizeof (sin->sin_addr)); 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate s = socket(AF_INET, SOCK_DGRAM, 0); 110*7c478bd9Sstevel@tonic-gate if (s < 0) { 111*7c478bd9Sstevel@tonic-gate return (-1); 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate if (ioctl(s, SIOCGARP, (caddr_t)&ar) < 0) { 114*7c478bd9Sstevel@tonic-gate (void) close(s); 115*7c478bd9Sstevel@tonic-gate return (-1); 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate (void) close(s); 118*7c478bd9Sstevel@tonic-gate if (ar.arp_flags & ATF_COM) { 119*7c478bd9Sstevel@tonic-gate bcopy(&ar.arp_ha.sa_data, node, 6); 120*7c478bd9Sstevel@tonic-gate } else 121*7c478bd9Sstevel@tonic-gate return (-1); 122*7c478bd9Sstevel@tonic-gate return (0); 123*7c478bd9Sstevel@tonic-gate } 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate /* Get all interface names. This will include IPv6 names. */ 127*7c478bd9Sstevel@tonic-gate int 128*7c478bd9Sstevel@tonic-gate get_net_if_names(char ***names) 129*7c478bd9Sstevel@tonic-gate { 130*7c478bd9Sstevel@tonic-gate char *buf; /* buffer for socket info */ 131*7c478bd9Sstevel@tonic-gate int sd; /* socket descriptor */ 132*7c478bd9Sstevel@tonic-gate int ifn; /* interface count structure */ 133*7c478bd9Sstevel@tonic-gate struct ifconf ifc; /* interface config buffer */ 134*7c478bd9Sstevel@tonic-gate struct ifreq *ifrp; 135*7c478bd9Sstevel@tonic-gate int numifs; 136*7c478bd9Sstevel@tonic-gate char **tmpnames; 137*7c478bd9Sstevel@tonic-gate int n; 138*7c478bd9Sstevel@tonic-gate char *tmpname; 139*7c478bd9Sstevel@tonic-gate sd = socket(AF_INET, SOCK_DGRAM, 0); 140*7c478bd9Sstevel@tonic-gate if (sd < 0) 141*7c478bd9Sstevel@tonic-gate return (-1); 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate if (ioctl(sd, SIOCGIFNUM, &ifn) < 0) { 144*7c478bd9Sstevel@tonic-gate (void) close(sd); 145*7c478bd9Sstevel@tonic-gate return (-1); 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate if (!(buf = malloc(ifn * sizeof (struct ifreq)))) { 149*7c478bd9Sstevel@tonic-gate (void) close(sd); 150*7c478bd9Sstevel@tonic-gate return (-1); 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate ifc.ifc_len = ifn * sizeof (struct ifreq); 154*7c478bd9Sstevel@tonic-gate ifc.ifc_buf = (caddr_t)buf; 155*7c478bd9Sstevel@tonic-gate if (ioctl(sd, SIOCGIFCONF, (char *)&ifc) < 0) { 156*7c478bd9Sstevel@tonic-gate free(buf); 157*7c478bd9Sstevel@tonic-gate (void) close(sd); 158*7c478bd9Sstevel@tonic-gate return (-1); 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate (void) close(sd); 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate ifrp = ifc.ifc_req; 163*7c478bd9Sstevel@tonic-gate numifs = ifc.ifc_len / sizeof (struct ifreq); 164*7c478bd9Sstevel@tonic-gate tmpnames = (char **)calloc((numifs+1), sizeof (char *)); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate if (tmpnames == NULL) { 167*7c478bd9Sstevel@tonic-gate free(buf); 168*7c478bd9Sstevel@tonic-gate return (-1); 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate for (n = 0; n < numifs; n++, ifrp++) { 171*7c478bd9Sstevel@tonic-gate if ((tmpnames[n] = strdup(ifrp->ifr_name)) == NULL) 172*7c478bd9Sstevel@tonic-gate break; 173*7c478bd9Sstevel@tonic-gate } 174*7c478bd9Sstevel@tonic-gate free(buf); 175*7c478bd9Sstevel@tonic-gate *names = tmpnames; 176*7c478bd9Sstevel@tonic-gate return (0); 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate /* 180*7c478bd9Sstevel@tonic-gate * frees previously-allocated array from get_net_if_names 181*7c478bd9Sstevel@tonic-gate */ 182*7c478bd9Sstevel@tonic-gate void 183*7c478bd9Sstevel@tonic-gate free_net_if_names(char **ifnames) 184*7c478bd9Sstevel@tonic-gate { 185*7c478bd9Sstevel@tonic-gate int i; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate i = 0; 188*7c478bd9Sstevel@tonic-gate while (ifnames[i] != NULL) { 189*7c478bd9Sstevel@tonic-gate free(ifnames[i]); 190*7c478bd9Sstevel@tonic-gate i++; 191*7c478bd9Sstevel@tonic-gate } 192*7c478bd9Sstevel@tonic-gate free(ifnames); 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate /* 197*7c478bd9Sstevel@tonic-gate * attempt to remove ppa from end of file name 198*7c478bd9Sstevel@tonic-gate * return -1 if none found 199*7c478bd9Sstevel@tonic-gate * return ppa if found and remove the ppa from the filename 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate static int 202*7c478bd9Sstevel@tonic-gate ifrm_num(char *fname, unsigned int *ppa) 203*7c478bd9Sstevel@tonic-gate { 204*7c478bd9Sstevel@tonic-gate int i; 205*7c478bd9Sstevel@tonic-gate uint_t p = 0; 206*7c478bd9Sstevel@tonic-gate unsigned int m = 1; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate i = strlen(fname) - 1; 209*7c478bd9Sstevel@tonic-gate while (i >= 0 && '0' <= fname[i] && fname[i] <= '9') { 210*7c478bd9Sstevel@tonic-gate p += (fname[i] - '0')*m; 211*7c478bd9Sstevel@tonic-gate m *= 10; 212*7c478bd9Sstevel@tonic-gate i--; 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate if (m == 1) { 215*7c478bd9Sstevel@tonic-gate return (-1); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate fname[i + 1] = '\0'; 218*7c478bd9Sstevel@tonic-gate *ppa = p; 219*7c478bd9Sstevel@tonic-gate return (0); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate /* 223*7c478bd9Sstevel@tonic-gate * Open the device defined in dev_att with the given mode starting with 224*7c478bd9Sstevel@tonic-gate * the module indicated by mod_cnt (1 indexed). If mod_cnt > 0, fd must 225*7c478bd9Sstevel@tonic-gate * contain the file descriptor that modules are to be pushed on. 226*7c478bd9Sstevel@tonic-gate * Returns -1 if device could not be opened, the index of 227*7c478bd9Sstevel@tonic-gate * the module that could not be pushed or 0 on success. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate static int 230*7c478bd9Sstevel@tonic-gate open_dev(dev_att_t *dev_att, int mode, int *fd, int mod_cnt) 231*7c478bd9Sstevel@tonic-gate { 232*7c478bd9Sstevel@tonic-gate int cnt; 233*7c478bd9Sstevel@tonic-gate int local_fd; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate if (debug) 236*7c478bd9Sstevel@tonic-gate (void) printf("open_dev: ifname: %s : dev %s fd %d " 237*7c478bd9Sstevel@tonic-gate " mod_cnt %d\n", 238*7c478bd9Sstevel@tonic-gate dev_att->ifname, dev_att->devname, *fd, mod_cnt); 239*7c478bd9Sstevel@tonic-gate /* 240*7c478bd9Sstevel@tonic-gate * if no module count is given, try and open the device 241*7c478bd9Sstevel@tonic-gate */ 242*7c478bd9Sstevel@tonic-gate if (mod_cnt == 0) { 243*7c478bd9Sstevel@tonic-gate if (debug) 244*7c478bd9Sstevel@tonic-gate (void) printf("open_dev: opening %s\n", 245*7c478bd9Sstevel@tonic-gate dev_att->devname); 246*7c478bd9Sstevel@tonic-gate if ((local_fd = open(dev_att->devname, mode)) < 0) { 247*7c478bd9Sstevel@tonic-gate if (debug) { 248*7c478bd9Sstevel@tonic-gate perror("open_dev: device"); 249*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate *fd = local_fd; 252*7c478bd9Sstevel@tonic-gate return (-1); 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate *fd = local_fd; 255*7c478bd9Sstevel@tonic-gate cnt = 1; 256*7c478bd9Sstevel@tonic-gate } else { 257*7c478bd9Sstevel@tonic-gate local_fd = *fd; 258*7c478bd9Sstevel@tonic-gate cnt = mod_cnt; 259*7c478bd9Sstevel@tonic-gate } 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate /* 262*7c478bd9Sstevel@tonic-gate * Try and push modules (if any) onto the device stream 263*7c478bd9Sstevel@tonic-gate */ 264*7c478bd9Sstevel@tonic-gate for (; cnt <= dev_att->mod_cnt; cnt++) { 265*7c478bd9Sstevel@tonic-gate if (debug) 266*7c478bd9Sstevel@tonic-gate (void) printf(" pushing: mod %s", 267*7c478bd9Sstevel@tonic-gate dev_att->modlist[cnt - 1]); 268*7c478bd9Sstevel@tonic-gate if (ioctl(local_fd, I_PUSH, dev_att->modlist[cnt - 1]) == -1) { 269*7c478bd9Sstevel@tonic-gate if (debug) { 270*7c478bd9Sstevel@tonic-gate perror("open_dev: push"); 271*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate return (cnt); 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate if (debug) 277*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 278*7c478bd9Sstevel@tonic-gate return (0); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate /* 282*7c478bd9Sstevel@tonic-gate * Debug routine to print out dev_att_t structure 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate static void 285*7c478bd9Sstevel@tonic-gate pf_dev_att(dev_att_t *dev_att) 286*7c478bd9Sstevel@tonic-gate { 287*7c478bd9Sstevel@tonic-gate int cnt; 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate (void) printf("\tifname: %s\n", dev_att->ifname); 290*7c478bd9Sstevel@tonic-gate (void) printf("\t style: %d\n", dev_att->style); 291*7c478bd9Sstevel@tonic-gate (void) printf("\t ppa: %d\n", dev_att->ppa); 292*7c478bd9Sstevel@tonic-gate (void) printf("\t mod_cnt: %d\n", dev_att->mod_cnt); 293*7c478bd9Sstevel@tonic-gate (void) printf("\t devname: %s\n", dev_att->devname); 294*7c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < dev_att->mod_cnt; cnt++) { 295*7c478bd9Sstevel@tonic-gate (void) printf("\t module: %s\n", dev_att->modlist[cnt]); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate /* 300*7c478bd9Sstevel@tonic-gate * This function parses a '.' delimited interface name of the form 301*7c478bd9Sstevel@tonic-gate * dev[.module[.module...]][:lun] 302*7c478bd9Sstevel@tonic-gate * and places the device and module name into dev_att 303*7c478bd9Sstevel@tonic-gate */ 304*7c478bd9Sstevel@tonic-gate static void 305*7c478bd9Sstevel@tonic-gate parse_ifname(dev_att_t *dev_att) 306*7c478bd9Sstevel@tonic-gate { 307*7c478bd9Sstevel@tonic-gate char *lunstr; 308*7c478bd9Sstevel@tonic-gate char *modlist = NULL; /* list of modules to push */ 309*7c478bd9Sstevel@tonic-gate int cnt = 0; /* number of modules to push */ 310*7c478bd9Sstevel@tonic-gate char modbuf[LIFNAMSIZ]; 311*7c478bd9Sstevel@tonic-gate char *nxtmod; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate /* 314*7c478bd9Sstevel@tonic-gate * check for specified lun at end of interface and 315*7c478bd9Sstevel@tonic-gate * strip it off. 316*7c478bd9Sstevel@tonic-gate */ 317*7c478bd9Sstevel@tonic-gate lunstr = strchr(dev_att->ifname, ':'); 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate if (lunstr) { 320*7c478bd9Sstevel@tonic-gate char *endptr; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate *lunstr = '\0'; 323*7c478bd9Sstevel@tonic-gate lunstr++; 324*7c478bd9Sstevel@tonic-gate endptr = lunstr; 325*7c478bd9Sstevel@tonic-gate dev_att->lun = strtoul(lunstr, &endptr, 10); 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate if (endptr == lunstr || *endptr != '\0') { 328*7c478bd9Sstevel@tonic-gate (void) printf("Invalid logical unit number:%s", lunstr); 329*7c478bd9Sstevel@tonic-gate exit(-1); 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate } else { 332*7c478bd9Sstevel@tonic-gate dev_att->lun = 0; 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate (void) strlcpy(modbuf, dev_att->ifname, LIFNAMSIZ); 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* parse '.' delmited module list */ 338*7c478bd9Sstevel@tonic-gate modlist = strchr(modbuf, '.'); 339*7c478bd9Sstevel@tonic-gate if (modlist) { 340*7c478bd9Sstevel@tonic-gate /* null-terminate interface name (device) */ 341*7c478bd9Sstevel@tonic-gate *modlist = '\0'; 342*7c478bd9Sstevel@tonic-gate modlist++; 343*7c478bd9Sstevel@tonic-gate if (strlen(modlist) == 0) 344*7c478bd9Sstevel@tonic-gate modlist = NULL; 345*7c478bd9Sstevel@tonic-gate while (modlist && cnt < MAX_MODS) { 346*7c478bd9Sstevel@tonic-gate nxtmod = strchr(modlist, '.'); 347*7c478bd9Sstevel@tonic-gate if (nxtmod) { 348*7c478bd9Sstevel@tonic-gate *nxtmod = '\0'; 349*7c478bd9Sstevel@tonic-gate nxtmod++; 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate (void) strncpy(dev_att->modlist[cnt], modlist, 352*7c478bd9Sstevel@tonic-gate LIFNAMSIZ); 353*7c478bd9Sstevel@tonic-gate cnt++; 354*7c478bd9Sstevel@tonic-gate modlist = nxtmod; 355*7c478bd9Sstevel@tonic-gate } 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate (void) snprintf(dev_att->devname, LIFNAMSIZ, "%s/%s", DEVDIR, modbuf); 358*7c478bd9Sstevel@tonic-gate dev_att->mod_cnt = cnt; 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate /* 362*7c478bd9Sstevel@tonic-gate * given a interface name (with possible modules to push) 363*7c478bd9Sstevel@tonic-gate * interface name must have the format of 364*7c478bd9Sstevel@tonic-gate * dev[ppa][.module[.module...][ppa]][:lun] 365*7c478bd9Sstevel@tonic-gate * where only one ppa may be specified e.g. ip0.foo.tun or ip.foo.tun0 366*7c478bd9Sstevel@tonic-gate */ 367*7c478bd9Sstevel@tonic-gate static int 368*7c478bd9Sstevel@tonic-gate ifname_open(char *dev_name, dev_att_t *dev_att) 369*7c478bd9Sstevel@tonic-gate { 370*7c478bd9Sstevel@tonic-gate int fd; 371*7c478bd9Sstevel@tonic-gate uint_t ppa; 372*7c478bd9Sstevel@tonic-gate int res; 373*7c478bd9Sstevel@tonic-gate int style; 374*7c478bd9Sstevel@tonic-gate dl_info_ack_t dl_info; 375*7c478bd9Sstevel@tonic-gate int mod_id; 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate if (debug) 378*7c478bd9Sstevel@tonic-gate (void) printf("ifname_open: %s\n", dev_name); 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate if (strlen(dev_name) > LIFNAMSIZ - 1) { 381*7c478bd9Sstevel@tonic-gate errno = EINVAL; 382*7c478bd9Sstevel@tonic-gate return (-1); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate /* save copy of original device name */ 386*7c478bd9Sstevel@tonic-gate (void) strncpy(dev_att->ifname, dev_name, LIFNAMSIZ); 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate /* parse modules */ 389*7c478bd9Sstevel@tonic-gate parse_ifname(dev_att); 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate /* try DLPI style 1 device first */ 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate if (debug) { 394*7c478bd9Sstevel@tonic-gate pf_dev_att(dev_att); 395*7c478bd9Sstevel@tonic-gate } 396*7c478bd9Sstevel@tonic-gate mod_id = open_dev(dev_att, O_RDWR, &fd, 0); 397*7c478bd9Sstevel@tonic-gate if (mod_id != 0) { 398*7c478bd9Sstevel@tonic-gate if (debug) { 399*7c478bd9Sstevel@tonic-gate (void) printf("Error on open_dev style 1 mod_id: %d" 400*7c478bd9Sstevel@tonic-gate " attemping style 2\n", mod_id); 401*7c478bd9Sstevel@tonic-gate pf_dev_att(dev_att); 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate if (mod_id == -1) { 404*7c478bd9Sstevel@tonic-gate res = ifrm_num(dev_att->devname, &ppa); 405*7c478bd9Sstevel@tonic-gate mod_id = 0; 406*7c478bd9Sstevel@tonic-gate if (res < 0) { 407*7c478bd9Sstevel@tonic-gate if (debug) 408*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 409*7c478bd9Sstevel@tonic-gate "%s: No such file or directory\n", 410*7c478bd9Sstevel@tonic-gate dev_att->devname); 411*7c478bd9Sstevel@tonic-gate (void) close(fd); 412*7c478bd9Sstevel@tonic-gate return (-1); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate /* 415*7c478bd9Sstevel@tonic-gate * ensure that it's the last module 416*7c478bd9Sstevel@tonic-gate * in the list to extract 417*7c478bd9Sstevel@tonic-gate * ppa 418*7c478bd9Sstevel@tonic-gate */ 419*7c478bd9Sstevel@tonic-gate } else if ((mod_id != dev_att->mod_cnt) || 420*7c478bd9Sstevel@tonic-gate (res = ifrm_num(dev_att->modlist[dev_att->mod_cnt - 1], 421*7c478bd9Sstevel@tonic-gate &ppa)) < 0) { 422*7c478bd9Sstevel@tonic-gate if (debug) { 423*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 424*7c478bd9Sstevel@tonic-gate "Error on open_dev style 2 mod_id: %d \n", 425*7c478bd9Sstevel@tonic-gate mod_id); 426*7c478bd9Sstevel@tonic-gate } 427*7c478bd9Sstevel@tonic-gate if (mod_id == dev_att->mod_cnt) 428*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libuuid: could not " 429*7c478bd9Sstevel@tonic-gate "locate ppa in %s\n", 430*7c478bd9Sstevel@tonic-gate dev_att->ifname); 431*7c478bd9Sstevel@tonic-gate (void) close(fd); 432*7c478bd9Sstevel@tonic-gate return (-1); 433*7c478bd9Sstevel@tonic-gate } 434*7c478bd9Sstevel@tonic-gate goto style2; 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate dev_att->style = 1; 437*7c478bd9Sstevel@tonic-gate dev_att->ppa = 0; 438*7c478bd9Sstevel@tonic-gate style = DL_STYLE1; 439*7c478bd9Sstevel@tonic-gate goto dl_info_chk; 440*7c478bd9Sstevel@tonic-gate style2: 441*7c478bd9Sstevel@tonic-gate dev_att->ppa = ppa; 442*7c478bd9Sstevel@tonic-gate mod_id = open_dev(dev_att, O_RDWR, &fd, mod_id); 443*7c478bd9Sstevel@tonic-gate if (mod_id != 0) { 444*7c478bd9Sstevel@tonic-gate if (debug) { 445*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 446*7c478bd9Sstevel@tonic-gate "Error on open_dev style 2 mod_id: %d \n", 447*7c478bd9Sstevel@tonic-gate mod_id); 448*7c478bd9Sstevel@tonic-gate if (mod_id > 0) { 449*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: No such module\n", 450*7c478bd9Sstevel@tonic-gate dev_att->modlist[mod_id - 2]); 451*7c478bd9Sstevel@tonic-gate } 452*7c478bd9Sstevel@tonic-gate pf_dev_att(dev_att); 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate (void) close(fd); 455*7c478bd9Sstevel@tonic-gate return (-1); 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate dev_att->style = 2; 458*7c478bd9Sstevel@tonic-gate style = DL_STYLE2; 459*7c478bd9Sstevel@tonic-gate dl_info_chk: 460*7c478bd9Sstevel@tonic-gate if (dlpi_info_req(fd, &dl_info) < 0) { 461*7c478bd9Sstevel@tonic-gate (void) close(fd); 462*7c478bd9Sstevel@tonic-gate pf_dev_att(dev_att); 463*7c478bd9Sstevel@tonic-gate return (-1); 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate if (dl_info.dl_provider_style != style) { 466*7c478bd9Sstevel@tonic-gate if (debug) { 467*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "DLPI provider style mismatch: " 468*7c478bd9Sstevel@tonic-gate "expected style %s got style %s (0x%lx)\n", 469*7c478bd9Sstevel@tonic-gate style == DL_STYLE1 ? "1" : "2", 470*7c478bd9Sstevel@tonic-gate dl_info.dl_provider_style == DL_STYLE1 ? "1" : "2", 471*7c478bd9Sstevel@tonic-gate dl_info.dl_provider_style); 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate (void) close(fd); 474*7c478bd9Sstevel@tonic-gate return (-1); 475*7c478bd9Sstevel@tonic-gate } 476*7c478bd9Sstevel@tonic-gate if (debug) { 477*7c478bd9Sstevel@tonic-gate (void) printf("pars_dev_att() success\n"); 478*7c478bd9Sstevel@tonic-gate pf_dev_att(dev_att); 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate return (fd); 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate 483*7c478bd9Sstevel@tonic-gate static int 484*7c478bd9Sstevel@tonic-gate dlpi_open_attach(char *ifname) 485*7c478bd9Sstevel@tonic-gate { 486*7c478bd9Sstevel@tonic-gate int fd; 487*7c478bd9Sstevel@tonic-gate dev_att_t dev_att; 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate if (debug) 490*7c478bd9Sstevel@tonic-gate (void) printf("dlpi_open_attach %s\n", ifname); 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate /* if lun is specified fail (backwards compat) */ 493*7c478bd9Sstevel@tonic-gate if (strchr(ifname, ':') != NULL) { 494*7c478bd9Sstevel@tonic-gate return (-1); 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate if ((fd = ifname_open(ifname, &dev_att)) < 0) { 497*7c478bd9Sstevel@tonic-gate /* Not found */ 498*7c478bd9Sstevel@tonic-gate errno = ENXIO; 499*7c478bd9Sstevel@tonic-gate return (-1); 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate if (dlpi_attach(fd, dev_att.ppa, dev_att.style) < 0) { 502*7c478bd9Sstevel@tonic-gate (void) close(fd); 503*7c478bd9Sstevel@tonic-gate return (-1); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate return (fd); 506*7c478bd9Sstevel@tonic-gate } 507*7c478bd9Sstevel@tonic-gate 508*7c478bd9Sstevel@tonic-gate static int 509*7c478bd9Sstevel@tonic-gate dlpi_attach(int fd, int ppa, int style) 510*7c478bd9Sstevel@tonic-gate { 511*7c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 512*7c478bd9Sstevel@tonic-gate char *buf; 513*7c478bd9Sstevel@tonic-gate struct strbuf ctl; 514*7c478bd9Sstevel@tonic-gate int flags; 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate if (style != 2) 517*7c478bd9Sstevel@tonic-gate return (0); 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate /* Allocate required buffers */ 520*7c478bd9Sstevel@tonic-gate if ((buf = malloc(BUFSIZ)) == NULL) { 521*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libuuid: malloc() failed\n"); 522*7c478bd9Sstevel@tonic-gate return (-1); 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate /* Issue DL_ATTACH_REQ */ 526*7c478bd9Sstevel@tonic-gate /* LINTED: malloc returns a pointer aligned for any use */ 527*7c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)buf; 528*7c478bd9Sstevel@tonic-gate dlp->attach_req.dl_primitive = DL_ATTACH_REQ; 529*7c478bd9Sstevel@tonic-gate dlp->attach_req.dl_ppa = ppa; 530*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 531*7c478bd9Sstevel@tonic-gate ctl.len = DL_ATTACH_REQ_SIZE; 532*7c478bd9Sstevel@tonic-gate if (putmsg(fd, &ctl, NULL, 0) < 0) { 533*7c478bd9Sstevel@tonic-gate perror("libuuid: putmsg"); 534*7c478bd9Sstevel@tonic-gate free(buf); 535*7c478bd9Sstevel@tonic-gate return (-1); 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate 538*7c478bd9Sstevel@tonic-gate /* read reply */ 539*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 540*7c478bd9Sstevel@tonic-gate ctl.len = 0; 541*7c478bd9Sstevel@tonic-gate ctl.maxlen = BUFSIZ; 542*7c478bd9Sstevel@tonic-gate flags = 0; 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate /* start timeout for DL_OK_ACK reply */ 545*7c478bd9Sstevel@tonic-gate if (timed_getmsg(fd, &ctl, &flags, dlpi_timeout, 546*7c478bd9Sstevel@tonic-gate "DL_OK_ACK", "DL_ATTACH_REQ") == 0) { 547*7c478bd9Sstevel@tonic-gate free(buf); 548*7c478bd9Sstevel@tonic-gate return (-1); 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate if (debug) { 552*7c478bd9Sstevel@tonic-gate (void) printf("ok_ack: ctl.len[%d] flags[%d]\n", ctl.len, 553*7c478bd9Sstevel@tonic-gate flags); 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate /* Validate DL_OK_ACK reply. */ 557*7c478bd9Sstevel@tonic-gate if (ctl.len < sizeof (t_uscalar_t)) { 558*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 559*7c478bd9Sstevel@tonic-gate "libuuid: attach failed: short reply to attach request\n"); 560*7c478bd9Sstevel@tonic-gate free(buf); 561*7c478bd9Sstevel@tonic-gate return (-1); 562*7c478bd9Sstevel@tonic-gate } 563*7c478bd9Sstevel@tonic-gate 564*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive == DL_ERROR_ACK) { 565*7c478bd9Sstevel@tonic-gate if (debug) 566*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 567*7c478bd9Sstevel@tonic-gate "attach failed: dl_errno %lu errno %lu\n", 568*7c478bd9Sstevel@tonic-gate dlp->error_ack.dl_errno, 569*7c478bd9Sstevel@tonic-gate dlp->error_ack.dl_unix_errno); 570*7c478bd9Sstevel@tonic-gate free(buf); 571*7c478bd9Sstevel@tonic-gate errno = ENXIO; 572*7c478bd9Sstevel@tonic-gate return (-1); 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive != DL_OK_ACK) { 575*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 576*7c478bd9Sstevel@tonic-gate "libuuid: attach failed: " 577*7c478bd9Sstevel@tonic-gate "unrecognizable dl_primitive %lu received", 578*7c478bd9Sstevel@tonic-gate dlp->dl_primitive); 579*7c478bd9Sstevel@tonic-gate free(buf); 580*7c478bd9Sstevel@tonic-gate return (-1); 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate if (ctl.len < DL_OK_ACK_SIZE) { 583*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 584*7c478bd9Sstevel@tonic-gate "libuuid: attach failed: " 585*7c478bd9Sstevel@tonic-gate "short attach acknowledgement received\n"); 586*7c478bd9Sstevel@tonic-gate free(buf); 587*7c478bd9Sstevel@tonic-gate return (-1); 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate if (dlp->ok_ack.dl_correct_primitive != DL_ATTACH_REQ) { 590*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 591*7c478bd9Sstevel@tonic-gate "libuuid: attach failed: " 592*7c478bd9Sstevel@tonic-gate "returned prim %lu != requested prim %lu\n", 593*7c478bd9Sstevel@tonic-gate dlp->ok_ack.dl_correct_primitive, 594*7c478bd9Sstevel@tonic-gate (t_uscalar_t)DL_ATTACH_REQ); 595*7c478bd9Sstevel@tonic-gate free(buf); 596*7c478bd9Sstevel@tonic-gate return (-1); 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate if (debug) 599*7c478bd9Sstevel@tonic-gate (void) printf("attach done\n"); 600*7c478bd9Sstevel@tonic-gate 601*7c478bd9Sstevel@tonic-gate free(buf); 602*7c478bd9Sstevel@tonic-gate return (0); 603*7c478bd9Sstevel@tonic-gate } 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate static int 606*7c478bd9Sstevel@tonic-gate dlpi_get_phys(int fd, uchar_t *eaddr) 607*7c478bd9Sstevel@tonic-gate { 608*7c478bd9Sstevel@tonic-gate union DL_primitives *dlp; 609*7c478bd9Sstevel@tonic-gate char *buf; 610*7c478bd9Sstevel@tonic-gate struct strbuf ctl; 611*7c478bd9Sstevel@tonic-gate int flags; 612*7c478bd9Sstevel@tonic-gate 613*7c478bd9Sstevel@tonic-gate /* Allocate required buffers */ 614*7c478bd9Sstevel@tonic-gate if ((buf = malloc(BUFSIZ)) == NULL) { 615*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libuuid: malloc() failed\n"); 616*7c478bd9Sstevel@tonic-gate return (-1); 617*7c478bd9Sstevel@tonic-gate } 618*7c478bd9Sstevel@tonic-gate /* Issue DL_PHYS_ADDR_REQ */ 619*7c478bd9Sstevel@tonic-gate /* LINTED: malloc returns a pointer aligned for any use */ 620*7c478bd9Sstevel@tonic-gate dlp = (union DL_primitives *)buf; 621*7c478bd9Sstevel@tonic-gate dlp->physaddr_req.dl_primitive = DL_PHYS_ADDR_REQ; 622*7c478bd9Sstevel@tonic-gate dlp->physaddr_req.dl_addr_type = DL_CURR_PHYS_ADDR; 623*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 624*7c478bd9Sstevel@tonic-gate ctl.len = DL_PHYS_ADDR_REQ_SIZE; 625*7c478bd9Sstevel@tonic-gate if (putmsg(fd, &ctl, NULL, 0) < 0) { 626*7c478bd9Sstevel@tonic-gate perror("libuuid: putmsg"); 627*7c478bd9Sstevel@tonic-gate free(buf); 628*7c478bd9Sstevel@tonic-gate return (-1); 629*7c478bd9Sstevel@tonic-gate } 630*7c478bd9Sstevel@tonic-gate 631*7c478bd9Sstevel@tonic-gate /* read reply */ 632*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 633*7c478bd9Sstevel@tonic-gate ctl.len = 0; 634*7c478bd9Sstevel@tonic-gate ctl.maxlen = BUFSIZ; 635*7c478bd9Sstevel@tonic-gate flags = 0; 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate if (timed_getmsg(fd, &ctl, &flags, dlpi_timeout, 638*7c478bd9Sstevel@tonic-gate "DL_PHYS_ADDR_ACK", "DL_PHYS_ADDR_REQ (DL_CURR_PHYS_ADDR)") == 0) { 639*7c478bd9Sstevel@tonic-gate free(buf); 640*7c478bd9Sstevel@tonic-gate return (-1); 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate if (debug) { 644*7c478bd9Sstevel@tonic-gate (void) printf("phys_addr_ack: ctl.len[%d] flags[%d]\n", ctl.len, 645*7c478bd9Sstevel@tonic-gate flags); 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate 648*7c478bd9Sstevel@tonic-gate /* Validate DL_PHYS_ADDR_ACK reply. */ 649*7c478bd9Sstevel@tonic-gate if (ctl.len < sizeof (t_uscalar_t)) { 650*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libuuid: phys_addr failed: " 651*7c478bd9Sstevel@tonic-gate "short reply to phys_addr request\n"); 652*7c478bd9Sstevel@tonic-gate free(buf); 653*7c478bd9Sstevel@tonic-gate return (-1); 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate 656*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive == DL_ERROR_ACK) { 657*7c478bd9Sstevel@tonic-gate /* 658*7c478bd9Sstevel@tonic-gate * Do not print errors for DL_UNSUPPORTED and DL_NOTSUPPORTED 659*7c478bd9Sstevel@tonic-gate */ 660*7c478bd9Sstevel@tonic-gate if (dlp->error_ack.dl_errno != DL_UNSUPPORTED && 661*7c478bd9Sstevel@tonic-gate dlp->error_ack.dl_errno != DL_NOTSUPPORTED) { 662*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libuuid: phys_addr failed: " 663*7c478bd9Sstevel@tonic-gate "dl_errno %lu errno %lu\n", 664*7c478bd9Sstevel@tonic-gate dlp->error_ack.dl_errno, 665*7c478bd9Sstevel@tonic-gate dlp->error_ack.dl_unix_errno); 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate free(buf); 668*7c478bd9Sstevel@tonic-gate return (-1); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive != DL_PHYS_ADDR_ACK) { 671*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libuuid: phys_addr failed: " 672*7c478bd9Sstevel@tonic-gate "unrecognizable dl_primitive %lu received\n", 673*7c478bd9Sstevel@tonic-gate dlp->dl_primitive); 674*7c478bd9Sstevel@tonic-gate free(buf); 675*7c478bd9Sstevel@tonic-gate return (-1); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate if (ctl.len < DL_PHYS_ADDR_ACK_SIZE) { 678*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libuuid: phys_addr failed: " 679*7c478bd9Sstevel@tonic-gate "short phys_addr acknowledgement received\n"); 680*7c478bd9Sstevel@tonic-gate free(buf); 681*7c478bd9Sstevel@tonic-gate return (-1); 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate /* Check length of address. */ 684*7c478bd9Sstevel@tonic-gate if (dlp->physaddr_ack.dl_addr_length != ETHERADDRL) { 685*7c478bd9Sstevel@tonic-gate free(buf); 686*7c478bd9Sstevel@tonic-gate return (-1); 687*7c478bd9Sstevel@tonic-gate } 688*7c478bd9Sstevel@tonic-gate 689*7c478bd9Sstevel@tonic-gate /* copy Ethernet address */ 690*7c478bd9Sstevel@tonic-gate (void) memcpy(eaddr, &buf[dlp->physaddr_ack.dl_addr_offset], 691*7c478bd9Sstevel@tonic-gate ETHERADDRL); 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate free(buf); 694*7c478bd9Sstevel@tonic-gate return (0); 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate static int 700*7c478bd9Sstevel@tonic-gate dlpi_info_req(int fd, dl_info_ack_t *info_ack) 701*7c478bd9Sstevel@tonic-gate { 702*7c478bd9Sstevel@tonic-gate dl_info_req_t info_req; 703*7c478bd9Sstevel@tonic-gate int buf[BUFSIZ/sizeof (int)]; 704*7c478bd9Sstevel@tonic-gate union DL_primitives *dlp = (union DL_primitives *)buf; 705*7c478bd9Sstevel@tonic-gate struct strbuf ctl; 706*7c478bd9Sstevel@tonic-gate int flags; 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate info_req.dl_primitive = DL_INFO_REQ; 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate ctl.len = DL_INFO_REQ_SIZE; 711*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)&info_req; 712*7c478bd9Sstevel@tonic-gate 713*7c478bd9Sstevel@tonic-gate flags = RS_HIPRI; 714*7c478bd9Sstevel@tonic-gate 715*7c478bd9Sstevel@tonic-gate if (putmsg(fd, &ctl, (struct strbuf *)NULL, flags) < 0) { 716*7c478bd9Sstevel@tonic-gate perror("libuuid: putmsg"); 717*7c478bd9Sstevel@tonic-gate return (-1); 718*7c478bd9Sstevel@tonic-gate } 719*7c478bd9Sstevel@tonic-gate 720*7c478bd9Sstevel@tonic-gate /* read reply */ 721*7c478bd9Sstevel@tonic-gate ctl.buf = (char *)dlp; 722*7c478bd9Sstevel@tonic-gate ctl.len = 0; 723*7c478bd9Sstevel@tonic-gate ctl.maxlen = BUFSIZ; 724*7c478bd9Sstevel@tonic-gate flags = 0; 725*7c478bd9Sstevel@tonic-gate /* start timeout for DL_BIND_ACK reply */ 726*7c478bd9Sstevel@tonic-gate if (timed_getmsg(fd, &ctl, &flags, dlpi_timeout, "DL_INFO_ACK", 727*7c478bd9Sstevel@tonic-gate "DL_INFO_ACK") == 0) { 728*7c478bd9Sstevel@tonic-gate return (-1); 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate 731*7c478bd9Sstevel@tonic-gate if (debug) { 732*7c478bd9Sstevel@tonic-gate (void) printf("info_ack: ctl.len[%d] flags[%d]\n", ctl.len, 733*7c478bd9Sstevel@tonic-gate flags); 734*7c478bd9Sstevel@tonic-gate } 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate /* Validate DL_BIND_ACK reply. */ 737*7c478bd9Sstevel@tonic-gate if (ctl.len < sizeof (t_uscalar_t)) { 738*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 739*7c478bd9Sstevel@tonic-gate "libuuid: info req failed: short reply to info request\n"); 740*7c478bd9Sstevel@tonic-gate return (-1); 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive == DL_ERROR_ACK) { 744*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 745*7c478bd9Sstevel@tonic-gate "libuuid: info req failed: dl_errno %lu errno %lu\n", 746*7c478bd9Sstevel@tonic-gate dlp->error_ack.dl_errno, dlp->error_ack.dl_unix_errno); 747*7c478bd9Sstevel@tonic-gate return (-1); 748*7c478bd9Sstevel@tonic-gate } 749*7c478bd9Sstevel@tonic-gate if (dlp->dl_primitive != DL_INFO_ACK) { 750*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 751*7c478bd9Sstevel@tonic-gate "libuuid: info req failed: " 752*7c478bd9Sstevel@tonic-gate "unrecognizable dl_primitive %lu received\n", 753*7c478bd9Sstevel@tonic-gate dlp->dl_primitive); 754*7c478bd9Sstevel@tonic-gate return (-1); 755*7c478bd9Sstevel@tonic-gate } 756*7c478bd9Sstevel@tonic-gate if (ctl.len < DL_INFO_ACK_SIZE) { 757*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 758*7c478bd9Sstevel@tonic-gate "libuuid: info req failed: " 759*7c478bd9Sstevel@tonic-gate "short info acknowledgement received\n"); 760*7c478bd9Sstevel@tonic-gate return (-1); 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate *info_ack = *(dl_info_ack_t *)dlp; 763*7c478bd9Sstevel@tonic-gate return (0); 764*7c478bd9Sstevel@tonic-gate } 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate /* 768*7c478bd9Sstevel@tonic-gate * interface called from libuuid to get the ethernet address - jhf 769*7c478bd9Sstevel@tonic-gate */ 770*7c478bd9Sstevel@tonic-gate int 771*7c478bd9Sstevel@tonic-gate dlpi_get_address(char *ifname, struct ether_addr *ea) 772*7c478bd9Sstevel@tonic-gate { 773*7c478bd9Sstevel@tonic-gate int fd; 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate if (debug) 776*7c478bd9Sstevel@tonic-gate (void) printf("dlpi_get_address: dlpi_open_attach\t"); 777*7c478bd9Sstevel@tonic-gate fd = dlpi_open_attach(ifname); 778*7c478bd9Sstevel@tonic-gate if (fd < 0) { 779*7c478bd9Sstevel@tonic-gate /* Do not report an error */ 780*7c478bd9Sstevel@tonic-gate return (-1); 781*7c478bd9Sstevel@tonic-gate } 782*7c478bd9Sstevel@tonic-gate 783*7c478bd9Sstevel@tonic-gate if (debug) 784*7c478bd9Sstevel@tonic-gate (void) printf("dlpi_get_address: dlpi_get_phys %s\n", ifname); 785*7c478bd9Sstevel@tonic-gate if (dlpi_get_phys(fd, (uchar_t *)ea) < 0) { 786*7c478bd9Sstevel@tonic-gate (void) close(fd); 787*7c478bd9Sstevel@tonic-gate return (-1); 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate (void) close(fd); 790*7c478bd9Sstevel@tonic-gate return (0); 791*7c478bd9Sstevel@tonic-gate } 792*7c478bd9Sstevel@tonic-gate 793*7c478bd9Sstevel@tonic-gate static int 794*7c478bd9Sstevel@tonic-gate timed_getmsg(int fd, struct strbuf *ctlp, int *flagsp, int timeout, char *kind, 795*7c478bd9Sstevel@tonic-gate char *request) 796*7c478bd9Sstevel@tonic-gate { 797*7c478bd9Sstevel@tonic-gate char perrorbuf[BUFSIZ]; 798*7c478bd9Sstevel@tonic-gate struct pollfd pfd; 799*7c478bd9Sstevel@tonic-gate int ret; 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate pfd.fd = fd; 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI; 804*7c478bd9Sstevel@tonic-gate if ((ret = poll(&pfd, 1, timeout * 1000)) == 0) { 805*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libuuid: %s timed out\n", kind); 806*7c478bd9Sstevel@tonic-gate return (0); 807*7c478bd9Sstevel@tonic-gate } else if (ret == -1) { 808*7c478bd9Sstevel@tonic-gate (void) snprintf(perrorbuf, sizeof (perrorbuf), 809*7c478bd9Sstevel@tonic-gate "libuuid: poll for %s from %s", kind, request); 810*7c478bd9Sstevel@tonic-gate perror(perrorbuf); 811*7c478bd9Sstevel@tonic-gate return (0); 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate 814*7c478bd9Sstevel@tonic-gate /* poll returned > 0 for this fd so getmsg should not block */ 815*7c478bd9Sstevel@tonic-gate if ((ret = getmsg(fd, ctlp, NULL, flagsp)) < 0) { 816*7c478bd9Sstevel@tonic-gate (void) snprintf(perrorbuf, sizeof (perrorbuf), 817*7c478bd9Sstevel@tonic-gate "libuuid: getmsg expecting %s for %s", kind, request); 818*7c478bd9Sstevel@tonic-gate perror(perrorbuf); 819*7c478bd9Sstevel@tonic-gate return (0); 820*7c478bd9Sstevel@tonic-gate } 821*7c478bd9Sstevel@tonic-gate 822*7c478bd9Sstevel@tonic-gate return (1); 823*7c478bd9Sstevel@tonic-gate } 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate /* 826*7c478bd9Sstevel@tonic-gate * Name: get_ethernet_address 827*7c478bd9Sstevel@tonic-gate * 828*7c478bd9Sstevel@tonic-gate * Description: Obtains the system ethernet address. 829*7c478bd9Sstevel@tonic-gate * 830*7c478bd9Sstevel@tonic-gate * Returns: 0 on success, non-zero otherwise. The system ethernet 831*7c478bd9Sstevel@tonic-gate * address is copied into the passed-in variable. 832*7c478bd9Sstevel@tonic-gate */ 833*7c478bd9Sstevel@tonic-gate int 834*7c478bd9Sstevel@tonic-gate get_ethernet_address(uuid_node_t *node) 835*7c478bd9Sstevel@tonic-gate { 836*7c478bd9Sstevel@tonic-gate char **ifnames; 837*7c478bd9Sstevel@tonic-gate char *ifname; 838*7c478bd9Sstevel@tonic-gate int i; 839*7c478bd9Sstevel@tonic-gate struct ether_addr addr; 840*7c478bd9Sstevel@tonic-gate int found; 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate if (arp_get(node) == 0) 843*7c478bd9Sstevel@tonic-gate return (0); 844*7c478bd9Sstevel@tonic-gate 845*7c478bd9Sstevel@tonic-gate /* 846*7c478bd9Sstevel@tonic-gate * go get all interface names 847*7c478bd9Sstevel@tonic-gate */ 848*7c478bd9Sstevel@tonic-gate if (get_net_if_names(&ifnames) == 0) { 849*7c478bd9Sstevel@tonic-gate return (0); 850*7c478bd9Sstevel@tonic-gate } 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate /* 853*7c478bd9Sstevel@tonic-gate * Assume failure 854*7c478bd9Sstevel@tonic-gate */ 855*7c478bd9Sstevel@tonic-gate found = -1; 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate /* 858*7c478bd9Sstevel@tonic-gate * for each interface, query it through dlpi to get its physical 859*7c478bd9Sstevel@tonic-gate * (ethernet) address 860*7c478bd9Sstevel@tonic-gate */ 861*7c478bd9Sstevel@tonic-gate if (ifnames != NULL) { 862*7c478bd9Sstevel@tonic-gate i = 0; 863*7c478bd9Sstevel@tonic-gate while ((ifnames[i] != NULL) && found) { 864*7c478bd9Sstevel@tonic-gate ifname = ifnames[i]; 865*7c478bd9Sstevel@tonic-gate /* Gross hack to avoid getting errors from /dev/lo0 */ 866*7c478bd9Sstevel@tonic-gate if (strcmp(ifname, LOOPBACK_IF) != 0) { 867*7c478bd9Sstevel@tonic-gate if (dlpi_get_address(ifname, &addr) == 0) { 868*7c478bd9Sstevel@tonic-gate bcopy(&addr, node, 6); 869*7c478bd9Sstevel@tonic-gate /* 870*7c478bd9Sstevel@tonic-gate * found one, set result to successful 871*7c478bd9Sstevel@tonic-gate */ 872*7c478bd9Sstevel@tonic-gate found = 0; 873*7c478bd9Sstevel@tonic-gate continue; 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate } 876*7c478bd9Sstevel@tonic-gate i++; 877*7c478bd9Sstevel@tonic-gate } 878*7c478bd9Sstevel@tonic-gate free_net_if_names(ifnames); 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate /* 882*7c478bd9Sstevel@tonic-gate * Couldn't get ethernet address from any interfaces... 883*7c478bd9Sstevel@tonic-gate */ 884*7c478bd9Sstevel@tonic-gate return (found); 885*7c478bd9Sstevel@tonic-gate } 886