1/*
2 * Copyright (c) 1996 by Internet Software Consortium.
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15 * SOFTWARE.
16 */
17
18#if defined(LIBC_SCCS) && !defined(lint)
19static const char orig_rcsid[] = "From Id: inet_net_ntop.c,v 8.2 1996/08/08 06:54:44 vixie Exp";
20static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.1.1.1 2003/11/19 01:51:29 kyu3 Exp $";
21#endif
22
23#include <sys/types.h>
24#include <sys/socket.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27
28#include <errno.h>
29#include <stdio.h>
30#include <string.h>
31#include <stdlib.h>
32
33#ifdef SPRINTF_CHAR
34# define SPRINTF(x) strlen(sprintf/**/x)
35#else
36# define SPRINTF(x) ((size_t)sprintf x)
37#endif
38
39static char *	inet_net_ntop_ipv4 (const u_char *src, int bits,
40					char *dst, size_t size);
41
42/*
43 * char *
44 * inet_net_ntop(af, src, bits, dst, size)
45 *	convert network number from network to presentation format.
46 *	generates CIDR style result always.
47 * return:
48 *	pointer to dst, or NULL if an error occurred (check errno).
49 * author:
50 *	Paul Vixie (ISC), July 1996
51 */
52char *
53inet_net_ntop(
54	int af,
55	const void *src,
56	int bits,
57	char *dst,
58	size_t size
59	)
60{
61	switch (af) {
62	case AF_INET:
63		return (inet_net_ntop_ipv4(src, bits, dst, size));
64	default:
65		errno = EAFNOSUPPORT;
66		return (NULL);
67	}
68}
69
70/*
71 * static char *
72 * inet_net_ntop_ipv4(src, bits, dst, size)
73 *	convert IPv4 network number from network to presentation format.
74 *	generates CIDR style result always.
75 * return:
76 *	pointer to dst, or NULL if an error occurred (check errno).
77 * note:
78 *	network byte order assumed.  this means 192.5.5.240/28 has
79 *	0x11110000 in its fourth octet.
80 * author:
81 *	Paul Vixie (ISC), July 1996
82 */
83static char *
84inet_net_ntop_ipv4(
85	const u_char *src,
86	int bits,
87	char *dst,
88	size_t size
89	)
90{
91	char *odst = dst;
92	char *t;
93	u_int m;
94	int b;
95
96	if (bits < 0 || bits > 32) {
97		errno = EINVAL;
98		return (NULL);
99	}
100	if (bits == 0) {
101		if (size < sizeof "0")
102			goto emsgsize;
103		*dst++ = '0';
104		*dst = '\0';
105	}
106
107	/* Format whole octets. */
108	for (b = bits / 8; b > 0; b--) {
109		if (size < sizeof "255.")
110			goto emsgsize;
111		t = dst;
112		dst += SPRINTF((dst, "%u", *src++));
113		if (b > 1) {
114			*dst++ = '.';
115			*dst = '\0';
116		}
117		size -= (size_t)(dst - t);
118	}
119
120	/* Format partial octet. */
121	b = bits % 8;
122	if (b > 0) {
123		if (size < sizeof ".255")
124			goto emsgsize;
125		t = dst;
126		if (dst != odst)
127			*dst++ = '.';
128		m = ((1 << b) - 1) << (8 - b);
129		dst += SPRINTF((dst, "%u", ((unsigned int)(*src & m))));
130		size -= (size_t)(dst - t);
131	}
132
133	/* Format CIDR /width. */
134	if (size < sizeof "/32")
135		goto emsgsize;
136	dst += SPRINTF((dst, "/%u", bits));
137	return (odst);
138
139 emsgsize:
140	errno = EMSGSIZE;
141	return (NULL);
142}
143