Compare commits
3 Commits
8ff8ce6284
...
876acda0ed
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | 876acda0ed | |
Susant Sahani | e9a8c550c1 | |
Susant Sahani | f69b4ae885 |
|
@ -459,6 +459,7 @@
|
||||||
reception.</para>
|
reception.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>BindCarrier=</varname></term>
|
<term><varname>BindCarrier=</varname></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -2351,6 +2352,28 @@
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>[LLDP] Section Options</title>
|
||||||
|
<para>The <literal>[LLDP]</literal> section manages the Link Layer Discovery Protocol (LLDP) and accepts the
|
||||||
|
following keys.</para>
|
||||||
|
<variablelist class='network-directives'>
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>MUDURL=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>Controls support for Ethernet LLDP packet's Manufacturer Usage Description (MUD). MUD is an embedded software
|
||||||
|
standard defined by the IETF that allows IoT Device makers to advertise device specifications, including the intended
|
||||||
|
communication patterns for their device when it connects to the network. The network can then use this intent to author
|
||||||
|
a context-specific access policy, so the device functions only within those parameters. Takes an URL of length up to 255
|
||||||
|
characters. A superficial verification that the string is a valid URL
|
||||||
|
will be performed. See
|
||||||
|
<ulink url="https://tools.ietf.org/html/rfc8520">RFC 8520</ulink> for details. The MUD URL received
|
||||||
|
from the LLDP packets will be saved at the state files and can be read via
|
||||||
|
<function>sd_lldp_neighbor_get_mud_url()</function> function.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>[CAN] Section Options</title>
|
<title>[CAN] Section Options</title>
|
||||||
<para>The <literal>[CAN]</literal> section manages the Controller Area Network (CAN bus) and accepts the
|
<para>The <literal>[CAN]</literal> section manages the Controller Area Network (CAN bus) and accepts the
|
||||||
|
|
|
@ -50,6 +50,7 @@ static void lldp_neighbor_free(sd_lldp_neighbor *n) {
|
||||||
free(n->port_description);
|
free(n->port_description);
|
||||||
free(n->system_name);
|
free(n->system_name);
|
||||||
free(n->system_description);
|
free(n->system_description);
|
||||||
|
free(n->mud_url);
|
||||||
free(n->chassis_id_as_string);
|
free(n->chassis_id_as_string);
|
||||||
free(n->port_id_as_string);
|
free(n->port_id_as_string);
|
||||||
free(n);
|
free(n);
|
||||||
|
@ -292,9 +293,20 @@ int lldp_neighbor_parse(sd_lldp_neighbor *n) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SD_LLDP_TYPE_PRIVATE:
|
case SD_LLDP_TYPE_PRIVATE: {
|
||||||
if (length < 4)
|
if (length < 4)
|
||||||
log_lldp("Found private TLV that is too short, ignoring.");
|
log_lldp("Found private TLV that is too short, ignoring.");
|
||||||
|
else {
|
||||||
|
/* RFC 8520: MUD URL */
|
||||||
|
if (memcmp(p, SD_LLDP_OUI_MUD, sizeof(SD_LLDP_OUI_MUD)) == 0 &&
|
||||||
|
p[sizeof(SD_LLDP_OUI_MUD)] == SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION) {
|
||||||
|
r = parse_string(&n->mud_url, p + sizeof(SD_LLDP_OUI_MUD) + 1,
|
||||||
|
length - 1 - sizeof(SD_LLDP_OUI_MUD));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -593,6 +605,17 @@ _public_ int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const ch
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_public_ int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret) {
|
||||||
|
assert_return(n, -EINVAL);
|
||||||
|
assert_return(ret, -EINVAL);
|
||||||
|
|
||||||
|
if (!n->mud_url)
|
||||||
|
return -ENODATA;
|
||||||
|
|
||||||
|
*ret = n->mud_url;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
_public_ int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret) {
|
_public_ int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret) {
|
||||||
assert_return(n, -EINVAL);
|
assert_return(n, -EINVAL);
|
||||||
assert_return(ret, -EINVAL);
|
assert_return(ret, -EINVAL);
|
||||||
|
|
|
@ -54,6 +54,7 @@ struct sd_lldp_neighbor {
|
||||||
char *port_description;
|
char *port_description;
|
||||||
char *system_name;
|
char *system_name;
|
||||||
char *system_description;
|
char *system_description;
|
||||||
|
char *mud_url;
|
||||||
|
|
||||||
uint16_t port_vlan_id;
|
uint16_t port_vlan_id;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <net/if_arp.h>
|
#include <net/if_arp.h>
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "escape.h"
|
||||||
#include "env-file.h"
|
#include "env-file.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "hostname-util.h"
|
#include "hostname-util.h"
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "unaligned.h"
|
#include "unaligned.h"
|
||||||
|
#include "web-util.h"
|
||||||
|
|
||||||
/* The LLDP spec calls this "txFastInit", see 9.2.5.19 */
|
/* The LLDP spec calls this "txFastInit", see 9.2.5.19 */
|
||||||
#define LLDP_TX_FAST_INIT 4U
|
#define LLDP_TX_FAST_INIT 4U
|
||||||
|
@ -81,9 +83,11 @@ static int lldp_make_packet(
|
||||||
const char *pretty_hostname,
|
const char *pretty_hostname,
|
||||||
uint16_t system_capabilities,
|
uint16_t system_capabilities,
|
||||||
uint16_t enabled_capabilities,
|
uint16_t enabled_capabilities,
|
||||||
|
char *mud,
|
||||||
void **ret, size_t *sz) {
|
void **ret, size_t *sz) {
|
||||||
|
|
||||||
size_t machine_id_length, ifname_length, port_description_length = 0, hostname_length = 0, pretty_hostname_length = 0;
|
size_t machine_id_length, ifname_length, port_description_length = 0, hostname_length = 0,
|
||||||
|
pretty_hostname_length = 0, mud_length = 0;
|
||||||
_cleanup_free_ void *packet = NULL;
|
_cleanup_free_ void *packet = NULL;
|
||||||
struct ether_header *h;
|
struct ether_header *h;
|
||||||
uint8_t *p;
|
uint8_t *p;
|
||||||
|
@ -110,6 +114,9 @@ static int lldp_make_packet(
|
||||||
if (pretty_hostname)
|
if (pretty_hostname)
|
||||||
pretty_hostname_length = strlen(pretty_hostname);
|
pretty_hostname_length = strlen(pretty_hostname);
|
||||||
|
|
||||||
|
if (mud)
|
||||||
|
mud_length = strlen(mud);
|
||||||
|
|
||||||
l = sizeof(struct ether_header) +
|
l = sizeof(struct ether_header) +
|
||||||
/* Chassis ID */
|
/* Chassis ID */
|
||||||
2 + 1 + machine_id_length +
|
2 + 1 + machine_id_length +
|
||||||
|
@ -134,6 +141,10 @@ static int lldp_make_packet(
|
||||||
if (pretty_hostname)
|
if (pretty_hostname)
|
||||||
l += 2 + pretty_hostname_length;
|
l += 2 + pretty_hostname_length;
|
||||||
|
|
||||||
|
/* MUD URL */
|
||||||
|
if (mud)
|
||||||
|
l += 2 + sizeof(SD_LLDP_OUI_MUD) + 1 + mud_length;
|
||||||
|
|
||||||
packet = malloc(l);
|
packet = malloc(l);
|
||||||
if (!packet)
|
if (!packet)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -184,6 +195,32 @@ static int lldp_make_packet(
|
||||||
p = mempcpy(p, pretty_hostname, pretty_hostname_length);
|
p = mempcpy(p, pretty_hostname, pretty_hostname_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mud) {
|
||||||
|
uint8_t oui_mud[sizeof(SD_LLDP_OUI_MUD)] = {0x00, 0x00, 0x5E};
|
||||||
|
/*
|
||||||
|
* +--------+--------+----------+---------+--------------
|
||||||
|
* |TLV Type| len | OUI |subtype | MUDString
|
||||||
|
* | =127 | |= 00 00 5E| = 1 |
|
||||||
|
* |(7 bits)|(9 bits)|(3 octets)|(1 octet)|(1-255 octets)
|
||||||
|
* +--------+--------+----------+---------+--------------
|
||||||
|
* where:
|
||||||
|
|
||||||
|
* o TLV Type = 127 indicates a vendor-specific TLV
|
||||||
|
* o len = indicates the TLV string length
|
||||||
|
* o OUI = 00 00 5E is the organizationally unique identifier of IANA
|
||||||
|
* o subtype = 1 (as assigned by IANA for the MUDstring)
|
||||||
|
* o MUDstring = the length MUST NOT exceed 255 octets
|
||||||
|
*/
|
||||||
|
|
||||||
|
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PRIVATE, sizeof(SD_LLDP_OUI_MUD) + 1 + mud_length);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
p = mempcpy(p, &oui_mud, sizeof(SD_LLDP_OUI_MUD));
|
||||||
|
*(p++) = SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION;
|
||||||
|
p = mempcpy(p, mud, mud_length);
|
||||||
|
}
|
||||||
|
|
||||||
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_CAPABILITIES, 4);
|
r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_CAPABILITIES, 4);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -281,6 +318,7 @@ static int link_send_lldp(Link *link) {
|
||||||
pretty_hostname,
|
pretty_hostname,
|
||||||
SD_LLDP_SYSTEM_CAPABILITIES_STATION|SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|SD_LLDP_SYSTEM_CAPABILITIES_ROUTER,
|
SD_LLDP_SYSTEM_CAPABILITIES_STATION|SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|SD_LLDP_SYSTEM_CAPABILITIES_ROUTER,
|
||||||
caps,
|
caps,
|
||||||
|
link->network ? link->network->lldp_mud : NULL,
|
||||||
&packet, &packet_size);
|
&packet, &packet_size);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -414,3 +452,40 @@ int config_parse_lldp_emit(
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int config_parse_lldp_mud(
|
||||||
|
const char *unit,
|
||||||
|
const char *filename,
|
||||||
|
unsigned line,
|
||||||
|
const char *section,
|
||||||
|
unsigned section_line,
|
||||||
|
const char *lvalue,
|
||||||
|
int ltype,
|
||||||
|
const char *rvalue,
|
||||||
|
void *data,
|
||||||
|
void *userdata) {
|
||||||
|
|
||||||
|
_cleanup_free_ char *unescaped = NULL;
|
||||||
|
Network *n = data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
|
||||||
|
r = cunescape(rvalue, 0, &unescaped);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
|
"Failed to Failed to unescape LLDP MUD URL, ignoring: %s", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!http_url_is_valid(unescaped) || strlen(unescaped) > 255) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||||
|
"Failed to parse LLDP MUD URL '%s', ignoring: %m", rvalue);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return free_and_replace(n->lldp_mud, unescaped);
|
||||||
|
}
|
||||||
|
|
|
@ -20,3 +20,4 @@ int link_lldp_emit_start(Link *link);
|
||||||
void link_lldp_emit_stop(Link *link);
|
void link_lldp_emit_stop(Link *link);
|
||||||
|
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_lldp_emit);
|
CONFIG_PARSER_PROTOTYPE(config_parse_lldp_emit);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mud);
|
||||||
|
|
|
@ -259,6 +259,7 @@ IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime,
|
||||||
IPv6Prefix.Assign, config_parse_prefix_assign, 0, 0
|
IPv6Prefix.Assign, config_parse_prefix_assign, 0, 0
|
||||||
IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0
|
IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0
|
||||||
IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0
|
IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0
|
||||||
|
LLDP.MUDURL, config_parse_lldp_mud, 0, 0
|
||||||
CAN.BitRate, config_parse_can_bitrate, 0, offsetof(Network, can_bitrate)
|
CAN.BitRate, config_parse_can_bitrate, 0, offsetof(Network, can_bitrate)
|
||||||
CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point)
|
CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point)
|
||||||
CAN.DataBitRate, config_parse_can_bitrate, 0, offsetof(Network, can_data_bitrate)
|
CAN.DataBitRate, config_parse_can_bitrate, 0, offsetof(Network, can_data_bitrate)
|
||||||
|
|
|
@ -485,6 +485,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
||||||
"IPv6PrefixDelegation\0"
|
"IPv6PrefixDelegation\0"
|
||||||
"IPv6Prefix\0"
|
"IPv6Prefix\0"
|
||||||
"IPv6RoutePrefix\0"
|
"IPv6RoutePrefix\0"
|
||||||
|
"LLDP\0"
|
||||||
"TrafficControlQueueingDiscipline\0"
|
"TrafficControlQueueingDiscipline\0"
|
||||||
"CAN\0"
|
"CAN\0"
|
||||||
"QDisc\0"
|
"QDisc\0"
|
||||||
|
@ -726,6 +727,8 @@ static Network *network_free(Network *network) {
|
||||||
|
|
||||||
set_free_free(network->dnssec_negative_trust_anchors);
|
set_free_free(network->dnssec_negative_trust_anchors);
|
||||||
|
|
||||||
|
free(network->lldp_mud);
|
||||||
|
|
||||||
ordered_hashmap_free(network->dhcp_client_send_options);
|
ordered_hashmap_free(network->dhcp_client_send_options);
|
||||||
ordered_hashmap_free(network->dhcp_client_send_vendor_options);
|
ordered_hashmap_free(network->dhcp_client_send_vendor_options);
|
||||||
ordered_hashmap_free(network->dhcp_server_send_options);
|
ordered_hashmap_free(network->dhcp_server_send_options);
|
||||||
|
|
|
@ -258,8 +258,10 @@ struct Network {
|
||||||
bool required_for_online; /* Is this network required to be considered online? */
|
bool required_for_online; /* Is this network required to be considered online? */
|
||||||
LinkOperationalStateRange required_operstate_for_online;
|
LinkOperationalStateRange required_operstate_for_online;
|
||||||
|
|
||||||
|
/* LLDP support */
|
||||||
LLDPMode lldp_mode; /* LLDP reception */
|
LLDPMode lldp_mode; /* LLDP reception */
|
||||||
LLDPEmit lldp_emit; /* LLDP transmission */
|
LLDPEmit lldp_emit; /* LLDP transmission */
|
||||||
|
char *lldp_mud; /* LLDP MUD URL */
|
||||||
|
|
||||||
LIST_HEAD(Address, static_addresses);
|
LIST_HEAD(Address, static_addresses);
|
||||||
LIST_HEAD(Route, static_routes);
|
LIST_HEAD(Route, static_routes);
|
||||||
|
|
|
@ -96,6 +96,9 @@ enum {
|
||||||
#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
|
#define SD_LLDP_OUI_802_1 (uint8_t[]) { 0x00, 0x80, 0xc2 }
|
||||||
#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
|
#define SD_LLDP_OUI_802_3 (uint8_t[]) { 0x00, 0x12, 0x0f }
|
||||||
|
|
||||||
|
#define SD_LLDP_OUI_MUD (uint8_t[]) { 0x00, 0x00, 0x5E }
|
||||||
|
#define SD_LLDP_OUI_SUBTYPE_MUD_USAGE_DESCRIPTION 0x01
|
||||||
|
|
||||||
/* IEEE 802.1AB-2009 Annex E */
|
/* IEEE 802.1AB-2009 Annex E */
|
||||||
enum {
|
enum {
|
||||||
SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1,
|
SD_LLDP_OUI_802_1_SUBTYPE_PORT_VLAN_ID = 1,
|
||||||
|
@ -169,6 +172,7 @@ int sd_lldp_neighbor_get_ttl(sd_lldp_neighbor *n, uint16_t *ret_sec);
|
||||||
int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret);
|
int sd_lldp_neighbor_get_system_name(sd_lldp_neighbor *n, const char **ret);
|
||||||
int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret);
|
int sd_lldp_neighbor_get_system_description(sd_lldp_neighbor *n, const char **ret);
|
||||||
int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret);
|
int sd_lldp_neighbor_get_port_description(sd_lldp_neighbor *n, const char **ret);
|
||||||
|
int sd_lldp_neighbor_get_mud_url(sd_lldp_neighbor *n, const char **ret);
|
||||||
int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
|
int sd_lldp_neighbor_get_system_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
|
||||||
int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
|
int sd_lldp_neighbor_get_enabled_capabilities(sd_lldp_neighbor *n, uint16_t *ret);
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,8 @@ LifetimeSec=
|
||||||
EgressUntagged=
|
EgressUntagged=
|
||||||
VLAN=
|
VLAN=
|
||||||
PVID=
|
PVID=
|
||||||
|
[LLDP]
|
||||||
|
MUDURL=
|
||||||
[CAN]
|
[CAN]
|
||||||
SamplePoint=
|
SamplePoint=
|
||||||
BitRate=
|
BitRate=
|
||||||
|
|
Loading…
Reference in New Issue