]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Various fixes.
authorGuy Harris <[email protected]>
Thu, 9 Jan 2014 00:59:07 +0000 (16:59 -0800)
committerGuy Harris <[email protected]>
Thu, 9 Jan 2014 00:59:07 +0000 (16:59 -0800)
Get rid of zero-length arrays; not all compilers support them.

Get rid of __attribute__((packed)); not all compilers support it, so we
can't depend on it.

Use explicit constants for sizes, just in case some compilers pad
structures.

Add some length checks.

Make some ND_TTEST2 calls ND_TCHECK2 calls instead, so they report
truncation if they fail.

Constify some pointers.

print-icmp6.c
rpl.h

index 819ebf5907afaecab9bbe78f262acf7027365412..83af36654e8e81935bf2ab0516d259abdaa67043 100644 (file)
@@ -481,7 +481,7 @@ static void icmp6_opt_print(netdissect_options *ndo, const u_char *, int);
 static void mld6_print(netdissect_options *ndo, const u_char *);
 static void mldv2_report_print(netdissect_options *ndo, const u_char *, u_int);
 static void mldv2_query_print(netdissect_options *ndo, const u_char *, u_int);
-static struct udphdr *get_upperlayer(netdissect_options *ndo, u_char *, u_int *);
+static const struct udphdr *get_upperlayer(netdissect_options *ndo, const u_char *, u_int *);
 static void dnsname_print(netdissect_options *ndo, const u_char *, const u_char *);
 static void icmp6_nodeinfo_print(netdissect_options *ndo, u_int, const u_char *, const u_char *);
 static void icmp6_rrenum_print(netdissect_options *ndo, const u_char *, const u_char *);
@@ -651,7 +651,7 @@ const struct tok rpl_subopt_values[] = {
 };
 
 static void
