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 *);
};
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;
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);
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);
}
}
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);
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]",
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;
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]",
/* 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;
trunc:
ND_PRINT((ndo," [|dao-truncated]"));
return;
+
+tooshort:
+ ND_PRINT((ndo," [|dao-length too short]"));
+ return;
}
static void
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;
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. */
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;
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;
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 {
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)
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
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 {
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
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 {
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)