2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * $KAME: ip6_forward.c,v 1.69 2001/05/17 03:48:30 itojun Exp $
34 #include <sys/cdefs.h>
36 #include "opt_inet6.h"
37 #include "opt_ipsec.h"
38 #include "opt_ipstealth.h"
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/malloc.h>
45 #include <sys/domain.h>
46 #include <sys/protosw.h>
47 #include <sys/socket.h>
48 #include <sys/errno.h>
50 #include <sys/kernel.h>
51 #include <sys/syslog.h>
54 #include <net/if_var.h>
55 #include <net/if_private.h>
56 #include <net/netisr.h>
57 #include <net/route.h>
58 #include <net/route/nhop.h>
61 #include <netinet/in.h>
62 #include <netinet/in_var.h>
63 #include <netinet/in_systm.h>
64 #include <netinet/ip.h>
65 #include <netinet/ip_var.h>
66 #include <netinet6/in6_var.h>
67 #include <netinet/ip6.h>
68 #include <netinet6/in6_fib.h>
69 #include <netinet6/ip6_var.h>
70 #include <netinet6/scope6_var.h>
71 #include <netinet/icmp6.h>
72 #include <netinet6/nd6.h>
74 #include <netinet/in_pcb.h>
76 #include <netipsec/ipsec_support.h>
79 * Forward a packet. If some error occurs return the sender
80 * an icmp packet. Note we can't always generate a meaningful
81 * icmp message because icmp doesn't have a large enough repertoire
84 * If not forwarding, just drop the packet. This could be confusing
85 * if ipforwarding was zero but some routing protocol was advancing
86 * us as a gateway to somewhere. However, we must let the routing
87 * protocol deal with that.
91 ip6_forward(struct mbuf
*m
, int srcrt
)
93 struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
94 struct sockaddr_in6 dst
;
95 struct nhop_object
*nh
= NULL
;
96 int error
, type
= 0, code
= 0;
97 struct mbuf
*mcopy
= NULL
;
98 struct ifnet
*origifp
; /* maybe unnecessary */
99 u_int32_t inzone
, outzone
;
100 struct in6_addr odst
;
101 struct m_tag
*fwd_tag
;
102 char ip6bufs
[INET6_ADDRSTRLEN
], ip6bufd
[INET6_ADDRSTRLEN
];
105 * Do not forward packets to multicast destination (should be handled
107 * Do not forward packets with unspecified source. It was discussed
108 * in July 2000, on the ipngwg mailing list.
110 if ((m
->m_flags
& (M_BCAST
|M_MCAST
)) != 0 ||
111 IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
) ||
112 IN6_IS_ADDR_UNSPECIFIED(&ip6
->ip6_src
)) {
113 IP6STAT_INC(ip6s_cantforward
);
114 /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
115 if (V_ip6_log_cannot_forward
&& ip6_log_ratelimit()) {
118 "from %s to %s nxt %d received on %s\n",
119 ip6_sprintf(ip6bufs
, &ip6
->ip6_src
),
120 ip6_sprintf(ip6bufd
, &ip6
->ip6_dst
),
122 if_name(m
->m_pkthdr
.rcvif
));
132 ip6
->ip6_hlim
<= IPV6_HLIMDEC
) {
133 /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
134 icmp6_error(m
, ICMP6_TIME_EXCEEDED
,
135 ICMP6_TIME_EXCEED_TRANSIT
, 0);
140 * Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU -
141 * size of IPv6 + ICMPv6 headers) bytes of the packet in case
142 * we need to generate an ICMP6 message to the src.
143 * Thanks to M_EXT, in most cases copy will not occur.
145 * It is important to save it before IPsec processing as IPsec
146 * processing may modify the mbuf.
148 mcopy
= m_copym(m
, 0, imin(m
->m_pkthdr
.len
, ICMPV6_PLD_MAXLEN
),
151 if (V_ip6stealth
== 0)
153 ip6
->ip6_hlim
-= IPV6_HLIMDEC
;
155 #if defined(IPSEC) || defined(IPSEC_SUPPORT)
156 if (IPSEC_ENABLED(ipv6
)) {
157 if ((error
= IPSEC_FORWARD(ipv6
, m
)) != 0) {
158 /* mbuf consumed by IPsec */
160 if (error
!= EINPROGRESS
)
161 IP6STAT_INC(ip6s_cantforward
);
164 /* No IPsec processing required */
168 * ip6_forward() operates with IPv6 addresses with deembedded scope.
170 * There are 3 sources of IPv6 destination address:
172 * 1) ip6_input(), where ip6_dst contains deembedded address.
173 * In order to deal with forwarding of link-local packets,
174 * calculate the scope based on input interface (RFC 4007, clause 9).
175 * 2) packet filters changing ip6_dst directly. It would embed scope
176 * for LL addresses, so in6_localip() performs properly.
177 * 3) packet filters attaching PACKET_TAG_IPFORWARD would embed
178 * scope for the nexthop.
180 bzero(&dst
, sizeof(struct sockaddr_in6
));
181 dst
.sin6_family
= AF_INET6
;
182 dst
.sin6_addr
= ip6
->ip6_dst
;
183 dst
.sin6_scope_id
= in6_get_unicast_scopeid(&ip6
->ip6_dst
, m
->m_pkthdr
.rcvif
);
185 nh
= fib6_lookup(M_GETFIB(m
), &dst
.sin6_addr
, dst
.sin6_scope_id
,
186 NHR_REF
, m
->m_pkthdr
.flowid
);
188 IP6STAT_INC(ip6s_noroute
);
189 in6_ifstat_inc(m
->m_pkthdr
.rcvif
, ifs6_in_noroute
);
191 icmp6_error(mcopy
, ICMP6_DST_UNREACH
,
192 ICMP6_DST_UNREACH_NOROUTE
, 0);
197 if (nh
->nh_flags
& (NHF_BLACKHOLE
| NHF_REJECT
)) {
198 IP6STAT_INC(ip6s_cantforward
);
200 if (nh
->nh_flags
& NHF_REJECT
) {
201 icmp6_error(mcopy
, ICMP6_DST_UNREACH
,
202 ICMP6_DST_UNREACH_REJECT
, 0);
210 * Source scope check: if a packet can't be delivered to its
211 * destination for the reason that the destination is beyond the scope
212 * of the source address, discard the packet and return an icmp6
213 * destination unreachable error with Code 2 (beyond scope of source
215 * [draft-ietf-ipngwg-icmp-v3-04.txt, Section 3.1]
217 outzone
= in6_get_unicast_scopeid(&ip6
->ip6_src
, nh
->nh_ifp
);
218 inzone
= in6_get_unicast_scopeid(&ip6
->ip6_src
, m
->m_pkthdr
.rcvif
);
219 if (inzone
!= outzone
) {
220 IP6STAT_INC(ip6s_cantforward
);
221 IP6STAT_INC(ip6s_badscope
);
222 in6_ifstat_inc(nh
->nh_ifp
, ifs6_in_discard
);
224 if (V_ip6_log_cannot_forward
&& ip6_log_ratelimit()) {
227 "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
228 ip6_sprintf(ip6bufs
, &ip6
->ip6_src
),
229 ip6_sprintf(ip6bufd
, &ip6
->ip6_dst
),
231 if_name(m
->m_pkthdr
.rcvif
), if_name(nh
->nh_ifp
));
234 icmp6_error(mcopy
, ICMP6_DST_UNREACH
,
235 ICMP6_DST_UNREACH_BEYONDSCOPE
, 0);
240 * Destination scope check: if a packet is going to break the scope
241 * zone of packet's destination address, discard it. This case should
242 * usually be prevented by appropriately-configured routing table, but
243 * we need an explicit check because we may mistakenly forward the
244 * packet to a different zone by (e.g.) a default route.
246 inzone
= in6_get_unicast_scopeid(&ip6
->ip6_dst
, m
->m_pkthdr
.rcvif
);
247 outzone
= in6_get_unicast_scopeid(&ip6
->ip6_dst
, nh
->nh_ifp
);
249 if (inzone
!= outzone
) {
250 IP6STAT_INC(ip6s_cantforward
);
251 IP6STAT_INC(ip6s_badscope
);
255 if (nh
->nh_flags
& NHF_GATEWAY
) {
256 /* Store gateway address in deembedded form */
257 dst
.sin6_addr
= nh
->gw6_sa
.sin6_addr
;
258 dst
.sin6_scope_id
= ntohs(in6_getscope(&dst
.sin6_addr
));
259 in6_clearscope(&dst
.sin6_addr
);
263 * If we are to forward the packet using the same interface
264 * as one we got the packet from, perhaps we should send a redirect
265 * to sender to shortcut a hop.
266 * Only send redirect if source is sending directly to us,
267 * and if packet was not source routed (or has any options).
268 * Also, don't send redirect if forwarding using a route
269 * modified by a redirect.
271 if (V_ip6_sendredirects
&& nh
->nh_ifp
== m
->m_pkthdr
.rcvif
&& !srcrt
&&
272 (nh
->nh_flags
& NHF_REDIRECT
) == 0)
276 * Fake scoped addresses. Note that even link-local source or
277 * destinaion can appear, if the originating node just sends the
278 * packet to us (without address resolution for the destination).
279 * Since both icmp6_error and icmp6_redirect_output fill the embedded
280 * link identifiers, we can do this stuff after making a copy for
281 * returning an error.
283 if ((nh
->nh_ifp
->if_flags
& IFF_LOOPBACK
) != 0) {
285 * See corresponding comments in ip6_output.
286 * XXX: but is it possible that ip6_forward() sends a packet
287 * to a loopback interface? I don't think so, and thus
288 * I bark here. (jinmei@kame.net)
289 * XXX: it is common to route invalid packets to loopback.
290 * also, the codepath will be visited on use of ::1 in
296 if ((rt
->rt_flags
& (RTF_BLACKHOLE
|RTF_REJECT
)) == 0)
299 printf("ip6_forward: outgoing interface is loopback. "
300 "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
301 ip6_sprintf(ip6bufs
, &ip6
->ip6_src
),
302 ip6_sprintf(ip6bufd
, &ip6
->ip6_dst
),
303 ip6
->ip6_nxt
, if_name(m
->m_pkthdr
.rcvif
),
304 if_name(nh
->nh_ifp
));
307 /* we can just use rcvif in forwarding. */
308 origifp
= m
->m_pkthdr
.rcvif
;
311 origifp
= nh
->nh_ifp
;
313 * clear embedded scope identifiers if necessary.
314 * in6_clearscope will touch the addresses only when necessary.
316 in6_clearscope(&ip6
->ip6_src
);
317 in6_clearscope(&ip6
->ip6_dst
);
319 /* Jump over all PFIL processing if hooks are not active. */
320 if (!PFIL_HOOKED_OUT(V_inet6_pfil_head
))
324 /* Run through list of hooks for forwarded packets. */
325 if (pfil_mbuf_fwd(V_inet6_pfil_head
, &m
, nh
->nh_ifp
,
328 ip6
= mtod(m
, struct ip6_hdr
*);
330 /* See if destination IP address was changed by packet filter. */
331 if (!IN6_ARE_ADDR_EQUAL(&odst
, &ip6
->ip6_dst
)) {
332 m
->m_flags
|= M_SKIP_FIREWALL
;
333 /* If destination is now ourself drop to ip6_input(). */
334 if (in6_localip(&ip6
->ip6_dst
))
335 m
->m_flags
|= M_FASTFWD_OURS
;
339 /* Update address and scopeid. Assume scope is embedded */
340 dst
.sin6_scope_id
= ntohs(in6_getscope(&ip6
->ip6_dst
));
341 dst
.sin6_addr
= ip6
->ip6_dst
;
342 in6_clearscope(&dst
.sin6_addr
);
343 goto again
; /* Redo the routing table lookup. */
347 /* See if local, if yes, send it to netisr. */
348 if (m
->m_flags
& M_FASTFWD_OURS
) {
349 if (m
->m_pkthdr
.rcvif
== NULL
)
350 m
->m_pkthdr
.rcvif
= V_loif
;
351 if (m
->m_pkthdr
.csum_flags
& CSUM_DELAY_DATA_IPV6
) {
352 m
->m_pkthdr
.csum_flags
|=
353 CSUM_DATA_VALID_IPV6
| CSUM_PSEUDO_HDR
;
354 m
->m_pkthdr
.csum_data
= 0xffff;
356 #if defined(SCTP) || defined(SCTP_SUPPORT)
357 if (m
->m_pkthdr
.csum_flags
& CSUM_SCTP_IPV6
)
358 m
->m_pkthdr
.csum_flags
|= CSUM_SCTP_VALID
;
360 error
= netisr_queue(NETISR_IPV6
, m
);
363 /* Or forward to some other address? */
364 if ((m
->m_flags
& M_IP6_NEXTHOP
) &&
365 (fwd_tag
= m_tag_find(m
, PACKET_TAG_IPFORWARD
, NULL
)) != NULL
) {
366 struct sockaddr_in6
*gw6
= (struct sockaddr_in6
*)(fwd_tag
+ 1);
368 /* Update address and scopeid. Assume scope is embedded */
369 dst
.sin6_scope_id
= ntohs(in6_getscope(&gw6
->sin6_addr
));
370 dst
.sin6_addr
= gw6
->sin6_addr
;
371 in6_clearscope(&dst
.sin6_addr
);
373 m
->m_flags
|= M_SKIP_FIREWALL
;
374 m
->m_flags
&= ~M_IP6_NEXTHOP
;
375 m_tag_delete(m
, fwd_tag
);
381 /* See if the size was changed by the packet filter. */
382 /* TODO: change to nh->nh_mtu */
383 if (m
->m_pkthdr
.len
> IN6_LINKMTU(nh
->nh_ifp
)) {
384 in6_ifstat_inc(nh
->nh_ifp
, ifs6_in_toobig
);
386 icmp6_error(mcopy
, ICMP6_PACKET_TOO_BIG
, 0,
387 IN6_LINKMTU(nh
->nh_ifp
));
391 /* Currently LLE layer stores embedded IPv6 addresses */
392 if (IN6_IS_SCOPE_LINKLOCAL(&dst
.sin6_addr
)) {
393 in6_set_unicast_scopeid(&dst
.sin6_addr
, dst
.sin6_scope_id
);
394 dst
.sin6_scope_id
= 0;
396 error
= nd6_output_ifp(nh
->nh_ifp
, origifp
, m
, &dst
, NULL
);
398 in6_ifstat_inc(nh
->nh_ifp
, ifs6_out_discard
);
399 IP6STAT_INC(ip6s_cantforward
);
401 IP6STAT_INC(ip6s_forward
);
402 in6_ifstat_inc(nh
->nh_ifp
, ifs6_out_forward
);
404 IP6STAT_INC(ip6s_redirectsent
);
415 if (type
== ND_REDIRECT
) {
416 icmp6_redirect_output(mcopy
, nh
);
422 /* xxx MTU is constant in PPP? */
426 /* Tell source to slow down like source quench in IP? */
429 case ENETUNREACH
: /* shouldn't happen, checked above */
434 type
= ICMP6_DST_UNREACH
;
435 code
= ICMP6_DST_UNREACH_ADDR
;
438 icmp6_error(mcopy
, type
, code
, 0);