Deleted Added
full compact
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 ---