Some messages do not need a new authentication tlv attached but instead only 
require
the existing tlv to be updated because a protected field was edited. These 
include
messages being forward via a transparent clock and management messages.

Introduce sad_update_auth_tlv() to search for existing authentication tlvs, 
confirm
their spp/security parameters are known, and regenerate the icv.

Because this function still requires valid tlv pointers, add msg_tlv_copy() to 
copy
the pointers from the formatted message to the raw message duplicate.

In addition add various calls to e2e_tc/p2p_tc to match port.c

Signed-off-by: Clay Kaiser <clay.kai...@ibm.com>
---
 clock.c  |  2 ++
 e2e_tc.c | 24 +++++++++++++++++++++++-
 msg.c    | 24 +++++++++++++++++++++++-
 msg.h    | 14 +++++++++++++-
 p2p_tc.c | 25 ++++++++++++++++++++++++-
 sad.c    | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 sad.h    | 11 +++++++++++
 tc.c     |  7 +++++++
 8 files changed, 156 insertions(+), 4 deletions(-)

diff --git a/clock.c b/clock.c
index 51c779b..785384b 100644
--- a/clock.c
+++ b/clock.c
@@ -337,6 +337,7 @@ void clock_send_notification(struct clock *c, struct 
ptp_message *msg,
                msg->management.targetPortIdentity.portNumber =
                        htons(s->targetPortIdentity.portNumber);
                msg->address = s->addr;
+               sad_update_auth_tlv(clock_config(c), msg);
                port_forward_to(uds, msg);
        }
 }
@@ -1588,6 +1589,7 @@ static int clock_do_forward_mgmt(struct clock *c,
                /* delay calling msg_pre_send until
                 * actually forwarding */
                msg_pre_send(msg);
+               sad_update_auth_tlv(clock_config(c), msg);
                *pre_sent = 1;
        }
        return port_forward(out, msg);
diff --git a/e2e_tc.c b/e2e_tc.c
index 2f8e821..8ca87f5 100644
--- a/e2e_tc.c
+++ b/e2e_tc.c
@@ -22,6 +22,7 @@
 #include "port_private.h"
 #include "print.h"
 #include "rtnl.h"
+#include "sad.h"
 #include "tc.h"
 
 void e2e_dispatch(struct port *p, enum fsm_event event, int mdiff)
@@ -50,6 +51,7 @@ void e2e_dispatch(struct port *p, enum fsm_event event, int 
mdiff)
        case PS_FAULTY:
        case PS_DISABLED:
                port_disable(p);
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                break;
        case PS_LISTENING:
                port_set_announce_tmo(p);
@@ -60,6 +62,7 @@ void e2e_dispatch(struct port *p, enum fsm_event event, int 
mdiff)
                break;
        case PS_MASTER:
        case PS_GRAND_MASTER:
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                break;
        case PS_PASSIVE:
                port_set_announce_tmo(p);
@@ -67,6 +70,7 @@ void e2e_dispatch(struct port *p, enum fsm_event event, int 
mdiff)
        case PS_UNCALIBRATED:
                flush_last_sync(p);
                flush_delay_req(p);
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                /* fall through */
        case PS_SLAVE:
                port_set_announce_tmo(p);
@@ -76,7 +80,7 @@ void e2e_dispatch(struct port *p, enum fsm_event event, int 
mdiff)
 
 enum fsm_event e2e_event(struct port *p, int fd_index)
 {
-       int cnt, fd = p->fda.fd[fd_index];
+       int cnt, fd = p->fda.fd[fd_index], err;
        enum fsm_event event = EV_NONE;
        struct ptp_message *msg, *dup;
 
@@ -160,9 +164,27 @@ enum fsm_event e2e_event(struct port *p, int fd_index)
                msg_put(msg);
                return EV_NONE;
        }
