nm-platform.h 76.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* nm-platform.c - Handle runtime kernel networking configuration
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
18
 * Copyright (C) 2009 - 2018 Red Hat, Inc.
19 20
 */

21 22
#ifndef __NETWORKMANAGER_PLATFORM_H__
#define __NETWORKMANAGER_PLATFORM_H__
23

24 25
#include "nm-dbus-interface.h"
#include "nm-core-types-internal.h"
26

27 28
#include "nm-core-utils.h"
#include "nm-setting-vlan.h"
29
#include "nm-setting-wired.h"
30
#include "nm-setting-wireless.h"
31
#include "nm-setting-ip-tunnel.h"
32

33 34 35 36 37 38 39
#define NM_TYPE_PLATFORM            (nm_platform_get_type ())
#define NM_PLATFORM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_PLATFORM, NMPlatform))
#define NM_PLATFORM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_PLATFORM, NMPlatformClass))
#define NM_IS_PLATFORM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_PLATFORM))
#define NM_IS_PLATFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_PLATFORM))
#define NM_PLATFORM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_PLATFORM, NMPlatformClass))

40 41
#define NM_PLATFORM_NETNS_SUPPORT_DEFAULT    FALSE

42
/*****************************************************************************/
43

44
#define NM_PLATFORM_NETNS_SUPPORT      "netns-support"
45
#define NM_PLATFORM_USE_UDEV           "use-udev"
46
#define NM_PLATFORM_LOG_WITH_PTR       "log-with-ptr"
47

48
/*****************************************************************************/
49

50 51 52 53 54 55
/* IFNAMSIZ is both defined in <linux/if.h> and <net/if.h>. In the past, these
 * headers conflicted, so we cannot simply include either of them in a header-file.*/
#define NMP_IFNAMSIZ 16

/*****************************************************************************/

56 57
struct _NMPWireGuardPeer;

58 59
struct udev_device;

60 61 62
typedef gboolean (*NMPObjectPredicateFunc) (const NMPObject *obj,
                                            gpointer user_data);

63 64 65 66 67 68 69 70
/* workaround for older libnl version, that does not define these flags. */
#ifndef IFA_F_MANAGETEMPADDR
#define IFA_F_MANAGETEMPADDR 0x100
#endif
#ifndef IFA_F_NOPREFIXROUTE
#define IFA_F_NOPREFIXROUTE 0x200
#endif

71 72
#define NM_RT_SCOPE_LINK                       253  /* RT_SCOPE_LINK */

73 74 75 76 77 78
/* Define of the IN6_ADDR_GEN_MODE_* values to workaround old kernel headers
 * that don't define it. */
#define NM_IN6_ADDR_GEN_MODE_UNKNOWN           255  /* no corresponding value.  */
#define NM_IN6_ADDR_GEN_MODE_EUI64             0    /* IN6_ADDR_GEN_MODE_EUI64 */
#define NM_IN6_ADDR_GEN_MODE_NONE              1    /* IN6_ADDR_GEN_MODE_NONE */
#define NM_IN6_ADDR_GEN_MODE_STABLE_PRIVACY    2    /* IN6_ADDR_GEN_MODE_STABLE_PRIVACY */
79
#define NM_IN6_ADDR_GEN_MODE_RANDOM            3    /* IN6_ADDR_GEN_MODE_RANDOM */
80

81 82
#define NM_IFF_MULTI_QUEUE                     0x0100 /* IFF_MULTI_QUEUE */

83 84 85
/* Redefine this in host's endianness */
#define NM_GRE_KEY      0x2000

86 87 88 89 90 91 92 93
typedef enum {
	/* use our own platform enum for the nlmsg-flags. Otherwise, we'd have
	 * to include <linux/netlink.h> */
	NMP_NLM_FLAG_F_REPLACE      = 0x100, /* NLM_F_REPLACE, Override existing */
	NMP_NLM_FLAG_F_EXCL         = 0x200, /* NLM_F_EXCL, Do not touch, if it exists */
	NMP_NLM_FLAG_F_CREATE       = 0x400, /* NLM_F_CREATE, Create, if it does not exist */
	NMP_NLM_FLAG_F_APPEND       = 0x800, /* NLM_F_APPEND, Add to end of list */

94 95 96 97 98 99 100 101 102
	NMP_NLM_FLAG_FMASK          = 0xFFFF, /* a mask for all NMP_NLM_FLAG_F_* flags */

	/* instructs NM to suppress logging an error message for any failures
	 * received from kernel.
	 *
	 * It will still log with debug-level, and it will still log
	 * other failures aside the kernel response. */
	NMP_NLM_FLAG_SUPPRESS_NETLINK_FAILURE = 0x10000,

103 104 105 106 107 108 109 110 111 112 113
	/* the following aliases correspond to iproute2's `ip route CMD` for
	 * RTM_NEWROUTE, with CMD being one of add, change, replace, prepend,
	 * append and test. */
	NMP_NLM_FLAG_ADD            = NMP_NLM_FLAG_F_CREATE                          | NMP_NLM_FLAG_F_EXCL,
	NMP_NLM_FLAG_CHANGE         =                         NMP_NLM_FLAG_F_REPLACE,
	NMP_NLM_FLAG_REPLACE        = NMP_NLM_FLAG_F_CREATE | NMP_NLM_FLAG_F_REPLACE,
	NMP_NLM_FLAG_PREPEND        = NMP_NLM_FLAG_F_CREATE,
	NMP_NLM_FLAG_APPEND         = NMP_NLM_FLAG_F_CREATE                                                | NMP_NLM_FLAG_F_APPEND,
	NMP_NLM_FLAG_TEST           =                                                  NMP_NLM_FLAG_F_EXCL,
} NMPNlmFlags;

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
typedef enum {
	/* compare fields which kernel considers as similar routes.
	 * It is a looser comparisong then NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID
	 * and means that `ip route add` would fail to add two routes
	 * that have the same NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID.
	 * On the other hand, `ip route append` would allow that, as
	 * long as NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID differs. */
	NM_PLATFORM_IP_ROUTE_CMP_TYPE_WEAK_ID,

	/* compare two routes as kernel would allow to add them with
	 * `ip route append`. In other words, kernel does not allow you to
	 * add two routes (at the same time) which compare equal according
	 * to NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID.
	 *
	 * For the ID we can only recognize route fields that we actually implement.
	 * However, kernel supports more routing options, some of them also part of
	 * the ID. NetworkManager is oblivious to these options and will wrongly think
	 * that two routes are idential, while they are not. That can lead to an
	 * inconsistent platform cache. Not much what we can do about that, except
	 * implementing all options that kernel supports *sigh*. See rh#1337860.
	 */
	NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID,

	/* compare all fields as they make sense for kernel. For example,
	 * a route destination 192.168.1.5/24 is not accepted by kernel and
	 * we treat it identical to 192.168.1.0/24. Semantically these
	 * routes are identical, but NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL will
141 142 143 144
	 * report them as different.
	 *
	 * The result shall be identical to call first nm_platform_ip_route_normalize()
	 * on both routes and then doing a full comparison. */
145 146 147 148 149 150 151 152 153
	NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY,

	/* compare all fields. This should have the same effect as memcmp(),
	 * except allowing for undefined data in holes between field alignment.
	 */
	NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL,

} NMPlatformIPRouteCmpType;

154 155 156 157 158 159 160 161
typedef enum {
	NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID,

	NM_PLATFORM_ROUTING_RULE_CMP_TYPE_SEMANTICALLY,

	NM_PLATFORM_ROUTING_RULE_CMP_TYPE_FULL,
} NMPlatformRoutingRuleCmpType;

162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
typedef enum {

	/* match-flags are strictly inclusive. That means,
	 * by default nothing is matched, but if you enable a particular
	 * flag, a candidate that matches passes the check.
	 *
	 * In other words: adding more flags can only extend the result
	 * set of matching objects.
	 *
	 * Also, the flags form partitions. Like, an address can be either of
	 * ADDRTYPE_NORMAL or ADDRTYPE_LINKLOCAL, but never both. Same for
	 * the ADDRSTATE match types.
	 */
	NM_PLATFORM_MATCH_WITH_NONE                                 = 0,

	NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL                      = (1LL <<  0),
	NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL                   = (1LL <<  1),
	NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY                        =   NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
	                                                              | NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL,

	NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL                     = (1LL <<  2),
	NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE                  = (1LL <<  3),
	NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED                  = (1LL <<  4),
	NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY                       =   NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL
	                                                              | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE
	                                                              | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DADFAILED,
} NMPlatformMatchFlags;

