static int
ipf_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
{
#if defined(INET6)
#  if defined(M_CSUM_TCPv6) && (__NetBSD_Version__ > 200000000)
	/*
	 * If the packet is out-bound, we can't delay checksums
	 * here.  For in-bound, the checksum has already been
	 * validated.
	 */
	if (dir == PFIL_OUT) {
		if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) {
#   if (__NetBSD_Version__ > 399000600)
			in6_delayed_cksum(*mp);
#   endif
			(*mp)->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv6|
							M_CSUM_UDPv6);
		}
	}
#  endif
#endif /* INET6 */

	return (ipf_check(&ipfmain, mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
	    ifp, (dir == PFIL_OUT), mp));
}
Example #2
0
int
ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *error)
{
#ifdef IPSEC
	struct secpolicy *sp;

	/*
	 * Check the security policy (SP) for the packet and, if
	 * required, do IPsec-related processing.  There are two
	 * cases here; the first time a packet is sent through
	 * it will be untagged and handled by ipsec4_checkpolicy.
	 * If the packet is resubmitted to ip6_output (e.g. after
	 * AH, ESP, etc. processing), there will be a tag to bypass
	 * the lookup and related policy checking.
	 */
	if (m_tag_find(*m, PACKET_TAG_IPSEC_OUT_DONE, NULL) != NULL) {
		*error = 0;
		return (0);
	}
	sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, error, inp);
	/*
	 * There are four return cases:
	 *    sp != NULL		    apply IPsec policy
	 *    sp == NULL, error == 0	    no IPsec handling needed
	 *    sp == NULL, error == -EINVAL  discard packet w/o error
	 *    sp == NULL, error != 0	    discard packet, report error
	 */
	if (sp != NULL) {
		/*
		 * Do delayed checksums now because we send before
		 * this is done in the normal processing path.
		 */
#ifdef INET
		if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
			in_delayed_cksum(*m);
			(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
		}
#endif
		if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA_IPV6) {
			in6_delayed_cksum(*m, (*m)->m_pkthdr.len - sizeof(struct ip6_hdr),
							sizeof(struct ip6_hdr));
			(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA_IPV6;
		}
#ifdef SCTP
		if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP_IPV6) {
			sctp_delayed_cksum(*m, sizeof(struct ip6_hdr));
			(*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP_IPV6;
		}
#endif

		/* NB: callee frees mbuf */
		*error = ipsec6_process_packet(*m, sp->req);

		if (*error == EJUSTRETURN) {
			/*
			 * We had a SP with a level of 'use' and no SA. We
			 * will just continue to process the packet without
			 * IPsec processing.
			 */
			*error = 0;
			goto done;
		}

		/*
		 * Preserve KAME behaviour: ENOENT can be returned
		 * when an SA acquire is in progress.  Don't propagate
		 * this to user-level; it confuses applications.
		 *
		 * XXX this will go away when the SADB is redone.
		 */
		if (*error == ENOENT)
			*error = 0;
		goto reinjected;
	} else {	/* sp == NULL */
		if (*error != 0) {
			/*
			 * Hack: -EINVAL is used to signal that a packet
			 * should be silently discarded.  This is typically
			 * because we asked key management for an SA and
			 * it was delayed (e.g. kicked up to IKE).
			 */
			if (*error == -EINVAL)
				*error = 0;
			goto bad;
		}
		/* No IPsec processing for this packet. */
	}
done:
	if (sp != NULL)
		KEY_FREESP(&sp);
	return 0;
reinjected:
	if (sp != NULL)
		KEY_FREESP(&sp);
	return -1;
bad:
	if (sp != NULL)
		KEY_FREESP(&sp);
	return 1;
#endif /* IPSEC */
	return 0;
}