+       msg_tlv_copy(dup, msg);
        if (tc_ignore(p, dup)) {
                msg_put(dup);
                dup = NULL;
+       } else {
+               err = sad_process_auth(clock_config(p->clock), p->spp, dup, 
msg);
+               if (err) {
+                       switch (err) {
+                       case -EBADMSG:
+                               pr_err("%s: bad message", p->log_name);
+                               break;
+                       case -EPROTO:
+                               pr_debug("%s: ignoring message", p->log_name);
+                               break;
+                       }
+                       msg_put(msg);
+                       if (dup) {
+                               msg_put(dup);
+                       }
+                       return EV_NONE;
+               }
        }
 
        switch (msg_type(msg)) {
diff --git a/msg.c b/msg.c
index c82a5cb..5181570 100644
--- a/msg.c
+++ b/msg.c
@@ -189,6 +189,8 @@ static int suffix_post_recv(struct ptp_message *msg, int 
len)
        if (!ptr)
                return 0;
 
+       msg_tlv_recycle(msg);
+
        while (len >= sizeof(struct TLV)) {
                extra = tlv_extra_alloc();
                if (!extra) {
@@ -233,7 +235,6 @@ static void suffix_pre_send(struct ptp_message *msg)
                tlv->type = htons(tlv->type);
                tlv->length = htons(tlv->length);
        }
-       msg_tlv_recycle(msg);
 }
 
 static void timestamp_post_recv(struct ptp_message *m, struct Timestamp *ts)
@@ -516,6 +517,27 @@ int msg_tlv_count(struct ptp_message *msg)
        return count;
 }
 
