- struct nd_rpl_option *opt = (struct nd_rpl_option *)&dio[1];
- length -= sizeof(struct nd_rpl_dio);
- char optname_buf[64];
- ND_TCHECK(opt->rpl_dio_len);
- while((opt->rpl_dio_type == RPL_OPT_PAD0 &&
- (u_char *)opt < ndo->ndo_snapend) ||
- ND_TTEST2(*opt,(opt->rpl_dio_len+2))) {
- unsigned int len = opt->rpl_dio_len+2;
- if(opt->rpl_dio_type == RPL_OPT_PAD0) {
- len = 1;
- ND_PRINT((ndo, " opt:pad0"));
- } else {
- ND_PRINT((ndo, " opt:%s len:%u ",
- rpl_subopt_name(opt->rpl_dio_type, optname_buf, sizeof(optname_buf)),
- len));
- if(ndo->ndo_vflag > 2) {
- int len = opt->rpl_dio_len;
- if(len > length) len = length;
- hex_print(ndo,
- " ",
- (char *)&opt[1], /* content of DIO option */
- len);
- }
- }
- opt = (struct nd_rpl_option *)(((char *)opt) + len);
- length -= len;
- }
+ const struct rpl_dio_genoption *opt = (const struct rpl_dio_genoption *)&dio[1];
+ rpl_dio_printopt(ndo, opt, length);
+ }
+ return;
+trunc:
+ ND_PRINT((ndo, "%s", rpl_tstr));
+ return;
+}
+
+static void
+rpl_dao_print(netdissect_options *ndo,
+ const u_char *bp, u_int length)
+{
+ const struct nd_rpl_dao *dao = (const struct nd_rpl_dao *)bp;
+ const char *dagid_str = "<elided>";
+
+ ND_TCHECK(*dao);
+ if (length < ND_RPL_DAO_MIN_LEN)
+ goto tooshort;
+
+ bp += ND_RPL_DAO_MIN_LEN;
+ length -= ND_RPL_DAO_MIN_LEN;
+ if(RPL_DAO_D(dao->rpl_flags)) {
+ ND_TCHECK2(dao->rpl_dagid, DAGID_LEN);
+ if (length < DAGID_LEN)
+ goto tooshort;
+ dagid_str = ip6addr_string (ndo, dao->rpl_dagid);
+ bp += DAGID_LEN;
+ length -= DAGID_LEN;
+ }
+
+ ND_PRINT((ndo, " [dagid:%s,seq:%u,instance:%u%s%s,%02x]",
+ dagid_str,
+ dao->rpl_daoseq,
+ dao->rpl_instanceid,
+ RPL_DAO_K(dao->rpl_flags) ? ",acK":"",
+ RPL_DAO_D(dao->rpl_flags) ? ",Dagid":"",
+ dao->rpl_flags));
+
+ if(ndo->ndo_vflag > 1) {
+ const struct rpl_dio_genoption *opt = (const struct rpl_dio_genoption *)bp;
+ rpl_dio_printopt(ndo, opt, length);
+ }
+ return;
+
+trunc:
+ ND_PRINT((ndo, "%s", rpl_tstr));
+ return;
+
+tooshort:
+ ND_PRINT((ndo," [|length too short]"));
+ return;
+}
+
+static void
+rpl_daoack_print(netdissect_options *ndo,
+ const u_char *bp, u_int length)
+{
+ const struct nd_rpl_daoack *daoack = (const struct nd_rpl_daoack *)bp;
+ const char *dagid_str = "<elided>";
+
+ ND_TCHECK2(*daoack, ND_RPL_DAOACK_MIN_LEN);
+ if (length < ND_RPL_DAOACK_MIN_LEN)
+ goto tooshort;
+
+ bp += ND_RPL_DAOACK_MIN_LEN;
+ length -= ND_RPL_DAOACK_MIN_LEN;
+ if(RPL_DAOACK_D(daoack->rpl_flags)) {
+ ND_TCHECK2(daoack->rpl_dagid, DAGID_LEN);
+ if (length < DAGID_LEN)
+ goto tooshort;
+ dagid_str = ip6addr_string (ndo, daoack->rpl_dagid);
+ bp += DAGID_LEN;
+ length -= DAGID_LEN;
+ }
+
+ ND_PRINT((ndo, " [dagid:%s,seq:%u,instance:%u,status:%u]",
+ dagid_str,
+ daoack->rpl_daoseq,
+ daoack->rpl_instanceid,
+ daoack->rpl_status));
+
+ /* no officially defined options for DAOACK, but print any we find */
+ if(ndo->ndo_vflag > 1) {
+ const struct rpl_dio_genoption *opt = (const struct rpl_dio_genoption *)bp;
+ rpl_dio_printopt(ndo, opt, length);