diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 3bf54e1379a..43fc7efb74b 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -1946,6 +1946,15 @@ DNS=. + + LPRServers= + + Similar to the DNS= setting described above, this + setting configures whether and what LPR (line printer) server information shall be emitted + as part of the DHCP lease. The same syntax, propagation semantics and defaults apply as for + DNS=. + + EmitRouter= diff --git a/src/libsystemd-network/dhcp-lease-internal.h b/src/libsystemd-network/dhcp-lease-internal.h index 5cbebb4a34b..67a77eb098c 100644 --- a/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/libsystemd-network/dhcp-lease-internal.h @@ -67,6 +67,9 @@ struct sd_dhcp_lease { struct in_addr *smtp_server; size_t smtp_server_size; + struct in_addr *lpr_server; + size_t lpr_server_size; + struct sd_dhcp_route *static_route; size_t static_route_size, static_route_allocated; diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index 1b427124798..a45167b198e 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -55,8 +55,8 @@ struct sd_dhcp_server { char *timezone; - struct in_addr *ntp, *dns, *sip, *pop3_server, *smtp_server; - unsigned n_ntp, n_dns, n_sip, n_pop3_server, n_smtp_server; + struct in_addr *ntp, *dns, *sip, *pop3_server, *smtp_server, *lpr_server; + unsigned n_ntp, n_dns, n_sip, n_pop3_server, n_smtp_server, n_lpr_server; OrderedHashmap *extra_options; OrderedHashmap *vendor_options; diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index 56ea1925869..29688f2d4fe 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -140,6 +140,13 @@ int sd_dhcp_lease_get_servers( *addr = lease->smtp_server; return (int) lease->smtp_server_size; + case SD_DHCP_LEASE_LPR_SERVERS: + if (lease->lpr_server_size <= 0) + return -ENODATA; + + *addr = lease->lpr_server; + return (int) lease->lpr_server_size; + default: return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Unknown DHCP lease info item %d.", what); @@ -161,6 +168,9 @@ int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **a int sd_dhcp_lease_get_smtp_server(sd_dhcp_lease *lease, const struct in_addr **addr) { return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SMTP_SERVERS, addr); } +int sd_dhcp_lease_get_lpr_servers(sd_dhcp_lease *lease, const struct in_addr **addr) { + return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_LPR_SERVERS, addr); +} int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { assert_return(lease, -EINVAL); @@ -314,6 +324,7 @@ static sd_dhcp_lease *dhcp_lease_free(sd_dhcp_lease *lease) { free(lease->sip); free(lease->pop3_server); free(lease->smtp_server); + free(lease->lpr_server); free(lease->static_route); free(lease->client_id); free(lease->vendor_specific); @@ -648,6 +659,12 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void log_debug_errno(r, "Failed to parse SMTP server, ignoring: %m"); break; + case SD_DHCP_OPTION_LPR_SERVER: + r = lease_parse_in_addrs(option, len, &lease->lpr_server, &lease->lpr_server_size); + if (r < 0) + log_debug_errno(r, "Failed to parse LPR server, ignoring: %m"); + break; + case SD_DHCP_OPTION_STATIC_ROUTE: r = lease_parse_routes(option, len, &lease->static_route, &lease->static_route_size, &lease->static_route_allocated); if (r < 0) @@ -1086,6 +1103,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { *sip = NULL, *pop3_server = NULL, *smtp_server = NULL, + *lpr_server = NULL, *mtu = NULL, *routes = NULL, *domains = NULL, @@ -1117,6 +1135,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { "SIP", &sip, "POP3_SERVERS", &pop3_server, "SMTP_SERVERS", &smtp_server, + "LPR_SERVERS", &lpr_server, "MTU", &mtu, "DOMAINNAME", &lease->domainname, "HOSTNAME", &lease->hostname, @@ -1245,6 +1264,15 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { lease->smtp_server_size = r; } + if (lpr_server) { + r = deserialize_in_addrs(&lease->lpr_server, lpr_server); + if (r < 0) + log_debug_errno(r, "Failed to deserialize LPR server %s, ignoring: %m", lpr_server); + else + lease->lpr_server_size = r; + } + + if (mtu) { r = safe_atou16(mtu, &lease->mtu); if (r < 0) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 1c61749ef06..57eed765eea 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -142,6 +142,7 @@ static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) { free(server->sip); free(server->pop3_server); free(server->smtp_server); + free(server->lpr_server); hashmap_free(server->leases_by_client_id); @@ -533,6 +534,15 @@ static int server_send_ack(sd_dhcp_server *server, DHCPRequest *req, return r; } + if (server->n_lpr_server > 0) { + r = dhcp_option_append( + &packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_LPR_SERVER, + sizeof(struct in_addr) * server->n_lpr_server, server->lpr_server); + if (r < 0) + return r; + } + if (server->timezone) { r = dhcp_option_append( &packet->dhcp, req->max_optlen, &offset, 0, @@ -1161,6 +1171,11 @@ int sd_dhcp_server_set_servers( n_a = &server->n_smtp_server; break; + case SD_DHCP_LEASE_LPR_SERVERS: + a = &server->lpr_server; + n_a = &server->n_lpr_server; + break; + default: return log_debug_errno(SYNTHETIC_ERRNO(ENXIO), "Unknown DHCP lease info item %d.", what); @@ -1199,6 +1214,9 @@ int sd_dhcp_server_set_pop3_server(sd_dhcp_server *server, const struct in_addr int sd_dhcp_server_set_smtp_server(sd_dhcp_server *server, const struct in_addr smtp[], unsigned n) { return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_SMTP_SERVERS, smtp, n); } +int sd_dhcp_server_set_lpr(sd_dhcp_server *server, const struct in_addr lpr[], unsigned n) { + return sd_dhcp_server_set_servers(server, SD_DHCP_LEASE_LPR_SERVERS, lpr, n); +} int sd_dhcp_server_set_emit_router(sd_dhcp_server *server, int enabled) { assert_return(server, -EINVAL); diff --git a/src/libsystemd/sd-network/sd-network.c b/src/libsystemd/sd-network/sd-network.c index acfab8ed74f..7e03817f82f 100644 --- a/src/libsystemd/sd-network/sd-network.c +++ b/src/libsystemd/sd-network/sd-network.c @@ -264,6 +264,10 @@ _public_ int sd_network_link_get_smtp_servers(int ifindex, char ***ret) { return network_link_get_strv(ifindex, "SMTP_SERVERS", ret); } +_public_ int sd_network_link_get_lpr_servers(int ifindex, char ***ret) { + return network_link_get_strv(ifindex, "LPR_SERVERS", ret); +} + _public_ int sd_network_link_get_dns_default_route(int ifindex) { char path[STRLEN("/run/systemd/netif/links/") + DECIMAL_STR_MAX(ifindex) + 1]; _cleanup_free_ char *s = NULL; diff --git a/src/network/networkctl.c b/src/network/networkctl.c index 2e2ba4732cd..cb04807f3a9 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -1241,7 +1241,7 @@ static int link_status_one( const LinkInfo *info) { _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **sip = NULL, **search_domains = NULL, **route_domains = NULL, - **pop3_server = NULL, **smtp_server = NULL; + **pop3_server = NULL, **smtp_server = NULL, **lpr_server = NULL; _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL; _cleanup_free_ char *t = NULL, *network = NULL; const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL; @@ -1270,6 +1270,7 @@ static int link_status_one( (void) sd_network_link_get_sip(info->ifindex, &sip); (void) sd_network_link_get_pop3_servers(info->ifindex, &pop3_server); (void) sd_network_link_get_smtp_servers(info->ifindex, &smtp_server); + (void) sd_network_link_get_lpr_servers(info->ifindex, &lpr_server); if (info->sd_device) { (void) sd_device_get_property_value(info->sd_device, "ID_NET_LINK_FILE", &link); @@ -1844,6 +1845,9 @@ static int link_status_one( if (r < 0) return r; r = dump_list(table, "SMTP servers:", smtp_server); + if (r < 0) + return r; + r = dump_list(table, "LPR servers:", lpr_server); if (r < 0) return r; r = dump_ifindexes(table, "Carrier Bound To:", carrier_bound_to); diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 7859768f5e6..c0df1fb2c4c 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -127,6 +127,11 @@ static int link_push_uplink_to_dhcp_server( lease_condition = link->network->dhcp_use_sip; break; + case SD_DHCP_LEASE_LPR_SERVERS: + servers = link->network->lpr; + lease_condition = true; + break; + default: assert_not_reached("Unknown DHCP lease info item"); } @@ -238,6 +243,11 @@ int dhcp4_server_configure(Link *link) { link->network->dhcp_server_smtp, link->network->n_dhcp_server_smtp, }, + [SD_DHCP_LEASE_LPR_SERVERS] = { + true, + link->network->dhcp_server_lpr, + link->network->n_dhcp_server_lpr, + }, }; assert_cc(ELEMENTSOF(configs) == _SD_DHCP_LEASE_INFO_MAX); @@ -454,3 +464,23 @@ int config_parse_dhcp_server_smtp_servers( &n->dhcp_server_smtp, &n->n_dhcp_server_smtp); } + +int config_parse_dhcp_server_lpr_servers( + 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) { + + Network *n = data; + + return config_parse_dhcp_lease_server_list(unit, filename, line, + lvalue, rvalue, + &n->dhcp_server_lpr, &n->n_dhcp_server_lpr); + +} diff --git a/src/network/networkd-dhcp-server.h b/src/network/networkd-dhcp-server.h index 9da475dd3f4..898e9acd524 100644 --- a/src/network/networkd-dhcp-server.h +++ b/src/network/networkd-dhcp-server.h @@ -14,3 +14,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_sip); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_pop3_servers); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_smtp_servers); +CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_lpr_servers); diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 7672b33128c..e261473f6f2 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -3951,9 +3951,9 @@ static void link_save_dns(FILE *f, struct in_addr_data *dns, unsigned n_dns, boo } int link_save(Link *link) { + const char *admin_state, *oper_state, *carrier_state, *address_state; _cleanup_free_ char *temp_path = NULL; _cleanup_fclose_ FILE *f = NULL; - const char *admin_state, *oper_state, *carrier_state, *address_state; Address *a; Route *route; Iterator i; @@ -4112,6 +4112,12 @@ int link_save(Link *link) { space = false; fputstrv(f, link->network->smtp, NULL, &space); + fputc('\n', f); + + fputs("LPR_SERVERS=", f); + space = false; + fputstrv(f, link->network->lpr, NULL, &space); + if (link->dhcp_lease) { const struct in_addr *addresses; @@ -4130,6 +4136,15 @@ int link_save(Link *link) { space = true; } + if (link->dhcp_lease) { + const struct in_addr *addresses; + + r = sd_dhcp_lease_get_lpr_servers(link->dhcp_lease, &addresses); + if (r > 0) + if (serialize_in_addrs(f, addresses, r, space, in4_addr_is_non_local) > 0) + space = true; + } + if (link->network->dhcp6_use_ntp && dhcp6_lease) { struct in6_addr *in6_addrs; char **hosts; diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 31bf02f5002..3e9fb8c2179 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -1495,7 +1495,7 @@ static int ordered_set_put_in4_addrv(OrderedSet *s, static int manager_save(Manager *m) { _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *pop3 = NULL, - *smtp = NULL, *search_domains = NULL, *route_domains = NULL; + *smtp = NULL, *lpr = NULL, *search_domains = NULL, *route_domains = NULL; const char *operstate_str, *carrier_state_str, *address_state_str; LinkOperationalState operstate = LINK_OPERSTATE_OFF; LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF; @@ -1529,8 +1529,12 @@ static int manager_save(Manager *m) { return -ENOMEM; smtp = ordered_set_new(&string_hash_ops); - if (!smtp) - return -ENOMEM; + if (!smtp) + return -ENOMEM; + + lpr = ordered_set_new(&string_hash_ops); + if (!lpr) + return -ENOMEM; search_domains = ordered_set_new(&dns_name_hash_ops); if (!search_domains) @@ -1623,6 +1627,14 @@ static int manager_save(Manager *m) { } else if (r < 0 && r != -ENODATA) return r; + r = sd_dhcp_lease_get_lpr_servers(link->dhcp_lease, &addresses); + if (r > 0) { + r = ordered_set_put_in4_addrv(lpr, addresses, r, in4_addr_is_non_local); + if (r < 0) + return r; + } else if (r < 0 && r != -ENODATA) + return r; + if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { const char *domainname; char **domains = NULL; @@ -1676,6 +1688,7 @@ static int manager_save(Manager *m) { ordered_set_print(f, "SIP=", sip); ordered_set_print(f, "POP3_SERVERS=", pop3); ordered_set_print(f, "SMTP_SERVERS=", smtp); + ordered_set_print(f, "LPR_SERVERS=", lpr); ordered_set_print(f, "DOMAINS=", search_domains); ordered_set_print(f, "ROUTE_DOMAINS=", route_domains); diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 1a37c4ac9e7..e376adbdeee 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -212,6 +212,7 @@ DHCPServer.EmitSIP, config_parse_bool, DHCPServer.SIP, config_parse_dhcp_server_sip, 0, 0 DHCPServer.POP3Servers, config_parse_dhcp_server_pop3_servers, 0, 0 DHCPServer.SMTPServers, config_parse_dhcp_server_smtp_servers, 0, 0 +DHCPServer.LPRServers, config_parse_dhcp_server_lpr_servers, 0, 0 DHCPServer.EmitRouter, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_router) DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone) DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone) diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 26656861436..cbdeda96fc4 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -155,6 +155,9 @@ struct Network { struct in_addr *dhcp_server_smtp; unsigned n_dhcp_server_smtp; + struct in_addr *dhcp_server_lpr; + unsigned n_dhcp_server_lpr; + bool dhcp_server_emit_router; bool dhcp_server_emit_timezone; char *dhcp_server_timezone; @@ -312,6 +315,7 @@ struct Network { char **sip; char **pop3; char **smtp; + char **lpr; char **bind_carrier; }; diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c index 3d1d3bd6845..5471e745923 100644 --- a/src/network/networkd-util.c +++ b/src/network/networkd-util.c @@ -43,6 +43,7 @@ static const char* const dhcp_lease_info_table[_SD_DHCP_LEASE_INFO_MAX] = { [SD_DHCP_LEASE_SIP_SERVERS] = "SIP servers", [SD_DHCP_LEASE_POP3_SERVERS] = "POP3 servers", [SD_DHCP_LEASE_SMTP_SERVERS] = "SMTP servers", + [SD_DHCP_LEASE_LPR_SERVERS] = "LPR servers", }; DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(address_family, AddressFamily, ADDRESS_FAMILY_YES); diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index da2aa6c73b7..032afc9f127 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -48,6 +48,7 @@ enum { SD_DHCP_OPTION_TIME_OFFSET = 2, SD_DHCP_OPTION_ROUTER = 3, SD_DHCP_OPTION_DOMAIN_NAME_SERVER = 6, + SD_DHCP_OPTION_LPR_SERVER = 9, SD_DHCP_OPTION_HOST_NAME = 12, SD_DHCP_OPTION_BOOT_FILE_SIZE = 13, SD_DHCP_OPTION_DOMAIN_NAME = 15, diff --git a/src/systemd/sd-dhcp-lease.h b/src/systemd/sd-dhcp-lease.h index 70544e13f1d..a3964d5989d 100644 --- a/src/systemd/sd-dhcp-lease.h +++ b/src/systemd/sd-dhcp-lease.h @@ -39,6 +39,7 @@ typedef enum sd_dhcp_lease_info { SD_DHCP_LEASE_SIP_SERVERS, SD_DHCP_LEASE_POP3_SERVERS, SD_DHCP_LEASE_SMTP_SERVERS, + SD_DHCP_LEASE_LPR_SERVERS, _SD_DHCP_LEASE_INFO_MAX, } sd_dhcp_lease_info; @@ -57,6 +58,7 @@ int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_pop3_server(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_smtp_server(sd_dhcp_lease *lease, const struct in_addr **addr); +int sd_dhcp_lease_get_lpr_servers(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu); int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains); diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h index 4c7938ca70c..017d2d9cbb5 100644 --- a/src/systemd/sd-dhcp-server.h +++ b/src/systemd/sd-dhcp-server.h @@ -56,6 +56,7 @@ int sd_dhcp_server_set_servers( const struct in_addr addresses[], unsigned n_addresses); +int sd_dhcp_server_set_lpr(sd_dhcp_server *server, const struct in_addr lpr[], unsigned n); int sd_dhcp_server_set_dns(sd_dhcp_server *server, const struct in_addr dns[], unsigned n); int sd_dhcp_server_set_ntp(sd_dhcp_server *server, const struct in_addr ntp[], unsigned n); int sd_dhcp_server_set_sip(sd_dhcp_server *server, const struct in_addr sip[], unsigned n); diff --git a/src/systemd/sd-network.h b/src/systemd/sd-network.h index c185e2ce304..2637a0f8bb1 100644 --- a/src/systemd/sd-network.h +++ b/src/systemd/sd-network.h @@ -173,6 +173,9 @@ int sd_network_link_get_pop3_servers(int ifindex, char ***pop3); /* Get the SMTP servers for a given link. */ int sd_network_link_get_smtp_servers(int ifindex, char ***smtp); +/* Get the LPR servers for a given link. */ +int sd_network_link_get_lpr_servers(int ifindex, char ***lpr); + /* Get whether this link shall be used as 'default route' for DNS queries */ int sd_network_link_get_dns_default_route(int ifindex); diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index 147ea1b6394..1cd18202f40 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -278,6 +278,7 @@ EmitSIP= SIP= POP3Servers= SMTPServers= +LPRServers= EmitRouter= MaxLeaseTimeSec= DefaultLeaseTimeSec=