10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 270Sstevel@tonic-gate /* All Rights Reserved */ 280Sstevel@tonic-gate 290Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 300Sstevel@tonic-gate 310Sstevel@tonic-gate #include "defs.h" 320Sstevel@tonic-gate #include "ifconfig.h" 330Sstevel@tonic-gate #include <sys/types.h> 340Sstevel@tonic-gate #include <sys/dlpi.h> 350Sstevel@tonic-gate #include <libdlpi.h> 360Sstevel@tonic-gate #include <sys/sysmacros.h> 370Sstevel@tonic-gate #include <deflt.h> 380Sstevel@tonic-gate 390Sstevel@tonic-gate #define IPADDRL sizeof (struct in_addr) 400Sstevel@tonic-gate #define RARPRETRIES 5 410Sstevel@tonic-gate 420Sstevel@tonic-gate /* 430Sstevel@tonic-gate * The following value (8) is determined to work reliably in switched 10/100MB 440Sstevel@tonic-gate * ethernet environments. Use caution if you plan on decreasing it. 450Sstevel@tonic-gate */ 460Sstevel@tonic-gate #define RARPTIMEOUT 8 470Sstevel@tonic-gate 480Sstevel@tonic-gate static char defaultfile[] = "/etc/inet/rarp"; 490Sstevel@tonic-gate static char retries_var[] = "RARP_RETRIES="; 500Sstevel@tonic-gate static int rarp_timeout = RARPTIMEOUT; 510Sstevel@tonic-gate static int rarp_retries = RARPRETRIES; 520Sstevel@tonic-gate 530Sstevel@tonic-gate static int rarp_write(int, struct arphdr *, uchar_t *, size_t, size_t); 540Sstevel@tonic-gate static int rarp_open(char *, t_uscalar_t, size_t *, uchar_t **, 550Sstevel@tonic-gate uchar_t **); 560Sstevel@tonic-gate 570Sstevel@tonic-gate /* ARGSUSED */ 580Sstevel@tonic-gate int 590Sstevel@tonic-gate doifrevarp(char *ifname, struct sockaddr_in *laddr) 600Sstevel@tonic-gate { 610Sstevel@tonic-gate int if_fd; 620Sstevel@tonic-gate struct pollfd pfd; 630Sstevel@tonic-gate int s, flags, ret; 640Sstevel@tonic-gate char *ctlbuf, *databuf, *cause; 650Sstevel@tonic-gate struct strbuf ctl, data; 660Sstevel@tonic-gate struct arphdr *req, *ans; 670Sstevel@tonic-gate struct in_addr from; 680Sstevel@tonic-gate struct in_addr answer; 690Sstevel@tonic-gate union DL_primitives *dlp; 700Sstevel@tonic-gate struct lifreq lifr; 710Sstevel@tonic-gate struct timeval senttime; 720Sstevel@tonic-gate struct timeval currenttime; 730Sstevel@tonic-gate int waittime; 740Sstevel@tonic-gate int tries_left; 750Sstevel@tonic-gate size_t ifaddrlen, ifrarplen; 760Sstevel@tonic-gate uchar_t *my_macaddr = NULL, *my_broadcast = NULL; 770Sstevel@tonic-gate 780Sstevel@tonic-gate 790Sstevel@tonic-gate if (ifname[0] == '\0') { 800Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: doifrevarp: name not set\n"); 810Sstevel@tonic-gate exit(1); 820Sstevel@tonic-gate } 830Sstevel@tonic-gate 840Sstevel@tonic-gate if (debug) 850Sstevel@tonic-gate (void) printf("doifrevarp interface %s\n", ifname); 860Sstevel@tonic-gate 870Sstevel@tonic-gate if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 880Sstevel@tonic-gate Perror0_exit("socket"); 890Sstevel@tonic-gate } 900Sstevel@tonic-gate (void) strncpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 910Sstevel@tonic-gate if (ioctl(s, SIOCGLIFFLAGS, (char *)&lifr) < 0) 920Sstevel@tonic-gate Perror0_exit("SIOCGLIFFLAGS"); 930Sstevel@tonic-gate 940Sstevel@tonic-gate /* don't try to revarp if we know it won't work */ 950Sstevel@tonic-gate if ((lifr.lifr_flags & IFF_LOOPBACK) || 960Sstevel@tonic-gate (lifr.lifr_flags & IFF_NOARP) || 970Sstevel@tonic-gate (lifr.lifr_flags & IFF_POINTOPOINT)) 980Sstevel@tonic-gate return (0); 990Sstevel@tonic-gate 1000Sstevel@tonic-gate /* open rarp interface */ 1010Sstevel@tonic-gate if_fd = rarp_open(ifname, ETHERTYPE_REVARP, &ifaddrlen, &my_macaddr, 1020Sstevel@tonic-gate &my_broadcast); 1030Sstevel@tonic-gate if (if_fd < 0) 1040Sstevel@tonic-gate return (0); 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate /* 1070Sstevel@tonic-gate * RARP looks at /etc/ethers and NIS, which only works 1080Sstevel@tonic-gate * with 6 byte addresses currently. 1090Sstevel@tonic-gate */ 1100Sstevel@tonic-gate if (ifaddrlen != ETHERADDRL) { 1110Sstevel@tonic-gate (void) close(if_fd); 1120Sstevel@tonic-gate free(my_macaddr); 1130Sstevel@tonic-gate free(my_broadcast); 1140Sstevel@tonic-gate return (0); 1150Sstevel@tonic-gate } 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate ifrarplen = sizeof (struct arphdr) + (2 * IPADDRL) + (2 * ifaddrlen); 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate /* look for adjustments to rarp_retries in the RARP defaults file */ 1200Sstevel@tonic-gate if (defopen(defaultfile) == 0) { 1210Sstevel@tonic-gate char *cp; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate if (cp = defread(retries_var)) { 1240Sstevel@tonic-gate int ntries; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate ntries = atoi(cp); 1270Sstevel@tonic-gate if (ntries > 0) 1280Sstevel@tonic-gate rarp_retries = ntries; 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate (void) defopen(NULL); /* close default file */ 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* allocate request and response buffers */ 1340Sstevel@tonic-gate if (((req = (struct arphdr *)malloc(ifrarplen)) == NULL) || 1350Sstevel@tonic-gate ((ans = (struct arphdr *)malloc(ifrarplen)) == NULL)) { 1360Sstevel@tonic-gate (void) close(if_fd); 1370Sstevel@tonic-gate free(req); 1380Sstevel@tonic-gate free(my_macaddr); 1390Sstevel@tonic-gate free(my_broadcast); 1400Sstevel@tonic-gate return (0); 1410Sstevel@tonic-gate } 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate /* create rarp request */ 1440Sstevel@tonic-gate (void) memset(req, 0, ifrarplen); 1450Sstevel@tonic-gate req->ar_hrd = htons(ARPHRD_ETHER); 1460Sstevel@tonic-gate req->ar_pro = htons(ETHERTYPE_IP); 1470Sstevel@tonic-gate req->ar_hln = ifaddrlen; 1480Sstevel@tonic-gate req->ar_pln = IPADDRL; 1490Sstevel@tonic-gate req->ar_op = htons(REVARP_REQUEST); 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate (void) memcpy((uchar_t *)req + sizeof (struct arphdr), my_macaddr, 1520Sstevel@tonic-gate ifaddrlen); 1530Sstevel@tonic-gate (void) memcpy((uchar_t *)req + sizeof (struct arphdr) + IPADDRL + 1540Sstevel@tonic-gate ifaddrlen, my_macaddr, ifaddrlen); 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate tries_left = rarp_retries; 1570Sstevel@tonic-gate rarp_retry: 1580Sstevel@tonic-gate /* send the request */ 1590Sstevel@tonic-gate if (rarp_write(if_fd, req, my_broadcast, ifaddrlen, ifrarplen) < 0) 1600Sstevel@tonic-gate goto fail; 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate gettimeofday(&senttime, NULL); 1630Sstevel@tonic-gate 1640Sstevel@tonic-gate if (debug) 1650Sstevel@tonic-gate (void) printf("rarp sent\n"); 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate /* read the answers */ 1690Sstevel@tonic-gate if ((databuf = malloc(BUFSIZ)) == NULL) { 1700Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: malloc() failed\n"); 1710Sstevel@tonic-gate goto fail; 1720Sstevel@tonic-gate } 1730Sstevel@tonic-gate if ((ctlbuf = malloc(BUFSIZ)) == NULL) { 1740Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: malloc() failed\n"); 1750Sstevel@tonic-gate goto fail; 1760Sstevel@tonic-gate } 1770Sstevel@tonic-gate for (;;) { 1780Sstevel@tonic-gate ctl.len = 0; 1790Sstevel@tonic-gate ctl.maxlen = BUFSIZ; 1800Sstevel@tonic-gate ctl.buf = ctlbuf; 1810Sstevel@tonic-gate data.len = 0; 1820Sstevel@tonic-gate data.maxlen = BUFSIZ; 1830Sstevel@tonic-gate data.buf = databuf; 1840Sstevel@tonic-gate flags = 0; 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* 1870Sstevel@tonic-gate * Check to see when the packet was last sent. 1880Sstevel@tonic-gate * If we have not sent a packet in the last 1890Sstevel@tonic-gate * RARP_TIMEOUT seconds, we should send one now. 1900Sstevel@tonic-gate * Note that if some other host on the network is 1910Sstevel@tonic-gate * sending a broadcast packet, poll will return and we 1920Sstevel@tonic-gate * will find out that it does not match the reply we 1930Sstevel@tonic-gate * are waiting for and then go back to poll. If the 1940Sstevel@tonic-gate * frequency of such packets is > rarp_timeout, we don't 1950Sstevel@tonic-gate * want to just go back to poll. We should send out one 1960Sstevel@tonic-gate * more RARP request before blocking in poll. 1970Sstevel@tonic-gate */ 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate gettimeofday(¤ttime, NULL); 2000Sstevel@tonic-gate waittime = rarp_timeout - 2010Sstevel@tonic-gate (currenttime.tv_sec - senttime.tv_sec); 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate if (waittime <= 0) { 2040Sstevel@tonic-gate if (--tries_left > 0) { 2050Sstevel@tonic-gate if (debug) 2060Sstevel@tonic-gate (void) printf("rarp retry\n"); 2070Sstevel@tonic-gate goto rarp_retry; 2080Sstevel@tonic-gate } else { 2090Sstevel@tonic-gate if (debug) 2100Sstevel@tonic-gate (void) printf("rarp timeout\n"); 2110Sstevel@tonic-gate goto fail; 2120Sstevel@tonic-gate } 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate /* start RARP reply timeout */ 2160Sstevel@tonic-gate pfd.fd = if_fd; 2170Sstevel@tonic-gate pfd.events = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI; 2180Sstevel@tonic-gate if ((ret = poll(&pfd, 1, waittime * 1000)) == 0) { 2190Sstevel@tonic-gate if (--tries_left > 0) { 2200Sstevel@tonic-gate if (debug) 2210Sstevel@tonic-gate (void) printf("rarp retry\n"); 2220Sstevel@tonic-gate goto rarp_retry; 2230Sstevel@tonic-gate } else { 2240Sstevel@tonic-gate if (debug) 2250Sstevel@tonic-gate (void) printf("rarp timeout\n"); 2260Sstevel@tonic-gate goto fail; 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate } else if (ret == -1) { 2290Sstevel@tonic-gate perror("ifconfig: RARP reply poll"); 2300Sstevel@tonic-gate goto fail; 2310Sstevel@tonic-gate } 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate /* poll returned > 0 for this fd so getmsg should not block */ 2340Sstevel@tonic-gate if ((ret = getmsg(if_fd, &ctl, &data, &flags)) < 0) { 2350Sstevel@tonic-gate perror("ifconfig: RARP reply getmsg"); 2360Sstevel@tonic-gate goto fail; 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate if (debug) { 2400Sstevel@tonic-gate (void) printf("rarp: ret[%d] ctl.len[%d] data.len[%d] " 2410Sstevel@tonic-gate "flags[%d]\n", ret, ctl.len, data.len, flags); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate /* Validate DL_UNITDATA_IND. */ 2440Sstevel@tonic-gate /* LINTED: malloc returns a pointer aligned for any use */ 2450Sstevel@tonic-gate dlp = (union DL_primitives *)ctlbuf; 2460Sstevel@tonic-gate if (debug) { 2470Sstevel@tonic-gate (void) printf("rarp: dl_primitive[%lu]\n", 2480Sstevel@tonic-gate dlp->dl_primitive); 2490Sstevel@tonic-gate if (dlp->dl_primitive == DL_ERROR_ACK) { 2500Sstevel@tonic-gate (void) printf( 2510Sstevel@tonic-gate "rarp: err ak: dl_errno %lu errno %lu\n", 2520Sstevel@tonic-gate dlp->error_ack.dl_errno, 2530Sstevel@tonic-gate dlp->error_ack.dl_unix_errno); 2540Sstevel@tonic-gate } 2550Sstevel@tonic-gate if (dlp->dl_primitive == DL_UDERROR_IND) { 2560Sstevel@tonic-gate (void) printf("rarp: ud err: err[%lu] len[%lu] " 2570Sstevel@tonic-gate "off[%lu]\n", 2580Sstevel@tonic-gate dlp->uderror_ind.dl_errno, 2590Sstevel@tonic-gate dlp->uderror_ind.dl_dest_addr_length, 2600Sstevel@tonic-gate dlp->uderror_ind.dl_dest_addr_offset); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate (void) memcpy(ans, databuf, ifrarplen); 2640Sstevel@tonic-gate cause = NULL; 2650Sstevel@tonic-gate if (ret & MORECTL) 2660Sstevel@tonic-gate cause = "MORECTL flag"; 2670Sstevel@tonic-gate else if (ret & MOREDATA) 2680Sstevel@tonic-gate cause = "MOREDATA flag"; 2690Sstevel@tonic-gate else if (ctl.len == 0) 2700Sstevel@tonic-gate cause = "missing control part of message"; 2710Sstevel@tonic-gate else if (ctl.len < 0) 2720Sstevel@tonic-gate cause = "short control part of message"; 2730Sstevel@tonic-gate else if (dlp->dl_primitive != DL_UNITDATA_IND) 2740Sstevel@tonic-gate cause = "not unitdata_ind"; 2750Sstevel@tonic-gate else if (ctl.len < DL_UNITDATA_IND_SIZE) 2760Sstevel@tonic-gate cause = "short unitdata_ind"; 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate else if (data.len < ifrarplen) 2790Sstevel@tonic-gate cause = "short arp"; 2800Sstevel@tonic-gate else if (ans->ar_hrd != htons(ARPHRD_ETHER)) 2810Sstevel@tonic-gate cause = "hrd"; 2820Sstevel@tonic-gate else if (ans->ar_pro != htons(ETHERTYPE_IP)) 2830Sstevel@tonic-gate cause = "pro"; 2840Sstevel@tonic-gate else if (ans->ar_hln != ifaddrlen) 2850Sstevel@tonic-gate cause = "hln"; 2860Sstevel@tonic-gate else if (ans->ar_pln != IPADDRL) 2870Sstevel@tonic-gate cause = "pln"; 2880Sstevel@tonic-gate if (cause) { 2890Sstevel@tonic-gate (void) fprintf(stderr, 2900Sstevel@tonic-gate "sanity check failed; cause: %s\n", cause); 2910Sstevel@tonic-gate continue; 2920Sstevel@tonic-gate } 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate switch (ntohs(ans->ar_op)) { 2950Sstevel@tonic-gate case ARPOP_REQUEST: 2960Sstevel@tonic-gate if (debug) 2970Sstevel@tonic-gate (void) printf("Got an arp request\n"); 2980Sstevel@tonic-gate break; 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate case ARPOP_REPLY: 3010Sstevel@tonic-gate if (debug) 3020Sstevel@tonic-gate (void) printf("Got an arp reply.\n"); 3030Sstevel@tonic-gate break; 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate case REVARP_REQUEST: 3060Sstevel@tonic-gate if (debug) 3070Sstevel@tonic-gate (void) printf("Got a rarp request.\n"); 3080Sstevel@tonic-gate break; 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate case REVARP_REPLY: 3110Sstevel@tonic-gate 3120Sstevel@tonic-gate (void) memcpy(&answer, (uchar_t *)ans + 3130Sstevel@tonic-gate sizeof (struct arphdr) + (2 * ifaddrlen) + 3140Sstevel@tonic-gate IPADDRL, sizeof (answer)); 3150Sstevel@tonic-gate (void) memcpy(&from, (uchar_t *)ans + 3160Sstevel@tonic-gate sizeof (struct arphdr) + ifaddrlen, sizeof (from)); 3170Sstevel@tonic-gate if (debug) { 3180Sstevel@tonic-gate (void) printf("answer: %s", inet_ntoa(answer)); 3190Sstevel@tonic-gate (void) printf(" [from %s]\n", inet_ntoa(from)); 3200Sstevel@tonic-gate } 3210Sstevel@tonic-gate laddr->sin_addr = answer; 3220Sstevel@tonic-gate (void) close(if_fd); 3230Sstevel@tonic-gate free(req); 3240Sstevel@tonic-gate free(ans); 3250Sstevel@tonic-gate free(my_macaddr); 3260Sstevel@tonic-gate free(my_broadcast); 3270Sstevel@tonic-gate return (1); 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate default: 3300Sstevel@tonic-gate (void) fprintf(stderr, 3310Sstevel@tonic-gate "ifconfig: unknown opcode 0x%xd\n", ans->ar_op); 3320Sstevel@tonic-gate break; 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate /* NOTREACHED */ 3360Sstevel@tonic-gate fail: 3370Sstevel@tonic-gate (void) close(if_fd); 3380Sstevel@tonic-gate free(req); 3390Sstevel@tonic-gate free(ans); 3400Sstevel@tonic-gate free(my_macaddr); 3410Sstevel@tonic-gate free(my_broadcast); 3420Sstevel@tonic-gate return (0); 3430Sstevel@tonic-gate } 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate /* 3460Sstevel@tonic-gate * Open the datalink provider device and bind to the REVARP type. 3470Sstevel@tonic-gate * Return the resulting descriptor. 3480Sstevel@tonic-gate */ 3490Sstevel@tonic-gate static int 3500Sstevel@tonic-gate rarp_open(char *ifname, t_uscalar_t type, size_t *alen, uchar_t **myaddr, 3510Sstevel@tonic-gate uchar_t **mybaddr) 3520Sstevel@tonic-gate { 3530Sstevel@tonic-gate int fd, len; 3540Sstevel@tonic-gate char *str; 3550Sstevel@tonic-gate dl_info_ack_t dlinfo; 3560Sstevel@tonic-gate dlpi_if_attr_t dia; 3570Sstevel@tonic-gate int i; 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate if (debug) 3600Sstevel@tonic-gate (void) printf("rarp_open %s\n", ifname); 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate fd = dlpi_if_open(ifname, &dia, _B_FALSE); 3630Sstevel@tonic-gate if (fd < 0) { 3640Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: could not open device for " 3650Sstevel@tonic-gate "%s\n", ifname); 3660Sstevel@tonic-gate return (-1); 3670Sstevel@tonic-gate } 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate if (dlpi_info(fd, -1, &dlinfo, NULL, NULL, NULL, NULL, NULL, 3700Sstevel@tonic-gate NULL) < 0) { 3710Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: info req failed\n"); 3720Sstevel@tonic-gate goto failed; 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate if ((*mybaddr = malloc(dlinfo.dl_brdcst_addr_length)) == NULL) { 3760Sstevel@tonic-gate (void) fprintf(stderr, "rarp_open: malloc() failed\n"); 3770Sstevel@tonic-gate goto failed; 3780Sstevel@tonic-gate } 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate if (dlpi_info(fd, -1, &dlinfo, NULL, NULL, NULL, NULL, *mybaddr, 3810Sstevel@tonic-gate NULL) < 0) { 3820Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: info req failed\n"); 3830Sstevel@tonic-gate goto failed; 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate if (debug) { 3870Sstevel@tonic-gate (void) printf("broadcast addr: "); 3880Sstevel@tonic-gate for (i = 0; i < dlinfo.dl_brdcst_addr_length; i++) 3890Sstevel@tonic-gate (void) printf("%02x", (*mybaddr)[i]); 3900Sstevel@tonic-gate (void) printf("\n"); 3910Sstevel@tonic-gate } 3920Sstevel@tonic-gate 3930Sstevel@tonic-gate len = *alen = dlinfo.dl_addr_length - abs(dlinfo.dl_sap_length); 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate if (debug) 3960Sstevel@tonic-gate (void) printf("rarp_open: addr length = %d\n", len); 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate if ((*myaddr = malloc(len)) == NULL) { 3990Sstevel@tonic-gate (void) fprintf(stderr, "rarp_open: malloc() failed\n"); 4000Sstevel@tonic-gate goto failed; 4010Sstevel@tonic-gate } 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate if (dlpi_bind(fd, -1, type, DL_CLDLS, _B_FALSE, NULL, NULL, 4040Sstevel@tonic-gate *myaddr, NULL) < 0) { 4050Sstevel@tonic-gate (void) fprintf(stderr, "rarp_open: dlpi_bind failed\n"); 4060Sstevel@tonic-gate goto failed; 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate if (debug) { 4100Sstevel@tonic-gate str = _link_ntoa(*myaddr, str, len, IFT_OTHER); 4110Sstevel@tonic-gate if (str != NULL) { 4120Sstevel@tonic-gate (void) printf("device %s mac address %s\n", 4130Sstevel@tonic-gate ifname, str); 4140Sstevel@tonic-gate free(str); 4150Sstevel@tonic-gate } 4160Sstevel@tonic-gate } 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate return (fd); 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate failed: 4210Sstevel@tonic-gate (void) dlpi_close(fd); 4220Sstevel@tonic-gate free(*mybaddr); 4230Sstevel@tonic-gate free(*myaddr); 4240Sstevel@tonic-gate return (-1); 4250Sstevel@tonic-gate } 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate static int 4280Sstevel@tonic-gate rarp_write(int fd, struct arphdr *ahdr, uchar_t *dhost, size_t maclen, 4290Sstevel@tonic-gate size_t rarplen) 4300Sstevel@tonic-gate { 4310Sstevel@tonic-gate struct strbuf ctl, data; 4320Sstevel@tonic-gate union DL_primitives *dlp; 4330Sstevel@tonic-gate char *ctlbuf; 4340Sstevel@tonic-gate int ret; 4350Sstevel@tonic-gate ushort_t etype = ETHERTYPE_REVARP; 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate /* 4380Sstevel@tonic-gate * Construct DL_UNITDATA_REQ. Allocate at least BUFSIZ bytes. 4390Sstevel@tonic-gate */ 4400Sstevel@tonic-gate ctl.len = DL_UNITDATA_REQ_SIZE + maclen + sizeof (ushort_t); 4410Sstevel@tonic-gate if ((ctl.buf = ctlbuf = malloc(ctl.len)) == NULL) { 4420Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: malloc() failed\n"); 4430Sstevel@tonic-gate return (-1); 4440Sstevel@tonic-gate } 4450Sstevel@tonic-gate /* LINTED: malloc returns a pointer aligned for any use */ 4460Sstevel@tonic-gate dlp = (union DL_primitives *)ctlbuf; 4470Sstevel@tonic-gate dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ; 4480Sstevel@tonic-gate dlp->unitdata_req.dl_dest_addr_length = maclen + sizeof (ushort_t); 4490Sstevel@tonic-gate dlp->unitdata_req.dl_dest_addr_offset = DL_UNITDATA_REQ_SIZE; 4500Sstevel@tonic-gate dlp->unitdata_req.dl_priority.dl_min = 0; 4510Sstevel@tonic-gate dlp->unitdata_req.dl_priority.dl_max = 0; 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate /* 4540Sstevel@tonic-gate * XXX FIXME Assumes a specific DLPI address format. 4550Sstevel@tonic-gate */ 4560Sstevel@tonic-gate (void) memcpy(ctlbuf + DL_UNITDATA_REQ_SIZE, dhost, maclen); 4570Sstevel@tonic-gate (void) memcpy(ctlbuf + DL_UNITDATA_REQ_SIZE + maclen, &etype, 4580Sstevel@tonic-gate sizeof (etype)); 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate /* Send DL_UNITDATA_REQ. */ 4610Sstevel@tonic-gate data.len = rarplen; 4620Sstevel@tonic-gate data.buf = (char *)ahdr; 4630Sstevel@tonic-gate ret = putmsg(fd, &ctl, &data, 0); 4640Sstevel@tonic-gate free(ctlbuf); 4650Sstevel@tonic-gate return (ret); 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate int 4690Sstevel@tonic-gate dlpi_set_address(char *ifname, uchar_t *ea, int length) 4700Sstevel@tonic-gate { 4710Sstevel@tonic-gate int fd; 4720Sstevel@tonic-gate dlpi_if_attr_t dia; 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate fd = dlpi_if_open(ifname, &dia, _B_FALSE); 4750Sstevel@tonic-gate if (fd < 0) { 4760Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: could not open device for " 4770Sstevel@tonic-gate "%s\n", ifname); 4780Sstevel@tonic-gate return (-1); 4790Sstevel@tonic-gate } 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate if (dlpi_set_phys_addr(fd, -1, ea, length) < 0) { 4820Sstevel@tonic-gate (void) dlpi_close(fd); 4830Sstevel@tonic-gate return (-1); 4840Sstevel@tonic-gate } 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate (void) dlpi_close(fd); 4870Sstevel@tonic-gate return (0); 4880Sstevel@tonic-gate } 4890Sstevel@tonic-gate 4900Sstevel@tonic-gate void 4910Sstevel@tonic-gate dlpi_print_address(char *ifname) 4920Sstevel@tonic-gate { 4930Sstevel@tonic-gate int fd, len; 4940Sstevel@tonic-gate uchar_t *laddr; 4950Sstevel@tonic-gate dl_info_ack_t dl_info; 4960Sstevel@tonic-gate char *str = NULL; 4970Sstevel@tonic-gate dlpi_if_attr_t dia; 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate fd = dlpi_if_open(ifname, &dia, _B_FALSE); 5000Sstevel@tonic-gate if (fd < 0) { 5010Sstevel@tonic-gate /* Do not report an error */ 5020Sstevel@tonic-gate return; 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate if (dlpi_info(fd, -1, &dl_info, NULL, NULL, NULL, NULL, NULL, 5060Sstevel@tonic-gate NULL) < 0) { 5070Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: info req failed\n"); 508*13Syw138387 (void) dlpi_close(fd); 509*13Syw138387 return; 5100Sstevel@tonic-gate } 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate len = dl_info.dl_addr_length - abs(dl_info.dl_sap_length); 5130Sstevel@tonic-gate if ((laddr = malloc(len)) == NULL) { 5140Sstevel@tonic-gate goto failed; 5150Sstevel@tonic-gate } 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate if (dlpi_phys_addr(fd, -1, DL_CURR_PHYS_ADDR, laddr, NULL) < 0) { 5180Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: phys_addr failed\n"); 5190Sstevel@tonic-gate goto failed; 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate (void) dlpi_close(fd); 5230Sstevel@tonic-gate str = _link_ntoa(laddr, str, len, IFT_OTHER); 5240Sstevel@tonic-gate if (str != NULL) { 5250Sstevel@tonic-gate switch (dl_info.dl_mac_type) { 5260Sstevel@tonic-gate case DL_IB: 5270Sstevel@tonic-gate (void) printf("\tipib %s \n", str); 5280Sstevel@tonic-gate break; 5290Sstevel@tonic-gate default: 5300Sstevel@tonic-gate (void) printf("\tether %s \n", str); 5310Sstevel@tonic-gate break; 5320Sstevel@tonic-gate } 5330Sstevel@tonic-gate free(str); 5340Sstevel@tonic-gate } 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate failed: 5370Sstevel@tonic-gate free(laddr); 5380Sstevel@tonic-gate (void) dlpi_close(fd); 5390Sstevel@tonic-gate } 540