Systemd/src/libsystemd-network/dhcp-identifier.h

63 lines
2.1 KiB
C
Raw Normal View History

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "sd-id128.h"
#include "macro.h"
#include "sparse-endian.h"
#include "time-util.h"
#include "unaligned.h"
sd-network: DHCPv6 - Add support to send vendor class data ``` 21.16. Vendor Class Option This option is used by a client to identify the vendor that manufactured the hardware on which the client is running. The information contained in the data area of this option is contained in one or more opaque fields that identify details of the hardware configuration. The format of the Vendor Class option is: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | OPTION_VENDOR_CLASS | option-len | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | enterprise-number | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ . . . vendor-class-data . . . . . . +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Figure 28: Vendor Class Option Format option-code OPTION_VENDOR_CLASS (16). option-len 4 + length of vendor-class-data field. enterprise-number The vendor's registered Enterprise Number as maintained by IANA [IANA-PEN]. A 4-octet field containing an unsigned integer. vendor-class-data The hardware configuration of the node on which the client is running. A variable-length field (4 octets less than the value in the option-len field). The vendor-class-data field is composed of a series of separate items, each of which describes some characteristic of the client's hardware configuration. Examples of vendor-class-data instances might include the version of the operating system the client is running or the amount of memory installed on the client. Each instance of vendor-class-data is formatted as follows: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+ | vendor-class-len | opaque-data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+ Figure 29: Format of vendor-class-data Field The vendor-class-len field is 2 octets long and specifies the length of the opaque vendor-class-data in network byte order. Servers and clients MUST NOT include more than one instance of OPTION_VENDOR_CLASS with the same Enterprise Number. Each instance of OPTION_VENDOR_CLASS can carry multiple vendor-class-data instances. ```
2020-04-20 09:04:58 +02:00
#define SYSTEMD_PEN 43793
2016-03-31 01:33:55 +02:00
typedef enum DUIDType {
DUID_TYPE_LLT = 1,
DUID_TYPE_EN = 2,
DUID_TYPE_LL = 3,
DUID_TYPE_UUID = 4,
_DUID_TYPE_MAX,
_DUID_TYPE_INVALID = -1,
} DUIDType;
/* RFC 3315 section 9.1:
* A DUID can be no more than 128 octets long (not including the type code).
*/
#define MAX_DUID_LEN 128
/* https://tools.ietf.org/html/rfc3315#section-9.1 */
struct duid {
2016-03-31 01:33:55 +02:00
be16_t type;
union {
struct {
/* DUID_TYPE_LLT */
be16_t htype;
be32_t time;
uint8_t haddr[0];
} _packed_ llt;
struct {
/* DUID_TYPE_EN */
be32_t pen;
uint8_t id[8];
} _packed_ en;
struct {
/* DUID_TYPE_LL */
be16_t htype;
uint8_t haddr[0];
} _packed_ ll;
struct {
/* DUID_TYPE_UUID */
sd_id128_t uuid;
} _packed_ uuid;
struct {
uint8_t data[MAX_DUID_LEN];
} _packed_ raw;
};
} _packed_;
dhcp6: don't enforce DUID content for sd_dhcp6_client_set_duid() There are various functions to set the DUID of a DHCPv6 client. However, none of them allows to set arbitrary data. The closest is sd_dhcp6_client_set_duid(), which would still do validation of the DUID's content via dhcp_validate_duid_len(). Relax the validation and only log a debug message if the DUID does not validate. Note that dhcp_validate_duid_len() already is not very strict. For example with DUID_TYPE_LLT it only ensures that the length is suitable to contain hwtype and time. It does not further check that the length of hwaddr is non-zero or suitable for hwtype. Also, non-well-known DUID types are accepted for extensibility. Why reject certain DUIDs but allowing clearly wrong formats otherwise? The validation and failure should happen earlier, when accepting the unsuitable DUID. At that point, there is more context of what is wrong, and a better failure reason (or warning) can be reported to the user. Rejecting the DUID when setting up the DHCPv6 client seems not optimal, in particular because the DHCPv6 client does not care about actual content of the DUID and treats it as opaque blob. Also, NetworkManager (which uses this code) allows to configure the entire binary DUID in binary. It intentionally does not validate the binary content any further. Hence, it needs to be able to set _invalid_ DUIDs, provided that some basic constraints are satisfied (like the maximum length). sd_dhcp6_client_set_duid() has two callers: both set the DUID obtained from link_get_duid(), which comes from configuration. `man networkd.conf` says: "The configured DHCP DUID should conform to the specification in RFC 3315, RFC 6355.". It does not not state that it MUST conform. Note that dhcp_validate_duid_len() has another caller: DHCPv4's dhcp_client_set_iaid_duid_internal(). In this case, continue with strict validation, as the callers are more controlled. Also, there is already sd_dhcp_client_set_client_id() which can be used to bypass this check and set arbitrary client identifiers.
2018-12-20 11:56:02 +01:00
int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict);
int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len);
int dhcp_identifier_set_iaid(int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, void *_id);