]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/network-internal.c
e7c22c9b76e051f743c63e2c3a9169dff07626bf
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "alloc-util.h"
7 #include "dhcp-lease-internal.h"
8 #include "dns-resolver-internal.h"
9 #include "extract-word.h"
10 #include "hexdecoct.h"
11 #include "in-addr-util.h"
12 #include "network-internal.h"
13 #include "parse-util.h"
14 #include "string-util.h"
17 size_t serialize_in_addrs(FILE *f
,
18 const struct in_addr
*addresses
,
20 bool *with_leading_space
,
21 bool (*predicate
)(const struct in_addr
*addr
)) {
27 if (!with_leading_space
)
28 with_leading_space
= &_space
;
30 for (size_t i
= 0; i
< size
; i
++) {
31 if (predicate
&& !predicate(&addresses
[i
]))
34 if (*with_leading_space
)
36 fputs(IN4_ADDR_TO_STRING(&addresses
[i
]), f
);
38 *with_leading_space
= true;
44 int deserialize_in_addrs(struct in_addr
**ret
, const char *string
) {
45 _cleanup_free_
struct in_addr
*addresses
= NULL
;
52 _cleanup_free_
char *word
= NULL
;
53 union in_addr_union a
;
56 r
= extract_first_word(&string
, &word
, NULL
, 0);
62 if (in_addr_from_string(AF_INET
, word
, &a
) < 0)
65 if (!GREEDY_REALLOC(addresses
, size
+ 1))
68 addresses
[size
++] = a
.in
;
71 *ret
= size
> 0 ? TAKE_PTR(addresses
) : NULL
;
76 void serialize_in6_addrs(FILE *f
, const struct in6_addr
*addresses
, size_t size
, bool *with_leading_space
) {
82 if (!with_leading_space
)
83 with_leading_space
= &_space
;
85 for (size_t i
= 0; i
< size
; i
++) {
86 if (*with_leading_space
)
88 fputs(IN6_ADDR_TO_STRING(&addresses
[i
]), f
);
89 *with_leading_space
= true;
93 int deserialize_in6_addrs(struct in6_addr
**ret
, const char *string
) {
94 _cleanup_free_
struct in6_addr
*addresses
= NULL
;
101 _cleanup_free_
char *word
= NULL
;
102 union in_addr_union a
;
105 r
= extract_first_word(&string
, &word
, NULL
, 0);
111 if (in_addr_from_string(AF_INET6
, word
, &a
) < 0)
114 if (!GREEDY_REALLOC(addresses
, size
+ 1))
117 addresses
[size
++] = a
.in6
;
120 *ret
= TAKE_PTR(addresses
);
125 int serialize_dnr(FILE *f
, const sd_dns_resolver
*dnr
, size_t n_dnr
, bool *with_leading_space
) {
129 if (!with_leading_space
)
130 with_leading_space
= &_space
;
133 _cleanup_strv_free_
char **names
= NULL
;
134 r
= dns_resolvers_to_dot_strv(dnr
, n_dnr
, &names
);
138 fputstrv(f
, names
, NULL
, with_leading_space
);
143 static int coalesce_dnr(sd_dns_resolver
*dnr
, size_t n_dnr
, int family
, const char *auth_name
,
144 union in_addr_union
*addr
) {
145 assert(dnr
|| n_dnr
== 0);
149 /* Look through list of DNR for matching resolvers to add our addr to. Since DoT is assumed, no need
150 * to compare transports/dohpath/etc. */
151 FOREACH_ARRAY(res
, dnr
, n_dnr
) {
152 if (family
== res
->family
&& streq(auth_name
, res
->auth_name
)) {
153 if (!GREEDY_REALLOC(res
->addrs
, res
->n_addrs
+ 1))
155 res
->addrs
[res
->n_addrs
++] = *addr
;
163 /* Deserialized resolvers are assumed to offer DoT service. */
164 int deserialize_dnr(sd_dns_resolver
**ret
, const char *string
) {
170 sd_dns_resolver
*dnr
= NULL
;
172 CLEANUP_ARRAY(dnr
, n
, dns_resolver_done_many
);
176 _cleanup_free_
char *word
= NULL
;
178 r
= extract_first_word(&string
, &word
, NULL
, 0);
186 _cleanup_free_
union in_addr_union
*addr
= new(union in_addr_union
, 1);
187 _cleanup_free_
char *auth_name
= NULL
;
189 r
= in_addr_port_ifindex_name_from_string_auto(word
, &family
, addr
, &port
, NULL
, &auth_name
);
193 r
= coalesce_dnr(dnr
, n
, family
, auth_name
, addr
);
199 if (!GREEDY_REALLOC(dnr
, n
+1))
203 dnr
[n
++] = (sd_dns_resolver
) {
204 .priority
= priority
, /* not serialized, but this will preserve the order */
205 .auth_name
= TAKE_PTR(auth_name
),
207 .addrs
= TAKE_PTR(addr
),
209 .transports
= SD_DNS_ALPN_DOT
,
214 *ret
= TAKE_PTR(dnr
);
218 void serialize_dhcp_routes(FILE *f
, const char *key
, sd_dhcp_route
**routes
, size_t size
) {
224 fprintf(f
, "%s=", key
);
226 for (size_t i
= 0; i
< size
; i
++) {
227 struct in_addr dest
, gw
;
230 assert_se(sd_dhcp_route_get_destination(routes
[i
], &dest
) >= 0);
231 assert_se(sd_dhcp_route_get_gateway(routes
[i
], &gw
) >= 0);
232 assert_se(sd_dhcp_route_get_destination_prefix_length(routes
[i
], &length
) >= 0);
234 fprintf(f
, "%s,%s%s",
235 IN4_ADDR_PREFIX_TO_STRING(&dest
, length
),
236 IN4_ADDR_TO_STRING(&gw
),
237 i
< size
- 1 ? " ": "");
243 int deserialize_dhcp_routes(struct sd_dhcp_route
**ret
, size_t *ret_size
, const char *string
) {
244 _cleanup_free_
struct sd_dhcp_route
*routes
= NULL
;
251 /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */
253 _cleanup_free_
char *word
= NULL
;
258 r
= extract_first_word(&string
, &word
, NULL
, 0);
264 if (!GREEDY_REALLOC(routes
, size
+ 1))
270 tok_end
= strchr(tok
, '/');
275 r
= inet_aton(tok
, &routes
[size
].dst_addr
);
281 /* get the prefixlen */
282 tok_end
= strchr(tok
, ',');
288 r
= safe_atou(tok
, &n
);
292 routes
[size
].dst_prefixlen
= (uint8_t) n
;
295 /* get the gateway */
296 r
= inet_aton(tok
, &routes
[size
].gw_addr
);
304 *ret
= TAKE_PTR(routes
);
309 int serialize_dhcp_option(FILE *f
, const char *key
, const void *data
, size_t size
) {
310 _cleanup_free_
char *hex_buf
= NULL
;
316 hex_buf
= hexmem(data
, size
);
320 fprintf(f
, "%s=%s\n", key
, hex_buf
);