190 191
#define NM_PLATFORM_LINK_OTHER_NETNS    (-1)

192 193 194 195 196 197 198
struct _NMPlatformObject {
	/* the object type has no fields of its own, it is only used to having
	 * a special pointer type that can be used to indicate "any" type. */
	char _dummy_don_t_use_me;
};

#define __NMPlatformObjWithIfindex_COMMON \
199 200 201
	int ifindex; \
	;

202 203 204 205
struct _NMPlatformObjWithIfindex {
	__NMPlatformObjWithIfindex_COMMON;
};

206
struct _NMPlatformLink {
207
	__NMPlatformObjWithIfindex_COMMON;
208
	char name[NMP_IFNAMSIZ];
209
	NMLinkType type;
210

211 212
	/* rtnl_link_get_type(), IFLA_INFO_KIND. */
	/* NMPlatform initializes this field with a static string. */
213 214
	const char *kind;

215
	/* NMPlatform initializes this field with a static string. */
216
	const char *driver;
217

218
	int master;
219 220 221 222

	/* rtnl_link_get_link(), IFLA_LINK.
	 * If IFLA_LINK_NETNSID indicates that the parent is in another namespace,
	 * this field be set to (negative) NM_PLATFORM_LINK_OTHER_NETNS. */
223
	int parent;
224

225 226 227 228 229
	/* IFF_* flags. Note that the flags in 'struct ifinfomsg' are declared as 'unsigned'. */
	guint n_ifi_flags;

	guint mtu;

230 231 232
	/* rtnl_link_get_arptype(), ifinfomsg.ifi_type. */
	guint32 arptype;

233
	/* rtnl_link_get_addr(), IFLA_ADDRESS */
234 235 236 237 238
	struct {
		guint8 data[20]; /* NM_UTILS_HWADDR_LEN_MAX */
		guint8 len;
	} addr;

239 240
	/* rtnl_link_inet6_get_token(), IFLA_INET6_TOKEN */
	NMUtilsIPv6IfaceId inet6_token;
241

242 243 244 245 246
	/* The bitwise inverse of rtnl_link_inet6_get_addr_gen_mode(). It is inverse
	 * to have a default of 0 -- meaning: unspecified. That way, a struct
	 * initialized with memset(0) has and unset value.*/
	guint8 inet6_addr_gen_mode_inv;

247 248 249 250 251 252
	/* Statistics */
	guint64 rx_packets;
	guint64 rx_bytes;
	guint64 tx_packets;
	guint64 tx_bytes;

253
	/* @connected is mostly identical to (@n_ifi_flags & IFF_UP). Except for bridge/bond masters,
254
	 * where we coerce the link as disconnect if it has no slaves. */
255
	bool connected:1;
256

257
	bool initialized:1;
258
};
259

260 261 262 263 264 265 266
typedef enum { /*< skip >*/
	NM_PLATFORM_SIGNAL_ID_NONE,
	NM_PLATFORM_SIGNAL_ID_LINK,
	NM_PLATFORM_SIGNAL_ID_IP4_ADDRESS,
	NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS,
	NM_PLATFORM_SIGNAL_ID_IP4_ROUTE,
	NM_PLATFORM_SIGNAL_ID_IP6_ROUTE,
267
	NM_PLATFORM_SIGNAL_ID_ROUTING_RULE,
268
	NM_PLATFORM_SIGNAL_ID_QDISC,
269
	NM_PLATFORM_SIGNAL_ID_TFILTER,
270 271 272 273 274
	_NM_PLATFORM_SIGNAL_ID_LAST,
} NMPlatformSignalIdType;

guint _nm_platform_signal_id_get (NMPlatformSignalIdType signal_type);

275
typedef enum {
276
	NM_PLATFORM_SIGNAL_NONE,
277 278 279 280 281
	NM_PLATFORM_SIGNAL_ADDED,
	NM_PLATFORM_SIGNAL_CHANGED,
	NM_PLATFORM_SIGNAL_REMOVED,
} NMPlatformSignalChangeType;

282 283
#define NM_PLATFORM_IP_ADDRESS_CAST(address) \
	NM_CONSTCAST (NMPlatformIPAddress, (address), NMPlatformIPXAddress, NMPlatformIP4Address, NMPlatformIP6Address)
284 285

#define __NMPlatformIPAddress_COMMON \
286
	__NMPlatformObjWithIfindex_COMMON; \
287
	NMIPConfigSource addr_source; \
288 289
	\
	/* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*().
290 291 292 293 294 295
	 *
	 * The rules are:
	 * 1 @lifetime==0: @timestamp and @preferred is irrelevant (but mostly set to 0 too). Such addresses
	 *   are permanent. This rule is so that unset addresses (calloc) are permanent by default.
	 * 2 @lifetime==@preferred==NM_PLATFORM_LIFETIME_PERMANENT: @timestamp is irrelevant (but mostly
	 *   set to 0). Such addresses are permanent.
luz.paz's avatar
luz.paz committed
296
	 * 3 Non permanent addresses should (almost) always have @timestamp > 0. 0 is not a valid timestamp
297 298
	 *   and never returned by nm_utils_get_monotonic_timestamp_s(). In this case @valid/@preferred
	 *   is anchored at @timestamp.
luz.paz's avatar
luz.paz committed
299
	 * 4 Non permanent addresses with @timestamp == 0 are implicitly anchored at *now*, thus the time
300 301 302 303 304 305
	 *   moves as time goes by. This is usually not useful, except e.g. nm_platform_ip[46]_address_add().
	 *
	 * Non permanent addresses from DHCP/RA might have the @timestamp set to the moment of when the
	 * lease was received. Addresses from kernel might have the @timestamp based on the last modification
	 * time of the addresses. But don't rely on this behaviour, the @timestamp is only defined for anchoring
	 * @lifetime and @preferred.
306 307 308 309
	 */ \
	guint32 timestamp; \
	guint32 lifetime;   /* seconds since timestamp */ \
	guint32 preferred;  /* seconds since timestamp */ \
310 311 312 313 314
	\
	/* ifa_flags in 'struct ifaddrmsg' from <linux/if_addr.h>, extended to 32 bit by
	 * IFA_FLAGS attribute. */ \
	guint32 n_ifa_flags; \
	\
315
	guint8 plen; \
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
	;

/**
 * NMPlatformIPAddress:
 *
 * Common parts of NMPlatformIP4Address and NMPlatformIP6Address.
 **/
typedef struct {
	__NMPlatformIPAddress_COMMON;
	union {
		guint8 address_ptr[1];
		guint32 __dummy_for_32bit_alignment;
	};
} NMPlatformIPAddress;

331 332 333 334
/**
 * NMPlatformIP4Address:
 * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_s()
 **/
335
struct _NMPlatformIP4Address {
336
	__NMPlatformIPAddress_COMMON;
337 338

	/* The local address IFA_LOCAL. */
339
	in_addr_t address;
340 341 342 343 344 345 346 347 348 349

	/* The IFA_ADDRESS PTP peer address. This field is rather important, because
	 * it constitutes the identifier for the IPv4 address (e.g. you can add two
	 * addresses that only differ by their peer's network-part.
	 *
	 * Beware that for most cases, NetworkManager doesn't want to set an explicit
	 * peer-address. Hoever, that corresponds to setting the peer address to @address
	 * itself. Leaving peer-address unset/zero, means explicitly setting the peer
	 * address to 0.0.0.0, which you probably don't want.
	 * */
350
	in_addr_t peer_address;  /* PTP peer address */
351

352
	char label[NMP_IFNAMSIZ];
353
};
354

355 356 357 358
/**
 * NMPlatformIP6Address:
 * @timestamp: timestamp as returned by nm_utils_get_monotonic_timestamp_s()
 **/
