]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/libsystemd-network/lldp-neighbor.c
tree-wide: use TAKE_PTR() and TAKE_FD() macros
[thirdparty/systemd.git] / src / libsystemd-network / lldp-neighbor.c
index 190c9baeced8c8953fc7ccbc24364c22358066e5..84231091d08c18e2162bef69ea7a0c65f1ece078 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
 /***
   This file is part of systemd.
 
@@ -24,7 +25,6 @@
 #include "in-addr-util.h"
 #include "lldp-internal.h"
 #include "lldp-neighbor.h"
-#include "lldp.h"
 #include "unaligned.h"
 
 static void lldp_neighbor_id_hash_func(const void *p, struct siphash *state) {
@@ -198,7 +198,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
         assert(n);
 
         if (n->raw_size < sizeof(struct ether_header)) {
-                log_lldp("Recieved truncated packet, ignoring.");
+                log_lldp("Received truncated packet, ignoring.");
                 return -EBADMSG;
         }
 
@@ -245,19 +245,18 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
 
                 switch (type) {
 
-                case LLDP_TYPE_END:
+                case SD_LLDP_TYPE_END:
                         if (length != 0) {
                                 log_lldp("End marker TLV not zero-sized, ignoring datagram.");
                                 return -EBADMSG;
                         }
-                        if (left != 0) {
-                                log_lldp("Trailing garbage in datagram, ignoring datagram.");
-                                return -EBADMSG;
-                        }
+
+                        /* Note that after processing the SD_LLDP_TYPE_END left could still be > 0
+                         * as the message may contain padding (see IEEE 802.1AB-2016, sec. 8.5.12) */
 
                         goto end_marker;
 
