1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <linux/if_ether.h>
5 #include <linux/if_macsec.h>
6 #include <linux/genetlink.h>
8 #include "conf-parser.h"
10 #include "hexdecoct.h"
12 #include "memory-util.h"
14 #include "netlink-util.h"
15 #include "network-internal.h"
16 #include "networkd-address.h"
17 #include "networkd-manager.h"
18 #include "sd-netlink.h"
19 #include "socket-util.h"
20 #include "string-table.h"
21 #include "string-util.h"
24 static void security_association_clear(SecurityAssociation
*sa
) {
28 explicit_bzero_safe(sa
->key
, sa
->key_len
);
32 static void macsec_receive_association_free(ReceiveAssociation
*c
) {
36 if (c
->macsec
&& c
->section
)
37 ordered_hashmap_remove(c
->macsec
->receive_associations_by_section
, c
->section
);
39 network_config_section_free(c
->section
);
40 security_association_clear(&c
->sa
);
45 DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveAssociation
, macsec_receive_association_free
);
47 static int macsec_receive_association_new_static(MACsec
*s
, const char *filename
, unsigned section_line
, ReceiveAssociation
**ret
) {
48 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
49 _cleanup_(macsec_receive_association_freep
) ReceiveAssociation
*c
= NULL
;
55 assert(section_line
> 0);
57 r
= network_config_section_new(filename
, section_line
, &n
);
61 c
= ordered_hashmap_get(s
->receive_associations_by_section
, n
);
67 c
= new(ReceiveAssociation
, 1);
71 *c
= (ReceiveAssociation
) {
73 .section
= TAKE_PTR(n
),
76 r
= ordered_hashmap_ensure_allocated(&s
->receive_associations_by_section
, &network_config_hash_ops
);
80 r
= ordered_hashmap_put(s
->receive_associations_by_section
, c
->section
, c
);
89 static void macsec_receive_channel_free(ReceiveChannel
*c
) {
94 if (c
->sci
.as_uint64
> 0)
95 ordered_hashmap_remove(c
->macsec
->receive_channels
, &c
->sci
.as_uint64
);
98 ordered_hashmap_remove(c
->macsec
->receive_channels_by_section
, c
->section
);
101 network_config_section_free(c
->section
);
106 DEFINE_NETWORK_SECTION_FUNCTIONS(ReceiveChannel
, macsec_receive_channel_free
);
108 static int macsec_receive_channel_new(MACsec
*s
, uint64_t sci
, ReceiveChannel
**ret
) {
113 c
= new(ReceiveChannel
, 1);
117 *c
= (ReceiveChannel
) {
119 .sci
.as_uint64
= sci
,
126 static int macsec_receive_channel_new_static(MACsec
*s
, const char *filename
, unsigned section_line
, ReceiveChannel
**ret
) {
127 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
128 _cleanup_(macsec_receive_channel_freep
) ReceiveChannel
*c
= NULL
;
134 assert(section_line
> 0);
136 r
= network_config_section_new(filename
, section_line
, &n
);
140 c
= ordered_hashmap_get(s
->receive_channels_by_section
, n
);
146 r
= macsec_receive_channel_new(s
, 0, &c
);
150 c
->section
= TAKE_PTR(n
);
152 r
= ordered_hashmap_ensure_allocated(&s
->receive_channels_by_section
, &network_config_hash_ops
);
156 r
= ordered_hashmap_put(s
->receive_channels_by_section
, c
->section
, c
);
165 static void macsec_transmit_association_free(TransmitAssociation
*a
) {
169 if (a
->macsec
&& a
->section
)
170 ordered_hashmap_remove(a
->macsec
->transmit_associations_by_section
, a
->section
);
172 network_config_section_free(a
->section
);
173 security_association_clear(&a
->sa
);
178 DEFINE_NETWORK_SECTION_FUNCTIONS(TransmitAssociation
, macsec_transmit_association_free
);
180 static int macsec_transmit_association_new_static(MACsec
*s
, const char *filename
, unsigned section_line
, TransmitAssociation
**ret
) {
181 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
182 _cleanup_(macsec_transmit_association_freep
) TransmitAssociation
*a
= NULL
;
188 assert(section_line
> 0);
190 r
= network_config_section_new(filename
, section_line
, &n
);
194 a
= ordered_hashmap_get(s
->transmit_associations_by_section
, n
);
200 a
= new(TransmitAssociation
, 1);
204 *a
= (TransmitAssociation
) {
206 .section
= TAKE_PTR(n
),
209 r
= ordered_hashmap_ensure_allocated(&s
->transmit_associations_by_section
, &network_config_hash_ops
);
213 r
= ordered_hashmap_put(s
->transmit_associations_by_section
, a
->section
, a
);
222 static int netdev_macsec_fill_message(NetDev
*netdev
, int command
, sd_netlink_message
**ret
) {
223 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
227 assert(netdev
->ifindex
> 0);
229 r
= sd_genl_message_new(netdev
->manager
->genl
, SD_GENL_MACSEC
, command
, &m
);
231 return log_netdev_error_errno(netdev
, r
, "Failed to create generic netlink message: %m");
233 r
= sd_netlink_message_append_u32(m
, MACSEC_ATTR_IFINDEX
, netdev
->ifindex
);
235 return log_netdev_error_errno(netdev
, r
, "Could not append MACSEC_ATTR_IFINDEX attribute: %m");
242 static int netdev_macsec_fill_message_sci(NetDev
*netdev
, MACsecSCI
*sci
, sd_netlink_message
*m
) {
249 r
= sd_netlink_message_open_container(m
, MACSEC_ATTR_RXSC_CONFIG
);
251 return log_netdev_error_errno(netdev
, r
, "Could not append MACSEC_ATTR_RXSC_CONFIG attribute: %m");
253 r
= sd_netlink_message_append_u64(m
, MACSEC_RXSC_ATTR_SCI
, sci
->as_uint64
);
255 return log_netdev_error_errno(netdev
, r
, "Could not append MACSEC_RXSC_ATTR_SCI attribute: %m");
257 r
= sd_netlink_message_close_container(m
);
259 return log_netdev_error_errno(netdev
, r
, "Could not append MACSEC_ATTR_RXSC_CONFIG attribute: %m");
264 static int netdev_macsec_fill_message_sa(NetDev
*netdev
, SecurityAssociation
*a
, sd_netlink_message
*m
) {
271 r
= sd_netlink_message_open_container(m
, MACSEC_ATTR_SA_CONFIG
);
273 return log_netdev_error_errno(netdev
, r
, "Could not append MACSEC_ATTR_SA_CONFIG attribute: %m");
275 r
= sd_netlink_message_append_u8(m
, MACSEC_SA_ATTR_AN
, a
->association_number
);
277 return log_netdev_error_errno(netdev
, r
, "Could not append MACSEC_SA_ATTR_AN attribute: %m");
279 if (a
->packet_number
> 0) {
280 r
= sd_netlink_message_append_u32(m
, MACSEC_SA_ATTR_PN
, a
->packet_number
);
282 return log_netdev_error_errno(netdev
, r
, "Could not append MACSEC_SA_ATTR_PN attribute: %m");
285 if (a
->key_len
> 0) {
286 r
= sd_netlink_message_append_data(m
, MACSEC_SA_ATTR_KEYID
, a
->key_id
, MACSEC_KEYID_LEN
);
288 return log_netdev_error_errno(netdev
, r
, "Could not append MACSEC_SA_ATTR_KEYID attribute: %m");
290 r
= sd_netlink_message_append_data(m
, MACSEC_SA_ATTR_KEY
, a
->key
, a
->key_len
);
292 return log_netdev_error_errno(netdev
, r
, "Could not append MACSEC_SA_ATTR_KEY attribute: %m");
295 r
= sd_netlink_message_close_container(m
);
297 return log_netdev_error_errno(netdev
, r
, "Could not append MACSEC_ATTR_SA_CONFIG attribute: %m");
302 static int macsec_receive_association_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, NetDev
*netdev
) {
306 assert(netdev
->state
!= _NETDEV_STATE_INVALID
);
308 r
= sd_netlink_message_get_errno(m
);
310 log_netdev_info(netdev
,
311 "MACsec receive secure association exists, "
312 "using existing without changing its parameters");
314 log_netdev_warning_errno(netdev
, r
,
315 "Failed to add receive secure association: %m");
321 log_netdev_debug(netdev
, "Receive secure association is configured");
326 static int netdev_macsec_configure_receive_association(NetDev
*netdev
, ReceiveAssociation
*a
) {
327 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
333 r
= netdev_macsec_fill_message(netdev
, MACSEC_CMD_ADD_RXSA
, &m
);
337 r
= netdev_macsec_fill_message_sa(netdev
, &a
->sa
, m
);
341 r
= netdev_macsec_fill_message_sci(netdev
, &a
->sci
, m
);
345 r
= netlink_call_async(netdev
->manager
->genl
, NULL
, m
, macsec_receive_association_handler
,
346 netdev_destroy_callback
, netdev
);
348 return log_netdev_error_errno(netdev
, r
, "Failed to configure receive secure association: %m");
355 static int macsec_receive_channel_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, ReceiveChannel
*c
) {
363 netdev
= NETDEV(c
->macsec
);
365 assert(netdev
->state
!= _NETDEV_STATE_INVALID
);
367 r
= sd_netlink_message_get_errno(m
);
369 log_netdev_debug(netdev
,
370 "MACsec receive channel exists, "
371 "using existing without changing its parameters");
373 log_netdev_warning_errno(netdev
, r
,
374 "Failed to add receive secure channel: %m");
380 log_netdev_debug(netdev
, "Receive channel is configured");
382 for (i
= 0; i
< c
->n_rxsa
; i
++) {
383 r
= netdev_macsec_configure_receive_association(netdev
, c
->rxsa
[i
]);
385 log_netdev_warning_errno(netdev
, r
,
386 "Failed to configure receive security association: %m");
395 static void receive_channel_destroy_callback(ReceiveChannel
*c
) {
399 netdev_unref(NETDEV(c
->macsec
));
402 static int netdev_macsec_configure_receive_channel(NetDev
*netdev
, ReceiveChannel
*c
) {
403 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
409 r
= netdev_macsec_fill_message(netdev
, MACSEC_CMD_ADD_RXSC
, &m
);
413 r
= netdev_macsec_fill_message_sci(netdev
, &c
->sci
, m
);
417 r
= netlink_call_async(netdev
->manager
->genl
, NULL
, m
, macsec_receive_channel_handler
,
418 receive_channel_destroy_callback
, c
);
420 return log_netdev_error_errno(netdev
, r
, "Failed to configure receive channel: %m");
427 static int macsec_transmit_association_handler(sd_netlink
*rtnl
, sd_netlink_message
*m
, NetDev
*netdev
) {
431 assert(netdev
->state
!= _NETDEV_STATE_INVALID
);
433 r
= sd_netlink_message_get_errno(m
);
435 log_netdev_info(netdev
,
436 "MACsec transmit secure association exists, "
437 "using existing without changing its parameters");
439 log_netdev_warning_errno(netdev
, r
,
440 "Failed to add transmit secure association: %m");
446 log_netdev_debug(netdev
, "Transmit secure association is configured");
451 static int netdev_macsec_configure_transmit_association(NetDev
*netdev
, TransmitAssociation
*a
) {
452 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
458 r
= netdev_macsec_fill_message(netdev
, MACSEC_CMD_ADD_TXSA
, &m
);
462 r
= netdev_macsec_fill_message_sa(netdev
, &a
->sa
, m
);
466 r
= netlink_call_async(netdev
->manager
->genl
, NULL
, m
, macsec_transmit_association_handler
,
467 netdev_destroy_callback
, netdev
);
469 return log_netdev_error_errno(netdev
, r
, "Failed to configure transmit secure association: %m");
476 static int netdev_macsec_configure(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
477 TransmitAssociation
*a
;
487 ORDERED_HASHMAP_FOREACH(a
, s
->transmit_associations_by_section
, i
) {
488 r
= netdev_macsec_configure_transmit_association(netdev
, a
);
493 ORDERED_HASHMAP_FOREACH(c
, s
->receive_channels
, i
) {
494 r
= netdev_macsec_configure_receive_channel(netdev
, c
);
502 static int netdev_macsec_fill_message_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
512 r
= sd_netlink_message_append_u16(m
, IFLA_MACSEC_PORT
, v
->port
);
514 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_MACSEC_PORT attribute: %m");
517 if (v
->encrypt
>= 0) {
518 r
= sd_netlink_message_append_u8(m
, IFLA_MACSEC_ENCRYPT
, v
->encrypt
);
520 return log_netdev_error_errno(netdev
, r
, "Could not append IFLA_MACSEC_ENCRYPT attribute: %m");
526 int config_parse_macsec_port(
528 const char *filename
,
531 unsigned section_line
,
538 _cleanup_(macsec_receive_association_free_or_set_invalidp
) ReceiveAssociation
*b
= NULL
;
539 _cleanup_(macsec_receive_channel_free_or_set_invalidp
) ReceiveChannel
*c
= NULL
;
540 MACsec
*s
= userdata
;
551 /* This parses port used to make Secure Channel Identifier (SCI) */
553 if (streq(section
, "MACsec"))
555 else if (streq(section
, "MACsecReceiveChannel")) {
556 r
= macsec_receive_channel_new_static(s
, filename
, section_line
, &c
);
562 assert(streq(section
, "MACsecReceiveAssociation"));
564 r
= macsec_receive_association_new_static(s
, filename
, section_line
, &b
);
571 r
= parse_ip_port(rvalue
, &port
);
573 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
574 "Failed to parse port '%s' for secure channel identifier. Ignoring assignment: %m",
579 *dest
= htobe16(port
);
587 int config_parse_macsec_hw_address(
589 const char *filename
,
592 unsigned section_line
,
599 _cleanup_(macsec_receive_association_free_or_set_invalidp
) ReceiveAssociation
*b
= NULL
;
600 _cleanup_(macsec_receive_channel_free_or_set_invalidp
) ReceiveChannel
*c
= NULL
;
601 MACsec
*s
= userdata
;
610 if (streq(section
, "MACsecReceiveChannel"))
611 r
= macsec_receive_channel_new_static(s
, filename
, section_line
, &c
);
613 r
= macsec_receive_association_new_static(s
, filename
, section_line
, &b
);
617 r
= ether_addr_from_string(rvalue
, b
? &b
->sci
.mac
: &c
->sci
.mac
);
619 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
620 "Failed to parse MAC address for secure channel identifier. "
621 "Ignoring assignment: %s", rvalue
);
631 int config_parse_macsec_packet_number(
633 const char *filename
,
636 unsigned section_line
,
643 _cleanup_(macsec_transmit_association_free_or_set_invalidp
) TransmitAssociation
*a
= NULL
;
644 _cleanup_(macsec_receive_association_free_or_set_invalidp
) ReceiveAssociation
*b
= NULL
;
645 MACsec
*s
= userdata
;
655 if (streq(section
, "MACsecTransmitAssociation"))
656 r
= macsec_transmit_association_new_static(s
, filename
, section_line
, &a
);
658 r
= macsec_receive_association_new_static(s
, filename
, section_line
, &b
);
662 dest
= a
? &a
->sa
.packet_number
: &b
->sa
.packet_number
;
664 r
= safe_atou32(rvalue
, &val
);
666 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
667 "Failed to parse packet number. Ignoring assignment: %s", rvalue
);
670 if (streq(section
, "MACsecTransmitAssociation") && val
== 0) {
671 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
672 "Invalid packet number. Ignoring assignment: %s", rvalue
);
683 int config_parse_macsec_key(
685 const char *filename
,
688 unsigned section_line
,
695 _cleanup_(macsec_transmit_association_free_or_set_invalidp
) TransmitAssociation
*a
= NULL
;
696 _cleanup_(macsec_receive_association_free_or_set_invalidp
) ReceiveAssociation
*b
= NULL
;
697 _cleanup_free_
void *p
;
698 MACsec
*s
= userdata
;
699 SecurityAssociation
*dest
;
709 if (streq(section
, "MACsecTransmitAssociation"))
710 r
= macsec_transmit_association_new_static(s
, filename
, section_line
, &a
);
712 r
= macsec_receive_association_new_static(s
, filename
, section_line
, &b
);
716 dest
= a
? &a
->sa
: &b
->sa
;
718 r
= unhexmem_full(rvalue
, strlen(rvalue
), true, &p
, &l
);
720 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
721 "Failed to parse key. Ignoring assignment: %m");
725 /* See DEFAULT_SAK_LEN in drivers/net/macsec.c */
726 explicit_bzero_safe(p
, l
);
727 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
728 "Invalid key length (%zu). Ignoring assignment", l
);
732 free_and_replace(dest
->key
, p
);
741 int config_parse_macsec_key_id(
743 const char *filename
,
746 unsigned section_line
,
753 _cleanup_(macsec_transmit_association_free_or_set_invalidp
) TransmitAssociation
*a
= NULL
;
754 _cleanup_(macsec_receive_association_free_or_set_invalidp
) ReceiveAssociation
*b
= NULL
;
755 _cleanup_free_
void *p
;
756 MACsec
*s
= userdata
;
767 if (streq(section
, "MACsecTransmitAssociation"))
768 r
= macsec_transmit_association_new_static(s
, filename
, section_line
, &a
);
770 r
= macsec_receive_association_new_static(s
, filename
, section_line
, &b
);
774 r
= unhexmem(rvalue
, strlen(rvalue
), &p
, &l
);
776 log_syntax(unit
, LOG_ERR
, filename
, line
, r
, "Failed to parse key id. Ignoring assignment: %s", rvalue
);
779 if (l
> MACSEC_KEYID_LEN
) {
780 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
781 "The size of key id is too large (%zu), maximum of %zu permitted. "
782 "Ignoring assignment: %s", l
, (size_t) MACSEC_KEYID_LEN
, rvalue
);
786 dest
= a
? a
->sa
.key_id
: b
->sa
.key_id
;
787 memcpy_safe(dest
, p
, l
);
788 memzero(dest
+ l
, MACSEC_KEYID_LEN
- l
);
796 static int macsec_receive_channel_verify(ReceiveChannel
*c
) {
803 netdev
= NETDEV(c
->macsec
);
805 if (section_is_invalid(c
->section
))
808 if (ether_addr_is_null(&c
->sci
.mac
))
809 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
810 "%s: MACsec receive channel without MAC address configured. "
811 "Ignoring [MACsecReceiveChannel] section from line %u",
812 c
->section
->filename
, c
->section
->line
);
814 if (c
->sci
.port
== 0)
815 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
816 "%s: MACsec receive channel without port configured. "
817 "Ignoring [MACsecReceiveChannel] section from line %u",
818 c
->section
->filename
, c
->section
->line
);
820 r
= ordered_hashmap_ensure_allocated(&c
->macsec
->receive_channels
, &uint64_hash_ops
);
824 r
= ordered_hashmap_put(c
->macsec
->receive_channels
, &c
->sci
.as_uint64
, c
);
826 return log_netdev_error_errno(netdev
, r
,
827 "%s: Multiple [MACsecReceiveChannel] sections have same SCI, "
828 "Ignoring [MACsecReceiveChannel] section from line %u",
829 c
->section
->filename
, c
->section
->line
);
831 return log_netdev_error_errno(netdev
, r
,
832 "%s: Failed to store [MACsecReceiveChannel] section at hashmap, "
833 "Ignoring [MACsecReceiveChannel] section from line %u",
834 c
->section
->filename
, c
->section
->line
);
838 static int macsec_transmit_association_verify(TransmitAssociation
*t
) {
844 netdev
= NETDEV(t
->macsec
);
846 if (section_is_invalid(t
->section
))
849 if (t
->sa
.packet_number
== 0)
850 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
851 "%s: MACsec transmit secure association without PacketNumber= configured. "
852 "Ignoring [MACsecTransmitAssociation] section from line %u",
853 t
->section
->filename
, t
->section
->line
);
855 if (t
->sa
.key_len
<= 0)
856 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
857 "%s: MACsec transmit secure association without key configured. "
858 "Ignoring [MACsecTransmitAssociation] section from line %u",
859 t
->section
->filename
, t
->section
->line
);
864 static int macsec_receive_association_verify(ReceiveAssociation
*a
) {
872 netdev
= NETDEV(a
->macsec
);
874 if (section_is_invalid(a
->section
))
877 if (a
->sa
.key_len
<= 0)
878 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
879 "%s: MACsec receive secure association without key configured. "
880 "Ignoring [MACsecReceiveAssociation] section from line %u",
881 a
->section
->filename
, a
->section
->line
);
883 if (ether_addr_is_null(&a
->sci
.mac
))
884 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
885 "%s: MACsec receive secure association without MAC address configured. "
886 "Ignoring [MACsecReceiveAssociation] section from line %u",
887 a
->section
->filename
, a
->section
->line
);
889 if (a
->sci
.port
== 0)
890 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
891 "%s: MACsec receive secure association without port configured. "
892 "Ignoring [MACsecReceiveAssociation] section from line %u",
893 a
->section
->filename
, a
->section
->line
);
895 c
= ordered_hashmap_get(a
->macsec
->receive_channels
, &a
->sci
.as_uint64
);
897 _cleanup_(macsec_receive_channel_freep
) ReceiveChannel
*new_channel
= NULL
;
899 r
= macsec_receive_channel_new(a
->macsec
, a
->sci
.as_uint64
, &new_channel
);
903 r
= ordered_hashmap_ensure_allocated(&a
->macsec
->receive_channels
, &uint64_hash_ops
);
907 r
= ordered_hashmap_put(a
->macsec
->receive_channels
, &new_channel
->sci
.as_uint64
, new_channel
);
909 return log_netdev_error_errno(netdev
, r
,
910 "%s: Failed to store receive channel at hashmap, "
911 "Ignoring [MACsecReceiveAssociation] section from line %u",
912 a
->section
->filename
, a
->section
->line
);
913 c
= TAKE_PTR(new_channel
);
915 if (c
->n_rxsa
>= MACSEC_MAX_ASSOCIATION_NUMBER
)
916 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(ERANGE
),
917 "%s: Too many [MACsecReceiveAssociation] sections for the same receive channel, "
918 "Ignoring [MACsecReceiveAssociation] section from line %u",
919 a
->section
->filename
, a
->section
->line
);
921 a
->sa
.association_number
= c
->n_rxsa
;
922 c
->rxsa
[c
->n_rxsa
++] = a
;
927 static int netdev_macsec_verify(NetDev
*netdev
, const char *filename
) {
928 MACsec
*v
= MACSEC(netdev
);
929 TransmitAssociation
*a
;
930 ReceiveAssociation
*n
;
940 ORDERED_HASHMAP_FOREACH(c
, v
->receive_channels_by_section
, i
) {
941 r
= macsec_receive_channel_verify(c
);
943 macsec_receive_channel_free(c
);
947 ORDERED_HASHMAP_FOREACH(a
, v
->transmit_associations_by_section
, i
) {
948 r
= macsec_transmit_association_verify(a
);
950 macsec_transmit_association_free(a
);
954 if (an
>= MACSEC_MAX_ASSOCIATION_NUMBER
) {
955 log_netdev_error(netdev
,
956 "%s: Too many [MACsecTransmitAssociation] sections configured. "
957 "Ignoring [MACsecTransmitAssociation] section from line %u",
958 a
->section
->filename
, a
->section
->line
);
959 macsec_transmit_association_free(a
);
963 a
->sa
.association_number
= an
++;
966 ORDERED_HASHMAP_FOREACH(n
, v
->receive_associations_by_section
, i
) {
967 r
= macsec_receive_association_verify(n
);
969 macsec_receive_association_free(n
);
975 static void macsec_init(NetDev
*netdev
) {
987 static void macsec_done(NetDev
*netdev
) {
996 ordered_hashmap_free_with_destructor(t
->receive_channels
, macsec_receive_channel_free
);
997 ordered_hashmap_free_with_destructor(t
->receive_channels_by_section
, macsec_receive_channel_free
);
998 ordered_hashmap_free_with_destructor(t
->transmit_associations_by_section
, macsec_transmit_association_free
);
999 ordered_hashmap_free_with_destructor(t
->receive_associations_by_section
, macsec_receive_association_free
);
1002 const NetDevVTable macsec_vtable
= {
1003 .object_size
= sizeof(MACsec
),
1004 .init
= macsec_init
,
1005 .sections
= "Match\0NetDev\0MACsec\0MACsecReceiveChannel\0MACsecTransmitAssociation\0MACsecReceiveAssociation\0",
1006 .fill_message_create
= netdev_macsec_fill_message_create
,
1007 .post_create
= netdev_macsec_configure
,
1008 .done
= macsec_done
,
1009 .create_type
= NETDEV_CREATE_STACKED
,
1010 .config_verify
= netdev_macsec_verify
,