1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "alloc-util.h"
6 #include "bus-internal.h"
7 #include "bus-protocol.h"
9 #include "in-addr-util.h"
12 #include "time-util.h"
13 #include "timesyncd-bus.h"
15 static int property_get_servers(
18 const char *interface
,
20 sd_bus_message
*reply
,
22 sd_bus_error
*error
) {
24 ServerName
*p
, **s
= userdata
;
31 r
= sd_bus_message_open_container(reply
, 'a', "s");
35 LIST_FOREACH(names
, p
, *s
) {
36 r
= sd_bus_message_append(reply
, "s", p
->string
);
41 return sd_bus_message_close_container(reply
);
44 static int property_get_current_server_name(
47 const char *interface
,
49 sd_bus_message
*reply
,
51 sd_bus_error
*error
) {
53 ServerName
**s
= userdata
;
59 return sd_bus_message_append(reply
, "s", *s
? (*s
)->string
: NULL
);
62 static int property_get_current_server_address(
65 const char *interface
,
67 sd_bus_message
*reply
,
69 sd_bus_error
*error
) {
78 a
= *(ServerAddress
**) userdata
;
81 return sd_bus_message_append(reply
, "(iay)", AF_UNSPEC
, 0);
83 r
= sd_bus_message_open_container(reply
, 'r', "iay");
87 r
= sd_bus_message_append(reply
, "i", a
->sockaddr
.sa
.sa_family
);
91 r
= sd_bus_message_append_array(reply
, 'y', &a
->sockaddr
.in
.sin_addr
, FAMILY_ADDRESS_SIZE(a
->sockaddr
.sa
.sa_family
));
95 return sd_bus_message_close_container(reply
);
98 static usec_t
ntp_ts_short_to_usec(const struct ntp_ts_short
*ts
) {
99 return be16toh(ts
->sec
) * USEC_PER_SEC
+ (be16toh(ts
->frac
) * USEC_PER_SEC
) / (usec_t
) 0x10000ULL
;
102 static usec_t
ntp_ts_to_usec(const struct ntp_ts
*ts
) {
103 return (be32toh(ts
->sec
) - OFFSET_1900_1970
) * USEC_PER_SEC
+ (be32toh(ts
->frac
) * USEC_PER_SEC
) / (usec_t
) 0x100000000ULL
;
106 static int property_get_ntp_message(
109 const char *interface
,
110 const char *property
,
111 sd_bus_message
*reply
,
113 sd_bus_error
*error
) {
115 Manager
*m
= userdata
;
121 r
= sd_bus_message_open_container(reply
, 'r', "uuuuittayttttbtt");
125 r
= sd_bus_message_append(reply
, "uuuuitt",
126 NTP_FIELD_LEAP(m
->ntpmsg
.field
),
127 NTP_FIELD_VERSION(m
->ntpmsg
.field
),
128 NTP_FIELD_MODE(m
->ntpmsg
.field
),
131 ntp_ts_short_to_usec(&m
->ntpmsg
.root_delay
),
132 ntp_ts_short_to_usec(&m
->ntpmsg
.root_dispersion
));
136 r
= sd_bus_message_append_array(reply
, 'y', m
->ntpmsg
.refid
, 4);
140 r
= sd_bus_message_append(reply
, "ttttbtt",
141 timespec_load(&m
->origin_time
),
142 ntp_ts_to_usec(&m
->ntpmsg
.recv_time
),
143 ntp_ts_to_usec(&m
->ntpmsg
.trans_time
),
144 timespec_load(&m
->dest_time
),
147 (usec_t
) (m
->samples_jitter
* USEC_PER_SEC
));
151 return sd_bus_message_close_container(reply
);
154 static const sd_bus_vtable manager_vtable
[] = {
155 SD_BUS_VTABLE_START(0),
157 SD_BUS_PROPERTY("LinkNTPServers", "as", property_get_servers
, offsetof(Manager
, link_servers
), 0),
158 SD_BUS_PROPERTY("SystemNTPServers", "as", property_get_servers
, offsetof(Manager
, system_servers
), SD_BUS_VTABLE_PROPERTY_CONST
),
159 SD_BUS_PROPERTY("FallbackNTPServers", "as", property_get_servers
, offsetof(Manager
, fallback_servers
), SD_BUS_VTABLE_PROPERTY_CONST
),
160 SD_BUS_PROPERTY("ServerName", "s", property_get_current_server_name
, offsetof(Manager
, current_server_name
), 0),
161 SD_BUS_PROPERTY("ServerAddress", "(iay)", property_get_current_server_address
, offsetof(Manager
, current_server_address
), 0),
162 SD_BUS_PROPERTY("RootDistanceMaxUSec", "t", bus_property_get_usec
, offsetof(Manager
, max_root_distance_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
163 SD_BUS_PROPERTY("PollIntervalMinUSec", "t", bus_property_get_usec
, offsetof(Manager
, poll_interval_min_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
164 SD_BUS_PROPERTY("PollIntervalMaxUSec", "t", bus_property_get_usec
, offsetof(Manager
, poll_interval_max_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
165 SD_BUS_PROPERTY("PollIntervalUSec", "t", bus_property_get_usec
, offsetof(Manager
, poll_interval_usec
), 0),
166 SD_BUS_PROPERTY("NTPMessage", "(uuuuittayttttbtt)", property_get_ntp_message
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
167 SD_BUS_PROPERTY("Frequency", "x", NULL
, offsetof(Manager
, drift_freq
), 0),
172 int manager_connect_bus(Manager
*m
) {
180 r
= bus_open_system_watch_bind_with_description(&m
->bus
, "bus-api-timesync");
182 return log_error_errno(r
, "Failed to connect to bus: %m");
184 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/timesync1", "org.freedesktop.timesync1.Manager", manager_vtable
, m
);
186 return log_error_errno(r
, "Failed to add manager object vtable: %m");
188 r
= sd_bus_request_name_async(m
->bus
, NULL
, "org.freedesktop.timesync1", 0, NULL
, NULL
);
190 return log_error_errno(r
, "Failed to request name: %m");
192 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
194 return log_error_errno(r
, "Failed to attach bus to event loop: %m");