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