Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/inet/inet_net_ntop.c
104197 views
1
/* $OpenBSD: inet_net_ntop.c,v 1.9 2019/07/03 03:24:04 deraadt Exp $ */
2
3
/*
4
* Copyright (c) 2012 by Gilles Chehade <[email protected]>
5
* Copyright (c) 1996 by Internet Software Consortium.
6
*
7
* SPDX-License-Identifier: ISC
8
*
9
* Permission to use, copy, modify, and distribute this software for any
10
* purpose with or without fee is hereby granted, provided that the above
11
* copyright notice and this permission notice appear in all copies.
12
*
13
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
14
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
16
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
17
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
18
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20
* SOFTWARE.
21
*/
22
23
#include "port_before.h"
24
25
#include <sys/types.h>
26
#include <sys/socket.h>
27
#include <netinet/in.h>
28
#include <arpa/inet.h>
29
30
#include <errno.h>
31
#include <stdio.h>
32
#include <string.h>
33
#include <stdlib.h>
34
35
#include "port_after.h"
36
37
static char *inet_net_ntop_ipv4(const u_char *, int, char *, size_t);
38
static char *inet_net_ntop_ipv6(const u_char *, int, char *, size_t);
39
40
/*
41
* char *
42
* inet_net_ntop(af, src, bits, dst, size)
43
* convert network number from network to presentation format.
44
* generates CIDR style result always.
45
* return:
46
* pointer to dst, or NULL if an error occurred (check errno).
47
* author:
48
* Paul Vixie (ISC), July 1996
49
*/
50
char *
51
inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
52
{
53
switch (af) {
54
case AF_INET:
55
return (inet_net_ntop_ipv4(src, bits, dst, size));
56
case AF_INET6:
57
return (inet_net_ntop_ipv6(src, bits, dst, size));
58
default:
59
errno = EAFNOSUPPORT;
60
return (NULL);
61
}
62
}
63
64
/*
65
* static char *
66
* inet_net_ntop_ipv4(src, bits, dst, size)
67
* convert IPv4 network number from network to presentation format.
68
* generates CIDR style result always.
69
* return:
70
* pointer to dst, or NULL if an error occurred (check errno).
71
* note:
72
* network byte order assumed. this means 192.5.5.240/28 has
73
* 0b11110000 in its fourth octet.
74
* author:
75
* Paul Vixie (ISC), July 1996
76
*/
77
static char *
78
inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size)
79
{
80
char *odst = dst;
81
u_int m;
82
int b;
83
char *ep;
84
int advance;
85
86
ep = dst + size;
87
if (ep <= dst)
88
goto emsgsize;
89
90
if (bits < 0 || bits > 32) {
91
errno = EINVAL;
92
return (NULL);
93
}
94
if (bits == 0) {
95
if (ep - dst < sizeof "0")
96
goto emsgsize;
97
*dst++ = '0';
98
*dst = '\0';
99
}
100
101
/* Format whole octets. */
102
for (b = bits / 8; b > 0; b--) {
103
if (ep - dst < sizeof "255.")
104
goto emsgsize;
105
advance = snprintf(dst, ep - dst, "%u", *src++);
106
if (advance <= 0 || advance >= ep - dst)
107
goto emsgsize;
108
dst += advance;
109
if (b > 1) {
110
if (dst + 1 >= ep)
111
goto emsgsize;
112
*dst++ = '.';
113
*dst = '\0';
114
}
115
}
116
117
/* Format partial octet. */
118
b = bits % 8;
119
if (b > 0) {
120
if (ep - dst < sizeof ".255")
121
goto emsgsize;
122
if (dst != odst)
123
*dst++ = '.';
124
m = ((1 << b) - 1) << (8 - b);
125
advance = snprintf(dst, ep - dst, "%u", *src & m);
126
if (advance <= 0 || advance >= ep - dst)
127
goto emsgsize;
128
dst += advance;
129
}
130
131
/* Format CIDR /width. */
132
if (ep - dst < sizeof "/32")
133
goto emsgsize;
134
advance = snprintf(dst, ep - dst, "/%u", bits);
135
if (advance <= 0 || advance >= ep - dst)
136
goto emsgsize;
137
dst += advance;
138
return (odst);
139
140
emsgsize:
141
errno = EMSGSIZE;
142
return (NULL);
143
}
144
145
static char *
146
inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size)
147
{
148
int ret;
149
char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255:255:255:255/128")];
150
151
if (bits < 0 || bits > 128) {
152
errno = EINVAL;
153
return (NULL);
154
}
155
156
if (inet_ntop(AF_INET6, src, buf, size) == NULL)
157
return (NULL);
158
159
ret = snprintf(dst, size, "%s/%d", buf, bits);
160
if (ret < 0 || ret >= size) {
161
errno = EMSGSIZE;
162
return (NULL);
163
}
164
165
return (dst);
166
}
167
168
/*
169
* Weak aliases for applications that use certain private entry points,
170
* and fail to include <arpa/inet.h>.
171
*/
172
#undef inet_net_ntop
173
__weak_reference(__inet_net_ntop, inet_net_ntop);
174
175