mirror of
https://github.com/systemd/systemd
synced 2026-04-20 22:14:52 +02:00
Compare commits
23 Commits
97f27f8a16
...
0b0ad494a0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b0ad494a0 | ||
|
|
0628d48ec2 | ||
|
|
a5e6986ac0 | ||
|
|
e6e2b66b8f | ||
|
|
65a0ede2ed | ||
|
|
a99a85242c | ||
|
|
0b95409928 | ||
|
|
cec7f09dc8 | ||
|
|
73a4ac8a75 | ||
|
|
deec0b6dd5 | ||
|
|
2d17d699bb | ||
|
|
e4bbd9c61e | ||
|
|
7ec1846242 | ||
|
|
1dec9d816b | ||
|
|
b3208e0fad | ||
|
|
828a81a937 | ||
|
|
e8b8b3eacb | ||
|
|
27e93a4b66 | ||
|
|
1f38b6f9c6 | ||
|
|
f50b93fed7 | ||
|
|
89346ac6f6 | ||
|
|
55c6f705ba | ||
|
|
058fd55efa |
2
.github/workflows/linter.yml
vendored
2
.github/workflows/linter.yml
vendored
@ -40,8 +40,6 @@ jobs:
|
||||
# - .*\.(in|SKELETON) - all template/skeleton files
|
||||
# - tools/coverity\.sh - external file (with some modifications)
|
||||
FILTER_REGEX_EXCLUDE: .*/(man/.*|src/kernel-install/.*|.*\.(in|SKELETON)|tools/coverity\.sh)$
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
MULTI_STATUS: true
|
||||
VALIDATE_ALL_CODEBASE: false
|
||||
VALIDATE_BASH: true
|
||||
VALIDATE_GITHUB_ACTIONS: true
|
||||
|
||||
@ -3967,12 +3967,14 @@ run_target(
|
||||
alias_target('update-dbus-docs', update_dbus_docs)
|
||||
alias_target('update-man-rules', update_man_rules)
|
||||
|
||||
custom_target(
|
||||
if not meson.is_cross_build()
|
||||
custom_target(
|
||||
'export-dbus-interfaces',
|
||||
output : dbus_interfaces_dir_name,
|
||||
install : dbus_interfaces_dir != 'no',
|
||||
install_dir : dbus_interfaces_dir_parent,
|
||||
command : [export_dbus_interfaces_py, '@OUTPUT@', dbus_programs])
|
||||
endif
|
||||
|
||||
############################################################
|
||||
|
||||
|
||||
@ -6173,6 +6173,7 @@ void unit_dump_config_items(FILE *f) {
|
||||
{ config_parse_si_uint64, "SIZE" },
|
||||
{ config_parse_bool, "BOOLEAN" },
|
||||
{ config_parse_string, "STRING" },
|
||||
{ config_parse_safe_string, "STRING" },
|
||||
{ config_parse_path, "PATH" },
|
||||
{ config_parse_unit_path_printf, "PATH" },
|
||||
{ config_parse_colon_separated_paths, "PATH" },
|
||||
|
||||
@ -569,7 +569,7 @@ finalize:
|
||||
|
||||
static int parse_config(void) {
|
||||
const ConfigTableItem items[] = {
|
||||
{ "Upload", "URL", config_parse_string, 0, &arg_url },
|
||||
{ "Upload", "URL", config_parse_safe_string, 0, &arg_url },
|
||||
{ "Upload", "ServerKeyFile", config_parse_path_or_ignore, 0, &arg_key },
|
||||
{ "Upload", "ServerCertificateFile", config_parse_path_or_ignore, 0, &arg_cert },
|
||||
{ "Upload", "TrustedCertificateFile", config_parse_path_or_ignore, 0, &arg_trust },
|
||||
|
||||
@ -1043,88 +1043,73 @@ int sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(sd_netlink_message
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_new_qdisc(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int tcm_family, int tcm_ifindex) {
|
||||
int sd_rtnl_message_new_traffic_control(
|
||||
sd_netlink *rtnl,
|
||||
sd_netlink_message **ret,
|
||||
uint16_t nlmsg_type,
|
||||
int ifindex,
|
||||
uint32_t handle,
|
||||
uint32_t parent) {
|
||||
|
||||
struct tcmsg *tcm;
|
||||
int r;
|
||||
|
||||
assert_return(rtnl_message_type_is_qdisc(nlmsg_type), -EINVAL);
|
||||
assert_return(rtnl_message_type_is_traffic_control(nlmsg_type), -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = message_new(rtnl, ret, nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (nlmsg_type == RTM_NEWQDISC)
|
||||
if (IN_SET(nlmsg_type, RTM_NEWQDISC, RTM_NEWTCLASS))
|
||||
(*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
|
||||
|
||||
tcm = NLMSG_DATA((*ret)->hdr);
|
||||
tcm->tcm_family = tcm_family;
|
||||
tcm->tcm_ifindex = tcm_ifindex;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_set_qdisc_parent(sd_netlink_message *m, uint32_t parent) {
|
||||
struct tcmsg *tcm;
|
||||
|
||||
assert_return(rtnl_message_type_is_qdisc(m->hdr->nlmsg_type), -EINVAL);
|
||||
|
||||
tcm = NLMSG_DATA(m->hdr);
|
||||
tcm->tcm_ifindex = ifindex;
|
||||
tcm->tcm_handle = handle;
|
||||
tcm->tcm_parent = parent;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_set_qdisc_handle(sd_netlink_message *m, uint32_t handle) {
|
||||
int sd_rtnl_message_traffic_control_get_ifindex(sd_netlink_message *m, int *ret) {
|
||||
struct tcmsg *tcm;
|
||||
|
||||
assert_return(rtnl_message_type_is_qdisc(m->hdr->nlmsg_type), -EINVAL);
|
||||
|
||||
tcm = NLMSG_DATA(m->hdr);
|
||||
tcm->tcm_handle = handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_new_tclass(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int tcm_family, int tcm_ifindex) {
|
||||
struct tcmsg *tcm;
|
||||
int r;
|
||||
|
||||
assert_return(rtnl_message_type_is_tclass(nlmsg_type), -EINVAL);
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
assert_return(rtnl_message_type_is_traffic_control(m->hdr->nlmsg_type), -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = message_new(rtnl, ret, nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (nlmsg_type == RTM_NEWTCLASS)
|
||||
(*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
|
||||
|
||||
tcm = NLMSG_DATA((*ret)->hdr);
|
||||
tcm->tcm_family = tcm_family;
|
||||
tcm->tcm_ifindex = tcm_ifindex;
|
||||
tcm = NLMSG_DATA(m->hdr);
|
||||
*ret = tcm->tcm_ifindex;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_set_tclass_parent(sd_netlink_message *m, uint32_t parent) {
|
||||
int sd_rtnl_message_traffic_control_get_handle(sd_netlink_message *m, uint32_t *ret) {
|
||||
struct tcmsg *tcm;
|
||||
|
||||
assert_return(rtnl_message_type_is_tclass(m->hdr->nlmsg_type), -EINVAL);
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
assert_return(rtnl_message_type_is_traffic_control(m->hdr->nlmsg_type), -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
tcm = NLMSG_DATA(m->hdr);
|
||||
tcm->tcm_parent = parent;
|
||||
*ret = tcm->tcm_handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_set_tclass_handle(sd_netlink_message *m, uint32_t handle) {
|
||||
int sd_rtnl_message_traffic_control_get_parent(sd_netlink_message *m, uint32_t *ret) {
|
||||
struct tcmsg *tcm;
|
||||
|
||||
assert_return(rtnl_message_type_is_tclass(m->hdr->nlmsg_type), -EINVAL);
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
assert_return(rtnl_message_type_is_traffic_control(m->hdr->nlmsg_type), -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
tcm = NLMSG_DATA(m->hdr);
|
||||
tcm->tcm_handle = handle;
|
||||
*ret = tcm->tcm_parent;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -119,7 +119,8 @@ int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
|
||||
assert_return(m->protocol != NETLINK_ROUTE ||
|
||||
IN_SET(m->hdr->nlmsg_type,
|
||||
RTM_GETLINK, RTM_GETLINKPROP, RTM_GETADDR, RTM_GETROUTE, RTM_GETNEIGH,
|
||||
RTM_GETRULE, RTM_GETADDRLABEL, RTM_GETNEXTHOP), -EINVAL);
|
||||
RTM_GETRULE, RTM_GETADDRLABEL, RTM_GETNEXTHOP, RTM_GETQDISC, RTM_GETTCLASS),
|
||||
-EINVAL);
|
||||
|
||||
SET_FLAG(m->hdr->nlmsg_flags, NLM_F_DUMP, dump);
|
||||
|
||||
|
||||
@ -59,12 +59,10 @@ static inline bool rtnl_message_type_is_routing_policy_rule(uint16_t type) {
|
||||
return IN_SET(type, RTM_NEWRULE, RTM_DELRULE, RTM_GETRULE);
|
||||
}
|
||||
|
||||
static inline bool rtnl_message_type_is_qdisc(uint16_t type) {
|
||||
return IN_SET(type, RTM_NEWQDISC, RTM_DELQDISC, RTM_GETQDISC);
|
||||
}
|
||||
|
||||
static inline bool rtnl_message_type_is_tclass(uint16_t type) {
|
||||
return IN_SET(type, RTM_NEWTCLASS, RTM_DELTCLASS, RTM_GETTCLASS);
|
||||
static inline bool rtnl_message_type_is_traffic_control(uint16_t type) {
|
||||
return IN_SET(type,
|
||||
RTM_NEWQDISC, RTM_DELQDISC, RTM_GETQDISC,
|
||||
RTM_NEWTCLASS, RTM_DELTCLASS, RTM_GETTCLASS);
|
||||
}
|
||||
|
||||
static inline bool rtnl_message_type_is_mdb(uint16_t type) {
|
||||
|
||||
@ -977,7 +977,8 @@ int sd_netlink_add_match(
|
||||
neighbor_groups[] = { RTNLGRP_NEIGH, },
|
||||
nexthop_groups[] = { RTNLGRP_NEXTHOP, },
|
||||
route_groups[] = { RTNLGRP_IPV4_ROUTE, RTNLGRP_IPV6_ROUTE, },
|
||||
rule_groups[] = { RTNLGRP_IPV4_RULE, RTNLGRP_IPV6_RULE, };
|
||||
rule_groups[] = { RTNLGRP_IPV4_RULE, RTNLGRP_IPV6_RULE, },
|
||||
tc_groups[] = { RTNLGRP_TC };
|
||||
const uint32_t *groups;
|
||||
size_t n_groups;
|
||||
|
||||
@ -1016,6 +1017,13 @@ int sd_netlink_add_match(
|
||||
groups = nexthop_groups;
|
||||
n_groups = ELEMENTSOF(nexthop_groups);
|
||||
break;
|
||||
case RTM_NEWQDISC:
|
||||
case RTM_DELQDISC:
|
||||
case RTM_NEWTCLASS:
|
||||
case RTM_DELTCLASS:
|
||||
groups = tc_groups;
|
||||
n_groups = ELEMENTSOF(tc_groups);
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ static int netdev_l2tp_create_message_tunnel(NetDev *netdev, union in_addr_union
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
switch(t->l2tp_encap_type) {
|
||||
switch (t->l2tp_encap_type) {
|
||||
case NETDEV_L2TP_ENCAPTYPE_IP:
|
||||
encap_type = L2TP_ENCAPTYPE_IP;
|
||||
break;
|
||||
|
||||
@ -178,14 +178,14 @@ Tun.OneQueue, config_parse_warn_compat,
|
||||
Tun.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue)
|
||||
Tun.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info)
|
||||
Tun.VNetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr)
|
||||
Tun.User, config_parse_string, 0, offsetof(TunTap, user_name)
|
||||
Tun.Group, config_parse_string, 0, offsetof(TunTap, group_name)
|
||||
Tun.User, config_parse_safe_string, 0, offsetof(TunTap, user_name)
|
||||
Tun.Group, config_parse_safe_string, 0, offsetof(TunTap, group_name)
|
||||
Tap.OneQueue, config_parse_warn_compat, DISABLED_LEGACY, 0
|
||||
Tap.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue)
|
||||
Tap.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info)
|
||||
Tap.VNetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr)
|
||||
Tap.User, config_parse_string, 0, offsetof(TunTap, user_name)
|
||||
Tap.Group, config_parse_string, 0, offsetof(TunTap, group_name)
|
||||
Tap.User, config_parse_safe_string, 0, offsetof(TunTap, user_name)
|
||||
Tap.Group, config_parse_safe_string, 0, offsetof(TunTap, group_name)
|
||||
Bond.Mode, config_parse_bond_mode, 0, offsetof(Bond, mode)
|
||||
Bond.TransmitHashPolicy, config_parse_bond_xmit_hash_policy, 0, offsetof(Bond, xmit_hash_policy)
|
||||
Bond.LACPTransmitRate, config_parse_bond_lacp_rate, 0, offsetof(Bond, lacp_rate)
|
||||
|
||||
@ -337,7 +337,7 @@ int config_parse_dhcp_or_ra_route_metric(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ltype) {
|
||||
switch (ltype) {
|
||||
case AF_INET:
|
||||
network->dhcp_route_metric = metric;
|
||||
network->dhcp_route_metric_set = true;
|
||||
@ -388,7 +388,7 @@ int config_parse_dhcp_use_dns(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ltype) {
|
||||
switch (ltype) {
|
||||
case AF_INET:
|
||||
network->dhcp_use_dns = r;
|
||||
network->dhcp_use_dns_set = true;
|
||||
@ -439,7 +439,7 @@ int config_parse_dhcp_use_domains(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ltype) {
|
||||
switch (ltype) {
|
||||
case AF_INET:
|
||||
network->dhcp_use_domains = d;
|
||||
network->dhcp_use_domains_set = true;
|
||||
@ -490,7 +490,7 @@ int config_parse_dhcp_use_ntp(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ltype) {
|
||||
switch (ltype) {
|
||||
case AF_INET:
|
||||
network->dhcp_use_ntp = r;
|
||||
network->dhcp_use_ntp_set = true;
|
||||
@ -542,7 +542,7 @@ int config_parse_dhcp_or_ra_route_table(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ltype) {
|
||||
switch (ltype) {
|
||||
case AF_INET:
|
||||
network->dhcp_route_table = rt;
|
||||
network->dhcp_route_table_set = true;
|
||||
@ -777,7 +777,7 @@ int config_parse_dhcp_send_option(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
switch (type) {
|
||||
case DHCP_OPTION_DATA_UINT8:{
|
||||
r = safe_atou8(p, &uint8_data);
|
||||
if (r < 0) {
|
||||
|
||||
@ -117,7 +117,7 @@ static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata) {
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return;
|
||||
|
||||
switch(event) {
|
||||
switch (event) {
|
||||
case SD_IPV4LL_EVENT_STOP:
|
||||
r = ipv4ll_address_lost(link);
|
||||
if (r < 0) {
|
||||
|
||||
@ -269,12 +269,10 @@ static Link *link_free(Link *link) {
|
||||
link_dns_settings_clear(link);
|
||||
|
||||
link->routes = set_free(link->routes);
|
||||
|
||||
link->nexthops = set_free(link->nexthops);
|
||||
|
||||
link->neighbors = set_free(link->neighbors);
|
||||
|
||||
link->addresses = set_free(link->addresses);
|
||||
link->traffic_control = set_free(link->traffic_control);
|
||||
|
||||
link->dhcp_pd_prefixes = set_free(link->dhcp_pd_prefixes);
|
||||
|
||||
@ -1099,7 +1097,7 @@ static int link_configure(Link *link) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = link_configure_traffic_control(link);
|
||||
r = link_request_traffic_control(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@ -108,6 +108,7 @@ typedef struct Link {
|
||||
Set *neighbors;
|
||||
Set *routes;
|
||||
Set *nexthops;
|
||||
Set *traffic_control;
|
||||
|
||||
sd_dhcp_client *dhcp_client;
|
||||
sd_dhcp_lease *dhcp_lease;
|
||||
|
||||
@ -45,12 +45,14 @@
|
||||
#include "ordered-set.h"
|
||||
#include "path-lookup.h"
|
||||
#include "path-util.h"
|
||||
#include "qdisc.h"
|
||||
#include "selinux-util.h"
|
||||
#include "set.h"
|
||||
#include "signal-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
#include "sysctl-util.h"
|
||||
#include "tclass.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
/* use 128 MB for receive socket kernel queue. */
|
||||
@ -311,6 +313,22 @@ static int manager_connect_rtnl(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = netlink_add_match(m->rtnl, NULL, RTM_NEWQDISC, &manager_rtnl_process_qdisc, NULL, m, "network-rtnl_process_qdisc");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = netlink_add_match(m->rtnl, NULL, RTM_DELQDISC, &manager_rtnl_process_qdisc, NULL, m, "network-rtnl_process_qdisc");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = netlink_add_match(m->rtnl, NULL, RTM_NEWTCLASS, &manager_rtnl_process_tclass, NULL, m, "network-rtnl_process_tclass");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = netlink_add_match(m->rtnl, NULL, RTM_DELTCLASS, &manager_rtnl_process_tclass, NULL, m, "network-rtnl_process_tclass");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address");
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -671,6 +689,34 @@ static int manager_enumerate_links(Manager *m) {
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_link);
|
||||
}
|
||||
|
||||
static int manager_enumerate_qdisc(Manager *m) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->rtnl);
|
||||
|
||||
r = sd_rtnl_message_new_traffic_control(m->rtnl, &req, RTM_GETQDISC, 0, 0, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_qdisc);
|
||||
}
|
||||
|
||||
static int manager_enumerate_tclass(Manager *m) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->rtnl);
|
||||
|
||||
r = sd_rtnl_message_new_traffic_control(m->rtnl, &req, RTM_GETTCLASS, 0, 0, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_tclass);
|
||||
}
|
||||
|
||||
static int manager_enumerate_addresses(Manager *m) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
@ -797,6 +843,14 @@ int manager_enumerate(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate links: %m");
|
||||
|
||||
r = manager_enumerate_qdisc(m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate QDisc: %m");
|
||||
|
||||
r = manager_enumerate_tclass(m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate TClass: %m");
|
||||
|
||||
r = manager_enumerate_addresses(m);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not enumerate addresses: %m");
|
||||
|
||||
@ -220,7 +220,7 @@ DHCPv4.SendHostname, config_parse_bool,
|
||||
DHCPv4.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname)
|
||||
DHCPv4.Label, config_parse_dhcp_label, 0, offsetof(Network, dhcp_label)
|
||||
DHCPv4.RequestBroadcast, config_parse_tristate, 0, offsetof(Network, dhcp_broadcast)
|
||||
DHCPv4.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCPv4.VendorClassIdentifier, config_parse_safe_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCPv4.MUDURL, config_parse_mud_url, 0, offsetof(Network, dhcp_mudurl)
|
||||
DHCPv4.MaxAttempts, config_parse_dhcp_max_attempts, 0, 0
|
||||
DHCPv4.UserClass, config_parse_dhcp_user_or_vendor_class, AF_INET, offsetof(Network, dhcp_user_class)
|
||||
@ -539,7 +539,7 @@ DHCP.SendHostname, config_parse_bool,
|
||||
DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname)
|
||||
DHCP.RequestBroadcast, config_parse_tristate, 0, offsetof(Network, dhcp_broadcast)
|
||||
DHCP.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical)
|
||||
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCP.VendorClassIdentifier, config_parse_safe_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCP.UserClass, config_parse_dhcp_user_or_vendor_class, AF_INET, offsetof(Network, dhcp_user_class)
|
||||
DHCP.IAID, config_parse_iaid, AF_INET, 0
|
||||
DHCP.DUIDType, config_parse_network_duid_type, 0, 0
|
||||
|
||||
@ -755,7 +755,7 @@ static Network *network_free(Network *network) {
|
||||
hashmap_free_with_destructor(network->rules_by_section, routing_policy_rule_free);
|
||||
hashmap_free_with_destructor(network->dhcp_static_leases_by_section, dhcp_static_lease_free);
|
||||
ordered_hashmap_free_with_destructor(network->sr_iov_by_section, sr_iov_free);
|
||||
ordered_hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
|
||||
hashmap_free_with_destructor(network->tc_by_section, traffic_control_free);
|
||||
|
||||
free(network->name);
|
||||
|
||||
|
||||
@ -341,7 +341,7 @@ struct Network {
|
||||
Hashmap *route_prefixes_by_section;
|
||||
Hashmap *rules_by_section;
|
||||
Hashmap *dhcp_static_leases_by_section;
|
||||
OrderedHashmap *tc_by_section;
|
||||
Hashmap *tc_by_section;
|
||||
OrderedHashmap *sr_iov_by_section;
|
||||
|
||||
/* All kinds of DNS configuration */
|
||||
|
||||
@ -1220,7 +1220,7 @@ int config_parse_nexthop_family(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(a) {
|
||||
switch (a) {
|
||||
case ADDRESS_FAMILY_IPV4:
|
||||
n->family = AF_INET;
|
||||
break;
|
||||
|
||||
@ -16,9 +16,10 @@
|
||||
#include "networkd-routing-policy-rule.h"
|
||||
#include "networkd-queue.h"
|
||||
#include "networkd-setlink.h"
|
||||
#include "tc.h"
|
||||
|
||||
static void request_free_object(RequestType type, void *object) {
|
||||
switch(type) {
|
||||
switch (type) {
|
||||
case REQUEST_TYPE_ACTIVATE_LINK:
|
||||
break;
|
||||
case REQUEST_TYPE_ADDRESS:
|
||||
@ -58,6 +59,10 @@ static void request_free_object(RequestType type, void *object) {
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK:
|
||||
case REQUEST_TYPE_STACKED_NETDEV:
|
||||
break;
|
||||
case REQUEST_TYPE_TRAFFIC_CONTROL:
|
||||
traffic_control_free(object);
|
||||
break;
|
||||
case REQUEST_TYPE_UP_DOWN:
|
||||
break;
|
||||
default:
|
||||
@ -100,7 +105,7 @@ static void request_hash_func(const Request *req, struct siphash *state) {
|
||||
siphash24_compress(&req->link->ifindex, sizeof(req->link->ifindex), state);
|
||||
siphash24_compress(&req->type, sizeof(req->type), state);
|
||||
|
||||
switch(req->type) {
|
||||
switch (req->type) {
|
||||
case REQUEST_TYPE_ACTIVATE_LINK:
|
||||
break;
|
||||
case REQUEST_TYPE_ADDRESS:
|
||||
@ -140,10 +145,12 @@ static void request_hash_func(const Request *req, struct siphash *state) {
|
||||
case REQUEST_TYPE_ROUTING_POLICY_RULE:
|
||||
routing_policy_rule_hash_func(req->rule, state);
|
||||
break;
|
||||
case REQUEST_TYPE_SET_LINK: {
|
||||
case REQUEST_TYPE_SET_LINK:
|
||||
trivial_hash_func(req->set_link_operation_ptr, state);
|
||||
break;
|
||||
}
|
||||
case REQUEST_TYPE_TRAFFIC_CONTROL:
|
||||
traffic_control_hash_func(req->traffic_control, state);
|
||||
break;
|
||||
case REQUEST_TYPE_UP_DOWN:
|
||||
break;
|
||||
default:
|
||||
@ -197,6 +204,8 @@ static int request_compare_func(const struct Request *a, const struct Request *b
|
||||
return routing_policy_rule_compare_func(a->rule, b->rule);
|
||||
case REQUEST_TYPE_SET_LINK:
|
||||
return trivial_compare_func(a->set_link_operation_ptr, b->set_link_operation_ptr);
|
||||
case REQUEST_TYPE_TRAFFIC_CONTROL:
|
||||
return traffic_control_compare_func(a->traffic_control, b->traffic_control);
|
||||
case REQUEST_TYPE_UP_DOWN:
|
||||
return 0;
|
||||
default:
|
||||
@ -242,7 +251,8 @@ int link_queue_request(
|
||||
REQUEST_TYPE_DHCP4_CLIENT,
|
||||
REQUEST_TYPE_DHCP6_CLIENT,
|
||||
REQUEST_TYPE_NDISC,
|
||||
REQUEST_TYPE_RADV) ||
|
||||
REQUEST_TYPE_RADV,
|
||||
REQUEST_TYPE_TRAFFIC_CONTROL) ||
|
||||
netlink_handler);
|
||||
|
||||
req = new(Request, 1);
|
||||
@ -296,7 +306,7 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
|
||||
Request *req;
|
||||
|
||||
ORDERED_SET_FOREACH(req, manager->request_queue) {
|
||||
switch(req->type) {
|
||||
switch (req->type) {
|
||||
case REQUEST_TYPE_ACTIVATE_LINK:
|
||||
r = request_process_activation(req);
|
||||
break;
|
||||
@ -348,6 +358,9 @@ int manager_process_requests(sd_event_source *s, void *userdata) {
|
||||
case REQUEST_TYPE_STACKED_NETDEV:
|
||||
r = request_process_stacked_netdev(req);
|
||||
break;
|
||||
case REQUEST_TYPE_TRAFFIC_CONTROL:
|
||||
r = request_process_traffic_control(req);
|
||||
break;
|
||||
case REQUEST_TYPE_UP_DOWN:
|
||||
r = request_process_link_up_or_down(req);
|
||||
break;
|
||||
|
||||
@ -14,6 +14,7 @@ typedef struct NetDev NetDev;
|
||||
typedef struct NextHop NextHop;
|
||||
typedef struct Route Route;
|
||||
typedef struct RoutingPolicyRule RoutingPolicyRule;
|
||||
typedef struct TrafficControl TrafficControl;
|
||||
|
||||
typedef enum RequestType {
|
||||
REQUEST_TYPE_ACTIVATE_LINK,
|
||||
@ -33,6 +34,7 @@ typedef enum RequestType {
|
||||
REQUEST_TYPE_ROUTING_POLICY_RULE,
|
||||
REQUEST_TYPE_SET_LINK,
|
||||
REQUEST_TYPE_STACKED_NETDEV,
|
||||
REQUEST_TYPE_TRAFFIC_CONTROL,
|
||||
REQUEST_TYPE_UP_DOWN,
|
||||
_REQUEST_TYPE_MAX,
|
||||
_REQUEST_TYPE_INVALID = -EINVAL,
|
||||
@ -54,6 +56,7 @@ typedef struct Request {
|
||||
RoutingPolicyRule *rule;
|
||||
void *set_link_operation_ptr;
|
||||
NetDev *netdev;
|
||||
TrafficControl *traffic_control;
|
||||
void *object;
|
||||
};
|
||||
void *userdata;
|
||||
|
||||
@ -132,7 +132,7 @@ int manager_genl_process_nl80211_config(sd_netlink *genl, sd_netlink_message *me
|
||||
strna(nl80211_cmd_to_string(cmd)), cmd,
|
||||
strna(nl80211_iftype_to_string(wlan_iftype)), strna(ssid));
|
||||
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
case NL80211_CMD_SET_INTERFACE:
|
||||
case NL80211_CMD_NEW_INTERFACE:
|
||||
link->wlan_iftype = wlan_iftype;
|
||||
@ -200,7 +200,7 @@ int manager_genl_process_nl80211_mlme(sd_netlink *genl, sd_netlink_message *mess
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
switch (cmd) {
|
||||
case NL80211_CMD_NEW_STATION:
|
||||
case NL80211_CMD_DEL_STATION: {
|
||||
struct ether_addr bssid;
|
||||
|
||||
@ -18,7 +18,7 @@ static int fifo_fill_message(Link *link, QDisc *qdisc, sd_netlink_message *req)
|
||||
assert(qdisc);
|
||||
assert(req);
|
||||
|
||||
switch(qdisc->kind) {
|
||||
switch (qdisc->kind) {
|
||||
case QDISC_KIND_PFIFO:
|
||||
assert_se(fifo = PFIFO(qdisc));
|
||||
break;
|
||||
@ -71,7 +71,7 @@ int config_parse_pfifo_size(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(qdisc->kind) {
|
||||
switch (qdisc->kind) {
|
||||
case QDISC_KIND_PFIFO:
|
||||
fifo = PFIFO(qdisc);
|
||||
break;
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "in-addr-util.h"
|
||||
#include "netlink-util.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-queue.h"
|
||||
#include "parse-util.h"
|
||||
#include "qdisc.h"
|
||||
#include "set.h"
|
||||
@ -50,17 +51,16 @@ static int qdisc_new(QDiscKind kind, QDisc **ret) {
|
||||
|
||||
*qdisc = (QDisc) {
|
||||
.meta.kind = TC_KIND_QDISC,
|
||||
.family = AF_UNSPEC,
|
||||
.parent = TC_H_ROOT,
|
||||
.kind = kind,
|
||||
};
|
||||
} else {
|
||||
assert(kind >= 0 && kind < _QDISC_KIND_MAX);
|
||||
qdisc = malloc0(qdisc_vtable[kind]->object_size);
|
||||
if (!qdisc)
|
||||
return -ENOMEM;
|
||||
|
||||
qdisc->meta.kind = TC_KIND_QDISC,
|
||||
qdisc->family = AF_UNSPEC;
|
||||
qdisc->parent = TC_H_ROOT;
|
||||
qdisc->kind = kind;
|
||||
|
||||
@ -92,7 +92,7 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
existing = ordered_hashmap_get(network->tc_by_section, n);
|
||||
existing = hashmap_get(network->tc_by_section, n);
|
||||
if (existing) {
|
||||
if (existing->kind != TC_KIND_QDISC)
|
||||
return -EINVAL;
|
||||
@ -115,7 +115,6 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
|
||||
return r;
|
||||
|
||||
if (q) {
|
||||
qdisc->family = q->family;
|
||||
qdisc->handle = q->handle;
|
||||
qdisc->parent = q->parent;
|
||||
qdisc->tca_kind = TAKE_PTR(q->tca_kind);
|
||||
@ -125,8 +124,9 @@ int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, uns
|
||||
|
||||
qdisc->network = network;
|
||||
qdisc->section = TAKE_PTR(n);
|
||||
qdisc->source = NETWORK_CONFIG_SOURCE_STATIC;
|
||||
|
||||
r = ordered_hashmap_ensure_put(&network->tc_by_section, &config_section_hash_ops, qdisc->section, TC(qdisc));
|
||||
r = hashmap_ensure_put(&network->tc_by_section, &config_section_hash_ops, qdisc->section, TC(qdisc));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -139,14 +139,165 @@ QDisc* qdisc_free(QDisc *qdisc) {
|
||||
return NULL;
|
||||
|
||||
if (qdisc->network && qdisc->section)
|
||||
ordered_hashmap_remove(qdisc->network->tc_by_section, qdisc->section);
|
||||
hashmap_remove(qdisc->network->tc_by_section, qdisc->section);
|
||||
|
||||
config_section_free(qdisc->section);
|
||||
|
||||
if (qdisc->link)
|
||||
set_remove(qdisc->link->traffic_control, TC(qdisc));
|
||||
|
||||
free(qdisc->tca_kind);
|
||||
return mfree(qdisc);
|
||||
}
|
||||
|
||||
static const char *qdisc_get_tca_kind(const QDisc *qdisc) {
|
||||
assert(qdisc);
|
||||
|
||||
return (QDISC_VTABLE(qdisc) && QDISC_VTABLE(qdisc)->tca_kind) ?
|
||||
QDISC_VTABLE(qdisc)->tca_kind : qdisc->tca_kind;
|
||||
}
|
||||
|
||||
void qdisc_hash_func(const QDisc *qdisc, struct siphash *state) {
|
||||
assert(qdisc);
|
||||
assert(state);
|
||||
|
||||
siphash24_compress(&qdisc->handle, sizeof(qdisc->handle), state);
|
||||
siphash24_compress(&qdisc->parent, sizeof(qdisc->parent), state);
|
||||
siphash24_compress_string(qdisc_get_tca_kind(qdisc), state);
|
||||
}
|
||||
|
||||
int qdisc_compare_func(const QDisc *a, const QDisc *b) {
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
r = CMP(a->handle, b->handle);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = CMP(a->parent, b->parent);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return strcmp_ptr(qdisc_get_tca_kind(a), qdisc_get_tca_kind(b));
|
||||
}
|
||||
|
||||
static int qdisc_get(Link *link, const QDisc *in, QDisc **ret) {
|
||||
TrafficControl *existing;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(in);
|
||||
|
||||
r = traffic_control_get(link, TC(in), &existing);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret)
|
||||
*ret = TC_TO_QDISC(existing);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qdisc_add(Link *link, QDisc *qdisc) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(qdisc);
|
||||
|
||||
r = traffic_control_add(link, TC(qdisc));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
qdisc->link = link;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qdisc_dup(const QDisc *src, QDisc **ret) {
|
||||
_cleanup_(qdisc_freep) QDisc *dst = NULL;
|
||||
|
||||
assert(src);
|
||||
assert(ret);
|
||||
|
||||
if (QDISC_VTABLE(src))
|
||||
dst = memdup(src, QDISC_VTABLE(src)->object_size);
|
||||
else
|
||||
dst = newdup(QDisc, src, 1);
|
||||
if (!dst)
|
||||
return -ENOMEM;
|
||||
|
||||
/* clear all pointers */
|
||||
dst->network = NULL;
|
||||
dst->section = NULL;
|
||||
dst->link = NULL;
|
||||
dst->tca_kind = NULL;
|
||||
|
||||
if (src->tca_kind) {
|
||||
dst->tca_kind = strdup(src->tca_kind);
|
||||
if (!dst->tca_kind)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void log_qdisc_debug(QDisc *qdisc, Link *link, const char *str) {
|
||||
_cleanup_free_ char *state = NULL;
|
||||
|
||||
assert(qdisc);
|
||||
assert(str);
|
||||
|
||||
if (!DEBUG_LOGGING)
|
||||
return;
|
||||
|
||||
(void) network_config_state_to_string_alloc(qdisc->state, &state);
|
||||
|
||||
log_link_debug(link, "%s %s QDisc (%s): handle=%"PRIx32":%"PRIx32", parent=%"PRIx32":%"PRIx32", kind=%s",
|
||||
str, strna(network_config_source_to_string(qdisc->source)), strna(state),
|
||||
TC_H_MAJ(qdisc->handle) >> 16, TC_H_MIN(qdisc->handle),
|
||||
TC_H_MAJ(qdisc->parent) >> 16, TC_H_MIN(qdisc->parent),
|
||||
strna(qdisc_get_tca_kind(qdisc)));
|
||||
}
|
||||
|
||||
int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *kind, QDisc **ret) {
|
||||
TrafficControl *tc;
|
||||
|
||||
assert(link);
|
||||
|
||||
handle = TC_H_MAJ(handle);
|
||||
|
||||
SET_FOREACH(tc, link->traffic_control) {
|
||||
QDisc *qdisc;
|
||||
|
||||
if (tc->kind != TC_KIND_QDISC)
|
||||
continue;
|
||||
|
||||
qdisc = TC_TO_QDISC(tc);
|
||||
|
||||
if (qdisc->handle != handle)
|
||||
continue;
|
||||
|
||||
if (qdisc->parent != parent)
|
||||
continue;
|
||||
|
||||
if (qdisc->source == NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
continue;
|
||||
|
||||
if (!qdisc_exists(qdisc))
|
||||
continue;
|
||||
|
||||
if (kind && !streq_ptr(kind, qdisc_get_tca_kind(qdisc)))
|
||||
continue;
|
||||
|
||||
if (ret)
|
||||
*ret = qdisc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int qdisc_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
@ -182,50 +333,182 @@ int qdisc_configure(Link *link, QDisc *qdisc) {
|
||||
assert(link->manager->rtnl);
|
||||
assert(link->ifindex > 0);
|
||||
|
||||
r = sd_rtnl_message_new_qdisc(link->manager->rtnl, &req, RTM_NEWQDISC, qdisc->family, link->ifindex);
|
||||
log_qdisc_debug(qdisc, link, "Configuring");
|
||||
|
||||
r = sd_rtnl_message_new_traffic_control(link->manager->rtnl, &req, RTM_NEWQDISC,
|
||||
link->ifindex, qdisc->handle, qdisc->parent);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Could not create RTM_NEWQDISC message: %m");
|
||||
|
||||
r = sd_rtnl_message_set_qdisc_parent(req, qdisc->parent);
|
||||
r = sd_netlink_message_append_string(req, TCA_KIND, qdisc_get_tca_kind(qdisc));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (qdisc->handle != TC_H_UNSPEC) {
|
||||
r = sd_rtnl_message_set_qdisc_handle(req, qdisc->handle);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (QDISC_VTABLE(qdisc)) {
|
||||
if (QDISC_VTABLE(qdisc)->fill_tca_kind) {
|
||||
r = QDISC_VTABLE(qdisc)->fill_tca_kind(link, qdisc, req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
r = sd_netlink_message_append_string(req, TCA_KIND, QDISC_VTABLE(qdisc)->tca_kind);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (QDISC_VTABLE(qdisc)->fill_message) {
|
||||
if (QDISC_VTABLE(qdisc) && QDISC_VTABLE(qdisc)->fill_message) {
|
||||
r = QDISC_VTABLE(qdisc)->fill_message(link, qdisc, req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
r = sd_netlink_message_append_string(req, TCA_KIND, qdisc->tca_kind);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req, qdisc_handler, link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Could not send netlink message: %m");
|
||||
|
||||
link_ref(link);
|
||||
link->tc_messages++;
|
||||
|
||||
qdisc_enter_configuring(qdisc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qdisc_is_ready_to_configure(Link *link, QDisc *qdisc) {
|
||||
assert(link);
|
||||
assert(qdisc);
|
||||
|
||||
if (IN_SET(qdisc->parent, TC_H_ROOT, TC_H_CLSACT)) /* TC_H_CLSACT == TC_H_INGRESS */
|
||||
return true;
|
||||
|
||||
return link_find_tclass(link, qdisc->parent, NULL) >= 0;
|
||||
}
|
||||
|
||||
int link_request_qdisc(Link *link, QDisc *qdisc) {
|
||||
QDisc *existing;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(qdisc);
|
||||
|
||||
if (qdisc_get(link, qdisc, &existing) < 0) {
|
||||
_cleanup_(qdisc_freep) QDisc *tmp = NULL;
|
||||
|
||||
r = qdisc_dup(qdisc, &tmp);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = qdisc_add(link, tmp);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to store QDisc: %m");
|
||||
|
||||
existing = TAKE_PTR(tmp);
|
||||
} else
|
||||
existing->source = qdisc->source;
|
||||
|
||||
log_qdisc_debug(existing, link, "Requesting");
|
||||
r = link_queue_request(link, REQUEST_TYPE_TRAFFIC_CONTROL, TC(existing), false,
|
||||
&link->tc_messages, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request QDisc: %m");
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
qdisc_enter_requesting(existing);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int manager_rtnl_process_qdisc(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||
_cleanup_(qdisc_freep) QDisc *tmp = NULL;
|
||||
QDisc *qdisc = NULL;
|
||||
Link *link;
|
||||
uint16_t type;
|
||||
int ifindex, r;
|
||||
|
||||
assert(rtnl);
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
r = sd_netlink_message_get_errno(message);
|
||||
if (r < 0)
|
||||
log_message_warning_errno(message, r, "rtnl: failed to receive QDisc message, ignoring");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_get_type(message, &type);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
|
||||
return 0;
|
||||
} else if (!IN_SET(type, RTM_NEWQDISC, RTM_DELQDISC)) {
|
||||
log_warning("rtnl: received unexpected message type %u when processing QDisc, ignoring.", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_traffic_control_get_ifindex(message, &ifindex);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m");
|
||||
return 0;
|
||||
} else if (ifindex <= 0) {
|
||||
log_warning("rtnl: received QDisc message with invalid ifindex %d, ignoring.", ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (link_get_by_index(m, ifindex, &link) < 0) {
|
||||
if (!m->enumerating)
|
||||
log_warning("rtnl: received QDisc for link '%d' we don't know about, ignoring.", ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = qdisc_new(_QDISC_KIND_INVALID, &tmp);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = sd_rtnl_message_traffic_control_get_handle(message, &tmp->handle);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: received QDisc message without handle, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_traffic_control_get_parent(message, &tmp->parent);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: received QDisc message without parent, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_string_strdup(message, TCA_KIND, &tmp->tca_kind);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: received QDisc message without kind, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) qdisc_get(link, tmp, &qdisc);
|
||||
|
||||
switch (type) {
|
||||
case RTM_NEWQDISC:
|
||||
if (qdisc) {
|
||||
qdisc_enter_configured(qdisc);
|
||||
log_qdisc_debug(qdisc, link, "Received remembered");
|
||||
} else {
|
||||
qdisc_enter_configured(tmp);
|
||||
log_qdisc_debug(tmp, link, "Received new");
|
||||
|
||||
r = qdisc_add(link, tmp);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Failed to remember QDisc, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
qdisc = TAKE_PTR(tmp);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RTM_DELQDISC:
|
||||
if (qdisc) {
|
||||
qdisc_enter_removed(qdisc);
|
||||
if (qdisc->state == 0) {
|
||||
log_qdisc_debug(qdisc, link, "Forgetting");
|
||||
qdisc_free(qdisc);
|
||||
} else
|
||||
log_qdisc_debug(qdisc, link, "Removed");
|
||||
} else
|
||||
log_qdisc_debug(tmp, link, "Kernel removed unknown");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact) {
|
||||
@ -293,11 +576,9 @@ int config_parse_qdisc_parent(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (streq(rvalue, "root")) {
|
||||
if (streq(rvalue, "root"))
|
||||
qdisc->parent = TC_H_ROOT;
|
||||
if (qdisc->handle == 0)
|
||||
qdisc->handle = TC_H_UNSPEC;
|
||||
} else if (streq(rvalue, "clsact")) {
|
||||
else if (streq(rvalue, "clsact")) {
|
||||
qdisc->parent = TC_H_CLSACT;
|
||||
qdisc->handle = TC_H_MAKE(TC_H_CLSACT, 0);
|
||||
} else if (streq(rvalue, "ingress")) {
|
||||
|
||||
@ -37,10 +37,12 @@ typedef enum QDiscKind {
|
||||
typedef struct QDisc {
|
||||
TrafficControl meta;
|
||||
|
||||
ConfigSection *section;
|
||||
Link *link;
|
||||
Network *network;
|
||||
ConfigSection *section;
|
||||
NetworkConfigSource source;
|
||||
NetworkConfigState state;
|
||||
|
||||
int family;
|
||||
uint32_t handle;
|
||||
uint32_t parent;
|
||||
|
||||
@ -53,7 +55,6 @@ typedef struct QDiscVTable {
|
||||
const char *tca_kind;
|
||||
/* called in qdisc_new() */
|
||||
int (*init)(QDisc *qdisc);
|
||||
int (*fill_tca_kind)(Link *link, QDisc *qdisc, sd_netlink_message *m);
|
||||
int (*fill_message)(Link *link, QDisc *qdisc, sd_netlink_message *m);
|
||||
int (*verify)(QDisc *qdisc);
|
||||
} QDiscVTable;
|
||||
@ -74,12 +75,23 @@ extern const QDiscVTable * const qdisc_vtable[_QDISC_KIND_MAX];
|
||||
/* For casting the various qdisc kinds into a qdisc */
|
||||
#define QDISC(q) (&(q)->meta)
|
||||
|
||||
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(QDisc, qdisc);
|
||||
|
||||
QDisc* qdisc_free(QDisc *qdisc);
|
||||
int qdisc_new_static(QDiscKind kind, Network *network, const char *filename, unsigned section_line, QDisc **ret);
|
||||
|
||||
void qdisc_hash_func(const QDisc *qdic, struct siphash *state);
|
||||
int qdisc_compare_func(const QDisc *a, const QDisc *b);
|
||||
|
||||
int link_find_qdisc(Link *link, uint32_t handle, uint32_t parent, const char *kind, QDisc **qdisc);
|
||||
|
||||
int link_request_qdisc(Link *link, QDisc *qdisc);
|
||||
int qdisc_is_ready_to_configure(Link *link, QDisc *qdisc);
|
||||
int qdisc_configure(Link *link, QDisc *qdisc);
|
||||
int qdisc_section_verify(QDisc *qdisc, bool *has_root, bool *has_clsact);
|
||||
|
||||
int manager_rtnl_process_qdisc(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
|
||||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(QDisc, qdisc_free);
|
||||
|
||||
DEFINE_TC_CAST(QDISC, QDisc);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "macro.h"
|
||||
#include "networkd-queue.h"
|
||||
#include "qdisc.h"
|
||||
#include "tc.h"
|
||||
#include "tclass.h"
|
||||
@ -21,11 +22,88 @@ void traffic_control_free(TrafficControl *tc) {
|
||||
}
|
||||
}
|
||||
|
||||
void traffic_control_hash_func(const TrafficControl *tc, struct siphash *state) {
|
||||
assert(tc);
|
||||
assert(state);
|
||||
|
||||
siphash24_compress(&tc->kind, sizeof(tc->kind), state);
|
||||
|
||||
switch (tc->kind) {
|
||||
case TC_KIND_QDISC:
|
||||
qdisc_hash_func(TC_TO_QDISC_CONST(tc), state);
|
||||
break;
|
||||
case TC_KIND_TCLASS:
|
||||
tclass_hash_func(TC_TO_TCLASS_CONST(tc), state);
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
int traffic_control_compare_func(const TrafficControl *a, const TrafficControl *b) {
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
r = CMP(a->kind, b->kind);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
switch (a->kind) {
|
||||
case TC_KIND_QDISC:
|
||||
return qdisc_compare_func(TC_TO_QDISC_CONST(a), TC_TO_QDISC_CONST(b));
|
||||
case TC_KIND_TCLASS:
|
||||
return tclass_compare_func(TC_TO_TCLASS_CONST(a), TC_TO_TCLASS_CONST(b));
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||
traffic_control_hash_ops,
|
||||
TrafficControl,
|
||||
traffic_control_hash_func,
|
||||
traffic_control_compare_func,
|
||||
traffic_control_free);
|
||||
|
||||
int traffic_control_get(Link *link, const TrafficControl *in, TrafficControl **ret) {
|
||||
TrafficControl *existing;
|
||||
|
||||
assert(link);
|
||||
assert(in);
|
||||
|
||||
existing = set_get(link->traffic_control, in);
|
||||
if (!existing)
|
||||
return -ENOENT;
|
||||
|
||||
if (ret)
|
||||
*ret = existing;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int traffic_control_add(Link *link, TrafficControl *tc) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(tc);
|
||||
|
||||
/* This must be called only from qdisc_add() or tclass_add(). */
|
||||
|
||||
r = set_ensure_put(&link->traffic_control, &traffic_control_hash_ops, tc);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return -EEXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int traffic_control_configure(Link *link, TrafficControl *tc) {
|
||||
assert(link);
|
||||
assert(tc);
|
||||
|
||||
switch(tc->kind) {
|
||||
switch (tc->kind) {
|
||||
case TC_KIND_QDISC:
|
||||
return qdisc_configure(link, TC_TO_QDISC(tc));
|
||||
case TC_KIND_TCLASS:
|
||||
@ -35,38 +113,91 @@ static int traffic_control_configure(Link *link, TrafficControl *tc) {
|
||||
}
|
||||
}
|
||||
|
||||
int link_configure_traffic_control(Link *link) {
|
||||
static int link_request_traffic_control_one(Link *link, TrafficControl *tc) {
|
||||
assert(link);
|
||||
assert(tc);
|
||||
|
||||
switch (tc->kind) {
|
||||
case TC_KIND_QDISC:
|
||||
return link_request_qdisc(link, TC_TO_QDISC(tc));
|
||||
case TC_KIND_TCLASS:
|
||||
return link_request_tclass(link, TC_TO_TCLASS(tc));
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
int link_request_traffic_control(Link *link) {
|
||||
TrafficControl *tc;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
|
||||
if (link->tc_messages != 0) {
|
||||
log_link_debug(link, "Traffic control is configuring.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
link->tc_configured = false;
|
||||
|
||||
ORDERED_HASHMAP_FOREACH(tc, link->network->tc_by_section) {
|
||||
r = traffic_control_configure(link, tc);
|
||||
HASHMAP_FOREACH(tc, link->network->tc_by_section) {
|
||||
r = link_request_traffic_control_one(link, tc);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not create send configuration message: %m");
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->tc_messages == 0)
|
||||
if (link->tc_messages == 0) {
|
||||
link->tc_configured = true;
|
||||
else
|
||||
log_link_debug(link, "Configuring traffic control");
|
||||
link_check_ready(link);
|
||||
} else {
|
||||
log_link_debug(link, "Setting traffic control");
|
||||
link_set_state(link, LINK_STATE_CONFIGURING);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int traffic_control_is_ready_to_configure(Link *link, TrafficControl *tc) {
|
||||
assert(link);
|
||||
assert(tc);
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
|
||||
return false;
|
||||
|
||||
switch(tc->kind) {
|
||||
case TC_KIND_QDISC:
|
||||
return qdisc_is_ready_to_configure(link, TC_TO_QDISC(tc));
|
||||
case TC_KIND_TCLASS:
|
||||
return tclass_is_ready_to_configure(link, TC_TO_TCLASS(tc));
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
int request_process_traffic_control(Request *req) {
|
||||
TrafficControl *tc;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(req);
|
||||
assert(req->traffic_control);
|
||||
assert(req->type == REQUEST_TYPE_TRAFFIC_CONTROL);
|
||||
|
||||
link = ASSERT_PTR(req->link);
|
||||
tc = ASSERT_PTR(req->traffic_control);
|
||||
|
||||
r = traffic_control_is_ready_to_configure(link, tc);
|
||||
if (r <= 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = traffic_control_configure(link, tc);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int traffic_control_section_verify(TrafficControl *tc, bool *qdisc_has_root, bool *qdisc_has_clsact) {
|
||||
assert(tc);
|
||||
|
||||
switch(tc->kind) {
|
||||
switch (tc->kind) {
|
||||
case TC_KIND_QDISC:
|
||||
return qdisc_section_verify(TC_TO_QDISC(tc), qdisc_has_root, qdisc_has_clsact);
|
||||
case TC_KIND_TCLASS:
|
||||
@ -82,7 +213,7 @@ void network_drop_invalid_traffic_control(Network *network) {
|
||||
|
||||
assert(network);
|
||||
|
||||
ORDERED_HASHMAP_FOREACH(tc, network->tc_by_section)
|
||||
HASHMAP_FOREACH(tc, network->tc_by_section)
|
||||
if (traffic_control_section_verify(tc, &has_root, &has_clsact) < 0)
|
||||
traffic_control_free(tc);
|
||||
}
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
|
||||
#include "networkd-link.h"
|
||||
|
||||
typedef struct Request Request;
|
||||
|
||||
typedef enum TrafficControlKind {
|
||||
TC_KIND_QDISC,
|
||||
TC_KIND_TCLASS,
|
||||
@ -22,11 +24,25 @@ typedef struct TrafficControl {
|
||||
return NULL; \
|
||||
\
|
||||
return (MixedCase*) tc; \
|
||||
} \
|
||||
static inline const MixedCase* TC_TO_##UPPERCASE##_CONST(const TrafficControl *tc) { \
|
||||
if (_unlikely_(!tc || tc->kind != TC_KIND_##UPPERCASE)) \
|
||||
return NULL; \
|
||||
\
|
||||
return (const MixedCase*) tc; \
|
||||
}
|
||||
|
||||
/* For casting the various tc kinds into a tc */
|
||||
#define TC(tc) (&(tc)->meta)
|
||||
|
||||
void traffic_control_free(TrafficControl *tc);
|
||||
int link_configure_traffic_control(Link *link);
|
||||
void network_drop_invalid_traffic_control(Network *network);
|
||||
|
||||
void traffic_control_hash_func(const TrafficControl *tc, struct siphash *state);
|
||||
int traffic_control_compare_func(const TrafficControl *a, const TrafficControl *b);
|
||||
|
||||
int traffic_control_get(Link *link, const TrafficControl *in, TrafficControl **ret);
|
||||
int traffic_control_add(Link *link, TrafficControl *tc);
|
||||
|
||||
int link_request_traffic_control(Link *link);
|
||||
int request_process_traffic_control(Request *req);
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "in-addr-util.h"
|
||||
#include "netlink-util.h"
|
||||
#include "networkd-manager.h"
|
||||
#include "networkd-queue.h"
|
||||
#include "parse-util.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
@ -25,11 +26,23 @@ static int tclass_new(TClassKind kind, TClass **ret) {
|
||||
_cleanup_(tclass_freep) TClass *tclass = NULL;
|
||||
int r;
|
||||
|
||||
if (kind == _TCLASS_KIND_INVALID) {
|
||||
tclass = new(TClass, 1);
|
||||
if (!tclass)
|
||||
return -ENOMEM;
|
||||
|
||||
*tclass = (TClass) {
|
||||
.meta.kind = TC_KIND_TCLASS,
|
||||
.parent = TC_H_ROOT,
|
||||
.kind = kind,
|
||||
};
|
||||
} else {
|
||||
assert(kind >= 0 && kind < _TCLASS_KIND_MAX);
|
||||
tclass = malloc0(tclass_vtable[kind]->object_size);
|
||||
if (!tclass)
|
||||
return -ENOMEM;
|
||||
|
||||
tclass->meta.kind = TC_KIND_TCLASS,
|
||||
tclass->meta.kind = TC_KIND_TCLASS;
|
||||
tclass->parent = TC_H_ROOT;
|
||||
tclass->kind = kind;
|
||||
|
||||
@ -38,6 +51,7 @@ static int tclass_new(TClassKind kind, TClass **ret) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(tclass);
|
||||
|
||||
@ -59,7 +73,7 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
existing = ordered_hashmap_get(network->tc_by_section, n);
|
||||
existing = hashmap_get(network->tc_by_section, n);
|
||||
if (existing) {
|
||||
TClass *t;
|
||||
|
||||
@ -81,8 +95,9 @@ int tclass_new_static(TClassKind kind, Network *network, const char *filename, u
|
||||
|
||||
tclass->network = network;
|
||||
tclass->section = TAKE_PTR(n);
|
||||
tclass->source = NETWORK_CONFIG_SOURCE_STATIC;
|
||||
|
||||
r = ordered_hashmap_ensure_put(&network->tc_by_section, &config_section_hash_ops, tclass->section, tclass);
|
||||
r = hashmap_ensure_put(&network->tc_by_section, &config_section_hash_ops, tclass->section, tclass);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -95,13 +110,157 @@ TClass* tclass_free(TClass *tclass) {
|
||||
return NULL;
|
||||
|
||||
if (tclass->network && tclass->section)
|
||||
ordered_hashmap_remove(tclass->network->tc_by_section, tclass->section);
|
||||
hashmap_remove(tclass->network->tc_by_section, tclass->section);
|
||||
|
||||
config_section_free(tclass->section);
|
||||
|
||||
if (tclass->link)
|
||||
set_remove(tclass->link->traffic_control, TC(tclass));
|
||||
|
||||
free(tclass->tca_kind);
|
||||
return mfree(tclass);
|
||||
}
|
||||
|
||||
static const char *tclass_get_tca_kind(const TClass *tclass) {
|
||||
assert(tclass);
|
||||
|
||||
return (TCLASS_VTABLE(tclass) && TCLASS_VTABLE(tclass)->tca_kind) ?
|
||||
TCLASS_VTABLE(tclass)->tca_kind : tclass->tca_kind;
|
||||
}
|
||||
|
||||
void tclass_hash_func(const TClass *tclass, struct siphash *state) {
|
||||
assert(tclass);
|
||||
assert(state);
|
||||
|
||||
siphash24_compress(&tclass->classid, sizeof(tclass->classid), state);
|
||||
siphash24_compress(&tclass->parent, sizeof(tclass->parent), state);
|
||||
siphash24_compress_string(tclass_get_tca_kind(tclass), state);
|
||||
}
|
||||
|
||||
int tclass_compare_func(const TClass *a, const TClass *b) {
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
r = CMP(a->classid, b->classid);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = CMP(a->parent, b->parent);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return strcmp_ptr(tclass_get_tca_kind(a), tclass_get_tca_kind(b));
|
||||
}
|
||||
|
||||
static int tclass_get(Link *link, const TClass *in, TClass **ret) {
|
||||
TrafficControl *existing;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(in);
|
||||
|
||||
r = traffic_control_get(link, TC(in), &existing);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret)
|
||||
*ret = TC_TO_TCLASS(existing);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tclass_add(Link *link, TClass *tclass) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(tclass);
|
||||
|
||||
r = traffic_control_add(link, TC(tclass));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
tclass->link = link;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tclass_dup(const TClass *src, TClass **ret) {
|
||||
_cleanup_(tclass_freep) TClass *dst = NULL;
|
||||
|
||||
assert(src);
|
||||
assert(ret);
|
||||
|
||||
if (TCLASS_VTABLE(src))
|
||||
dst = memdup(src, TCLASS_VTABLE(src)->object_size);
|
||||
else
|
||||
dst = newdup(TClass, src, 1);
|
||||
if (!dst)
|
||||
return -ENOMEM;
|
||||
|
||||
/* clear all pointers */
|
||||
dst->network = NULL;
|
||||
dst->section = NULL;
|
||||
dst->link = NULL;
|
||||
dst->tca_kind = NULL;
|
||||
|
||||
if (src->tca_kind) {
|
||||
dst->tca_kind = strdup(src->tca_kind);
|
||||
if (!dst->tca_kind)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int link_find_tclass(Link *link, uint32_t classid, TClass **ret) {
|
||||
TrafficControl *tc;
|
||||
|
||||
assert(link);
|
||||
|
||||
SET_FOREACH(tc, link->traffic_control) {
|
||||
TClass *tclass;
|
||||
|
||||
if (tc->kind != TC_KIND_TCLASS)
|
||||
continue;
|
||||
|
||||
tclass = TC_TO_TCLASS(tc);
|
||||
|
||||
if (tclass->classid != classid)
|
||||
continue;
|
||||
|
||||
if (tclass->source == NETWORK_CONFIG_SOURCE_FOREIGN)
|
||||
continue;
|
||||
|
||||
if (!tclass_exists(tclass))
|
||||
continue;
|
||||
|
||||
if (ret)
|
||||
*ret = tclass;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static void log_tclass_debug(TClass *tclass, Link *link, const char *str) {
|
||||
_cleanup_free_ char *state = NULL;
|
||||
|
||||
assert(tclass);
|
||||
assert(str);
|
||||
|
||||
if (!DEBUG_LOGGING)
|
||||
return;
|
||||
|
||||
(void) network_config_state_to_string_alloc(tclass->state, &state);
|
||||
|
||||
log_link_debug(link, "%s %s TClass (%s): classid=%"PRIx32":%"PRIx32", parent=%"PRIx32":%"PRIx32", kind=%s",
|
||||
str, strna(network_config_source_to_string(tclass->source)), strna(state),
|
||||
TC_H_MAJ(tclass->classid) >> 16, TC_H_MIN(tclass->classid),
|
||||
TC_H_MAJ(tclass->parent) >> 16, TC_H_MIN(tclass->parent),
|
||||
strna(tclass_get_tca_kind(tclass)));
|
||||
}
|
||||
|
||||
static int tclass_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
@ -137,20 +296,13 @@ int tclass_configure(Link *link, TClass *tclass) {
|
||||
assert(link->manager->rtnl);
|
||||
assert(link->ifindex > 0);
|
||||
|
||||
r = sd_rtnl_message_new_tclass(link->manager->rtnl, &req, RTM_NEWTCLASS, AF_UNSPEC, link->ifindex);
|
||||
log_tclass_debug(tclass, link, "Configuring");
|
||||
|
||||
r = sd_rtnl_message_new_traffic_control(link->manager->rtnl, &req, RTM_NEWTCLASS,
|
||||
link->ifindex, tclass->classid, tclass->parent);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Could not create RTM_NEWTCLASS message: %m");
|
||||
|
||||
r = sd_rtnl_message_set_tclass_parent(req, tclass->parent);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (tclass->classid != TC_H_UNSPEC) {
|
||||
r = sd_rtnl_message_set_tclass_handle(req, tclass->classid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_append_string(req, TCA_KIND, TCLASS_VTABLE(tclass)->tca_kind);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -166,9 +318,157 @@ int tclass_configure(Link *link, TClass *tclass) {
|
||||
return log_link_debug_errno(link, r, "Could not send netlink message: %m");
|
||||
|
||||
link_ref(link);
|
||||
link->tc_messages++;
|
||||
|
||||
tclass_enter_configuring(tclass);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tclass_is_ready_to_configure(Link *link, TClass *tclass) {
|
||||
assert(link);
|
||||
assert(tclass);
|
||||
|
||||
return link_find_qdisc(link, tclass->classid, tclass->parent, tclass_get_tca_kind(tclass), NULL) >= 0;
|
||||
}
|
||||
|
||||
int link_request_tclass(Link *link, TClass *tclass) {
|
||||
TClass *existing;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(tclass);
|
||||
|
||||
if (tclass_get(link, tclass, &existing) < 0) {
|
||||
_cleanup_(tclass_freep) TClass *tmp = NULL;
|
||||
|
||||
r = tclass_dup(tclass, &tmp);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = tclass_add(link, tmp);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to store TClass: %m");
|
||||
|
||||
existing = TAKE_PTR(tmp);
|
||||
} else
|
||||
existing->source = tclass->source;
|
||||
|
||||
log_tclass_debug(existing, link, "Requesting");
|
||||
r = link_queue_request(link, REQUEST_TYPE_TRAFFIC_CONTROL, TC(existing), false,
|
||||
&link->tc_messages, NULL, NULL);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Failed to request TClass: %m");
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
tclass_enter_requesting(existing);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
|
||||
_cleanup_(tclass_freep) TClass *tmp = NULL;
|
||||
TClass *tclass = NULL;
|
||||
Link *link;
|
||||
uint16_t type;
|
||||
int ifindex, r;
|
||||
|
||||
assert(rtnl);
|
||||
assert(message);
|
||||
assert(m);
|
||||
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
r = sd_netlink_message_get_errno(message);
|
||||
if (r < 0)
|
||||
log_message_warning_errno(message, r, "rtnl: failed to receive TClass message, ignoring");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_get_type(message, &type);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: could not get message type, ignoring: %m");
|
||||
return 0;
|
||||
} else if (!IN_SET(type, RTM_NEWTCLASS, RTM_DELTCLASS)) {
|
||||
log_warning("rtnl: received unexpected message type %u when processing TClass, ignoring.", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_traffic_control_get_ifindex(message, &ifindex);
|
||||
if (r < 0) {
|
||||
log_warning_errno(r, "rtnl: could not get ifindex from message, ignoring: %m");
|
||||
return 0;
|
||||
} else if (ifindex <= 0) {
|
||||
log_warning("rtnl: received TClass message with invalid ifindex %d, ignoring.", ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (link_get_by_index(m, ifindex, &link) < 0) {
|
||||
if (!m->enumerating)
|
||||
log_warning("rtnl: received TClass for link '%d' we don't know about, ignoring.", ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = tclass_new(_TCLASS_KIND_INVALID, &tmp);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
r = sd_rtnl_message_traffic_control_get_handle(message, &tmp->classid);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: received TClass message without handle, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_traffic_control_get_parent(message, &tmp->parent);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: received TClass message without parent, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_string_strdup(message, TCA_KIND, &tmp->tca_kind);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "rtnl: received TClass message without kind, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) tclass_get(link, tmp, &tclass);
|
||||
|
||||
switch (type) {
|
||||
case RTM_NEWTCLASS:
|
||||
if (tclass) {
|
||||
tclass_enter_configured(tclass);
|
||||
log_tclass_debug(tclass, link, "Received remembered");
|
||||
} else {
|
||||
tclass_enter_configured(tmp);
|
||||
log_tclass_debug(tmp, link, "Received new");
|
||||
|
||||
r = tclass_add(link, tmp);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Failed to remember TClass, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
tclass = TAKE_PTR(tmp);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RTM_DELTCLASS:
|
||||
if (tclass) {
|
||||
tclass_enter_removed(tclass);
|
||||
if (tclass->state == 0) {
|
||||
log_tclass_debug(tclass, link, "Forgetting");
|
||||
tclass_free(tclass);
|
||||
} else
|
||||
log_tclass_debug(tclass, link, "Removed");
|
||||
} else
|
||||
log_tclass_debug(tmp, link, "Kernel removed unknown");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tclass_section_verify(TClass *tclass) {
|
||||
|
||||
@ -19,13 +19,17 @@ typedef enum TClassKind {
|
||||
typedef struct TClass {
|
||||
TrafficControl meta;
|
||||
|
||||
ConfigSection *section;
|
||||
Link *link;
|
||||
Network *network;
|
||||
ConfigSection *section;
|
||||
NetworkConfigSource source;
|
||||
NetworkConfigState state;
|
||||
|
||||
uint32_t classid;
|
||||
uint32_t parent;
|
||||
|
||||
TClassKind kind;
|
||||
char *tca_kind;
|
||||
} TClass;
|
||||
|
||||
typedef struct TClassVTable {
|
||||
@ -53,12 +57,23 @@ extern const TClassVTable * const tclass_vtable[_TCLASS_KIND_MAX];
|
||||
/* For casting the various tclass kinds into a tclass */
|
||||
#define TCLASS(t) (&(t)->meta)
|
||||
|
||||
DEFINE_NETWORK_CONFIG_STATE_FUNCTIONS(TClass, tclass);
|
||||
|
||||
TClass* tclass_free(TClass *tclass);
|
||||
int tclass_new_static(TClassKind kind, Network *network, const char *filename, unsigned section_line, TClass **ret);
|
||||
|
||||
void tclass_hash_func(const TClass *tclass, struct siphash *state);
|
||||
int tclass_compare_func(const TClass *a, const TClass *b);
|
||||
|
||||
int link_find_tclass(Link *link, uint32_t classid, TClass **ret);
|
||||
|
||||
int link_request_tclass(Link *link, TClass *tclass);
|
||||
int tclass_is_ready_to_configure(Link *link, TClass *tclass);
|
||||
int tclass_configure(Link *link, TClass *tclass);
|
||||
int tclass_section_verify(TClass *tclass);
|
||||
|
||||
int manager_rtnl_process_tclass(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
|
||||
|
||||
DEFINE_SECTION_CLEANUP_FUNCTIONS(TClass, tclass_free);
|
||||
|
||||
DEFINE_TC_CAST(TCLASS, TClass);
|
||||
|
||||
@ -1,34 +1,25 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "macro.h"
|
||||
#include "netlink-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "teql.h"
|
||||
|
||||
static int trivial_link_equalizer_fill_tca_kind(Link *link, QDisc *qdisc, sd_netlink_message *req) {
|
||||
char kind[STRLEN("teql") + DECIMAL_STR_MAX(unsigned)];
|
||||
static int trivial_link_equalizer_verify(QDisc *qdisc) {
|
||||
_cleanup_free_ char *tca_kind = NULL;
|
||||
TrivialLinkEqualizer *teql;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(qdisc);
|
||||
assert(req);
|
||||
teql = TEQL(ASSERT_PTR(qdisc));
|
||||
|
||||
teql = TEQL(qdisc);
|
||||
if (asprintf(&tca_kind, "teql%u", teql->id) < 0)
|
||||
return log_oom();
|
||||
|
||||
xsprintf(kind, "teql%u", teql->id);
|
||||
r = sd_netlink_message_append_string(req, TCA_KIND, kind);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not append TCA_KIND attribute: %m");
|
||||
|
||||
return 0;
|
||||
return free_and_replace(qdisc->tca_kind, tca_kind);
|
||||
}
|
||||
|
||||
const QDiscVTable teql_vtable = {
|
||||
.object_size = sizeof(TrivialLinkEqualizer),
|
||||
.fill_tca_kind = trivial_link_equalizer_fill_tca_kind,
|
||||
.verify = trivial_link_equalizer_verify,
|
||||
};
|
||||
|
||||
int config_parse_trivial_link_equalizer_id(
|
||||
|
||||
@ -24,7 +24,7 @@ Exec.Ephemeral, config_parse_tristate, 0, of
|
||||
Exec.ProcessTwo, config_parse_pid2, 0, 0
|
||||
Exec.Parameters, config_parse_strv, 0, offsetof(Settings, parameters)
|
||||
Exec.Environment, config_parse_strv, 0, offsetof(Settings, environment)
|
||||
Exec.User, config_parse_string, 0, offsetof(Settings, user)
|
||||
Exec.User, config_parse_safe_string, 0, offsetof(Settings, user)
|
||||
Exec.Capability, config_parse_capability, 0, offsetof(Settings, capability)
|
||||
Exec.AmbientCapability, config_parse_capability, 0, offsetof(Settings, ambient_capability)
|
||||
Exec.DropCapability, config_parse_capability, 0, offsetof(Settings, drop_capability)
|
||||
|
||||
@ -40,18 +40,18 @@ int config_item_table_lookup(
|
||||
const void *table,
|
||||
const char *section,
|
||||
const char *lvalue,
|
||||
ConfigParserCallback *func,
|
||||
int *ltype,
|
||||
void **data,
|
||||
ConfigParserCallback *ret_func,
|
||||
int *ret_ltype,
|
||||
void **ret_data,
|
||||
void *userdata) {
|
||||
|
||||
const ConfigTableItem *t;
|
||||
|
||||
assert(table);
|
||||
assert(lvalue);
|
||||
assert(func);
|
||||
assert(ltype);
|
||||
assert(data);
|
||||
assert(ret_func);
|
||||
assert(ret_ltype);
|
||||
assert(ret_data);
|
||||
|
||||
for (t = table; t->lvalue; t++) {
|
||||
|
||||
@ -61,12 +61,15 @@ int config_item_table_lookup(
|
||||
if (!streq_ptr(section, t->section))
|
||||
continue;
|
||||
|
||||
*func = t->parse;
|
||||
*ltype = t->ltype;
|
||||
*data = t->data;
|
||||
*ret_func = t->parse;
|
||||
*ret_ltype = t->ltype;
|
||||
*ret_data = t->data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
*ret_func = NULL;
|
||||
*ret_ltype = 0;
|
||||
*ret_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -74,9 +77,9 @@ int config_item_perf_lookup(
|
||||
const void *table,
|
||||
const char *section,
|
||||
const char *lvalue,
|
||||
ConfigParserCallback *func,
|
||||
int *ltype,
|
||||
void **data,
|
||||
ConfigParserCallback *ret_func,
|
||||
int *ret_ltype,
|
||||
void **ret_data,
|
||||
void *userdata) {
|
||||
|
||||
ConfigPerfItemLookup lookup = (ConfigPerfItemLookup) table;
|
||||
@ -84,9 +87,9 @@ int config_item_perf_lookup(
|
||||
|
||||
assert(table);
|
||||
assert(lvalue);
|
||||
assert(func);
|
||||
assert(ltype);
|
||||
assert(data);
|
||||
assert(ret_func);
|
||||
assert(ret_ltype);
|
||||
assert(ret_data);
|
||||
|
||||
if (section) {
|
||||
const char *key;
|
||||
@ -95,12 +98,16 @@ int config_item_perf_lookup(
|
||||
p = lookup(key, strlen(key));
|
||||
} else
|
||||
p = lookup(lvalue, strlen(lvalue));
|
||||
if (!p)
|
||||
if (!p) {
|
||||
*ret_func = NULL;
|
||||
*ret_ltype = 0;
|
||||
*ret_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*func = p->parse;
|
||||
*ltype = p->ltype;
|
||||
*data = (uint8_t*) userdata + p->offset;
|
||||
*ret_func = p->parse;
|
||||
*ret_ltype = p->ltype;
|
||||
*ret_data = (uint8_t*) userdata + p->offset;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -133,11 +140,11 @@ static int next_assignment(
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
if (func)
|
||||
if (!func)
|
||||
return 0;
|
||||
|
||||
return func(unit, filename, line, section, section_line,
|
||||
lvalue, ltype, rvalue, data, userdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Warn about unknown non-extension fields. */
|
||||
@ -160,7 +167,7 @@ static int parse_line(
|
||||
char **section,
|
||||
unsigned *section_line,
|
||||
bool *section_ignored,
|
||||
char *l,
|
||||
char *l, /* is modified */
|
||||
void *userdata) {
|
||||
|
||||
char *e;
|
||||
@ -171,18 +178,18 @@ static int parse_line(
|
||||
assert(l);
|
||||
|
||||
l = strstrip(l);
|
||||
if (!*l)
|
||||
if (isempty(l))
|
||||
return 0;
|
||||
|
||||
if (*l == '\n')
|
||||
if (l[0] == '\n')
|
||||
return 0;
|
||||
|
||||
if (!utf8_is_valid(l))
|
||||
return log_syntax_invalid_utf8(unit, LOG_WARNING, filename, line, l);
|
||||
|
||||
if (*l == '[') {
|
||||
if (l[0] == '[') {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
size_t k;
|
||||
char *n;
|
||||
|
||||
k = strlen(l);
|
||||
assert(k > 0);
|
||||
@ -194,15 +201,18 @@ static int parse_line(
|
||||
if (!n)
|
||||
return log_oom();
|
||||
|
||||
if (!string_is_safe(n))
|
||||
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EBADMSG), "Bad characters in section header '%s'", l);
|
||||
|
||||
if (sections && !nulstr_contains(sections, n)) {
|
||||
bool ignore = flags & CONFIG_PARSE_RELAXED;
|
||||
bool ignore;
|
||||
const char *t;
|
||||
|
||||
ignore = ignore || startswith(n, "X-");
|
||||
ignore = (flags & CONFIG_PARSE_RELAXED) || startswith(n, "X-");
|
||||
|
||||
if (!ignore)
|
||||
NULSTR_FOREACH(t, sections)
|
||||
if (streq_ptr(n, startswith(t, "-"))) {
|
||||
if (streq_ptr(n, startswith(t, "-"))) { /* Ignore sections prefixed with "-" in valid section list */
|
||||
ignore = true;
|
||||
break;
|
||||
}
|
||||
@ -210,7 +220,6 @@ static int parse_line(
|
||||
if (!ignore)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown section '%s'. Ignoring.", n);
|
||||
|
||||
free(n);
|
||||
*section = mfree(*section);
|
||||
*section_line = 0;
|
||||
*section_ignored = true;
|
||||
@ -633,6 +642,7 @@ DEFINE_PARSER(nsec, nsec_t, parse_nsec);
|
||||
DEFINE_PARSER(sec, usec_t, parse_sec);
|
||||
DEFINE_PARSER(sec_def_infinity, usec_t, parse_sec_def_infinity);
|
||||
DEFINE_PARSER(mode, mode_t, parse_mode);
|
||||
DEFINE_PARSER(pid, pid_t, parse_pid);
|
||||
|
||||
int config_parse_iec_size(
|
||||
const char* unit,
|
||||
@ -873,6 +883,33 @@ int config_parse_string(
|
||||
return free_and_strdup_warn(s, empty_to_null(rvalue));
|
||||
}
|
||||
|
||||
int config_parse_safe_string(
|
||||
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) {
|
||||
|
||||
char **s = data;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (!string_is_safe(rvalue)) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Specified string contains unsafe characters, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return free_and_strdup_warn(s, empty_to_null(rvalue));
|
||||
}
|
||||
|
||||
int config_parse_path(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
||||
@ -69,18 +69,18 @@ typedef int (*ConfigItemLookup)(
|
||||
const void *table,
|
||||
const char *section,
|
||||
const char *lvalue,
|
||||
ConfigParserCallback *func,
|
||||
int *ltype,
|
||||
void **data,
|
||||
ConfigParserCallback *ret_func,
|
||||
int *ret_ltype,
|
||||
void **ret_data,
|
||||
void *userdata);
|
||||
|
||||
/* Linear table search implementation of ConfigItemLookup, based on
|
||||
* ConfigTableItem arrays */
|
||||
int config_item_table_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata);
|
||||
int config_item_table_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *ret_func, int *ret_ltype, void **ret_data, void *userdata);
|
||||
|
||||
/* gperf implementation of ConfigItemLookup, based on gperf
|
||||
* ConfigPerfItem tables */
|
||||
int config_item_perf_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata);
|
||||
int config_item_perf_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *ret_func, int *ret_ltype, void **ret_data, void *userdata);
|
||||
|
||||
int config_parse(
|
||||
const char *unit,
|
||||
@ -168,6 +168,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_bool);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_id128);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_tristate);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_string);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_safe_string);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_path);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_strv);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_sec);
|
||||
@ -194,6 +195,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ether_addrs);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_non_null);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_percent);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_permyriad);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_pid);
|
||||
|
||||
typedef enum Disabled {
|
||||
DISABLED_CONFIGURATION,
|
||||
|
||||
@ -202,13 +202,11 @@ int sd_rtnl_message_routing_policy_rule_get_fib_type(sd_netlink_message *m, uint
|
||||
int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, uint32_t flags);
|
||||
int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, uint32_t *flags);
|
||||
|
||||
int sd_rtnl_message_new_qdisc(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int tcm_family, int tcm_ifindex);
|
||||
int sd_rtnl_message_set_qdisc_parent(sd_netlink_message *m, uint32_t parent);
|
||||
int sd_rtnl_message_set_qdisc_handle(sd_netlink_message *m, uint32_t handle);
|
||||
|
||||
int sd_rtnl_message_new_tclass(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int tcm_family, int tcm_ifindex);
|
||||
int sd_rtnl_message_set_tclass_parent(sd_netlink_message *m, uint32_t parent);
|
||||
int sd_rtnl_message_set_tclass_handle(sd_netlink_message *m, uint32_t handle);
|
||||
int sd_rtnl_message_new_traffic_control(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type,
|
||||
int ifindex, uint32_t handle, uint32_t parent);
|
||||
int sd_rtnl_message_traffic_control_get_ifindex(sd_netlink_message *m, int *ret);
|
||||
int sd_rtnl_message_traffic_control_get_handle(sd_netlink_message *m, uint32_t *ret);
|
||||
int sd_rtnl_message_traffic_control_get_parent(sd_netlink_message *m, uint32_t *ret);
|
||||
|
||||
int sd_rtnl_message_new_mdb(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int mdb_ifindex);
|
||||
|
||||
|
||||
@ -174,13 +174,13 @@ static int process_one_password_file(const char *filename) {
|
||||
_cleanup_free_ char *socket_name = NULL, *message = NULL;
|
||||
bool accept_cached = false, echo = false, silent = false;
|
||||
uint64_t not_after = 0;
|
||||
unsigned pid = 0;
|
||||
pid_t pid = 0;
|
||||
|
||||
const ConfigTableItem items[] = {
|
||||
{ "Ask", "Socket", config_parse_string, 0, &socket_name },
|
||||
{ "Ask", "Socket", config_parse_safe_string, 0, &socket_name },
|
||||
{ "Ask", "NotAfter", config_parse_uint64, 0, ¬_after },
|
||||
{ "Ask", "Message", config_parse_string, 0, &message },
|
||||
{ "Ask", "PID", config_parse_unsigned, 0, &pid },
|
||||
{ "Ask", "PID", config_parse_pid, 0, &pid },
|
||||
{ "Ask", "AcceptCached", config_parse_bool, 0, &accept_cached },
|
||||
{ "Ask", "Echo", config_parse_bool, 0, &echo },
|
||||
{ "Ask", "Silent", config_parse_bool, 0, &silent },
|
||||
@ -212,14 +212,14 @@ static int process_one_password_file(const char *filename) {
|
||||
|
||||
switch (arg_action) {
|
||||
case ACTION_LIST:
|
||||
printf("'%s' (PID %u)\n", strna(message), pid);
|
||||
printf("'%s' (PID " PID_FMT ")\n", strna(message), pid);
|
||||
return 0;
|
||||
|
||||
case ACTION_WALL: {
|
||||
_cleanup_free_ char *wall = NULL;
|
||||
|
||||
if (asprintf(&wall,
|
||||
"Password entry required for \'%s\' (PID %u).\r\n"
|
||||
"Password entry required for \'%s\' (PID " PID_FMT ").\r\n"
|
||||
"Please enter password with the systemd-tty-ask-password-agent tool.",
|
||||
strna(message),
|
||||
pid) < 0)
|
||||
@ -235,7 +235,7 @@ static int process_one_password_file(const char *filename) {
|
||||
|
||||
if (access(socket_name, W_OK) < 0) {
|
||||
if (arg_action == ACTION_QUERY)
|
||||
log_info("Not querying '%s' (PID %u), lacking privileges.", strna(message), pid);
|
||||
log_info("Not querying '%s' (PID " PID_FMT "), lacking privileges.", strna(message), pid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -288,22 +288,22 @@ static int xdg_config_item_table_lookup(
|
||||
const void *table,
|
||||
const char *section,
|
||||
const char *lvalue,
|
||||
ConfigParserCallback *func,
|
||||
int *ltype,
|
||||
void **data,
|
||||
ConfigParserCallback *ret_func,
|
||||
int *ret_ltype,
|
||||
void **ret_data,
|
||||
void *userdata) {
|
||||
|
||||
assert(lvalue);
|
||||
|
||||
/* Ignore any keys with [] as those are translations. */
|
||||
if (strchr(lvalue, '[')) {
|
||||
*func = NULL;
|
||||
*ltype = 0;
|
||||
*data = NULL;
|
||||
*ret_func = NULL;
|
||||
*ret_ltype = 0;
|
||||
*ret_data = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return config_item_table_lookup(table, section, lvalue, func, ltype, data, userdata);
|
||||
return config_item_table_lookup(table, section, lvalue, ret_func, ret_ltype, ret_data, userdata);
|
||||
}
|
||||
|
||||
XdgAutostartService *xdg_autostart_service_parse_desktop(const char *path) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user