Add a second UDS port to allow unprivileged applications to monitor ptp4l. On this "read-only" port, disable non-GET actions, forwarding, and access to subscriptions.
Ignore non-management messages on both UDS ports to prevent them from changing the clock or port state. (This should be a separate patch?) TODO: - add option to configure the UDS address (default /var/run/ptp4ro?) - chmod(0666) ? - update man page Signed-off-by: Miroslav Lichvar <mlich...@redhat.com> --- clock.c | 122 +++++++++++++++++++++++++++++++++++++++----------------- port.c | 3 ++ 2 files changed, 89 insertions(+), 36 deletions(-) diff --git a/clock.c b/clock.c index 08c61eb..475aa3d 100644 --- a/clock.c +++ b/clock.c @@ -95,10 +95,11 @@ struct clock { struct foreign_clock *best; struct ClockIdentity best_id; LIST_HEAD(ports_head, port) ports; - struct port *uds_port; + struct port *uds_rw_port; + struct port *uds_ro_port; struct pollfd *pollfd; int pollfd_valid; - int nports; /* does not include the UDS port */ + int nports; /* does not include the two UDS ports */ int last_port_number; int sde; int free_running; @@ -129,7 +130,8 @@ struct clock { struct clock_stats stats; int stats_interval; struct clockcheck *sanity_check; - struct interface *udsif; + struct interface *uds_rw_if; + struct interface *uds_ro_if; LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers; struct monitor *slave_event_monitor; }; @@ -245,7 +247,7 @@ void clock_send_notification(struct clock *c, struct ptp_message *msg, { unsigned int event_pos = event / 8; uint8_t mask = 1 << (event % 8); - struct port *uds = c->uds_port; + struct port *uds = c->uds_rw_port; struct clock_subscriber *s; LIST_FOREACH(s, &c->subscribers, list) { @@ -267,13 +269,15 @@ void clock_destroy(struct clock *c) { struct port *p, *tmp; - interface_destroy(c->udsif); + interface_destroy(c->uds_rw_if); + interface_destroy(c->uds_ro_if); clock_flush_subscriptions(c); LIST_FOREACH_SAFE(p, &c->ports, list, tmp) { clock_remove_port(c, p); } monitor_destroy(c->slave_event_monitor); - port_close(c->uds_port); + port_close(c->uds_rw_port); + port_close(c->uds_ro_port); free(c->pollfd); if (c->clkid != CLOCK_REALTIME) { phc_close(c->clkid); @@ -442,8 +446,8 @@ static int clock_management_fill_response(struct clock *c, struct port *p, datalen = sizeof(*gsn); break; case TLV_SUBSCRIBE_EVENTS_NP: - if (p != c->uds_port) { - /* Only the UDS port allowed. */ + if (p != c->uds_rw_port) { + /* Only the UDS RW port allowed. */ break; } sen = (struct subscribe_events_np *)tlv->data; @@ -774,6 +778,10 @@ static int clock_utc_correct(struct clock *c, tmv_t ingress) static int forwarding(struct clock *c, struct port *p) { enum port_state ps = port_state(p); + + if (p == c->uds_ro_port) + return 0; + switch (ps) { case PS_MASTER: case PS_GRAND_MASTER: @@ -784,7 +792,7 @@ static int forwarding(struct clock *c, struct port *p) default: break; } - if (p == c->uds_port && ps != PS_FAULTY) { + if (p == c->uds_rw_port && ps != PS_FAULTY) { return 1; } return 0; @@ -818,7 +826,7 @@ static int clock_add_port(struct clock *c, const char *phc_device, { struct port *p, *piter, *lastp = NULL; - if (clock_resize_pollfd(c, c->nports + 1)) { + if (clock_resize_pollfd(c, c->nports + 2)) { return -1; } p = port_open(phc_device, phc_index, timestamping, @@ -1044,20 +1052,40 @@ struct clock *clock_create(enum clock_type type, struct config *config, /* Configure the UDS. */ uds_ifname = config_get_string(config, NULL, "uds_address"); - c->udsif = interface_create(uds_ifname); - if (config_set_section_int(config, interface_name(c->udsif), + c->uds_rw_if = interface_create(uds_ifname); + if (config_set_section_int(config, interface_name(c->uds_rw_if), "announceReceiptTimeout", 0)) { return NULL; } - if (config_set_section_int(config, interface_name(c->udsif), + if (config_set_section_int(config, interface_name(c->uds_rw_if), "delay_mechanism", DM_AUTO)) { return NULL; } - if (config_set_section_int(config, interface_name(c->udsif), + if (config_set_section_int(config, interface_name(c->uds_rw_if), "network_transport", TRANS_UDS)) { return NULL; } - if (config_set_section_int(config, interface_name(c->udsif), + if (config_set_section_int(config, interface_name(c->uds_rw_if), + "delay_filter_length", 1)) { + return NULL; + } + + //uds_ifname = config_get_string(config, NULL, "uds_address2"); + uds_ifname = "/var/run/ptp4lro"; + c->uds_ro_if = interface_create(uds_ifname); + if (config_set_section_int(config, interface_name(c->uds_ro_if), + "announceReceiptTimeout", 0)) { + return NULL; + } + if (config_set_section_int(config, interface_name(c->uds_ro_if), + "delay_mechanism", DM_AUTO)) { + return NULL; + } + if (config_set_section_int(config, interface_name(c->uds_ro_if), + "network_transport", TRANS_UDS)) { + return NULL; + } + if (config_set_section_int(config, interface_name(c->uds_ro_if), "delay_filter_length", 1)) { return NULL; } @@ -1173,27 +1201,36 @@ struct clock *clock_create(enum clock_type type, struct config *config, LIST_INIT(&c->subscribers); LIST_INIT(&c->ports); - c->last_port_number = 0; + c->last_port_number = -1; if (clock_resize_pollfd(c, 0)) { pr_err("failed to allocate pollfd"); return NULL; } - /* Create the UDS interface. */ - c->uds_port = port_open(phc_device, phc_index, timestamping, 0, c->udsif, c); - if (!c->uds_port) { - pr_err("failed to open the UDS port"); + /* Create the UDS interfaces. */ + c->uds_rw_port = port_open(phc_device, phc_index, timestamping, + ++c->last_port_number, c->uds_rw_if, c); + if (!c->uds_rw_port) { + pr_err("failed to open the UDS RW port"); return NULL; } clock_fda_changed(c); - c->slave_event_monitor = monitor_create(config, c->uds_port); + c->slave_event_monitor = monitor_create(config, c->uds_rw_port); if (!c->slave_event_monitor) { pr_err("failed to create slave event monitor"); return NULL; } + c->uds_ro_port = port_open(phc_device, phc_index, timestamping, + ++c->last_port_number, c->uds_ro_if, c); + if (!c->uds_rw_port) { + pr_err("failed to open the UDS RO port"); + return NULL; + } + clock_fda_changed(c); + /* Create the ports. */ STAILQ_FOREACH(iface, &config->interfaces, list) { if (clock_add_port(c, phc_device, phc_index, timestamping, iface)) { @@ -1207,7 +1244,8 @@ struct clock *clock_create(enum clock_type type, struct config *config, LIST_FOREACH(p, &c->ports, list) { port_dispatch(p, EV_INITIALIZE, 0); } - port_dispatch(c->uds_port, EV_INITIALIZE, 0); + port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0); + port_dispatch(c->uds_ro_port, EV_INITIALIZE, 0); return c; } @@ -1278,9 +1316,9 @@ static int clock_resize_pollfd(struct clock *c, int new_nports) { struct pollfd *new_pollfd; - /* Need to allocate one whole extra block of fds for UDS. */ + /* Need to allocate two whole extra blocks of fds for UDS ports. */ new_pollfd = realloc(c->pollfd, - (new_nports + 1) * N_CLOCK_PFD * + (new_nports + 2) * N_CLOCK_PFD * sizeof(struct pollfd)); if (!new_pollfd) { return -1; @@ -1315,7 +1353,9 @@ static void clock_check_pollfd(struct clock *c) clock_fill_pollfd(dest, p); dest += N_CLOCK_PFD; } - clock_fill_pollfd(dest, c->uds_port); + clock_fill_pollfd(dest, c->uds_rw_port); + dest += N_CLOCK_PFD; + clock_fill_pollfd(dest, c->uds_ro_port); c->pollfd_valid = 1; } @@ -1331,8 +1371,9 @@ static int clock_do_forward_mgmt(struct clock *c, if (in == out || !forwarding(c, out)) return 0; - /* Don't forward any requests to the UDS port. */ - if (out == c->uds_port) { + /* Don't forward any requests to the UDS RW port + (UDS RO port doesn't allow any forwarding). */ + if (out == c->uds_rw_port) { switch (management_action(msg)) { case GET: case SET: @@ -1363,7 +1404,7 @@ static void clock_forward_mgmt_msg(struct clock *c, struct port *p, struct ptp_m pr_err("port %d: management forward failed", port_number(piter)); } - if (clock_do_forward_mgmt(c, p, c->uds_port, msg, &msg_ready)) + if (clock_do_forward_mgmt(c, p, c->uds_rw_port, msg, &msg_ready)) pr_err("uds port: management forward failed"); if (msg_ready) { msg_post_recv(msg, pdulen); @@ -1415,8 +1456,8 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg) clock_management_send_error(p, msg, TLV_WRONG_LENGTH); return changed; } - if (p != c->uds_port) { - /* Sorry, only allowed on the UDS port. */ + if (p != c->uds_rw_port) { + /* Sorry, only allowed on the UDS RW port. */ clock_management_send_error(p, msg, TLV_NOT_SUPPORTED); return changed; } @@ -1431,8 +1472,8 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg) switch (mgt->id) { case TLV_PORT_PROPERTIES_NP: - if (p != c->uds_port) { - /* Only the UDS port allowed. */ + if (p != c->uds_rw_port) { + /* Only the UDS RW port allowed. */ clock_management_send_error(p, msg, TLV_NOT_SUPPORTED); return 0; } @@ -1496,7 +1537,7 @@ int clock_manage(struct clock *c, struct port *p, struct ptp_message *msg) void clock_notify_event(struct clock *c, enum notification event) { - struct port *uds = c->uds_port; + struct port *uds = c->uds_rw_port; struct PortIdentity pid = port_identity(uds); struct ptp_message *msg; int id; @@ -1543,7 +1584,7 @@ int clock_poll(struct clock *c) struct port *p; clock_check_pollfd(c); - cnt = poll(c->pollfd, (c->nports + 1) * N_CLOCK_PFD, -1); + cnt = poll(c->pollfd, (c->nports + 2) * N_CLOCK_PFD, -1); if (cnt < 0) { if (EINTR == errno) { return 0; @@ -1597,10 +1638,19 @@ int clock_poll(struct clock *c) cur += N_CLOCK_PFD; } - /* Check the UDS port. */ + /* Check the UDS ports. */ + for (i = 0; i < N_POLLFD; i++) { + if (cur[i].revents & (POLLIN|POLLPRI)) { + event = port_event(c->uds_rw_port, i); + if (EV_STATE_DECISION_EVENT == event) { + c->sde = 1; + } + } + } + cur += N_CLOCK_PFD; for (i = 0; i < N_POLLFD; i++) { if (cur[i].revents & (POLLIN|POLLPRI)) { - event = port_event(c->uds_port, i); + event = port_event(c->uds_ro_port, i); if (EV_STATE_DECISION_EVENT == event) { c->sde = 1; } diff --git a/port.c b/port.c index 0a93c06..7f4cd2d 100644 --- a/port.c +++ b/port.c @@ -691,6 +691,9 @@ static int port_ignore(struct port *p, struct ptp_message *m) { struct ClockIdentity c1, c2; + if (transport_type(p->trp) == TRANS_UDS && msg_type(m) != MANAGEMENT) { + return 1; + } if (incapable_ignore(p, m)) { return 1; } -- 2.26.2 _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel