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
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.
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]
24 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
29 #include <sys/types.h>
30 #include <sys/cmn_err.h>
31 #include <sys/systm.h>
32 #include <sys/socket.h>
33 #include <sys/sunddi.h>
34 #include <netinet/in.h>
37 static void convert2ascii(char *, const in6_addr_t
*);
38 static char *strchr_w(const char *, int);
39 static int str2inet_addr(char *, ipaddr_t
*);
42 * inet_ntop -- Convert an IPv4 or IPv6 address in binary form into
43 * printable form, and return a pointer to that string. Caller should
44 * provide a buffer of correct length to store string into.
45 * Note: this routine is kernel version of inet_ntop. It has similar
46 * format as inet_ntop() defined in rfc2553. But it does not do
47 * error handling operations exactly as rfc2553 defines. This function
48 * is used by kernel inet directory routines only for debugging.
49 * This inet_ntop() function, does not return NULL if third argument
50 * is NULL. The reason is simple that we don't want kernel to panic
51 * as the output of this function is directly fed to ip<n>dbg macro.
52 * Instead it uses a local buffer for destination address for
53 * those calls which purposely pass NULL ptr for the destination
54 * buffer. This function is thread-safe when the caller passes a non-
55 * null buffer with the third argument.
59 inet_ntop(int af
, const void *addr
, char *buf
, int addrlen
)
61 static char local_buf
[INET6_ADDRSTRLEN
];
62 static char *err_buf1
= "<badaddr>";
63 static char *err_buf2
= "<badfamily>";
69 * We don't allow thread unsafe inet_ntop calls, they
70 * must pass a non-null buffer pointer. For DEBUG mode
71 * we use the ASSERT() and for non-debug kernel it will
72 * silently allow it for now. Someday we should remove
73 * the static buffer from this function.
81 /* Let user know politely not to send NULL or unaligned addr */
82 if (addr
== NULL
|| !(OK_32PTR(addr
))) {
84 cmn_err(CE_WARN
, "inet_ntop: addr is <null> or unaligned");
90 #define UC(b) (((int)b) & 0xff)
93 ASSERT(addrlen
>= INET_ADDRSTRLEN
);
94 v4addr
= (uchar_t
*)addr
;
95 (void) sprintf(buf
, "%03d.%03d.%03d.%03d",
96 UC(v4addr
[0]), UC(v4addr
[1]), UC(v4addr
[2]), UC(v4addr
[3]));
100 ASSERT(addrlen
>= INET6_ADDRSTRLEN
);
101 v6addr
= (in6_addr_t
*)addr
;
102 if (IN6_IS_ADDR_V4MAPPED(v6addr
)) {
103 caddr
= (char *)addr
;
104 (void) sprintf(buf
, "::ffff:%d.%d.%d.%d",
105 UC(caddr
[12]), UC(caddr
[13]),
106 UC(caddr
[14]), UC(caddr
[15]));
107 } else if (IN6_IS_ADDR_V4COMPAT(v6addr
)) {
108 caddr
= (char *)addr
;
109 (void) sprintf(buf
, "::%d.%d.%d.%d",
110 UC(caddr
[12]), UC(caddr
[13]), UC(caddr
[14]),
112 } else if (IN6_IS_ADDR_UNSPECIFIED(v6addr
)) {
113 (void) sprintf(buf
, "::");
115 convert2ascii(buf
, v6addr
);
127 * v6 formats supported
128 * General format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
129 * The short hand notation :: is used for COMPAT addr
130 * Other forms : fe80::xxxx:xxxx:xxxx:xxxx
133 convert2ascii(char *buf
, const in6_addr_t
*addr
)
138 /* tempbuf must be big enough to hold ffff:\0 */
141 uint16_t *addr_component
;
143 boolean_t first
= B_FALSE
;
144 boolean_t med_zero
= B_FALSE
;
145 boolean_t end_zero
= B_FALSE
;
147 addr_component
= (uint16_t *)addr
;
150 /* First count if trailing zeroes higher in number */
151 for (hexdigits
= 0; hexdigits
< 8; hexdigits
++) {
152 if (*addr_component
== 0) {
160 addr_component
= (uint16_t *)addr
;
161 if (tail_zero
> head_zero
&& (head_zero
+ tail_zero
) != 7)
164 for (hexdigits
= 0; hexdigits
< 8; hexdigits
++) {
166 /* if entry is a 0 */
168 if (*addr_component
== 0) {
169 if (!first
&& *(addr_component
+ 1) == 0) {
170 if (end_zero
&& (hexdigits
< 4)) {
175 * address starts with 0s ..
176 * stick in leading ':' of pair
185 } else if (first
&& med_zero
) {
201 (void) sprintf(tempbuf
, "%x:", ntohs(*addr_component
) & 0xffff);
202 len
= strlen(tempbuf
);
203 bcopy(tempbuf
, ptr
, len
);
211 * search for char c, terminate on trailing white space
214 strchr_w(const char *sp
, int c
)
216 /* skip leading white space */
217 while (*sp
&& (*sp
== ' ' || *sp
== '\t')) {
224 if (*sp
== ' ' || *sp
== '\t')
231 str2inet_addr(char *cp
, ipaddr_t
*addrp
)
238 for (i
= 0; i
< 4; i
++) {
239 if (ddi_strtol(cp
, &end
, 10, &byte
) != 0 || byte
< 0 ||
243 addr
= (addr
<< 8) | (uint8_t)byte
;
259 * inet_pton: This function takes string format IPv4 or IPv6 address and
260 * converts it to binary form. The format of this function corresponds to
261 * inet_pton() in the socket library.
264 * 0 invalid IPv4 or IPv6 address
265 * 1 successful conversion
266 * -1 af is not AF_INET or AF_INET6
269 __inet_pton(int af
, char *inp
, void *outp
, int compat
)
277 if (str2inet_addr(inp
, (ipaddr_t
*)outp
) != 0) {
279 *(uint32_t *)outp
= htonl(*(uint32_t *)outp
);
286 uint16_t v6words_u
[8];
289 uint16_t *dbl_col
= NULL
;
290 char lastbyte
= NULL
;
292 v6outp
= (union v6buf_u
*)outp
;
294 if (strchr_w(inp
, '.') != NULL
) {
297 /* v4 mapped or v4 compatable */
298 if (strncmp(inp
, "::ffff:", 7) == 0) {
299 ipaddr_t ipv4_all_zeroes
= 0;
300 /* mapped - first init prefix and then fill */
301 IN6_IPADDR_TO_V4MAPPED(ipv4_all_zeroes
,
303 ret
= str2inet_addr(inp
+ 7,
304 &(v6outp
->v6addr_u
.s6_addr32
[3]));
305 } else if (strncmp(inp
, "::", 2) == 0) {
306 /* v4 compatable - prefix all zeroes */
307 bzero(&v6outp
->v6addr_u
, sizeof (in6_addr_t
));
308 ret
= str2inet_addr(inp
+ 2,
309 &(v6outp
->v6addr_u
.s6_addr32
[3]));
311 if (ret
> 0 && !compat
) {
312 v6outp
->v6addr_u
.s6_addr32
[3] =
313 htonl(v6outp
->v6addr_u
.s6_addr32
[3]);
317 for (i
= 0; i
< 8; i
++) {
320 * if ddi_strtol() fails it could be because
321 * the string is "::". That is valid and
322 * checked for below so just set the value to
325 if ((error
= ddi_strtol(inp
, &end
, 16, &byte
)) != 0) {
330 if (byte
< 0 || byte
> 0x0ffff) {
334 v6buf
.v6words_u
[i
] = (uint16_t)byte
;
336 v6buf
.v6words_u
[i
] = htons((uint16_t)byte
);
338 if (*end
== NULL
|| i
== 7) {
342 if (inp
== end
) { /* not a number must be */
344 ((i
== 0 && *(inp
+ 1) == ':') ||
351 dbl_col
= &v6buf
.v6words_u
[i
];
354 } else if (*inp
== NULL
|| *inp
== ' ' ||
367 if (*inp
== NULL
|| *inp
== ' ' || *inp
== '\t') {
372 if (*inp
!= NULL
&& *inp
!= ' ' && *inp
!= '\t') {
376 * v6words now contains the bytes we could translate
377 * dbl_col points to the word (should be 0) where
378 * a double colon was found
381 v6outp
->v6addr_u
= v6buf
.v6addr_u
;
386 if (dbl_col
== NULL
) {
389 bzero(&v6outp
->v6addr_u
, sizeof (in6_addr_t
));
390 rem
= dbl_col
- &v6buf
.v6words_u
[0];
391 for (next
= 0; next
< rem
; next
++) {
392 v6outp
->v6words_u
[next
] = v6buf
.v6words_u
[next
];
394 next
++; /* skip dbl_col 0 */
398 v6outp
->v6words_u
[word
] = v6buf
.v6words_u
[next
];
404 return (1); /* Success */
407 return (-1); /* return -1 for default case */
411 * Provide fixed inet_pton() implementation.
414 _inet_pton(int af
, char *inp
, void *outp
)
416 return (__inet_pton(af
, inp
, outp
, 0));
420 * Provide broken inet_pton() implementation by default for binary
424 inet_pton(int af
, char *inp
, void *outp
)
426 return (__inet_pton(af
, inp
, outp
, 1));