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 --- |