| File: | build-scan/../src/network/networkd-lldp-tx.c |
| Warning: | line 132, column 24 Potential leak of memory pointed to by 'h' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | ||||
| 3 | #include <endian.h> | |||
| 4 | #include <inttypes.h> | |||
| 5 | #include <string.h> | |||
| 6 | ||||
| 7 | #include "alloc-util.h" | |||
| 8 | #include "fd-util.h" | |||
| 9 | #include "fileio.h" | |||
| 10 | #include "hostname-util.h" | |||
| 11 | #include "networkd-lldp-tx.h" | |||
| 12 | #include "networkd-manager.h" | |||
| 13 | #include "parse-util.h" | |||
| 14 | #include "random-util.h" | |||
| 15 | #include "socket-util.h" | |||
| 16 | #include "string-util.h" | |||
| 17 | #include "unaligned.h" | |||
| 18 | ||||
| 19 | /* The LLDP spec calls this "txFastInit", see 9.2.5.19 */ | |||
| 20 | #define LLDP_TX_FAST_INIT4U 4U | |||
| 21 | ||||
| 22 | /* The LLDP spec calls this "msgTxHold", see 9.2.5.6 */ | |||
| 23 | #define LLDP_TX_HOLD4U 4U | |||
| 24 | ||||
| 25 | /* The jitter range to add, see 9.2.2. */ | |||
| 26 | #define LLDP_JITTER_USEC(400U * ((usec_t) 1000ULL)) (400U * USEC_PER_MSEC((usec_t) 1000ULL)) | |||
| 27 | ||||
| 28 | /* The LLDP spec calls this msgTxInterval, but we subtract half the jitter off it. */ | |||
| 29 | #define LLDP_TX_INTERVAL_USEC(30U * ((usec_t) 1000000ULL) - (400U * ((usec_t) 1000ULL)) / 2 ) (30U * USEC_PER_SEC((usec_t) 1000000ULL) - LLDP_JITTER_USEC(400U * ((usec_t) 1000ULL)) / 2) | |||
| 30 | ||||
| 31 | /* The LLDP spec calls this msgFastTx, but we subtract half the jitter off it. */ | |||
| 32 | #define LLDP_FAST_TX_USEC(1U * ((usec_t) 1000000ULL) - (400U * ((usec_t) 1000ULL)) / 2 ) (1U * USEC_PER_SEC((usec_t) 1000000ULL) - LLDP_JITTER_USEC(400U * ((usec_t) 1000ULL)) / 2) | |||
| 33 | ||||
| 34 | static const struct ether_addr lldp_multicast_addr[_LLDP_EMIT_MAX] = { | |||
| 35 | [LLDP_EMIT_NEAREST_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }}, | |||
| 36 | [LLDP_EMIT_NON_TPMR_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }}, | |||
| 37 | [LLDP_EMIT_CUSTOMER_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }}, | |||
| 38 | }; | |||
| 39 | ||||
| 40 | static int lldp_write_tlv_header(uint8_t **p, uint8_t id, size_t sz) { | |||
| 41 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/network/networkd-lldp-tx.c" , 41, __PRETTY_FUNCTION__); } while (0); | |||
| 42 | ||||
| 43 | if (id > 127) | |||
| 44 | return -EBADMSG74; | |||
| 45 | if (sz > 511) | |||
| 46 | return -ENOBUFS105; | |||
| 47 | ||||
| 48 | (*p)[0] = (id << 1) | !!(sz & 256); | |||
| 49 | (*p)[1] = sz & 255; | |||
| 50 | ||||
| 51 | *p = *p + 2; | |||
| 52 | return 0; | |||
| 53 | } | |||
| 54 | ||||
| 55 | static int lldp_make_packet( | |||
| 56 | LLDPEmit mode, | |||
| 57 | const struct ether_addr *hwaddr, | |||
| 58 | const char *machine_id, | |||
| 59 | const char *ifname, | |||
| 60 | uint16_t ttl, | |||
| 61 | const char *port_description, | |||
| 62 | const char *hostname, | |||
| 63 | const char *pretty_hostname, | |||
| 64 | uint16_t system_capabilities, | |||
| 65 | uint16_t enabled_capabilities, | |||
| 66 | void **ret, size_t *sz) { | |||
| 67 | ||||
| 68 | size_t machine_id_length, ifname_length, port_description_length = 0, hostname_length = 0, pretty_hostname_length = 0; | |||
| 69 | _cleanup_free___attribute__((cleanup(freep))) void *packet = NULL((void*)0); | |||
| 70 | struct ether_header *h; | |||
| 71 | uint8_t *p; | |||
| 72 | size_t l; | |||
| 73 | int r; | |||
| 74 | ||||
| 75 | assert(mode > LLDP_EMIT_NO)do { if ((__builtin_expect(!!(!(mode > LLDP_EMIT_NO)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("mode > LLDP_EMIT_NO" ), "../src/network/networkd-lldp-tx.c", 75, __PRETTY_FUNCTION__ ); } while (0); | |||
| 76 | assert(mode < _LLDP_EMIT_MAX)do { if ((__builtin_expect(!!(!(mode < _LLDP_EMIT_MAX)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("mode < _LLDP_EMIT_MAX" ), "../src/network/networkd-lldp-tx.c", 76, __PRETTY_FUNCTION__ ); } while (0); | |||
| 77 | assert(hwaddr)do { if ((__builtin_expect(!!(!(hwaddr)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("hwaddr"), "../src/network/networkd-lldp-tx.c" , 77, __PRETTY_FUNCTION__); } while (0); | |||
| 78 | assert(machine_id)do { if ((__builtin_expect(!!(!(machine_id)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("machine_id"), "../src/network/networkd-lldp-tx.c" , 78, __PRETTY_FUNCTION__); } while (0); | |||
| 79 | assert(ifname)do { if ((__builtin_expect(!!(!(ifname)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ifname"), "../src/network/networkd-lldp-tx.c" , 79, __PRETTY_FUNCTION__); } while (0); | |||
| 80 | assert(ret)do { if ((__builtin_expect(!!(!(ret)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret"), "../src/network/networkd-lldp-tx.c" , 80, __PRETTY_FUNCTION__); } while (0); | |||
| 81 | assert(sz)do { if ((__builtin_expect(!!(!(sz)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("sz"), "../src/network/networkd-lldp-tx.c" , 81, __PRETTY_FUNCTION__); } while (0); | |||
| 82 | ||||
| 83 | machine_id_length = strlen(machine_id); | |||
| 84 | ifname_length = strlen(ifname); | |||
| 85 | ||||
| 86 | if (port_description) | |||
| 87 | port_description_length = strlen(port_description); | |||
| 88 | ||||
| 89 | if (hostname) | |||
| 90 | hostname_length = strlen(hostname); | |||
| 91 | ||||
| 92 | if (pretty_hostname) | |||
| 93 | pretty_hostname_length = strlen(pretty_hostname); | |||
| 94 | ||||
| 95 | l = sizeof(struct ether_header) + | |||
| 96 | /* Chassis ID */ | |||
| 97 | 2 + 1 + machine_id_length + | |||
| 98 | /* Port ID */ | |||
| 99 | 2 + 1 + ifname_length + | |||
| 100 | /* TTL */ | |||
| 101 | 2 + 2 + | |||
| 102 | /* System Capabilities */ | |||
| 103 | 2 + 4 + | |||
| 104 | /* End */ | |||
| 105 | 2; | |||
| 106 | ||||
| 107 | /* Port Description */ | |||
| 108 | if (port_description
| |||
| 109 | l += 2 + port_description_length; | |||
| 110 | ||||
| 111 | /* System Name */ | |||
| 112 | if (hostname
| |||
| 113 | l += 2 + hostname_length; | |||
| 114 | ||||
| 115 | /* System Description */ | |||
| 116 | if (pretty_hostname
| |||
| 117 | l += 2 + pretty_hostname_length; | |||
| 118 | ||||
| 119 | packet = malloc(l); | |||
| 120 | if (!packet) | |||
| 121 | return -ENOMEM12; | |||
| 122 | ||||
| 123 | h = (struct ether_header*) packet; | |||
| 124 | h->ether_type = htobe16(ETHERTYPE_LLDP0x88cc); | |||
| 125 | memcpy(h->ether_dhost, lldp_multicast_addr + mode, ETH_ALEN6); | |||
| 126 | memcpy(h->ether_shost, hwaddr, ETH_ALEN6); | |||
| 127 | ||||
| 128 | p = (uint8_t*) packet + sizeof(struct ether_header); | |||
| 129 | ||||
| 130 | r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_CHASSIS_ID, 1 + machine_id_length); | |||
| 131 | if (r
| |||
| 132 | return r; | |||
| ||||
| 133 | *(p++) = SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED; | |||
| 134 | p = mempcpy(p, machine_id, machine_id_length); | |||
| 135 | ||||
| 136 | r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_ID, 1 + ifname_length); | |||
| 137 | if (r < 0) | |||
| 138 | return r; | |||
| 139 | *(p++) = SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME; | |||
| 140 | p = mempcpy(p, ifname, ifname_length); | |||
| 141 | ||||
| 142 | r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_TTL, 2); | |||
| 143 | if (r < 0) | |||
| 144 | return r; | |||
| 145 | unaligned_write_be16(p, ttl); | |||
| 146 | p += 2; | |||
| 147 | ||||
| 148 | if (port_description) { | |||
| 149 | r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_DESCRIPTION, port_description_length); | |||
| 150 | if (r < 0) | |||
| 151 | return r; | |||
| 152 | p = mempcpy(p, port_description, port_description_length); | |||
| 153 | } | |||
| 154 | ||||
| 155 | if (hostname) { | |||
| 156 | r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_NAME, hostname_length); | |||
| 157 | if (r < 0) | |||
| 158 | return r; | |||
| 159 | p = mempcpy(p, hostname, hostname_length); | |||
| 160 | } | |||
| 161 | ||||
| 162 | if (pretty_hostname) { | |||
| 163 | r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_DESCRIPTION, pretty_hostname_length); | |||
| 164 | if (r < 0) | |||
| 165 | return r; | |||
| 166 | p = mempcpy(p, pretty_hostname, pretty_hostname_length); | |||
| 167 | } | |||
| 168 | ||||
| 169 | r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_CAPABILITIES, 4); | |||
| 170 | if (r < 0) | |||
| 171 | return r; | |||
| 172 | unaligned_write_be16(p, system_capabilities); | |||
| 173 | p += 2; | |||
| 174 | unaligned_write_be16(p, enabled_capabilities); | |||
| 175 | p += 2; | |||
| 176 | ||||
| 177 | r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_END, 0); | |||
| 178 | if (r < 0) | |||
| 179 | return r; | |||
| 180 | ||||
| 181 | assert(p == (uint8_t*) packet + l)do { if ((__builtin_expect(!!(!(p == (uint8_t*) packet + l)), 0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("p == (uint8_t*) packet + l" ), "../src/network/networkd-lldp-tx.c", 181, __PRETTY_FUNCTION__ ); } while (0); | |||
| 182 | ||||
| 183 | *ret = TAKE_PTR(packet)({ typeof(packet) _ptr_ = (packet); (packet) = ((void*)0); _ptr_ ; }); | |||
| 184 | *sz = l; | |||
| 185 | ||||
| 186 | return 0; | |||
| 187 | } | |||
| 188 | ||||
| 189 | static int lldp_send_packet( | |||
| 190 | int ifindex, | |||
| 191 | const struct ether_addr *address, | |||
| 192 | const void *packet, | |||
| 193 | size_t packet_size) { | |||
| 194 | ||||
| 195 | union sockaddr_union sa = { | |||
| 196 | .ll.sll_family = AF_PACKET17, | |||
| 197 | .ll.sll_protocol = htobe16(ETHERTYPE_LLDP0x88cc), | |||
| 198 | .ll.sll_ifindex = ifindex, | |||
| 199 | .ll.sll_halen = ETH_ALEN6, | |||
| 200 | }; | |||
| 201 | ||||
| 202 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | |||
| 203 | ssize_t l; | |||
| 204 | ||||
| 205 | assert(ifindex > 0)do { if ((__builtin_expect(!!(!(ifindex > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ifindex > 0"), "../src/network/networkd-lldp-tx.c" , 205, __PRETTY_FUNCTION__); } while (0); | |||
| 206 | assert(address)do { if ((__builtin_expect(!!(!(address)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("address"), "../src/network/networkd-lldp-tx.c" , 206, __PRETTY_FUNCTION__); } while (0); | |||
| 207 | assert(packet || packet_size <= 0)do { if ((__builtin_expect(!!(!(packet || packet_size <= 0 )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("packet || packet_size <= 0" ), "../src/network/networkd-lldp-tx.c", 207, __PRETTY_FUNCTION__ ); } while (0); | |||
| 208 | ||||
| 209 | memcpy(sa.ll.sll_addr, address, ETH_ALEN6); | |||
| 210 | ||||
| 211 | fd = socket(PF_PACKET17, SOCK_RAWSOCK_RAW|SOCK_CLOEXECSOCK_CLOEXEC, IPPROTO_RAWIPPROTO_RAW); | |||
| 212 | if (fd < 0) | |||
| 213 | return -errno(*__errno_location ()); | |||
| 214 | ||||
| 215 | l = sendto(fd, packet, packet_size, MSG_NOSIGNALMSG_NOSIGNAL, &sa.sa, sizeof(sa.ll)); | |||
| 216 | if (l < 0) | |||
| 217 | return -errno(*__errno_location ()); | |||
| 218 | ||||
| 219 | if ((size_t) l != packet_size) | |||
| 220 | return -EIO5; | |||
| 221 | ||||
| 222 | return 0; | |||
| 223 | } | |||
| 224 | ||||
| 225 | static int link_send_lldp(Link *link) { | |||
| 226 | char machine_id_string[SD_ID128_STRING_MAX33]; | |||
| 227 | _cleanup_free___attribute__((cleanup(freep))) char *hostname = NULL((void*)0), *pretty_hostname = NULL((void*)0); | |||
| 228 | _cleanup_free___attribute__((cleanup(freep))) void *packet = NULL((void*)0); | |||
| 229 | size_t packet_size = 0; | |||
| 230 | sd_id128_t machine_id; | |||
| 231 | uint16_t caps; | |||
| 232 | usec_t ttl; | |||
| 233 | int r; | |||
| 234 | ||||
| 235 | assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-lldp-tx.c" , 235, __PRETTY_FUNCTION__); } while (0); | |||
| 236 | ||||
| 237 | if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) | |||
| 238 | return 0; | |||
| 239 | ||||
| 240 | assert(link->network->lldp_emit < _LLDP_EMIT_MAX)do { if ((__builtin_expect(!!(!(link->network->lldp_emit < _LLDP_EMIT_MAX)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("link->network->lldp_emit < _LLDP_EMIT_MAX"), "../src/network/networkd-lldp-tx.c" , 240, __PRETTY_FUNCTION__); } while (0); | |||
| 241 | ||||
| 242 | r = sd_id128_get_machine(&machine_id); | |||
| 243 | if (r < 0) | |||
| 244 | return r; | |||
| 245 | ||||
| 246 | (void) gethostname_strict(&hostname); | |||
| 247 | (void) parse_env_file(NULL((void*)0), "/etc/machine-info", NEWLINE"\n\r", "PRETTY_HOSTNAME", &pretty_hostname, NULL((void*)0)); | |||
| 248 | ||||
| 249 | assert_cc(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1 <= (UINT16_MAX - 1) * USEC_PER_SEC)GCC diagnostic push
; GCC diagnostic ignored "-Wdeclaration-after-statement" ; struct _assert_struct_11 { char x[((30U * ((usec_t) 1000000ULL ) - (400U * ((usec_t) 1000ULL)) / 2) * 4U + 1 <= ((65535) - 1) * ((usec_t) 1000000ULL)) ? 0 : -1]; }; GCC diagnostic pop ; | |||
| 250 | ttl = DIV_ROUND_UP(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1, USEC_PER_SEC)({ const typeof(((30U * ((usec_t) 1000000ULL) - (400U * ((usec_t ) 1000ULL)) / 2) * 4U + 1)) __unique_prefix_X12 = (((30U * (( usec_t) 1000000ULL) - (400U * ((usec_t) 1000ULL)) / 2) * 4U + 1)); const typeof((((usec_t) 1000000ULL))) __unique_prefix_Y13 = ((((usec_t) 1000000ULL))); (__unique_prefix_X12 / __unique_prefix_Y13 + !!(__unique_prefix_X12 % __unique_prefix_Y13)); }); | |||
| 251 | ||||
| 252 | caps = (link->network
| |||
| 253 | SD_LLDP_SYSTEM_CAPABILITIES_ROUTER : | |||
| 254 | SD_LLDP_SYSTEM_CAPABILITIES_STATION; | |||
| 255 | ||||
| 256 | r = lldp_make_packet(link->network->lldp_emit, | |||
| 257 | &link->mac, | |||
| 258 | sd_id128_to_string(machine_id, machine_id_string), | |||
| 259 | link->ifname, | |||
| 260 | (uint16_t) ttl, | |||
| 261 | link->network
| |||
| 262 | hostname, | |||
| 263 | pretty_hostname, | |||
| 264 | SD_LLDP_SYSTEM_CAPABILITIES_STATION|SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|SD_LLDP_SYSTEM_CAPABILITIES_ROUTER, | |||
| 265 | caps, | |||
| 266 | &packet, &packet_size); | |||
| 267 | if (r < 0) | |||
| 268 | return r; | |||
| 269 | ||||
| 270 | return lldp_send_packet(link->ifindex, lldp_multicast_addr + link->network->lldp_emit, packet, packet_size); | |||
| 271 | } | |||
| 272 | ||||
| 273 | static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) { | |||
| 274 | Link *link = userdata; | |||
| 275 | usec_t current, delay, next; | |||
| 276 | int r; | |||
| 277 | ||||
| 278 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/network/networkd-lldp-tx.c" , 278, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
| 279 | assert(userdata)do { if ((__builtin_expect(!!(!(userdata)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("userdata"), "../src/network/networkd-lldp-tx.c" , 279, __PRETTY_FUNCTION__); } while (0); | |||
| 280 | ||||
| 281 | log_link_debug(link, "Sending LLDP packet...")({ const Link *_l = (link); _l ? log_object_internal(7, 0, "../src/network/networkd-lldp-tx.c" , 281, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void *)0), "Sending LLDP packet...") : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/network/networkd-lldp-tx.c" , 281, __func__, "Sending LLDP packet..."); }); | |||
| 282 | ||||
| 283 | r = link_send_lldp(link); | |||
| 284 | if (r < 0) | |||
| 285 | log_link_debug_errno(link, r, "Failed to send LLDP packet, ignoring: %m")({ const Link *_l = (link); _l ? log_object_internal(7, r, "../src/network/networkd-lldp-tx.c" , 285, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void *)0), "Failed to send LLDP packet, ignoring: %m") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), r, "../src/network/networkd-lldp-tx.c" , 285, __func__, "Failed to send LLDP packet, ignoring: %m"); }); | |||
| 286 | ||||
| 287 | if (link->lldp_tx_fast > 0) | |||
| 288 | link->lldp_tx_fast--; | |||
| 289 | ||||
| 290 | assert_se(sd_event_now(sd_event_source_get_event(s), clock_boottime_or_monotonic(), ¤t) >= 0)do { if ((__builtin_expect(!!(!(sd_event_now(sd_event_source_get_event (s), clock_boottime_or_monotonic(), ¤t) >= 0)),0 ))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("sd_event_now(sd_event_source_get_event(s), clock_boottime_or_monotonic(), ¤t) >= 0" ), "../src/network/networkd-lldp-tx.c", 290, __PRETTY_FUNCTION__ ); } while (0); | |||
| 291 | ||||
| 292 | delay = link->lldp_tx_fast > 0 ? LLDP_FAST_TX_USEC(1U * ((usec_t) 1000000ULL) - (400U * ((usec_t) 1000ULL)) / 2 ) : LLDP_TX_INTERVAL_USEC(30U * ((usec_t) 1000000ULL) - (400U * ((usec_t) 1000ULL)) / 2 ); | |||
| 293 | next = usec_add(usec_add(current, delay), (usec_t) random_u64() % LLDP_JITTER_USEC(400U * ((usec_t) 1000ULL))); | |||
| 294 | ||||
| 295 | r = sd_event_source_set_time(s, next); | |||
| 296 | if (r < 0) | |||
| 297 | return log_link_error_errno(link, r, "Failed to restart LLDP timer: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-lldp-tx.c" , 297, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void *)0), "Failed to restart LLDP timer: %m") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-lldp-tx.c" , 297, __func__, "Failed to restart LLDP timer: %m"); }); | |||
| 298 | ||||
| 299 | r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT); | |||
| 300 | if (r < 0) | |||
| 301 | return log_link_error_errno(link, r, "Failed to enable LLDP timer: %m")({ const Link *_l = (link); _l ? log_object_internal(3, r, "../src/network/networkd-lldp-tx.c" , 301, __func__, "INTERFACE=", _l->ifname, ((void*)0), ((void *)0), "Failed to enable LLDP timer: %m") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/network/networkd-lldp-tx.c" , 301, __func__, "Failed to enable LLDP timer: %m"); }); | |||
| 302 | ||||
| 303 | return 0; | |||
| 304 | } | |||
| 305 | ||||
| 306 | int link_lldp_emit_start(Link *link) { | |||
| 307 | usec_t next; | |||
| 308 | int r; | |||
| 309 | ||||
| 310 | assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-lldp-tx.c" , 310, __PRETTY_FUNCTION__); } while (0); | |||
| 311 | ||||
| 312 | if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) { | |||
| 313 | link_lldp_emit_stop(link); | |||
| 314 | return 0; | |||
| 315 | } | |||
| 316 | ||||
| 317 | /* Starts the LLDP transmission in "fast" mode. If it is already started, turns "fast" mode back on again. */ | |||
| 318 | ||||
| 319 | link->lldp_tx_fast = LLDP_TX_FAST_INIT4U; | |||
| 320 | ||||
| 321 | next = usec_add(usec_add(now(clock_boottime_or_monotonic()), LLDP_FAST_TX_USEC(1U * ((usec_t) 1000000ULL) - (400U * ((usec_t) 1000ULL)) / 2 )), | |||
| 322 | (usec_t) random_u64() % LLDP_JITTER_USEC(400U * ((usec_t) 1000ULL))); | |||
| 323 | ||||
| 324 | if (link->lldp_emit_event_source) { | |||
| 325 | usec_t old; | |||
| 326 | ||||
| 327 | /* Lower the timeout, maybe */ | |||
| 328 | r = sd_event_source_get_time(link->lldp_emit_event_source, &old); | |||
| 329 | if (r < 0) | |||
| 330 | return r; | |||
| 331 | ||||
| 332 | if (old <= next) | |||
| 333 | return 0; | |||
| 334 | ||||
| 335 | return sd_event_source_set_time(link->lldp_emit_event_source, next); | |||
| 336 | } else { | |||
| 337 | r = sd_event_add_time( | |||
| 338 | link->manager->event, | |||
| 339 | &link->lldp_emit_event_source, | |||
| 340 | clock_boottime_or_monotonic(), | |||
| 341 | next, | |||
| 342 | 0, | |||
| 343 | on_lldp_timer, | |||
| 344 | link); | |||
| 345 | if (r < 0) | |||
| 346 | return r; | |||
| 347 | ||||
| 348 | (void) sd_event_source_set_description(link->lldp_emit_event_source, "lldp-tx"); | |||
| 349 | } | |||
| 350 | ||||
| 351 | return 0; | |||
| 352 | } | |||
| 353 | ||||
| 354 | void link_lldp_emit_stop(Link *link) { | |||
| 355 | assert(link)do { if ((__builtin_expect(!!(!(link)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("link"), "../src/network/networkd-lldp-tx.c" , 355, __PRETTY_FUNCTION__); } while (0); | |||
| 356 | ||||
| 357 | link->lldp_emit_event_source = sd_event_source_unref(link->lldp_emit_event_source); | |||
| 358 | } | |||
| 359 | ||||
| 360 | int config_parse_lldp_emit( | |||
| 361 | const char *unit, | |||
| 362 | const char *filename, | |||
| 363 | unsigned line, | |||
| 364 | const char *section, | |||
| 365 | unsigned section_line, | |||
| 366 | const char *lvalue, | |||
| 367 | int ltype, | |||
| 368 | const char *rvalue, | |||
| 369 | void *data, | |||
| 370 | void *userdata) { | |||
| 371 | ||||
| 372 | LLDPEmit *emit = data; | |||
| 373 | int r; | |||
| 374 | ||||
| 375 | assert(filename)do { if ((__builtin_expect(!!(!(filename)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("filename"), "../src/network/networkd-lldp-tx.c" , 375, __PRETTY_FUNCTION__); } while (0); | |||
| 376 | assert(lvalue)do { if ((__builtin_expect(!!(!(lvalue)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("lvalue"), "../src/network/networkd-lldp-tx.c" , 376, __PRETTY_FUNCTION__); } while (0); | |||
| 377 | assert(rvalue)do { if ((__builtin_expect(!!(!(rvalue)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("rvalue"), "../src/network/networkd-lldp-tx.c" , 377, __PRETTY_FUNCTION__); } while (0); | |||
| 378 | ||||
| 379 | if (isempty(rvalue)) | |||
| 380 | *emit = LLDP_EMIT_NO; | |||
| 381 | else if (streq(rvalue, "nearest-bridge")(strcmp((rvalue),("nearest-bridge")) == 0)) | |||
| 382 | *emit = LLDP_EMIT_NEAREST_BRIDGE; | |||
| 383 | else if (streq(rvalue, "non-tpmr-bridge")(strcmp((rvalue),("non-tpmr-bridge")) == 0)) | |||
| 384 | *emit = LLDP_EMIT_NON_TPMR_BRIDGE; | |||
| 385 | else if (streq(rvalue, "customer-bridge")(strcmp((rvalue),("customer-bridge")) == 0)) | |||
| 386 | *emit = LLDP_EMIT_CUSTOMER_BRIDGE; | |||
| 387 | else { | |||
| 388 | r = parse_boolean(rvalue); | |||
| 389 | if (r < 0) { | |||
| 390 | log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse LLDP emission setting, ignoring: %s", rvalue)({ int _level = (3), _e = (0); (log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= ((_level) & 0x07)) ? log_syntax_internal(unit, _level , filename, line, _e, "../src/network/networkd-lldp-tx.c", 390 , __func__, "Failed to parse LLDP emission setting, ignoring: %s" , rvalue) : -abs(_e); }); | |||
| 391 | return 0; | |||
| 392 | } | |||
| 393 | ||||
| 394 | *emit = r ? LLDP_EMIT_NEAREST_BRIDGE : LLDP_EMIT_NO; | |||
| 395 | } | |||
| 396 | ||||
| 397 | return 0; | |||
| 398 | } |