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 2004 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 <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 34*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 35*7c478bd9Sstevel@tonic-gate #include <inet/led.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate static void convert2ascii(char *, const in6_addr_t *); 38*7c478bd9Sstevel@tonic-gate static char *strchr_w(const char *, int); 39*7c478bd9Sstevel@tonic-gate static int str2inet_addr(char *, ipaddr_t *); 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* 42*7c478bd9Sstevel@tonic-gate * inet_ntop -- Convert an IPv4 or IPv6 address in binary form into 43*7c478bd9Sstevel@tonic-gate * printable form, and return a pointer to that string. Caller should 44*7c478bd9Sstevel@tonic-gate * provide a buffer of correct length to store string into. 45*7c478bd9Sstevel@tonic-gate * Note: this routine is kernel version of inet_ntop. It has similar 46*7c478bd9Sstevel@tonic-gate * format as inet_ntop() defined in rfc2553. But it does not do 47*7c478bd9Sstevel@tonic-gate * error handling operations exactly as rfc2553 defines. This function 48*7c478bd9Sstevel@tonic-gate * is used by kernel inet directory routines only for debugging. 49*7c478bd9Sstevel@tonic-gate * This inet_ntop() function, does not return NULL if third argument 50*7c478bd9Sstevel@tonic-gate * is NULL. The reason is simple that we don't want kernel to panic 51*7c478bd9Sstevel@tonic-gate * as the output of this function is directly fed to ip<n>dbg macro. 52*7c478bd9Sstevel@tonic-gate * Instead it uses a local buffer for destination address for 53*7c478bd9Sstevel@tonic-gate * those calls which purposely pass NULL ptr for the destination 54*7c478bd9Sstevel@tonic-gate * buffer. This function is thread-safe when the caller passes a non- 55*7c478bd9Sstevel@tonic-gate * null buffer with the third argument. 56*7c478bd9Sstevel@tonic-gate */ 57*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 58*7c478bd9Sstevel@tonic-gate char * 59*7c478bd9Sstevel@tonic-gate inet_ntop(int af, const void *addr, char *buf, int addrlen) 60*7c478bd9Sstevel@tonic-gate { 61*7c478bd9Sstevel@tonic-gate static char local_buf[INET6_ADDRSTRLEN]; 62*7c478bd9Sstevel@tonic-gate static char *err_buf1 = "<badaddr>"; 63*7c478bd9Sstevel@tonic-gate static char *err_buf2 = "<badfamily>"; 64*7c478bd9Sstevel@tonic-gate in6_addr_t *v6addr; 65*7c478bd9Sstevel@tonic-gate uchar_t *v4addr; 66*7c478bd9Sstevel@tonic-gate char *caddr; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* 69*7c478bd9Sstevel@tonic-gate * We don't allow thread unsafe inet_ntop calls, they 70*7c478bd9Sstevel@tonic-gate * must pass a non-null buffer pointer. For DEBUG mode 71*7c478bd9Sstevel@tonic-gate * we use the ASSERT() and for non-debug kernel it will 72*7c478bd9Sstevel@tonic-gate * silently allow it for now. Someday we should remove 73*7c478bd9Sstevel@tonic-gate * the static buffer from this function. 74*7c478bd9Sstevel@tonic-gate */ 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate ASSERT(buf != NULL); 77*7c478bd9Sstevel@tonic-gate if (buf == NULL) 78*7c478bd9Sstevel@tonic-gate buf = local_buf; 79*7c478bd9Sstevel@tonic-gate buf[0] = '\0'; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* Let user know politely not to send NULL or unaligned addr */ 82*7c478bd9Sstevel@tonic-gate if (addr == NULL || !(OK_32PTR(addr))) { 83*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 84*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "inet_ntop: addr is <null> or unaligned"); 85*7c478bd9Sstevel@tonic-gate #endif 86*7c478bd9Sstevel@tonic-gate return (err_buf1); 87*7c478bd9Sstevel@tonic-gate } 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate #define UC(b) (((int)b) & 0xff) 91*7c478bd9Sstevel@tonic-gate switch (af) { 92*7c478bd9Sstevel@tonic-gate case AF_INET: 93*7c478bd9Sstevel@tonic-gate ASSERT(addrlen >= INET_ADDRSTRLEN); 94*7c478bd9Sstevel@tonic-gate v4addr = (uchar_t *)addr; 95*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%03d.%03d.%03d.%03d", 96*7c478bd9Sstevel@tonic-gate UC(v4addr[0]), UC(v4addr[1]), UC(v4addr[2]), UC(v4addr[3])); 97*7c478bd9Sstevel@tonic-gate return (buf); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate case AF_INET6: 100*7c478bd9Sstevel@tonic-gate ASSERT(addrlen >= INET6_ADDRSTRLEN); 101*7c478bd9Sstevel@tonic-gate v6addr = (in6_addr_t *)addr; 102*7c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(v6addr)) { 103*7c478bd9Sstevel@tonic-gate caddr = (char *)addr; 104*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "::ffff:%d.%d.%d.%d", 105*7c478bd9Sstevel@tonic-gate UC(caddr[12]), UC(caddr[13]), 106*7c478bd9Sstevel@tonic-gate UC(caddr[14]), UC(caddr[15])); 107*7c478bd9Sstevel@tonic-gate } else if (IN6_IS_ADDR_V4COMPAT(v6addr)) { 108*7c478bd9Sstevel@tonic-gate caddr = (char *)addr; 109*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "::%d.%d.%d.%d", 110*7c478bd9Sstevel@tonic-gate UC(caddr[12]), UC(caddr[13]), UC(caddr[14]), 111*7c478bd9Sstevel@tonic-gate UC(caddr[15])); 112*7c478bd9Sstevel@tonic-gate } else if (IN6_IS_ADDR_UNSPECIFIED(v6addr)) { 113*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "::"); 114*7c478bd9Sstevel@tonic-gate } else { 115*7c478bd9Sstevel@tonic-gate convert2ascii(buf, v6addr); 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate return (buf); 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate default: 120*7c478bd9Sstevel@tonic-gate return (err_buf2); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate #undef UC 123*7c478bd9Sstevel@tonic-gate } 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate /* 126*7c478bd9Sstevel@tonic-gate * 127*7c478bd9Sstevel@tonic-gate * v6 formats supported 128*7c478bd9Sstevel@tonic-gate * General format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx 129*7c478bd9Sstevel@tonic-gate * The short hand notation :: is used for COMPAT addr 130*7c478bd9Sstevel@tonic-gate * Other forms : fe80::xxxx:xxxx:xxxx:xxxx 131*7c478bd9Sstevel@tonic-gate */ 132*7c478bd9Sstevel@tonic-gate static void 133*7c478bd9Sstevel@tonic-gate convert2ascii(char *buf, const in6_addr_t *addr) 134*7c478bd9Sstevel@tonic-gate { 135*7c478bd9Sstevel@tonic-gate int hexdigits; 136*7c478bd9Sstevel@tonic-gate int head_zero = 0; 137*7c478bd9Sstevel@tonic-gate int tail_zero = 0; 138*7c478bd9Sstevel@tonic-gate /* tempbuf must be big enough to hold ffff:\0 */ 139*7c478bd9Sstevel@tonic-gate char tempbuf[6]; 140*7c478bd9Sstevel@tonic-gate char *ptr; 141*7c478bd9Sstevel@tonic-gate uint16_t *addr_component; 142*7c478bd9Sstevel@tonic-gate size_t len; 143*7c478bd9Sstevel@tonic-gate boolean_t first = B_FALSE; 144*7c478bd9Sstevel@tonic-gate boolean_t med_zero = B_FALSE; 145*7c478bd9Sstevel@tonic-gate boolean_t end_zero = B_FALSE; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate addr_component = (uint16_t *)addr; 148*7c478bd9Sstevel@tonic-gate ptr = buf; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate /* First count if trailing zeroes higher in number */ 151*7c478bd9Sstevel@tonic-gate for (hexdigits = 0; hexdigits < 8; hexdigits++) { 152*7c478bd9Sstevel@tonic-gate if (*addr_component == 0) { 153*7c478bd9Sstevel@tonic-gate if (hexdigits < 4) 154*7c478bd9Sstevel@tonic-gate head_zero++; 155*7c478bd9Sstevel@tonic-gate else 156*7c478bd9Sstevel@tonic-gate tail_zero++; 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate addr_component++; 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate addr_component = (uint16_t *)addr; 161*7c478bd9Sstevel@tonic-gate if (tail_zero > head_zero && (head_zero + tail_zero) != 7) 162*7c478bd9Sstevel@tonic-gate end_zero = B_TRUE; 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate for (hexdigits = 0; hexdigits < 8; hexdigits++) { 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate /* if entry is a 0 */ 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate if (*addr_component == 0) { 169*7c478bd9Sstevel@tonic-gate if (!first && *(addr_component + 1) == 0) { 170*7c478bd9Sstevel@tonic-gate if (end_zero && (hexdigits < 4)) { 171*7c478bd9Sstevel@tonic-gate *ptr++ = '0'; 172*7c478bd9Sstevel@tonic-gate *ptr++ = ':'; 173*7c478bd9Sstevel@tonic-gate } else { 174*7c478bd9Sstevel@tonic-gate /* 175*7c478bd9Sstevel@tonic-gate * address starts with 0s .. 176*7c478bd9Sstevel@tonic-gate * stick in leading ':' of pair 177*7c478bd9Sstevel@tonic-gate */ 178*7c478bd9Sstevel@tonic-gate if (hexdigits == 0) 179*7c478bd9Sstevel@tonic-gate *ptr++ = ':'; 180*7c478bd9Sstevel@tonic-gate /* add another */ 181*7c478bd9Sstevel@tonic-gate *ptr++ = ':'; 182*7c478bd9Sstevel@tonic-gate first = B_TRUE; 183*7c478bd9Sstevel@tonic-gate med_zero = B_TRUE; 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate } else if (first && med_zero) { 186*7c478bd9Sstevel@tonic-gate if (hexdigits == 7) 187*7c478bd9Sstevel@tonic-gate *ptr++ = ':'; 188*7c478bd9Sstevel@tonic-gate addr_component++; 189*7c478bd9Sstevel@tonic-gate continue; 190*7c478bd9Sstevel@tonic-gate } else { 191*7c478bd9Sstevel@tonic-gate *ptr++ = '0'; 192*7c478bd9Sstevel@tonic-gate *ptr++ = ':'; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate addr_component++; 195*7c478bd9Sstevel@tonic-gate continue; 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate if (med_zero) 198*7c478bd9Sstevel@tonic-gate med_zero = B_FALSE; 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate tempbuf[0] = '\0'; 201*7c478bd9Sstevel@tonic-gate (void) sprintf(tempbuf, "%x:", ntohs(*addr_component) & 0xffff); 202*7c478bd9Sstevel@tonic-gate len = strlen(tempbuf); 203*7c478bd9Sstevel@tonic-gate bcopy(tempbuf, ptr, len); 204*7c478bd9Sstevel@tonic-gate ptr = ptr + len; 205*7c478bd9Sstevel@tonic-gate addr_component++; 206*7c478bd9Sstevel@tonic-gate } 207*7c478bd9Sstevel@tonic-gate *--ptr = '\0'; 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate /* 211*7c478bd9Sstevel@tonic-gate * search for char c, terminate on trailing white space 212*7c478bd9Sstevel@tonic-gate */ 213*7c478bd9Sstevel@tonic-gate static char * 214*7c478bd9Sstevel@tonic-gate strchr_w(const char *sp, int c) 215*7c478bd9Sstevel@tonic-gate { 216*7c478bd9Sstevel@tonic-gate /* skip leading white space */ 217*7c478bd9Sstevel@tonic-gate while (*sp && (*sp == ' ' || *sp == '\t')) { 218*7c478bd9Sstevel@tonic-gate sp++; 219*7c478bd9Sstevel@tonic-gate } 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate do { 222*7c478bd9Sstevel@tonic-gate if (*sp == (char)c) 223*7c478bd9Sstevel@tonic-gate return ((char *)sp); 224*7c478bd9Sstevel@tonic-gate if (*sp == ' ' || *sp == '\t') 225*7c478bd9Sstevel@tonic-gate return (NULL); 226*7c478bd9Sstevel@tonic-gate } while (*sp++); 227*7c478bd9Sstevel@tonic-gate return (NULL); 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate static int 231*7c478bd9Sstevel@tonic-gate str2inet_addr(char *cp, ipaddr_t *addrp) 232*7c478bd9Sstevel@tonic-gate { 233*7c478bd9Sstevel@tonic-gate char *end; 234*7c478bd9Sstevel@tonic-gate long byte; 235*7c478bd9Sstevel@tonic-gate int i; 236*7c478bd9Sstevel@tonic-gate ipaddr_t addr = 0; 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate for (i = 0; i < 4; i++) { 239*7c478bd9Sstevel@tonic-gate if (ddi_strtol(cp, &end, 10, &byte) != 0 || byte < 0 || 240*7c478bd9Sstevel@tonic-gate byte > 255) { 241*7c478bd9Sstevel@tonic-gate return (0); 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate addr = (addr << 8) | (uint8_t)byte; 244*7c478bd9Sstevel@tonic-gate if (i < 3) { 245*7c478bd9Sstevel@tonic-gate if (*end != '.') { 246*7c478bd9Sstevel@tonic-gate return (0); 247*7c478bd9Sstevel@tonic-gate } else { 248*7c478bd9Sstevel@tonic-gate cp = end + 1; 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate } else { 251*7c478bd9Sstevel@tonic-gate cp = end; 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate *addrp = addr; 255*7c478bd9Sstevel@tonic-gate return (1); 256*7c478bd9Sstevel@tonic-gate } 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate /* 259*7c478bd9Sstevel@tonic-gate * inet_pton: This function takes string format IPv4 or IPv6 address and 260*7c478bd9Sstevel@tonic-gate * converts it to binary form. The format of this function corresponds to 261*7c478bd9Sstevel@tonic-gate * inet_pton() in the socket library. 262*7c478bd9Sstevel@tonic-gate * It returns 0 for invalid IPv4 and IPv6 address 263*7c478bd9Sstevel@tonic-gate * 1 when successfully converts ascii to binary 264*7c478bd9Sstevel@tonic-gate * -1 when af is not AF_INET or AF_INET6 265*7c478bd9Sstevel@tonic-gate */ 266*7c478bd9Sstevel@tonic-gate int 267*7c478bd9Sstevel@tonic-gate inet_pton(int af, char *inp, void *outp) 268*7c478bd9Sstevel@tonic-gate { 269*7c478bd9Sstevel@tonic-gate int i; 270*7c478bd9Sstevel@tonic-gate long byte; 271*7c478bd9Sstevel@tonic-gate char *end; 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate switch (af) { 274*7c478bd9Sstevel@tonic-gate case AF_INET: 275*7c478bd9Sstevel@tonic-gate return (str2inet_addr(inp, (ipaddr_t *)outp)); 276*7c478bd9Sstevel@tonic-gate case AF_INET6: { 277*7c478bd9Sstevel@tonic-gate union v6buf_u { 278*7c478bd9Sstevel@tonic-gate uint16_t v6words_u[8]; 279*7c478bd9Sstevel@tonic-gate in6_addr_t v6addr_u; 280*7c478bd9Sstevel@tonic-gate } v6buf, *v6outp; 281*7c478bd9Sstevel@tonic-gate uint16_t *dbl_col = NULL; 282*7c478bd9Sstevel@tonic-gate char lastbyte = NULL; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate v6outp = (union v6buf_u *)outp; 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate if (strchr_w(inp, '.') != NULL) { 287*7c478bd9Sstevel@tonic-gate /* v4 mapped or v4 compatable */ 288*7c478bd9Sstevel@tonic-gate if (strncmp(inp, "::ffff:", 7) == 0) { 289*7c478bd9Sstevel@tonic-gate ipaddr_t ipv4_all_zeroes = 0; 290*7c478bd9Sstevel@tonic-gate /* mapped - first init prefix and then fill */ 291*7c478bd9Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(ipv4_all_zeroes, 292*7c478bd9Sstevel@tonic-gate &v6outp->v6addr_u); 293*7c478bd9Sstevel@tonic-gate return (str2inet_addr(inp + 7, 294*7c478bd9Sstevel@tonic-gate &(v6outp->v6addr_u.s6_addr32[3]))); 295*7c478bd9Sstevel@tonic-gate } else if (strncmp(inp, "::", 2) == 0) { 296*7c478bd9Sstevel@tonic-gate /* v4 compatable - prefix all zeroes */ 297*7c478bd9Sstevel@tonic-gate bzero(&v6outp->v6addr_u, sizeof (in6_addr_t)); 298*7c478bd9Sstevel@tonic-gate return (str2inet_addr(inp + 2, 299*7c478bd9Sstevel@tonic-gate &(v6outp->v6addr_u.s6_addr32[3]))); 300*7c478bd9Sstevel@tonic-gate } 301*7c478bd9Sstevel@tonic-gate return (0); 302*7c478bd9Sstevel@tonic-gate } 303*7c478bd9Sstevel@tonic-gate for (i = 0; i < 8; i++) { 304*7c478bd9Sstevel@tonic-gate int error; 305*7c478bd9Sstevel@tonic-gate /* 306*7c478bd9Sstevel@tonic-gate * if ddi_strtol() fails it could be because 307*7c478bd9Sstevel@tonic-gate * the string is "::". That is valid and 308*7c478bd9Sstevel@tonic-gate * checked for below so just set the value to 309*7c478bd9Sstevel@tonic-gate * 0 and continue. 310*7c478bd9Sstevel@tonic-gate */ 311*7c478bd9Sstevel@tonic-gate if ((error = ddi_strtol(inp, &end, 16, &byte)) != 0) { 312*7c478bd9Sstevel@tonic-gate if (error == ERANGE) 313*7c478bd9Sstevel@tonic-gate return (0); 314*7c478bd9Sstevel@tonic-gate byte = 0; 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate if (byte < 0 || byte > 0x0ffff) { 317*7c478bd9Sstevel@tonic-gate return (0); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate v6buf.v6words_u[i] = (uint16_t)byte; 320*7c478bd9Sstevel@tonic-gate if (*end == NULL || i == 7) { 321*7c478bd9Sstevel@tonic-gate inp = end; 322*7c478bd9Sstevel@tonic-gate break; 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate if (inp == end) { /* not a number must be */ 325*7c478bd9Sstevel@tonic-gate if (*inp == ':' && 326*7c478bd9Sstevel@tonic-gate ((i == 0 && *(inp + 1) == ':') || 327*7c478bd9Sstevel@tonic-gate lastbyte == ':')) { 328*7c478bd9Sstevel@tonic-gate if (dbl_col) { 329*7c478bd9Sstevel@tonic-gate return (0); 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate if (byte != 0) 332*7c478bd9Sstevel@tonic-gate i++; 333*7c478bd9Sstevel@tonic-gate dbl_col = &v6buf.v6words_u[i]; 334*7c478bd9Sstevel@tonic-gate if (i == 0) 335*7c478bd9Sstevel@tonic-gate inp++; 336*7c478bd9Sstevel@tonic-gate } else if (*inp == NULL || *inp == ' ' || 337*7c478bd9Sstevel@tonic-gate *inp == '\t') { 338*7c478bd9Sstevel@tonic-gate break; 339*7c478bd9Sstevel@tonic-gate } else { 340*7c478bd9Sstevel@tonic-gate return (0); 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate } else { 343*7c478bd9Sstevel@tonic-gate inp = end; 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate if (*inp != ':') { 346*7c478bd9Sstevel@tonic-gate return (0); 347*7c478bd9Sstevel@tonic-gate } 348*7c478bd9Sstevel@tonic-gate inp++; 349*7c478bd9Sstevel@tonic-gate if (*inp == NULL || *inp == ' ' || *inp == '\t') { 350*7c478bd9Sstevel@tonic-gate break; 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate lastbyte = *inp; 353*7c478bd9Sstevel@tonic-gate } 354*7c478bd9Sstevel@tonic-gate if (*inp != NULL && *inp != ' ' && *inp != '\t') { 355*7c478bd9Sstevel@tonic-gate return (0); 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate /* 358*7c478bd9Sstevel@tonic-gate * v6words now contains the bytes we could translate 359*7c478bd9Sstevel@tonic-gate * dbl_col points to the word (should be 0) where 360*7c478bd9Sstevel@tonic-gate * a double colon was found 361*7c478bd9Sstevel@tonic-gate */ 362*7c478bd9Sstevel@tonic-gate if (i == 7) { 363*7c478bd9Sstevel@tonic-gate v6outp->v6addr_u = v6buf.v6addr_u; 364*7c478bd9Sstevel@tonic-gate } else { 365*7c478bd9Sstevel@tonic-gate int rem; 366*7c478bd9Sstevel@tonic-gate int word; 367*7c478bd9Sstevel@tonic-gate int next; 368*7c478bd9Sstevel@tonic-gate if (dbl_col == NULL) { 369*7c478bd9Sstevel@tonic-gate return (0); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate bzero(&v6outp->v6addr_u, sizeof (in6_addr_t)); 372*7c478bd9Sstevel@tonic-gate rem = dbl_col - &v6buf.v6words_u[0]; 373*7c478bd9Sstevel@tonic-gate for (next = 0; next < rem; next++) { 374*7c478bd9Sstevel@tonic-gate v6outp->v6words_u[next] = v6buf.v6words_u[next]; 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate next++; /* skip dbl_col 0 */ 377*7c478bd9Sstevel@tonic-gate rem = i - rem; 378*7c478bd9Sstevel@tonic-gate word = 8 - rem; 379*7c478bd9Sstevel@tonic-gate while (rem > 0) { 380*7c478bd9Sstevel@tonic-gate v6outp->v6words_u[word] = v6buf.v6words_u[next]; 381*7c478bd9Sstevel@tonic-gate word++; 382*7c478bd9Sstevel@tonic-gate rem--; 383*7c478bd9Sstevel@tonic-gate next++; 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate return (1); /* Success */ 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate } /* switch */ 389*7c478bd9Sstevel@tonic-gate return (-1); /* return -1 for default case */ 390*7c478bd9Sstevel@tonic-gate } 391