inet_ntop.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
static void convert2ascii(char *, const in6_addr_t *);
static char *strchr_w(const char *, int);
static int str2inet_addr(char *, ipaddr_t *);
/*
* inet_ntop -- Convert an IPv4 or IPv6 address in binary form into
* printable form, and return a pointer to that string. Caller should
* provide a buffer of correct length to store string into.
* Note: this routine is kernel version of inet_ntop. It has similar
* format as inet_ntop() defined in rfc2553. But it does not do
* error handling operations exactly as rfc2553 defines. This function
* is used by kernel inet directory routines only for debugging.
* This inet_ntop() function, does not return NULL if third argument
* is NULL. The reason is simple that we don't want kernel to panic
* as the output of this function is directly fed to ip<n>dbg macro.
* Instead it uses a local buffer for destination address for
* those calls which purposely pass NULL ptr for the destination
* buffer. This function is thread-safe when the caller passes a non-
* null buffer with the third argument.
*/
/* ARGSUSED */
char *
{
static char local_buf[INET6_ADDRSTRLEN];
static char *err_buf1 = "<badaddr>";
static char *err_buf2 = "<badfamily>";
char *caddr;
/*
* We don't allow thread unsafe inet_ntop calls, they
* must pass a non-null buffer pointer. For DEBUG mode
* we use the ASSERT() and for non-debug kernel it will
* silently allow it for now. Someday we should remove
* the static buffer from this function.
*/
buf[0] = '\0';
/* Let user know politely not to send NULL or unaligned addr */
#ifdef DEBUG
#endif
return (err_buf1);
}
#define UC(b) (((int)b) & 0xff)
switch (af) {
case AF_INET:
return (buf);
case AF_INET6:
if (IN6_IS_ADDR_V4MAPPED(v6addr)) {
} else if (IN6_IS_ADDR_V4COMPAT(v6addr)) {
} else if (IN6_IS_ADDR_UNSPECIFIED(v6addr)) {
} else {
}
return (buf);
default:
return (err_buf2);
}
}
/*
*
* v6 formats supported
* General format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
* The short hand notation :: is used for COMPAT addr
* Other forms : fe80::xxxx:xxxx:xxxx:xxxx
*/
static void
{
int hexdigits;
int head_zero = 0;
int tail_zero = 0;
/* tempbuf must be big enough to hold ffff:\0 */
char tempbuf[6];
char *ptr;
/* First count if trailing zeroes higher in number */
if (*addr_component == 0) {
if (hexdigits < 4)
head_zero++;
else
tail_zero++;
}
}
/* if entry is a 0 */
if (*addr_component == 0) {
*ptr++ = '0';
*ptr++ = ':';
} else {
/*
* address starts with 0s ..
* stick in leading ':' of pair
*/
if (hexdigits == 0)
*ptr++ = ':';
/* add another */
*ptr++ = ':';
}
if (hexdigits == 7)
*ptr++ = ':';
continue;
} else {
*ptr++ = '0';
*ptr++ = ':';
}
continue;
}
if (med_zero)
tempbuf[0] = '\0';
}
*--ptr = '\0';
}
/*
* search for char c, terminate on trailing white space
*/
static char *
{
/* skip leading white space */
sp++;
}
do {
if (*sp == (char)c)
return ((char *)sp);
return (NULL);
} while (*sp++);
return (NULL);
}
static int
{
char *end;
long byte;
int i;
for (i = 0; i < 4; i++) {
byte > 255) {
return (0);
}
if (i < 3) {
if (*end != '.') {
return (0);
} else {
}
} else {
}
}
return (1);
}
/*
* inet_pton: This function takes string format IPv4 or IPv6 address and
* converts it to binary form. The format of this function corresponds to
* inet_pton() in the socket library.
* It returns 0 for invalid IPv4 and IPv6 address
* 1 when successfully converts ascii to binary
* -1 when af is not AF_INET or AF_INET6
*/
int
{
int i;
long byte;
char *end;
switch (af) {
case AF_INET:
case AF_INET6: {
union v6buf_u {
/* v4 mapped or v4 compatable */
ipaddr_t ipv4_all_zeroes = 0;
/* mapped - first init prefix and then fill */
/* v4 compatable - prefix all zeroes */
}
return (0);
}
for (i = 0; i < 8; i++) {
int error;
/*
* if ddi_strtol() fails it could be because
* the string is "::". That is valid and
* checked for below so just set the value to
* 0 and continue.
*/
return (0);
byte = 0;
}
return (0);
}
break;
}
if (*inp == ':' &&
lastbyte == ':')) {
if (dbl_col) {
return (0);
}
if (byte != 0)
i++;
if (i == 0)
inp++;
*inp == '\t') {
break;
} else {
return (0);
}
} else {
}
if (*inp != ':') {
return (0);
}
inp++;
break;
}
}
return (0);
}
/*
* v6words now contains the bytes we could translate
* dbl_col points to the word (should be 0) where
* a double colon was found
*/
if (i == 7) {
} else {
int rem;
int word;
int next;
return (0);
}
}
next++; /* skip dbl_col 0 */
while (rem > 0) {
word++;
rem--;
next++;
}
}
return (1); /* Success */
}
} /* switch */
return (-1); /* return -1 for default case */
}