1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2022 Felix Fietkau <nbd@nbd.name>
6 #include <sys/socket.h>
11 int network_get_endpoint(union network_endpoint
*dest
, const char *str
,
12 int default_port
, int idx
)
14 struct addrinfo hints
= {
15 .ai_flags
= AI_ADDRCONFIG
,
16 .ai_family
= AF_UNSPEC
,
18 char *buf
= strdup(str
);
19 char *host
= buf
, *port
;
20 struct addrinfo
*ai
, *ai_cur
;
24 memset(dest
, 0, sizeof(*dest
));
28 port
= strchr(host
, ']');
35 else if (*port
== ':')
39 hints
.ai_family
= AF_INET6
;
40 hints
.ai_flags
|= AI_NUMERICHOST
;
44 port
= strchr(host
, ':');
49 if (getaddrinfo(host
, port
, &hints
, &ai
) || !ai
)
54 for (n_res
= 0; ai_cur
; ai_cur
= ai_cur
->ai_next
, n_res
++)
62 if (ai_cur
->ai_addrlen
> sizeof(*dest
))
65 memcpy(dest
, ai_cur
->ai_addr
, ai_cur
->ai_addrlen
);
67 dest
->in
.sin_port
= htons(default_port
);
78 int network_get_subnet(int af
, union network_addr
*addr
, int *mask
, const char *str
)
80 char *buf
= strdup(str
);
89 sep
= strchr(buf
, '/');
95 val
= strtoul(sep
, &end
, 0);
96 if ((end
&& *end
) || val
> *mask
)
102 if (inet_pton(af
, buf
, addr
) == 1)
110 int network_get_local_addr(void *local
, const union network_endpoint
*target
)
112 union network_endpoint ep
= {};
117 memset(local
, 0, sizeof(union network_addr
));
118 if (target
->sa
.sa_family
== AF_INET6
)
119 len
= sizeof(ep
.in6
);
123 fd
= socket(target
->sa
.sa_family
, SOCK_DGRAM
, IPPROTO_UDP
);
127 if (connect(fd
, (const struct sockaddr
*)target
, len
))
131 if (getsockname(fd
, &ep
.sa
, &len
))
134 if (ep
.sa
.sa_family
== AF_INET6
)
135 memcpy(local
, &ep
.in6
.sin6_addr
, sizeof(ep
.in6
.sin6_addr
));
137 memcpy(local
, &ep
.in
.sin_addr
, sizeof(ep
.in
.sin_addr
));