359
struct _NMPlatformIP6Address {
360
	__NMPlatformIPAddress_COMMON;
361
	struct in6_addr address;
362
	struct in6_addr peer_address;
363
};
364

365 366 367 368 369 370
typedef union {
	NMPlatformIPAddress  ax;
	NMPlatformIP4Address a4;
	NMPlatformIP6Address a6;
} NMPlatformIPXAddress;

371 372
#undef __NMPlatformIPAddress_COMMON

373 374 375 376 377 378 379 380 381
/* Default value for adding an IPv4 route. This is also what iproute2 does.
 * Note that contrary to IPv6, you can add routes with metric 0 and it is even
 * the default.
 */
#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 0

/* Default value for adding an IPv6 route. This is also what iproute2 does.
 * Adding an IPv6 route with metric 0, kernel translates to IP6_RT_PRIO_USER (1024). */
#define NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 1024
382

383 384 385 386
/* For IPv4, kernel adds a device route (subnet routes) with metric 0 when user
 * configures addresses. */
#define NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE 0

387
#define __NMPlatformIPRoute_COMMON \
388
	__NMPlatformObjWithIfindex_COMMON; \
389 390 391 392
	\
	/* The NMIPConfigSource. For routes that we receive from cache this corresponds
	 * to the rtm_protocol field (and is one of the NM_IP_CONFIG_SOURCE_RTPROT_* values).
	 * When adding a route, the source will be coerced to the protocol using
393 394 395 396 397 398 399 400 401
	 * nmp_utils_ip_config_source_coerce_to_rtprot().
	 *
	 * rtm_protocol is part of the primary key of an IPv4 route (meaning, you can add
	 * two IPv4 routes that only differ in their rtm_protocol. For IPv6, that is not
	 * the case.
	 *
	 * When deleting an IPv4/IPv6 route, the rtm_protocol field must match (even
	 * if it is not part of the primary key for IPv6) -- unless rtm_protocol is set
	 * to zero, in which case the first matching route (with proto ignored) is deleted. */ \
402
	NMIPConfigSource rt_source; \
403
	\
404
	guint8 plen; \
405
	\
406 407 408
	/* RTA_METRICS:
	 *
	 * For IPv4 routes, these properties are part of their
409
	 * ID (meaning: you can add otherwise idential IPv4 routes that
410 411 412
	 * only differ by the metric property).
	 * On the other hand, for IPv6 you cannot add two IPv6 routes that only differ
	 * by an RTA_METRICS property.
413
	 *
luz.paz's avatar
luz.paz committed
414
	 * When deleting a route, kernel seems to ignore the RTA_METRICS properties.
415 416 417
	 * That is a problem/bug for IPv4 because you cannot explicitly select which
	 * route to delete. Kernel just picks the first. See rh#1475642. */ \
	\
418 419 420 421 422 423 424
	/* RTA_METRICS.RTAX_LOCK (iproute2: "lock" arguments) */ \
	bool lock_window:1; \
	bool lock_cwnd:1; \
	bool lock_initcwnd:1; \
	bool lock_initrwnd:1; \
	bool lock_mtu:1; \
	\
425 426 427 428 429 430
	/* rtnh_flags
	 *
	 * Routes with rtm_flags RTM_F_CLONED are hidden by platform and
	 * do not exist from the point-of-view of platform users.
	 * Such a route is not alive, according to nmp_object_is_alive().
	 *
431
	 * NOTE: currently we ignore all flags except RTM_F_CLONED
432
	 * and RTNH_F_ONLINK.
433 434 435 436
	 * We also may not properly consider the flags as part of the ID
	 * in route-cmp. */ \
	unsigned r_rtm_flags; \
	\
437
	/* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \
438
	guint32 mss; \
439
	\
440
	/* RTA_METRICS.RTAX_WINDOW (iproute2: window) */ \
441
	guint32 window; \
442
	\
443
	/* RTA_METRICS.RTAX_CWND (iproute2: cwnd) */ \
444
	guint32 cwnd; \
445 446
	\
	/* RTA_METRICS.RTAX_INITCWND (iproute2: initcwnd) */ \
447
	guint32 initcwnd; \
448 449
	\
	/* RTA_METRICS.RTAX_INITRWND (iproute2: initrwnd) */ \
450
	guint32 initrwnd; \
451 452
	\
	/* RTA_METRICS.RTAX_MTU (iproute2: mtu) */ \
453
	guint32 mtu; \
454 455
	\
	\
456
	/* RTA_PRIORITY (iproute2: metric) */ \
457 458
	guint32 metric; \
	\
459 460 461 462
	/* rtm_table, RTA_TABLE.
	 *
	 * This is not the original table ID. Instead, 254 (RT_TABLE_MAIN) and
	 * zero (RT_TABLE_UNSPEC) are swapped, so that the default is the main
463
	 * table. Use nm_platform_route_table_coerce()/nm_platform_route_table_uncoerce(). */ \
464 465
	guint32 table_coerced; \
	\
466 467
	/*end*/

468 469 470 471 472 473 474 475
typedef struct {
	__NMPlatformIPRoute_COMMON;
	union {
		guint8 network_ptr[1];
		guint32 __dummy_for_32bit_alignment;
	};
} NMPlatformIPRoute;

476 477 478
#define NM_PLATFORM_IP_ROUTE_CAST(route) \
	NM_CONSTCAST (NMPlatformIPRoute, (route), NMPlatformIPXRoute, NMPlatformIP4Route, NMPlatformIP6Route)

479
#define NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route) \
480
	(NM_PLATFORM_IP_ROUTE_CAST (route)->plen <= 0)
481

482
struct _NMPlatformIP4Route {
483
	__NMPlatformIPRoute_COMMON;
484
	in_addr_t network;
485 486

	/* RTA_GATEWAY. The gateway is part of the primary key for a route */
487
	in_addr_t gateway;
488

489 490 491 492
	/* RTA_PREFSRC (called "src" by iproute2).
	 *
	 * pref_src is part of the ID of an IPv4 route. When deleting a route,
	 * pref_src must match, unless set to 0.0.0.0 to match any. */
493
	in_addr_t pref_src;
494

495 496 497 498 499 500 501
	/* rtm_tos (iproute2: tos)
	 *
	 * For IPv4, tos is part of the weak-id (like metric).
	 *
	 * For IPv6, tos is ignored by kernel.  */
	guint8 tos;

502 503 504 505 506 507 508 509 510 511 512 513
	/* The bitwise inverse of the route scope rtm_scope. It is inverted so that the
	 * default value (RT_SCOPE_NOWHERE) is zero. Use nm_platform_route_scope_inv()
	 * to convert back and forth between the inverese representation and the
	 * real value.
	 *
	 * rtm_scope is part of the primary key for IPv4 routes. When deleting a route,
	 * the scope must match, unless it is left at RT_SCOPE_NOWHERE, in which case the first
	 * matching route is deleted.
	 *
	 * For IPv6 routes, the scope is ignored and kernel always assumes global scope.
	 * Hence, this field is only in NMPlatformIP4Route. */
	guint8 scope_inv;
514
};
515

516
struct _NMPlatformIP6Route {
517
	__NMPlatformIPRoute_COMMON;
518
	struct in6_addr network;
519 520

	/* RTA_GATEWAY. The gateway is part of the primary key for a route */
521
	struct in6_addr gateway;
522

523 524 525 526 527 528
	/* RTA_PREFSRC (called "src" by iproute2).
	 *
	 * pref_src is not part of the ID for an IPv6 route. You cannot add two
	 * routes that only differ by pref_src.
	 *
	 * When deleting a route, pref_src is ignored by kernel. */
529
	struct in6_addr pref_src;
530

531 532 533 534 535 536 537 538
	/* RTA_SRC and rtm_src_len (called "from" by iproute2).
	 *
	 * Kernel clears the host part of src/src_plen.
	 *
	 * src/src_plen is part of the ID of a route just like network/plen. That is,
	 * Not only `ip route append`, but also `ip route add` allows to add routes that only
	 * differ in their src/src_plen.
	 */
539 540
	struct in6_addr src;
	guint8 src_plen;
541 542 543 544 545 546

