Merge pull request #23616 from keszybz/in-addr-to-string-formatting

Add macros that allocate a fixed buffer for in_addr_to_string(), in_addr_prefix+to_string()
This commit is contained in:
Yu Watanabe
2022-06-09 15:21:57 +09:00
committed by GitHub
45 changed files with 323 additions and 444 deletions
+15 -25
View File
@@ -14,6 +14,7 @@
#include "macro.h"
#include "parse-util.h"
#include "random-util.h"
#include "stdio-util.h"
#include "string-util.h"
#include "strxcpyx.h"
#include "util.h"
@@ -444,44 +445,33 @@ int in_addr_to_string(int family, const union in_addr_union *u, char **ret) {
return -ENOMEM;
errno = 0;
if (!inet_ntop(family, u, x, l))
if (!typesafe_inet_ntop(family, u, x, l))
return errno_or_else(EINVAL);
*ret = TAKE_PTR(x);
return 0;
}
int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret) {
_cleanup_free_ char *x = NULL;
char *p;
size_t l;
int in_addr_prefix_to_string(
int family,
const union in_addr_union *u,
unsigned prefixlen,
char *buf,
size_t buf_len) {
assert(u);
assert(ret);
assert(buf);
if (family == AF_INET)
l = INET_ADDRSTRLEN + 3;
else if (family == AF_INET6)
l = INET6_ADDRSTRLEN + 4;
else
if (!IN_SET(family, AF_INET, AF_INET6))
return -EAFNOSUPPORT;
if (prefixlen > FAMILY_ADDRESS_SIZE(family) * 8)
return -EINVAL;
x = new(char, l);
if (!x)
return -ENOMEM;
errno = 0;
if (!inet_ntop(family, u, x, l))
return errno_or_else(EINVAL);
if (!typesafe_inet_ntop(family, u, buf, buf_len))
return errno_or_else(ENOSPC);
p = x + strlen(x);
l -= strlen(x);
(void) strpcpyf(&p, l, "/%u", prefixlen);
*ret = TAKE_PTR(x);
size_t l = strlen(buf);
if (!snprintf_ok(buf + l, buf_len - l, "/%u", prefixlen))
return -ENOSPC;
return 0;
}
+52 -3
View File
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stddef.h>
#include <sys/socket.h>
@@ -68,14 +69,62 @@ int in_addr_prefix_range(
unsigned prefixlen,
union in_addr_union *ret_start,
union in_addr_union *ret_end);
int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
static inline int in6_addr_to_string(const struct in6_addr *u, char **ret) {
return in_addr_to_string(AF_INET6, (const union in_addr_union*) u, ret);
}
int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret);
static inline int in6_addr_prefix_to_string(const struct in6_addr *u, unsigned prefixlen, char **ret) {
return in_addr_prefix_to_string(AF_INET6, (const union in_addr_union*) u, prefixlen, ret);
static inline const char* typesafe_inet_ntop(int family, const union in_addr_union *a, char *buf, size_t len) {
return inet_ntop(family, a, buf, len);
}
static inline const char* typesafe_inet_ntop4(const struct in_addr *a, char *buf, size_t len) {
return inet_ntop(AF_INET, a, buf, len);
}
static inline const char* typesafe_inet_ntop6(const struct in6_addr *a, char *buf, size_t len) {
return inet_ntop(AF_INET6, a, buf, len);
}
/* Note: the lifetime of the compound literal is the immediately surrounding block,
* see C11 §6.5.2.5, and
* https://stackoverflow.com/questions/34880638/compound-literal-lifetime-and-if-blocks */
#define IN_ADDR_MAX CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)
#define IN_ADDR_TO_STRING(family, addr) typesafe_inet_ntop(family, addr, (char[IN_ADDR_MAX]){}, IN_ADDR_MAX)
#define IN4_ADDR_TO_STRING(addr) typesafe_inet_ntop4(addr, (char[INET_ADDRSTRLEN]){}, INET_ADDRSTRLEN)
#define IN6_ADDR_TO_STRING(addr) typesafe_inet_ntop6(addr, (char[INET6_ADDRSTRLEN]){}, INET6_ADDRSTRLEN)
int in_addr_prefix_to_string(
int family,
const union in_addr_union *u,
unsigned prefixlen,
char *buf,
size_t buf_len);
static inline const char* _in_addr_prefix_to_string(
int family,
const union in_addr_union *u,
unsigned prefixlen,
char *buf,
size_t buf_len) {
/* We assume that this is called with an appropriately sized buffer and can never fail. */
assert_se(in_addr_prefix_to_string(family, u, prefixlen, buf, buf_len) == 0);
return buf;
}
static inline const char* _in4_addr_prefix_to_string(const struct in_addr *a, unsigned prefixlen, char *buf, size_t buf_len) {
return _in_addr_prefix_to_string(AF_INET, (const union in_addr_union *) a, prefixlen, buf, buf_len);
}
static inline const char* _in6_addr_prefix_to_string(const struct in6_addr *a, unsigned prefixlen, char *buf, size_t buf_len) {
return _in_addr_prefix_to_string(AF_INET6, (const union in_addr_union *) a, prefixlen, buf, buf_len);
}
#define PREFIX_SUFFIX_MAX (1 + DECIMAL_STR_MAX(unsigned))
#define IN_ADDR_PREFIX_TO_STRING(family, addr, prefixlen) \
_in_addr_prefix_to_string(family, addr, prefixlen, (char[IN_ADDR_MAX + PREFIX_SUFFIX_MAX]){}, IN_ADDR_MAX + PREFIX_SUFFIX_MAX)
#define IN4_ADDR_PREFIX_TO_STRING(addr, prefixlen) \
_in4_addr_prefix_to_string(addr, prefixlen, (char[INET_ADDRSTRLEN + PREFIX_SUFFIX_MAX]){}, INET_ADDRSTRLEN + PREFIX_SUFFIX_MAX)
#define IN6_ADDR_PREFIX_TO_STRING(addr, prefixlen) \
_in6_addr_prefix_to_string(addr, prefixlen, (char[INET6_ADDRSTRLEN + PREFIX_SUFFIX_MAX]){}, INET6_ADDRSTRLEN + PREFIX_SUFFIX_MAX)
int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret);
static inline int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
return in_addr_port_ifindex_name_to_string(family, u, 0, ifindex, NULL, ret);
+1 -3
View File
@@ -490,9 +490,7 @@ int sockaddr_pretty(
if (r < 0)
return -ENOMEM;
} else {
char a[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &sa->in6.sin6_addr, a, sizeof(a));
const char *a = IN6_ADDR_TO_STRING(&sa->in6.sin6_addr);
if (include_port) {
if (asprintf(&p,