static int calipso_opt_getattr(const unsigned char *calipso,
			       struct netlbl_lsm_secattr *secattr)
{
	int ret_val = -ENOMSG;
	u32 doi, len = calipso[1], cat_len = calipso[6] * 4;
	struct calipso_doi *doi_def;

	if (cat_len + 8 > len)
		return -EINVAL;

	if (calipso_cache_check(calipso + 2, calipso[1], secattr) == 0)
		return 0;

	doi = get_unaligned_be32(calipso + 2);
	rcu_read_lock();
	doi_def = calipso_doi_search(doi);
	if (!doi_def)
		goto getattr_return;

	secattr->attr.mls.lvl = calipso[7];
	secattr->flags |= NETLBL_SECATTR_MLS_LVL;

	if (cat_len) {
		ret_val = calipso_map_cat_ntoh(doi_def,
					       calipso + 10,
					       cat_len,
					       secattr);
		if (ret_val != 0) {
			netlbl_catmap_free(secattr->attr.mls.cat);
			goto getattr_return;
		}

		if (secattr->attr.mls.cat)
			secattr->flags |= NETLBL_SECATTR_MLS_CAT;
	}

	secattr->type = NETLBL_NLTYPE_CALIPSO;

getattr_return:
	rcu_read_unlock();
	return ret_val;
}
static int calipso_opt_getattr(const unsigned char *calipso,
			       struct netlbl_lsm_secattr *secattr)
{
	int ret_val = -ENOMSG;
	u32 doi, len = calipso[1], cat_len = calipso[6] * 4;
	struct calipso_doi *doi_def;

	if (cat_len + 8 > len)
		return -EINVAL;

	if (calipso_cache_check(calipso + 2, calipso[1], secattr) == 0)
		return 0;

	doi = get_unaligned_be32(calipso + 2);
	rcu_read_lock();
	doi_def = calipso_doi_search(doi);
	if (!doi_def)
		goto getattr_return;

	secattr->attr.mls.lvl = calipso[7];
	secattr->flags |= NETLBL_SECATTR_MLS_LVL;

	if (cat_len) {
		ret_val = calipso_map_cat_ntoh(doi_def,
					       calipso + 10,
					       cat_len,
					       secattr);
		if (ret_val != 0) {
			netlbl_catmap_free(secattr->attr.mls.cat);
			goto getattr_return;
		}

		if (secattr->attr.mls.cat)
			secattr->flags |= NETLBL_SECATTR_MLS_CAT;
	}

	secattr->type = NETLBL_NLTYPE_CALIPSO;

getattr_return:
	rcu_read_unlock();
	return ret_val;
}