17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5c7e4935fSss150715 * Common Development and Distribution License (the "License"). 6c7e4935fSss150715 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*e11c3f44Smeem * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 267c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include "defs.h" 297c478bd9Sstevel@tonic-gate #include "ifconfig.h" 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <libdlpi.h> 327c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 33c7e4935fSss150715 #include <sys/time.h> 347c478bd9Sstevel@tonic-gate #include <deflt.h> 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #define IPADDRL sizeof (struct in_addr) 377c478bd9Sstevel@tonic-gate #define RARPRETRIES 5 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 407c478bd9Sstevel@tonic-gate * The following value (8) is determined to work reliably in switched 10/100MB 417c478bd9Sstevel@tonic-gate * ethernet environments. Use caution if you plan on decreasing it. 427c478bd9Sstevel@tonic-gate */ 437c478bd9Sstevel@tonic-gate #define RARPTIMEOUT 8 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate static char defaultfile[] = "/etc/inet/rarp"; 467c478bd9Sstevel@tonic-gate static char retries_var[] = "RARP_RETRIES="; 477c478bd9Sstevel@tonic-gate static int rarp_timeout = RARPTIMEOUT; 487c478bd9Sstevel@tonic-gate static int rarp_retries = RARPRETRIES; 497c478bd9Sstevel@tonic-gate 50c7e4935fSss150715 static dlpi_handle_t rarp_open(const char *, size_t *, uchar_t *, uchar_t *); 51c7e4935fSss150715 static int rarp_recv(dlpi_handle_t, struct arphdr *, size_t, size_t, int64_t); 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate int 54c7e4935fSss150715 doifrevarp(const char *linkname, struct sockaddr_in *laddr) 557c478bd9Sstevel@tonic-gate { 56c7e4935fSss150715 int s, retval; 577c478bd9Sstevel@tonic-gate struct arphdr *req, *ans; 587c478bd9Sstevel@tonic-gate struct in_addr from; 597c478bd9Sstevel@tonic-gate struct in_addr answer; 607c478bd9Sstevel@tonic-gate struct lifreq lifr; 617c478bd9Sstevel@tonic-gate int tries_left; 62c7e4935fSss150715 size_t physaddrlen, ifrarplen; 63c7e4935fSss150715 uchar_t my_macaddr[DLPI_PHYSADDR_MAX]; 64c7e4935fSss150715 uchar_t my_broadcast[DLPI_PHYSADDR_MAX]; 65c7e4935fSss150715 dlpi_handle_t dh; 667c478bd9Sstevel@tonic-gate 67c7e4935fSss150715 if (linkname[0] == '\0') { 687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "ifconfig: doifrevarp: name not set\n"); 697c478bd9Sstevel@tonic-gate exit(1); 707c478bd9Sstevel@tonic-gate } 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate if (debug) 73c7e4935fSss150715 (void) printf("doifrevarp interface %s\n", linkname); 747c478bd9Sstevel@tonic-gate 75c7e4935fSss150715 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 767c478bd9Sstevel@tonic-gate Perror0_exit("socket"); 77c7e4935fSss150715 78c7e4935fSss150715 (void) strlcpy(lifr.lifr_name, linkname, sizeof (lifr.lifr_name)); 79c7e4935fSss150715 if (ioctl(s, SIOCGLIFFLAGS, (char *)&lifr) < 0) { 80c7e4935fSss150715 (void) close(s); 817c478bd9Sstevel@tonic-gate Perror0_exit("SIOCGLIFFLAGS"); 82c7e4935fSss150715 } 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* don't try to revarp if we know it won't work */ 857c478bd9Sstevel@tonic-gate if ((lifr.lifr_flags & IFF_LOOPBACK) || 867c478bd9Sstevel@tonic-gate (lifr.lifr_flags & IFF_NOARP) || 87*e11c3f44Smeem (lifr.lifr_flags & IFF_IPMP) || 88c7e4935fSss150715 (lifr.lifr_flags & IFF_POINTOPOINT)) { 89c7e4935fSss150715 (void) close(s); 907c478bd9Sstevel@tonic-gate return (0); 91c7e4935fSss150715 } 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* open rarp interface */ 94c7e4935fSss150715 dh = rarp_open(linkname, &physaddrlen, my_macaddr, my_broadcast); 95c7e4935fSss150715 if (dh == NULL) { 96c7e4935fSss150715 (void) close(s); 977c478bd9Sstevel@tonic-gate return (0); 98c7e4935fSss150715 } 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate /* 1017c478bd9Sstevel@tonic-gate * RARP looks at /etc/ethers and NIS, which only works 1027c478bd9Sstevel@tonic-gate * with 6 byte addresses currently. 1037c478bd9Sstevel@tonic-gate */ 104c7e4935fSss150715 if (physaddrlen != ETHERADDRL) { 105c7e4935fSss150715 dlpi_close(dh); 106c7e4935fSss150715 (void) close(s); 1077c478bd9Sstevel@tonic-gate return (0); 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate 110c7e4935fSss150715 ifrarplen = sizeof (struct arphdr) + (2 * IPADDRL) + (2 * physaddrlen); 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /* look for adjustments to rarp_retries in the RARP defaults file */ 1137c478bd9Sstevel@tonic-gate if (defopen(defaultfile) == 0) { 1147c478bd9Sstevel@tonic-gate char *cp; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate if (cp = defread(retries_var)) { 1177c478bd9Sstevel@tonic-gate int ntries; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate ntries = atoi(cp); 1207c478bd9Sstevel@tonic-gate if (ntries > 0) 1217c478bd9Sstevel@tonic-gate rarp_retries = ntries; 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate (void) defopen(NULL); /* close default file */ 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* allocate request and response buffers */ 127c7e4935fSss150715 if (((req = malloc(ifrarplen)) == NULL) || 128c7e4935fSss150715 ((ans = malloc(ifrarplen)) == NULL)) { 129c7e4935fSss150715 dlpi_close(dh); 130c7e4935fSss150715 (void) close(s); 1317c478bd9Sstevel@tonic-gate free(req); 1327c478bd9Sstevel@tonic-gate return (0); 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* create rarp request */ 1367c478bd9Sstevel@tonic-gate (void) memset(req, 0, ifrarplen); 1377c478bd9Sstevel@tonic-gate req->ar_hrd = htons(ARPHRD_ETHER); 1387c478bd9Sstevel@tonic-gate req->ar_pro = htons(ETHERTYPE_IP); 139c7e4935fSss150715 req->ar_hln = physaddrlen; 1407c478bd9Sstevel@tonic-gate req->ar_pln = IPADDRL; 1417c478bd9Sstevel@tonic-gate req->ar_op = htons(REVARP_REQUEST); 1427c478bd9Sstevel@tonic-gate 143c7e4935fSss150715 (void) memcpy(&req[1], my_macaddr, physaddrlen); 1447c478bd9Sstevel@tonic-gate (void) memcpy((uchar_t *)req + sizeof (struct arphdr) + IPADDRL + 145c7e4935fSss150715 physaddrlen, my_macaddr, physaddrlen); 1467c478bd9Sstevel@tonic-gate 147c7e4935fSss150715 for (tries_left = rarp_retries; tries_left > 0; --tries_left) { 1487c478bd9Sstevel@tonic-gate /* send the request */ 149c7e4935fSss150715 retval = dlpi_send(dh, my_broadcast, physaddrlen, req, 150c7e4935fSss150715 ifrarplen, NULL); 151c7e4935fSss150715 if (retval != DLPI_SUCCESS) { 152c7e4935fSss150715 Perrdlpi("doifrevarp: cannot send rarp request", 153c7e4935fSss150715 linkname, retval); 154c7e4935fSss150715 break; 155c7e4935fSss150715 } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate if (debug) 1587c478bd9Sstevel@tonic-gate (void) printf("rarp sent\n"); 1597c478bd9Sstevel@tonic-gate 160c7e4935fSss150715 retval = rarp_recv(dh, ans, ifrarplen, physaddrlen, 161c7e4935fSss150715 rarp_timeout * MILLISEC); 1627c478bd9Sstevel@tonic-gate 163c7e4935fSss150715 if (retval != DLPI_ETIMEDOUT) 164c7e4935fSss150715 break; 165c7e4935fSss150715 166c7e4935fSss150715 if (debug) 167c7e4935fSss150715 (void) printf("rarp retry\n"); 1687c478bd9Sstevel@tonic-gate } 169c7e4935fSss150715 170c7e4935fSss150715 if (retval == DLPI_SUCCESS) { 171c7e4935fSss150715 (void) memcpy(&answer, (uchar_t *)ans + 172c7e4935fSss150715 sizeof (struct arphdr) + (2 * physaddrlen) + IPADDRL, 173c7e4935fSss150715 sizeof (answer)); 174c7e4935fSss150715 (void) memcpy(&from, (uchar_t *)ans + physaddrlen + 175c7e4935fSss150715 sizeof (struct arphdr), sizeof (from)); 176c7e4935fSss150715 177c7e4935fSss150715 if (debug) { 178c7e4935fSss150715 (void) printf("answer: %s", inet_ntoa(answer)); 179c7e4935fSss150715 (void) printf(" [from %s]\n", inet_ntoa(from)); 1807c478bd9Sstevel@tonic-gate } 181c7e4935fSss150715 laddr->sin_addr = answer; 182c7e4935fSss150715 } else if (debug) { 183c7e4935fSss150715 Perrdlpi("doifrevarp: could not receive rarp reply", 184c7e4935fSss150715 linkname, retval); 185c7e4935fSss150715 } 186c7e4935fSss150715 187c7e4935fSss150715 dlpi_close(dh); 188c7e4935fSss150715 (void) close(s); 189c7e4935fSss150715 free(req); 190c7e4935fSss150715 free(ans); 191c7e4935fSss150715 return (retval == DLPI_SUCCESS); 192c7e4935fSss150715 } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 195c7e4935fSss150715 * Open the datalink provider device and bind to the REVARP type. 196c7e4935fSss150715 * Return the resulting DLPI handle. 1977c478bd9Sstevel@tonic-gate */ 198c7e4935fSss150715 static dlpi_handle_t 199c7e4935fSss150715 rarp_open(const char *linkname, size_t *alen, uchar_t *myaddr, uchar_t *mybaddr) 200c7e4935fSss150715 { 201c7e4935fSss150715 int retval; 202c7e4935fSss150715 char *physaddr, *bcastaddr; 203c7e4935fSss150715 dlpi_info_t dlinfo; 204c7e4935fSss150715 dlpi_handle_t dh; 2057c478bd9Sstevel@tonic-gate 206c7e4935fSss150715 if (debug) 207c7e4935fSss150715 (void) printf("rarp_open %s\n", linkname); 2087c478bd9Sstevel@tonic-gate 209c7e4935fSss150715 if ((retval = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) { 210c7e4935fSss150715 Perrdlpi("rarp_open: dlpi_open failed", linkname, retval); 211c7e4935fSss150715 return (NULL); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 214c7e4935fSss150715 if ((retval = dlpi_bind(dh, ETHERTYPE_REVARP, NULL)) != DLPI_SUCCESS) { 215c7e4935fSss150715 Perrdlpi("rarp_open: dlpi_bind failed", linkname, retval); 216c7e4935fSss150715 goto failed; 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 219c7e4935fSss150715 if ((retval = dlpi_info(dh, &dlinfo, 0)) != DLPI_SUCCESS) { 220c7e4935fSss150715 Perrdlpi("rarp_open: dlpi_info failed", linkname, retval); 221c7e4935fSss150715 goto failed; 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 224c7e4935fSss150715 if (dlinfo.di_bcastaddrlen == 0) { 225c7e4935fSss150715 (void) fprintf(stderr, "ifconfig: rarp_open: %s broadcast " 226c7e4935fSss150715 "not supported\n", linkname); 227c7e4935fSss150715 goto failed; 228c7e4935fSss150715 } 229c7e4935fSss150715 230c7e4935fSss150715 /* we assume the following are equal and fill in 'alen' */ 231c7e4935fSss150715 assert(dlinfo.di_bcastaddrlen == dlinfo.di_physaddrlen); 232c7e4935fSss150715 233c7e4935fSss150715 (void) memcpy(mybaddr, dlinfo.di_bcastaddr, dlinfo.di_bcastaddrlen); 234c7e4935fSss150715 235c7e4935fSss150715 *alen = dlinfo.di_physaddrlen; 236c7e4935fSss150715 237c7e4935fSss150715 (void) memcpy(myaddr, dlinfo.di_physaddr, dlinfo.di_physaddrlen); 238c7e4935fSss150715 2397c478bd9Sstevel@tonic-gate if (debug) { 240c7e4935fSss150715 bcastaddr = _link_ntoa(mybaddr, NULL, dlinfo.di_bcastaddrlen, 241c7e4935fSss150715 IFT_OTHER); 242c7e4935fSss150715 243c7e4935fSss150715 physaddr = _link_ntoa(myaddr, NULL, dlinfo.di_physaddrlen, 244c7e4935fSss150715 IFT_OTHER); 245c7e4935fSss150715 246c7e4935fSss150715 if (physaddr != NULL && bcastaddr != NULL) { 247c7e4935fSss150715 (void) printf("device %s: broadcast address %s, mac " 248c7e4935fSss150715 "address %s\n", linkname, bcastaddr, physaddr); 2497c478bd9Sstevel@tonic-gate } 250c7e4935fSss150715 251c7e4935fSss150715 free(physaddr); 252c7e4935fSss150715 free(bcastaddr); 253c7e4935fSss150715 254c7e4935fSss150715 (void) printf("rarp_open: addr length = %d\n", 255c7e4935fSss150715 dlinfo.di_physaddrlen); 2567c478bd9Sstevel@tonic-gate } 257c7e4935fSss150715 258c7e4935fSss150715 return (dh); 259c7e4935fSss150715 260c7e4935fSss150715 failed: 261c7e4935fSss150715 dlpi_close(dh); 262c7e4935fSss150715 return (NULL); 2637c478bd9Sstevel@tonic-gate } 264c7e4935fSss150715 265c7e4935fSss150715 /* 266c7e4935fSss150715 * Read reply for RARP request. If a reply is received within waitms, 267c7e4935fSss150715 * validate the reply. If it is a correct RARP reply return DLPI_SUCCESS, 268c7e4935fSss150715 * otherwise return DLPI_ETIMEDOUT. If there is an error while reading retrun 269c7e4935fSss150715 * the error code. 270c7e4935fSss150715 */ 271c7e4935fSss150715 static int 272c7e4935fSss150715 rarp_recv(dlpi_handle_t dh, struct arphdr *ans, size_t msglen, 273c7e4935fSss150715 size_t physaddrlen, int64_t waitms) 274c7e4935fSss150715 { 275c7e4935fSss150715 int retval; 276c7e4935fSss150715 char *cause; 277c7e4935fSss150715 size_t anslen = msglen; 278c7e4935fSss150715 hrtime_t endtime = gethrtime() + MSEC2NSEC(waitms); 279c7e4935fSss150715 hrtime_t currtime; 280c7e4935fSss150715 281c7e4935fSss150715 while ((currtime = gethrtime()) < endtime) { 282c7e4935fSss150715 waitms = NSEC2MSEC(endtime - currtime); 283c7e4935fSss150715 retval = dlpi_recv(dh, NULL, NULL, ans, &anslen, waitms, NULL); 284c7e4935fSss150715 if (retval == DLPI_SUCCESS) { 2857c478bd9Sstevel@tonic-gate cause = NULL; 2867c478bd9Sstevel@tonic-gate 287c7e4935fSss150715 if (anslen < msglen) 288c7e4935fSss150715 cause = "short packet"; 2897c478bd9Sstevel@tonic-gate else if (ans->ar_hrd != htons(ARPHRD_ETHER)) 290c7e4935fSss150715 cause = "hardware type not Ethernet"; 2917c478bd9Sstevel@tonic-gate else if (ans->ar_pro != htons(ETHERTYPE_IP)) 292c7e4935fSss150715 cause = "protocol type not IP"; 293c7e4935fSss150715 else if (ans->ar_hln != physaddrlen) 294c7e4935fSss150715 cause = "unexpected hardware address length"; 2957c478bd9Sstevel@tonic-gate else if (ans->ar_pln != IPADDRL) 296c7e4935fSss150715 cause = "unexpected protocol address length"; 297c7e4935fSss150715 if (cause != NULL) { 298c7e4935fSss150715 (void) fprintf(stderr, "RARP packet received " 299c7e4935fSss150715 "but discarded (%s)\n", cause); 3007c478bd9Sstevel@tonic-gate continue; 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate switch (ntohs(ans->ar_op)) { 3037c478bd9Sstevel@tonic-gate case REVARP_REQUEST: 3047c478bd9Sstevel@tonic-gate if (debug) 3057c478bd9Sstevel@tonic-gate (void) printf("Got a rarp request.\n"); 3067c478bd9Sstevel@tonic-gate break; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate case REVARP_REPLY: 309c7e4935fSss150715 return (DLPI_SUCCESS); 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate default: 312c7e4935fSss150715 (void) fprintf(stderr, "ifconfig: unknown " 313c7e4935fSss150715 "RARP opcode 0x%x\n", ans->ar_op); 3147c478bd9Sstevel@tonic-gate break; 3157c478bd9Sstevel@tonic-gate } 316c7e4935fSss150715 } else if (retval != DLPI_ETIMEDOUT) { 317c7e4935fSss150715 Perrdlpi("doifrevarp: dlpi_recv failed", 318c7e4935fSss150715 dlpi_linkname(dh), retval); 319c7e4935fSss150715 return (retval); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 323c7e4935fSss150715 return (DLPI_ETIMEDOUT); 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate void 327c7e4935fSss150715 dlpi_print_address(const char *linkname) 3287c478bd9Sstevel@tonic-gate { 329c7e4935fSss150715 uint_t physaddrlen = DLPI_PHYSADDR_MAX; 330c7e4935fSss150715 uchar_t physaddr[DLPI_PHYSADDR_MAX]; 331c7e4935fSss150715 char *str; 332c7e4935fSss150715 int retv; 333c7e4935fSss150715 dlpi_handle_t dh; 334c7e4935fSss150715 dlpi_info_t dlinfo; 3357c478bd9Sstevel@tonic-gate 336c7e4935fSss150715 if (dlpi_open(linkname, &dh, 0) != DLPI_SUCCESS) { 3377c478bd9Sstevel@tonic-gate /* Do not report an error */ 3387c478bd9Sstevel@tonic-gate return; 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate 341c7e4935fSss150715 retv = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, physaddr, &physaddrlen); 342c7e4935fSss150715 if (retv != DLPI_SUCCESS) { 343c7e4935fSss150715 Perrdlpi("dlpi_get_physaddr failed", linkname, retv); 344c7e4935fSss150715 dlpi_close(dh); 345b1241e9cSyw138387 return; 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate 348c7e4935fSss150715 retv = dlpi_info(dh, &dlinfo, 0); 349c7e4935fSss150715 if (retv != DLPI_SUCCESS) { 350c7e4935fSss150715 Perrdlpi("dlpi_info failed", linkname, retv); 351c7e4935fSss150715 dlpi_close(dh); 352c7e4935fSss150715 return; 3537c478bd9Sstevel@tonic-gate } 354c7e4935fSss150715 dlpi_close(dh); 3557c478bd9Sstevel@tonic-gate 356c7e4935fSss150715 str = _link_ntoa(physaddr, NULL, physaddrlen, IFT_OTHER); 3577c478bd9Sstevel@tonic-gate 358c08e5e1aSdr146992 if (str != NULL && physaddrlen != 0) { 359c7e4935fSss150715 switch (dlinfo.di_mactype) { 3607c478bd9Sstevel@tonic-gate case DL_IB: 3617c478bd9Sstevel@tonic-gate (void) printf("\tipib %s \n", str); 3627c478bd9Sstevel@tonic-gate break; 3637c478bd9Sstevel@tonic-gate default: 3647c478bd9Sstevel@tonic-gate (void) printf("\tether %s \n", str); 3657c478bd9Sstevel@tonic-gate break; 3667c478bd9Sstevel@tonic-gate } 3677c478bd9Sstevel@tonic-gate free(str); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate } 370