예제 #1
0
파일: ipsec_mast.c 프로젝트: OPSF/uClinux
/*
 * Verify that the skb can go out on this ipsp.
 * Return 0 if OK, error code otherwise.
 */
static int
ipsec_mast_check_outbound_policy(struct ipsec_xmit_state *ixs)
{
	int failed_outbound_check = 0;
	struct ipsec_sa *ipsp = ixs->ipsp;

	if (!ixs || !ixs->ipsp || !ixs->iph)
		return -EFAULT;

	/* Note: "xor" (^) logically replaces "not equal"
	 * (!=) and "bitwise or" (|) logically replaces
	 * "boolean or" (||).  This is done to speed up
	 * execution by doing only bitwise operations and
	 * no branch operations */
	if (osw_ip_hdr_version(ixs) == 4) {
		struct iphdr *ipp = osw_ip4_hdr(ixs);
		if (ip_address_family(&ipsp->ips_said.dst) != AF_INET) {
			failed_outbound_check = 1;
		} else if (((ipp->saddr & ipsp->ips_mask_s.u.v4.sin_addr.s_addr)
				^ ipsp->ips_flow_s.u.v4.sin_addr.s_addr)
				| ((ipp->daddr & ipsp->ips_mask_d.u.v4.sin_addr.s_addr)
				^ ipsp->ips_flow_d.u.v4.sin_addr.s_addr)) {
			failed_outbound_check = 1;
		}
	} else if (osw_ip_hdr_version(ixs) == 6) {
		struct ipv6hdr *ipp6 = osw_ip6_hdr(ixs);
		if (ip_address_family(&ipsp->ips_said.dst) != AF_INET6) {
			failed_outbound_check = 1;
		} else if (((ipp6->saddr.s6_addr32[0] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[0])
				^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[0])
				| ((ipp6->daddr.s6_addr32[0] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[0])
				^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[0])) {
			failed_outbound_check = 1;
		} else if (((ipp6->saddr.s6_addr32[1] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[1])
				^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[1])
				| ((ipp6->daddr.s6_addr32[1] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[1])
				^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[1])) {
			failed_outbound_check = 1;
		} else if (((ipp6->saddr.s6_addr32[2] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[2])
				^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[2])
				| ((ipp6->daddr.s6_addr32[2] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[2])
				^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[2])) {
			failed_outbound_check = 1;
		} else if (((ipp6->saddr.s6_addr32[3] & ipsp->ips_mask_s.u.v6.sin6_addr.s6_addr32[3])
				^ ipsp->ips_flow_s.u.v6.sin6_addr.s6_addr32[3])
				| ((ipp6->daddr.s6_addr32[3] & ipsp->ips_mask_d.u.v6.sin6_addr.s6_addr32[3])
				^ ipsp->ips_flow_d.u.v6.sin6_addr.s6_addr32[3])) {
			failed_outbound_check = 1;
		}
	}
	if (failed_outbound_check) {
		char saddr_txt[ADDRTOA_BUF], daddr_txt[ADDRTOA_BUF];
		char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF];

		if (ipsp->ips_flow_s.u.v4.sin_family == AF_INET6) {
			subnet6toa(&ipsp->ips_flow_s.u.v6.sin6_addr,
					&ipsp->ips_mask_s.u.v6.sin6_addr,
					0, sflow_txt, sizeof(sflow_txt));
			subnet6toa(&ipsp->ips_flow_d.u.v6.sin6_addr,
					&ipsp->ips_mask_d.u.v6.sin6_addr,
					0, dflow_txt, sizeof(dflow_txt));
			inet_addrtot(AF_INET6, &osw_ip6_hdr(ixs)->saddr, 0, saddr_txt,
					sizeof(saddr_txt));
			inet_addrtot(AF_INET6, &osw_ip6_hdr(ixs)->daddr, 0, daddr_txt,
					sizeof(daddr_txt));
		} else {
			subnettoa(ipsp->ips_flow_s.u.v4.sin_addr,
					ipsp->ips_mask_s.u.v4.sin_addr,
					0, sflow_txt, sizeof(sflow_txt));
			subnettoa(ipsp->ips_flow_d.u.v4.sin_addr,
					ipsp->ips_mask_d.u.v4.sin_addr,
					0, dflow_txt, sizeof(dflow_txt));
			inet_addrtot(AF_INET, &osw_ip4_hdr(ixs)->saddr, 0, saddr_txt,
					sizeof(saddr_txt));
			inet_addrtot(AF_INET, &osw_ip4_hdr(ixs)->daddr, 0, daddr_txt,
					sizeof(daddr_txt));
		}

		if (!ixs->sa_len) ixs->sa_len = KLIPS_SATOT(debug_mast,
				&ixs->outgoing_said, 0,
				ixs->sa_txt, sizeof(ixs->sa_txt));

		KLIPS_PRINT(debug_mast,
			    "klips_debug:ipsec_mast_check_outbound_policy: "
			    "SA:%s, inner tunnel policy [%s -> %s] does not agree with pkt contents [%s -> %s].\n",
			    ixs->sa_len ? ixs->sa_txt : " (error)",
			    sflow_txt, dflow_txt, saddr_txt, daddr_txt);
		if(ixs->stats)
			ixs->stats->rx_dropped++;
		return -EACCES;
	}