	/* RTA_PREF router preference.
	 *
	 * The type is guint8 to keep the struct size small. But the values are compatible with
	 * the NMIcmpv6RouterPref enum. */
	guint8 rt_pref;
547
};
548

549 550 551 552 553 554
typedef union {
	NMPlatformIPRoute  rx;
	NMPlatformIP4Route r4;
	NMPlatformIP6Route r6;
} NMPlatformIPXRoute;

555 556
#undef __NMPlatformIPRoute_COMMON

557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
typedef struct {
	/* struct fib_rule_uid_range */
	guint32 start;
	guint32 end;
} NMFibRuleUidRange;

typedef struct {
	/* struct fib_rule_port_range */
	guint16 start;
	guint16 end;
} NMFibRulePortRange;

typedef struct {
	NMIPAddr src;                        /* FRA_SRC */
	NMIPAddr dst;                        /* FRA_DST */
	guint64  tun_id;                     /* betoh64(FRA_TUN_ID) */
	guint32  table;                      /* (struct fib_rule_hdr).table, FRA_TABLE */
	guint32  flags;                      /* (struct fib_rule_hdr).flags */
	guint32  priority;                   /* RA_PRIORITY */
	guint32  fwmark;                     /* FRA_FWMARK */
	guint32  fwmask;                     /* FRA_FWMASK */
	guint32  goto_target;                /* FRA_GOTO */
	guint32  flow;                       /* FRA_FLOW */
	guint32  suppress_prefixlen_inverse; /* ~(FRA_SUPPRESS_PREFIXLEN) */
	guint32  suppress_ifgroup_inverse;   /* ~(FRA_SUPPRESS_IFGROUP) */
	NMFibRuleUidRange uid_range;         /* FRA_UID_RANGE */
	NMFibRulePortRange sport_range;      /* FRA_SPORT_RANGE */
	NMFibRulePortRange dport_range;      /* FRA_DPORT_RANGE */
	char     iifname[NMP_IFNAMSIZ];      /* FRA_IIFNAME */
	char     oifname[NMP_IFNAMSIZ];      /* FRA_OIFNAME */
	guint8   addr_family;                /* (struct fib_rule_hdr).family */
	guint8   action;                     /* (struct fib_rule_hdr).action */
	guint8   tos;                        /* (struct fib_rule_hdr).tos */
	guint8   src_len;                    /* (struct fib_rule_hdr).src_len */
	guint8   dst_len;                    /* (struct fib_rule_hdr).dst_len */
	guint8   l3mdev;                     /* FRA_L3MDEV */
	guint8   protocol;                   /* FRA_PROTOCOL */
	guint8   ip_proto;                   /* FRA_IP_PROTO */

	bool     uid_range_has:1;            /* has(FRA_UID_RANGE) */
} NMPlatformRoutingRule;

599 600
#define NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET   (~((guint32) 0))

601 602 603 604
#define NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED ((guint32) 0x83126E97u)

G_STATIC_ASSERT (((((guint64) NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED) * 1000u) >> 10) == (guint64) INT_MAX);

605 606 607 608 609 610
typedef struct {
	guint32 limit;
	guint32 flows;
	guint32 target;
	guint32 interval;
	guint32 quantum;
611 612 613 614 615 616 617
	guint32 ce_threshold; /* TCA_FQ_CODEL_CE_THRESHOLD: kernel internally stores this value as
	                       *   ((val64 * NSEC_PER_USEC) >> CODEL_SHIFT). The default value (in
	                       *   the domain with this coersion) is CODEL_DISABLED_THRESHOLD (INT_MAX).
	                       *   That means, "disabled" is expressed on RTM_NEWQDISC netlink API by absence of the
	                       *   netlink attribute but also as the special value 0x83126E97u
	                       *   (NM_PLATFORM_FQ_CODEL_CE_THRESHOLD_DISABLED).
	                       *   Beware: zero is not the default you must always explicitly set this value. */
618
	guint32 memory_limit; /* TCA_FQ_CODEL_MEMORY_LIMIT: note that only values <= 2^31 are accepted by kernel
619 620 621 622 623
	                       *   and kernel defaults to 32MB.
	                       *   Note that we use the special value NM_PLATFORM_FQ_CODEL_MEMORY_LIMIT_UNSET
	                       *   to indicate that no explicit limit is set (when we send a RTM_NEWQDISC request).
	                       *   This will cause kernel to choose the default (32MB).
	                       *   Beware: zero is not the default you must always explicitly set this value. */
624 625 626
	bool ecn:1;
} NMPlatformQdiscFqCodel;

627
typedef struct {
628
	__NMPlatformObjWithIfindex_COMMON;
629 630 631 632 633
	const char *kind;
	int addr_family;
	guint32 handle;
	guint32 parent;
	guint32 info;
634 635 636
	union {
		NMPlatformQdiscFqCodel fq_codel;
	};
637
} NMPlatformQdisc;
638

639 640 641 642
typedef struct {
	char sdata[32];
} NMPlatformActionSimple;

643 644
typedef struct {
	int ifindex;
645 646 647 648
	bool egress:1;
	bool ingress:1;
	bool mirror:1;
	bool redirect:1;
649 650
} NMPlatformActionMirred;

651 652 653 654
typedef struct {
	const char *kind;
	union {
		NMPlatformActionSimple simple;
655
		NMPlatformActionMirred mirred;
656 657 658
	};
} NMPlatformAction;

659
#define NM_PLATFORM_ACTION_KIND_SIMPLE "simple"
660
#define NM_PLATFORM_ACTION_KIND_MIRRED "mirred"
661

662
typedef struct {
663
	__NMPlatformObjWithIfindex_COMMON;
664 665 666 667 668 669 670 671
	const char *kind;
	int addr_family;
	guint32 handle;
	guint32 parent;
	guint32 info;
	NMPlatformAction action;
} NMPlatformTfilter;

672
#undef __NMPlatformObjWithIfindex_COMMON
673

674 675
typedef struct {
	gboolean is_ip4;
676
	NMPObjectType obj_type;
677 678
	int addr_family;
	gsize sizeof_route;
679
	int (*route_cmp) (const NMPlatformIPXRoute *a, const NMPlatformIPXRoute *b, NMPlatformIPRouteCmpType cmp_type);
680
	const char *(*route_to_string) (const NMPlatformIPXRoute *route, char *buf, gsize len);
681 682 683
	guint32 (*metric_normalize) (guint32 metric);
} NMPlatformVTableRoute;

684 685 686 687 688 689 690 691 692
typedef union {
	struct {
		NMPlatformVTableRoute v6;
		NMPlatformVTableRoute v4;
	};
	NMPlatformVTableRoute vx[2];
} _NMPlatformVTableRouteUnion;

extern const _NMPlatformVTableRouteUnion nm_platform_vtable_route;
693

694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
typedef struct {
	guint16 id;
	guint32 qos;
	bool proto_ad:1;
} NMPlatformVFVlan;

typedef struct {
	guint32 index;
	guint32 min_tx_rate;
	guint32 max_tx_rate;
	guint num_vlans;
	NMPlatformVFVlan *vlans;
	struct {
		guint8 data[20]; /* NM_UTILS_HWADDR_LEN_MAX */
		guint8 len;
	} mac;
	gint8 spoofchk;
	gint8 trust;
} NMPlatformVF;

714
typedef struct {
715 716
	guint16 vid_start;
	guint16 vid_end;
717 718 719 720
	bool untagged:1;
	bool pvid:1;
} NMPlatformBridgeVlan;

721
typedef struct {
722 723
	in_addr_t local;
	in_addr_t remote;
724 725 726 727 728 729 730
	int parent_ifindex;
	guint16 input_flags;
	guint16 output_flags;
	guint32 input_key;
	guint32 output_key;
	guint8 ttl;
	guint8 tos;
731
	bool path_mtu_discovery:1;
732
	bool is_tap:1;
733
} NMPlatformLnkGre;
734

735
typedef struct {
736
	int p_key;
737
	const char *mode;
738
} NMPlatformLnkInfiniband;
739

