1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include "alloc-util.h"
4 #include "ether-addr-util.h"
6 #include "networkd-dhcp-server-static-lease.h"
7 #include "networkd-network.h"
8 #include "networkd-util.h"
10 DEFINE_NETWORK_SECTION_FUNCTIONS(DHCPStaticLease
, dhcp_static_lease_free
);
12 DHCPStaticLease
*dhcp_static_lease_free(DHCPStaticLease
*static_lease
) {
16 if (static_lease
->network
&& static_lease
->section
)
17 hashmap_remove(static_lease
->network
->dhcp_static_leases_by_section
, static_lease
->section
);
19 network_config_section_free(static_lease
->section
);
20 free(static_lease
->client_id
);
21 return mfree(static_lease
);
24 static int dhcp_static_lease_new(DHCPStaticLease
**ret
) {
29 p
= new0(DHCPStaticLease
, 1);
37 static int lease_new_static(Network
*network
, const char *filename
, unsigned section_line
, DHCPStaticLease
**ret
) {
38 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
39 _cleanup_(dhcp_static_lease_freep
) DHCPStaticLease
*static_lease
= NULL
;
44 assert(section_line
> 0);
47 r
= network_config_section_new(filename
, section_line
, &n
);
51 static_lease
= hashmap_get(network
->dhcp_static_leases_by_section
, n
);
53 *ret
= TAKE_PTR(static_lease
);
57 r
= dhcp_static_lease_new(&static_lease
);
61 static_lease
->network
= network
;
62 static_lease
->section
= TAKE_PTR(n
);
63 r
= hashmap_ensure_put(&network
->dhcp_static_leases_by_section
, &network_config_hash_ops
, static_lease
->section
, static_lease
);
67 *ret
= TAKE_PTR(static_lease
);
71 static int static_lease_verify(DHCPStaticLease
*static_lease
) {
72 if (section_is_invalid(static_lease
->section
))
75 if (in4_addr_is_null(&static_lease
->address
))
76 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
77 "%s: DHCP static lease without Address= field configured. "
78 "Ignoring [DHCPServerStaticLease] section from line %u.",
79 static_lease
->section
->filename
, static_lease
->section
->line
);
81 /* TODO: check that the address is in the pool. */
83 if (static_lease
->client_id_size
== 0 || !static_lease
->client_id
)
84 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL
),
85 "%s: DHCP static lease without MACAddress= field configured. "
86 "Ignoring [DHCPServerStaticLease] section from line %u.",
87 static_lease
->section
->filename
, static_lease
->section
->line
);
89 assert(static_lease
->client_id_size
== ETH_ALEN
+ 1);
94 void network_drop_invalid_static_leases(Network
*network
) {
95 DHCPStaticLease
*static_lease
;
99 HASHMAP_FOREACH(static_lease
, network
->dhcp_static_leases_by_section
)
100 if (static_lease_verify(static_lease
) < 0)
101 dhcp_static_lease_free(static_lease
);
104 int config_parse_dhcp_static_lease_address(
106 const char *filename
,
109 unsigned section_line
,
116 _cleanup_(dhcp_static_lease_free_or_set_invalidp
) DHCPStaticLease
*lease
= NULL
;
117 Network
*network
= userdata
;
118 union in_addr_union addr
;
126 r
= lease_new_static(network
, filename
, section_line
, &lease
);
130 if (isempty(rvalue
)) {
131 lease
->address
.s_addr
= 0;
136 r
= in_addr_from_string(AF_INET
, rvalue
, &addr
);
138 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
139 "Failed to parse IPv4 address for DHCPv4 static lease, ignoring assignment: %s", rvalue
);
142 if (in4_addr_is_null(&addr
.in
)) {
143 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
144 "IPv4 address for DHCPv4 static lease cannot be the ANY address, ignoring assignment: %s", rvalue
);
148 lease
->address
= addr
.in
;
154 int config_parse_dhcp_static_lease_hwaddr(
156 const char *filename
,
159 unsigned section_line
,
166 _cleanup_(dhcp_static_lease_free_or_set_invalidp
) DHCPStaticLease
*lease
= NULL
;
167 Network
*network
= userdata
;
168 struct ether_addr hwaddr
;
177 r
= lease_new_static(network
, filename
, section_line
, &lease
);
181 if (isempty(rvalue
)) {
182 lease
->client_id
= mfree(lease
->client_id
);
183 lease
->client_id_size
= 0;
187 r
= ether_addr_from_string(rvalue
, &hwaddr
);
189 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
190 "Failed to parse MAC address for DHCPv4 static lease, ignoring assignment: %s", rvalue
);
193 if (ether_addr_is_null(&hwaddr
) || (hwaddr
.ether_addr_octet
[0] & 0x01)) {
194 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
195 "MAC address for DHCPv4 static lease cannot be null or multicast, ignoring assignment: %s", rvalue
);
199 c
= new(uint8_t, ETH_ALEN
+ 1);
203 /* set client id type to 1: Ethernet Link-Layer (RFC 2132) */
205 memcpy(c
+ 1, &hwaddr
, ETH_ALEN
);
207 free_and_replace(lease
->client_id
, c
);
208 lease
->client_id_size
= ETH_ALEN
+ 1;