diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/calendarspec.c | 98 | ||||
-rw-r--r-- | src/basic/calendarspec.h | 1 | ||||
-rw-r--r-- | src/core/macros.systemd.in | 2 | ||||
-rw-r--r-- | src/core/service.c | 31 | ||||
-rw-r--r-- | src/core/service.h | 1 | ||||
-rw-r--r-- | src/libsystemd/sd-hwdb/sd-hwdb.c | 2 | ||||
-rw-r--r-- | src/libsystemd/sd-netlink/netlink-types.c | 27 | ||||
-rw-r--r-- | src/network/networkd-ndisc.c | 8 | ||||
-rw-r--r-- | src/network/networkd-network.h | 2 | ||||
-rw-r--r-- | src/network/networkd-route.c | 14 | ||||
-rw-r--r-- | src/network/networkd-route.h | 1 | ||||
-rw-r--r-- | src/test/test-calendarspec.c | 9 |
12 files changed, 154 insertions, 42 deletions
diff --git a/src/basic/calendarspec.c b/src/basic/calendarspec.c index fda293fcb9..359bb16cae 100644 --- a/src/basic/calendarspec.c +++ b/src/basic/calendarspec.c @@ -34,6 +34,8 @@ /* Longest valid date/time range is 1970..2199 */ #define MAX_RANGE_LEN 230 +#define MIN_YEAR 1970 +#define MAX_YEAR 2199 #define BITS_WEEKDAYS 127 static void free_chain(CalendarComponent *c) { @@ -135,6 +137,9 @@ int calendar_spec_normalize(CalendarSpec *c) { if (c->weekdays_bits <= 0 || c->weekdays_bits >= BITS_WEEKDAYS) c->weekdays_bits = -1; + if (c->end_of_month && !c->day) + c->end_of_month = false; + fix_year(c->year); sort_chain(&c->year); @@ -147,18 +152,27 @@ int calendar_spec_normalize(CalendarSpec *c) { return 0; } -_pure_ static bool chain_valid(CalendarComponent *c, int from, int to) { +_pure_ static bool chain_valid(CalendarComponent *c, int from, int to, bool eom) { if (!c) return true; if (c->value < from || c->value > to) return false; - if (c->value + c->repeat > to) + /* + * c->repeat must be short enough so at least one repetition may + * occur before the end of the interval. For dates scheduled + * relative to the end of the month (eom), c->value corresponds + * to the Nth last day of the month. + */ + if (eom && c->value - c->repeat < from) + return false; + + if (!eom && c->value + c->repeat > to) return false; if (c->next) - return chain_valid(c->next, from, to); + return chain_valid(c->next, from, to, eom); return true; } @@ -169,22 +183,22 @@ _pure_ bool calendar_spec_valid(CalendarSpec *c) { if (c->weekdays_bits > BITS_WEEKDAYS) return false; - if (!chain_valid(c->year, 1970, 2199)) + if (!chain_valid(c->year, MIN_YEAR, MAX_YEAR, false)) return false; - if (!chain_valid(c->month, 1, 12)) + if (!chain_valid(c->month, 1, 12, false)) return false; - if (!chain_valid(c->day, 1, 31)) + if (!chain_valid(c->day, 1, 31, c->end_of_month)) return false; - if (!chain_valid(c->hour, 0, 23)) + if (!chain_valid(c->hour, 0, 23, false)) return false; - if (!chain_valid(c->minute, 0, 59)) + if (!chain_valid(c->minute, 0, 59, false)) return false; - if (!chain_valid(c->microsecond, 0, 60*USEC_PER_SEC-1)) + if (!chain_valid(c->microsecond, 0, 60*USEC_PER_SEC-1, false)) return false; return true; @@ -291,7 +305,7 @@ int calendar_spec_to_string(const CalendarSpec *c, char **p) { format_chain(f, 4, c->year, false); fputc('-', f); format_chain(f, 2, c->month, false); - fputc('-', f); + fputc(c->end_of_month ? '~' : '-', f); format_chain(f, 2, c->day, false); fputc(' ', f); format_chain(f, 2, c->hour, false); @@ -540,7 +554,7 @@ static int prepend_component(const char **p, bool usec, CalendarComponent **c) { } } - if (*e != 0 && *e != ' ' && *e != ',' && *e != '-' && *e != ':') + if (*e != 0 && *e != ' ' && *e != ',' && *e != '-' && *e != '~' && *e != ':') return -EINVAL; cc = new0(CalendarComponent, 1); @@ -620,7 +634,9 @@ static int parse_date(const char **p, CalendarSpec *c) { return 0; } - if (*t != '-') { + if (*t == '~') + c->end_of_month = true; + else if (*t != '-') { free_chain(first); return -EINVAL; } @@ -638,9 +654,12 @@ static int parse_date(const char **p, CalendarSpec *c) { c->month = first; c->day = second; return 0; - } + } else if (c->end_of_month) + return -EINVAL; - if (*t != '-') { + if (*t == '~') + c->end_of_month = true; + else if (*t != '-') { free_chain(first); free_chain(second); return -EINVAL; @@ -654,7 +673,7 @@ static int parse_date(const char **p, CalendarSpec *c) { return r; } - /* Got tree parts, hence it is year, month and day */ + /* Got three parts, hence it is year, month and day */ if (*t == ' ' || *t == 0) { *p = t + strspn(t, " "); c->year = first; @@ -965,9 +984,11 @@ fail: return r; } -static int find_matching_component(const CalendarComponent *c, int *val) { - const CalendarComponent *n; - int d = -1; +static int find_matching_component(const CalendarSpec *spec, const CalendarComponent *c, + struct tm *tm, int *val) { + const CalendarComponent *n, *p = c; + struct tm t; + int v, d = -1; bool d_set = false; int r; @@ -979,17 +1000,30 @@ static int find_matching_component(const CalendarComponent *c, int *val) { while (c) { n = c->next; - if (c->value >= *val) { + if (spec->end_of_month && p == spec->day) { + t = *tm; + t.tm_mon++; + t.tm_mday = 1 - c->value; + + if (mktime_or_timegm(&t, spec->utc) == (time_t) -1 || + t.tm_mon != tm->tm_mon) + v = -1; + else + v = t.tm_mday; + } else + v = c->value; + + if (v >= *val) { - if (!d_set || c->value < d) { - d = c->value; + if (!d_set || v < d) { + d = v; d_set = true; } } else if (c->repeat > 0) { int k; - k = c->value + c->repeat * ((*val - c->value + c->repeat -1) / c->repeat); + k = v + c->repeat * ((*val - v + c->repeat -1) / c->repeat); if (!d_set || k < d) { d = k; @@ -1017,6 +1051,14 @@ static bool tm_out_of_bounds(const struct tm *tm, bool utc) { if (mktime_or_timegm(&t, utc) == (time_t) -1) return true; + /* + * Set an upper bound on the year so impossible dates like "*-02-31" + * don't cause find_next() to loop forever. tm_year contains years + * since 1900, so adjust it accordingly. + */ + if (tm->tm_year + 1900 > MAX_YEAR) + return true; + /* Did any normalization take place? If so, it was out of bounds before */ return t.tm_year != tm->tm_year || @@ -1059,7 +1101,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { c.tm_isdst = spec->dst; c.tm_year += 1900; - r = find_matching_component(spec->year, &c.tm_year); + r = find_matching_component(spec, spec->year, &c, &c.tm_year); c.tm_year -= 1900; if (r > 0) { @@ -1073,7 +1115,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { return -ENOENT; c.tm_mon += 1; - r = find_matching_component(spec->month, &c.tm_mon); + r = find_matching_component(spec, spec->month, &c, &c.tm_mon); c.tm_mon -= 1; if (r > 0) { @@ -1088,7 +1130,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { continue; } - r = find_matching_component(spec->day, &c.tm_mday); + r = find_matching_component(spec, spec->day, &c, &c.tm_mday); if (r > 0) c.tm_hour = c.tm_min = c.tm_sec = tm_usec = 0; if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { @@ -1104,7 +1146,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { continue; } - r = find_matching_component(spec->hour, &c.tm_hour); + r = find_matching_component(spec, spec->hour, &c, &c.tm_hour); if (r > 0) c.tm_min = c.tm_sec = tm_usec = 0; if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { @@ -1113,7 +1155,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { continue; } - r = find_matching_component(spec->minute, &c.tm_min); + r = find_matching_component(spec, spec->minute, &c, &c.tm_min); if (r > 0) c.tm_sec = tm_usec = 0; if (r < 0 || tm_out_of_bounds(&c, spec->utc)) { @@ -1123,7 +1165,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { } c.tm_sec = c.tm_sec * USEC_PER_SEC + tm_usec; - r = find_matching_component(spec->microsecond, &c.tm_sec); + r = find_matching_component(spec, spec->microsecond, &c, &c.tm_sec); tm_usec = c.tm_sec % USEC_PER_SEC; c.tm_sec /= USEC_PER_SEC; diff --git a/src/basic/calendarspec.h b/src/basic/calendarspec.h index c6087228fd..78af27403c 100644 --- a/src/basic/calendarspec.h +++ b/src/basic/calendarspec.h @@ -36,6 +36,7 @@ typedef struct CalendarComponent { typedef struct CalendarSpec { int weekdays_bits; + bool end_of_month; bool utc; int dst; diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in index 6e8a3b3e3d..8d7ce1c238 100644 --- a/src/core/macros.systemd.in +++ b/src/core/macros.systemd.in @@ -81,7 +81,7 @@ fi \ %systemd_user_postun_with_restart() %{nil} %udev_hwdb_update() \ -udevadm hwdb --update >/dev/null 2>&1 || : \ +systemd-hwdb update >/dev/null 2>&1 || : \ %{nil} %udev_rules_update() \ diff --git a/src/core/service.c b/src/core/service.c index 9ad4cf5070..180854b57c 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1694,7 +1694,9 @@ static void service_enter_running(Service *s, ServiceResult f) { service_arm_timer(s, usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec)); } - } else if (s->remain_after_exit) + } else if (f != SERVICE_SUCCESS) + service_enter_signal(s, SERVICE_FINAL_SIGTERM, f); + else if (s->remain_after_exit) service_set_state(s, SERVICE_EXITED); else service_enter_stop(s, SERVICE_SUCCESS); @@ -2578,16 +2580,18 @@ static void service_notify_cgroup_empty_event(Unit *u) { case SERVICE_START: case SERVICE_START_POST: - /* If we were hoping for the daemon to write its PID file, - * we can give up now. */ - if (s->pid_file_pathspec) { + if (s->type == SERVICE_NOTIFY) + /* No chance of getting a ready notification anymore */ + service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL); + else if (s->pid_file_pathspec) { + /* Give up hoping for the daemon to write its PID file */ log_unit_warning(u, "Daemon never wrote its PID file. Failing."); service_unwatch_pid_file(s); if (s->state == SERVICE_START) - service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES); + service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL); else - service_enter_stop(s, SERVICE_FAILURE_RESOURCES); + service_enter_stop(s, SERVICE_FAILURE_PROTOCOL); } break; @@ -2721,6 +2725,16 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { else service_enter_signal(s, SERVICE_FINAL_SIGTERM, f); break; + } else if (s->type == SERVICE_NOTIFY) { + /* Only enter running through a notification, so that the + * SERVICE_START state signifies that no ready notification + * has been received */ + if (f != SERVICE_SUCCESS) + service_enter_signal(s, SERVICE_FINAL_SIGTERM, f); + else if (!s->remain_after_exit) + /* The service has never been active */ + service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL); + break; } /* Fall through */ @@ -2825,7 +2839,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { if (!has_start_post && r < 0) { r = service_demand_pid_file(s); if (r < 0 || !cgroup_good(s)) - service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES); + service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_PROTOCOL); break; } } else @@ -2847,7 +2861,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { if (r < 0) { r = service_demand_pid_file(s); if (r < 0 || !cgroup_good(s)) - service_enter_stop(s, SERVICE_FAILURE_RESOURCES); + service_enter_stop(s, SERVICE_FAILURE_PROTOCOL); break; } } else @@ -3384,6 +3398,7 @@ DEFINE_STRING_TABLE_LOOKUP(notify_state, NotifyState); static const char* const service_result_table[_SERVICE_RESULT_MAX] = { [SERVICE_SUCCESS] = "success", [SERVICE_FAILURE_RESOURCES] = "resources", + [SERVICE_FAILURE_PROTOCOL] = "protocol", [SERVICE_FAILURE_TIMEOUT] = "timeout", [SERVICE_FAILURE_EXIT_CODE] = "exit-code", [SERVICE_FAILURE_SIGNAL] = "signal", diff --git a/src/core/service.h b/src/core/service.h index 2869144fcb..278cc1ceb8 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -81,6 +81,7 @@ typedef enum NotifyState { typedef enum ServiceResult { SERVICE_SUCCESS, SERVICE_FAILURE_RESOURCES, /* a bit of a misnomer, just our catch-all error for errnos we didn't expect */ + SERVICE_FAILURE_PROTOCOL, SERVICE_FAILURE_TIMEOUT, SERVICE_FAILURE_EXIT_CODE, SERVICE_FAILURE_SIGNAL, diff --git a/src/libsystemd/sd-hwdb/sd-hwdb.c b/src/libsystemd/sd-hwdb/sd-hwdb.c index 488e101ea8..719e3505c1 100644 --- a/src/libsystemd/sd-hwdb/sd-hwdb.c +++ b/src/libsystemd/sd-hwdb/sd-hwdb.c @@ -321,7 +321,7 @@ _public_ int sd_hwdb_new(sd_hwdb **ret) { } if (!hwdb->f) { - log_debug("hwdb.bin does not exist, please run udevadm hwdb --update"); + log_debug("hwdb.bin does not exist, please run systemd-hwdb update"); return -ENOENT; } diff --git a/src/libsystemd/sd-netlink/netlink-types.c b/src/libsystemd/sd-netlink/netlink-types.c index 1c10dd55a7..0f8b0cc70b 100644 --- a/src/libsystemd/sd-netlink/netlink-types.c +++ b/src/libsystemd/sd-netlink/netlink-types.c @@ -500,6 +500,28 @@ static const NLTypeSystem rtnl_address_type_system = { .types = rtnl_address_types, }; +/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */ + +static const NLType rtnl_route_metrics_types[] = { + [RTAX_MTU] = { .type = NETLINK_TYPE_U32 }, + [RTAX_WINDOW] = { .type = NETLINK_TYPE_U32 }, + [RTAX_RTT] = { .type = NETLINK_TYPE_U32 }, + [RTAX_RTTVAR] = { .type = NETLINK_TYPE_U32 }, + [RTAX_SSTHRESH] = { .type = NETLINK_TYPE_U32 }, + [RTAX_CWND] = { .type = NETLINK_TYPE_U32 }, + [RTAX_ADVMSS] = { .type = NETLINK_TYPE_U32 }, + [RTAX_REORDERING] = { .type = NETLINK_TYPE_U32 }, + [RTAX_HOPLIMIT] = { .type = NETLINK_TYPE_U32 }, + [RTAX_INITCWND] = { .type = NETLINK_TYPE_U32 }, + [RTAX_FEATURES] = { .type = NETLINK_TYPE_U32 }, + [RTAX_RTO_MIN] = { .type = NETLINK_TYPE_U32 }, +}; + +static const NLTypeSystem rtnl_route_metrics_type_system = { + .count = ELEMENTSOF(rtnl_route_metrics_types), + .types = rtnl_route_metrics_types, +}; + static const NLType rtnl_route_types[] = { [RTA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ [RTA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ @@ -508,9 +530,8 @@ static const NLType rtnl_route_types[] = { [RTA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR }, [RTA_PRIORITY] = { .type = NETLINK_TYPE_U32 }, [RTA_PREFSRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */ -/* - [RTA_METRICS] = { .type = NETLINK_TYPE_NESTED }, - [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, + [RTA_METRICS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_metrics_type_system}, +/* [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, */ [RTA_FLOW] = { .type = NETLINK_TYPE_U32 }, /* 6? */ /* diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c index 70283e5347..5320592f7a 100644 --- a/src/network/networkd-ndisc.c +++ b/src/network/networkd-ndisc.c @@ -56,6 +56,7 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { struct in6_addr gateway; uint16_t lifetime; unsigned preference; + uint32_t mtu; usec_t time_now; int r; Address *address; @@ -116,6 +117,12 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { return; } + r = sd_ndisc_router_get_mtu(rt, &mtu); + if (r < 0) { + log_link_warning_errno(link, r, "Failed to get default router MTU from RA: %m"); + return; + } + r = route_new(&route); if (r < 0) { log_link_error_errno(link, r, "Could not allocate route: %m"); @@ -128,6 +135,7 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { route->pref = preference; route->gw.in6 = gateway; route->lifetime = time_now + lifetime * USEC_PER_SEC; + route->mtu = mtu; r = route_configure(route, link, ndisc_netlink_handler); if (r < 0) { diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index 17cff956da..4dbc19fc3b 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -174,7 +174,7 @@ struct Network { IPv6PrivacyExtensions ipv6_privacy_extensions; struct ether_addr *mac; - unsigned mtu; + size_t mtu; int arp; uint32_t iaid; DUID duid; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index f78e106991..bde26a42d4 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -605,6 +605,20 @@ int route_configure( if (r < 0) return log_error_errno(r, "Could not append RTA_OIF attribute: %m"); + r = sd_netlink_message_open_container(req, RTA_METRICS); + if (r < 0) + return log_error_errno(r, "Could not append RTA_METRICS attribute: %m"); + + if (route->mtu > 0) { + r = sd_netlink_message_append_u32(req, RTAX_MTU, route->mtu); + if (r < 0) + return log_error_errno(r, "Could not append RTAX_MTU attribute: %m"); + } + + r = sd_netlink_message_close_container(req); + if (r < 0) + return log_error_errno(r, "Could not append RTA_METRICS attribute: %m"); + r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL); if (r < 0) return log_error_errno(r, "Could not send rtnetlink message: %m"); diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h index d4e4dbac0b..02f0b27675 100644 --- a/src/network/networkd-route.h +++ b/src/network/networkd-route.h @@ -37,6 +37,7 @@ struct Route { unsigned char tos; uint32_t priority; /* note that ip(8) calls this 'metric' */ uint32_t table; + uint32_t mtu; unsigned char pref; unsigned flags; diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c index 59217b131c..76f5819bb9 100644 --- a/src/test/test-calendarspec.c +++ b/src/test/test-calendarspec.c @@ -176,6 +176,9 @@ int main(int argc, char* argv[]) { test_one("1..3-1..3 1..3:1..3", "*-01,02,03-01,02,03 01,02,03:01,02,03:00"); test_one("00:00:1.125..2.125", "*-*-* 00:00:01.125000,02.125000"); test_one("00:00:1.0..3.8", "*-*-* 00:00:01,02,03"); + test_one("*-*~1 Utc", "*-*~01 00:00:00 UTC"); + test_one("*-*~05,3 ", "*-*~03,05 00:00:00"); + test_one("*-*~* 00:00:00", "*-*-* 00:00:00"); test_next("2016-03-27 03:17:00", "", 12345, 1459048620000000); test_next("2016-03-27 03:17:00", "CET", 12345, 1459041420000000); @@ -190,6 +193,10 @@ int main(int argc, char* argv[]) { test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683420000, 1447398685190000); test_next("2015-11-13 09:11:23.42/1.77", "EET", 1447398683419999, 1447398683420000); test_next("Sun 16:00:00", "CET", 1456041600123456, 1456066800000000); + test_next("*-04-31", "", 12345, -1); + test_next("2016-02~01 UTC", "", 12345, 1456704000000000); + test_next("Mon 2017-05~01..07 UTC", "", 12345, 1496016000000000); + test_next("Mon 2017-05~07/1 UTC", "", 12345, 1496016000000000); assert_se(calendar_spec_from_string("test", &c) < 0); assert_se(calendar_spec_from_string("", &c) < 0); @@ -199,6 +206,8 @@ int main(int argc, char* argv[]) { assert_se(calendar_spec_from_string("2000-03-05 00:00.1:00", &c) < 0); assert_se(calendar_spec_from_string("00:00:00/0.00000001", &c) < 0); assert_se(calendar_spec_from_string("00:00:00.0..00.9", &c) < 0); + assert_se(calendar_spec_from_string("2016~11-22", &c) < 0); + assert_se(calendar_spec_from_string("*-*~5/5", &c) < 0); test_timestamp(); test_hourly_bug_4031(); |