public void readAttribute(byte[] data, int offset, int length)
			throws RadiusException {
		// check length
		if (length < 6)
			throw new RadiusException("Vendor-Specific attribute too short: "
					+ length);

		int vsaCode = data[offset];
		int vsaLen = ((int) data[offset + 1] & 0x000000ff) - 6;

		if (vsaCode != VENDOR_SPECIFIC)
			throw new RadiusException("not a Vendor-Specific attribute");

		// read vendor ID and vendor data
		/*
		 * int vendorId = (data[offset + 2] << 24 | data[offset + 3] << 16 |
		 * data[offset + 4] << 8 | ((int)data[offset + 5] & 0x000000ff));
		 */
		int vendorId = (unsignedByteToInt(data[offset + 2]) << 24
				| unsignedByteToInt(data[offset + 3]) << 16
				| unsignedByteToInt(data[offset + 4]) << 8 | unsignedByteToInt(data[offset + 5]));
		setChildVendorId(vendorId);

		// validate sub-attribute structure
		int pos = 0;
		int count = 0;
		while (pos < vsaLen) {
			if (pos + 1 >= vsaLen)
				throw new RadiusException("Vendor-Specific attribute malformed");
            int vsaSubType = data[(offset + 6) + pos ] & 0x0ff;
            int vsaSubLen = data[(offset + 6) + pos + 1] & 0x0ff;
            if (vsaSubLen == 0)
                throw new RadiusException("Vendor-Specific "+vendorId+" attribute malformed sublen=0, subtype="+vsaSubType 
                        + " data="+RadiusUtil.escape(data,offset,length));
			pos += vsaSubLen;
			count++;
		}
		if (pos != vsaLen)
			throw new RadiusException("Vendor-Specific "+vendorId+" attribute malformed pos="+pos+"!=vsaLen="+vsaLen + " data="+RadiusUtil.escape(data,offset,length));

		subAttributes = new ArrayList(count);
		pos = 0;
		while (pos < vsaLen) {
            int vsaSubType = data[(offset + 6) + pos] & 0x0ff;
            int vsaSubLen = (data[(offset + 6) + pos + 1] & 0x0ff);
			RadiusAttribute a = createRadiusAttribute(getDictionary(),
					vendorId, vsaSubType);
			try {
			    a.readAttribute(data, (offset + 6) + pos, vsaSubLen);
			} catch (RadiusException e ) {
	            throw new RadiusException("Vendor-Specific "+vendorId+" attribute malformed pos="+pos
	                    +" data="+RadiusUtil.escape(data,offset,length)+" ("+e.getMessage()+")");
			}
			subAttributes.add(a);
			pos += vsaSubLen;
		}
	}