#if 0
	{
		char sflow_txt[SUBNETTOA_BUF], dflow_txt[SUBNETTOA_BUF];
		char saddr_txt[ADDRTOA_BUF], daddr_txt[ADDRTOA_BUF];
		struct in_addr ipaddr;

		subnettoa(ixs->ipsp->ips_flow_s.u.v4.sin_addr,
			  ixs->ipsp->ips_mask_s.u.v4.sin_addr,
			  0, sflow_txt, sizeof(sflow_txt));
		subnettoa(ixs->ipsp->ips_flow_d.u.v4.sin_addr,
			  ixs->ipsp->ips_mask_d.u.v4.sin_addr,
			  0, dflow_txt, sizeof(dflow_txt));

		ipaddr.s_addr = ixs->iph->saddr;
		addrtoa(ipaddr, 0, saddr_txt, sizeof(saddr_txt));
		ipaddr.s_addr = ixs->iph->daddr;
		addrtoa(ipaddr, 0, daddr_txt, sizeof(daddr_txt));

		if (!ixs->sa_len) ixs->sa_len = KLIPS_SATOT(debug_mast,
				&ixs->outgoing_said, 0,
				ixs->sa_txt, sizeof(ixs->sa_txt));

		KLIPS_PRINT(debug_mast,
			    "klips_debug:ipsec_mast_check_outbound_policy: "
			    "SA:%s, inner tunnel policy [%s -> %s] agrees with pkt contents [%s -> %s].\n",
			    ixs->sa_len ? ixs->sa_txt : " (error)",
			    sflow_txt, dflow_txt, saddr_txt, daddr_txt);
	}