740 741 742
typedef struct {
	struct in6_addr local;
	struct in6_addr remote;
743
	int parent_ifindex;
744 745 746 747
	guint8 ttl;
	guint8 tclass;
	guint8 encap_limit;
	guint8 proto;
748
	guint flow_label;
749
	guint32 flags;
750 751 752 753 754 755 756 757

	/* IP6GRE only */
	guint32 input_key;
	guint32 output_key;
	guint16 input_flags;
	guint16 output_flags;
	bool is_tap:1;
	bool is_gre:1;
758 759
} NMPlatformLnkIp6Tnl;

760 761 762
typedef struct {
	in_addr_t local;
	in_addr_t remote;
763
	int parent_ifindex;
764 765
	guint8 ttl;
	guint8 tos;
766
	bool path_mtu_discovery:1;
767 768
} NMPlatformLnkIpIp;

769 770
typedef struct {
	int parent_ifindex;
771
	guint64 sci;                    /* host byte order */
772 773 774 775 776 777 778 779 780 781 782 783 784
	guint64 cipher_suite;
	guint32 window;
	guint8 icv_length;
	guint8 encoding_sa;
	guint8 validation;
	bool encrypt:1;
	bool protect:1;
	bool include_sci:1;
	bool es:1;
	bool scb:1;
	bool replay_protect:1;
} NMPlatformLnkMacsec;

785
typedef struct {
786
	guint mode;
787 788
	bool no_promisc:1;
	bool tap:1;
789
} NMPlatformLnkMacvlan;
790

791 792
typedef NMPlatformLnkMacvlan NMPlatformLnkMacvtap;

793 794 795
typedef struct {
	in_addr_t local;
	in_addr_t remote;
796
	int parent_ifindex;
797
	guint16 flags;
798 799 800
	guint8 ttl;
	guint8 tos;
	guint8 proto;
801
	bool path_mtu_discovery:1;
802 803
} NMPlatformLnkSit;

804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
typedef struct {
	guint32 owner;
	guint32 group;

	guint8 type;

	bool owner_valid:1;
	bool group_valid:1;

	bool pi:1;
	bool vnet_hdr:1;
	bool multi_queue:1;
	bool persist:1;
} NMPlatformLnkTun;

819 820 821
typedef struct {
	/* rtnl_link_vlan_get_id(), IFLA_VLAN_ID */
	guint16 id;
822
	NMVlanFlags flags;
823 824
} NMPlatformLnkVlan;

825 826 827
typedef struct {
	struct in6_addr group6;
	struct in6_addr local6;
828 829 830 831
	in_addr_t group;
	in_addr_t local;
	int parent_ifindex;
	guint32 id;
832 833 834 835 836
	guint32 ageing;
	guint32 limit;
	guint16 dst_port;
	guint16 src_port_min;
	guint16 src_port_max;
837 838 839 840 841 842 843
	guint8 tos;
	guint8 ttl;
	bool learning:1;
	bool proxy:1;
	bool rsc:1;
	bool l2miss:1;
	bool l3miss:1;
844
} NMPlatformLnkVxlan;
845

846 847 848
#define NMP_WIREGUARD_PUBLIC_KEY_LEN 32
#define NMP_WIREGUARD_SYMMETRIC_KEY_LEN 32

849 850
typedef struct {
	guint32 fwmark;
851 852 853
	guint16 listen_port;
	guint8 private_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
	guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
854
} NMPlatformLnkWireGuard;
855

856
typedef enum {
857
	NM_PLATFORM_LINK_DUPLEX_UNKNOWN,
858 859 860 861
	NM_PLATFORM_LINK_DUPLEX_HALF,
	NM_PLATFORM_LINK_DUPLEX_FULL,
} NMPlatformLinkDuplexType;

862
typedef enum {
863 864 865 866 867
	NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE                        = 0,
	NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS               = (1LL << 0),
	NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY             = (1LL << 1),
	NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_LISTEN_PORT             = (1LL << 2),
	NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_FWMARK                  = (1LL << 3),
868 869
} NMPlatformWireGuardChangeFlags;

870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885
typedef enum {
	NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_NONE                   = 0,
	NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REMOVE_ME              = (1LL << 0),
	NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY      = (1LL << 1),
	NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL = (1LL << 2),
	NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT           = (1LL << 3),
	NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS         = (1LL << 4),
	NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_REPLACE_ALLOWEDIPS     = (1LL << 5),

	NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_DEFAULT =   NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_PRESHARED_KEY
	                                                 | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_KEEPALIVE_INTERVAL
	                                                 | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ENDPOINT
	                                                 | NM_PLATFORM_WIREGUARD_CHANGE_PEER_FLAG_HAS_ALLOWEDIPS,

} NMPlatformWireGuardChangePeerFlags;

886
/*****************************************************************************/
887

888 889 890 891
typedef enum {
	NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS,
	NM_PLATFORM_KERNEL_SUPPORT_TYPE_USER_IPV6LL,
	NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF,
892
	NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV,
893
	NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE,
894
	NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_PROTOCOL,
895 896 897 898 899

	/* this also includes FRA_SPORT_RANGE and FRA_DPORT_RANGE which
	 * were added at the same time. */
	NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_IP_PROTO,

900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932
	_NM_PLATFORM_KERNEL_SUPPORT_NUM,
} NMPlatformKernelSupportType;

extern volatile int _nm_platform_kernel_support_state[_NM_PLATFORM_KERNEL_SUPPORT_NUM];

int _nm_platform_kernel_support_init (NMPlatformKernelSupportType type,
                                      int value);

#define _nm_platform_kernel_support_detected(type) \
	G_LIKELY (({ \
		const NMPlatformKernelSupportType _type = (type); \
		\
		nm_assert (_NM_INT_NOT_NEGATIVE (_type) && _type < G_N_ELEMENTS (_nm_platform_kernel_support_state)); \
		\
		(_nm_platform_kernel_support_state[_type] != 0); \
	}))

#define nm_platform_kernel_support_get(type) \
	({ \
		const NMPlatformKernelSupportType _type = (type); \
		int _v; \
		\
		nm_assert (_NM_INT_NOT_NEGATIVE (_type) && _type < G_N_ELEMENTS (_nm_platform_kernel_support_state)); \
		\
		_v = _nm_platform_kernel_support_state[_type]; \
		if (G_UNLIKELY (_v == 0)) \
			_v = _nm_platform_kernel_support_init (_type, 0); \
		\
		(_v >= 0); \
	})

/*****************************************************************************/

933 934
struct _NMPlatformPrivate;

935
struct _NMPlatform {
936
	GObject parent;
937
	NMPNetns *_netns;
938
	struct _NMPlatformPrivate *_priv;
939
};
940 941 942 943

