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 assert(IN_SET(a
->sockaddr
.sa
.sa_family
, AF_INET
, AF_INET6
));
85 r
= sd_bus_message_open_container(reply
, 'r', "iay");
89 r
= sd_bus_message_append(reply
, "i", a
->sockaddr
.sa
.sa_family
);
93 r
= sd_bus_message_append_array(reply
, 'y',
94 a
->sockaddr
.sa
.sa_family
== AF_INET
? (void*) &a
->sockaddr
.in
.sin_addr
: (void*) &a
->sockaddr
.in6
.sin6_addr
,
95 FAMILY_ADDRESS_SIZE(a
->sockaddr
.sa
.sa_family
));
99 return sd_bus_message_close_container(reply
);
102 static usec_t
ntp_ts_short_to_usec(const struct ntp_ts_short
*ts
) {
103 return be16toh(ts
->sec
) * USEC_PER_SEC
+ (be16toh(ts
->frac
) * USEC_PER_SEC
) / (usec_t
) 0x10000ULL
;
106 static usec_t
ntp_ts_to_usec(const struct ntp_ts
*ts
) {
107 return (be32toh(ts
->sec
) - OFFSET_1900_1970
) * USEC_PER_SEC
+ (be32toh(ts
->frac
) * USEC_PER_SEC
) / (usec_t
) 0x100000000ULL
;
110 static int property_get_ntp_message(
113 const char *interface
,
114 const char *property
,
115 sd_bus_message
*reply
,
117 sd_bus_error
*error
) {
119 Manager
*m
= userdata
;
125 r
= sd_bus_message_open_container(reply
, 'r', "uuuuittayttttbtt");
129 r
= sd_bus_message_append(reply
, "uuuuitt",
130 NTP_FIELD_LEAP(m
->ntpmsg
.field
),
131 NTP_FIELD_VERSION(m
->ntpmsg
.field
),
132 NTP_FIELD_MODE(m
->ntpmsg
.field
),
135 ntp_ts_short_to_usec(&m
->ntpmsg
.root_delay
),
136 ntp_ts_short_to_usec(&m
->ntpmsg
.root_dispersion
));
140 r
= sd_bus_message_append_array(reply
, 'y', m
->ntpmsg
.refid
, 4);
144 r
= sd_bus_message_append(reply
, "ttttbtt",
145 timespec_load(&m
->origin_time
),
146 ntp_ts_to_usec(&m
->ntpmsg
.recv_time
),
147 ntp_ts_to_usec(&m
->ntpmsg
.trans_time
),
148 timespec_load(&m
->dest_time
),
151 (usec_t
) (m
->samples_jitter
* USEC_PER_SEC
));
155 return sd_bus_message_close_container(reply
);
158 static const sd_bus_vtable manager_vtable
[] = {
159 SD_BUS_VTABLE_START(0),
161 SD_BUS_PROPERTY("LinkNTPServers", "as", property_get_servers
, offsetof(Manager
, link_servers
), 0),
162 SD_BUS_PROPERTY("SystemNTPServers", "as", property_get_servers
, offsetof(Manager
, system_servers
), SD_BUS_VTABLE_PROPERTY_CONST
),
163 SD_BUS_PROPERTY("FallbackNTPServers", "as", property_get_servers
, offsetof(Manager
, fallback_servers
), SD_BUS_VTABLE_PROPERTY_CONST
),
164 SD_BUS_PROPERTY("ServerName", "s", property_get_current_server_name
, offsetof(Manager
, current_server_name
), 0),
165 SD_BUS_PROPERTY("ServerAddress", "(iay)", property_get_current_server_address
, offsetof(Manager
, current_server_address
), 0),
166 SD_BUS_PROPERTY("RootDistanceMaxUSec", "t", bus_property_get_usec
, offsetof(Manager
, max_root_distance_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
167 SD_BUS_PROPERTY("PollIntervalMinUSec", "t", bus_property_get_usec
, offsetof(Manager
, poll_interval_min_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
168 SD_BUS_PROPERTY("PollIntervalMaxUSec", "t", bus_property_get_usec
, offsetof(Manager
, poll_interval_max_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
169 SD_BUS_PROPERTY("PollIntervalUSec", "t", bus_property_get_usec
, offsetof(Manager
, poll_interval_usec
), 0),
170 SD_BUS_PROPERTY("NTPMessage", "(uuuuittayttttbtt)", property_get_ntp_message
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
171 SD_BUS_PROPERTY("Frequency", "x", NULL
, offsetof(Manager
, drift_freq
), 0),
176 int manager_connect_bus(Manager
*m
) {
184 r
= bus_open_system_watch_bind_with_description(&m
->bus
, "bus-api-timesync");
186 return log_error_errno(r
, "Failed to connect to bus: %m");
188 r
= sd_bus_add_object_vtable(m
->bus
, NULL
, "/org/freedesktop/timesync1", "org.freedesktop.timesync1.Manager", manager_vtable
, m
);
190 return log_error_errno(r
, "Failed to add manager object vtable: %m");
192 r
= sd_bus_request_name_async(m
->bus
, NULL
, "org.freedesktop.timesync1", 0, NULL
, NULL
);
194 return log_error_errno(r
, "Failed to request name: %m");
196 r
= sd_bus_attach_event(m
->bus
, m
->event
, 0);
198 return log_error_errno(r
, "Failed to attach bus to event loop: %m");