1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "netdev-util.h"
#include "networkd-address.h"
#include "networkd-link.h"
#include "string-table.h"
static const char * const netdev_local_address_type_table[_NETDEV_LOCAL_ADDRESS_TYPE_MAX] = {
[NETDEV_LOCAL_ADDRESS_IPV4LL] = "ipv4_link_local",
[NETDEV_LOCAL_ADDRESS_IPV6LL] = "ipv6_link_local",
[NETDEV_LOCAL_ADDRESS_DHCP4] = "dhcp4",
[NETDEV_LOCAL_ADDRESS_DHCP6] = "dhcp6",
[NETDEV_LOCAL_ADDRESS_SLAAC] = "slaac",
};
DEFINE_STRING_TABLE_LOOKUP(netdev_local_address_type, NetDevLocalAddressType);
int link_get_local_address(
Link *link,
NetDevLocalAddressType type,
int family,
int *ret_family,
union in_addr_union *ret_address) {
Address *a;
assert(link);
switch (type) {
case NETDEV_LOCAL_ADDRESS_IPV4LL:
assert(IN_SET(family, AF_UNSPEC, AF_INET));
family = AF_INET;
break;
case NETDEV_LOCAL_ADDRESS_IPV6LL:
assert(IN_SET(family, AF_UNSPEC, AF_INET6));
family = AF_INET6;
break;
case NETDEV_LOCAL_ADDRESS_DHCP4:
assert(IN_SET(family, AF_UNSPEC, AF_INET));
family = AF_INET;
break;
case NETDEV_LOCAL_ADDRESS_DHCP6:
assert(IN_SET(family, AF_UNSPEC, AF_INET6));
family = AF_INET6;
break;
case NETDEV_LOCAL_ADDRESS_SLAAC:
assert(IN_SET(family, AF_UNSPEC, AF_INET6));
family = AF_INET6;
break;
default:
assert_not_reached();
}
if (!link_is_ready_to_configure(link, /* allow_unmanaged = */ false))
return -EBUSY;
SET_FOREACH(a, link->addresses) {
if (!address_is_ready(a))
continue;
if (a->family != family)
continue;
if (in_addr_is_set(a->family, &a->in_addr_peer))
continue;
switch (type) {
case NETDEV_LOCAL_ADDRESS_IPV4LL:
if (a->source != NETWORK_CONFIG_SOURCE_IPV4LL)
continue;
break;
case NETDEV_LOCAL_ADDRESS_IPV6LL:
if (!in6_addr_is_link_local(&a->in_addr.in6))
continue;
break;
case NETDEV_LOCAL_ADDRESS_DHCP4:
if (a->source != NETWORK_CONFIG_SOURCE_DHCP4)
continue;
break;
case NETDEV_LOCAL_ADDRESS_DHCP6:
if (a->source != NETWORK_CONFIG_SOURCE_DHCP6)
continue;
break;
case NETDEV_LOCAL_ADDRESS_SLAAC:
if (a->source != NETWORK_CONFIG_SOURCE_NDISC)
continue;
break;
default:
assert_not_reached();
}
if (ret_family)
*ret_family = a->family;
if (ret_address)
*ret_address = a->in_addr;
return 1;
}
return -ENXIO;
}
|