@Override
 protected int calcLength() {
   int len = 0;
   for (IpV6NeighborDiscoveryOption o : options) {
     len += o.length();
   }
   return len + OPTIONS_OFFSET;
 }
    private IcmpV6NeighborAdvertisementHeader(byte[] rawData, int offset, int length)
        throws IllegalRawDataException {
      if (length < OPTIONS_OFFSET) {
        StringBuilder sb = new StringBuilder(120);
        sb.append("The raw data must be more than ")
            .append(OPTIONS_OFFSET - 1)
            .append("bytes")
            .append(" to build this header. raw data: ")
            .append(ByteArrays.toHexString(rawData, " "))
            .append(", offset: ")
            .append(offset)
            .append(", length: ")
            .append(length);
        throw new IllegalRawDataException(sb.toString());
      }

      int tmp = ByteArrays.getInt(rawData, R_S_O_RESERVED_OFFSET + offset);
      this.routerFlag = (tmp & 0x80000000) != 0;
      this.solicitedFlag = (tmp & 0x40000000) != 0;
      this.overrideFlag = (tmp & 0x20000000) != 0;
      this.reserved = 0x1FFFFFFF & tmp;
      this.targetAddress = ByteArrays.getInet6Address(rawData, TARGET_ADDRESS_OFFSET + offset);
      this.options = new ArrayList<IpV6NeighborDiscoveryOption>();
      int currentOffsetInHeader = OPTIONS_OFFSET;
      while (currentOffsetInHeader < length) {
        IpV6NeighborDiscoveryOptionType type =
            IpV6NeighborDiscoveryOptionType.getInstance(rawData[currentOffsetInHeader + offset]);
        IpV6NeighborDiscoveryOption newOne;
        try {
          newOne =
              PacketFactories.getFactory(
                      IpV6NeighborDiscoveryOption.class, IpV6NeighborDiscoveryOptionType.class)
                  .newInstance(
                      rawData,
                      currentOffsetInHeader + offset,
                      length - currentOffsetInHeader,
                      type);
        } catch (Exception e) {
          break;
        }

        options.add(newOne);
        currentOffsetInHeader += newOne.length();
      }
    }
 @Override
 protected List<byte[]> getRawFields() {
   List<byte[]> rawFields = new ArrayList<byte[]>();
   int tmp = 0x1FFFFFFF & reserved;
   if (routerFlag) {
     tmp |= 0x80000000;
   }
   if (solicitedFlag) {
     tmp |= 0x40000000;
   }
   if (overrideFlag) {
     tmp |= 0x20000000;
   }
   rawFields.add(ByteArrays.toByteArray(tmp));
   rawFields.add(ByteArrays.toByteArray(targetAddress));
   for (IpV6NeighborDiscoveryOption o : options) {
     rawFields.add(o.getRawData());
   }
   return rawFields;
 }