#endif

	return 0;
}
예제 #2
0
파일: ipsec_proc.c 프로젝트: dkg/libreswan
IPSEC_PROCFS_DEBUG_NO_STATIC
int ipsec_spi_format(struct ipsec_sa *sa_p, struct seq_file *seq)
{
	char sa[SATOT_BUF];
	char buf_s[SUBNETTOA_BUF];
	char buf_d[SUBNETTOA_BUF];
	size_t sa_len;

	ipsec_sa_get(sa_p, IPSEC_REFPROC);
	sa_len = satot(&sa_p->ips_said, 'x', sa, sizeof(sa));
	seq_printf(seq, "%s ", sa_len ? sa : " (error)");
	seq_printf(seq, "%s%s%s", IPS_XFORM_NAME(sa_p));
	seq_printf(seq, ": dir=%s", (sa_p->ips_flags & EMT_INBOUND) ? "in " : "out");

	if (sa_p->ips_addr_s) {
		sin_addrtot(sa_p->ips_addr_s, 0, buf_s, sizeof(buf_s));
		seq_printf(seq, " src=%s", buf_s);
	}

	if ((sa_p->ips_said.proto == IPPROTO_IPIP)
	   && (sa_p->ips_flags & (SADB_X_SAFLAGS_INFLOW
			   |SADB_X_SAFLAGS_POLICYONLY))) {
		if (sa_p->ips_flow_s.u.v4.sin_family == AF_INET) {
			subnettoa(sa_p->ips_flow_s.u.v4.sin_addr,
				  sa_p->ips_mask_s.u.v4.sin_addr,
				  0,
				  buf_s,
				  sizeof(buf_s));
			subnettoa(sa_p->ips_flow_d.u.v4.sin_addr,
				  sa_p->ips_mask_d.u.v4.sin_addr,
				  0,
				  buf_d,
				  sizeof(buf_d));
		} else {
			subnet6toa(&sa_p->ips_flow_s.u.v6.sin6_addr,
				   &sa_p->ips_mask_s.u.v6.sin6_addr,
				   0,
				   buf_s,
				   sizeof(buf_s));
			subnet6toa(&sa_p->ips_flow_d.u.v6.sin6_addr,
				   &sa_p->ips_mask_d.u.v6.sin6_addr,
				   0,
				   buf_d,
				   sizeof(buf_d));
		}

		seq_printf(seq, " policy=%s->%s", buf_s, buf_d);
	}

	if (sa_p->ips_iv_bits) {
		int j;
		seq_printf(seq, " iv_bits=%dbits iv=0x", sa_p->ips_iv_bits);

		for (j = 0; j < sa_p->ips_iv_bits / 8; j++) {
#ifdef CONFIG_KLIPS_OCF
			if (sa_p->ips_iv == NULL) {
				/*
				 * ocf doesn't set the IV
				 * so fake it for the test cases
				 */
				seq_printf(seq, "%02x", 0xA5 + j);
			} else
#endif
			seq_printf(seq, "%02x", ((__u8*)sa_p->ips_iv)[j]);
		}
	}

	if (sa_p->ips_encalg || sa_p->ips_authalg) {
		if (sa_p->ips_replaywin)
			seq_printf(seq, " ooowin=%d", sa_p->ips_replaywin);
		if (sa_p->ips_errs.ips_replaywin_errs)
			seq_printf(seq, " ooo_errs=%d", sa_p->ips_errs.ips_replaywin_errs);
		if (sa_p->ips_replaywin_lastseq)
		       seq_printf(seq, " seq=%d", sa_p->ips_replaywin_lastseq);
		if (sa_p->ips_replaywin_bitmap)
			seq_printf(seq, " bit=0x%Lx", sa_p->ips_replaywin_bitmap);
		if (sa_p->ips_replaywin_maxdiff)
			seq_printf(seq, " max_seq_diff=%d", sa_p->ips_replaywin_maxdiff);
	}

	if (sa_p->ips_flags & ~EMT_INBOUND) {
		seq_printf(seq, " flags=0x%x", sa_p->ips_flags & ~EMT_INBOUND);
		seq_printf(seq, "<");
		/* flag printing goes here */
		seq_printf(seq, ">");
	}

	if (sa_p->ips_auth_bits)
		seq_printf(seq, " alen=%d", sa_p->ips_auth_bits);
	if (sa_p->ips_key_bits_a)
		seq_printf(seq, " aklen=%d", sa_p->ips_key_bits_a);
	if (sa_p->ips_errs.ips_auth_errs)
		seq_printf(seq, " auth_errs=%d", sa_p->ips_errs.ips_auth_errs);
	if (sa_p->ips_key_bits_e)
		seq_printf(seq, " eklen=%d", sa_p->ips_key_bits_e);
	if (sa_p->ips_errs.ips_encsize_errs)
		seq_printf(seq, " encr_size_errs=%d", sa_p->ips_errs.ips_encsize_errs);
	if (sa_p->ips_errs.ips_encpad_errs)
		seq_printf(seq, " encr_pad_errs=%d", sa_p->ips_errs.ips_encpad_errs);

	seq_printf(seq, " jiffies=%lu", jiffies);

	seq_printf(seq, " life(c,s,h)=");

	ipsec_lifetime_format(seq, "alloc",
			      ipsec_life_countbased, &sa_p->ips_life.ipl_allocations);

	ipsec_lifetime_format(seq, "bytes",
			      ipsec_life_countbased, &sa_p->ips_life.ipl_bytes);

	ipsec_lifetime_format(seq, "addtime",
			      ipsec_life_timebased, &sa_p->ips_life.ipl_addtime);

	ipsec_lifetime_format(seq, "usetime",
			      ipsec_life_timebased, &sa_p->ips_life.ipl_usetime);

	ipsec_lifetime_format(seq, "packets",
			      ipsec_life_countbased, &sa_p->ips_life.ipl_packets);

	if (sa_p->ips_life.ipl_usetime.ipl_last) { /* XXX-MCR should be last? */
		seq_printf(seq, " idle=%Ld",
			   ipsec_jiffieshz_elapsed(jiffies/HZ, sa_p->ips_life.ipl_usetime.ipl_last));
	}

#ifdef CONFIG_KLIPS_IPCOMP
	if (sa_p->ips_said.proto == IPPROTO_COMP &&
	   (sa_p->ips_comp_ratio_dbytes ||
	    sa_p->ips_comp_ratio_cbytes)) {
		seq_printf(seq, " ratio=%Ld:%Ld",
			   sa_p->ips_comp_ratio_dbytes,
			   sa_p->ips_comp_ratio_cbytes);
	}
#endif /* CONFIG_KLIPS_IPCOMP */

	seq_printf(seq, " natencap=");
	switch (sa_p->ips_natt_type) {
	case 0:
		seq_printf(seq, "none");
		break;
	case ESPINUDP_WITH_NON_IKE:
		seq_printf(seq, "nonike");
		break;
	case ESPINUDP_WITH_NON_ESP:
		seq_printf(seq, "nonesp");
		break;
	default:
		seq_printf(seq, "unknown");
		break;
	}

	seq_printf(seq, " natsport=%d", sa_p->ips_natt_sport);
	seq_printf(seq, " natdport=%d", sa_p->ips_natt_dport);

	/* we decrement by one, because this SA has been referenced in order to dump this info */
	seq_printf(seq, " refcount=%d", atomic_read(&sa_p->ips_refcount)-1);
#ifdef IPSEC_SA_RECOUNT_DEBUG
	{
		int f;
		seq_printf(seq, "[");
		for (f = 0; f < sizeof(sa_p->ips_track); f++)
			seq_printf(seq, "%s%d", f == 0 ? "" : ",", sa_p->ips_track[f]);
		seq_printf(seq, "]");
	}
#endif

	seq_printf(seq, " ref=%d", sa_p->ips_ref);
	seq_printf(seq, " refhim=%d", sa_p->ips_refhim);

	if (sa_p->ips_out) {
		seq_printf(seq, " outif=%s:%d",
			   sa_p->ips_out->name,
			   sa_p->ips_transport_direct);
	}

	if (debug_xform) {
		seq_printf(seq, " reftable=%lu refentry=%lu",
			   (unsigned long)IPsecSAref2table(sa_p->ips_ref),
			   (unsigned long)IPsecSAref2entry(sa_p->ips_ref));
	}

	seq_printf(seq, "\n");

	ipsec_sa_put(sa_p, IPSEC_REFPROC);
	return 0;
}