diff options
author | Guy Harris <gharris@sonic.net> | 2020-05-28 02:22:09 -0700 |
---|---|---|
committer | Guy Harris <gharris@sonic.net> | 2020-05-28 02:22:09 -0700 |
commit | 80c07e2a8b50dc71033d6a88e3236298be8e5b0b (patch) | |
tree | e2895fdf6ce16043546d53dff0f9adb931d3058a /print-macsec.c | |
parent | df2d7be173d4a34dd5b39850da6addf44c952401 (diff) | |
download | tcpdump-80c07e2a8b50dc71033d6a88e3236298be8e5b0b.tar.gz |
macsec: take ths short length into account when setting *lengthp and *caplenp.
If the short length is *larger* than the updated length or caplen,
report an error.
If it's *smaller* than the updated length or caplen, update the length
and caplen to the smaller short length.
Diffstat (limited to 'print-macsec.c')
-rw-r--r-- | print-macsec.c | 61 |
1 files changed, 49 insertions, 12 deletions
diff --git a/print-macsec.c b/print-macsec.c index a7bde0b9..892f2c33 100644 --- a/print-macsec.c +++ b/print-macsec.c @@ -100,6 +100,7 @@ int macsec_print(netdissect_options *ndo, const u_char **bp, u_int hdrlen = *hdrlenp; const struct macsec_sectag *sectag = (const struct macsec_sectag *)p; u_int sectag_len; + u_int short_length; save_protocol = ndo->ndo_protocol; ndo->ndo_protocol = "MACsec"; @@ -138,6 +139,7 @@ int macsec_print(netdissect_options *ndo, const u_char **bp, return hdrlen + caplen; } + short_length = GET_U_1(sectag->short_length) & MACSEC_SL_MASK; if (ndo->ndo_eflag) { ND_PRINT("an %u, pn %u, flags %s", GET_U_1(sectag->tci_an) & MACSEC_AN_MASK, @@ -145,8 +147,8 @@ int macsec_print(netdissect_options *ndo, const u_char **bp, bittok2str_nosep(macsec_flag_values, "none", GET_U_1(sectag->tci_an) & MACSEC_TCI_FLAGS)); - if ((GET_U_1(sectag->short_length) & MACSEC_SL_MASK) != 0) - ND_PRINT(", sl %u", GET_U_1(sectag->short_length) & MACSEC_SL_MASK); + if (short_length != 0) + ND_PRINT(", sl %u", short_length); if (GET_U_1(sectag->tci_an) & MACSEC_TCI_SC) ND_PRINT(", sci " SCI_FMT, GET_BE_U_8(sectag->secure_channel_id)); @@ -169,17 +171,52 @@ int macsec_print(netdissect_options *ndo, const u_char **bp, */ ndo->ndo_protocol = save_protocol; return 0; - } else { + } + + /* + * The payload isn't encrypted; remove the + * ICV length from the lengths, so our caller + * doesn't treat it as payload. + */ + if (*lengthp < MACSEC_DEFAULT_ICV_LEN) { + nd_print_trunc(ndo); + ndo->ndo_protocol = save_protocol; + return hdrlen + caplen; + } + if (*caplenp < MACSEC_DEFAULT_ICV_LEN) { + nd_print_trunc(ndo); + ndo->ndo_protocol = save_protocol; + return hdrlen + caplen; + } + *lengthp -= MACSEC_DEFAULT_ICV_LEN; + *caplenp -= MACSEC_DEFAULT_ICV_LEN; + + /* + * If the SL field is non-zero, then it's the length of the + * Secure Data; otherwise, the Secure Data is what's left + * ver after the MACsec header and ICV are removed. + */ + if (short_length != 0) { /* - * The payload isn't encrypted; remove the - * ICV length from the lengths, so our caller - * doesn't treat it as payload. + * If the short length is more than we *have*, + * that's an error. */ - if (*lengthp >= MACSEC_DEFAULT_ICV_LEN) - *lengthp -= MACSEC_DEFAULT_ICV_LEN; - if (*caplenp >= MACSEC_DEFAULT_ICV_LEN) - *caplenp -= MACSEC_DEFAULT_ICV_LEN; - ndo->ndo_protocol = save_protocol; - return -1; + if (short_length > *lengthp) { + nd_print_trunc(ndo); + ndo->ndo_protocol = save_protocol; + return hdrlen + caplen; + } + if (short_length > *caplenp) { + nd_print_trunc(ndo); + ndo->ndo_protocol = save_protocol; + return hdrlen + caplen; + } + if (*lengthp > short_length) + *lengthp = short_length; + if (*caplenp > short_length) + *caplenp = short_length; } + + ndo->ndo_protocol = save_protocol; + return -1; } |