]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-mptcp.c
Fix MPTCP support
[tcpdump] / print-mptcp.c
index 551fcbd9d9b280d6b877362f3dde44ad4bebb897..86c752b7969505ad5b9f250c35428d21f7dc556a 100644 (file)
 
 #include "ipproto.h"
 #include "mptcp.h"
+#include "tcp.h"
 
-static int dummy_print(const u_char *opt _U_, u_int opt_len _U_)
+static int dummy_print(const u_char *opt _U_, u_int opt_len _U_, u_char flags _U_)
 {
         return 1;
 }
 
-static int mp_capable_print(const u_char *opt, u_int opt_len)
+static int mp_capable_print(const u_char *opt, u_int opt_len, u_char flags)
 {
         struct mp_capable *mpc = (struct mp_capable *) opt;
 
+        if (!(opt_len == 12 && flags & TH_SYN) &&
+            !(opt_len == 20 && (flags & (TH_SYN | TH_ACK)) == TH_ACK))
+                return 0;
+
+        if (mpc->ver != 0) {
+                printf(" Unknown Version (%d)", mpc->ver);
+                return 1;
+        }
+
         if (mpc->c)
                 printf(" csum");
-        printf(" {0x%" PRIx64, mpc->sender_key);
-        if (opt_len == 20)
-                printf(",0x%" PRIx64, mpc->receiver_key);
+        printf(" {0x%" PRIx64, EXTRACT_64BITS(&mpc->sender_key));
+        if (opt_len == 20) /* ACK */
+                printf(",0x%" PRIx64, EXTRACT_64BITS(&mpc->receiver_key));
         printf("}");
         return 1;
 }
 
