Add a second UDS port to allow untrusted applications to monitor ptp4l.
On this "read-only" UDS port disable non-GET actions and forwarding.
The path can be configured with the uds_address2 option (default is
/var/run/ptp4lro).

Forwarding is disabled to limit the access to the local ptp4l instance.

Subscriptions are not enabled to prevent the applications from making a
large number of subscriptions or interfere with applications that have
access to the read-write UDS port.

Signed-off-by: Miroslav Lichvar <mlich...@redhat.com>
---
 clock.c             | 74 +++++++++++++++++++++++++++++++++++++--------
 config.c            |  1 +
 configs/default.cfg |  1 +
 ptp4l.8             |  6 ++++
 4 files changed, 69 insertions(+), 13 deletions(-)

diff --git a/clock.c b/clock.c
index 12f4d8c..fb11c54 100644
--- a/clock.c
+++ b/clock.c
@@ -96,9 +96,10 @@ struct clock {
        struct ClockIdentity best_id;
        LIST_HEAD(ports_head, port) ports;
        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;
@@ -130,6 +131,7 @@ struct clock {
        int stats_interval;
        struct clockcheck *sanity_check;
        struct interface *uds_rw_if;
+       struct interface *uds_ro_if;
        LIST_HEAD(clock_subscribers_head, clock_subscriber) subscribers;
        struct monitor *slave_event_monitor;
 };
@@ -268,12 +270,14 @@ void clock_destroy(struct clock *c)
        struct port *p, *tmp;
 
        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_rw_port);
+       port_close(c->uds_ro_port);
        free(c->pollfd);
        if (c->clkid != CLOCK_REALTIME) {
                phc_close(c->clkid);
@@ -443,7 +447,7 @@ static int clock_management_fill_response(struct clock *c, 
struct port *p,
                break;
        case TLV_SUBSCRIBE_EVENTS_NP:
                if (p != c->uds_rw_port) {
-                       /* Only the UDS port allowed. */
+                       /* 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:
@@ -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,
@@ -1043,6 +1051,7 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
        }
 
        /* Configure the UDS. */
+
        uds_ifname = config_get_string(config, NULL, "uds_address");
        c->uds_rw_if = interface_create(uds_ifname);
        if (config_set_section_int(config, interface_name(c->uds_rw_if),
@@ -1062,6 +1071,25 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
                return NULL;
        }
 
+       uds_ifname = config_get_string(config, NULL, "uds_address2");
+       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;
+       }
+
        c->config = config;
        c->free_running = config_get_int(config, NULL, "free_running");
        c->freq_est_interval = config_get_int(config, NULL, 
"freq_est_interval");
@@ -1180,11 +1208,12 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
                return NULL;
        }
 
-       /* Create the UDS interface. */
+       /* Create the UDS interfaces. */
+
        c->uds_rw_port = port_open(phc_device, phc_index, timestamping, 0,
                                   c->uds_rw_if, c);
        if (!c->uds_rw_port) {
-               pr_err("failed to open the UDS port");
+               pr_err("failed to open the UDS-RW port");
                return NULL;
        }
        clock_fda_changed(c);
@@ -1195,6 +1224,14 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
                return NULL;
        }
 
+       c->uds_ro_port = port_open(phc_device, phc_index, timestamping, 0,
+                                  c->uds_ro_if, c);
+       if (!c->uds_ro_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)) {
@@ -1209,6 +1246,7 @@ struct clock *clock_create(enum clock_type type, struct 
config *config,
                port_dispatch(p, EV_INITIALIZE, 0);
        }
        port_dispatch(c->uds_rw_port, EV_INITIALIZE, 0);
+       port_dispatch(c->uds_ro_port, EV_INITIALIZE, 0);
 
        return c;
 }
@@ -1279,9 +1317,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;
@@ -1317,6 +1355,8 @@ static void clock_check_pollfd(struct clock *c)
                dest += N_CLOCK_PFD;
        }
        clock_fill_pollfd(dest, c->uds_rw_port);
