2017-11-18 17:09:20 +01:00
|
|
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
#include <netinet/ether.h>
|
|
|
|
#include <linux/if.h>
|
|
|
|
|
2015-10-27 03:01:06 +01:00
|
|
|
#include "alloc-util.h"
|
|
|
|
#include "dhcp-lease-internal.h"
|
2015-05-18 17:10:07 +02:00
|
|
|
#include "hostname-util.h"
|
2017-11-24 21:03:05 +01:00
|
|
|
#include "parse-util.h"
|
2017-09-07 11:08:39 +02:00
|
|
|
#include "netdev/vrf.h"
|
2014-08-08 12:12:17 +02:00
|
|
|
#include "network-internal.h"
|
2016-11-13 04:59:06 +01:00
|
|
|
#include "networkd-link.h"
|
|
|
|
#include "networkd-manager.h"
|
|
|
|
#include "networkd-network.h"
|
2017-11-24 21:03:05 +01:00
|
|
|
#include "string-util.h"
|
|
|
|
#include "sysctl-util.h"
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-06-12 16:31:33 +02:00
|
|
|
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
|
2014-08-08 12:12:17 +02:00
|
|
|
void *userdata) {
|
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
|
|
|
_cleanup_(link_unrefp) Link *link = userdata;
|
2014-08-08 12:12:17 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(link);
|
2015-11-03 13:01:43 +01:00
|
|
|
assert(link->dhcp4_messages > 0);
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2016-02-23 05:32:04 +01:00
|
|
|
link->dhcp4_messages--;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-06-12 16:31:33 +02:00
|
|
|
r = sd_netlink_message_get_errno(m);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r < 0 && r != -EEXIST) {
|
2015-08-27 13:04:33 +02:00
|
|
|
log_link_error_errno(link, r, "Could not set DHCPv4 route: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
link_enter_failed(link);
|
|
|
|
}
|
|
|
|
|
2015-11-03 13:01:43 +01:00
|
|
|
if (link->dhcp4_messages == 0) {
|
2014-08-08 12:12:17 +02:00
|
|
|
link->dhcp4_configured = true;
|
2015-09-28 13:38:43 +02:00
|
|
|
link_check_ready(link);
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-05-20 13:05:18 +02:00
|
|
|
static int route_scope_from_address(const Route *route, const struct in_addr *self_addr) {
|
|
|
|
assert(route);
|
|
|
|
assert(self_addr);
|
|
|
|
|
|
|
|
if (in_addr_is_localhost(AF_INET, &route->dst) ||
|
|
|
|
(self_addr->s_addr && route->dst.in.s_addr == self_addr->s_addr))
|
|
|
|
return RT_SCOPE_HOST;
|
|
|
|
else if (in4_addr_is_null(&route->gw.in))
|
|
|
|
return RT_SCOPE_LINK;
|
|
|
|
else
|
|
|
|
return RT_SCOPE_UNIVERSE;
|
|
|
|
}
|
|
|
|
|
2014-08-08 12:12:17 +02:00
|
|
|
static int link_set_dhcp_routes(Link *link) {
|
2016-01-20 14:44:14 +01:00
|
|
|
_cleanup_free_ sd_dhcp_route **static_routes = NULL;
|
2018-01-20 00:42:45 +01:00
|
|
|
bool classless_route = false, static_route = false;
|
|
|
|
struct in_addr gateway, address;
|
2014-08-08 12:12:17 +02:00
|
|
|
int r, n, i;
|
2017-09-07 11:08:39 +02:00
|
|
|
uint32_t table;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
assert(link);
|
2017-08-31 10:58:39 +02:00
|
|
|
|
|
|
|
if (!link->dhcp_lease) /* link went down while we configured the IP addresses? */
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!link->network) /* link went down while we configured the IP addresses? */
|
|
|
|
return 0;
|
2016-04-21 02:36:33 +02:00
|
|
|
|
|
|
|
if (!link->network->dhcp_use_routes)
|
|
|
|
return 0;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2017-09-07 11:08:39 +02:00
|
|
|
/* When the interface is part of an VRF use the VRFs routing table, unless
|
|
|
|
* there is a another table specified. */
|
|
|
|
table = link->network->dhcp_route_table;
|
|
|
|
if (!link->network->dhcp_route_table_set && link->network->vrf != NULL)
|
|
|
|
table = VRF(link->network->vrf)->table;
|
|
|
|
|
2017-05-24 14:05:49 +02:00
|
|
|
r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
|
|
|
|
|
2017-11-22 07:43:55 +01:00
|
|
|
n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
|
2018-06-25 14:04:22 +02:00
|
|
|
if (n == -ENODATA)
|
|
|
|
log_link_debug_errno(link, n, "DHCP: No routes received from DHCP server: %m");
|
|
|
|
else if (n < 0)
|
2017-11-23 17:38:08 +01:00
|
|
|
log_link_debug_errno(link, n, "DHCP error: could not get routes: %m");
|
2017-11-22 07:43:55 +01:00
|
|
|
|
2018-01-20 00:42:45 +01:00
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
if (static_routes[i]->option == SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE)
|
|
|
|
classless_route = true;
|
|
|
|
|
|
|
|
if (static_routes[i]->option == SD_DHCP_OPTION_STATIC_ROUTE)
|
|
|
|
static_route = true;
|
|
|
|
}
|
|
|
|
|
2017-11-22 07:43:55 +01:00
|
|
|
for (i = 0; i < n; i++) {
|
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
|
|
|
_cleanup_(route_freep) Route *route = NULL;
|
2017-11-22 07:43:55 +01:00
|
|
|
|
2018-01-20 00:42:45 +01:00
|
|
|
/* if the DHCP server returns both a Classless Static Routes option and a Static Routes option,
|
|
|
|
the DHCP client MUST ignore the Static Routes option. */
|
|
|
|
if (classless_route && static_routes[i]->option == SD_DHCP_OPTION_STATIC_ROUTE)
|
|
|
|
continue;
|
|
|
|
|
2017-11-22 07:43:55 +01:00
|
|
|
r = route_new(&route);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not allocate route: %m");
|
|
|
|
|
|
|
|
route->family = AF_INET;
|
|
|
|
route->protocol = RTPROT_DHCP;
|
|
|
|
assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0);
|
|
|
|
assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
|
|
|
|
assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
|
|
|
|
route->priority = link->network->dhcp_route_metric;
|
|
|
|
route->table = table;
|
|
|
|
route->scope = route_scope_from_address(route, &address);
|
|
|
|
|
|
|
|
r = route_configure(route, link, dhcp4_route_handler);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_warning_errno(link, r, "Could not set host route: %m");
|
|
|
|
|
|
|
|
link->dhcp4_messages++;
|
|
|
|
}
|
|
|
|
|
2014-08-08 12:12:17 +02:00
|
|
|
r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
|
2017-11-20 19:23:34 +01:00
|
|
|
if (r == -ENODATA)
|
2018-06-25 07:42:10 +02:00
|
|
|
log_link_info_errno(link, r, "DHCP: No gateway received from DHCP server: %m");
|
2017-11-20 19:23:34 +01:00
|
|
|
else if (r < 0)
|
|
|
|
log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m");
|
2015-08-27 13:04:33 +02:00
|
|
|
|
2017-11-22 07:43:55 +01:00
|
|
|
/* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
|
|
|
|
a Router option, the DHCP client MUST ignore the Router option. */
|
2018-01-20 00:42:45 +01:00
|
|
|
if (classless_route && static_route)
|
|
|
|
log_link_warning(link, "Classless static routes received from DHCP server: ignoring static-route option and router option");
|
|
|
|
|
|
|
|
if (r >= 0 && !classless_route) {
|
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
|
|
|
_cleanup_(route_freep) Route *route = NULL;
|
|
|
|
_cleanup_(route_freep) Route *route_gw = NULL;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-10-09 23:43:52 +02:00
|
|
|
r = route_new(&route);
|
2015-08-27 13:04:33 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not allocate route: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-10-09 23:43:52 +02:00
|
|
|
route->protocol = RTPROT_DHCP;
|
|
|
|
|
|
|
|
r = route_new(&route_gw);
|
2015-08-27 13:04:33 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "Could not allocate route: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
/* The dhcp netmask may mask out the gateway. Add an explicit
|
|
|
|
* route for the gw host so that we can route no matter the
|
|
|
|
* netmask or existing kernel route tables. */
|
|
|
|
route_gw->family = AF_INET;
|
2015-10-25 15:09:40 +01:00
|
|
|
route_gw->dst.in = gateway;
|
2014-08-08 12:12:17 +02:00
|
|
|
route_gw->dst_prefixlen = 32;
|
2015-10-25 15:09:40 +01:00
|
|
|
route_gw->prefsrc.in = address;
|
2014-08-08 12:12:17 +02:00
|
|
|
route_gw->scope = RT_SCOPE_LINK;
|
2015-10-09 23:43:52 +02:00
|
|
|
route_gw->protocol = RTPROT_DHCP;
|
2015-10-26 17:04:57 +01:00
|
|
|
route_gw->priority = link->network->dhcp_route_metric;
|
2017-09-07 11:08:39 +02:00
|
|
|
route_gw->table = table;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2016-05-15 16:22:40 +02:00
|
|
|
r = route_configure(route_gw, link, dhcp4_route_handler);
|
2015-08-27 13:04:33 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_link_warning_errno(link, r, "Could not set host route: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2016-02-23 05:32:04 +01:00
|
|
|
link->dhcp4_messages++;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
route->family = AF_INET;
|
2015-10-25 15:09:40 +01:00
|
|
|
route->gw.in = gateway;
|
|
|
|
route->prefsrc.in = address;
|
2015-10-26 17:04:57 +01:00
|
|
|
route->priority = link->network->dhcp_route_metric;
|
2017-09-07 11:08:39 +02:00
|
|
|
route->table = table;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2016-05-15 16:22:40 +02:00
|
|
|
r = route_configure(route, link, dhcp4_route_handler);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r < 0) {
|
2015-08-27 13:04:33 +02:00
|
|
|
log_link_warning_errno(link, r, "Could not set routes: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
link_enter_failed(link);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2016-02-23 05:32:04 +01:00
|
|
|
link->dhcp4_messages++;
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dhcp_lease_lost(Link *link) {
|
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
|
|
|
_cleanup_(address_freep) Address *address = NULL;
|
2014-08-08 12:12:17 +02:00
|
|
|
struct in_addr addr;
|
|
|
|
struct in_addr netmask;
|
|
|
|
struct in_addr gateway;
|
2014-09-17 19:00:55 +02:00
|
|
|
unsigned prefixlen = 0;
|
2014-08-08 12:12:17 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(link);
|
|
|
|
assert(link->dhcp_lease);
|
|
|
|
|
2014-11-27 20:20:23 +01:00
|
|
|
log_link_warning(link, "DHCP lease lost");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2016-01-25 21:47:02 +01:00
|
|
|
if (link->network->dhcp_use_routes) {
|
2016-01-20 14:44:14 +01:00
|
|
|
_cleanup_free_ sd_dhcp_route **routes = NULL;
|
2014-08-08 12:12:17 +02:00
|
|
|
int n, i;
|
|
|
|
|
|
|
|
n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes);
|
|
|
|
if (n >= 0) {
|
|
|
|
for (i = 0; i < n; i++) {
|
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
|
|
|
_cleanup_(route_freep) Route *route = NULL;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-10-09 23:43:52 +02:00
|
|
|
r = route_new(&route);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r >= 0) {
|
|
|
|
route->family = AF_INET;
|
2016-01-20 14:44:14 +01:00
|
|
|
assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0);
|
|
|
|
assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0);
|
|
|
|
assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0);
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-09-24 15:25:20 +02:00
|
|
|
route_remove(route, link,
|
2016-05-15 16:22:40 +02:00
|
|
|
link_route_remove_handler);
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-21 15:53:40 +02:00
|
|
|
r = address_new(&address);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r >= 0) {
|
|
|
|
r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
|
|
|
|
if (r >= 0) {
|
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
|
|
|
_cleanup_(route_freep) Route *route_gw = NULL;
|
|
|
|
_cleanup_(route_freep) Route *route = NULL;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-10-09 23:43:52 +02:00
|
|
|
r = route_new(&route_gw);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r >= 0) {
|
|
|
|
route_gw->family = AF_INET;
|
2015-10-25 15:09:40 +01:00
|
|
|
route_gw->dst.in = gateway;
|
2014-08-08 12:12:17 +02:00
|
|
|
route_gw->dst_prefixlen = 32;
|
|
|
|
route_gw->scope = RT_SCOPE_LINK;
|
|
|
|
|
2015-09-24 15:25:20 +02:00
|
|
|
route_remove(route_gw, link,
|
2016-05-15 16:22:40 +02:00
|
|
|
link_route_remove_handler);
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
|
2015-10-09 23:43:52 +02:00
|
|
|
r = route_new(&route);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r >= 0) {
|
|
|
|
route->family = AF_INET;
|
2015-10-25 15:09:40 +01:00
|
|
|
route->gw.in = gateway;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-09-24 15:25:20 +02:00
|
|
|
route_remove(route, link,
|
2016-05-15 16:22:40 +02:00
|
|
|
link_route_remove_handler);
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-17 19:00:55 +02:00
|
|
|
r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr);
|
|
|
|
if (r >= 0) {
|
|
|
|
r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
|
|
|
|
if (r >= 0)
|
2017-09-01 14:40:02 +02:00
|
|
|
prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2014-09-17 19:00:55 +02:00
|
|
|
address->family = AF_INET;
|
|
|
|
address->in_addr.in = addr;
|
|
|
|
address->prefixlen = prefixlen;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2016-05-15 16:22:40 +02:00
|
|
|
address_remove(address, link, link_address_remove_handler);
|
2014-09-17 19:00:55 +02:00
|
|
|
}
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
|
2016-01-25 21:47:02 +01:00
|
|
|
if (link->network->dhcp_use_mtu) {
|
2014-08-08 12:12:17 +02:00
|
|
|
uint16_t mtu;
|
|
|
|
|
|
|
|
r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
|
|
|
|
if (r >= 0 && link->original_mtu != mtu) {
|
|
|
|
r = link_set_mtu(link, link->original_mtu);
|
|
|
|
if (r < 0) {
|
2014-11-27 20:20:23 +01:00
|
|
|
log_link_warning(link,
|
2014-08-08 12:12:17 +02:00
|
|
|
"DHCP error: could not reset MTU");
|
|
|
|
link_enter_failed(link);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-25 21:47:02 +01:00
|
|
|
if (link->network->dhcp_use_hostname) {
|
2014-08-08 12:12:17 +02:00
|
|
|
const char *hostname = NULL;
|
|
|
|
|
2016-01-25 21:47:02 +01:00
|
|
|
if (link->network->dhcp_hostname)
|
|
|
|
hostname = link->network->dhcp_hostname;
|
2015-08-27 12:53:43 +02:00
|
|
|
else
|
|
|
|
(void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
|
2015-07-10 12:12:27 +02:00
|
|
|
|
2015-08-27 12:53:43 +02:00
|
|
|
if (hostname) {
|
|
|
|
/* If a hostname was set due to the lease, then unset it now. */
|
2016-11-21 23:15:41 +01:00
|
|
|
r = manager_set_hostname(link->manager, NULL);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r < 0)
|
2015-08-27 12:53:43 +02:00
|
|
|
log_link_warning_errno(link, r, "Failed to reset transient hostname: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
|
2015-11-18 14:21:06 +01:00
|
|
|
link_dirty(link);
|
2014-08-08 12:12:17 +02:00
|
|
|
link->dhcp4_configured = false;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-06-12 16:31:33 +02:00
|
|
|
static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
|
2014-08-08 12:12:17 +02:00
|
|
|
void *userdata) {
|
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
|
|
|
_cleanup_(link_unrefp) Link *link = userdata;
|
2014-08-08 12:12:17 +02:00
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(link);
|
|
|
|
|
2015-06-12 16:31:33 +02:00
|
|
|
r = sd_netlink_message_get_errno(m);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r < 0 && r != -EEXIST) {
|
2015-08-27 13:04:33 +02:00
|
|
|
log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
link_enter_failed(link);
|
2014-12-08 19:54:06 +01:00
|
|
|
} else if (r >= 0)
|
2015-09-22 17:18:20 +02:00
|
|
|
manager_rtnl_process_address(rtnl, m, link->manager);
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
link_set_dhcp_routes(link);
|
|
|
|
|
2018-04-17 17:12:00 +02:00
|
|
|
if (link->dhcp4_messages == 0) {
|
|
|
|
link->dhcp4_configured = true;
|
|
|
|
link_check_ready(link);
|
|
|
|
}
|
|
|
|
|
2014-08-08 12:12:17 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dhcp4_update_address(Link *link,
|
|
|
|
struct in_addr *address,
|
|
|
|
struct in_addr *netmask,
|
|
|
|
uint32_t lifetime) {
|
tree-wide: drop redundant _cleanup_ macros (#8810)
This drops a good number of type-specific _cleanup_ macros, and patches
all users to just use the generic ones.
In most recent code we abstained from defining type-specific macros, and
this basically removes all those added already, with the exception of
the really low-level ones.
Having explicit macros for this is not too useful, as the expression
without the extra macro is generally just 2ch wider. We should generally
emphesize generic code, unless there are really good reasons for
specific code, hence let's follow this in this case too.
Note that _cleanup_free_ and similar really low-level, libc'ish, Linux
API'ish macros continue to be defined, only the really high-level OO
ones are dropped. From now on this should really be the rule: for really
low-level stuff, such as memory allocation, fd handling and so one, go
ahead and define explicit per-type macros, but for high-level, specific
program code, just use the generic _cleanup_() macro directly, in order
to keep things simple and as readable as possible for the uninitiated.
Note that before this patch some of the APIs (notable libudev ones) were
already used with the high-level macros at some places and with the
generic _cleanup_ macro at others. With this patch we hence unify on the
latter.
2018-04-25 12:31:45 +02:00
|
|
|
_cleanup_(address_freep) Address *addr = NULL;
|
2014-08-08 12:12:17 +02:00
|
|
|
unsigned prefixlen;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(address);
|
|
|
|
assert(netmask);
|
|
|
|
assert(lifetime);
|
|
|
|
|
2017-09-01 14:40:02 +02:00
|
|
|
prefixlen = in4_addr_netmask_to_prefixlen(netmask);
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-09-21 15:53:40 +02:00
|
|
|
r = address_new(&addr);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
addr->family = AF_INET;
|
|
|
|
addr->in_addr.in.s_addr = address->s_addr;
|
|
|
|
addr->cinfo.ifa_prefered = lifetime;
|
|
|
|
addr->cinfo.ifa_valid = lifetime;
|
|
|
|
addr->prefixlen = prefixlen;
|
|
|
|
addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
|
|
|
|
|
2015-10-01 17:31:14 +02:00
|
|
|
/* allow reusing an existing address and simply update its lifetime
|
|
|
|
* in case it already exists */
|
2016-05-15 16:22:40 +02:00
|
|
|
r = address_configure(addr, link, dhcp4_address_handler, true);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
|
|
|
|
sd_dhcp_lease *lease;
|
|
|
|
struct in_addr address;
|
|
|
|
struct in_addr netmask;
|
|
|
|
uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(link);
|
|
|
|
assert(client);
|
|
|
|
assert(link->network);
|
|
|
|
|
|
|
|
r = sd_dhcp_client_get_lease(client, &lease);
|
2015-08-27 13:04:33 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
sd_dhcp_lease_unref(link->dhcp_lease);
|
|
|
|
link->dhcp4_configured = false;
|
2015-08-26 12:30:56 +02:00
|
|
|
link->dhcp_lease = sd_dhcp_lease_ref(lease);
|
2015-11-18 14:21:06 +01:00
|
|
|
link_dirty(link);
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
r = sd_dhcp_lease_get_address(lease, &address);
|
2015-08-27 13:04:33 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_link_warning_errno(link, r, "DHCP error: no address: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
r = sd_dhcp_lease_get_netmask(lease, &netmask);
|
2015-08-27 13:04:33 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
if (!link->network->dhcp_critical) {
|
2015-08-27 13:04:33 +02:00
|
|
|
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
r = dhcp4_update_address(link, &address, &netmask, lifetime);
|
|
|
|
if (r < 0) {
|
2015-08-27 13:04:33 +02:00
|
|
|
log_link_warning_errno(link, r, "Could not update IP address: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
link_enter_failed(link);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
|
|
|
|
sd_dhcp_lease *lease;
|
|
|
|
struct in_addr address;
|
|
|
|
struct in_addr netmask;
|
|
|
|
struct in_addr gateway;
|
|
|
|
unsigned prefixlen;
|
|
|
|
uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(client);
|
|
|
|
assert(link);
|
|
|
|
|
|
|
|
r = sd_dhcp_client_get_lease(client, &lease);
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
if (r < 0)
|
2015-08-27 13:04:33 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP error: No lease: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
r = sd_dhcp_lease_get_address(lease, &address);
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
if (r < 0)
|
2015-08-27 13:04:33 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP error: No address: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
r = sd_dhcp_lease_get_netmask(lease, &netmask);
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
if (r < 0)
|
2015-08-27 13:04:33 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2017-09-01 14:40:02 +02:00
|
|
|
prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
r = sd_dhcp_lease_get_router(lease, &gateway);
|
2015-09-04 21:16:35 +02:00
|
|
|
if (r < 0 && r != -ENODATA)
|
2015-08-27 13:04:33 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
if (r >= 0)
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_struct(LOG_INFO,
|
|
|
|
LOG_LINK_INTERFACE(link),
|
|
|
|
LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
|
|
|
|
ADDRESS_FMT_VAL(address),
|
|
|
|
prefixlen,
|
|
|
|
ADDRESS_FMT_VAL(gateway)),
|
|
|
|
"ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
|
|
|
|
"PREFIXLEN=%u", prefixlen,
|
2018-06-04 12:59:22 +02:00
|
|
|
"GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway));
|
2014-08-08 12:12:17 +02:00
|
|
|
else
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_struct(LOG_INFO,
|
|
|
|
LOG_LINK_INTERFACE(link),
|
|
|
|
LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
|
|
|
|
ADDRESS_FMT_VAL(address),
|
|
|
|
prefixlen),
|
|
|
|
"ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
|
2018-06-04 12:59:22 +02:00
|
|
|
"PREFIXLEN=%u", prefixlen);
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-08-26 12:30:56 +02:00
|
|
|
link->dhcp_lease = sd_dhcp_lease_ref(lease);
|
2015-11-18 14:21:06 +01:00
|
|
|
link_dirty(link);
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2016-01-25 21:47:02 +01:00
|
|
|
if (link->network->dhcp_use_mtu) {
|
2014-08-08 12:12:17 +02:00
|
|
|
uint16_t mtu;
|
|
|
|
|
|
|
|
r = sd_dhcp_lease_get_mtu(lease, &mtu);
|
|
|
|
if (r >= 0) {
|
|
|
|
r = link_set_mtu(link, mtu);
|
|
|
|
if (r < 0)
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-25 21:47:02 +01:00
|
|
|
if (link->network->dhcp_use_hostname) {
|
2017-12-13 18:00:46 +01:00
|
|
|
const char *dhcpname = NULL;
|
|
|
|
_cleanup_free_ char *hostname = NULL;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2016-01-25 21:47:02 +01:00
|
|
|
if (link->network->dhcp_hostname)
|
2017-12-13 18:00:46 +01:00
|
|
|
dhcpname = link->network->dhcp_hostname;
|
2015-08-27 12:53:43 +02:00
|
|
|
else
|
2017-12-13 18:00:46 +01:00
|
|
|
(void) sd_dhcp_lease_get_hostname(lease, &dhcpname);
|
|
|
|
|
|
|
|
if (dhcpname) {
|
|
|
|
r = shorten_overlong(dhcpname, &hostname);
|
|
|
|
if (r < 0)
|
|
|
|
log_link_warning_errno(link, r, "Unable to shorten overlong DHCP hostname '%s', ignoring: %m", dhcpname);
|
|
|
|
if (r == 1)
|
|
|
|
log_link_notice(link, "Overlong DCHP hostname received, shortened from '%s' to '%s'", dhcpname, hostname);
|
|
|
|
}
|
2015-07-10 12:12:27 +02:00
|
|
|
|
2015-08-27 12:53:43 +02:00
|
|
|
if (hostname) {
|
2016-11-21 23:15:41 +01:00
|
|
|
r = manager_set_hostname(link->manager, hostname);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r < 0)
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-25 21:47:02 +01:00
|
|
|
if (link->network->dhcp_use_timezone) {
|
2015-08-27 02:12:27 +02:00
|
|
|
const char *tz = NULL;
|
|
|
|
|
|
|
|
(void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
|
|
|
|
|
|
|
|
if (tz) {
|
2016-11-21 23:15:41 +01:00
|
|
|
r = manager_set_timezone(link->manager, tz);
|
2015-08-27 02:12:27 +02:00
|
|
|
if (r < 0)
|
|
|
|
log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-08 12:12:17 +02:00
|
|
|
if (!link->network->dhcp_critical) {
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
|
2018-08-07 08:48:37 +02:00
|
|
|
if (r < 0)
|
|
|
|
return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
r = dhcp4_update_address(link, &address, &netmask, lifetime);
|
|
|
|
if (r < 0) {
|
core,network: major per-object logging rework
This changes log_unit_info() (and friends) to take a real Unit* object
insted of just a unit name as parameter. The call will now prefix all
logged messages with the unit name, thus allowing the unit name to be
dropped from the various passed romat strings, simplifying invocations
drastically, and unifying log output across messages. Also, UNIT= vs.
USER_UNIT= is now derived from the Manager object attached to the Unit
object, instead of getpid(). This has the benefit of correcting the
field for --test runs.
Also contains a couple of other logging improvements:
- Drops a couple of strerror() invocations in favour of using %m.
- Not only .mount units now warn if a symlinks exist for the mount
point already, .automount units do that too, now.
- A few invocations of log_struct() that didn't actually pass any
additional structured data have been replaced by simpler invocations
of log_unit_info() and friends.
- For structured data a new LOG_UNIT_MESSAGE() macro has been added,
that works like LOG_MESSAGE() but prefixes the message with the unit
name. Similar, there's now LOG_LINK_MESSAGE() and
LOG_NETDEV_MESSAGE().
- For structured data new LOG_UNIT_ID(), LOG_LINK_INTERFACE(),
LOG_NETDEV_INTERFACE() macros have been added that generate the
necessary per object fields. The old log_unit_struct() call has been
removed in favour of these new macros used in raw log_struct()
invocations. In addition to removing one more function call this
allows generated structured log messages that contain two object
fields, as necessary for example for network interfaces that are
joined into another network interface, and whose messages shall be
indexed by both.
- The LOG_ERRNO() macro has been removed, in favour of
log_struct_errno(). The latter has the benefit of ensuring that %m in
format strings is properly resolved to the specified error number.
- A number of logging messages have been converted to use
log_unit_info() instead of log_info()
- The client code in sysv-generator no longer #includes core code from
src/core/.
- log_unit_full_errno() has been removed, log_unit_full() instead takes
an errno now, too.
- log_unit_info(), log_link_info(), log_netdev_info() and friends, now
avoid double evaluation of their parameters
2015-05-11 20:38:21 +02:00
|
|
|
log_link_warning_errno(link, r, "Could not update IP address: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
link_enter_failed(link);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
|
|
|
|
Link *link = userdata;
|
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
assert(link);
|
|
|
|
assert(link->network);
|
|
|
|
assert(link->manager);
|
|
|
|
|
|
|
|
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (event) {
|
2015-09-22 14:46:21 +02:00
|
|
|
case SD_DHCP_CLIENT_EVENT_EXPIRED:
|
|
|
|
case SD_DHCP_CLIENT_EVENT_STOP:
|
|
|
|
case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
|
2014-08-08 12:12:17 +02:00
|
|
|
if (link->network->dhcp_critical) {
|
2015-08-27 13:04:33 +02:00
|
|
|
log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
|
2014-08-08 12:12:17 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (link->dhcp_lease) {
|
|
|
|
r = dhcp_lease_lost(link);
|
|
|
|
if (r < 0) {
|
|
|
|
link_enter_failed(link);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-22 14:46:21 +02:00
|
|
|
if (event == SD_DHCP_CLIENT_EVENT_IP_CHANGE) {
|
2014-08-08 12:12:17 +02:00
|
|
|
r = dhcp_lease_acquired(client, link);
|
|
|
|
if (r < 0) {
|
|
|
|
link_enter_failed(link);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2015-09-22 14:46:21 +02:00
|
|
|
case SD_DHCP_CLIENT_EVENT_RENEW:
|
2014-08-08 12:12:17 +02:00
|
|
|
r = dhcp_lease_renew(client, link);
|
|
|
|
if (r < 0) {
|
|
|
|
link_enter_failed(link);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2015-09-22 14:46:21 +02:00
|
|
|
case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
|
2014-08-08 12:12:17 +02:00
|
|
|
r = dhcp_lease_acquired(client, link);
|
|
|
|
if (r < 0) {
|
|
|
|
link_enter_failed(link);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (event < 0)
|
2015-08-27 13:04:33 +02:00
|
|
|
log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
else
|
2015-08-27 13:04:33 +02:00
|
|
|
log_link_warning(link, "DHCP unknown event: %i", event);
|
2014-08-08 12:12:17 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-18 13:02:57 +01:00
|
|
|
static int dhcp4_set_hostname(Link *link) {
|
|
|
|
_cleanup_free_ char *hostname = NULL;
|
|
|
|
const char *hn;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(link);
|
|
|
|
|
|
|
|
if (!link->network->dhcp_send_hostname)
|
|
|
|
hn = NULL;
|
|
|
|
else if (link->network->dhcp_hostname)
|
|
|
|
hn = link->network->dhcp_hostname;
|
|
|
|
else {
|
|
|
|
r = gethostname_strict(&hostname);
|
|
|
|
if (r < 0 && r != -ENXIO) /* ENXIO: no hostname set or hostname is "localhost" */
|
|
|
|
return r;
|
|
|
|
|
|
|
|
hn = hostname;
|
|
|
|
}
|
|
|
|
|
2018-08-02 09:31:10 +02:00
|
|
|
r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
|
|
|
|
if (r == -EINVAL && hostname)
|
|
|
|
/* Ignore error when the machine's hostname is not suitable to send in DHCP packet. */
|
|
|
|
log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set hostname from kernel hostname, ignoring: %m");
|
|
|
|
else if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set hostname: %m");
|
|
|
|
|
|
|
|
return 0;
|
2016-11-18 13:02:57 +01:00
|
|
|
}
|
|
|
|
|
2017-11-24 21:03:05 +01:00
|
|
|
static bool promote_secondaries_enabled(const char *ifname) {
|
2017-12-05 15:51:23 +01:00
|
|
|
_cleanup_free_ char *promote_secondaries_sysctl = NULL;
|
|
|
|
char *promote_secondaries_path;
|
2017-11-24 21:03:05 +01:00
|
|
|
int r;
|
|
|
|
|
|
|
|
promote_secondaries_path = strjoina("net/ipv4/conf/", ifname, "/promote_secondaries");
|
|
|
|
r = sysctl_read(promote_secondaries_path, &promote_secondaries_sysctl);
|
|
|
|
if (r < 0) {
|
|
|
|
log_debug_errno(r, "Cannot read sysctl %s", promote_secondaries_path);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
truncate_nl(promote_secondaries_sysctl);
|
|
|
|
r = parse_boolean(promote_secondaries_sysctl);
|
|
|
|
if (r < 0)
|
|
|
|
log_warning_errno(r, "Cannot parse sysctl %s with content %s as boolean", promote_secondaries_path, promote_secondaries_sysctl);
|
|
|
|
return r > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* dhcp4_set_promote_secondaries will ensure this interface has
|
|
|
|
* the "promote_secondaries" option in the kernel set. If this sysctl
|
|
|
|
* is not set DHCP will work only as long as the IP address does not
|
|
|
|
* changes between leases. The kernel will remove all secondary IP
|
|
|
|
* addresses of an interface otherwise. The way systemd-network works
|
|
|
|
* is that the new IP of a lease is added as a secondary IP and when
|
|
|
|
* the primary one expires it relies on the kernel to promote the
|
|
|
|
* secondary IP. See also https://github.com/systemd/systemd/issues/7163
|
|
|
|
*/
|
|
|
|
int dhcp4_set_promote_secondaries(Link *link) {
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(link);
|
|
|
|
assert(link->network);
|
|
|
|
assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
|
|
|
|
|
|
|
|
/* check if the kernel has promote_secondaries enabled for our
|
|
|
|
* interface. If it is not globally enabled or enabled for the
|
|
|
|
* specific interface we must either enable it.
|
|
|
|
*/
|
2017-12-05 15:49:00 +01:00
|
|
|
if (!(promote_secondaries_enabled("all") || promote_secondaries_enabled(link->ifname))) {
|
2017-11-24 21:03:05 +01:00
|
|
|
char *promote_secondaries_path = NULL;
|
|
|
|
|
|
|
|
log_link_debug(link, "promote_secondaries is unset, setting it");
|
|
|
|
promote_secondaries_path = strjoina("net/ipv4/conf/", link->ifname, "/promote_secondaries");
|
|
|
|
r = sysctl_write(promote_secondaries_path, "1");
|
|
|
|
if (r < 0)
|
|
|
|
log_link_warning_errno(link, r, "cannot set sysctl %s to 1", promote_secondaries_path);
|
|
|
|
return r > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-06 10:33:12 +02:00
|
|
|
int dhcp4_set_client_identifier(Link *link) {
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(link);
|
|
|
|
assert(link->network);
|
|
|
|
assert(link->dhcp_client);
|
|
|
|
|
|
|
|
switch (link->network->dhcp_client_identifier) {
|
|
|
|
case DHCP_CLIENT_ID_DUID: {
|
|
|
|
/* If configured, apply user specified DUID and/or IAID */
|
|
|
|
const DUID *duid = link_get_duid(link);
|
|
|
|
|
|
|
|
r = sd_dhcp_client_set_iaid_duid(link->dhcp_client,
|
|
|
|
link->network->iaid,
|
|
|
|
duid->type,
|
|
|
|
duid->raw_data_len > 0 ? duid->raw_data : NULL,
|
|
|
|
duid->raw_data_len);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DHCP_CLIENT_ID_DUID_ONLY: {
|
|
|
|
/* If configured, apply user specified DUID */
|
|
|
|
const DUID *duid = link_get_duid(link);
|
|
|
|
|
|
|
|
r = sd_dhcp_client_set_duid(link->dhcp_client,
|
|
|
|
duid->type,
|
|
|
|
duid->raw_data_len > 0 ? duid->raw_data : NULL,
|
|
|
|
duid->raw_data_len);
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case DHCP_CLIENT_ID_MAC:
|
|
|
|
r = sd_dhcp_client_set_client_id(link->dhcp_client,
|
|
|
|
ARPHRD_ETHER,
|
|
|
|
(const uint8_t *) &link->mac,
|
|
|
|
sizeof(link->mac));
|
|
|
|
if (r < 0)
|
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set client ID: %m");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert_not_reached("Unknown client identifier type.");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-08-08 12:12:17 +02:00
|
|
|
int dhcp4_configure(Link *link) {
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(link);
|
|
|
|
assert(link->network);
|
2015-06-09 01:05:34 +02:00
|
|
|
assert(link->network->dhcp & ADDRESS_FAMILY_IPV4);
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2015-10-01 22:29:50 +02:00
|
|
|
if (!link->dhcp_client) {
|
2017-08-03 03:32:46 +02:00
|
|
|
r = sd_dhcp_client_new(&link->dhcp_client, link->network->dhcp_anonymize);
|
2018-08-01 03:35:17 +02:00
|
|
|
if (r == -ENOMEM)
|
|
|
|
return log_oom();
|
2015-10-01 22:29:50 +02:00
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to create DHCP4 client: %m");
|
2015-10-01 22:29:50 +02:00
|
|
|
}
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0);
|
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to attach event: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2014-10-08 21:15:45 +02:00
|
|
|
r = sd_dhcp_client_set_mac(link->dhcp_client,
|
|
|
|
(const uint8_t *) &link->mac,
|
|
|
|
sizeof (link->mac), ARPHRD_ETHER);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set MAC address: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
2016-05-23 16:13:18 +02:00
|
|
|
r = sd_dhcp_client_set_ifindex(link->dhcp_client, link->ifindex);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set ifindex: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link);
|
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set callback: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
r = sd_dhcp_client_set_request_broadcast(link->dhcp_client,
|
|
|
|
link->network->dhcp_broadcast);
|
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for broadcast: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
if (link->mtu) {
|
|
|
|
r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu);
|
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set MTU: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
|
2016-01-25 21:47:02 +01:00
|
|
|
if (link->network->dhcp_use_mtu) {
|
2015-08-27 01:18:10 +02:00
|
|
|
r = sd_dhcp_client_set_request_option(link->dhcp_client,
|
2016-01-20 14:44:24 +01:00
|
|
|
SD_DHCP_OPTION_INTERFACE_MTU);
|
2015-08-27 01:18:10 +02:00
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for MTU: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
|
2017-08-03 19:19:51 +02:00
|
|
|
/* NOTE: even if this variable is called "use", it also "sends" PRL
|
|
|
|
* options, maybe there should be a different configuration variable
|
|
|
|
* to send or not route options?. */
|
2017-11-10 16:03:43 +01:00
|
|
|
/* NOTE: when using Anonymize=yes, routes PRL options are sent
|
|
|
|
* by default, so they don't need to be added here. */
|
2017-08-03 19:19:51 +02:00
|
|
|
if (link->network->dhcp_use_routes && !link->network->dhcp_anonymize) {
|
2014-08-08 12:12:17 +02:00
|
|
|
r = sd_dhcp_client_set_request_option(link->dhcp_client,
|
2016-01-20 14:44:24 +01:00
|
|
|
SD_DHCP_OPTION_STATIC_ROUTE);
|
2014-08-08 12:12:17 +02:00
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for static route: %m");
|
|
|
|
|
2014-08-08 12:12:17 +02:00
|
|
|
r = sd_dhcp_client_set_request_option(link->dhcp_client,
|
2016-01-20 14:44:24 +01:00
|
|
|
SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
|
2015-08-06 00:31:09 +02:00
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for classless static route: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
|
2017-09-05 12:26:32 +02:00
|
|
|
if (link->network->dhcp_use_ntp) {
|
|
|
|
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
|
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for NTP server: %m");
|
2017-09-05 12:26:32 +02:00
|
|
|
}
|
2015-08-27 01:14:20 +02:00
|
|
|
|
2017-09-06 10:10:50 +02:00
|
|
|
if (link->network->dhcp_use_timezone) {
|
|
|
|
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE);
|
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set request flag for timezone: %m");
|
2017-09-06 10:10:50 +02:00
|
|
|
}
|
2015-08-26 19:19:32 +02:00
|
|
|
|
2016-11-18 13:02:57 +01:00
|
|
|
r = dhcp4_set_hostname(link);
|
|
|
|
if (r < 0)
|
2018-08-02 09:31:10 +02:00
|
|
|
return r;
|
2014-08-08 12:12:17 +02:00
|
|
|
|
|
|
|
if (link->network->dhcp_vendor_class_identifier) {
|
|
|
|
r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client,
|
|
|
|
link->network->dhcp_vendor_class_identifier);
|
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set vendor class identifier: %m");
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|
|
|
|
|
2018-05-07 14:21:02 +02:00
|
|
|
if (link->network->dhcp_user_class) {
|
|
|
|
r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class);
|
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set user class: %m");
|
2018-05-07 14:21:02 +02:00
|
|
|
}
|
|
|
|
|
2016-11-11 00:34:19 +01:00
|
|
|
if (link->network->dhcp_client_port) {
|
|
|
|
r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port);
|
|
|
|
if (r < 0)
|
2018-08-01 03:35:17 +02:00
|
|
|
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set listen port: %m");
|
2016-11-11 00:34:19 +01:00
|
|
|
}
|
|
|
|
|
2018-08-06 10:33:12 +02:00
|
|
|
return dhcp4_set_client_identifier(link);
|
2014-08-08 12:12:17 +02:00
|
|
|
}
|