-                case LLDP_TYPE_CHASSIS_ID:
+                case SD_LLDP_TYPE_CHASSIS_ID:
                         if (length < 2 || length > 256) { /* includes the chassis subtype, hence one extra byte */
                                 log_lldp("Chassis ID field size out of range, ignoring datagram.");
                                 return -EBADMSG;
@@ -274,7 +273,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
                         n->id.chassis_id_size = length;
                         break;
 
-                case LLDP_TYPE_PORT_ID:
+                case SD_LLDP_TYPE_PORT_ID:
                         if (length < 2 || length > 256) { /* includes the port subtype, hence one extra byte */
                                 log_lldp("Port ID field size out of range, ignoring datagram.");
                                 return -EBADMSG;
@@ -291,7 +290,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
                         n->id.port_id_size = length;
                         break;
 
-                case LLDP_TYPE_TTL:
+                case SD_LLDP_TYPE_TTL:
                         if (length != 2) {
                                 log_lldp("TTL field has wrong size, ignoring datagram.");
                                 return -EBADMSG;
@@ -306,25 +305,25 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
                         n->has_ttl = true;
                         break;
 
-                case LLDP_TYPE_PORT_DESCRIPTION:
+                case SD_LLDP_TYPE_PORT_DESCRIPTION:
                         r = parse_string(&n->port_description, p, length);
                         if (r < 0)
                                 return r;
                         break;
 
-                case LLDP_TYPE_SYSTEM_NAME:
+                case SD_LLDP_TYPE_SYSTEM_NAME:
                         r = parse_string(&n->system_name, p, length);
                         if (r < 0)
                                 return r;
                         break;
 
-                case LLDP_TYPE_SYSTEM_DESCRIPTION:
+                case SD_LLDP_TYPE_SYSTEM_DESCRIPTION:
                         r = parse_string(&n->system_description, p, length);
                         if (r < 0)
                                 return r;
                         break;
 
-                case LLDP_TYPE_SYSTEM_CAPABILITIES:
+                case SD_LLDP_TYPE_SYSTEM_CAPABILITIES:
                         if (length != 4)
                                 log_lldp("System capabilities field has wrong size, ignoring.");
                         else {
@@ -335,7 +334,7 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
 
                         break;
 
-                case LLDP_TYPE_PRIVATE:
+                case SD_LLDP_TYPE_PRIVATE:
                         if (length < 4)
                                 log_lldp("Found private TLV that is too short, ignoring.");
 
@@ -361,9 +360,16 @@ end_marker:
 void lldp_neighbor_start_ttl(sd_lldp_neighbor *n) {
         assert(n);
 
-        if (n->ttl > 0)
-                n->until = usec_add(now(clock_boottime_or_monotonic()), n->ttl * USEC_PER_SEC);
-        else
+        if (n->ttl > 0) {
+                usec_t base;
+
+                /* Use the packet's timestamp if there is one known */
+                base = triple_timestamp_by_clock(&n->timestamp, clock_boottime_or_monotonic());
+                if (base <= 0 || base == USEC_INFINITY)
+                        base = now(clock_boottime_or_monotonic()); /* Otherwise, take the current time */
+
+                n->until = usec_add(base, n->ttl * USEC_PER_SEC);
+        } else
                 n->until = 0;
 
         if (n->lldp)
@@ -479,18 +485,18 @@ _public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, cons
 
         switch (*(uint8_t*) n->id.chassis_id) {
 
-        case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT:
-        case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS:
-        case LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT:
-        case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME:
-        case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED:
+        case SD_LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT:
+        case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS:
+        case SD_LLDP_CHASSIS_SUBTYPE_PORT_COMPONENT:
+        case SD_LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME:
+        case SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED:
                 k = cescape_length((char*) n->id.chassis_id + 1, n->id.chassis_id_size - 1);
                 if (!k)
                         return -ENOMEM;
 
                 goto done;
 
-        case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
+        case SD_LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
                 r = format_mac_address(n->id.chassis_id, n->id.chassis_id_size, &k);
                 if (r < 0)
                         return r;
@@ -499,7 +505,7 @@ _public_ int sd_lldp_neighbor_get_chassis_id_as_string(sd_lldp_neighbor *n, cons
 
                 break;
 
-        case LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS:
+        case SD_LLDP_CHASSIS_SUBTYPE_NETWORK_ADDRESS:
                 r = format_network_address(n->id.chassis_id, n->id.chassis_id_size, &k);
                 if (r < 0)
                         return r;
@@ -550,17 +556,17 @@ _public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const c
 
         switch (*(uint8_t*) n->id.port_id) {
 
-        case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS:
-        case LLDP_PORT_SUBTYPE_PORT_COMPONENT:
-        case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
-        case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED:
+        case SD_LLDP_PORT_SUBTYPE_INTERFACE_ALIAS:
+        case SD_LLDP_PORT_SUBTYPE_PORT_COMPONENT:
+        case SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME:
+        case SD_LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED:
                 k = cescape_length((char*) n->id.port_id + 1, n->id.port_id_size - 1);
                 if (!k)
                         return -ENOMEM;
 
                 goto done;
 
-        case LLDP_PORT_SUBTYPE_MAC_ADDRESS:
+        case SD_LLDP_PORT_SUBTYPE_MAC_ADDRESS:
                 r = format_mac_address(n->id.port_id, n->id.port_id_size, &k);
                 if (r < 0)
                         return r;
@@ -569,7 +575,7 @@ _public_ int sd_lldp_neighbor_get_port_id_as_string(sd_lldp_neighbor *n, const c
 
                 break;
 
-        case LLDP_PORT_SUBTYPE_NETWORK_ADDRESS:
+        case SD_LLDP_PORT_SUBTYPE_NETWORK_ADDRESS:
                 r = format_network_address(n->id.port_id, n->id.port_id_size, &k);
                 if (r < 0)
                         return r;
@@ -589,11 +595,11 @@ done:
         return 0;
 }
 
-_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret) {
+_public_ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec) {
         assert_return(n, -EINVAL);
-        assert_return(ret, -EINVAL);
+        assert_return(ret_sec, -EINVAL);
 
-        *ret = n->ttl;
+        *ret_sec = n->ttl;
         return 0;
 }
 
@@ -652,7 +658,7 @@ _public_ int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint
         return 0;
 }
 
-int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) {
+_public_ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t raw_size) {
         _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL;
         int r;
 
@@ -668,8 +674,7 @@ int sd_lldp_neighbor_from_raw(sd_lldp_neighbor **ret, const void *raw, size_t ra
         if (r < 0)
                 return r;
 
-        *ret = n;
-        n = 0;
+        *ret = TAKE_PTR(n);
 
         return r;
 }
@@ -680,7 +685,7 @@ _public_ int sd_lldp_neighbor_tlv_rewind(sd_lldp_neighbor *n) {
         assert(n->raw_size >= sizeof(struct ether_header));
         n->rindex = sizeof(struct ether_header);
 
-        return 0;
+        return n->rindex < n->raw_size;
 }
 
 _public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) {
@@ -694,7 +699,7 @@ _public_ int sd_lldp_neighbor_tlv_next(sd_lldp_neighbor *n) {
         if (n->rindex + 2 > n->raw_size) /* Truncated message */
                 return -EBADMSG;
 
-        length = LLDP_NEIGHBOR_LENGTH(n);
+        length = LLDP_NEIGHBOR_TLV_LENGTH(n);
         if (n->rindex + 2 + length > n->raw_size)
                 return -EBADMSG;
 
@@ -712,7 +717,7 @@ _public_ int sd_lldp_neighbor_tlv_get_type(sd_lldp_neighbor *n, uint8_t *type) {
         if (n->rindex + 2 > n->raw_size)
                 return -EBADMSG;
 
-        *type = LLDP_NEIGHBOR_TYPE(n);
+        *type = LLDP_NEIGHBOR_TLV_TYPE(n);
         return 0;
 }
 
@@ -738,20 +743,20 @@ _public_ int sd_lldp_neighbor_tlv_get_oui(sd_lldp_neighbor *n, uint8_t oui[3], u
         assert_return(oui, -EINVAL);
         assert_return(subtype, -EINVAL);
 
-        r = sd_lldp_neighbor_tlv_is_type(n, LLDP_TYPE_PRIVATE);
+        r = sd_lldp_neighbor_tlv_is_type(n, SD_LLDP_TYPE_PRIVATE);
         if (r < 0)
                 return r;
         if (r == 0)
                 return -ENXIO;
 
-        length = LLDP_NEIGHBOR_LENGTH(n);
+        length = LLDP_NEIGHBOR_TLV_LENGTH(n);
         if (length < 4)
                 return -EBADMSG;
 
         if (n->rindex + 2 + length > n->raw_size)
                 return -EBADMSG;
 
-        d = LLDP_NEIGHBOR_DATA(n);
+        d = LLDP_NEIGHBOR_TLV_DATA(n);
         memcpy(oui, d, 3);
         *subtype = d[3];
 
@@ -783,8 +788,7 @@ _public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret,
         if (n->rindex + 2 > n->raw_size)
                 return -EBADMSG;
 
-        length = LLDP_NEIGHBOR_LENGTH(n);
-
+        length = LLDP_NEIGHBOR_TLV_LENGTH(n);
         if (n->rindex + 2 + length > n->raw_size)
                 return -EBADMSG;
 
@@ -793,3 +797,16 @@ _public_ int sd_lldp_neighbor_tlv_get_raw(sd_lldp_neighbor *n, const void **ret,
 
         return 0;
 }
+
+_public_ int sd_lldp_neighbor_get_timestamp(sd_lldp_neighbor *n, clockid_t clock, uint64_t *ret) {
+        assert_return(n, -EINVAL);
+        assert_return(TRIPLE_TIMESTAMP_HAS_CLOCK(clock), -EOPNOTSUPP);
+        assert_return(clock_supported(clock), -EOPNOTSUPP);
+        assert_return(ret, -EINVAL);
+
+        if (!triple_timestamp_is_set(&n->timestamp))
+                return -ENODATA;
+
+        *ret = triple_timestamp_by_clock(&n->timestamp, clock);
+        return 0;
+}