GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/net/inet_ntop.c Lines: 57 79 72.2 %
Date: 2017-11-07 Branches: 45 75 60.0 %

Line Branch Exec Source
1
/*	$OpenBSD: inet_ntop.c,v 1.13 2016/09/21 04:38:56 guenther Exp $	*/
2
3
/* Copyright (c) 1996 by Internet Software Consortium.
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
10
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
11
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
12
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16
 * SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/socket.h>
21
#include <netinet/in.h>
22
#include <arpa/inet.h>
23
#include <arpa/nameser.h>
24
#include <string.h>
25
#include <errno.h>
26
#include <stdio.h>
27
28
/*
29
 * WARNING: Don't even consider trying to compile this on a system where
30
 * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
31
 */
32
33
static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
34
static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
35
36
/* const char *
37
 * inet_ntop(af, src, dst, size)
38
 *	convert a network format address to presentation format.
39
 * return:
40
 *	pointer to presentation format address (`dst'), or NULL (see errno).
41
 * author:
42
 *	Paul Vixie, 1996.
43
 */
44
const char *
45
inet_ntop(int af, const void *src, char *dst, socklen_t size)
46
{
47
2146
	switch (af) {
48
	case AF_INET:
49
680
		return (inet_ntop4(src, dst, size));
50
	case AF_INET6:
51
393
		return (inet_ntop6(src, dst, size));
52
	default:
53
		errno = EAFNOSUPPORT;
54
		return (NULL);
55
	}
56
	/* NOTREACHED */
57
1073
}
58
DEF_WEAK(inet_ntop);
59
60
/* const char *
61
 * inet_ntop4(src, dst, size)
62
 *	format an IPv4 address, more or less like inet_ntoa()
63
 * return:
64
 *	`dst' (as a const)
65
 * notes:
66
 *	(1) uses no statics
67
 *	(2) takes a u_char* not an in_addr as input
68
 * author:
69
 *	Paul Vixie, 1996.
70
 */
71
static const char *
72
inet_ntop4(const u_char *src, char *dst, size_t size)
73
{
74
1360
	char tmp[sizeof "255.255.255.255"];
75
	int l;
76
77
1360
	l = snprintf(tmp, sizeof(tmp), "%u.%u.%u.%u",
78
680
	    src[0], src[1], src[2], src[3]);
79

1360
	if (l <= 0 || l >= size) {
80
		errno = ENOSPC;
81
		return (NULL);
82
	}
83
680
	strlcpy(dst, tmp, size);
84
680
	return (dst);
85
680
}
86
87
/* const char *
88
 * inet_ntop6(src, dst, size)
89
 *	convert IPv6 binary address into presentation (printable) format
90
 * author:
91
 *	Paul Vixie, 1996.
92
 */
93
static const char *
94
inet_ntop6(const u_char *src, char *dst, size_t size)
95
{
96
	/*
97
	 * Note that int32_t and int16_t need only be "at least" large enough
98
	 * to contain a value of the specified size.  On some systems, like
99
	 * Crays, there is no such thing as an integer variable with 16 bits.
100
	 * Keep this in mind if you think this function should have been coded
101
	 * to use pointer overlays.  All the world's not a VAX.
102
	 */
103
786
	char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
104
	char *tp, *ep;
105
	struct { int base, len; } best, cur;
106
393
	u_int words[IN6ADDRSZ / INT16SZ];
107
	int i;
108
	int advance;
109
110
	/*
111
	 * Preprocess:
112
	 *	Copy the input (bytewise) array into a wordwise array.
113
	 *	Find the longest run of 0x00's in src[] for :: shorthanding.
114
	 */
115
393
	memset(words, '\0', sizeof words);
116
13362
	for (i = 0; i < IN6ADDRSZ; i++)
117
6288
		words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
118
	best.base = -1;
119
	cur.base = -1;
120
7074
	for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
121
3144
		if (words[i] == 0) {
122
2689
			if (cur.base == -1)
123
393
				cur.base = i, cur.len = 1;
124
			else
125
2296
				cur.len++;
126
		} else {
127
455
			if (cur.base != -1) {
128

214
				if (best.base == -1 || cur.len > best.len)
129
214
					best = cur;
130
				cur.base = -1;
131
214
			}
132
		}
133
	}
134
393
	if (cur.base != -1) {
135

179
		if (best.base == -1 || cur.len > best.len)
136
179
			best = cur;
137
	}
138

786
	if (best.base != -1 && best.len < 2)
139
		best.base = -1;
140
141
	/*
142
	 * Format the result.
143
	 */
144
393
	tp = tmp;
145
393
	ep = tmp + sizeof(tmp);
146

10218
	for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
147
		/* Are we inside the best run of 0x00's? */
148

9263
		if (best.base != -1 && i >= best.base &&
149
2975
		    i < (best.base + best.len)) {
150
2689
			if (i == best.base) {
151
393
				if (tp + 1 >= ep) {
152
					errno = ENOSPC;
153
					return (NULL);
154
				}
155
393
				*tp++ = ':';
156
393
			}
157
			continue;
158
		}
159
		/* Are we following an initial run of 0x00s or any real hex? */
160
455
		if (i != 0) {
161
304
			if (tp + 1 >= ep) {
162
				errno = ENOSPC;
163
				return (NULL);
164
			}
165
304
			*tp++ = ':';
166
304
		}
167
		/* Is this address an encapsulated IPv4? */
168

479
		if (i == 6 && best.base == 0 &&
169
		    (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
170
			if (!inet_ntop4(src+12, tp, ep - tp))
171
				return (NULL);
172
			tp += strlen(tp);
173
			break;
174
		}
175
455
		advance = snprintf(tp, ep - tp, "%x", words[i]);
176

910
		if (advance <= 0 || advance >= ep - tp) {
177
			errno = ENOSPC;
178
			return (NULL);
179
		}
180
455
		tp += advance;
181
455
	}
182
	/* Was it a trailing run of 0x00's? */
183

786
	if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
184
179
		if (tp + 1 >= ep) {
185
			errno = ENOSPC;
186
			return (NULL);
187
		}
188
179
		*tp++ = ':';
189
179
	}
190
393
	if (tp + 1 >= ep) {
191
		errno = ENOSPC;
192
		return (NULL);
193
	}
194
393
	*tp++ = '\0';
195
196
	/*
197
	 * Check for overflow, copy, and we're done.
198
	 */
199
393
	if ((size_t)(tp - tmp) > size) {
200
		errno = ENOSPC;
201
		return (NULL);
202
	}
203
393
	strlcpy(dst, tmp, size);
204
393
	return (dst);
205
393
}