case SENT_IPSP:
case SENT_IP4:
check_ipsec_policy(struct inpcb *inp, void *daddr){    struct route_enc re0, *re = &re0;    struct sockaddr_encap *dst, *gw;    u_int8_t sa_require, sa_have;    struct tdb tdb2, *tdb = NULL;    union sockaddr_union sunion;    struct socket *so;    int error, i, s;    if (inp == NULL || ((so = inp->inp_socket) == 0))      return (EINVAL);    /* If IPSEC is not required just use what we got */    if (!(sa_require = inp->inp_secrequire))      return 0;    s = spltdb();    if (!inp->inp_tdb)    {	bzero((caddr_t) re, sizeof(*re));	dst = (struct sockaddr_encap *) &re->re_dst;	dst->sen_family = PF_KEY;#ifdef INET6	if (inp->inp_flags & INP_IPV6)	{	    dst->sen_len = SENT_IP6_LEN;	    dst->sen_type = SENT_IP6;	    dst->sen_ip6_src = inp->inp_laddr6;	    if (inp->inp_faddr6.s6_addr)	      dst->sen_ip6_dst = inp->inp_faddr6;	    else	      dst->sen_ip6_dst =  (*((struct in6_addr *) daddr));	    dst->sen_ip6_proto = so->so_proto->pr_protocol;	    switch (dst->sen_ip6_proto)	    {		case IPPROTO_UDP:		case IPPROTO_TCP:		    dst->sen_ip6_sport = htons(inp->inp_lport);		    dst->sen_ip6_dport = htons(inp->inp_fport);		    break;		default:		    dst->sen_ip6_sport = 0;		    dst->sen_ip6_dport = 0;	    }	}#endif /* INET6 */#ifdef INET	if (!(inp->inp_flags & INP_IPV6))	{	    dst->sen_len = SENT_IP4_LEN;	    dst->sen_type = SENT_IP4;	    dst->sen_ip_src = inp->inp_laddr;	    if (inp->inp_faddr.s_addr)	      dst->sen_ip_dst = inp->inp_faddr;	    else	      dst->sen_ip_dst = (*((struct in_addr *) daddr));	    dst->sen_proto = so->so_proto->pr_protocol;	    switch (dst->sen_proto)	    {		case IPPROTO_UDP:		case IPPROTO_TCP:		    dst->sen_sport = htons(inp->inp_lport);		    dst->sen_dport = htons(inp->inp_fport);		    break;		default:		    dst->sen_sport = 0;		    dst->sen_dport = 0;	    }	}#endif /* INET */	/* Try to find a flow */	rtalloc((struct route *) re);	if (re->re_rt != NULL)	{	    gw = (struct sockaddr_encap *) (re->re_rt->rt_gateway);#ifdef INET	    if (gw->sen_type == SENT_IPSP)	    {		bzero(&sunion, sizeof(sunion));	        sunion.sin.sin_family = AF_INET;		sunion.sin.sin_len = sizeof(struct sockaddr_in);		sunion.sin.sin_addr = gw->sen_ipsp_dst;	      		tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion,					    gw->sen_ipsp_sproto);	    }#endif /* INET */#ifdef INET6	    if (gw->sen_type == SENT_IPSP6)	    {		bzero(&sunion, sizeof(sunion));	        sunion.sin6.sin6_family = AF_INET6;		sunion.sin6.sin6_len = sizeof(struct sockaddr_in6);		sunion.sin6.sin6_addr = gw->sen_ipsp6_dst;	      		tdb = (struct tdb *) gettdb(gw->sen_ipsp6_spi, &sunion,					    gw->sen_ipsp6_sproto);	    }#endif /* INET6 */	    RTFREE(re->re_rt);	}    }    else      tdb = inp->inp_tdb;    if (tdb)      SPI_CHAIN_ATTRIB(sa_have, tdb_onext, tdb);    else      sa_have = 0;    splx(s);    /* Check if our requirements are met */    if (!(sa_require & ~sa_have))      return 0;    error = i = 0;    inp->inp_secresult = SR_WAIT;    /* If necessary try to notify keymanagement three times */    while (i < 3)    {	switch (dst->sen_type)	{#ifdef INET	    case SENT_IPSP:		DPRINTF(("ipsec: send SA request (%d), remote IPv4 address: %s, SA type: %d\n", i + 1, inet_ntoa4(dst->sen_ip_dst), sa_require));		break;#endif /* INET */#ifdef INET6	    case SENT_IPSP6:		DPRINTF(("ipsec: send SA request (%d), remote IPv6 address: %s, SA type: %d\n", i + 1, inet6_ntoa4(dst->sen_ip6_dst), sa_require));		break;#endif /* INET6 */	    default:		DPRINTF(("ipsec: unsupported protocol family %d, cannot notify kkey management\n", dst->sen_type));		return EPFNOSUPPORT;	}	/* Initialize TDB for PF_KEY notification */	bzero(&tdb2, sizeof(tdb2));	tdb2.tdb_satype = get_sa_require(inp);	/* Check for PFS */	if (ipsec_require_pfs)	  tdb2.tdb_flags |= TDBF_PFS;	/* Initialize expirations */	if (ipsec_soft_allocations > 0)	  tdb2.tdb_soft_allocations = ipsec_soft_allocations;	if (ipsec_exp_allocations > 0)	  tdb2.tdb_exp_allocations = ipsec_exp_allocations;	if (ipsec_soft_bytes > 0)	  tdb2.tdb_soft_bytes = ipsec_soft_bytes;	if (ipsec_exp_bytes > 0)	  tdb2.tdb_exp_bytes = ipsec_exp_bytes;	if (ipsec_soft_timeout > 0)	  tdb2.tdb_soft_timeout = ipsec_soft_timeout;	if (ipsec_exp_timeout > 0)	  tdb2.tdb_exp_timeout = ipsec_exp_timeout;	if (ipsec_soft_first_use > 0)	  tdb2.tdb_soft_first_use = ipsec_soft_first_use;	if (ipsec_exp_first_use > 0)	  tdb2.tdb_exp_first_use = ipsec_exp_first_use;	if (tdb2.tdb_satype & NOTIFY_SATYPE_CONF)	{	    if (!strncasecmp(ipsec_def_enc, "des", sizeof("des")))	      tdb2.tdb_encalgxform = &enc_xform_des;	    else	      if (!strncasecmp(ipsec_def_enc, "3des", sizeof("3des")))		tdb2.tdb_encalgxform = &enc_xform_3des;	      else		if (!strncasecmp(ipsec_def_enc, "blowfish", sizeof("blowfish")))		  tdb2.tdb_encalgxform = &enc_xform_blf;		else		  if (!strncasecmp(ipsec_def_enc, "cast128", sizeof("cast128")))		    tdb2.tdb_encalgxform = &enc_xform_cast5;		  else		    if (!strncasecmp(ipsec_def_enc, "skipjack",				     sizeof("skipjack")))		      tdb2.tdb_encalgxform = &enc_xform_skipjack;	}	if (tdb2.tdb_satype & NOTIFY_SATYPE_AUTH)	{	    if (!strncasecmp(ipsec_def_auth, "hmac-md5", sizeof("hmac-md5")))	      tdb2.tdb_authalgxform = &auth_hash_hmac_md5_96;	    else	      if (!strncasecmp(ipsec_def_auth, "hmac-sha1",			       sizeof("hmac-sha1")))		tdb2.tdb_authalgxform = &auth_hash_hmac_sha1_96;	      else		if (!strncasecmp(ipsec_def_auth, "hmac-ripemd160",				 sizeof("hmac_ripemd160")))		  tdb2.tdb_authalgxform = &auth_hash_hmac_ripemd_160_96;	}	/* XXX Initialize src_id/dst_id */#ifdef INET	if (!(inp->inp_flags & INP_IPV6))	{	    tdb2.tdb_src.sin.sin_family = AF_INET;	    tdb2.tdb_src.sin.sin_len = sizeof(struct sockaddr_in);	    tdb2.tdb_src.sin.sin_addr = inp->inp_laddr;	    tdb2.tdb_dst.sin.sin_family = AF_INET;	    tdb2.tdb_dst.sin.sin_len = sizeof(struct sockaddr_in);	    tdb2.tdb_dst.sin.sin_addr = inp->inp_faddr;	}#endif /* INET */#ifdef INET6	if (inp->inp_flags & INP_IPV6)	{	    tdb2.tdb_src.sin6.sin6_family = AF_INET6;	    tdb2.tdb_src.sin6.sin6_len = sizeof(struct sockaddr_in6);	    tdb2.tdb_src.sin6.sin6_addr = inp->inp_laddr6;	    tdb2.tdb_dst.sin6.sin6_family = AF_INET6;	    tdb2.tdb_dst.sin6.sin6_len = sizeof(struct sockaddr_in6);	    tdb2.tdb_dst.sin6.sin6_addr = inp->inp_faddr6;	}#endif /* INET6 */	/* Send PF_KEYv2 Notify */	if ((error = pfkeyv2_acquire(&tdb2, 0)) != 0)	  return error;	/* 	 * Wait for the keymanagement daemon to establich a new SA,	 * even on error check again, perhaps some other process	 * already established the necessary SA.	 */	error = tsleep((caddr_t)inp, PSOCK|PCATCH, "ipsecnotify", 30*hz);	DPRINTF(("check_ipsec: sleep %d\n", error));	if (error && error != EWOULDBLOCK)	  break;	/* 	 * A Key Management daemon returned an apropriate SA back	 * to the kernel, the kernel noted that state in the waiting	 * socket.	 */	if (inp->inp_secresult == SR_SUCCESS)	  return (0);	/*	 * Key Management returned a permanent failure, we do not	 * need to retry again.	 *	 * XXX when more than one key management daemon is available	 * XXX we can not do that.	 */	if (inp->inp_secresult == SR_FAILED)	  break;	i++;    }    return (error ? error : EWOULDBLOCK);}