xref: /netbsd-src/sys/netinet6/ip6_forward.c (revision 3b01aba77a7a698587faaae455bbfe740923c1f5)
1 /*	$NetBSD: ip6_forward.c,v 1.23 2001/07/18 09:24:26 itojun Exp $	*/
2 /*	$KAME: ip6_forward.c,v 1.74 2001/06/12 23:54:55 itojun 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 "opt_ipsec.h"
34 #include "opt_pfil_hooks.h"
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/mbuf.h>
40 #include <sys/domain.h>
41 #include <sys/protosw.h>
42 #include <sys/socket.h>
43 #include <sys/errno.h>
44 #include <sys/time.h>
45 #include <sys/kernel.h>
46 #include <sys/syslog.h>
47 
48 #include <net/if.h>
49 #include <net/route.h>
50 
51 #include <netinet/in.h>
52 #include <netinet/in_var.h>
53 #include <netinet/ip_var.h>
54 #include <netinet/ip6.h>
55 #include <netinet6/ip6_var.h>
56 #include <netinet/icmp6.h>
57 #include <netinet6/nd6.h>
58 
59 #ifdef IPSEC
60 #include <netinet6/ipsec.h>
61 #include <netkey/key.h>
62 #endif /* IPSEC */
63 
64 #ifdef PFIL_HOOKS
65 #include <net/pfil.h>
66 #endif
67 
68 #include <net/net_osdep.h>
69 
70 struct	route_in6 ip6_forward_rt;
71 
72 #ifdef PFIL_HOOKS
73 extern struct pfil_head inet6_pfil_hook;	/* XXX */
74 #endif
75 
76 /*
77  * Forward a packet.  If some error occurs return the sender
78  * an icmp packet.  Note we can't always generate a meaningful
79  * icmp message because icmp doesn't have a large enough repertoire
80  * of codes and types.
81  *
82  * If not forwarding, just drop the packet.  This could be confusing
83  * if ipforwarding was zero but some routing protocol was advancing
84  * us as a gateway to somewhere.  However, we must let the routing
85  * protocol deal with that.
86  *
87  */
88 
89 void
90 ip6_forward(m, srcrt)
91 	struct mbuf *m;
92 	int srcrt;
93 {
94 	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
95 	struct sockaddr_in6 *dst;
96 	struct rtentry *rt;
97 	int error, type = 0, code = 0;
98 	struct mbuf *mcopy = NULL;
99 	struct ifnet *origifp;	/* maybe unnecessary */
100 #ifdef IPSEC
101 	struct secpolicy *sp = NULL;
102 #endif
103 	long time_second = time.tv_sec;
104 
105 #ifdef IPSEC
106 	/*
107 	 * Check AH/ESP integrity.
108 	 */
109 	/*
110 	 * Don't increment ip6s_cantforward because this is the check
111 	 * before forwarding packet actually.
112 	 */
113 	if (ipsec6_in_reject(m, NULL)) {
114 		ipsec6stat.in_polvio++;
115 		m_freem(m);
116 		return;
117 	}
118 #endif /*IPSEC*/
119 
120 	/*
121 	 * Do not forward packets to multicast destination (should be handled
122 	 * by ip6_mforward().
123 	 * Do not forward packets with unspecified source.  It was discussed
124 	 * in July 2000, on ipngwg mailing list.
125 	 */
126 	if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
127 	    IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
128 	    IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
129 		ip6stat.ip6s_cantforward++;
130 		/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
131 		if (ip6_log_time + ip6_log_interval < time_second) {
132 			ip6_log_time = time_second;
133 			log(LOG_DEBUG,
134 			    "cannot forward "
135 			    "from %s to %s nxt %d received on %s\n",
136 			    ip6_sprintf(&ip6->ip6_src),
137 			    ip6_sprintf(&ip6->ip6_dst),
138 			    ip6->ip6_nxt,
139 			    if_name(m->m_pkthdr.rcvif));
140 		}
141 		m_freem(m);
142 		return;
143 	}
144 
145 	if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
146 		/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
147 		icmp6_error(m, ICMP6_TIME_EXCEEDED,
148 				ICMP6_TIME_EXCEED_TRANSIT, 0);
149 		return;
150 	}
151 	ip6->ip6_hlim -= IPV6_HLIMDEC;
152 
153 	/*
154 	 * Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU -
155 	 * size of IPv6 + ICMPv6 headers) bytes of the packet in case
156 	 * we need to generate an ICMP6 message to the src.
157 	 * Thanks to M_EXT, in most cases copy will not occur.
158 	 *
159 	 * It is important to save it before IPsec processing as IPsec
160 	 * processing may modify the mbuf.
161 	 */
162 	mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));
163 
164 #ifdef IPSEC
165 	/* get a security policy for this packet */
166 	sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, IP_FORWARDING,
167 	    &error);
168 	if (sp == NULL) {
169 		ipsec6stat.out_inval++;
170 		ip6stat.ip6s_cantforward++;
171 		if (mcopy) {
172 #if 0
173 			/* XXX: what icmp ? */
174 #else
175 			m_freem(mcopy);
176 #endif
177 		}
178 		m_freem(m);
179 		return;
180 	}
181 
182 	error = 0;
183 
184 	/* check policy */
185 	switch (sp->policy) {
186 	case IPSEC_POLICY_DISCARD:
187 		/*
188 		 * This packet is just discarded.
189 		 */
190 		ipsec6stat.out_polvio++;
191 		ip6stat.ip6s_cantforward++;
192 		key_freesp(sp);
193 		if (mcopy) {
194 #if 0
195 			/* XXX: what icmp ? */
196 #else
197 			m_freem(mcopy);
198 #endif
199 		}
200 		m_freem(m);
201 		return;
202 
203 	case IPSEC_POLICY_BYPASS:
204 	case IPSEC_POLICY_NONE:
205 		/* no need to do IPsec. */
206 		key_freesp(sp);
207 		goto skip_ipsec;
208 
209 	case IPSEC_POLICY_IPSEC:
210 		if (sp->req == NULL) {
211 			/* XXX should be panic ? */
212 			printf("ip6_forward: No IPsec request specified.\n");
213 			ip6stat.ip6s_cantforward++;
214 			key_freesp(sp);
215 			if (mcopy) {
216 #if 0
217 				/* XXX: what icmp ? */
218 #else
219 				m_freem(mcopy);
220 #endif
221 			}
222 			m_freem(m);
223 			return;
224 		}
225 		/* do IPsec */
226 		break;
227 
228 	case IPSEC_POLICY_ENTRUST:
229 	default:
230 		/* should be panic ?? */
231 		printf("ip6_forward: Invalid policy found. %d\n", sp->policy);
232 		key_freesp(sp);
233 		goto skip_ipsec;
234 	}
235 
236     {
237 	struct ipsec_output_state state;
238 
239 	/*
240 	 * All the extension headers will become inaccessible
241 	 * (since they can be encrypted).
242 	 * Don't panic, we need no more updates to extension headers
243 	 * on inner IPv6 packet (since they are now encapsulated).
244 	 *
245 	 * IPv6 [ESP|AH] IPv6 [extension headers] payload
246 	 */
247 	bzero(&state, sizeof(state));
248 	state.m = m;
249 	state.ro = NULL;	/* update at ipsec6_output_tunnel() */
250 	state.dst = NULL;	/* update at ipsec6_output_tunnel() */
251 
252 	error = ipsec6_output_tunnel(&state, sp, 0);
253 
254 	m = state.m;
255 #if 0	/* XXX allocate a route (ro, dst) again later */
256 	ro = (struct route_in6 *)state.ro;
257 	dst = (struct sockaddr_in6 *)state.dst;
258 #endif
259 	key_freesp(sp);
260 
261 	if (error) {
262 		/* mbuf is already reclaimed in ipsec6_output_tunnel. */
263 		switch (error) {
264 		case EHOSTUNREACH:
265 		case ENETUNREACH:
266 		case EMSGSIZE:
267 		case ENOBUFS:
268 		case ENOMEM:
269 			break;
270 		default:
271 			printf("ip6_output (ipsec): error code %d\n", error);
272 			/*fall through*/
273 		case ENOENT:
274 			/* don't show these error codes to the user */
275 			break;
276 		}
277 		ip6stat.ip6s_cantforward++;
278 		if (mcopy) {
279 #if 0
280 			/* XXX: what icmp ? */
281 #else
282 			m_freem(mcopy);
283 #endif
284 		}
285 		m_freem(m);
286 		return;
287 	}
288     }
289     skip_ipsec:
290 #endif /* IPSEC */
291 
292 	dst = &ip6_forward_rt.ro_dst;
293 	if (!srcrt) {
294 		/*
295 		 * ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst
296 		 */
297 		if (ip6_forward_rt.ro_rt == 0 ||
298 		    (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) == 0) {
299 			if (ip6_forward_rt.ro_rt) {
300 				RTFREE(ip6_forward_rt.ro_rt);
301 				ip6_forward_rt.ro_rt = 0;
302 			}
303 			/* this probably fails but give it a try again */
304 			rtalloc((struct route *)&ip6_forward_rt);
305 		}
306 
307 		if (ip6_forward_rt.ro_rt == 0) {
308 			ip6stat.ip6s_noroute++;
309 			/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
310 			if (mcopy) {
311 				icmp6_error(mcopy, ICMP6_DST_UNREACH,
312 					    ICMP6_DST_UNREACH_NOROUTE, 0);
313 			}
314 			m_freem(m);
315 			return;
316 		}
317 	} else if ((rt = ip6_forward_rt.ro_rt) == 0 ||
318 		 !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst->sin6_addr)) {
319 		if (ip6_forward_rt.ro_rt) {
320 			RTFREE(ip6_forward_rt.ro_rt);
321 			ip6_forward_rt.ro_rt = 0;
322 		}
323 		bzero(dst, sizeof(*dst));
324 		dst->sin6_len = sizeof(struct sockaddr_in6);
325 		dst->sin6_family = AF_INET6;
326 		dst->sin6_addr = ip6->ip6_dst;
327 
328 		rtalloc((struct route *)&ip6_forward_rt);
329 		if (ip6_forward_rt.ro_rt == 0) {
330 			ip6stat.ip6s_noroute++;
331 			/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
332 			if (mcopy) {
333 				icmp6_error(mcopy, ICMP6_DST_UNREACH,
334 					    ICMP6_DST_UNREACH_NOROUTE, 0);
335 			}
336 			m_freem(m);
337 			return;
338 		}
339 	}
340 	rt = ip6_forward_rt.ro_rt;
341 
342 	/*
343 	 * Scope check: if a packet can't be delivered to its destination
344 	 * for the reason that the destination is beyond the scope of the
345 	 * source address, discard the packet and return an icmp6 destination
346 	 * unreachable error with Code 2 (beyond scope of source address).
347 	 * [draft-ietf-ipngwg-icmp-v3-00.txt, Section 3.1]
348 	 */
349 	if (in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_src) !=
350 	    in6_addr2scopeid(rt->rt_ifp, &ip6->ip6_src)) {
351 		ip6stat.ip6s_cantforward++;
352 		ip6stat.ip6s_badscope++;
353 		in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);
354 
355 		if (ip6_log_time + ip6_log_interval < time_second) {
356 			ip6_log_time = time_second;
357 			log(LOG_DEBUG,
358 			    "cannot forward "
359 			    "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
360 			    ip6_sprintf(&ip6->ip6_src),
361 			    ip6_sprintf(&ip6->ip6_dst),
362 			    ip6->ip6_nxt,
363 			    if_name(m->m_pkthdr.rcvif), if_name(rt->rt_ifp));
364 		}
365 		if (mcopy)
366 			icmp6_error(mcopy, ICMP6_DST_UNREACH,
367 				    ICMP6_DST_UNREACH_BEYONDSCOPE, 0);
368 		m_freem(m);
369 		return;
370 	}
371 
372 	if (m->m_pkthdr.len > rt->rt_ifp->if_mtu) {
373 		in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
374 		if (mcopy) {
375 			u_long mtu;
376 #ifdef IPSEC
377 			struct secpolicy *sp;
378 			int ipsecerror;
379 			size_t ipsechdrsiz;
380 #endif
381 
382 			mtu = rt->rt_ifp->if_mtu;
383 #ifdef IPSEC
384 			/*
385 			 * When we do IPsec tunnel ingress, we need to play
386 			 * with if_mtu value (decrement IPsec header size
387 			 * from mtu value).  The code is much simpler than v4
388 			 * case, as we have the outgoing interface for
389 			 * encapsulated packet as "rt->rt_ifp".
390 			 */
391 			sp = ipsec6_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND,
392 				IP_FORWARDING, &ipsecerror);
393 			if (sp) {
394 				ipsechdrsiz = ipsec6_hdrsiz(mcopy,
395 					IPSEC_DIR_OUTBOUND, NULL);
396 				if (ipsechdrsiz < mtu)
397 					mtu -= ipsechdrsiz;
398 			}
399 
400 			/*
401 			 * if mtu becomes less than minimum MTU,
402 			 * tell minimum MTU (and I'll need to fragment it).
403 			 */
404 			if (mtu < IPV6_MMTU)
405 				mtu = IPV6_MMTU;
406 #endif
407 			icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu);
408 		}
409 		m_freem(m);
410 		return;
411  	}
412 
413 	if (rt->rt_flags & RTF_GATEWAY)
414 		dst = (struct sockaddr_in6 *)rt->rt_gateway;
415 
416 	/*
417 	 * If we are to forward the packet using the same interface
418 	 * as one we got the packet from, perhaps we should send a redirect
419 	 * to sender to shortcut a hop.
420 	 * Only send redirect if source is sending directly to us,
421 	 * and if packet was not source routed (or has any options).
422 	 * Also, don't send redirect if forwarding using a route
423 	 * modified by a redirect.
424 	 */
425 	if (rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt &&
426 	    (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {
427 		if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) &&
428 		    nd6_is_addr_neighbor((struct sockaddr_in6 *)&ip6_forward_rt.ro_dst, rt->rt_ifp)) {
429 			/*
430 			 * If the incoming interface is equal to the outgoing
431 			 * one, the link attached to the interface is
432 			 * point-to-point, and the IPv6 destination is
433 			 * regarded as on-link on the link, then it will be
434 			 * highly probable that the destination address does
435 			 * not exist on the link and that the packet is going
436 			 * to loop.  Thus, we immediately drop the packet and
437 			 * send an ICMPv6 error message.
438 			 * For other routing loops, we dare to let the packet
439 			 * go to the loop, so that a remote diagnosing host
440 			 * can detect the loop by traceroute.
441 			 * type/code is based on suggestion by Rich Draves.
442 			 * not sure if it is the best pick.
443 			 */
444 			icmp6_error(mcopy, ICMP6_DST_UNREACH,
445 				    ICMP6_DST_UNREACH_ADDR, 0);
446 			m_freem(m);
447 			return;
448 		}
449 		type = ND_REDIRECT;
450 	}
451 
452 	/*
453 	 * Fake scoped addresses. Note that even link-local source or
454 	 * destinaion can appear, if the originating node just sends the
455 	 * packet to us (without address resolution for the destination).
456 	 * Since both icmp6_error and icmp6_redirect_output fill the embedded
457 	 * link identifiers, we can do this stuff after making a copy for
458 	 * returning an error.
459 	 */
460 	if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
461 		/*
462 		 * See corresponding comments in ip6_output.
463 		 * XXX: but is it possible that ip6_forward() sends a packet
464 		 *      to a loopback interface? I don't think so, and thus
465 		 *      I bark here. (jinmei@kame.net)
466 		 * XXX: it is common to route invalid packets to loopback.
467 		 *	also, the codepath will be visited on use of ::1 in
468 		 *	rthdr. (itojun)
469 		 */
470 #if 1
471 		if (0)
472 #else
473 		if ((rt->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) == 0)
474 #endif
475 		{
476 			printf("ip6_forward: outgoing interface is loopback. "
477 			       "src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
478 			       ip6_sprintf(&ip6->ip6_src),
479 			       ip6_sprintf(&ip6->ip6_dst),
480 			       ip6->ip6_nxt, if_name(m->m_pkthdr.rcvif),
481 			       if_name(rt->rt_ifp));
482 		}
483 
484 		/* we can just use rcvif in forwarding. */
485 		origifp = m->m_pkthdr.rcvif;
486 	}
487 	else
488 		origifp = rt->rt_ifp;
489 	if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
490 		ip6->ip6_src.s6_addr16[1] = 0;
491 	if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
492 		ip6->ip6_dst.s6_addr16[1] = 0;
493 
494 #ifdef PFIL_HOOKS
495 	/*
496 	 * Run through list of hooks for output packets.
497 	 */
498 	if ((error = pfil_run_hooks(&inet6_pfil_hook, &m, rt->rt_ifp,
499 				    PFIL_OUT)) != 0)
500 		goto senderr;
501 	if (m == NULL)
502 		goto freecopy;
503 	ip6 = mtod(m, struct ip6_hdr *);
504 #endif /* PFIL_HOOKS */
505 
506 #ifdef OLDIP6OUTPUT
507 	error = (*rt->rt_ifp->if_output)(rt->rt_ifp, m,
508 					 (struct sockaddr *)dst,
509 					 ip6_forward_rt.ro_rt);
510 #else
511 	error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
512 #endif
513 	if (error) {
514 		in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
515 		ip6stat.ip6s_cantforward++;
516 	} else {
517 		ip6stat.ip6s_forward++;
518 		in6_ifstat_inc(rt->rt_ifp, ifs6_out_forward);
519 		if (type)
520 			ip6stat.ip6s_redirectsent++;
521 		else {
522 			if (mcopy)
523 				goto freecopy;
524 		}
525 	}
526 
527 #ifdef PFIL_HOOKS
528  senderr:
529 #endif
530 	if (mcopy == NULL)
531 		return;
532 	switch (error) {
533 	case 0:
534 #if 1
535 		if (type == ND_REDIRECT) {
536 			icmp6_redirect_output(mcopy, rt);
537 			return;
538 		}
539 #endif
540 		goto freecopy;
541 
542 	case EMSGSIZE:
543 		/* xxx MTU is constant in PPP? */
544 		goto freecopy;
545 
546 	case ENOBUFS:
547 		/* Tell source to slow down like source quench in IP? */
548 		goto freecopy;
549 
550 	case ENETUNREACH:	/* shouldn't happen, checked above */
551 	case EHOSTUNREACH:
552 	case ENETDOWN:
553 	case EHOSTDOWN:
554 	default:
555 		type = ICMP6_DST_UNREACH;
556 		code = ICMP6_DST_UNREACH_ADDR;
557 		break;
558 	}
559 	icmp6_error(mcopy, type, code, 0);
560 	return;
561 
562  freecopy:
563 	m_freem(mcopy);
564 	return;
565 }
566