typedef struct {
	GObjectClass parent;

944 945
	gboolean (*sysctl_set) (NMPlatform *, const char *pathid, int dirfd, const char *path, const char *value);
	char * (*sysctl_get) (NMPlatform *, const char *pathid, int dirfd, const char *path);
946

947 948 949 950 951 952 953 954
	int (*link_add) (NMPlatform *,
	                 const char *name,
	                 NMLinkType type,
	                 const char *veth_peer,
	                 const void *address,
	                 size_t address_len,
	                 const NMPlatformLink **out_link);

955
	gboolean (*link_delete) (NMPlatform *, int ifindex);
956

957
	gboolean (*link_refresh) (NMPlatform *, int ifindex);
958 959 960

	gboolean (*link_set_netns) (NMPlatform *, int ifindex, int netns_fd);

961
	void (*process_events) (NMPlatform *self);
962

963
	gboolean (*link_set_up) (NMPlatform *, int ifindex, gboolean *out_no_firmware);
964 965 966
	gboolean (*link_set_down) (NMPlatform *, int ifindex);
	gboolean (*link_set_arp) (NMPlatform *, int ifindex);
	gboolean (*link_set_noarp) (NMPlatform *, int ifindex);
967

968
	const char *(*link_get_udi) (NMPlatform *self, int ifindex);
969
	struct udev_device *(*link_get_udev_device) (NMPlatform *self, int ifindex);
970

971
	int (*link_set_user_ipv6ll_enabled) (NMPlatform *, int ifindex, gboolean enabled);
972
	gboolean (*link_set_token) (NMPlatform *, int ifindex, NMUtilsIPv6IfaceId iid);
973

974 975 976 977
	gboolean (*link_get_permanent_address) (NMPlatform *,
	                                        int ifindex,
	                                        guint8 *buf,
	                                        size_t *length);
978 979
	int (*link_set_address) (NMPlatform *, int ifindex, gconstpointer address, size_t length);
	int (*link_set_mtu) (NMPlatform *, int ifindex, guint32 mtu);
980
	gboolean (*link_set_name) (NMPlatform *, int ifindex, const char *name);
981
	gboolean (*link_set_sriov_params) (NMPlatform *, int ifindex, guint num_vfs, int autoprobe);
982
	gboolean (*link_set_sriov_vfs) (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs);
983
	gboolean (*link_set_bridge_vlans) (NMPlatform *self, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans);
984

985 986
	char *   (*link_get_physical_port_id) (NMPlatform *, int ifindex);
	guint    (*link_get_dev_id) (NMPlatform *, int ifindex);
987
	gboolean (*link_get_wake_on_lan) (NMPlatform *, int ifindex);
988 989 990 991 992
	gboolean (*link_get_driver_info) (NMPlatform *,
	                                  int ifindex,
	                                  char **out_driver_name,
	                                  char **out_driver_version,
	                                  char **out_fw_version);
993

994 995
	gboolean (*link_supports_carrier_detect) (NMPlatform *, int ifindex);
	gboolean (*link_supports_vlans) (NMPlatform *, int ifindex);
996
	gboolean (*link_supports_sriov) (NMPlatform *, int ifindex);
997

998 999 1000
	gboolean (*link_enslave) (NMPlatform *, int master, int slave);
	gboolean (*link_release) (NMPlatform *, int master, int slave);

1001 1002
	gboolean (*link_can_assume) (NMPlatform *, int ifindex);

1003 1004 1005 1006
	int (*link_wireguard_change) (NMPlatform *self,
	                              int ifindex,
	                              const NMPlatformLnkWireGuard *lnk_wireguard,
	                              const struct _NMPWireGuardPeer *peers,
1007
	                              const NMPlatformWireGuardChangePeerFlags *peer_flags,
1008
	                              guint peers_len,
1009
	                              NMPlatformWireGuardChangeFlags change_flags);
1010

1011
	gboolean (*vlan_add) (NMPlatform *, const char *name, int parent, int vlanid, guint32 vlanflags, const NMPlatformLink **out_link);
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
	gboolean (*link_vlan_change) (NMPlatform *self,
	                              int ifindex,
	                              NMVlanFlags flags_mask,
	                              NMVlanFlags flags_set,
	                              gboolean ingress_reset_all,
	                              const NMVlanQosMapping *ingress_map,
	                              gsize n_ingress_map,
	                              gboolean egress_reset_all,
	                              const NMVlanQosMapping *egress_map,
	                              gsize n_egress_map);
1022 1023 1024
	gboolean (*link_vxlan_add) (NMPlatform *,
	                            const char *name,
	                            const NMPlatformLnkVxlan *props,
1025
	                            const NMPlatformLink **out_link);
1026 1027 1028
	gboolean (*link_gre_add) (NMPlatform *,
	                          const char *name,
	                          const NMPlatformLnkGre *props,
1029
	                          const NMPlatformLink **out_link);
1030 1031 1032
	gboolean (*link_ip6tnl_add) (NMPlatform *,
	                             const char *name,
	                             const NMPlatformLnkIp6Tnl *props,
1033
	                             const NMPlatformLink **out_link);
1034 1035 1036 1037
	gboolean (*link_ip6gre_add) (NMPlatform *,
	                             const char *name,
	                             const NMPlatformLnkIp6Tnl *props,
	                             const NMPlatformLink **out_link);
1038 1039 1040
	gboolean (*link_ipip_add) (NMPlatform *,
	                           const char *name,
	                           const NMPlatformLnkIpIp *props,
1041
	                           const NMPlatformLink **out_link);
1042 1043 1044 1045 1046
	gboolean (*link_macsec_add) (NMPlatform *,
	                             const char *name,
	                             int parent,
	                             const NMPlatformLnkMacsec *props,
	                             const NMPlatformLink **out_link);
1047 1048 1049 1050
	gboolean (*link_macvlan_add) (NMPlatform *,
	                              const char *name,
	                              int parent,
	                              const NMPlatformLnkMacvlan *props,
1051
	                              const NMPlatformLink **out_link);
1052 1053 1054
	gboolean (*link_sit_add) (NMPlatform *,
	                          const char *name,
	                          const NMPlatformLnkSit *props,
1055
	                          const NMPlatformLink **out_link);
1056

1057 1058 1059
	gboolean (*link_tun_add) (NMPlatform *platform,
	                          const char *name,
	                          const NMPlatformLnkTun *props,
1060 1061
	                          const NMPlatformLink **out_link,
	                          int *out_fd);
1062

1063 1064 1065 1066 1067
	gboolean (*link_6lowpan_add) (NMPlatform *platform,
	                              const char *name,
	                              int parent,
	                              const NMPlatformLink **out_link);

1068
	gboolean (*infiniband_partition_add) (NMPlatform *, int parent, int p_key, const NMPlatformLink **out_link);
1069
	gboolean (*infiniband_partition_delete) (NMPlatform *, int parent, int p_key);
1070

1071
	gboolean    (*wifi_get_capabilities) (NMPlatform *, int ifindex, NMDeviceWifiCapabilities *caps);
1072
	gboolean    (*wifi_get_bssid)        (NMPlatform *, int ifindex, guint8 *bssid);
1073 1074 1075 1076 1077
	guint32     (*wifi_get_frequency)    (NMPlatform *, int ifindex);
	int         (*wifi_get_quality)      (NMPlatform *, int ifindex);
	guint32     (*wifi_get_rate)         (NMPlatform *, int ifindex);
	NM80211Mode (*wifi_get_mode)         (NMPlatform *, int ifindex);
	void        (*wifi_set_mode)         (NMPlatform *, int ifindex, NM80211Mode mode);
1078
	void        (*wifi_set_powersave)    (NMPlatform *, int ifindex, guint32 powersave);
1079 1080
	guint32     (*wifi_find_frequency)   (NMPlatform *, int ifindex, const guint32 *freqs);
	void        (*wifi_indicate_addressing_running) (NMPlatform *, int ifindex, gboolean running);
1081
	NMSettingWirelessWakeOnWLan (*wifi_get_wake_on_wlan) (NMPlatform *, int ifindex);
1082
	gboolean    (*wifi_set_wake_on_wlan) (NMPlatform *, int ifindex, NMSettingWirelessWakeOnWLan wowl);
1083 1084 1085

	guint32     (*mesh_get_channel)      (NMPlatform *, int ifindex);
	gboolean    (*mesh_set_channel)      (NMPlatform *, int ifindex, guint32 channel);
1086
	gboolean    (*mesh_set_ssid)         (NMPlatform *, int ifindex, const guint8 *ssid, gsize len);
1087

1088 1089 1090 1091
	guint16     (*wpan_get_pan_id)       (NMPlatform *, int ifindex);
	gboolean    (*wpan_set_pan_id)       (NMPlatform *, int ifindex, guint16 pan_id);
	guint16     (*wpan_get_short_addr)   (NMPlatform *, int ifindex);
	gboolean    (*wpan_set_short_addr)   (NMPlatform *, int ifindex, guint16 short_addr);
1092
	gboolean    (*wpan_set_channel)      (NMPlatform *, int ifindex, guint8 page, guint8 channel);
1093

1094 1095
	gboolean (*object_delete) (NMPlatform *, const NMPObject *obj);

1096 1097 1098
	gboolean (*ip4_address_add) (NMPlatform *,
	                             int ifindex,
	                             in_addr_t address,
1099
	                             guint8 plen,
1100 1101 1102
	                             in_addr_t peer_address,
	                             guint32 lifetime,
	                             guint32 preferred_lft,
1103
	                             guint32 flags,
1104
	                             const char *label);
1105 1106 1107
	gboolean (*ip6_address_add) (NMPlatform *,
	                             int ifindex,
	                             struct in6_addr address,
1108
	                             guint8 plen,
1109 1110 1111
	                             struct in6_addr peer_address,
	                             guint32 lifetime,
	                             guint32 preferred_lft,
1112
	                             guint32 flags);
1113 1114
	gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
	gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, guint8 plen);
