X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/ed85e20e4d6a27d5405f37366dd34b64c10a9211..de0c7fc746c37eb83e15a6890d30dc6f608e9d76:/print-ripng.c diff --git a/print-ripng.c b/print-ripng.c index 99694c33..19398931 100644 --- a/print-ripng.c +++ b/print-ripng.c @@ -19,16 +19,15 @@ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define NETDISSECT_REWORKED +/* \summary: IPv6 Routing Information Protocol (RIPng) printer */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif -#ifdef INET6 - -#include +#include -#include "interface.h" +#include "netdissect.h" #include "addrtoname.h" #include "extract.h" @@ -68,14 +67,14 @@ struct netinfo6 { struct in6_addr rip6_dest; uint16_t rip6_tag; - uint8_t rip6_plen; - uint8_t rip6_metric; + uint8_t rip6_plen; + uint8_t rip6_metric; }; struct rip6 { - uint8_t rip6_cmd; - uint8_t rip6_vers; - uint8_t rip6_res1[2]; + uint8_t rip6_cmd; + uint8_t rip6_vers; + uint8_t rip6_res1[2]; union { struct netinfo6 ru6_nets[1]; char ru6_tracefile[1]; @@ -100,7 +99,7 @@ rip6_entry_print(netdissect_options *ndo, register const struct netinfo6 *ni, in int l; l = ND_PRINT((ndo, "%s/%d", ip6addr_string(ndo, &ni->rip6_dest), ni->rip6_plen)); if (ni->rip6_tag) - l += ND_PRINT((ndo, " [%d]", EXTRACT_16BITS(&ni->rip6_tag))); + l += ND_PRINT((ndo, " [%d]", EXTRACT_BE_U_2(&ni->rip6_tag))); if (metric) l += ND_PRINT((ndo, " (%d)", ni->rip6_metric)); return l; @@ -109,68 +108,76 @@ rip6_entry_print(netdissect_options *ndo, register const struct netinfo6 *ni, in void ripng_print(netdissect_options *ndo, const u_char *dat, unsigned int length) { - register const struct rip6 *rp = (struct rip6 *)dat; + register const struct rip6 *rp = (const struct rip6 *)dat; register const struct netinfo6 *ni; - register u_int amt; - register u_int i; - int j; - int trunc; - - if (ndo->ndo_snapend < dat) - return; - amt = ndo->ndo_snapend - dat; - i = min(length, amt); - if (i < (sizeof(struct rip6) - sizeof(struct netinfo6))) - return; - i -= (sizeof(struct rip6) - sizeof(struct netinfo6)); + unsigned int length_left; + u_int j; + ND_TCHECK(rp->rip6_cmd); switch (rp->rip6_cmd) { case RIP6_REQUEST: - j = length / sizeof(*ni); - if (j == 1 - && rp->rip6_nets->rip6_metric == HOPCNT_INFINITY6 - && IN6_IS_ADDR_UNSPECIFIED(&rp->rip6_nets->rip6_dest)) { - ND_PRINT((ndo, " ripng-req dump")); - break; + length_left = length; + if (length_left < (sizeof(struct rip6) - sizeof(struct netinfo6))) + goto trunc; + length_left -= (sizeof(struct rip6) - sizeof(struct netinfo6)); + j = length_left / sizeof(*ni); + if (j == 1) { + ND_TCHECK(rp->rip6_nets); + if (rp->rip6_nets->rip6_metric == HOPCNT_INFINITY6 + && IN6_IS_ADDR_UNSPECIFIED(&rp->rip6_nets->rip6_dest)) { + ND_PRINT((ndo, " ripng-req dump")); + break; + } } - if (j * sizeof(*ni) != length - 4) - ND_PRINT((ndo, " ripng-req %d[%u]:", j, length)); + if (j * sizeof(*ni) != length_left) + ND_PRINT((ndo, " ripng-req %u[%u]:", j, length)); else - ND_PRINT((ndo, " ripng-req %d:", j)); - trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i); - for (ni = rp->rip6_nets; i >= sizeof(*ni); - i -= sizeof(*ni), ++ni) { + ND_PRINT((ndo, " ripng-req %u:", j)); + for (ni = rp->rip6_nets; length_left >= sizeof(*ni); + length_left -= sizeof(*ni), ++ni) { + ND_TCHECK(*ni); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n\t")); else ND_PRINT((ndo, " ")); rip6_entry_print(ndo, ni, 0); } + if (length_left != 0) + goto trunc; break; case RIP6_RESPONSE: - j = length / sizeof(*ni); - if (j * sizeof(*ni) != length - 4) + length_left = length; + if (length_left < (sizeof(struct rip6) - sizeof(struct netinfo6))) + goto trunc; + length_left -= (sizeof(struct rip6) - sizeof(struct netinfo6)); + j = length_left / sizeof(*ni); + if (j * sizeof(*ni) != length_left) ND_PRINT((ndo, " ripng-resp %d[%u]:", j, length)); else ND_PRINT((ndo, " ripng-resp %d:", j)); - trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i); - for (ni = rp->rip6_nets; i >= sizeof(*ni); - i -= sizeof(*ni), ++ni) { + for (ni = rp->rip6_nets; length_left >= sizeof(*ni); + length_left -= sizeof(*ni), ++ni) { + ND_TCHECK(*ni); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n\t")); else ND_PRINT((ndo, " ")); rip6_entry_print(ndo, ni, ni->rip6_metric); } - if (trunc) - ND_PRINT((ndo, "[|ripng]")); + if (length_left != 0) + goto trunc; break; default: ND_PRINT((ndo, " ripng-%d ?? %u", rp->rip6_cmd, length)); break; } + ND_TCHECK(rp->rip6_vers); if (rp->rip6_vers != RIP6_VERSION) ND_PRINT((ndo, " [vers %d]", rp->rip6_vers)); + return; + +trunc: + ND_PRINT((ndo, "[|ripng]")); + return; } -#endif /* INET6 */