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