-static int mp_join_print(const u_char *opt, u_int opt_len)
+static int mp_join_print(const u_char *opt, u_int opt_len, u_char flags)
 {
         struct mp_join *mpj = (struct mp_join *) opt;
 
-        if (mpj->b)
-                printf(" backup");
-        printf(" id %" PRIu8, mpj->addr_id);
+        if (!(opt_len == 12 && flags & TH_SYN) &&
+            !(opt_len == 16 && (flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) &&
+            !(opt_len == 24 && flags & TH_ACK))
+                return 0;
 
-        if (opt_len == 12)
-                printf(" token 0x%" PRIx32, mpj->u.syn.token);
+        if (opt_len != 24) {
+                if (mpj->b)
+                        printf(" backup");
+                printf(" id %u", mpj->addr_id);
+        }
 
+        switch (opt_len) {
+        case 12: /* SYN */
+                printf(" token 0x%" PRIx32 " nonce 0x%" PRIx32,
+                        EXTRACT_32BITS(&mpj->u.syn.token),
+                        EXTRACT_32BITS(&mpj->u.syn.nonce));
+                break;
+        case 16: /* SYN/ACK */
+                printf(" hmac 0x%" PRIx64 " nonce 0x%" PRIx32,
+                        EXTRACT_64BITS(&mpj->u.synack.mac),
+                        EXTRACT_32BITS(&mpj->u.synack.nonce));
+                break;
+        case 24: {/* ACK */
+                int i;
+                printf(" hmac 0x");
+                for (i = 0; i < sizeof(mpj->u.ack.mac); ++i)
+                        printf("%02x", mpj->u.ack.mac[i]);
+        }
+        default:
+                break;
+        }
         return 1;
 }
 
-static u_int mp_dss_len(struct mp_dss *m, u_int csum)
+static u_int mp_dss_len(struct mp_dss *m, int csum)
 {
         return 4 + m->A * (4 + m->a * 4) + m->M * (10 + m->m * 4 + csum * 2);
 }
 
-static int mp_dss_print(const u_char *opt, u_int opt_len)
+static int mp_dss_print(const u_char *opt, u_int opt_len, u_char flags)
 {
         struct mp_dss *mdss = (struct mp_dss *) opt;
 
+        if ((opt_len != mp_dss_len(mdss, 1) &&
+             opt_len != mp_dss_len(mdss, 0)) || flags & TH_SYN)
+                return 0;
+
         if (mdss->F)
                 printf(" fin");
 
@@ -120,23 +158,28 @@ static int mp_dss_print(const u_char *opt, u_int opt_len)
         return 1;
 }
 
-static int add_addr_print(const u_char *opt, u_int opt_len)
+static int add_addr_print(const u_char *opt, u_int opt_len, u_char flags _U_)
 {
         struct mp_add_addr *add_addr = (struct mp_add_addr *) opt;
 
-        printf(" id %" PRIu8, add_addr->addr_id);
+        if (!((opt_len == 8 || opt_len == 10) && add_addr->ipver == 4) &&
+            !((opt_len == 20 || opt_len == 22) && add_addr->ipver == 6))
+                return 0;
+
+        printf(" id %u", add_addr->addr_id);
         switch (add_addr->ipver) {
         case 4:
                 printf(" %s", ipaddr_string(&add_addr->u.v4.addr));
                 break;
-#ifdef INET6
         case 6:
+#ifdef INET6
                 printf(" %s", ip6addr_string(&add_addr->u.v6.addr));
-                break;
 #endif
+                break;
         default:
                 return 0;
         }
+
         if (opt_len == 10 || opt_len == 22)
                 printf(":%" PRIu16, ntohs(add_addr->ipver == 4 ?
                                          add_addr->u.v4.port :
@@ -144,66 +187,82 @@ static int add_addr_print(const u_char *opt, u_int opt_len)
         return 1;
 }
 
-static int remove_addr_print(const u_char *opt, u_int opt_len)
+static int remove_addr_print(const u_char *opt, u_int opt_len, u_char flags _U_)
 {
         struct mp_remove_addr *rem_addr = (struct mp_remove_addr *) opt;
         u_int8_t *addr_id = &rem_addr->addrs_id;
 
+        if (opt_len < 4)
+                return 0;
+
         opt_len -= 3;
         printf(" id");
         while (opt_len--)
-                printf(" %" PRIu8, *addr_id++);
+                printf(" %u", *addr_id++);
         return 1;
 }
 
-static int mp_prio_print(const u_char *opt, u_int opt_len)
+static int mp_prio_print(const u_char *opt, u_int opt_len, u_char flags _U_)
 {
         struct mp_prio *mpp = (struct mp_prio *) opt;
 
+        if (opt_len != 3 && opt_len != 4)
+                return 0;
+
         if (mpp->b)
                 printf(" backup");
         else
                 printf(" non-backup");
         if (opt_len == 4)
-                printf(" id %" PRIu8, mpp->addr_id);
+                printf(" id %u", mpp->addr_id);
 
         return 1;
 }
 
-static int mp_fail_print(const u_char *opt, u_int opt_len _U_)
+static int mp_fail_print(const u_char *opt, u_int opt_len, u_char flags)
 {
-        opt += 4;
-        printf(" seq %" PRIu64, EXTRACT_64BITS(opt));
+        if (opt_len != 12)
+                return 0;
+
+        printf(" seq %" PRIu64, EXTRACT_64BITS(opt + 4));
         return 1;
 }
 
-static int mp_fast_close_print(const u_char *opt, u_int opt_len _U_)
+static int mp_fast_close_print(const u_char *opt, u_int opt_len, u_char flags)
 {
-        opt += 4;
-        printf(" key 0x%" PRIx64, *((uint64_t *)opt));
+        if (opt_len != 12)
+                return 0;
+
+        printf(" key 0x%" PRIx64, EXTRACT_64BITS(opt + 4));
         return 1;
 }
 
 static struct {
         const char *name;
-        int (*print)(const u_char *, u_int);
+        int (*print)(const u_char *, u_int, u_char);
 } mptcp_options[] = {
-        { "capable",        mp_capable_print },
-        { "join",        mp_join_print },
+        { "capable", mp_capable_print},
+        { "join",       mp_join_print },
         { "dss",        mp_dss_print },
-        { "add-addr",        add_addr_print },
-        { "rem-addr",        remove_addr_print },
-        { "prio",        mp_prio_print },
-        { "fail",        mp_fail_print },
-        { "fast-close",        mp_fast_close_print },
-        { "unknown",        dummy_print },
+        { "add-addr",   add_addr_print },
+        { "rem-addr",   remove_addr_print },
+        { "prio",       mp_prio_print },
+        { "fail",       mp_fail_print },
+        { "fast-close", mp_fast_close_print },
+        { "unknown",    dummy_print },
 };
 
-int mptcp_print(const u_char *cp, u_int len)
+int mptcp_print(const u_char *cp, u_int len, u_char flags)
 {
-        struct mptcp_option *opt = (struct mptcp_option *) cp;
-        u_int subtype = min(opt->sub, MPTCP_SUB_FCLOSE + 1);
+        struct mptcp_option *opt;
+        u_int subtype;
+
+        if (len < 3)
+                return 0;
+
+        opt = (struct mptcp_option *) cp;
+        subtype = min(opt->sub, MPTCP_SUB_FCLOSE + 1);
 
         printf(" %s", mptcp_options[subtype].name);
-        return mptcp_options[subtype].print(cp, len);
+        return mptcp_options[subtype].print(cp, len, flags);
 }