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

Reply via email to