Files
NetworkManager/src/core/dhcp/nm-dhcp-client.h
Thomas Haller 28d7f9b7c4 dhcp: drop NMDhcpClientClass.get_duid() hook
Note that there are no callers of nm_dhcp_client_get_effective_client_id(),
hence calling the setter had no effect. This is a bug, that we will fix
later.

But before fixing the bug, change how this works. Drop the get_duid() hook.
It's only confusing and backward.

We will keep the nm_dhcp_client_[gs]et_effective_client_id() functions.
They will be used later.
2022-12-19 11:29:11 +01:00

307 lines
11 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2005 - 2010 Red Hat, Inc.
*/
#ifndef __NETWORKMANAGER_DHCP_CLIENT_H__
#define __NETWORKMANAGER_DHCP_CLIENT_H__
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
#include "nm-dhcp-utils.h"
#define NM_DHCP_TIMEOUT_DEFAULT ((guint32) 45) /* default DHCP timeout, in seconds */
#define NM_DHCP_TIMEOUT_INFINITY ((guint32) G_MAXINT32)
#define NM_TYPE_DHCP_CLIENT (nm_dhcp_client_get_type())
#define NM_DHCP_CLIENT(obj) \
(_NM_G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_CLIENT, NMDhcpClient))
#define NM_DHCP_CLIENT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_CLIENT, NMDhcpClientClass))
#define NM_IS_DHCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_CLIENT))
#define NM_IS_DHCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_CLIENT))
#define NM_DHCP_CLIENT_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_CLIENT, NMDhcpClientClass))
#define NM_DHCP_CLIENT_CONFIG "config"
#define NM_DHCP_CLIENT_NOTIFY "dhcp-notify"
typedef enum {
NM_DHCP_CLIENT_EVENT_TYPE_UNSPECIFIED,
NM_DHCP_CLIENT_EVENT_TYPE_BOUND,
NM_DHCP_CLIENT_EVENT_TYPE_EXTENDED,
NM_DHCP_CLIENT_EVENT_TYPE_TIMEOUT,
NM_DHCP_CLIENT_EVENT_TYPE_EXPIRE,
NM_DHCP_CLIENT_EVENT_TYPE_FAIL,
NM_DHCP_CLIENT_EVENT_TYPE_TERMINATED,
} NMDhcpClientEventType;
typedef enum _nm_packed {
NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE,
/* When NM_DHCP_CLIENT_NO_LEASE_TIMEOUT expired and the state
* switched from NM_DHCP_CLIENT_STATE_NO_LEASE to
* NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT. */
NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT,
/* NMDhcpClient will indefinitely try to get/renew the lease.
* As such, it's never officially in a non-recoverable state.
* However, there are cases when it really looks like we won't
* be able to get a lease. For example, if the underlying interface
* is layer 3 only, if we have no IPv6 link local address for a prolonged
* time, or if dhclient is not installed.
* But even these cases are potentially recoverable. This is only
* a hint to the user (which they might ignore).
*
* In particular, NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT might mean
* that the DHCP is currently not running, but that could change
* at any moment and from client's side, it does not look bad. */
NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD,
NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED,
} NMDhcpClientNotifyType;
typedef struct {
NMDhcpClientNotifyType notify_type;
union {
struct {
/* This is either the new lease information we just received,
* or NULL (if a previous lease timed out). It can also be the
* previous lease, that was injected. */
const NML3ConfigData *l3cd;
bool accepted;
} lease_update;
struct {
const NMPlatformIP6Address *prefix;
} prefix_delegated;
struct {
const char *reason;
} it_looks_bad;
};
} NMDhcpClientNotifyData;
const char *nm_dhcp_client_event_type_to_string(NMDhcpClientEventType client_event_type);
typedef struct {
int addr_family;
/* The NML3Cfg instance is the manager object for the ifindex on which
* NMDhcpClient is supposed to run. */
NML3Cfg *l3cfg;
/* FIXME(l3cfg:dhcp:previous-lease): most parameters of NMDhcpClient are immutable,
* so to change them (during reapply), we need to create and start
* a new NMDhcpClient instance.
*
* However, while the restart happens, we want to stick to the previous
* lease (if any). Allow the caller to provide such a previous lease,
* and if present, the instance starts by pretending that it just received
* this lease, before really starting. */
const NML3ConfigData *previous_lease;
const char *iface;
/* The hardware address */
GBytes *hwaddr;
/* The broadcast hardware address */
GBytes *bcast_hwaddr;
/* Timeout in seconds before reporting failure */
guint32 timeout;
/* Flags for the hostname and FQDN DHCP options */
NMDhcpHostnameFlags hostname_flags;
/* The UUID of the connection. Used mainly to build
* lease file names. */
const char *uuid;
/* Set to reduce the number of broadcast packets when the
* anycast hardware address of the DHCP service is known. */
const char *anycast_address;
/* The hostname or FQDN to send. */
const char *hostname;
/* The Manufacturer Usage Description (RFC 8520) URL to send */
const char *mud_url;
/* The value for the Vendor Class Identifier option */
GBytes *vendor_class_identifier;
/* A list of servers from which offers should be rejected */
const char *const *reject_servers;
/* The client identifier (DHCPv4) or DUID (DHCPv6) to send */
GBytes *client_id;
/* Whether to send the hostname or FQDN option */
bool send_hostname : 1;
/* Whether to send the hostname as HOSTNAME option or FQDN.
* For DHCPv6 this is always TRUE. */
bool use_fqdn : 1;
union {
struct {
/* The address from the previous lease */
const char *last_address;
/* Whether to do ACD for the DHCPv4 address. With timeout zero, ACD
* is disabled. */
guint acd_timeout_msec;
/* Set BOOTP broadcast flag in request packets, so that servers
* will always broadcast replies. */
bool request_broadcast : 1;
} v4;
struct {
/* If set, the DUID from the connection is used; otherwise
* the one from an existing lease is used. */
gboolean enforce_duid;
/* The IAID to use */
guint32 iaid;
/* Whether the IAID was explicitly set in the connection or
* as global default */
gboolean iaid_explicit;
/* Number to prefixes (IA_PD) to request */
guint needed_prefixes;
/* Use Information-request to get stateless configuration
* parameters (don't request a IA_NA) */
bool info_only : 1;
} v6;
};
} NMDhcpClientConfig;
struct _NMDhcpClientPrivate;
typedef struct {
GObject parent;
struct _NMDhcpClientPrivate *_priv;
} NMDhcpClient;
typedef enum _nm_packed {
NM_DHCP_CLIENT_FLAGS_NONE = 0,
NM_DHCP_CLIENT_FLAGS_INFO_ONLY = (1LL << 0),
NM_DHCP_CLIENT_FLAGS_USE_FQDN = (1LL << 1),
NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST = (1LL << 2),
_NM_DHCP_CLIENT_FLAGS_LAST,
NM_DHCP_CLIENT_FLAGS_ALL = ((_NM_DHCP_CLIENT_FLAGS_LAST - 1) << 1) - 1,
} NMDhcpClientFlags;
typedef struct {
GObjectClass parent;
gboolean (*ip4_start)(NMDhcpClient *self, GError **error);
gboolean (*accept)(NMDhcpClient *self, const NML3ConfigData *l3cd, GError **error);
gboolean (*decline)(NMDhcpClient *self,
const NML3ConfigData *l3cd,
const char *error_message,
GError **error);
gboolean (*ip6_start)(NMDhcpClient *self, const struct in6_addr *ll_addr, GError **error);
void (*stop)(NMDhcpClient *self, gboolean release);
} NMDhcpClientClass;
GType nm_dhcp_client_get_type(void);
gboolean nm_dhcp_client_start(NMDhcpClient *self, GError **error);
const NMDhcpClientConfig *nm_dhcp_client_get_config(NMDhcpClient *self);
pid_t nm_dhcp_client_get_pid(NMDhcpClient *self);
static inline const NML3ConfigData *
nm_dhcp_client_get_lease(NMDhcpClient *self)
{
/* FIXME(l3cfg:dhcp:previous-lease): this function returns the currently
* valid, exposed lease.
*
* Note that NMDhcpClient should accept as construct argument a *previous* lease,
* and (if that lease is still valid), pretend that it's good to use. The point is
* so that during reapply we keep using the current address, until a new lease
* was received. */
return NULL;
}
void nm_dhcp_client_stop(NMDhcpClient *self, gboolean release);
/* Backend helpers for subclasses */
void nm_dhcp_client_stop_existing(const char *pid_file, const char *binary_name);
void nm_dhcp_client_stop_pid(pid_t pid, const char *iface);
void nm_dhcp_client_start_timeout(NMDhcpClient *self);
void nm_dhcp_client_watch_child(NMDhcpClient *self, pid_t pid);
void nm_dhcp_client_stop_watch_child(NMDhcpClient *self, pid_t pid);
void _nm_dhcp_client_notify(NMDhcpClient *self,
NMDhcpClientEventType client_event_type,
const NML3ConfigData *l3cd);
gboolean _nm_dhcp_client_accept_offer(NMDhcpClient *self, gconstpointer p_yiaddr);
gboolean nm_dhcp_client_handle_event(gpointer unused,
const char *iface,
int pid,
GVariant *options,
const char *reason,
GDBusMethodInvocation *invocation,
NMDhcpClient *self);
void nm_dhcp_client_emit_ipv6_prefix_delegated(NMDhcpClient *self,
const NMPlatformIP6Address *prefix);
gboolean nm_dhcp_client_server_id_is_rejected(NMDhcpClient *self, gconstpointer addr);
int nm_dhcp_client_get_addr_family(NMDhcpClient *self);
const char *nm_dhcp_client_get_iface(NMDhcpClient *self);
NMDedupMultiIndex *nm_dhcp_client_get_multi_idx(NMDhcpClient *self);
int nm_dhcp_client_get_ifindex(NMDhcpClient *self);
void nm_dhcp_client_set_effective_client_id(NMDhcpClient *self, GBytes *client_id);
GBytes *nm_dhcp_client_get_effective_client_id(NMDhcpClient *self);
NML3ConfigData *nm_dhcp_client_create_l3cd(NMDhcpClient *self);
/*****************************************************************************
* Client data
*****************************************************************************/
typedef struct {
GType (*get_type_4)(void);
GType (*get_type_6)(void);
const char *name;
const char *(*get_path)(void);
/* whether this plugin is an undocumented, internal plugin. */
bool undocumented : 1;
} NMDhcpClientFactory;
GType nm_dhcp_nettools_get_type(void);
extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcanon;
extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhclient;
extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcd;
extern const NMDhcpClientFactory _nm_dhcp_client_factory_internal;
extern const NMDhcpClientFactory _nm_dhcp_client_factory_systemd;
extern const NMDhcpClientFactory _nm_dhcp_client_factory_nettools;
#endif /* __NETWORKMANAGER_DHCP_CLIENT_H__ */