Deleted Added
full compact
ip_output.c (133720) ip_output.c (133920)
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

--- 13 unchanged lines hidden (view full) ---

22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
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

--- 13 unchanged lines hidden (view full) ---

22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
30 * $FreeBSD: head/sys/netinet/ip_output.c 133720 2004-08-14 15:32:40Z dwmalone $
30 * $FreeBSD: head/sys/netinet/ip_output.c 133920 2004-08-17 22:05:54Z andre $
31 */
32
33#include "opt_ipfw.h"
31 */
32
33#include "opt_ipfw.h"
34#include "opt_ipdn.h"
35#include "opt_ipdivert.h"
36#include "opt_ipfilter.h"
37#include "opt_ipsec.h"
38#include "opt_mac.h"
39#include "opt_pfil_hooks.h"
40#include "opt_mbuf_stress_test.h"
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/kernel.h>
45#include <sys/mac.h>
46#include <sys/malloc.h>
47#include <sys/mbuf.h>
48#include <sys/protosw.h>
49#include <sys/socket.h>
50#include <sys/socketvar.h>
51#include <sys/sysctl.h>
52
53#include <net/if.h>
34#include "opt_ipsec.h"
35#include "opt_mac.h"
36#include "opt_pfil_hooks.h"
37#include "opt_mbuf_stress_test.h"
38
39#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/kernel.h>
42#include <sys/mac.h>
43#include <sys/malloc.h>
44#include <sys/mbuf.h>
45#include <sys/protosw.h>
46#include <sys/socket.h>
47#include <sys/socketvar.h>
48#include <sys/sysctl.h>
49
50#include <net/if.h>
51#include <net/netisr.h>
54#include <net/route.h>
55
56#include <netinet/in.h>
57#include <netinet/in_systm.h>
58#include <netinet/ip.h>
59#include <netinet/in_pcb.h>
60#include <netinet/in_var.h>
61#include <netinet/ip_var.h>

--- 17 unchanged lines hidden (view full) ---

79#endif /*IPSEC*/
80
81#ifdef FAST_IPSEC
82#include <netipsec/ipsec.h>
83#include <netipsec/xform.h>
84#include <netipsec/key.h>
85#endif /*FAST_IPSEC*/
86
52#include <net/route.h>
53
54#include <netinet/in.h>
55#include <netinet/in_systm.h>
56#include <netinet/ip.h>
57#include <netinet/in_pcb.h>
58#include <netinet/in_var.h>
59#include <netinet/ip_var.h>

--- 17 unchanged lines hidden (view full) ---

77#endif /*IPSEC*/
78
79#ifdef FAST_IPSEC
80#include <netipsec/ipsec.h>
81#include <netipsec/xform.h>
82#include <netipsec/key.h>
83#endif /*FAST_IPSEC*/
84
87#include <netinet/ip_fw.h>
88#include <netinet/ip_divert.h>
89#include <netinet/ip_dummynet.h>
90
91#define print_ip(x, a, y) printf("%s %d.%d.%d.%d%s",\
92 x, (ntohl(a.s_addr)>>24)&0xFF,\
93 (ntohl(a.s_addr)>>16)&0xFF,\
94 (ntohl(a.s_addr)>>8)&0xFF,\
95 (ntohl(a.s_addr))&0xFF, y);
96
97u_short ip_id;
98

--- 29 unchanged lines hidden (view full) ---

128int
129ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
130 int flags, struct ip_moptions *imo, struct inpcb *inp)
131{
132 struct ip *ip;
133 struct ifnet *ifp = NULL; /* keep compiler happy */
134 struct mbuf *m0;
135 int hlen = sizeof (struct ip);
85#define print_ip(x, a, y) printf("%s %d.%d.%d.%d%s",\
86 x, (ntohl(a.s_addr)>>24)&0xFF,\
87 (ntohl(a.s_addr)>>16)&0xFF,\
88 (ntohl(a.s_addr)>>8)&0xFF,\
89 (ntohl(a.s_addr))&0xFF, y);
90
91u_short ip_id;
92

--- 29 unchanged lines hidden (view full) ---

