Deleted Added
full compact
34c34
< * $FreeBSD: head/sys/netinet/ip_output.c 54175 1999-12-06 00:43:07Z archie $
---
> * $FreeBSD: head/sys/netinet/ip_output.c 55009 1999-12-22 19:13:38Z shin $
42a43
> #include "opt_ipsec.h"
51a53
> #include <sys/proc.h>
62a65,66
> #include "faith.h"
>
69a74,83
> #ifdef IPSEC
> #include <netinet6/ipsec.h>
> #include <netkey/key.h>
> #ifdef IPSEC_DEBUG
> #include <netkey/key_debug.h>
> #else
> #define KEYDEBUG(lev,arg)
> #endif
> #endif /*IPSEC*/
>
125a140,144
> #ifdef IPSEC
> struct route iproute;
> struct socket *so;
> struct secpolicy *sp = NULL;
> #endif
138a158,183
>
> #ifdef IPSEC
> /*
> * NOTE: If IP_SOCKINMRCVIF flag is set, 'socket *' is kept in
> * m->m_pkthdr.rcvif for later IPSEC check. In this case,
> * m->m_pkthdr will be NULL cleared after the contents is saved in
> * 'so'.
> * NULL clearance of rcvif should be natural because the packet should
> * have been sent from my own socket and has no rcvif in this case.
> * It is also necessary because someone might consider it as
> * 'ifnet *', and cause SEGV.
> */
> if ((flags & IP_SOCKINMRCVIF) != 0) {
> #if defined(IPFIREWALL) && defined(DUMMYNET)
> if (m->m_type == MT_DUMMYNET) {
> so = (struct socket *)m->m_next->m_pkthdr.rcvif;
> m->m_next->m_pkthdr.rcvif = NULL;
> } else
> #endif
> {
> so = (struct socket *)m->m_pkthdr.rcvif;
> m->m_pkthdr.rcvif = NULL;
> }
> } else
> so = NULL;
> #endif /*IPSEC*/
153a199
> dst = (struct sockaddr_in *)((struct dn_pkt *)m)->dn_dst;
156d201
< dst = (struct sockaddr_in *)flags ;
160d204
< flags = 0 ; /* XXX is this correct ? */
458c502,503
< dummynet_io(off & 0xffff, DN_TO_IP_OUT, m,ifp,ro,dst,rule);
---
> dummynet_io(off & 0xffff, DN_TO_IP_OUT, m,ifp,ro,dst,rule,
> flags);
599a645,763
> #ifdef IPSEC
> /* get SP for this packet */
> if (so == NULL)
> sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error);
> else
> sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
>
> if (sp == NULL) {
> ipsecstat.out_inval++;
> goto bad;
> }
>
> error = 0;
>
> /* check policy */
> switch (sp->policy) {
> case IPSEC_POLICY_DISCARD:
> /*
> * This packet is just discarded.
> */
> ipsecstat.out_polvio++;
> goto bad;
>
> case IPSEC_POLICY_BYPASS:
> case IPSEC_POLICY_NONE:
> /* no need to do IPsec. */
> goto skip_ipsec;
>
> case IPSEC_POLICY_IPSEC:
> if (sp->req == NULL) {
> /* XXX should be panic ? */
> printf("ip_output: No IPsec request specified.\n");
> error = EINVAL;
> goto bad;
> }
> break;
>
> case IPSEC_POLICY_ENTRUST:
> default:
> printf("ip_output: Invalid policy found. %d\n", sp->policy);
> }
>
> ip->ip_len = htons((u_short)ip->ip_len);
> ip->ip_off = htons((u_short)ip->ip_off);
> ip->ip_sum = 0;
>
> {
> struct ipsec_output_state state;
> bzero(&state, sizeof(state));
> state.m = m;
> if (flags & IP_ROUTETOIF) {
> state.ro = &iproute;
> bzero(&iproute, sizeof(iproute));
> } else
> state.ro = ro;
> state.dst = (struct sockaddr *)dst;
>
> error = ipsec4_output(&state, sp, flags);
>
> m = state.m;
> if (flags & IP_ROUTETOIF) {
> /*
> * if we have tunnel mode SA, we may need to ignore
> * IP_ROUTETOIF.
> */
> if (state.ro != &iproute || state.ro->ro_rt != NULL) {
> flags &= ~IP_ROUTETOIF;
> ro = state.ro;
> }
> } else
> ro = state.ro;
> dst = (struct sockaddr_in *)state.dst;
> if (error) {
> /* mbuf is already reclaimed in ipsec4_output. */
> m0 = NULL;
> switch (error) {
> case EHOSTUNREACH:
> case ENETUNREACH:
> case EMSGSIZE:
> case ENOBUFS:
> case ENOMEM:
> break;
> default:
> printf("ip4_output (ipsec): error code %d\n", error);
> /*fall through*/
> case ENOENT:
> /* don't show these error codes to the user */
> error = 0;
> break;
> }
> goto bad;
> }
> }
>
> /* be sure to update variables that are affected by ipsec4_output() */
> ip = mtod(m, struct ip *);
> #ifdef _IP_VHL
> hlen = IP_VHL_HL(ip->ip_vhl) << 2;
> #else
> hlen = ip->ip_hl << 2;
> #endif
> if (ro->ro_rt == NULL) {
> if ((flags & IP_ROUTETOIF) == 0) {
> printf("ip_output: "
> "can't update route after IPsec processing\n");
> error = EHOSTUNREACH; /*XXX*/
> goto bad;
> }
> } else {
> /* nobody uses ia beyond here */
> ifp = ro->ro_rt->rt_ifp;
> }
>
> /* make it flipped, again. */
> ip->ip_len = ntohs((u_short)ip->ip_len);
> ip->ip_off = ntohs((u_short)ip->ip_off);
> skip_ipsec:
> #endif /*IPSEC*/
>
726a891,901
> #ifdef IPSEC
> if (ro == &iproute && ro->ro_rt) {
> RTFREE(ro->ro_rt);
> ro->ro_rt = NULL;
> }
> if (sp != NULL) {
> KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
> printf("DP ip_output call free SP:%p\n", sp));
> key_freesp(sp);
> }
> #endif /* IPSEC */
870a1046,1048
> #if defined(NFAITH) && NFAITH > 0
> case IP_FAITH:
> #endif
904a1083,1088
>
> #if defined(NFAITH) && NFAITH > 0
> case IP_FAITH:
> OPTSET(INP_FAITH);
> break;
> #endif
945a1130,1151
> #ifdef IPSEC
> case IP_IPSEC_POLICY:
> {
> caddr_t req;
> int priv;
> struct mbuf *m;
> int optname;
>
> if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
> break;
> if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
> break;
> priv = (sopt->sopt_p != NULL &&
> suser(sopt->sopt_p) != 0) ? 0 : 1;
> req = mtod(m, caddr_t);
> optname = sopt->sopt_name;
> error = ipsec4_set_policy(inp, optname, req, priv);
> m_freem(m);
> break;
> }
> #endif /*IPSEC*/
>
971a1178,1180
> #if defined(NFAITH) && NFAITH > 0
> case IP_FAITH:
> #endif
1007a1217,1222
>
> #if defined(NFAITH) && NFAITH > 0
> case IP_FAITH:
> optval = OPTBIT(INP_FAITH);
> break;
> #endif
1020a1236,1251
> #ifdef IPSEC
> case IP_IPSEC_POLICY:
> {
> struct mbuf *m;
> caddr_t req = NULL;
>
> if (m != 0)
> req = mtod(m, caddr_t);
> error = ipsec4_get_policy(sotoinpcb(so), req, &m);
> if (error == 0)
> error = soopt_mcopyout(sopt, m); /* XXX */
> m_freem(m);
> break;
> }
> #endif /*IPSEC*/
>