1/*
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
--- 17 unchanged lines hidden (view full) ---
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
34 * $FreeBSD: head/sys/netinet/ip_output.c 55009 1999-12-22 19:13:38Z shin $
35 */
36
37#define _IP_VHL
38
39#include "opt_ipfw.h"
40#include "opt_ipdn.h"
41#include "opt_ipdivert.h"
42#include "opt_ipfilter.h"
43#include "opt_ipsec.h"
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/kernel.h>
48#include <sys/malloc.h>
49#include <sys/mbuf.h>
50#include <sys/protosw.h>
51#include <sys/socket.h>
52#include <sys/socketvar.h>
53#include <sys/proc.h>
54
55#include <net/if.h>
56#include <net/route.h>
57
58#include <netinet/in.h>
59#include <netinet/in_systm.h>
60#include <netinet/ip.h>
61#include <netinet/in_pcb.h>
62#include <netinet/in_var.h>
63#include <netinet/ip_var.h>
64
65#include "faith.h"
66
67#ifdef vax
68#include <machine/mtpr.h>
69#endif
70#include <machine/in_cksum.h>
71
72static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
73
74#ifdef IPSEC
75#include <netinet6/ipsec.h>
76#include <netkey/key.h>
77#ifdef IPSEC_DEBUG
78#include <netkey/key_debug.h>
79#else
80#define KEYDEBUG(lev,arg)
81#endif
82#endif /*IPSEC*/
83
84#include <netinet/ip_fw.h>
85
86#ifdef DUMMYNET
87#include <netinet/ip_dummynet.h>
88#endif
89
90#ifdef IPFIREWALL_FORWARD_DEBUG
91#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
--- 40 unchanged lines hidden (view full) ---
132 struct ip *ip, *mhip;
133 struct ifnet *ifp;
134 struct mbuf *m = m0;
135 int hlen = sizeof (struct ip);
136 int len, off, error = 0;
137 struct sockaddr_in *dst;
138 struct in_ifaddr *ia;
139 int isbroadcast;
140#ifdef IPSEC
141 struct route iproute;
142 struct socket *so;
143 struct secpolicy *sp = NULL;
144#endif
145 u_int16_t divert_cookie; /* firewall cookie */
146#ifdef IPFIREWALL_FORWARD
147 int fwd_rewrite_src = 0;
148#endif
149 struct ip_fw_chain *rule = NULL;
150
151#ifdef IPDIVERT
152 /* Get and reset firewall cookie */
153 divert_cookie = ip_divert_cookie;
154 ip_divert_cookie = 0;
155#else
156 divert_cookie = 0;
157#endif
158
159#ifdef IPSEC
160 /*
161 * NOTE: If IP_SOCKINMRCVIF flag is set, 'socket *' is kept in
162 * m->m_pkthdr.rcvif for later IPSEC check. In this case,
163 * m->m_pkthdr will be NULL cleared after the contents is saved in
164 * 'so'.
165 * NULL clearance of rcvif should be natural because the packet should
166 * have been sent from my own socket and has no rcvif in this case.
167 * It is also necessary because someone might consider it as
168 * 'ifnet *', and cause SEGV.
169 */
170 if ((flags & IP_SOCKINMRCVIF) != 0) {
171#if defined(IPFIREWALL) && defined(DUMMYNET)
172 if (m->m_type == MT_DUMMYNET) {
173 so = (struct socket *)m->m_next->m_pkthdr.rcvif;
174 m->m_next->m_pkthdr.rcvif = NULL;
175 } else
176#endif
177 {
178 so = (struct socket *)m->m_pkthdr.rcvif;
179 m->m_pkthdr.rcvif = NULL;
180 }
181 } else
182 so = NULL;
183#endif /*IPSEC*/
184
185#if defined(IPFIREWALL) && defined(DUMMYNET)
186 /*
187 * dummynet packet are prepended a vestigial mbuf with
188 * m_type = MT_DUMMYNET and m_data pointing to the matching
189 * rule.
190 */
191 if (m->m_type == MT_DUMMYNET) {
192 /*
193 * the packet was already tagged, so part of the
194 * processing was already done, and we need to go down.
195 * opt, flags and imo have already been used, and now
196 * they are used to hold ifp, dst and NULL, respectively.
197 */
198 rule = (struct ip_fw_chain *)(m->m_data) ;
199 dst = (struct sockaddr_in *)((struct dn_pkt *)m)->dn_dst;
200 m0 = m = m->m_next ;
201 ip = mtod(m, struct ip *);
202 ifp = (struct ifnet *)opt;
203 hlen = IP_VHL_HL(ip->ip_vhl) << 2 ;
204 opt = NULL ;
205 goto sendit;
206 } else
207 rule = NULL ;
208#endif
209
210#ifdef DIAGNOSTIC
211 if ((m->m_flags & M_PKTHDR) == 0)
212 panic("ip_output no HDR");
--- 281 unchanged lines hidden (view full) ---
494 * pass the pkt to dummynet. Need to include
495 * pipe number, m, ifp, ro, dst because these are
496 * not recomputed in the next pass.
497 * All other parameters have been already used and
498 * so they are not needed anymore.
499 * XXX note: if the ifp or ro entry are deleted
500 * while a pkt is in dummynet, we are in trouble!
501 */
502 dummynet_io(off & 0xffff, DN_TO_IP_OUT, m,ifp,ro,dst,rule,
503 flags);
504 goto done;
505 }
506#endif
507#ifdef IPDIVERT
508 if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) {
509 struct mbuf *clone = NULL;
510
511 /* Clone packet if we're doing a 'tee' */
--- 125 unchanged lines hidden (view full) ---
637 * we have to drop the pkt
638 */
639 m_freem(m);
640 error = EACCES; /* not sure this is the right error msg */
641 goto done;
642 }
643
644pass:
645#ifdef IPSEC
646 /* get SP for this packet */
647 if (so == NULL)
648 sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error);
649 else
650 sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
651
652 if (sp == NULL) {
653 ipsecstat.out_inval++;
654 goto bad;
655 }
656
657 error = 0;
658
659 /* check policy */
660 switch (sp->policy) {
661 case IPSEC_POLICY_DISCARD:
662 /*
663 * This packet is just discarded.
664 */
665 ipsecstat.out_polvio++;
666 goto bad;
667
668 case IPSEC_POLICY_BYPASS:
669 case IPSEC_POLICY_NONE:
670 /* no need to do IPsec. */
671 goto skip_ipsec;
672
673 case IPSEC_POLICY_IPSEC:
674 if (sp->req == NULL) {
675 /* XXX should be panic ? */
676 printf("ip_output: No IPsec request specified.\n");
677 error = EINVAL;
678 goto bad;
679 }
680 break;
681
682 case IPSEC_POLICY_ENTRUST:
683 default:
684 printf("ip_output: Invalid policy found. %d\n", sp->policy);
685 }
686
687 ip->ip_len = htons((u_short)ip->ip_len);
688 ip->ip_off = htons((u_short)ip->ip_off);
689 ip->ip_sum = 0;
690
691 {
692 struct ipsec_output_state state;
693 bzero(&state, sizeof(state));
694 state.m = m;
695 if (flags & IP_ROUTETOIF) {
696 state.ro = &iproute;
697 bzero(&iproute, sizeof(iproute));
698 } else
699 state.ro = ro;
700 state.dst = (struct sockaddr *)dst;
701
702 error = ipsec4_output(&state, sp, flags);
703
704 m = state.m;
705 if (flags & IP_ROUTETOIF) {
706 /*
707 * if we have tunnel mode SA, we may need to ignore
708 * IP_ROUTETOIF.
709 */
710 if (state.ro != &iproute || state.ro->ro_rt != NULL) {
711 flags &= ~IP_ROUTETOIF;
712 ro = state.ro;
713 }
714 } else
715 ro = state.ro;
716 dst = (struct sockaddr_in *)state.dst;
717 if (error) {
718 /* mbuf is already reclaimed in ipsec4_output. */
719 m0 = NULL;
720 switch (error) {
721 case EHOSTUNREACH:
722 case ENETUNREACH:
723 case EMSGSIZE:
724 case ENOBUFS:
725 case ENOMEM:
726 break;
727 default:
728 printf("ip4_output (ipsec): error code %d\n", error);
729 /*fall through*/
730 case ENOENT:
731 /* don't show these error codes to the user */
732 error = 0;
733 break;
734 }
735 goto bad;
736 }
737 }
738
739 /* be sure to update variables that are affected by ipsec4_output() */
740 ip = mtod(m, struct ip *);
741#ifdef _IP_VHL
742 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
743#else
744 hlen = ip->ip_hl << 2;
745#endif
746 if (ro->ro_rt == NULL) {
747 if ((flags & IP_ROUTETOIF) == 0) {
748 printf("ip_output: "
749 "can't update route after IPsec processing\n");
750 error = EHOSTUNREACH; /*XXX*/
751 goto bad;
752 }
753 } else {
754 /* nobody uses ia beyond here */
755 ifp = ro->ro_rt->rt_ifp;
756 }
757
758 /* make it flipped, again. */
759 ip->ip_len = ntohs((u_short)ip->ip_len);
760 ip->ip_off = ntohs((u_short)ip->ip_off);
761skip_ipsec:
762#endif /*IPSEC*/
763
764 /*
765 * If small enough for interface, can just send directly.
766 */
767 if ((u_short)ip->ip_len <= ifp->if_mtu) {
768 ip->ip_len = htons((u_short)ip->ip_len);
769 ip->ip_off = htons((u_short)ip->ip_off);
770 ip->ip_sum = 0;
771 if (ip->ip_vhl == IP_VHL_BORING) {
--- 111 unchanged lines hidden (view full) ---
883 else
884 m_freem(m);
885 }
886
887 if (error == 0)
888 ipstat.ips_fragmented++;
889 }
890done:
891#ifdef IPSEC
892 if (ro == &iproute && ro->ro_rt) {
893 RTFREE(ro->ro_rt);
894 ro->ro_rt = NULL;
895 }
896 if (sp != NULL) {
897 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
898 printf("DP ip_output call free SP:%p\n", sp));
899 key_freesp(sp);
900 }
901#endif /* IPSEC */
902 return (error);
903bad:
904 m_freem(m0);
905 goto done;
906}
907
908/*
909 * Insert IP options into preformed packet.
--- 128 unchanged lines hidden (view full) ---
1038 }
1039
1040 case IP_TOS:
1041 case IP_TTL:
1042 case IP_RECVOPTS:
1043 case IP_RECVRETOPTS:
1044 case IP_RECVDSTADDR:
1045 case IP_RECVIF:
1046#if defined(NFAITH) && NFAITH > 0
1047 case IP_FAITH:
1048#endif
1049 error = sooptcopyin(sopt, &optval, sizeof optval,
1050 sizeof optval);
1051 if (error)
1052 break;
1053
1054 switch (sopt->sopt_name) {
1055 case IP_TOS:
1056 inp->inp_ip_tos = optval;
--- 18 unchanged lines hidden (view full) ---
1075
1076 case IP_RECVDSTADDR:
1077 OPTSET(INP_RECVDSTADDR);
1078 break;
1079
1080 case IP_RECVIF:
1081 OPTSET(INP_RECVIF);
1082 break;
1083
1084#if defined(NFAITH) && NFAITH > 0
1085 case IP_FAITH:
1086 OPTSET(INP_FAITH);
1087 break;
1088#endif
1089 }
1090 break;
1091#undef OPTSET
1092
1093 case IP_MULTICAST_IF:
1094 case IP_MULTICAST_VIF:
1095 case IP_MULTICAST_TTL:
1096 case IP_MULTICAST_LOOP:
--- 25 unchanged lines hidden (view full) ---
1122 break;
1123
1124 default:
1125 error = EINVAL;
1126 break;
1127 }
1128 break;
1129
1130#ifdef IPSEC
1131 case IP_IPSEC_POLICY:
1132 {
1133 caddr_t req;
1134 int priv;
1135 struct mbuf *m;
1136 int optname;
1137
1138 if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
1139 break;
1140 if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
1141 break;
1142 priv = (sopt->sopt_p != NULL &&
1143 suser(sopt->sopt_p) != 0) ? 0 : 1;
1144 req = mtod(m, caddr_t);
1145 optname = sopt->sopt_name;
1146 error = ipsec4_set_policy(inp, optname, req, priv);
1147 m_freem(m);
1148 break;
1149 }
1150#endif /*IPSEC*/
1151
1152 default:
1153 error = ENOPROTOOPT;
1154 break;
1155 }
1156 break;
1157
1158 case SOPT_GET:
1159 switch (sopt->sopt_name) {
--- 10 unchanged lines hidden (view full) ---
1170
1171 case IP_TOS:
1172 case IP_TTL:
1173 case IP_RECVOPTS:
1174 case IP_RECVRETOPTS:
1175 case IP_RECVDSTADDR:
1176 case IP_RECVIF:
1177 case IP_PORTRANGE:
1178#if defined(NFAITH) && NFAITH > 0
1179 case IP_FAITH:
1180#endif
1181 switch (sopt->sopt_name) {
1182
1183 case IP_TOS:
1184 optval = inp->inp_ip_tos;
1185 break;
1186
1187 case IP_TTL:
1188 optval = inp->inp_ip_ttl;
--- 20 unchanged lines hidden (view full) ---
1209 case IP_PORTRANGE:
1210 if (inp->inp_flags & INP_HIGHPORT)
1211 optval = IP_PORTRANGE_HIGH;
1212 else if (inp->inp_flags & INP_LOWPORT)
1213 optval = IP_PORTRANGE_LOW;
1214 else
1215 optval = 0;
1216 break;
1217
1218#if defined(NFAITH) && NFAITH > 0
1219 case IP_FAITH:
1220 optval = OPTBIT(INP_FAITH);
1221 break;
1222#endif
1223 }
1224 error = sooptcopyout(sopt, &optval, sizeof optval);
1225 break;
1226
1227 case IP_MULTICAST_IF:
1228 case IP_MULTICAST_VIF:
1229 case IP_MULTICAST_TTL:
1230 case IP_MULTICAST_LOOP:
1231 case IP_ADD_MEMBERSHIP:
1232 case IP_DROP_MEMBERSHIP:
1233 error = ip_getmoptions(sopt, inp->inp_moptions);
1234 break;
1235
1236#ifdef IPSEC
1237 case IP_IPSEC_POLICY:
1238 {
1239 struct mbuf *m;
1240 caddr_t req = NULL;
1241
1242 if (m != 0)
1243 req = mtod(m, caddr_t);
1244 error = ipsec4_get_policy(sotoinpcb(so), req, &m);
1245 if (error == 0)
1246 error = soopt_mcopyout(sopt, m); /* XXX */
1247 m_freem(m);
1248 break;
1249 }
1250#endif /*IPSEC*/
1251
1252 default:
1253 error = ENOPROTOOPT;
1254 break;
1255 }
1256 break;
1257 }
1258 return (error);
1259}
--- 543 unchanged lines hidden ---
2 * Copyright (c) 1982, 1986, 1988, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
--- 17 unchanged lines hidden (view full) ---
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
34 * $FreeBSD: head/sys/netinet/ip_output.c 55009 1999-12-22 19:13:38Z shin $
35 */
36
37#define _IP_VHL
38
39#include "opt_ipfw.h"
40#include "opt_ipdn.h"
41#include "opt_ipdivert.h"
42#include "opt_ipfilter.h"
43#include "opt_ipsec.h"
44
45#include <sys/param.h>
46#include <sys/systm.h>
47#include <sys/kernel.h>
48#include <sys/malloc.h>
49#include <sys/mbuf.h>
50#include <sys/protosw.h>
51#include <sys/socket.h>
52#include <sys/socketvar.h>
53#include <sys/proc.h>
54
55#include <net/if.h>
56#include <net/route.h>
57
58#include <netinet/in.h>
59#include <netinet/in_systm.h>
60#include <netinet/ip.h>
61#include <netinet/in_pcb.h>
62#include <netinet/in_var.h>
63#include <netinet/ip_var.h>
64
65#include "faith.h"
66
67#ifdef vax
68#include <machine/mtpr.h>
69#endif
70#include <machine/in_cksum.h>
71
72static MALLOC_DEFINE(M_IPMOPTS, "ip_moptions", "internet multicast options");
73
74#ifdef IPSEC
75#include <netinet6/ipsec.h>
76#include <netkey/key.h>
77#ifdef IPSEC_DEBUG
78#include <netkey/key_debug.h>
79#else
80#define KEYDEBUG(lev,arg)
81#endif
82#endif /*IPSEC*/
83
84#include <netinet/ip_fw.h>
85
86#ifdef DUMMYNET
87#include <netinet/ip_dummynet.h>
88#endif
89
90#ifdef IPFIREWALL_FORWARD_DEBUG
91#define print_ip(a) printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\
--- 40 unchanged lines hidden (view full) ---
132 struct ip *ip, *mhip;
133 struct ifnet *ifp;
134 struct mbuf *m = m0;
135 int hlen = sizeof (struct ip);
136 int len, off, error = 0;
137 struct sockaddr_in *dst;
138 struct in_ifaddr *ia;
139 int isbroadcast;
140#ifdef IPSEC
141 struct route iproute;
142 struct socket *so;
143 struct secpolicy *sp = NULL;
144#endif
145 u_int16_t divert_cookie; /* firewall cookie */
146#ifdef IPFIREWALL_FORWARD
147 int fwd_rewrite_src = 0;
148#endif
149 struct ip_fw_chain *rule = NULL;
150
151#ifdef IPDIVERT
152 /* Get and reset firewall cookie */
153 divert_cookie = ip_divert_cookie;
154 ip_divert_cookie = 0;
155#else
156 divert_cookie = 0;
157#endif
158
159#ifdef IPSEC
160 /*
161 * NOTE: If IP_SOCKINMRCVIF flag is set, 'socket *' is kept in
162 * m->m_pkthdr.rcvif for later IPSEC check. In this case,
163 * m->m_pkthdr will be NULL cleared after the contents is saved in
164 * 'so'.
165 * NULL clearance of rcvif should be natural because the packet should
166 * have been sent from my own socket and has no rcvif in this case.
167 * It is also necessary because someone might consider it as
168 * 'ifnet *', and cause SEGV.
169 */
170 if ((flags & IP_SOCKINMRCVIF) != 0) {
171#if defined(IPFIREWALL) && defined(DUMMYNET)
172 if (m->m_type == MT_DUMMYNET) {
173 so = (struct socket *)m->m_next->m_pkthdr.rcvif;
174 m->m_next->m_pkthdr.rcvif = NULL;
175 } else
176#endif
177 {
178 so = (struct socket *)m->m_pkthdr.rcvif;
179 m->m_pkthdr.rcvif = NULL;
180 }
181 } else
182 so = NULL;
183#endif /*IPSEC*/
184
185#if defined(IPFIREWALL) && defined(DUMMYNET)
186 /*
187 * dummynet packet are prepended a vestigial mbuf with
188 * m_type = MT_DUMMYNET and m_data pointing to the matching
189 * rule.
190 */
191 if (m->m_type == MT_DUMMYNET) {
192 /*
193 * the packet was already tagged, so part of the
194 * processing was already done, and we need to go down.
195 * opt, flags and imo have already been used, and now
196 * they are used to hold ifp, dst and NULL, respectively.
197 */
198 rule = (struct ip_fw_chain *)(m->m_data) ;
199 dst = (struct sockaddr_in *)((struct dn_pkt *)m)->dn_dst;
200 m0 = m = m->m_next ;
201 ip = mtod(m, struct ip *);
202 ifp = (struct ifnet *)opt;
203 hlen = IP_VHL_HL(ip->ip_vhl) << 2 ;
204 opt = NULL ;
205 goto sendit;
206 } else
207 rule = NULL ;
208#endif
209
210#ifdef DIAGNOSTIC
211 if ((m->m_flags & M_PKTHDR) == 0)
212 panic("ip_output no HDR");
--- 281 unchanged lines hidden (view full) ---
494 * pass the pkt to dummynet. Need to include
495 * pipe number, m, ifp, ro, dst because these are
496 * not recomputed in the next pass.
497 * All other parameters have been already used and
498 * so they are not needed anymore.
499 * XXX note: if the ifp or ro entry are deleted
500 * while a pkt is in dummynet, we are in trouble!
501 */
502 dummynet_io(off & 0xffff, DN_TO_IP_OUT, m,ifp,ro,dst,rule,
503 flags);
504 goto done;
505 }
506#endif
507#ifdef IPDIVERT
508 if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) {
509 struct mbuf *clone = NULL;
510
511 /* Clone packet if we're doing a 'tee' */
--- 125 unchanged lines hidden (view full) ---
637 * we have to drop the pkt
638 */
639 m_freem(m);
640 error = EACCES; /* not sure this is the right error msg */
641 goto done;
642 }
643
644pass:
645#ifdef IPSEC
646 /* get SP for this packet */
647 if (so == NULL)
648 sp = ipsec4_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, flags, &error);
649 else
650 sp = ipsec4_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
651
652 if (sp == NULL) {
653 ipsecstat.out_inval++;
654 goto bad;
655 }
656
657 error = 0;
658
659 /* check policy */
660 switch (sp->policy) {
661 case IPSEC_POLICY_DISCARD:
662 /*
663 * This packet is just discarded.
664 */
665 ipsecstat.out_polvio++;
666 goto bad;
667
668 case IPSEC_POLICY_BYPASS:
669 case IPSEC_POLICY_NONE:
670 /* no need to do IPsec. */
671 goto skip_ipsec;
672
673 case IPSEC_POLICY_IPSEC:
674 if (sp->req == NULL) {
675 /* XXX should be panic ? */
676 printf("ip_output: No IPsec request specified.\n");
677 error = EINVAL;
678 goto bad;
679 }
680 break;
681
682 case IPSEC_POLICY_ENTRUST:
683 default:
684 printf("ip_output: Invalid policy found. %d\n", sp->policy);
685 }
686
687 ip->ip_len = htons((u_short)ip->ip_len);
688 ip->ip_off = htons((u_short)ip->ip_off);
689 ip->ip_sum = 0;
690
691 {
692 struct ipsec_output_state state;
693 bzero(&state, sizeof(state));
694 state.m = m;
695 if (flags & IP_ROUTETOIF) {
696 state.ro = &iproute;
697 bzero(&iproute, sizeof(iproute));
698 } else
699 state.ro = ro;
700 state.dst = (struct sockaddr *)dst;
701
702 error = ipsec4_output(&state, sp, flags);
703
704 m = state.m;
705 if (flags & IP_ROUTETOIF) {
706 /*
707 * if we have tunnel mode SA, we may need to ignore
708 * IP_ROUTETOIF.
709 */
710 if (state.ro != &iproute || state.ro->ro_rt != NULL) {
711 flags &= ~IP_ROUTETOIF;
712 ro = state.ro;
713 }
714 } else
715 ro = state.ro;
716 dst = (struct sockaddr_in *)state.dst;
717 if (error) {
718 /* mbuf is already reclaimed in ipsec4_output. */
719 m0 = NULL;
720 switch (error) {
721 case EHOSTUNREACH:
722 case ENETUNREACH:
723 case EMSGSIZE:
724 case ENOBUFS:
725 case ENOMEM:
726 break;
727 default:
728 printf("ip4_output (ipsec): error code %d\n", error);
729 /*fall through*/
730 case ENOENT:
731 /* don't show these error codes to the user */
732 error = 0;
733 break;
734 }
735 goto bad;
736 }
737 }
738
739 /* be sure to update variables that are affected by ipsec4_output() */
740 ip = mtod(m, struct ip *);
741#ifdef _IP_VHL
742 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
743#else
744 hlen = ip->ip_hl << 2;
745#endif
746 if (ro->ro_rt == NULL) {
747 if ((flags & IP_ROUTETOIF) == 0) {
748 printf("ip_output: "
749 "can't update route after IPsec processing\n");
750 error = EHOSTUNREACH; /*XXX*/
751 goto bad;
752 }
753 } else {
754 /* nobody uses ia beyond here */
755 ifp = ro->ro_rt->rt_ifp;
756 }
757
758 /* make it flipped, again. */
759 ip->ip_len = ntohs((u_short)ip->ip_len);
760 ip->ip_off = ntohs((u_short)ip->ip_off);
761skip_ipsec:
762#endif /*IPSEC*/
763
764 /*
765 * If small enough for interface, can just send directly.
766 */
767 if ((u_short)ip->ip_len <= ifp->if_mtu) {
768 ip->ip_len = htons((u_short)ip->ip_len);
769 ip->ip_off = htons((u_short)ip->ip_off);
770 ip->ip_sum = 0;
771 if (ip->ip_vhl == IP_VHL_BORING) {
--- 111 unchanged lines hidden (view full) ---
883 else
884 m_freem(m);
885 }
886
887 if (error == 0)
888 ipstat.ips_fragmented++;
889 }
890done:
891#ifdef IPSEC
892 if (ro == &iproute && ro->ro_rt) {
893 RTFREE(ro->ro_rt);
894 ro->ro_rt = NULL;
895 }
896 if (sp != NULL) {
897 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
898 printf("DP ip_output call free SP:%p\n", sp));
899 key_freesp(sp);
900 }
901#endif /* IPSEC */
902 return (error);
903bad:
904 m_freem(m0);
905 goto done;
906}
907
908/*
909 * Insert IP options into preformed packet.
--- 128 unchanged lines hidden (view full) ---
1038 }
1039
1040 case IP_TOS:
1041 case IP_TTL:
1042 case IP_RECVOPTS:
1043 case IP_RECVRETOPTS:
1044 case IP_RECVDSTADDR:
1045 case IP_RECVIF:
1046#if defined(NFAITH) && NFAITH > 0
1047 case IP_FAITH:
1048#endif
1049 error = sooptcopyin(sopt, &optval, sizeof optval,
1050 sizeof optval);
1051 if (error)
1052 break;
1053
1054 switch (sopt->sopt_name) {
1055 case IP_TOS:
1056 inp->inp_ip_tos = optval;
--- 18 unchanged lines hidden (view full) ---
1075
1076 case IP_RECVDSTADDR:
1077 OPTSET(INP_RECVDSTADDR);
1078 break;
1079
1080 case IP_RECVIF:
1081 OPTSET(INP_RECVIF);
1082 break;
1083
1084#if defined(NFAITH) && NFAITH > 0
1085 case IP_FAITH:
1086 OPTSET(INP_FAITH);
1087 break;
1088#endif
1089 }
1090 break;
1091#undef OPTSET
1092
1093 case IP_MULTICAST_IF:
1094 case IP_MULTICAST_VIF:
1095 case IP_MULTICAST_TTL:
1096 case IP_MULTICAST_LOOP:
--- 25 unchanged lines hidden (view full) ---
1122 break;
1123
1124 default:
1125 error = EINVAL;
1126 break;
1127 }
1128 break;
1129
1130#ifdef IPSEC
1131 case IP_IPSEC_POLICY:
1132 {
1133 caddr_t req;
1134 int priv;
1135 struct mbuf *m;
1136 int optname;
1137
1138 if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
1139 break;
1140 if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
1141 break;
1142 priv = (sopt->sopt_p != NULL &&
1143 suser(sopt->sopt_p) != 0) ? 0 : 1;
1144 req = mtod(m, caddr_t);
1145 optname = sopt->sopt_name;
1146 error = ipsec4_set_policy(inp, optname, req, priv);
1147 m_freem(m);
1148 break;
1149 }
1150#endif /*IPSEC*/
1151
1152 default:
1153 error = ENOPROTOOPT;
1154 break;
1155 }
1156 break;
1157
1158 case SOPT_GET:
1159 switch (sopt->sopt_name) {
--- 10 unchanged lines hidden (view full) ---
1170
1171 case IP_TOS:
1172 case IP_TTL:
1173 case IP_RECVOPTS:
1174 case IP_RECVRETOPTS:
1175 case IP_RECVDSTADDR:
1176 case IP_RECVIF:
1177 case IP_PORTRANGE:
1178#if defined(NFAITH) && NFAITH > 0
1179 case IP_FAITH:
1180#endif
1181 switch (sopt->sopt_name) {
1182
1183 case IP_TOS:
1184 optval = inp->inp_ip_tos;
1185 break;
1186
1187 case IP_TTL:
1188 optval = inp->inp_ip_ttl;
--- 20 unchanged lines hidden (view full) ---
1209 case IP_PORTRANGE:
1210 if (inp->inp_flags & INP_HIGHPORT)
1211 optval = IP_PORTRANGE_HIGH;
1212 else if (inp->inp_flags & INP_LOWPORT)
1213 optval = IP_PORTRANGE_LOW;
1214 else
1215 optval = 0;
1216 break;
1217
1218#if defined(NFAITH) && NFAITH > 0
1219 case IP_FAITH:
1220 optval = OPTBIT(INP_FAITH);
1221 break;
1222#endif
1223 }
1224 error = sooptcopyout(sopt, &optval, sizeof optval);
1225 break;
1226
1227 case IP_MULTICAST_IF:
1228 case IP_MULTICAST_VIF:
1229 case IP_MULTICAST_TTL:
1230 case IP_MULTICAST_LOOP:
1231 case IP_ADD_MEMBERSHIP:
1232 case IP_DROP_MEMBERSHIP:
1233 error = ip_getmoptions(sopt, inp->inp_moptions);
1234 break;
1235
1236#ifdef IPSEC
1237 case IP_IPSEC_POLICY:
1238 {
1239 struct mbuf *m;
1240 caddr_t req = NULL;
1241
1242 if (m != 0)
1243 req = mtod(m, caddr_t);
1244 error = ipsec4_get_policy(sotoinpcb(so), req, &m);
1245 if (error == 0)
1246 error = soopt_mcopyout(sopt, m); /* XXX */
1247 m_freem(m);
1248 break;
1249 }
1250#endif /*IPSEC*/
1251
1252 default:
1253 error = ENOPROTOOPT;
1254 break;
1255 }
1256 break;
1257 }
1258 return (error);
1259}
--- 543 unchanged lines hidden ---