1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <sys/capability.h>
7 #include "alloc-util.h"
8 #include "bus-get-properties.h"
9 #include "bus-internal.h"
10 #include "bus-log-control-api.h"
11 #include "bus-polkit.h"
12 #include "bus-protocol.h"
14 #include "dns-domain.h"
15 #include "in-addr-util.h"
19 #include "time-util.h"
20 #include "timesyncd-bus.h"
21 #include "user-util.h"
23 static int property_get_servers(
26 const char *interface
,
28 sd_bus_message
*reply
,
30 sd_bus_error
*error
) {
32 ServerName
**s
= ASSERT_PTR(userdata
);
38 r
= sd_bus_message_open_container(reply
, 'a', "s");
42 LIST_FOREACH(names
, p
, *s
) {
43 r
= sd_bus_message_append(reply
, "s", p
->string
);
48 return sd_bus_message_close_container(reply
);
51 static int method_set_runtime_servers(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
52 _cleanup_strv_free_
char **msg_names
= NULL
;
53 Manager
*m
= ASSERT_PTR(userdata
);
58 r
= sd_bus_message_read_strv(message
, &msg_names
);
62 STRV_FOREACH(name
, msg_names
) {
63 r
= dns_name_is_valid_or_address(*name
);
65 return log_error_errno(r
, "Failed to check validity of NTP server name or address '%s': %m", *name
);
67 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid NTP server name or address, refusing: %s", *name
);
70 r
= bus_verify_polkit_async(
72 "org.freedesktop.timesync1.set-runtime-servers",
79 /* Polkit will call us back */
82 manager_flush_runtime_servers(m
);
84 STRV_FOREACH(name
, msg_names
) {
85 r
= server_name_new(m
, NULL
, SERVER_RUNTIME
, *name
);
87 manager_flush_runtime_servers(m
);
89 return log_error_errno(r
, "Failed to add runtime server '%s': %m", *name
);
93 m
->exhausted_servers
= true;
94 manager_set_server_name(m
, NULL
);
95 (void) manager_connect(m
);
97 return sd_bus_reply_method_return(message
, NULL
);
100 static int property_get_current_server_name(
103 const char *interface
,
104 const char *property
,
105 sd_bus_message
*reply
,
107 sd_bus_error
*error
) {
109 ServerName
**s
= ASSERT_PTR(userdata
);
114 return sd_bus_message_append(reply
, "s", *s
? (*s
)->string
: NULL
);
117 static int property_get_current_server_address(
120 const char *interface
,
121 const char *property
,
122 sd_bus_message
*reply
,
124 sd_bus_error
*error
) {
133 a
= *(ServerAddress
**) userdata
;
136 return sd_bus_message_append(reply
, "(iay)", AF_UNSPEC
, 0);
138 assert(IN_SET(a
->sockaddr
.sa
.sa_family
, AF_INET
, AF_INET6
));
140 r
= sd_bus_message_open_container(reply
, 'r', "iay");
144 r
= sd_bus_message_append(reply
, "i", a
->sockaddr
.sa
.sa_family
);
148 r
= sd_bus_message_append_array(reply
, 'y',
149 a
->sockaddr
.sa
.sa_family
== AF_INET
? (void*) &a
->sockaddr
.in
.sin_addr
: (void*) &a
->sockaddr
.in6
.sin6_addr
,
150 FAMILY_ADDRESS_SIZE(a
->sockaddr
.sa
.sa_family
));
154 return sd_bus_message_close_container(reply
);
157 static usec_t
ntp_ts_short_to_usec(const struct ntp_ts_short
*ts
) {
158 return be16toh(ts
->sec
) * USEC_PER_SEC
+ (be16toh(ts
->frac
) * USEC_PER_SEC
) / (usec_t
) 0x10000ULL
;
161 static usec_t
ntp_ts_to_usec(const struct ntp_ts
*ts
) {
162 return (be32toh(ts
->sec
) - OFFSET_1900_1970
) * USEC_PER_SEC
+ (be32toh(ts
->frac
) * USEC_PER_SEC
) / (usec_t
) 0x100000000ULL
;
165 static int property_get_ntp_message(
168 const char *interface
,
169 const char *property
,
170 sd_bus_message
*reply
,
172 sd_bus_error
*error
) {
174 Manager
*m
= ASSERT_PTR(userdata
);
179 r
= sd_bus_message_open_container(reply
, 'r', "uuuuittayttttbtt");
183 r
= sd_bus_message_append(reply
, "uuuuitt",
184 NTP_FIELD_LEAP(m
->ntpmsg
.field
),
185 NTP_FIELD_VERSION(m
->ntpmsg
.field
),
186 NTP_FIELD_MODE(m
->ntpmsg
.field
),
189 ntp_ts_short_to_usec(&m
->ntpmsg
.root_delay
),
190 ntp_ts_short_to_usec(&m
->ntpmsg
.root_dispersion
));
194 r
= sd_bus_message_append_array(reply
, 'y', m
->ntpmsg
.refid
, 4);
198 r
= sd_bus_message_append(reply
, "ttttbtt",
199 timespec_load(&m
->origin_time
),
200 ntp_ts_to_usec(&m
->ntpmsg
.recv_time
),
201 ntp_ts_to_usec(&m
->ntpmsg
.trans_time
),
202 timespec_load(&m
->dest_time
),
205 (usec_t
) (m
->samples_jitter
* USEC_PER_SEC
));
209 return sd_bus_message_close_container(reply
);
212 static const sd_bus_vtable manager_vtable
[] = {
213 SD_BUS_VTABLE_START(0),
215 SD_BUS_PROPERTY("LinkNTPServers", "as", property_get_servers
, offsetof(Manager
, link_servers
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
216 SD_BUS_PROPERTY("SystemNTPServers", "as", property_get_servers
, offsetof(Manager
, system_servers
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
217 SD_BUS_PROPERTY("RuntimeNTPServers", "as", property_get_servers
, offsetof(Manager
, runtime_servers
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
218 SD_BUS_PROPERTY("FallbackNTPServers", "as", property_get_servers
, offsetof(Manager
, fallback_servers
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
219 SD_BUS_PROPERTY("ServerName", "s", property_get_current_server_name
, offsetof(Manager
, current_server_name
), 0),
220 SD_BUS_PROPERTY("ServerAddress", "(iay)", property_get_current_server_address
, offsetof(Manager
, current_server_address
), 0),
221 SD_BUS_PROPERTY("RootDistanceMaxUSec", "t", bus_property_get_usec
, offsetof(Manager
, root_distance_max_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
222 SD_BUS_PROPERTY("PollIntervalMinUSec", "t", bus_property_get_usec
, offsetof(Manager
, poll_interval_min_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
223 SD_BUS_PROPERTY("PollIntervalMaxUSec", "t", bus_property_get_usec
, offsetof(Manager
, poll_interval_max_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
224 SD_BUS_PROPERTY("PollIntervalUSec", "t", bus_property_get_usec
, offsetof(Manager
, poll_interval_usec
), 0),
225 SD_BUS_PROPERTY("NTPMessage", "(uuuuittayttttbtt)", property_get_ntp_message
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
226 SD_BUS_PROPERTY("Frequency", "x", NULL
, offsetof(Manager
, drift_freq
), 0),
228 SD_BUS_METHOD_WITH_ARGS("SetRuntimeNTPServers",
229 SD_BUS_ARGS("as", runtime_servers
),
231 method_set_runtime_servers
,
232 SD_BUS_VTABLE_UNPRIVILEGED
),
237 int manager_connect_bus(Manager
*m
) {
245 r
= bus_open_system_watch_bind_with_description(&m
->bus
, "bus-api-timesync");
247 return log_error_errno(r
, "Failed to connect to bus: %m");
249 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/timesync1", "org.freedesktop.timesync1.Manager", manager_vtable
, m
);
251 return log_error_errno(r
, "Failed to add manager object vtable: %m");
253 r
= bus_log_control_api_register(m
->bus
);
257 r
= sd_bus_request_name_async(m
->bus
, NULL
, "org.freedesktop.timesync1", 0, NULL
, NULL
);
259 return log_error_errno(r
, "Failed to request name: %m");
261 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
263 return log_error_errno(r
, "Failed to attach bus to event loop: %m");