122int
123ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
124 int flags, struct ip_moptions *imo, struct inpcb *inp)
125{
126 struct ip *ip;
127 struct ifnet *ifp = NULL; /* keep compiler happy */
128 struct mbuf *m0;
129 int hlen = sizeof (struct ip);
136 int len, off, error = 0;
130 int len, error = 0;
137 struct sockaddr_in *dst = NULL; /* keep compiler happy */
138 struct in_ifaddr *ia = NULL;
139 int isbroadcast, sw_csum;
131 struct sockaddr_in *dst = NULL; /* keep compiler happy */
132 struct in_ifaddr *ia = NULL;
133 int isbroadcast, sw_csum;
140 struct in_addr pkt_dst;
141 struct route iproute;
134 struct route iproute;
142 struct m_tag *mtag, *dummytag;
135 struct in_addr odst;
136#ifdef IPFIREWALL_FORWARD
137 struct m_tag *fwd_tag = NULL;
138#endif
143#ifdef IPSEC
144 struct secpolicy *sp = NULL;
145#endif
146#ifdef FAST_IPSEC
147 struct secpolicy *sp = NULL;
148 struct tdb_ident *tdbi;
139#ifdef IPSEC
140 struct secpolicy *sp = NULL;
141#endif
142#ifdef FAST_IPSEC
143 struct secpolicy *sp = NULL;
144 struct tdb_ident *tdbi;
145 struct m_tag *mtag;
149 int s;
150#endif /* FAST_IPSEC */
146 int s;
147#endif /* FAST_IPSEC */
151 struct ip_fw_args args;
152 int src_was_INADDR_ANY = 0; /* as the name says... */
153
148
154 args.eh = NULL;
155 args.rule = NULL;
156
157 M_ASSERTPKTHDR(m);
158
149 M_ASSERTPKTHDR(m);
150
159 args.next_hop = m_claim_next(m, PACKET_TAG_IPFORWARD);
160 dummytag = m_tag_find(m, PACKET_TAG_DUMMYNET, NULL);
161 if (dummytag != NULL) {
162 struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
163 /*
164 * Prevent lower layers from finding the tag
165 * Cleanup and free is done below
166 */
167 m_tag_unlink(m, dummytag);
168 /*
169 * the packet was already tagged, so part of the
170 * processing was already done, and we need to go down.
171 * Get parameters from the header.
172 */
173 args.rule = dt->rule;
174 ro = &(dt->ro);
175 dst = dt->dn_dst;
176 ifp = dt->ifp;
177 }
178
179 if (ro == NULL) {
180 ro = &iproute;
181 bzero(ro, sizeof (*ro));
182 }
183
184 if (inp != NULL)
185 INP_LOCK_ASSERT(inp);
186
151 if (ro == NULL) {
152 ro = &iproute;
153 bzero(ro, sizeof (*ro));
154 }
155
156 if (inp != NULL)
157 INP_LOCK_ASSERT(inp);
158
187 if (args.rule != NULL) { /* dummynet already saw us */
188 ip = mtod(m, struct ip *);
189 hlen = ip->ip_hl << 2 ;
190 if (ro->ro_rt)
191 ia = ifatoia(ro->ro_rt->rt_ifa);
192 goto sendit;
193 }
194
195 if (opt) {
196 len = 0;
197 m = ip_insertoptions(m, opt, &len);
198 if (len != 0)
199 hlen = len;
200 }
201 ip = mtod(m, struct ip *);
159 if (opt) {
160 len = 0;
161 m = ip_insertoptions(m, opt, &len);
162 if (len != 0)
163 hlen = len;
164 }
165 ip = mtod(m, struct ip *);
202 pkt_dst = args.next_hop ? args.next_hop->sin_addr : ip->ip_dst;
203
204 /*
205 * Fill in IP header. If we are not allowing fragmentation,
206 * then the ip_id field is meaningless, but we don't set it
207 * to zero. Doing so causes various problems when devices along
208 * the path (routers, load balancers, firewalls, etc.) illegally
209 * disable DF on our packet. Note that a 16-bit counter
210 * will wrap around in less than 10 seconds at 100 Mbit/s on a

--- 6 unchanged lines hidden (view full) ---

217 ip->ip_hl = hlen >> 2;
218 ip->ip_id = ip_newid();
219 ipstat.ips_localout++;
220 } else {
221 hlen = ip->ip_hl << 2;
222 }
223
224 dst = (struct sockaddr_in *)&ro->ro_dst;
166
167 /*
168 * Fill in IP header. If we are not allowing fragmentation,
169 * then the ip_id field is meaningless, but we don't set it
170 * to zero. Doing so causes various problems when devices along
171 * the path (routers, load balancers, firewalls, etc.) illegally
172 * disable DF on our packet. Note that a 16-bit counter
173 * will wrap around in less than 10 seconds at 100 Mbit/s on a

--- 6 unchanged lines hidden (view full) ---

180 ip->ip_hl = hlen >> 2;
181 ip->ip_id = ip_newid();
182 ipstat.ips_localout++;
183 } else {
184 hlen = ip->ip_hl << 2;
185 }
186
187 dst = (struct sockaddr_in *)&ro->ro_dst;
188again:
225 /*
226 * If there is a cached route,
227 * check that it is to the same destination
228 * and is still up. If not, free it and try again.
229 * The address family should also be checked in case of sharing the
230 * cache with IPv6.
231 */
232 if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
233 dst->sin_family != AF_INET ||
189 /*
190 * If there is a cached route,
191 * check that it is to the same destination
192 * and is still up. If not, free it and try again.
193 * The address family should also be checked in case of sharing the
194 * cache with IPv6.
195 */
196 if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
197 dst->sin_family != AF_INET ||
234 dst->sin_addr.s_addr != pkt_dst.s_addr)) {
198 dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
235 RTFREE(ro->ro_rt);
236 ro->ro_rt = (struct rtentry *)0;
237 }
199 RTFREE(ro->ro_rt);
200 ro->ro_rt = (struct rtentry *)0;
201 }
202#ifdef IPFIREWALL_FORWARD
203 if (ro->ro_rt == NULL && fwd_tag == NULL) {
204#else
238 if (ro->ro_rt == NULL) {
205 if (ro->ro_rt == NULL) {
206#endif
239 bzero(dst, sizeof(*dst));
240 dst->sin_family = AF_INET;
241 dst->sin_len = sizeof(*dst);
207 bzero(dst, sizeof(*dst));
208 dst->sin_family = AF_INET;
209 dst->sin_len = sizeof(*dst);
242 dst->sin_addr = pkt_dst;
210 dst->sin_addr = ip->ip_dst;
243 }
244 /*
245 * If routing to interface only,
246 * short circuit routing lookup.
247 */
248 if (flags & IP_ROUTETOIF) {
249 if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL &&
250 (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == NULL) {

--- 31 unchanged lines hidden (view full) ---

282 ro->ro_rt->rt_rmx.rmx_pksent++;
283 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
284 dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
285 if (ro->ro_rt->rt_flags & RTF_HOST)
286 isbroadcast = (ro->ro_rt->rt_flags & RTF_BROADCAST);
287 else
288 isbroadcast = in_broadcast(dst->sin_addr, ifp);
289 }
211 }
212 /*
213 * If routing to interface only,
214 * short circuit routing lookup.
215 */
216 if (flags & IP_ROUTETOIF) {
217 if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL &&
218 (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == NULL) {

--- 31 unchanged lines hidden (view full) ---

250 ro->ro_rt->rt_rmx.rmx_pksent++;
251 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
252 dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
253 if (ro->ro_rt->rt_flags & RTF_HOST)
254 isbroadcast = (ro->ro_rt->rt_flags & RTF_BROADCAST);
255 else
256 isbroadcast = in_broadcast(dst->sin_addr, ifp);
257 }
290 if (IN_MULTICAST(ntohl(pkt_dst.s_addr))) {
258 if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
291 struct in_multi *inm;
292
293 m->m_flags |= M_MCAST;
294 /*
295 * IP destination address is multicast. Make sure "dst"
296 * still points to the address in "ro". (It may have been
297 * changed to point to a gateway address, above.)
298 */

--- 25 unchanged lines hidden (view full) ---

324 * of outgoing interface.
325 */
326 if (ip->ip_src.s_addr == INADDR_ANY) {
327 /* Interface may have no addresses. */
328 if (ia != NULL)
329 ip->ip_src = IA_SIN(ia)->sin_addr;
330 }
331
259 struct in_multi *inm;
260
261 m->m_flags |= M_MCAST;
262 /*
263 * IP destination address is multicast. Make sure "dst"
264 * still points to the address in "ro". (It may have been
265 * changed to point to a gateway address, above.)
266 */

--- 25 unchanged lines hidden (view full) ---

292 * of outgoing interface.
293 */
294 if (ip->ip_src.s_addr == INADDR_ANY) {
295 /* Interface may have no addresses. */
296 if (ia != NULL)
297 ip->ip_src = IA_SIN(ia)->sin_addr;
298 }
299
332 IN_LOOKUP_MULTI(pkt_dst, ifp, inm);
300 IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
333 if (inm != NULL &&
334 (imo == NULL || imo->imo_multicast_loop)) {
335 /*
336 * If we belong to the destination multicast group
337 * on the outgoing interface, and the caller did not
338 * forbid loopback, loop back a copy.
339 */
340 ip_mloopback(ifp, m, dst, hlen);

--- 49 unchanged lines hidden (view full) ---

390 * of the outoing interface. In case, keep note we did that, so
391 * if the the firewall changes the next-hop causing the output
392 * interface to change, we can fix that.
393 */
394 if (ip->ip_src.s_addr == INADDR_ANY) {
395 /* Interface may have no addresses. */
396 if (ia != NULL) {
397 ip->ip_src = IA_SIN(ia)->sin_addr;
301 if (inm != NULL &&
302 (imo == NULL || imo->imo_multicast_loop)) {
303 /*
304 * If we belong to the destination multicast group
305 * on the outgoing interface, and the caller did not
306 * forbid loopback, loop back a copy.
307 */
308 ip_mloopback(ifp, m, dst, hlen);

--- 49 unchanged lines hidden (view full) ---

358 * of the outoing interface. In case, keep note we did that, so
359 * if the the firewall changes the next-hop causing the output
360 * interface to change, we can fix that.
361 */
362 if (ip->ip_src.s_addr == INADDR_ANY) {
363 /* Interface may have no addresses. */
364 if (ia != NULL) {
365 ip->ip_src = IA_SIN(ia)->sin_addr;
398 src_was_INADDR_ANY = 1;
399 }
400 }
401#endif /* notdef */
402#ifdef ALTQ
403 /*
404 * disable packet drop hack.
405 * packetdrop should be done by queueing.
406 */

--- 281 unchanged lines hidden (view full) ---

688 error = EHOSTUNREACH;
689 goto bad;
690 }
691#endif
692 }
693spd_done:
694#endif /* FAST_IPSEC */
695
366 }
367 }
368#endif /* notdef */
369#ifdef ALTQ
370 /*
371 * disable packet drop hack.
372 * packetdrop should be done by queueing.
373 */

--- 281 unchanged lines hidden (view full) ---

655 error = EHOSTUNREACH;
656 goto bad;
657 }
658#endif
659 }
660spd_done:
661#endif /* FAST_IPSEC */
662
696 /*
697 * IpHack's section.
698 * - Xlate: translate packet's addr/port (NAT).
699 * - Firewall: deny/allow/etc.
700 * - Wrap: fake packet's addr/port <unimpl.>
701 * - Encapsulate: put it in another IP and send out. <unimp.>
702 */
703#ifdef PFIL_HOOKS
704 /*
705 * Run through list of hooks for output packets.
706 */
663#ifdef PFIL_HOOKS
664 /*
665 * Run through list of hooks for output packets.
666 */
667 odst.s_addr = ip->ip_dst.s_addr;
707 error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT);
708 if (error != 0 || m == NULL)
709 goto done;
668 error = pfil_run_hooks(&inet_pfil_hook, &m, ifp, PFIL_OUT);
669 if (error != 0 || m == NULL)
670 goto done;
671
710 ip = mtod(m, struct ip *);
672 ip = mtod(m, struct ip *);
711#endif /* PFIL_HOOKS */
712
673
713 /*
714 * Check with the firewall...
715 * but not if we are already being fwd'd from a firewall.
716 */
717 if (fw_enable && IPFW_LOADED && !args.next_hop) {
718 struct sockaddr_in *old = dst;
674 /* See if destination IP address was changed by packet filter. */
675 if (odst.s_addr != ip->ip_dst.s_addr) {
676 m->m_flags |= M_SKIP_FIREWALL;
677 if (in_localip(ip->ip_dst)) {
678 m->m_flags |= M_FASTFWD_OURS;
679 if (m->m_pkthdr.rcvif == NULL)
680 m->m_pkthdr.rcvif = ifunit("lo0");
681 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
682 m->m_pkthdr.csum_flags |=
683 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
684 m->m_pkthdr.csum_data = 0xffff;
685 }
686 m->m_pkthdr.csum_flags |=
687 CSUM_IP_CHECKED | CSUM_IP_VALID;
719
688
720 args.m = m;
721 args.next_hop = dst;
722 args.oif = ifp;
723 off = ip_fw_chk_ptr(&args);
724 m = args.m;
725 dst = args.next_hop;
726
727 /*
728 * On return we must do the following:
729 * m == NULL -> drop the pkt (old interface, deprecated)
730 * (off & IP_FW_PORT_DENY_FLAG) -> drop the pkt (new interface)
731 * 1<=off<= 0xffff -> DIVERT
732 * (off & IP_FW_PORT_DYNT_FLAG) -> send to a DUMMYNET pipe
733 * (off & IP_FW_PORT_TEE_FLAG) -> TEE the packet
734 * dst != old -> IPFIREWALL_FORWARD
735 * off==0, dst==old -> accept
736 * If some of the above modules are not compiled in, then
737 * we should't have to check the corresponding condition
738 * (because the ipfw control socket should not accept
739 * unsupported rules), but better play safe and drop
740 * packets in case of doubt.
741 */
742 if ( (off & IP_FW_PORT_DENY_FLAG) || m == NULL) {
743 if (m)
744 m_freem(m);
745 error = EACCES;
689 error = netisr_queue(NETISR_IP, m);
746 goto done;
690 goto done;
747 }
748 ip = mtod(m, struct ip *);
749 if (off == 0 && dst == old) /* common case */
750 goto pass;
751 if (DUMMYNET_LOADED && (off & IP_FW_PORT_DYNT_FLAG) != 0) {
752 /*
753 * pass the pkt to dummynet. Need to include
754 * pipe number, m, ifp, ro, dst because these are
755 * not recomputed in the next pass.
756 * All other parameters have been already used and
757 * so they are not needed anymore.
758 * XXX note: if the ifp or ro entry are deleted
759 * while a pkt is in dummynet, we are in trouble!
760 */
761 args.ro = ro;
762 args.dst = dst;
763 args.flags = flags;
691 } else
692 goto again;
693 }
764
694
765 error = ip_dn_io_ptr(m, off & 0xffff, DN_TO_IP_OUT,
766 &args);
767 goto done;
695#ifdef IPFIREWALL_FORWARD
696 /* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */
697 if (m->m_flags & M_FASTFWD_OURS) {
698 if (m->m_pkthdr.rcvif == NULL)
699 m->m_pkthdr.rcvif = ifunit("lo0");
700 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
701 m->m_pkthdr.csum_flags |=
702 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
703 m->m_pkthdr.csum_data = 0xffff;
768 }
704 }
769#ifdef IPDIVERT
770 if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) {
771 struct mbuf *clone;
705 m->m_pkthdr.csum_flags |=
706 CSUM_IP_CHECKED | CSUM_IP_VALID;
772
707
773 /* Clone packet if we're doing a 'tee' */
774 if ((off & IP_FW_PORT_TEE_FLAG) != 0)
775 clone = divert_clone(m);
776 else
777 clone = NULL;
778
779 /* Restore packet header fields to original values */
780 ip->ip_len = htons(ip->ip_len);
781 ip->ip_off = htons(ip->ip_off);
782
783 /* Deliver packet to divert input routine */
784 divert_packet(m, 0);
785
786 /* If 'tee', continue with original packet */
787 if (clone != NULL) {
788 m = clone;
789 ip = mtod(m, struct ip *);
790 goto pass;
791 }
792 goto done;
708 error = netisr_queue(NETISR_IP, m);
709 goto done;
710 }
711 /* Or forward to some other address? */
712 fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
713 if (fwd_tag) {
714 if (!in_localip(ip->ip_src) && !in_localaddr(ip->ip_dst)) {
715 dst = (struct sockaddr_in *)&ro->ro_dst;
716 bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in));
717 m->m_flags |= M_SKIP_FIREWALL;
718 m_tag_delete(m, fwd_tag);
719 goto again;
720 } else {
721 m_tag_delete(m, fwd_tag);
722 /* Continue. */
793 }
723 }
724 }
794#endif
795
725#endif
726
796 /* IPFIREWALL_FORWARD */
797 /*
798 * Check dst to make sure it is directly reachable on the
799 * interface we previously thought it was.
800 * If it isn't (which may be likely in some situations) we have
801 * to re-route it (ie, find a route for the next-hop and the
802 * associated interface) and set them here. This is nested
803 * forwarding which in most cases is undesirable, except where
804 * such control is nigh impossible. So we do it here.
805 * And I'm babbling.
806 */
807 if (off == 0 && old != dst) { /* FORWARD, dst has changed */
808#if 0
809 /*
810 * XXX To improve readability, this block should be
811 * changed into a function call as below:
812 */
813 error = ip_ipforward(&m, &dst, &ifp);
814 if (error)
815 goto bad;
816 if (m == NULL) /* ip_input consumed the mbuf */
817 goto done;
818#else
819 struct in_ifaddr *ia;
727#endif /* PFIL_HOOKS */
820
728
821 /*
822 * XXX sro_fwd below is static, and a pointer
823 * to it gets passed to routines downstream.
824 * This could have surprisingly bad results in
825 * practice, because its content is overwritten
826 * by subsequent packets.
827 * XXX: Breaks on SMP and possibly preemption!
828 */
829 /* There must be a better way to do this next line... */
830 static struct route sro_fwd;
831 struct route *ro_fwd = &sro_fwd;
832
833#if 0
729#if 0
834 print_ip("IPFIREWALL_FORWARD: New dst ip: ",
835 dst->sin_addr, "\n");
836#endif
837
838 /*
839 * We need to figure out if we have been forwarded
840 * to a local socket. If so, then we should somehow
841 * "loop back" to ip_input, and get directed to the
842 * PCB as if we had received this packet. This is
843 * because it may be dificult to identify the packets
844 * you want to forward until they are being output
845 * and have selected an interface. (e.g. locally
846 * initiated packets) If we used the loopback inteface,
847 * we would not be able to control what happens
848 * as the packet runs through ip_input() as
849 * it is done through an ISR.
850 */
851 LIST_FOREACH(ia,
852 INADDR_HASH(dst->sin_addr.s_addr), ia_hash) {
853 /*
854 * If the addr to forward to is one
855 * of ours, we pretend to
856 * be the destination for this packet.
857 */
858 if (IA_SIN(ia)->sin_addr.s_addr ==
859 dst->sin_addr.s_addr)
860 break;
861 }
862 if (ia) { /* tell ip_input "dont filter" */
863 mtag = m_tag_get(
864 PACKET_TAG_IPFORWARD,
865 sizeof(struct sockaddr_in *), M_NOWAIT);
866 if (mtag == NULL) {
867 error = ENOBUFS;
868 goto bad;
869 }
870 *(struct sockaddr_in **)(mtag+1) =
871 args.next_hop;
872 m_tag_prepend(m, mtag);
873
874 if (m->m_pkthdr.rcvif == NULL)
875 m->m_pkthdr.rcvif = ifunit("lo0");
876 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
877 m->m_pkthdr.csum_flags |=
878 CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
879 m->m_pkthdr.csum_data = 0xffff;
880 }
881 m->m_pkthdr.csum_flags |=
882 CSUM_IP_CHECKED | CSUM_IP_VALID;
883 ip->ip_len = htons(ip->ip_len);
884 ip->ip_off = htons(ip->ip_off);
885 ip_input(m);
886 goto done;
887 }
888 /*
889 * Some of the logic for this was
890 * nicked from above.
891 */
892 bcopy(dst, &ro_fwd->ro_dst, sizeof(*dst));
893
894 ro_fwd->ro_rt = 0;
895 rtalloc_ign(ro_fwd, RTF_CLONING);
896
897 if (ro_fwd->ro_rt == NULL) {
898 ipstat.ips_noroute++;
899 error = EHOSTUNREACH;
900 goto bad;
901 }
902
903 ia = ifatoia(ro_fwd->ro_rt->rt_ifa);
904 ifp = ro_fwd->ro_rt->rt_ifp;
905 ro_fwd->ro_rt->rt_rmx.rmx_pksent++;
906 if (ro_fwd->ro_rt->rt_flags & RTF_GATEWAY)
907 dst = (struct sockaddr_in *)
908 ro_fwd->ro_rt->rt_gateway;
909 if (ro_fwd->ro_rt->rt_flags & RTF_HOST)
910 isbroadcast =
911 (ro_fwd->ro_rt->rt_flags & RTF_BROADCAST);
912 else
913 isbroadcast = in_broadcast(dst->sin_addr, ifp);
914 if (ro->ro_rt)
915 RTFREE(ro->ro_rt);
916 ro->ro_rt = ro_fwd->ro_rt;
917 dst = (struct sockaddr_in *)&ro_fwd->ro_dst;
918
919#endif /* ... block to be put into a function */
920 /*
921 * If we added a default src ip earlier,
922 * which would have been gotten from the-then
923 * interface, do it again, from the new one.
924 */
925 if (src_was_INADDR_ANY)
926 ip->ip_src = IA_SIN(ia)->sin_addr;
927 goto pass ;
928 }
929
930 /*
931 * if we get here, none of the above matches, and
932 * we have to drop the pkt
933 */
934 m_freem(m);
935 error = EACCES; /* not sure this is the right error msg */
936 goto done;
937 }
938
939pass:
730pass:
731#endif
940 /* 127/8 must not appear on wire - RFC1122. */
941 if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
942 (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
943 if ((ifp->if_flags & IFF_LOOPBACK) == 0) {
944 ipstat.ips_badaddr++;
945 error = EADDRNOTAVAIL;
946 goto bad;
947 }

--- 84 unchanged lines hidden (view full) ---

1032 }
1033
1034 if (error == 0)
1035 ipstat.ips_fragmented++;
1036
1037done:
1038 if (ro == &iproute && ro->ro_rt) {
1039 RTFREE(ro->ro_rt);
732 /* 127/8 must not appear on wire - RFC1122. */
733 if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
734 (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
735 if ((ifp->if_flags & IFF_LOOPBACK) == 0) {
736 ipstat.ips_badaddr++;
737 error = EADDRNOTAVAIL;
738 goto bad;
739 }

--- 84 unchanged lines hidden (view full) ---

824 }
825
826 if (error == 0)
827 ipstat.ips_fragmented++;
828
829done:
830 if (ro == &iproute && ro->ro_rt) {
831 RTFREE(ro->ro_rt);
1040 ro->ro_rt = NULL;
1041 }
832 }
1042 if (dummytag) {
1043 struct dn_pkt_tag *dt = (struct dn_pkt_tag *)(dummytag+1);
1044 if (dt->ro.ro_rt)
1045 RTFREE(dt->ro.ro_rt);
1046 m_tag_free(dummytag);
1047 }
1048#ifdef IPSEC
1049 if (sp != NULL) {
1050 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
1051 printf("DP ip_output call free SP:%p\n", sp));
1052 key_freesp(sp);
1053 }
1054#endif
1055#ifdef FAST_IPSEC

--- 1173 unchanged lines hidden ---
833#ifdef IPSEC
834 if (sp != NULL) {
835 KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
836 printf("DP ip_output call free SP:%p\n", sp));
837 key_freesp(sp);
838 }
839#endif
840#ifdef FAST_IPSEC

--- 1173 unchanged lines hidden ---