ip_output.c (286001) | ip_output.c (286028) |
---|---|
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 --- 16 unchanged lines hidden (view full) --- 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 */ 31 32#include <sys/cdefs.h> | 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 --- 16 unchanged lines hidden (view full) --- 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 */ 31 32#include <sys/cdefs.h> |
33__FBSDID("$FreeBSD: head/sys/netinet/ip_output.c 286001 2015-07-29 08:12:05Z ae $"); | 33__FBSDID("$FreeBSD: head/sys/netinet/ip_output.c 286028 2015-07-29 18:04:01Z eri $"); |
34 35#include "opt_inet.h" 36#include "opt_ipfw.h" 37#include "opt_ipsec.h" 38#include "opt_mbuf_stress_test.h" 39#include "opt_mpath.h" 40#include "opt_route.h" 41#include "opt_sctp.h" --- 59 unchanged lines hidden (view full) --- 101 102static void ip_mloopback 103 (struct ifnet *, struct mbuf *, struct sockaddr_in *, int); 104 105 106extern int in_mcast_loop; 107extern struct protosw inetsw[]; 108 | 34 35#include "opt_inet.h" 36#include "opt_ipfw.h" 37#include "opt_ipsec.h" 38#include "opt_mbuf_stress_test.h" 39#include "opt_mpath.h" 40#include "opt_route.h" 41#include "opt_sctp.h" --- 59 unchanged lines hidden (view full) --- 101 102static void ip_mloopback 103 (struct ifnet *, struct mbuf *, struct sockaddr_in *, int); 104 105 106extern int in_mcast_loop; 107extern struct protosw inetsw[]; 108 |
109static inline int 110ip_output_pfil(struct mbuf *m, struct ifnet *ifp, struct inpcb *inp, 111 struct sockaddr_in *dst, int *fibnum, int *error) 112{ 113 struct m_tag *fwd_tag = NULL; 114 struct in_addr odst; 115 struct ip *ip; 116 117 ip = mtod(m, struct ip *); 118 119 /* Run through list of hooks for output packets. */ 120 odst.s_addr = ip->ip_dst.s_addr; 121 *error = pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_OUT, inp); 122 if ((*error) != 0 || m == NULL) 123 return 1; /* Finished */ 124 125 ip = mtod(m, struct ip *); 126 127 /* See if destination IP address was changed by packet filter. */ 128 if (odst.s_addr != ip->ip_dst.s_addr) { 129 m->m_flags |= M_SKIP_FIREWALL; 130 /* If destination is now ourself drop to ip_input(). */ 131 if (in_localip(ip->ip_dst)) { 132 m->m_flags |= M_FASTFWD_OURS; 133 if (m->m_pkthdr.rcvif == NULL) 134 m->m_pkthdr.rcvif = V_loif; 135 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 136 m->m_pkthdr.csum_flags |= 137 CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 138 m->m_pkthdr.csum_data = 0xffff; 139 } 140 m->m_pkthdr.csum_flags |= 141 CSUM_IP_CHECKED | CSUM_IP_VALID; 142#ifdef SCTP 143 if (m->m_pkthdr.csum_flags & CSUM_SCTP) 144 m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; 145#endif 146 *error = netisr_queue(NETISR_IP, m); 147 return 1; /* Finished */ 148 } 149 150 bzero(dst, sizeof(*dst)); 151 dst->sin_family = AF_INET; 152 dst->sin_len = sizeof(*dst); 153 dst->sin_addr = ip->ip_dst; 154 155 return -1; /* Reloop */ 156 } 157 /* See if fib was changed by packet filter. */ 158 if ((*fibnum) != M_GETFIB(m)) { 159 m->m_flags |= M_SKIP_FIREWALL; 160 *fibnum = M_GETFIB(m); 161 return -1; /* Reloop for FIB change */ 162 } 163 164 /* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */ 165 if (m->m_flags & M_FASTFWD_OURS) { 166 if (m->m_pkthdr.rcvif == NULL) 167 m->m_pkthdr.rcvif = V_loif; 168 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 169 m->m_pkthdr.csum_flags |= 170 CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 171 m->m_pkthdr.csum_data = 0xffff; 172 } 173#ifdef SCTP 174 if (m->m_pkthdr.csum_flags & CSUM_SCTP) 175 m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; 176#endif 177 m->m_pkthdr.csum_flags |= 178 CSUM_IP_CHECKED | CSUM_IP_VALID; 179 180 *error = netisr_queue(NETISR_IP, m); 181 return 1; /* Finished */ 182 } 183 /* Or forward to some other address? */ 184 if ((m->m_flags & M_IP_NEXTHOP) && 185 ((fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL)) { 186 bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in)); 187 m->m_flags |= M_SKIP_FIREWALL; 188 m->m_flags &= ~M_IP_NEXTHOP; 189 m_tag_delete(m, fwd_tag); 190 191 return -1; /* Reloop for CHANGE of dst */ 192 } 193 194 return 0; 195} 196 |
|
109/* 110 * IP output. The packet in mbuf chain m contains a skeletal IP 111 * header (with len, off, ttl, proto, tos, src, dst). 112 * The mbuf chain containing the packet will be freed. 113 * The mbuf opt, if present, will not be freed. 114 * If route ro is present and has ro_rt initialized, route lookup would be 115 * skipped and ro->ro_rt would be used. If ro is present but ro->ro_rt is NULL, 116 * then result of route lookup is stored in ro->ro_rt. --- 14 unchanged lines hidden (view full) --- 131 int error = 0; 132 struct sockaddr_in *dst; 133 const struct sockaddr_in *gw; 134 struct in_ifaddr *ia; 135 int isbroadcast; 136 uint16_t ip_len, ip_off; 137 struct route iproute; 138 struct rtentry *rte; /* cache for ro->ro_rt */ | 197/* 198 * IP output. The packet in mbuf chain m contains a skeletal IP 199 * header (with len, off, ttl, proto, tos, src, dst). 200 * The mbuf chain containing the packet will be freed. 201 * The mbuf opt, if present, will not be freed. 202 * If route ro is present and has ro_rt initialized, route lookup would be 203 * skipped and ro->ro_rt would be used. If ro is present but ro->ro_rt is NULL, 204 * then result of route lookup is stored in ro->ro_rt. --- 14 unchanged lines hidden (view full) --- 219 int error = 0; 220 struct sockaddr_in *dst; 221 const struct sockaddr_in *gw; 222 struct in_ifaddr *ia; 223 int isbroadcast; 224 uint16_t ip_len, ip_off; 225 struct route iproute; 226 struct rtentry *rte; /* cache for ro->ro_rt */ |
139 struct in_addr odst; 140 struct m_tag *fwd_tag = NULL; | |
141 uint32_t fibnum; 142 int have_ia_ref; | 227 uint32_t fibnum; 228 int have_ia_ref; |
143 int needfiblookup; | |
144#ifdef IPSEC 145 int no_route_but_check_spd = 0; 146#endif 147 M_ASSERTPKTHDR(m); 148 149 if (inp != NULL) { 150 INP_LOCK_ASSERT(inp); 151 M_SETFIB(m, inp->inp_inc.inc_fibnum); --- 37 unchanged lines hidden (view full) --- 189 * dst/gw handling: 190 * 191 * dst can be rewritten but always points to &ro->ro_dst. 192 * gw is readonly but can point either to dst OR rt_gateway, 193 * therefore we need restore gw if we're redoing lookup. 194 */ 195 gw = dst = (struct sockaddr_in *)&ro->ro_dst; 196 fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m); | 229#ifdef IPSEC 230 int no_route_but_check_spd = 0; 231#endif 232 M_ASSERTPKTHDR(m); 233 234 if (inp != NULL) { 235 INP_LOCK_ASSERT(inp); 236 M_SETFIB(m, inp->inp_inc.inc_fibnum); --- 37 unchanged lines hidden (view full) --- 274 * dst/gw handling: 275 * 276 * dst can be rewritten but always points to &ro->ro_dst. 277 * gw is readonly but can point either to dst OR rt_gateway, 278 * therefore we need restore gw if we're redoing lookup. 279 */ 280 gw = dst = (struct sockaddr_in *)&ro->ro_dst; 281 fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m); |
197again: 198 ia = NULL; 199 have_ia_ref = 0; | 282 rte = ro->ro_rt; |
200 /* | 283 /* |
201 * If there is a cached route, check that it is to the same 202 * destination and is still up. If not, free it and try again. | |
203 * The address family should also be checked in case of sharing 204 * the cache with IPv6. 205 */ | 284 * The address family should also be checked in case of sharing 285 * the cache with IPv6. 286 */ |
206 rte = ro->ro_rt; 207 if (rte && ((rte->rt_flags & RTF_UP) == 0 || 208 rte->rt_ifp == NULL || 209 !RT_LINK_IS_UP(rte->rt_ifp) || 210 dst->sin_family != AF_INET || 211 dst->sin_addr.s_addr != ip->ip_dst.s_addr)) { 212 RO_RTFREE(ro); 213 ro->ro_lle = NULL; 214 rte = NULL; 215 gw = dst; 216 } 217 if (rte == NULL && fwd_tag == NULL) { | 287 if (rte == NULL || dst->sin_family != AF_INET) { |
218 bzero(dst, sizeof(*dst)); 219 dst->sin_family = AF_INET; 220 dst->sin_len = sizeof(*dst); 221 dst->sin_addr = ip->ip_dst; 222 } | 288 bzero(dst, sizeof(*dst)); 289 dst->sin_family = AF_INET; 290 dst->sin_len = sizeof(*dst); 291 dst->sin_addr = ip->ip_dst; 292 } |
293again: 294 ia = NULL; 295 have_ia_ref = 0; |
|
223 /* 224 * If routing to interface only, short circuit routing lookup. 225 * The use of an all-ones broadcast address implies this; an 226 * interface is specified by the broadcast address of an interface, 227 * or the destination address of a ptp interface. 228 */ 229 if (flags & IP_SENDONES) { 230 if ((ia = ifatoia(ifa_ifwithbroadaddr(sintosa(dst), --- 46 unchanged lines hidden (view full) --- 277 ntohl(ip->ip_src.s_addr ^ ip->ip_dst.s_addr), 278 fibnum); 279#else 280 in_rtalloc_ign(ro, 0, fibnum); 281#endif 282 rte = ro->ro_rt; 283 } 284 if (rte == NULL || | 296 /* 297 * If routing to interface only, short circuit routing lookup. 298 * The use of an all-ones broadcast address implies this; an 299 * interface is specified by the broadcast address of an interface, 300 * or the destination address of a ptp interface. 301 */ 302 if (flags & IP_SENDONES) { 303 if ((ia = ifatoia(ifa_ifwithbroadaddr(sintosa(dst), --- 46 unchanged lines hidden (view full) --- 350 ntohl(ip->ip_src.s_addr ^ ip->ip_dst.s_addr), 351 fibnum); 352#else 353 in_rtalloc_ign(ro, 0, fibnum); 354#endif 355 rte = ro->ro_rt; 356 } 357 if (rte == NULL || |
358 (rte->rt_flags & RTF_UP) == 0 || |
|
285 rte->rt_ifp == NULL || 286 !RT_LINK_IS_UP(rte->rt_ifp)) { 287#ifdef IPSEC 288 /* 289 * There is no route for this packet, but it is 290 * possible that a matching SPD entry exists. 291 */ 292 no_route_but_check_spd = 1; --- 9 unchanged lines hidden (view full) --- 302 counter_u64_add(rte->rt_pksent, 1); 303 if (rte->rt_flags & RTF_GATEWAY) 304 gw = (struct sockaddr_in *)rte->rt_gateway; 305 if (rte->rt_flags & RTF_HOST) 306 isbroadcast = (rte->rt_flags & RTF_BROADCAST); 307 else 308 isbroadcast = in_broadcast(gw->sin_addr, ifp); 309 } | 359 rte->rt_ifp == NULL || 360 !RT_LINK_IS_UP(rte->rt_ifp)) { 361#ifdef IPSEC 362 /* 363 * There is no route for this packet, but it is 364 * possible that a matching SPD entry exists. 365 */ 366 no_route_but_check_spd = 1; --- 9 unchanged lines hidden (view full) --- 376 counter_u64_add(rte->rt_pksent, 1); 377 if (rte->rt_flags & RTF_GATEWAY) 378 gw = (struct sockaddr_in *)rte->rt_gateway; 379 if (rte->rt_flags & RTF_HOST) 380 isbroadcast = (rte->rt_flags & RTF_BROADCAST); 381 else 382 isbroadcast = in_broadcast(gw->sin_addr, ifp); 383 } |
384 |
|
310 /* 311 * Calculate MTU. If we have a route that is up, use that, 312 * otherwise use the interface's MTU. 313 */ 314 if (rte != NULL && (rte->rt_flags & (RTF_UP|RTF_HOST))) 315 mtu = rte->rt_mtu; 316 else 317 mtu = ifp->if_mtu; 318 /* Catch a possible divide by zero later. */ 319 KASSERT(mtu > 0, ("%s: mtu %d <= 0, rte=%p (rt_flags=0x%08x) ifp=%p", 320 __func__, mtu, rte, (rte != NULL) ? rte->rt_flags : 0, ifp)); | 385 /* 386 * Calculate MTU. If we have a route that is up, use that, 387 * otherwise use the interface's MTU. 388 */ 389 if (rte != NULL && (rte->rt_flags & (RTF_UP|RTF_HOST))) 390 mtu = rte->rt_mtu; 391 else 392 mtu = ifp->if_mtu; 393 /* Catch a possible divide by zero later. */ 394 KASSERT(mtu > 0, ("%s: mtu %d <= 0, rte=%p (rt_flags=0x%08x) ifp=%p", 395 __func__, mtu, rte, (rte != NULL) ? rte->rt_flags : 0, ifp)); |
396 |
|
321 if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { 322 m->m_flags |= M_MCAST; 323 /* 324 * IP destination address is multicast. Make sure "gw" 325 * still points to the address in "ro". (It may have been 326 * changed to point to a gateway address, above.) 327 */ 328 gw = dst; --- 141 unchanged lines hidden (view full) --- 470 goto bad; 471 } 472 /* Update variables that are affected by ipsec4_output(). */ 473 ip = mtod(m, struct ip *); 474 hlen = ip->ip_hl << 2; 475#endif /* IPSEC */ 476 477 /* Jump over all PFIL processing if hooks are not active. */ | 397 if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { 398 m->m_flags |= M_MCAST; 399 /* 400 * IP destination address is multicast. Make sure "gw" 401 * still points to the address in "ro". (It may have been 402 * changed to point to a gateway address, above.) 403 */ 404 gw = dst; --- 141 unchanged lines hidden (view full) --- 546 goto bad; 547 } 548 /* Update variables that are affected by ipsec4_output(). */ 549 ip = mtod(m, struct ip *); 550 hlen = ip->ip_hl << 2; 551#endif /* IPSEC */ 552 553 /* Jump over all PFIL processing if hooks are not active. */ |
478 if (!PFIL_HOOKED(&V_inet_pfil_hook)) 479 goto passout; | 554 if (PFIL_HOOKED(&V_inet_pfil_hook)) { 555 switch (ip_output_pfil(m, ifp, inp, dst, &fibnum, &error)) { 556 case 1: /* Finished */ 557 goto done; |
480 | 558 |
481 /* Run through list of hooks for output packets. */ 482 odst.s_addr = ip->ip_dst.s_addr; 483 error = pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_OUT, inp); 484 if (error != 0 || m == NULL) 485 goto done; | 559 case 0: /* Continue normally */ 560 ip = mtod(m, struct ip *); 561 break; |
486 | 562 |
487 ip = mtod(m, struct ip *); 488 needfiblookup = 0; 489 490 /* See if destination IP address was changed by packet filter. */ 491 if (odst.s_addr != ip->ip_dst.s_addr) { 492 m->m_flags |= M_SKIP_FIREWALL; 493 /* If destination is now ourself drop to ip_input(). */ 494 if (in_localip(ip->ip_dst)) { 495 m->m_flags |= M_FASTFWD_OURS; 496 if (m->m_pkthdr.rcvif == NULL) 497 m->m_pkthdr.rcvif = V_loif; 498 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 499 m->m_pkthdr.csum_flags |= 500 CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 501 m->m_pkthdr.csum_data = 0xffff; 502 } 503 m->m_pkthdr.csum_flags |= 504 CSUM_IP_CHECKED | CSUM_IP_VALID; 505#ifdef SCTP 506 if (m->m_pkthdr.csum_flags & CSUM_SCTP) 507 m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; 508#endif 509 error = netisr_queue(NETISR_IP, m); 510 goto done; 511 } else { | 563 case -1: /* Need to try again */ 564 /* Reset everything for a new round */ 565 RO_RTFREE(ro); |
512 if (have_ia_ref) 513 ifa_free(&ia->ia_ifa); | 566 if (have_ia_ref) 567 ifa_free(&ia->ia_ifa); |
514 needfiblookup = 1; /* Redo the routing table lookup. */ 515 } 516 } 517 /* See if fib was changed by packet filter. */ 518 if (fibnum != M_GETFIB(m)) { 519 m->m_flags |= M_SKIP_FIREWALL; 520 fibnum = M_GETFIB(m); 521 RO_RTFREE(ro); 522 needfiblookup = 1; 523 } 524 if (needfiblookup) 525 goto again; | 568 ro->ro_lle = NULL; 569 rte = NULL; 570 gw = dst; 571 ip = mtod(m, struct ip *); 572 goto again; |
526 | 573 |
527 /* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */ 528 if (m->m_flags & M_FASTFWD_OURS) { 529 if (m->m_pkthdr.rcvif == NULL) 530 m->m_pkthdr.rcvif = V_loif; 531 if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { 532 m->m_pkthdr.csum_flags |= 533 CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 534 m->m_pkthdr.csum_data = 0xffff; | |
535 } | 574 } |
536#ifdef SCTP 537 if (m->m_pkthdr.csum_flags & CSUM_SCTP) 538 m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID; 539#endif 540 m->m_pkthdr.csum_flags |= 541 CSUM_IP_CHECKED | CSUM_IP_VALID; 542 543 error = netisr_queue(NETISR_IP, m); 544 goto done; | |
545 } | 575 } |
546 /* Or forward to some other address? */ 547 if ((m->m_flags & M_IP_NEXTHOP) && 548 (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) { 549 bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in)); 550 m->m_flags |= M_SKIP_FIREWALL; 551 m->m_flags &= ~M_IP_NEXTHOP; 552 m_tag_delete(m, fwd_tag); 553 if (have_ia_ref) 554 ifa_free(&ia->ia_ifa); 555 goto again; 556 } | |
557 | 576 |
558passout: | |
559 /* 127/8 must not appear on wire - RFC1122. */ 560 if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || 561 (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { 562 if ((ifp->if_flags & IFF_LOOPBACK) == 0) { 563 IPSTAT_INC(ips_badaddr); 564 error = EADDRNOTAVAIL; 565 goto bad; 566 } --- 806 unchanged lines hidden --- | 577 /* 127/8 must not appear on wire - RFC1122. */ 578 if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || 579 (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { 580 if ((ifp->if_flags & IFF_LOOPBACK) == 0) { 581 IPSTAT_INC(ips_badaddr); 582 error = EADDRNOTAVAIL; 583 goto bad; 584 } --- 806 unchanged lines hidden --- |