+       dest += N_CLOCK_PFD;
+       clock_fill_pollfd(dest, c->uds_ro_port);
        c->pollfd_valid = 1;
 }
 
@@ -1332,7 +1372,8 @@ 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. */
+       /* Don't forward any requests to the UDS-RW port
+          (the UDS-RO port doesn't allow any forwarding). */
        if (out == c->uds_rw_port) {
                switch (management_action(msg)) {
                case GET:
@@ -1417,7 +1458,7 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
                        return changed;
                }
                if (p != c->uds_rw_port) {
-                       /* Sorry, only allowed on the UDS port. */
+                       /* Sorry, only allowed on the UDS-RW port. */
                        clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
                        return changed;
                }
@@ -1426,7 +1467,7 @@ int clock_manage(struct clock *c, struct port *p, struct 
ptp_message *msg)
                break;
        case COMMAND:
                if (p != c->uds_rw_port) {
-                       /* Sorry, only allowed on the UDS port. */
+                       /* Sorry, only allowed on the UDS-RW port. */
                        clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
                        return changed;
                }
@@ -1438,7 +1479,7 @@ 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_rw_port) {
-                       /* Only the UDS port allowed. */
+                       /* Only the UDS-RW port allowed. */
                        clock_management_send_error(p, msg, TLV_NOT_SUPPORTED);
                        return 0;
                }
@@ -1549,7 +1590,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;
@@ -1603,7 +1644,7 @@ 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);
@@ -1612,6 +1653,13 @@ int clock_poll(struct clock *c)
                        }
                }
        }
+       cur += N_CLOCK_PFD;
+       for (i = 0; i < N_POLLFD; i++) {
+               if (cur[i].revents & (POLLIN|POLLPRI)) {
+                       event = port_event(c->uds_ro_port, i);
+                       /* sde is not expected on the UDS-RO port */
+               }
+       }
 
        if (c->sde) {
                handle_state_decision_event(c);
diff --git a/config.c b/config.c
index df5a1ef..273ed59 100644
--- a/config.c
+++ b/config.c
@@ -324,6 +324,7 @@ struct config_item config_tab[] = {
        PORT_ITEM_INT("udp_ttl", 1, 1, 255),
        PORT_ITEM_INT("udp6_scope", 0x0E, 0x00, 0x0F),
        GLOB_ITEM_STR("uds_address", "/var/run/ptp4l"),
+       GLOB_ITEM_STR("uds_address2", "/var/run/ptp4lro"),
        PORT_ITEM_INT("unicast_listen", 0, 0, 1),
        PORT_ITEM_INT("unicast_master_table", 0, 0, INT_MAX),
        PORT_ITEM_INT("unicast_max_message_rate", 1024, 1, INT_MAX),
diff --git a/configs/default.cfg b/configs/default.cfg
index 4317e3a..b8f6680 100644
--- a/configs/default.cfg
+++ b/configs/default.cfg
@@ -91,6 +91,7 @@ p2p_dst_mac           01:80:C2:00:00:0E
 udp_ttl                        1
 udp6_scope             0x0E
 uds_address            /var/run/ptp4l
+uds_address2           /var/run/ptp4lro
 #
 # Default interface options
 #
diff --git a/ptp4l.8 b/ptp4l.8
index 8f7e3c8..cda1039 100644
--- a/ptp4l.8
+++ b/ptp4l.8
@@ -626,6 +626,12 @@ is only relevant with IPv6 transport.  See RFC 4291.  The 
default is
 Specifies the address of the UNIX domain socket for receiving local
 management messages. The default is /var/run/ptp4l.
 .TP
+.B uds_address2
+Specifies the address of the second UNIX domain socket for receiving local
+management messages, which is restricted to GET actions and does not forward
+messages to other ports. Access to this socket can be given to untrusted
+applications for monitoring purposes. The default is /var/run/ptp4lro.
+.TP
 .B dscp_event
 Defines the Differentiated Services Codepoint (DSCP) to be used for PTP
 event messages. Must be a value between 0 and 63. There are several media
-- 
2.26.2



_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to