+int msg_tlv_copy(struct ptp_message *msg, struct ptp_message *dup) {
+       struct tlv_extra *extra, *dup_extra;
+       struct TLV *tlv;
+
+       if (msg_type(msg) != msg_type(dup)) {
+               return -1;
+       }
+       if (msg->header.messageLength != ntohs(dup->header.messageLength)) {
+               return -1;
+       }
+
+       TAILQ_FOREACH(extra, &msg->tlv_list, list) {
+               tlv = (void *) extra->tlv - (void *) msg + (void *) dup;
+               dup_extra = tlv_extra_alloc();
+               dup_extra->tlv = tlv;
+               msg_tlv_attach(dup, dup_extra);
+       }
+
+       return 0;
+}
+
 const char *msg_type_string(int type)
 {
        switch (type) {
diff --git a/msg.h b/msg.h
index 044b92b..0b4c5f0 100644
--- a/msg.h
+++ b/msg.h
@@ -309,6 +309,18 @@ struct tlv_extra *msg_tlv_append(struct ptp_message *msg, 
int length);
  */
 void msg_tlv_attach(struct ptp_message *msg, struct tlv_extra *extra);
 
+/**
+ * Copy list of TLVs from message that has gone through @ref msg_post_recv()
+ * to a network byte order duplicate message. This is useful for TC 
applications
+ * where any auth tlvs must be updated on the raw forwarded messages.
+ * @param msg  A message obtained using @ref msg_allocate().
+ *             The passed message must have been passed to @ref msg_post_recv()
+ *             in order to have tlv pointers attached.
+ * @param dup  A duplicate of msg that is still in network byte order.
+ * @return     -1 if the messages do not match, otherwise 0
+ */
+int msg_tlv_copy(struct ptp_message *msg, struct ptp_message *dup);
+
 /*
  * Return the number of TLVs attached to a message.
  * @param msg  A message obtained using @ref msg_allocate().
@@ -366,7 +378,7 @@ void msg_cleanup(void);
  * @param msg  A message obtained using @ref msg_allocate().
  *             The passed message must be in network byte order, not
  *             having been passed to @ref msg_post_recv().
- * @param cnt  The size of 'msg' in bytes. set to zero when
+ * @param cnt  The size of msg in bytes. set to zero when
  *             @ref msg_post_recv() is not required (icv calculation)
  * @return     Pointer to a message on success, NULL otherwise.
  *             The returned message will be in host byte order, having
diff --git a/p2p_tc.c b/p2p_tc.c
index 75cb3b9..1289563 100644
--- a/p2p_tc.c
+++ b/p2p_tc.c
@@ -22,6 +22,7 @@
 #include "port_private.h"
 #include "print.h"
 #include "rtnl.h"
+#include "sad.h"
 #include "tc.h"
 
 static int p2p_delay_request(struct port *p)
@@ -69,6 +70,7 @@ void p2p_dispatch(struct port *p, enum fsm_event event, int 
mdiff)
        case PS_FAULTY:
        case PS_DISABLED:
                port_disable(p);
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                break;
        case PS_LISTENING:
                port_set_announce_tmo(p);
@@ -79,11 +81,14 @@ void p2p_dispatch(struct port *p, enum fsm_event event, int 
mdiff)
                break;
        case PS_MASTER:
        case PS_GRAND_MASTER:
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
                break;
        case PS_PASSIVE:
                port_set_announce_tmo(p);
                break;
        case PS_UNCALIBRATED:
+               sad_set_last_seqid(clock_config(p->clock), p->spp, 0);
+               /* fall through */
        case PS_SLAVE:
                port_set_announce_tmo(p);
                break;
@@ -92,7 +97,7 @@ void p2p_dispatch(struct port *p, enum fsm_event event, int 
mdiff)
 
 enum fsm_event p2p_event(struct port *p, int fd_index)
 {
-       int cnt, fd = p->fda.fd[fd_index];
+       int cnt, fd = p->fda.fd[fd_index], err;
        enum fsm_event event = EV_NONE;
        struct ptp_message *msg, *dup;
 
@@ -163,9 +168,27 @@ enum fsm_event p2p_event(struct port *p, int fd_index)
                msg_put(msg);
                return EV_NONE;
        }
+       msg_tlv_copy(dup, msg);
        if (tc_ignore(p, dup)) {
                msg_put(dup);
                dup = NULL;
+       } else {
+               err = sad_process_auth(clock_config(p->clock), p->spp, dup, 
msg);
+               if (err) {
+                       switch (err) {
+                       case -EBADMSG:
+                               pr_err("%s: bad message", p->log_name);
+                               break;
+                       case -EPROTO:
+                               pr_debug("%s: ignoring message", p->log_name);
+                               break;
+                       }
+                       msg_put(msg);
+                       if (dup) {
+                               msg_put(dup);
+                       }
+                       return EV_NONE;
+               }
        }
 
        switch (msg_type(msg)) {
diff --git a/sad.c b/sad.c
index ee8ead4..9849934 100644
--- a/sad.c
+++ b/sad.c
@@ -100,6 +100,59 @@ static int sad_generate_icv(struct security_association 
*sa,
        return icv_len;
 }
 
+int sad_update_auth_tlv(struct config *cfg,
+                       struct ptp_message *msg)
+{
+       struct tlv_extra *extra;
+       struct authentication_tlv *auth;
+       struct security_association *sa;
+       struct security_association_key *key;
+       void *sequenceNo, *res, *icv;
+       /* update any/all authentication tlvs now */
+       TAILQ_FOREACH(extra, &msg->tlv_list, list) {
+               if (ntohs(extra->tlv->type) != TLV_AUTHENTICATION) {
+                       continue;
+               }
+               auth = (struct authentication_tlv *) extra->tlv;
+               /* retrieve sa specified by spp in tlv */
+               sa = sad_get_association(cfg, auth->spp);
+               if (sa == NULL) {
+                       return -1;
+               }
+               /* verify res and seqnum field indicators match expectations */
+               if ((sa->res_ind != (auth->secParamIndicator & 0x1)) ||
+                   (sa->seqnum_ind != (auth->secParamIndicator & 0x2))) {
+                       pr_debug("sa %u: unable to update auth tlv,"
+                               " sec param %d does not match",
+                                sa->spp, auth->secParamIndicator);
+                       return -1;
+               }
+               /* retrieve key specified by keyid in tlv */
+               key = sad_get_key(sa, ntohl(auth->keyID));
+               if (key == NULL) {
+                       pr_debug("sa %u: unable to update auth tlv,"
+                               " unable to retrieve key %u",
+                               sa->spp, ntohl(auth->keyID));
+                       return -1;
+               }
+               /* confirm tlv length to be generated matches what already 
exists */
+               if (ntohs(auth->length) != sad_get_auth_tlv_len(sa, 
key->icv.len) - 4) {
+                       pr_debug("sa %u: unable to update auth tlv,"
+                                " length is not maintained", sa->spp);
+                       return -1;
+               }
+               /* set pointers to extra data used for icv generation */
+               sequenceNo = auth->data;
+               res = sequenceNo + (sa->seqnum_ind ? sa->seqnum_len : 0);
+               icv = res + (sa->res_ind ? sa->res_len : 0);
+               if (!sad_generate_icv(sa, key, msg, icv)) {
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
 int sad_append_auth_tlv(struct config *cfg, int spp,
                        UInteger32 key_id, struct ptp_message *msg)
 {
diff --git a/sad.h b/sad.h
index 7a5051d..6c11ab4 100644
--- a/sad.h
+++ b/sad.h
@@ -37,6 +37,17 @@ struct security_association {
        UInteger16      last_seqid;
 };
 
+/**
+ * Update authentication tlvs. Pass a network byte order message that
+ * still contains tlv pointers. Attempt to recalcute icv for each
+ * authentication tlv attached.
+ * @param cfg  pointer to config that contains sad
+ * @param msg  msg that the authentication tlvs should be updated for
+ * @return     -1 if sa/key is unknown, otherwise 0
+ */
+int sad_update_auth_tlv(struct config *cfg,
+                       struct ptp_message *msg);
+
 /**
  * Append authentication tlv. Includes msg_pre_send() to put message in
  * network byte order so the icv can be calculated.
diff --git a/tc.c b/tc.c
index 1847041..810b7e7 100644
--- a/tc.c
+++ b/tc.c
@@ -20,6 +20,7 @@
 
 #include "port.h"
 #include "print.h"
+#include "sad.h"
 #include "tc.h"
 #include "tmv.h"
 
@@ -162,6 +163,7 @@ static void tc_complete_response(struct port *q, struct 
port *p,
        c1 = net2host64(resp->header.correction);
        c2 = c1 + tmv_to_TimeInterval(residence);
        resp->header.correction = host2net64(c2);
+       sad_update_auth_tlv(clock_config(q->clock), resp);
        cnt = transport_send(p->trp, &p->fda, TRANS_GENERAL, resp);
        if (cnt <= 0) {
                pr_err("tc failed to forward response on %s", p->log_name);
@@ -223,6 +225,7 @@ static void tc_complete_syfup(struct port *q, struct port 
*p,
        c2 += tmv_to_TimeInterval(q->peer_delay);
        c2 += q->asymmetry;
        fup->header.correction = host2net64(c2);
+       sad_update_auth_tlv(clock_config(q->clock), fup);
        cnt = transport_send(p->trp, &p->fda, TRANS_GENERAL, fup);
        if (cnt <= 0) {
                pr_err("tc failed to forward follow up on %s", p->log_name);
@@ -389,6 +392,7 @@ int tc_forward(struct port *q, struct ptp_message *msg)
        if (q->tc_spanning_tree && msg_type(msg) == ANNOUNCE) {
                steps_removed = ntohs(msg->announce.stepsRemoved);
                msg->announce.stepsRemoved = htons(1 + steps_removed);
+               sad_update_auth_tlv(clock_config(q->clock), msg);
        }
 
        for (p = clock_first_port(q->clock); p; p = LIST_NEXT(p, list)) {
@@ -458,7 +462,10 @@ int tc_fwd_sync(struct port *q, struct ptp_message *msg)
                fup->header.sequenceId         = msg->header.sequenceId;
                fup->header.logMessageInterval = msg->header.logMessageInterval;
                fup->follow_up.preciseOriginTimestamp = 
msg->sync.originTimestamp;
+               sad_append_auth_tlv(clock_config(q->clock), q->spp,
+                                   q->active_key_id, fup);
                msg->header.flagField[0]      |= TWO_STEP;
+               sad_update_auth_tlv(clock_config(q->clock), msg);
        }
        err = tc_fwd_event(q, msg);
        if (err) {
-- 
2.42.1



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

Reply via email to