1115

1116 1117 1118 1119 1120 1121 1122 1123 1124
	int (*ip_route_add) (NMPlatform *,
	                     NMPNlmFlags flags,
	                     int addr_family,
	                     const NMPlatformIPRoute *route);
	int (*ip_route_get) (NMPlatform *self,
	                     int addr_family,
	                     gconstpointer address,
	                     int oif_ifindex,
	                     NMPObject **out_route);
1125

1126 1127 1128 1129
	int (*routing_rule_add) (NMPlatform *self,
	                         NMPNlmFlags flags,
	                         const NMPlatformRoutingRule *routing_rule);

1130 1131 1132
	int (*qdisc_add)   (NMPlatform *self,
	                    NMPNlmFlags flags,
	                    const NMPlatformQdisc *qdisc);
1133

1134 1135 1136
	int (*tfilter_add)   (NMPlatform *self,
	                      NMPNlmFlags flags,
	                      const NMPlatformTfilter *tfilter);
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
} NMPlatformClass;

/* NMPlatform signals
 *
 * Each signal handler is called with a type-specific object that provides
 * key attributes that constitute identity of the object. They may also
 * provide additional attributes for convenience.
 *
 * The object only intended to be used by the signal handler to determine
 * the current values. It is no longer valid after the signal handler exits
 * but you are free to copy the provided information and use it for later
 * reference.
 */
1150 1151 1152 1153 1154
#define NM_PLATFORM_SIGNAL_LINK_CHANGED "link-changed"
#define NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED "ip4-address-changed"
#define NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED "ip6-address-changed"
#define NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED "ip4-route-changed"
#define NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED "ip6-route-changed"
1155
#define NM_PLATFORM_SIGNAL_ROUTING_RULE_CHANGED "routing-rule-changed"
1156
#define NM_PLATFORM_SIGNAL_QDISC_CHANGED "qdisc-changed"
1157
#define NM_PLATFORM_SIGNAL_TFILTER_CHANGED "tfilter-changed"
1158

1159 1160
const char *nm_platform_signal_change_type_to_string (NMPlatformSignalChangeType change_type);

1161
/*****************************************************************************/
1162 1163 1164

GType nm_platform_get_type (void);

1165
void nm_platform_setup (NMPlatform *instance);
1166 1167
NMPlatform *nm_platform_get (void);

1168 1169
#define NM_PLATFORM_GET (nm_platform_get ())

1170
/*****************************************************************************/
1171

1172 1173
/**
 * nm_platform_route_table_coerce:
1174 1175
 * @table: the route table, in its original value as received
 *   from rtm_table/RTA_TABLE.
1176
 *
1177 1178
 * Returns: returns the coerced table id, that can be stored in
 *   NMPlatformIPRoute.table_coerced.
1179 1180 1181 1182
 */
static inline guint32
nm_platform_route_table_coerce (guint32 table)
{
1183 1184 1185 1186 1187 1188
	/* For kernel, the default table is RT_TABLE_MAIN (254).
	 * We want that in NMPlatformIPRoute.table_coerced a numeric
	 * zero is the default. Hence, @table_coerced swaps the
	 * value 0 and 254. Use nm_platform_route_table_coerce()
	 * and nm_platform_route_table_uncoerce() to convert between
	 * the two domains. */
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
	switch (table) {
	case 0 /* RT_TABLE_UNSPEC */:
		return 254;
	case 254 /* RT_TABLE_MAIN */:
		return 0;
	default:
		return table;
	}
}

1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
/**
 * nm_platform_route_table_uncoerce:
 * @table: the route table, in its coerced value
 * @normalize: whether to normalize RT_TABLE_UNSPEC to
 *   RT_TABLE_MAIN. For kernel, routes with a table id
 *   RT_TABLE_UNSPEC do not exist and are treated like
 *   RT_TABLE_MAIN.
 *
 * Returns: reverts the coerced table ID in NMPlatformIPRoute.table_coerced
 *   to the original value as kernel understands it.
 */
static inline guint32
nm_platform_route_table_uncoerce (guint32 table_coerced, gboolean normalize)
{
	/* this undoes nm_platform_route_table_coerce().  */
	switch (table_coerced) {
	case 0 /* RT_TABLE_UNSPEC */:
		return 254;
	case 254 /* RT_TABLE_MAIN */:
		return normalize ? 254 : 0;
	default:
		return table_coerced;
	}
}

static inline gboolean
nm_platform_route_table_is_main (guint32 table)
{
	/* same as
	 *   nm_platform_route_table_uncoerce (table, TRUE) == RT_TABLE_MAIN
	 * and
	 *   nm_platform_route_table_uncoerce (nm_platform_route_table_coerce (table), TRUE) == RT_TABLE_MAIN
	 *
	 * That is, the function operates the same on @table and its coerced
	 * form.
	 */
	return table == 0 || table == 254;
}

1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
/**
 * nm_platform_route_scope_inv:
 * @scope: the route scope, either its original value, or its inverse.
 *
 * This function is useful, because the constants such as RT_SCOPE_NOWHERE
 * are 'int', so ~scope also gives an 'int'. This function gets the type
 * casts to guint8 right.
 *
 * Returns: the bitwise inverse of the route scope.
 * */
1248
#define nm_platform_route_scope_inv _nm_platform_uint8_inv
1249
static inline guint8
1250
_nm_platform_uint8_inv (guint8 scope)
1251 1252 1253 1254
{
	return (guint8) ~scope;
}

1255
gboolean nm_platform_get_use_udev (NMPlatform *self);
1256 1257
gboolean nm_platform_get_log_with_ptr (NMPlatform *self);

1258 1259 1260
NMPNetns *nm_platform_netns_get (NMPlatform *self);
gboolean nm_platform_netns_push (NMPlatform *platform, NMPNetns **netns);

1261 1262
const char *nm_link_type_to_string (NMLinkType link_type);

1263 1264 1265
#define NMP_SYSCTL_PATHID_ABSOLUTE(path) \
	((const char *) NULL), -1, (path)

1266
#define NMP_SYSCTL_PATHID_NETDIR_unsafe(dirfd, ifname, path) \
1267 1268 1269 1270 1271 1272 1273 1274 1275
	nm_sprintf_buf_unsafe_a (  NM_STRLEN ("net:/sys/class/net//\0") \
	                         + NMP_IFNAMSIZ \
	                         + ({ \
	                             const gsize _l = strlen (path); \
	                             \
	                             nm_assert (_l < 200); \
	                             _l; \
	                            }), \
	                         "net:/sys/class/net/%s/%s", (ifname), (path)), \
1276 1277 1278
	(dirfd), (path)

#define NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, path) \
1279
	nm_sprintf_bufa (NM_STRLEN ("net:/sys/class/net//"path"/\0") + NMP_IFNAMSIZ, \
1280 1281 1282 1283
	                 "net:/sys/class/net/%s/%s", (ifname), path), \
	(dirfd), (""path"")

int nm_platform_sysctl_open_netdir (NMPlatform *self, int ifindex, char *out_ifname);
1284 1285 1286 1287
gboolean nm_platform_sysctl_set (NMPlatform *self, const char *pathid, int dirfd, const char *path, const char *value);
char *nm_platform_sysctl_get (NMPlatform *self, const char *pathid, int dirfd, const char *path);
gint32 nm_platform_sysctl_get_int32 (NMPlatform *self, const char *pathid, int dirfd, const char *path, gint32 fallback);
gint64 nm_platform_sysctl_get_int_checked (NMPlatform *self, const char *pathid, int dirfd, const char *path, guint base, gint64 min, gint64 max, gint64 fallback);
1288

1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314
char *nm_platform_sysctl_ip_conf_get (NMPlatform *platform,
                                      int addr_family,
                                      const char *ifname,
                                      const char *property);

