xref: /openbsd-src/sys/netinet6/ip6_forward.c (revision 84d9c64aba152a33fde7c9c690969428d4f7efb9)
1 /*	$OpenBSD: ip6_forward.c,v 1.125 2025/01/03 21:27:40 bluhm Exp $	*/
2 /*	$KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include "pf.h"
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/mbuf.h>
38 #include <sys/socket.h>
39 #include <sys/errno.h>
40 #include <sys/time.h>
41 #include <sys/kernel.h>
42 #include <sys/syslog.h>
43 
44 #include <net/if.h>
45 #include <net/if_var.h>
46 #include <net/if_enc.h>
47 #include <net/route.h>
48 #if NPF > 0
49 #include <net/pfvar.h>
50 #endif
51 
52 #include <netinet/in.h>
53 #include <netinet/ip_var.h>
54 #include <netinet6/in6_var.h>
55 #include <netinet/ip6.h>
56 #include <netinet6/ip6_var.h>
57 #include <netinet/icmp6.h>
58 #include <netinet6/nd6.h>
59 #include <netinet/udp.h>
60 #include <netinet/tcp.h>
61 #include <netinet/tcp_timer.h>
62 #include <netinet/tcp_var.h>
63 #ifdef IPSEC
64 #include <netinet/ip_ipsp.h>
65 #include <netinet/ip_ah.h>
66 #include <netinet/ip_esp.h>
67 #endif
68 
69 /*
70  * Forward a packet.  If some error occurs return the sender
71  * an icmp packet.  Note we can't always generate a meaningful
72  * icmp message because icmp doesn't have a large enough repertoire
73  * of codes and types.
74  *
75  * If not forwarding, just drop the packet.  This could be confusing
76  * if ip6_forwarding was zero but some routing protocol was advancing
77  * us as a gateway to somewhere.  However, we must let the routing
78  * protocol deal with that.
79  *
80  */
81 
82 void
83 ip6_forward(struct mbuf *m, struct route *ro, int flags)
84 {
85 	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
86 	struct route iproute;
87 	struct rtentry *rt;
88 	struct sockaddr *dst;
89 	struct ifnet *ifp = NULL;
90 	u_int rtableid = m->m_pkthdr.ph_rtableid;
91 	u_int ifidx = m->m_pkthdr.ph_ifidx;
92 	u_int8_t loopcnt = m->m_pkthdr.ph_loopcnt;
93 	u_int icmp_len;
94 	char icmp_buf[MHLEN];
95 	CTASSERT(sizeof(struct ip6_hdr) + sizeof(struct tcphdr) +
96 	    MAX_TCPOPTLEN <= sizeof(icmp_buf));
97 	u_short mflags, pfflags;
98 	struct mbuf *mcopy;
99 	int error = 0, type = 0, code = 0, destmtu = 0;
100 #ifdef IPSEC
101 	struct tdb *tdb = NULL;
102 #endif /* IPSEC */
103 	char src6[INET6_ADDRSTRLEN], dst6[INET6_ADDRSTRLEN];
104 
105 	/*
106 	 * Do not forward packets to multicast destination (should be handled
107 	 * by ip6_mforward().
108 	 * Do not forward packets with unspecified source.  It was discussed
109 	 * in July 2000, on ipngwg mailing list.
110 	 */
111 	if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
112 	    IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
113 	    IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
114 		time_t uptime;
115 
116 		ip6stat_inc(ip6s_cantforward);
117 		uptime = getuptime();
118 
119 		if (ip6_log_time + ip6_log_interval < uptime) {
120 			ip6_log_time = uptime;
121 			inet_ntop(AF_INET6, &ip6->ip6_src, src6, sizeof(src6));
122 			inet_ntop(AF_INET6, &ip6->ip6_dst, dst6, sizeof(dst6));
123 			log(LOG_DEBUG,
124 			    "cannot forward "
125 			    "from %s to %s nxt %d received on interface %u\n",
126 			    src6, dst6, ip6->ip6_nxt, ifidx);
127 		}
128 		m_freem(m);
129 		goto done;
130 	}
131 
132 	if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
133 		icmp6_error(m, ICMP6_TIME_EXCEEDED,
134 				ICMP6_TIME_EXCEED_TRANSIT, 0);
135 		goto done;
136 	}
137 	ip6->ip6_hlim -= IPV6_HLIMDEC;
138 
139 	/*
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.
144 	 * For small packets copy original onto stack instead of mbuf.
145 	 *
146 	 * For final protocol header like TCP or UDP, full header chain in
147 	 * ICMP6 packet is not necessary.  In this case only copy small
148 	 * part of original packet and save it on stack instead of mbuf.
149 	 * Although this violates RFC 4443 2.4. (c), it avoids additional
150 	 * mbuf allocations.  Also pf nat and rdr do not affect the shared
151 	 * mbuf cluster.
152 	 *
153 	 * It is important to save it before IPsec processing as IPsec
154 	 * processing may modify the mbuf.
155 	 */
156 	switch (ip6->ip6_nxt) {
157 	case IPPROTO_TCP:
158 		icmp_len = sizeof(struct ip6_hdr) + sizeof(struct tcphdr) +
159 		    MAX_TCPOPTLEN;
160 		break;
161 	case IPPROTO_UDP:
162 		icmp_len = sizeof(struct ip6_hdr) + sizeof(struct udphdr);
163 		break;
164 	case IPPROTO_ESP:
165 		icmp_len = sizeof(struct ip6_hdr) + 2 * sizeof(u_int32_t);
166 		break;
167 	default:
168 		icmp_len = ICMPV6_PLD_MAXLEN;
169 		break;
170 	}
171 	if (icmp_len > m->m_pkthdr.len)
172 		icmp_len = m->m_pkthdr.len;
173 	if (icmp_len <= sizeof(icmp_buf)) {
174 		mflags = m->m_flags;
175 		pfflags = m->m_pkthdr.pf.flags;
176 		m_copydata(m, 0, icmp_len, icmp_buf);
177 		mcopy = NULL;
178 	} else {
179 		mcopy = m_copym(m, 0, icmp_len, M_NOWAIT);
180 		icmp_len = 0;
181 	}
182 
183 #if NPF > 0
184 reroute:
185 #endif
186 
187 #ifdef IPSEC
188 	if (ipsec_in_use) {
189 		error = ip6_output_ipsec_lookup(m, NULL, &tdb);
190 		if (error) {
191 			/*
192 			 * -EINVAL is used to indicate that the packet should
193 			 * be silently dropped, typically because we've asked
194 			 * key management for an SA.
195 			 */
196 			if (error == -EINVAL) /* Should silently drop packet */
197 				error = 0;
198 
199 			m_freem(m);
200 			goto freecopy;
201 		}
202 	}
203 #endif /* IPSEC */
204 
205 	if (ro == NULL) {
206 		ro = &iproute;
207 		ro->ro_rt = NULL;
208 	}
209 	rt = route6_mpath(ro, &ip6->ip6_dst, &ip6->ip6_src,
210 	    m->m_pkthdr.ph_rtableid);
211 	if (rt == NULL) {
212 		ip6stat_inc(ip6s_noroute);
213 		type = ICMP6_DST_UNREACH;
214 		code = ICMP6_DST_UNREACH_NOROUTE;
215 		m_freem(m);
216 		goto icmperror;
217 	}
218 	dst = &ro->ro_dstsa;
219 
220 	/*
221 	 * Scope check: if a packet can't be delivered to its destination
222 	 * for the reason that the destination is beyond the scope of the
223 	 * source address, discard the packet and return an icmp6 destination
224 	 * unreachable error with Code 2 (beyond scope of source address).
225 	 * [draft-ietf-ipngwg-icmp-v3-00.txt, Section 3.1]
226 	 */
227 	if (in6_addr2scopeid(ifidx, &ip6->ip6_src) !=
228 	    in6_addr2scopeid(rt->rt_ifidx, &ip6->ip6_src)) {
229 		time_t uptime;
230 
231 		ip6stat_inc(ip6s_cantforward);
232 		ip6stat_inc(ip6s_badscope);
233 		uptime = getuptime();
234 
235 		if (ip6_log_time + ip6_log_interval < uptime) {
236 			ip6_log_time = uptime;
237 			inet_ntop(AF_INET6, &ip6->ip6_src, src6, sizeof(src6));
238 			inet_ntop(AF_INET6, &ip6->ip6_dst, dst6, sizeof(dst6));
239 			log(LOG_DEBUG,
240 			    "cannot forward "
241 			    "src %s, dst %s, nxt %d, rcvif %u, outif %u\n",
242 			    src6, dst6, ip6->ip6_nxt, ifidx, rt->rt_ifidx);
243 		}
244 		type = ICMP6_DST_UNREACH;
245 		code = ICMP6_DST_UNREACH_BEYONDSCOPE;
246 		m_freem(m);
247 		goto icmperror;
248 	}
249 
250 #ifdef IPSEC
251 	/*
252 	 * Check if the packet needs encapsulation.
253 	 * ipsp_process_packet will never come back to here.
254 	 */
255 	if (tdb != NULL) {
256 		/* Callee frees mbuf */
257 		error = ip6_output_ipsec_send(tdb, m, ro, 0, 1);
258 		rt = ro->ro_rt;
259 		if (error)
260 			goto senderr;
261 		goto freecopy;
262 	}
263 #endif /* IPSEC */
264 
265 	if (rt->rt_flags & RTF_GATEWAY)
266 		dst = rt->rt_gateway;
267 
268 	/*
269 	 * If we are to forward the packet using the same interface
270 	 * as one we got the packet from, perhaps we should send a redirect
271 	 * to sender to shortcut a hop.
272 	 * Only send redirect if source is sending directly to us,
273 	 * and if packet was not source routed (or has any options).
274 	 * Also, don't send redirect if forwarding using a route
275 	 * modified by a redirect.
276 	 */
277 	ifp = if_get(rt->rt_ifidx);
278 	if (ifp == NULL) {
279 		m_freem(m);
280 		goto freecopy;
281 	}
282 	if (rt->rt_ifidx == ifidx &&
283 	    !ISSET(rt->rt_flags, RTF_DYNAMIC|RTF_MODIFIED) &&
284 	    !ISSET(flags, IPV6_REDIRECT) &&
285 	    atomic_load_int(&ip6_sendredirects)) {
286 		if ((ifp->if_flags & IFF_POINTOPOINT) &&
287 		    nd6_is_addr_neighbor(&ro->ro_dstsin6, ifp)) {
288 			/*
289 			 * If the incoming interface is equal to the outgoing
290 			 * one, the link attached to the interface is
291 			 * point-to-point, and the IPv6 destination is
292 			 * regarded as on-link on the link, then it will be
293 			 * highly probable that the destination address does
294 			 * not exist on the link and that the packet is going
295 			 * to loop.  Thus, we immediately drop the packet and
296 			 * send an ICMPv6 error message.
297 			 * For other routing loops, we dare to let the packet
298 			 * go to the loop, so that a remote diagnosing host
299 			 * can detect the loop by traceroute.
300 			 * type/code is based on suggestion by Rich Draves.
301 			 * not sure if it is the best pick.
302 			 */
303 			type = ICMP6_DST_UNREACH;
304 			code = ICMP6_DST_UNREACH_ADDR;
305 			m_freem(m);
306 			goto icmperror;
307 		}
308 		type = ND_REDIRECT;
309 	}
310 
311 	/*
312 	 * Fake scoped addresses. Note that even link-local source or
313 	 * destination can appear, if the originating node just sends the
314 	 * packet to us (without address resolution for the destination).
315 	 * Since both icmp6_error and icmp6_redirect_output fill the embedded
316 	 * link identifiers, we can do this stuff after making a copy for
317 	 * returning an error.
318 	 */
319 	if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
320 		ip6->ip6_src.s6_addr16[1] = 0;
321 	if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
322 		ip6->ip6_dst.s6_addr16[1] = 0;
323 
324 #if NPF > 0
325 	if (pf_test(AF_INET6, PF_FWD, ifp, &m) != PF_PASS) {
326 		m_freem(m);
327 		goto senderr;
328 	}
329 	if (m == NULL)
330 		goto senderr;
331 	ip6 = mtod(m, struct ip6_hdr *);
332 	if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) ==
333 	    (PF_TAG_REROUTE | PF_TAG_GENERATED)) {
334 		/* already rerun the route lookup, go on */
335 		m->m_pkthdr.pf.flags &= ~(PF_TAG_GENERATED | PF_TAG_REROUTE);
336 	} else if (m->m_pkthdr.pf.flags & PF_TAG_REROUTE) {
337 		/* tag as generated to skip over pf_test on rerun */
338 		m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
339 		SET(flags, IPV6_REDIRECT);
340 		if (ro == &iproute)
341 			rtfree(ro->ro_rt);
342 		ro = NULL;
343 		if_put(ifp);
344 		ifp = NULL;
345 		goto reroute;
346 	}
347 #endif
348 
349 #ifdef IPSEC
350 	if (ISSET(flags, IPV6_FORWARDING) &&
351 	    ISSET(flags, IPV6_FORWARDING_IPSEC) &&
352 	    !ISSET(m->m_pkthdr.ph_tagsset, PACKET_TAG_IPSEC_IN_DONE)) {
353 		error = EHOSTUNREACH;
354 		goto senderr;
355 	}
356 #endif
357 
358 	error = if_output_tso(ifp, &m, dst, rt, ifp->if_mtu);
359 	if (error)
360 		ip6stat_inc(ip6s_cantforward);
361 	else if (m == NULL)
362 		ip6stat_inc(ip6s_forward);
363 	if (error || m == NULL)
364 		goto senderr;
365 
366 	type = ICMP6_PACKET_TOO_BIG;
367 	destmtu = ifp->if_mtu;
368 	m_freem(m);
369 	goto icmperror;
370 
371 senderr:
372 	if (mcopy == NULL && icmp_len == 0)
373 		goto done;
374 
375 	switch (error) {
376 	case 0:
377 		if (type == ND_REDIRECT) {
378 			if (icmp_len != 0) {
379 				mcopy = m_gethdr(M_DONTWAIT, MT_DATA);
380 				if (mcopy == NULL)
381 					goto done;
382 				mcopy->m_len = mcopy->m_pkthdr.len = icmp_len;
383 				mcopy->m_flags |= (mflags & M_COPYFLAGS);
384 				mcopy->m_pkthdr.ph_rtableid = rtableid;
385 				mcopy->m_pkthdr.ph_ifidx = ifidx;
386 				mcopy->m_pkthdr.ph_loopcnt = loopcnt;
387 				mcopy->m_pkthdr.pf.flags |=
388 				    (pfflags & PF_TAG_GENERATED);
389 				memcpy(mcopy->m_data, icmp_buf, icmp_len);
390 			}
391 			if (mcopy != NULL) {
392 				icmp6_redirect_output(mcopy, rt);
393 				ip6stat_inc(ip6s_redirectsent);
394 			}
395 			goto done;
396 		}
397 		goto freecopy;
398 
399 	case EMSGSIZE:
400 		type = ICMP6_PACKET_TOO_BIG;
401 		if (rt != NULL) {
402 			u_int rtmtu;
403 
404 			rtmtu = atomic_load_int(&rt->rt_mtu);
405 			if (rtmtu != 0) {
406 				destmtu = rtmtu;
407 			} else {
408 				struct ifnet *destifp;
409 
410 				destifp = if_get(rt->rt_ifidx);
411 				if (destifp != NULL)
412 					destmtu = destifp->if_mtu;
413 				if_put(destifp);
414 			}
415 		}
416 		ip6stat_inc(ip6s_cantfrag);
417 		if (destmtu == 0)
418 			goto freecopy;
419 		break;
420 
421 	case EACCES:
422 		/*
423 		 * pf(4) blocked the packet. There is no need to send an ICMP
424 		 * packet back since pf(4) takes care of it.
425 		 */
426 		goto freecopy;
427 
428 	case ENOBUFS:
429 		/* Tell source to slow down like source quench in IP? */
430 		goto freecopy;
431 
432 	case ENETUNREACH:	/* shouldn't happen, checked above */
433 	case EHOSTUNREACH:
434 	case ENETDOWN:
435 	case EHOSTDOWN:
436 	default:
437 		type = ICMP6_DST_UNREACH;
438 		code = ICMP6_DST_UNREACH_ADDR;
439 		break;
440 	}
441  icmperror:
442 	if (icmp_len != 0) {
443 		mcopy = m_gethdr(M_DONTWAIT, MT_DATA);
444 		if (mcopy == NULL)
445 			goto done;
446 		mcopy->m_len = mcopy->m_pkthdr.len = icmp_len;
447 		mcopy->m_flags |= (mflags & M_COPYFLAGS);
448 		mcopy->m_pkthdr.ph_rtableid = rtableid;
449 		mcopy->m_pkthdr.ph_ifidx = ifidx;
450 		mcopy->m_pkthdr.ph_loopcnt = loopcnt;
451 		mcopy->m_pkthdr.pf.flags |= (pfflags & PF_TAG_GENERATED);
452 		memcpy(mcopy->m_data, icmp_buf, icmp_len);
453 	}
454 	if (mcopy != NULL)
455 		icmp6_error(mcopy, type, code, destmtu);
456 	goto done;
457 
458  freecopy:
459 	m_freem(mcopy);
460  done:
461 	if (ro == &iproute)
462 		rtfree(ro->ro_rt);
463 	if_put(ifp);
464 #ifdef IPSEC
465 	tdb_unref(tdb);
466 #endif /* IPSEC */
467 }
468