-rpl_format_dagid(char dagid_str[65], u_char *dagid)
+rpl_format_dagid(char dagid_str[65], const u_char *dagid)
 {
         char *d = dagid_str;
         int  i;
@@ -669,11 +669,11 @@ rpl_format_dagid(char dagid_str[65], u_char *dagid)
 
 static void
 rpl_dio_printopt(netdissect_options *ndo,
-                 struct rpl_dio_genoption *opt,
+                 const struct rpl_dio_genoption *opt,
                  u_int length)
 {
-        if(length == 0) return;
-        length -= sizeof(struct rpl_dio_genoption);
+        if(length < RPL_DIO_GENOPTION_LEN) return;
+        length -= RPL_DIO_GENOPTION_LEN;
 
         ND_TCHECK(opt->rpl_dio_len);
 
@@ -694,7 +694,7 @@ rpl_dio_printopt(netdissect_options *ndo,
                                 if(paylen > length) paylen = length;
                                 hex_print(ndo,
                                           " ",
-                                          opt->rpl_dio_data,  /* content of DIO option */
+                                          ((u_int8_t *)opt) + RPL_DIO_GENOPTION_LEN,  /* content of DIO option */
                                           paylen);
                         }
                 }
@@ -711,7 +711,7 @@ static void
 rpl_dio_print(netdissect_options *ndo,
               const u_char *bp, u_int length)
 {
-        struct nd_rpl_dio *dio = (struct nd_rpl_dio *)bp;
+        const struct nd_rpl_dio *dio = (struct nd_rpl_dio *)bp;
         char dagid_str[65];
 
         ND_TCHECK(*dio);
@@ -740,19 +740,23 @@ static void
 rpl_dao_print(netdissect_options *ndo,
               const u_char *bp, u_int length)
 {
-        struct nd_rpl_dao *dao = (struct nd_rpl_dao *)bp;
-        u_char *dao_end = (u_char *)&dao[1];
+        const struct nd_rpl_dao *dao = (struct nd_rpl_dao *)bp;
         char dagid_str[65];
 
         ND_TCHECK(*dao);
+        if (length < ND_RPL_DAO_MIN_LEN)
+               goto tooshort;
 
         strcpy(dagid_str,"<elided>");
-        length -= sizeof(struct nd_rpl_dao);
+        bp += ND_RPL_DAO_MIN_LEN;
+        length -= ND_RPL_DAO_MIN_LEN;
         if(RPL_DAO_D(dao->rpl_flags)) {
-                ND_TTEST2(dao->rpl_dagid, 16);
+                ND_TCHECK2(dao->rpl_dagid, DAGID_LEN);
+                if (length < DAGID_LEN)
+                       goto tooshort;
                 rpl_format_dagid(dagid_str, dao->rpl_dagid);
-                dao_end += DAGID_LEN;
-                length  -= DAGID_LEN;
+                bp += DAGID_LEN;
+                length -= DAGID_LEN;
         }
 
         ND_PRINT((ndo, " [dagid:%s,seq:%u,instance:%u]",
@@ -761,7 +765,7 @@ rpl_dao_print(netdissect_options *ndo,
                   dao->rpl_instanceid));
 
         if(ndo->ndo_vflag > 1) {
-                struct rpl_dio_genoption *opt = (struct rpl_dio_genoption *)dao_end;
+                const struct rpl_dio_genoption *opt = (struct rpl_dio_genoption *)bp;
                 rpl_dio_printopt(ndo, opt, length);
         }
        return;
@@ -769,25 +773,33 @@ rpl_dao_print(netdissect_options *ndo,
 trunc:
        ND_PRINT((ndo," [|truncated]"));
        return;
+
+tooshort:
+       ND_PRINT((ndo," [|length too short]"));
+       return;
 }
 
 static void
 rpl_daoack_print(netdissect_options *ndo,
                  const u_char *bp, u_int length)
 {
-        struct nd_rpl_daoack *daoack = (struct nd_rpl_daoack *)bp;
-        u_char *daoack_end = (u_char *)&daoack[1];
+        const struct nd_rpl_daoack *daoack = (struct nd_rpl_daoack *)bp;
         char dagid_str[65];
 
-        ND_TCHECK(*daoack);
+        ND_TCHECK2(*daoack, ND_RPL_DAOACK_MIN_LEN);
+        if (length < ND_RPL_DAOACK_MIN_LEN)
+               goto tooshort;
 
         strcpy(dagid_str,"<elided>");
-        length -= sizeof(struct nd_rpl_daoack);
+        bp += ND_RPL_DAOACK_MIN_LEN;
+        length -= ND_RPL_DAOACK_MIN_LEN;
         if(RPL_DAOACK_D(daoack->rpl_flags)) {
-                ND_TTEST2(daoack->rpl_dagid, 16);
+                ND_TCHECK2(daoack->rpl_dagid, 16);
+                if (length < DAGID_LEN)
+                       goto tooshort;
                 rpl_format_dagid(dagid_str, daoack->rpl_dagid);
-                daoack_end += DAGID_LEN;
-                length     -= DAGID_LEN;
+                bp += DAGID_LEN;
+                length -= DAGID_LEN;
         }
 
         ND_PRINT((ndo, " [dagid:%s,seq:%u,instance:%u,status:%u]",
@@ -798,7 +810,7 @@ rpl_daoack_print(netdissect_options *ndo,
 
         /* no officially defined options for DAOACK, but print any we find */
         if(ndo->ndo_vflag > 1) {
-                struct rpl_dio_genoption *opt = (struct rpl_dio_genoption *)daoack_end;
+                const struct rpl_dio_genoption *opt = (struct rpl_dio_genoption *)bp;
                 rpl_dio_printopt(ndo, opt, length);
         }
        return;
@@ -806,6 +818,10 @@ rpl_daoack_print(netdissect_options *ndo,
 trunc:
        ND_PRINT((ndo," [|dao-truncated]"));
        return;
+
+tooshort:
+       ND_PRINT((ndo," [|dao-length too short]"));
+       return;
 }
 
 static void
@@ -1159,15 +1175,15 @@ trunc:
        ND_PRINT((ndo, "[|icmp6]"));
 }
 
-static struct udphdr *
-get_upperlayer(netdissect_options *ndo, u_char *bp, u_int *prot)
+static const struct udphdr *
+get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot)
 {
        const u_char *ep;
-       struct ip6_hdr *ip6 = (struct ip6_hdr *)bp;
-       struct udphdr *uh;
-       struct ip6_hbh *hbh;
-       struct ip6_frag *fragh;
-       struct ah *ah;
+       const struct ip6_hdr *ip6 = (struct ip6_hdr *)bp;
+       const struct udphdr *uh;
+       const struct ip6_hbh *hbh;
+       const struct ip6_frag *fragh;
+       const struct ah *ah;
        u_int nh;
        int hlen;
 
@@ -1388,7 +1404,7 @@ icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
 static void
 mld6_print(netdissect_options *ndo, const u_char *bp)
 {
-       struct mld6_hdr *mp = (struct mld6_hdr *)bp;
+       const struct mld6_hdr *mp = (struct mld6_hdr *)bp;
        const u_char *ep;
 
        /* 'ep' points to the end of available data. */
@@ -1564,8 +1580,8 @@ dnsname_print(netdissect_options *ndo, const u_char *cp, const u_char *ep)
 static void
 icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp, const u_char *ep)
 {
-       struct icmp6_nodeinfo *ni6;
-       struct icmp6_hdr *dp;
+       const struct icmp6_nodeinfo *ni6;
+       const struct icmp6_hdr *dp;
        const u_char *cp;
        size_t siz, i;
        int needcomma;
@@ -1813,7 +1829,7 @@ trunc:
 static void
 icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep)
 {
-       struct icmp6_router_renum *rr6;
+       const struct icmp6_router_renum *rr6;
        const char *cp;
        struct rr_pco_match *match;
        struct rr_pco_use *use;
diff --git a/rpl.h b/rpl.h
index 764e9a8152a23497e32305ba6c0e0e9a37f27877..30a24f135bac0297dae9cddcecad6e18d230e891 100644 (file)
--- a/rpl.h
+++ b/rpl.h
@@ -45,15 +45,19 @@ struct nd_rpl_security {
     u_int16_t rpl_sec_kim_lvl_flags;  /* bit 15/14, KIM */
                                       /* bit 10-8, LVL, bit 7-0 flags */
     u_int32_t rpl_sec_counter;
+#if 0
     u_int8_t  rpl_sec_ki[0];          /* depends upon kim */
-} PACKED;
+#endif
+};
 
 /* section 6.2.1, DODAG Information Solication (DIS_IS) */
 struct nd_rpl_dis_is {
     u_int8_t rpl_dis_flags;
     u_int8_t rpl_dis_reserved;
+#if 0
     u_int8_t rpl_dis_options[0];
-} PACKED;
+#endif
+};
 
 /* section 6.3.1, DODAG Information Object (DIO) */
 struct nd_rpl_dio {
@@ -65,7 +69,7 @@ struct nd_rpl_dio {
     u_int8_t  rpl_flags;    /* no flags defined yet */
     u_int8_t  rpl_resv1;
     u_int8_t  rpl_dagid[DAGID_LEN];
-} PACKED;
+};
 #define RPL_DIO_GROUND_FLAG 0x80
 #define RPL_DIO_MOP_SHIFT   3
 #define RPL_DIO_MOP_MASK    (7 << RPL_DIO_MOP_SHIFT)
@@ -97,8 +101,8 @@ enum RPL_SUBOPT {
 struct rpl_dio_genoption {
     u_int8_t rpl_dio_type;
     u_int8_t rpl_dio_len;        /* suboption length, not including type/len */
-    u_int8_t rpl_dio_data[0];
-} PACKED;
+};
+#define RPL_DIO_GENOPTION_LEN  2
 
 #define RPL_DIO_LIFETIME_INFINITE   0xffffffff
 #define RPL_DIO_LIFETIME_DISCONNECT 0
@@ -109,8 +113,10 @@ struct rpl_dio_destprefix {
     u_int8_t rpl_dio_prefixlen;        /* in bits */
     u_int8_t rpl_dio_prf;              /* flags, including Route Preference */
     u_int32_t rpl_dio_prefixlifetime;  /* in seconds */
-    u_int8_t rpl_dio_prefix[0];        /* variables number of bytes */
-} PACKED;
+#if 0
+    u_int8_t rpl_dio_prefix[0];        /* variable number of bytes */
+#endif
+};
 
 /* section 6.4.1, DODAG Information Object (DIO) */
 struct nd_rpl_dao {
@@ -118,8 +124,9 @@ struct nd_rpl_dao {
     u_int8_t  rpl_flags;      /* bit 7=K, 6=D */
     u_int8_t  rpl_resv;
     u_int8_t  rpl_daoseq;
-    u_int8_t  rpl_dagid[0];   /* [DAGID_LEN] present when D set. */
-} PACKED;
+    u_int8_t  rpl_dagid[DAGID_LEN];   /* present when D set. */
+};
+#define ND_RPL_DAO_MIN_LEN     4       /* length without DAGID */
 
 /* indicates if this DAO is to be acK'ed */
 #define RPL_DAO_K_SHIFT   7
@@ -136,8 +143,10 @@ struct rpl_dao_target {
     u_int8_t rpl_dao_len;
     u_int8_t rpl_dao_flags;            /* unused */
     u_int8_t rpl_dao_prefixlen;        /* in bits */
-    u_int8_t rpl_dao_prefix[0];        /* variables number of bytes */
-} PACKED;
+#if 0
+    u_int8_t rpl_dao_prefix[0];        /* variable number of bytes */
+#endif
+};
 
 /* section 6.5.1, Destination Advertisement Object Acknowledgement (DAO-ACK) */
 struct nd_rpl_daoack {
@@ -145,8 +154,9 @@ struct nd_rpl_daoack {
     u_int8_t  rpl_flags;      /* bit 7=D */
     u_int8_t  rpl_daoseq;
     u_int8_t  rpl_status;
-    u_int8_t  rpl_dagid[0];   /* [DAGID_LEN] present when D set. */
-} PACKED;
+    u_int8_t  rpl_dagid[DAGID_LEN];   /* present when D set. */
+};
+#define ND_RPL_DAOACK_MIN_LEN  4       /* length without DAGID */
 /* indicates if the DAGID is present */
 #define RPL_DAOACK_D_SHIFT   7
 #define RPL_DAOACK_D_MASK    (1 << RPL_DAOACK_D_SHIFT)