gint64 nm_platform_sysctl_ip_conf_get_int_checked (NMPlatform *platform,
                                                   int addr_family,
                                                   const char *ifname,
                                                   const char *property,
                                                   guint base,
                                                   gint64 min,
                                                   gint64 max,
                                                   gint64 fallback);

gboolean nm_platform_sysctl_ip_conf_set (NMPlatform *platform,
                                         int addr_family,
                                         const char *ifname,
                                         const char *property,
                                         const char *value);

gboolean nm_platform_sysctl_ip_conf_set_int64 (NMPlatform *platform,
                                               int addr_family,
                                               const char *ifname,
                                               const char *property,
                                               gint64 value);

1315 1316 1317
gboolean nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe (NMPlatform *self,
                                                             const char *iface,
                                                             int value);
1318

1319 1320 1321
const char *nm_platform_if_indextoname (NMPlatform *self, int ifindex, char *out_ifname/* of size IFNAMSIZ */);
int nm_platform_if_nametoindex (NMPlatform *self, const char *ifname);

1322 1323 1324
const NMPObject *nm_platform_link_get_obj (NMPlatform *self,
                                           int ifindex,
                                           gboolean visible_only);
1325 1326
const NMPlatformLink *nm_platform_link_get (NMPlatform *self, int ifindex);
const NMPlatformLink *nm_platform_link_get_by_ifname (NMPlatform *self, const char *ifname);
1327
const NMPlatformLink *nm_platform_link_get_by_address (NMPlatform *self, NMLinkType link_type, gconstpointer address, size_t length);
1328

1329
GPtrArray *nm_platform_link_get_all (NMPlatform *self, gboolean sort_by_name);
1330 1331 1332 1333 1334
int nm_platform_link_dummy_add (NMPlatform *self, const char *name, const NMPlatformLink **out_link);
int nm_platform_link_bridge_add (NMPlatform *self, const char *name, const void *address, size_t address_len, const NMPlatformLink **out_link);
int nm_platform_link_bond_add (NMPlatform *self, const char *name, const NMPlatformLink **out_link);
int nm_platform_link_team_add (NMPlatform *self, const char *name, const NMPlatformLink **out_link);
int nm_platform_link_veth_add (NMPlatform *self, const char *name, const char *peer, const NMPlatformLink **out_link);
1335

1336
gboolean nm_platform_link_delete (NMPlatform *self, int ifindex);
1337

1338 1339
gboolean nm_platform_link_set_netns (NMPlatform *self, int ifindex, int netns_fd);

1340 1341 1342 1343 1344
struct _NMDedupMultiHeadEntry;
struct _NMPLookup;
const struct _NMDedupMultiHeadEntry *nm_platform_lookup (NMPlatform *platform,
                                                         const struct _NMPLookup *lookup);

1345 1346
gboolean nm_platform_lookup_predicate_routes_main (const NMPObject *obj,
                                                   gpointer user_data);
1347 1348
gboolean nm_platform_lookup_predicate_routes_main_skip_rtprot_kernel (const NMPObject *obj,
                                                                      gpointer user_data);
1349 1350 1351

GPtrArray *nm_platform_lookup_clone (NMPlatform *platform,
                                     const struct _NMPLookup *lookup,
1352
                                     NMPObjectPredicateFunc predicate,
1353 1354
                                     gpointer user_data);

luz.paz's avatar
luz.paz committed
1355
/* convenience methods to lookup the link and access fields of NMPlatformLink. */
1356 1357 1358 1359
int nm_platform_link_get_ifindex (NMPlatform *self, const char *name);
const char *nm_platform_link_get_name (NMPlatform *self, int ifindex);
NMLinkType nm_platform_link_get_type (NMPlatform *self, int ifindex);
gboolean nm_platform_link_is_software (NMPlatform *self, int ifindex);
1360
int nm_platform_link_get_ifi_flags (NMPlatform *self, int ifindex, guint requested_flags);
1361 1362 1363 1364 1365
gboolean nm_platform_link_is_up (NMPlatform *self, int ifindex);
gboolean nm_platform_link_is_connected (NMPlatform *self, int ifindex);
gboolean nm_platform_link_uses_arp (NMPlatform *self, int ifindex);
guint32 nm_platform_link_get_mtu (NMPlatform *self, int ifindex);
gboolean nm_platform_link_get_user_ipv6ll_enabled (NMPlatform *self, int ifindex);
1366

1367
gconstpointer nm_platform_link_get_address (NMPlatform *self, int ifindex, size_t *length);
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380

static inline GBytes *
nm_platform_link_get_address_as_bytes (NMPlatform *self, int ifindex)
{
	gconstpointer p;
	gsize l;

	p = nm_platform_link_get_address (self, ifindex, &l);
	return p
	       ? g_bytes_new (p, l)
	       : NULL;
}

1381 1382
int nm_platform_link_get_master (NMPlatform *self, int slave);

1383 1384
gboolean nm_platform_link_can_assume (NMPlatform *self, int ifindex);

1385
gboolean nm_platform_link_get_unmanaged (NMPlatform *self, int ifindex, gboolean *unmanaged);
1386
gboolean nm_platform_link_supports_slaves (NMPlatform *self, int ifindex);
1387
const char *nm_platform_link_get_type_name (NMPlatform *self, int ifindex);
1388 1389

gboolean nm_platform_link_refresh (NMPlatform *self, int ifindex);
1390
void nm_platform_process_events (NMPlatform *self);
1391

1392 1393 1394 1395
const NMPlatformLink *nm_platform_process_events_ensure_link (NMPlatform *self,
                                                              int ifindex,
                                                              const char *ifname);

1396
gboolean nm_platform_link_set_up (NMPlatform *self, int ifindex, gboolean *out_no_firmware);
1397 1398 1399 1400
gboolean nm_platform_link_set_down (NMPlatform *self, int ifindex);
gboolean nm_platform_link_set_arp (NMPlatform *self, int ifindex);
gboolean nm_platform_link_set_noarp (NMPlatform *self, int ifindex);

1401
const char *nm_platform_link_get_udi (NMPlatform *self, int ifindex);
1402

1403
struct udev_device *nm_platform_link_get_udev_device (NMPlatform *self, int ifindex);
1404

1405
int nm_platform_link_set_user_ipv6ll_enabled (NMPlatform *self, int ifindex, gboolean enabled);
1406
gboolean nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid);
1407

1408
gboolean nm_platform_link_get_permanent_address (NMPlatform *self, int ifindex, guint8 *buf, size_t *length);
1409 1410
int nm_platform_link_set_address (NMPlatform *self, int ifindex, const void *address, size_t length);
int nm_platform_link_set_mtu (NMPlatform *self, int ifindex, guint32 mtu);
1411
gboolean nm_platform_link_set_name (NMPlatform *self, int ifindex, const char *name);
1412
gboolean nm_platform_link_set_sriov_params (NMPlatform *self, int ifindex, guint num_vfs, int autoprobe);
1413
gboolean nm_platform_link_set_sriov_vfs (NMPlatform *self, int ifindex, const NMPlatformVF *const *vfs);
1414
gboolean nm_platform_link_set_bridge_vlans (NMPlatform *self, int ifindex, gboolean on_master, const NMPlatformBridgeVlan *const *vlans);
1415 1416 1417 1418

char    *nm_platform_link_get_physical_port_id (NMPlatform *self, int ifindex);
guint    nm_platform_link_get_dev_id (NMPlatform *self, int ifindex);
gboolean nm_platform_link_get_wake_on_lan (NMPlatform *self, int ifindex);
1419 1420 1421 1422 1423
gboolean nm_platform_link_get_driver_info (NMPlatform *self,
                                           int ifindex,
                                           char **out_driver_name,
                                           char **out_driver_version,
                                           char **out_fw_version);
1424 1425 1426

gboolean nm_platform_link_supports_carrier_detect (NMPlatform *self, int ifindex);
gboolean nm_platform_link_supports_vlans (NMPlatform *self, int ifindex);
1427
gboolean nm_platform_link_supports_sriov (NMPlatform *self, int ifindex);