Deleted Added
full compact
ip6_input.c (77003) ip6_input.c (78064)
1/* $FreeBSD: head/sys/netinet6/ip6_input.c 77003 2001-05-22 17:32:02Z ume $ */
2/* $KAME: ip6_input.c,v 1.95 2000/07/02 07:49:37 jinmei Exp $ */
1/* $FreeBSD: head/sys/netinet6/ip6_input.c 78064 2001-06-11 12:39:29Z ume $ */
2/* $KAME: ip6_input.c,v 1.194 2001/05/27 13:28:35 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:

--- 57 unchanged lines hidden (view full) ---

68#include "opt_ip6fw.h"
69#include "opt_inet.h"
70#include "opt_inet6.h"
71#include "opt_ipsec.h"
72#include "opt_pfil_hooks.h"
73
74#include <sys/param.h>
75#include <sys/systm.h>
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:

--- 57 unchanged lines hidden (view full) ---

68#include "opt_ip6fw.h"
69#include "opt_inet.h"
70#include "opt_inet6.h"
71#include "opt_ipsec.h"
72#include "opt_pfil_hooks.h"
73
74#include <sys/param.h>
75#include <sys/systm.h>
76#include <sys/malloc.h>
76#include <sys/mbuf.h>
77#include <sys/domain.h>
78#include <sys/protosw.h>
79#include <sys/socket.h>
80#include <sys/socketvar.h>
81#include <sys/errno.h>
82#include <sys/time.h>
83#include <sys/kernel.h>

--- 19 unchanged lines hidden (view full) ---

103#include <netinet6/in6_var.h>
104#include <netinet6/ip6_var.h>
105#include <netinet/in_pcb.h>
106#include <netinet/icmp6.h>
107#include <netinet6/in6_ifattach.h>
108#include <netinet6/nd6.h>
109#include <netinet6/in6_prefix.h>
110
77#include <sys/mbuf.h>
78#include <sys/domain.h>
79#include <sys/protosw.h>
80#include <sys/socket.h>
81#include <sys/socketvar.h>
82#include <sys/errno.h>
83#include <sys/time.h>
84#include <sys/kernel.h>

--- 19 unchanged lines hidden (view full) ---

104#include <netinet6/in6_var.h>
105#include <netinet6/ip6_var.h>
106#include <netinet/in_pcb.h>
107#include <netinet/icmp6.h>
108#include <netinet6/in6_ifattach.h>
109#include <netinet6/nd6.h>
110#include <netinet6/in6_prefix.h>
111
112#ifdef IPSEC
113#include <netinet6/ipsec.h>
114#ifdef INET6
115#include <netinet6/ipsec6.h>
116#endif
117#endif
118
111#include <netinet6/ip6_fw.h>
112
113#include <netinet6/ip6protosw.h>
114
115#include "faith.h"
116#include "gif.h"
117
118#include <net/net_osdep.h>
119
120extern struct domain inet6domain;
121extern struct ip6protosw inet6sw[];
122
123u_char ip6_protox[IPPROTO_MAX];
124static int ip6qmaxlen = IFQ_MAXLEN;
125struct in6_ifaddr *in6_ifaddr;
126
119#include <netinet6/ip6_fw.h>
120
121#include <netinet6/ip6protosw.h>
122
123#include "faith.h"
124#include "gif.h"
125
126#include <net/net_osdep.h>
127
128extern struct domain inet6domain;
129extern struct ip6protosw inet6sw[];
130
131u_char ip6_protox[IPPROTO_MAX];
132static int ip6qmaxlen = IFQ_MAXLEN;
133struct in6_ifaddr *in6_ifaddr;
134
135extern struct callout in6_tmpaddrtimer_ch;
136
127int ip6_forward_srcrt; /* XXX */
128int ip6_sourcecheck; /* XXX */
129int ip6_sourcecheck_interval; /* XXX */
130const int int6intrq_present = 1;
131
137int ip6_forward_srcrt; /* XXX */
138int ip6_sourcecheck; /* XXX */
139int ip6_sourcecheck_interval; /* XXX */
140const int int6intrq_present = 1;
141
142int ip6_ours_check_algorithm;
143
144
132/* firewall hooks */
133ip6_fw_chk_t *ip6_fw_chk_ptr;
134ip6_fw_ctl_t *ip6_fw_ctl_ptr;
135int ip6_fw_enable = 1;
136
137struct ip6stat ip6stat;
138
139static void ip6_init2 __P((void *));
145/* firewall hooks */
146ip6_fw_chk_t *ip6_fw_chk_ptr;
147ip6_fw_ctl_t *ip6_fw_ctl_ptr;
148int ip6_fw_enable = 1;
149
150struct ip6stat ip6stat;
151
152static void ip6_init2 __P((void *));
153static struct mbuf *ip6_setdstifaddr __P((struct mbuf *, struct in6_ifaddr *));
140
141static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
142#ifdef PULLDOWN_TEST
143static struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int));
144#endif
145
154
155static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
156#ifdef PULLDOWN_TEST
157static struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int));
158#endif
159
160
146/*
147 * IP6 initialization: fill in IP6 protocol switch table.
148 * All protocols not implemented in kernel go to raw IP6 protocol handler.
149 */
150void
151ip6_init()
152{
161/*
162 * IP6 initialization: fill in IP6 protocol switch table.
163 * All protocols not implemented in kernel go to raw IP6 protocol handler.
164 */
165void
166ip6_init()
167{
153 register struct ip6protosw *pr;
154 register int i;
168 struct ip6protosw *pr;
169 int i;
155 struct timeval tv;
156
170 struct timeval tv;
171
172#ifdef DIAGNOSTIC
173 if (sizeof(struct protosw) != sizeof(struct ip6protosw))
174 panic("sizeof(protosw) != sizeof(ip6protosw)");
175#endif
157 pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
158 if (pr == 0)
159 panic("ip6_init");
160 for (i = 0; i < IPPROTO_MAX; i++)
161 ip6_protox[i] = pr - inet6sw;
162 for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
163 pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
164 if (pr->pr_domain->dom_family == PF_INET6 &&

--- 5 unchanged lines hidden (view full) ---

170 nd6_init();
171 frag6_init();
172 /*
173 * in many cases, random() here does NOT return random number
174 * as initialization during bootstrap time occur in fixed order.
175 */
176 microtime(&tv);
177 ip6_flow_seq = random() ^ tv.tv_usec;
176 pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
177 if (pr == 0)
178 panic("ip6_init");
179 for (i = 0; i < IPPROTO_MAX; i++)
180 ip6_protox[i] = pr - inet6sw;
181 for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
182 pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
183 if (pr->pr_domain->dom_family == PF_INET6 &&

--- 5 unchanged lines hidden (view full) ---

189 nd6_init();
190 frag6_init();
191 /*
192 * in many cases, random() here does NOT return random number
193 * as initialization during bootstrap time occur in fixed order.
194 */
195 microtime(&tv);
196 ip6_flow_seq = random() ^ tv.tv_usec;
197 microtime(&tv);
198 ip6_desync_factor = (random() ^ tv.tv_usec) % MAX_TEMP_DESYNC_FACTOR;
178}
179
180static void
181ip6_init2(dummy)
182 void *dummy;
183{
184
185 /*
186 * to route local address of p2p link to loopback,
187 * assign loopback address first.
188 */
189 in6_ifattach(&loif[0], NULL);
190
191 /* nd6_timer_init */
199}
200
201static void
202ip6_init2(dummy)
203 void *dummy;
204{
205
206 /*
207 * to route local address of p2p link to loopback,
208 * assign loopback address first.
209 */
210 in6_ifattach(&loif[0], NULL);
211
212 /* nd6_timer_init */
192 timeout(nd6_timer, (caddr_t)0, hz);
213 callout_init(&nd6_timer_ch, 0);
214 callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL);
215
193 /* router renumbering prefix list maintenance */
216 /* router renumbering prefix list maintenance */
194 timeout(in6_rr_timer, (caddr_t)0, hz);
217 callout_init(&in6_rr_timer_ch, 0);
218 callout_reset(&in6_rr_timer_ch, hz, in6_rr_timer, NULL);
219
220 /* timer for regeneranation of temporary addresses randomize ID */
221 callout_reset(&in6_tmpaddrtimer_ch,
222 (ip6_temp_preferred_lifetime - ip6_desync_factor -
223 ip6_temp_regen_advance) * hz,
224 in6_tmpaddrtimer, NULL);
195}
196
197/* cheat */
198/* This must be after route_init(), which is now SI_ORDER_THIRD */
199SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
200
201/*
202 * IP6 input interrupt handling. Just pass the packet to ip6_input.

--- 39 unchanged lines hidden (view full) ---

242 */
243 if (m) {
244 m->m_flags &= ~M_AUTHIPHDR;
245 m->m_flags &= ~M_AUTHIPDGM;
246 }
247#endif
248
249 /*
225}
226
227/* cheat */
228/* This must be after route_init(), which is now SI_ORDER_THIRD */
229SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
230
231/*
232 * IP6 input interrupt handling. Just pass the packet to ip6_input.

--- 39 unchanged lines hidden (view full) ---

272 */
273 if (m) {
274 m->m_flags &= ~M_AUTHIPHDR;
275 m->m_flags &= ~M_AUTHIPDGM;
276 }
277#endif
278
279 /*
280 * make sure we don't have onion peering information into m_aux.
281 */
282 ip6_delaux(m);
283
284 /*
250 * mbuf statistics by kazu
251 */
252 if (m->m_flags & M_EXT) {
253 if (m->m_next)
254 ip6stat.ip6s_mext2m++;
255 else
256 ip6stat.ip6s_mext1++;
257 } else {
285 * mbuf statistics by kazu
286 */
287 if (m->m_flags & M_EXT) {
288 if (m->m_next)
289 ip6stat.ip6s_mext2m++;
290 else
291 ip6stat.ip6s_mext1++;
292 } else {
293#define M2MMAX (sizeof(ip6stat.ip6s_m2m)/sizeof(ip6stat.ip6s_m2m[0]))
258 if (m->m_next) {
259 if (m->m_flags & M_LOOP) {
260 ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/
294 if (m->m_next) {
295 if (m->m_flags & M_LOOP) {
296 ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/
261 } else if (m->m_pkthdr.rcvif->if_index <= 31)
297 } else if (m->m_pkthdr.rcvif->if_index < M2MMAX)
262 ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
263 else
264 ip6stat.ip6s_m2m[0]++;
265 } else
266 ip6stat.ip6s_m1++;
298 ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
299 else
300 ip6stat.ip6s_m2m[0]++;
301 } else
302 ip6stat.ip6s_m1++;
303#undef M2MMAX
267 }
268
269 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
270 ip6stat.ip6s_total++;
271
272#ifndef PULLDOWN_TEST
273 /*
274 * L2 bridge code and some other code can return mbuf chain

--- 80 unchanged lines hidden (view full) ---

355 m_freem(m);
356 m = NULL;
357 }
358 if (!m)
359 return;
360 }
361
362 /*
304 }
305
306 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
307 ip6stat.ip6s_total++;
308
309#ifndef PULLDOWN_TEST
310 /*
311 * L2 bridge code and some other code can return mbuf chain

--- 80 unchanged lines hidden (view full) ---

392 m_freem(m);
393 m = NULL;
394 }
395 if (!m)
396 return;
397 }
398
399 /*
363 * Scope check
400 * Check against address spoofing/corruption.
364 */
365 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
366 IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
401 */
402 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
403 IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
404 /*
405 * XXX: "badscope" is not very suitable for a multicast source.
406 */
367 ip6stat.ip6s_badscope++;
368 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
369 goto bad;
370 }
407 ip6stat.ip6s_badscope++;
408 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
409 goto bad;
410 }
371
411 if ((IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
412 IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) &&
413 (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
414 ip6stat.ip6s_badscope++;
415 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
416 goto bad;
417 }
372 /*
418 /*
373 * Don't check IPv4 mapped address here. SIIT assumes that
374 * routers would forward IPv6 native packets with IPv4 mapped
375 * address normally.
419 * The following check is not documented in specs. A malicious
420 * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
421 * and bypass security checks (act as if it was from 127.0.0.1 by using
422 * IPv6 src ::ffff:127.0.0.1). Be cautious.
423 *
424 * This check chokes if we are in an SIIT cloud. As none of BSDs
425 * support IPv4-less kernel compilation, we cannot support SIIT
426 * environment at all. So, it makes more sense for us to reject any
427 * malicious packets for non-SIIT environment, than try to do a
428 * partical support for SIIT environment.
376 */
429 */
430 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
431 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
432 ip6stat.ip6s_badscope++;
433 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
434 goto bad;
435 }
377#if 0
378 /*
379 * Reject packets with IPv4 compatible addresses (auto tunnel).
380 *
381 * The code forbids auto tunnel relay case in RFC1933 (the check is
382 * stronger than RFC1933). We may want to re-enable it if mech-xx
383 * is revised to forbid relaying case.
384 */
385 if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
386 IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
387 ip6stat.ip6s_badscope++;
388 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
389 goto bad;
390 }
391#endif
436#if 0
437 /*
438 * Reject packets with IPv4 compatible addresses (auto tunnel).
439 *
440 * The code forbids auto tunnel relay case in RFC1933 (the check is
441 * stronger than RFC1933). We may want to re-enable it if mech-xx
442 * is revised to forbid relaying case.
443 */
444 if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
445 IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
446 ip6stat.ip6s_badscope++;
447 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
448 goto bad;
449 }
450#endif
392 if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
393 IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
394 if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
395 struct in6_ifaddr *ia6;
396
451
397 if ((ia6 = in6ifa_ifpwithaddr(m->m_pkthdr.rcvif,
398 &ip6->ip6_dst)) != NULL) {
399 ia6->ia_ifa.if_ipackets++;
400 ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
401 } else {
402 /*
403 * The packet is looped back, but we do not
404 * have the destination address for some
405 * reason.
406 * XXX: should we return an icmp6 error?
407 */
408 goto bad;
409 }
410 ours = 1;
411 deliverifp = m->m_pkthdr.rcvif;
412 goto hbhcheck;
413 } else {
452 /* drop packets if interface ID portion is already filled */
453 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
454 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src) &&
455 ip6->ip6_src.s6_addr16[1]) {
414 ip6stat.ip6s_badscope++;
456 ip6stat.ip6s_badscope++;
415 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
416 goto bad;
417 }
457 goto bad;
458 }
459 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst) &&
460 ip6->ip6_dst.s6_addr16[1]) {
461 ip6stat.ip6s_badscope++;
462 goto bad;
463 }
418 }
419
464 }
465
420#ifndef FAKE_LOOPBACK_IF
421 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0)
422#else
423 if (1)
424#endif
425 {
426 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
427 ip6->ip6_src.s6_addr16[1]
428 = htons(m->m_pkthdr.rcvif->if_index);
429 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
430 ip6->ip6_dst.s6_addr16[1]
431 = htons(m->m_pkthdr.rcvif->if_index);
432 }
466 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
467 ip6->ip6_src.s6_addr16[1]
468 = htons(m->m_pkthdr.rcvif->if_index);
469 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
470 ip6->ip6_dst.s6_addr16[1]
471 = htons(m->m_pkthdr.rcvif->if_index);
433
472
473#if 0 /* this case seems to be unnecessary. (jinmei, 20010401) */
434 /*
474 /*
435 * XXX we need this since we do not have "goto ours" hack route
436 * for some of our ifaddrs on loopback interface.
437 * we should correct it by changing in6_ifattach to install
438 * "goto ours" hack route.
475 * We use rt->rt_ifp to determine if the address is ours or not.
476 * If rt_ifp is lo0, the address is ours.
477 * The problem here is, rt->rt_ifp for fe80::%lo0/64 is set to lo0,
478 * so any address under fe80::%lo0/64 will be mistakenly considered
479 * local. The special case is supplied to handle the case properly
480 * by actually looking at interface addresses
481 * (using in6ifa_ifpwithaddr).
439 */
482 */
440 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) != 0) {
441 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
442 struct in6_ifaddr *ia6;
443#ifndef FAKE_LOOPBACK_IF
444 int deliverifid;
445
446 /*
447 * Get the "real" delivered interface, which should be
448 * embedded in the second 16 bits of the destination
449 * address. We can probably trust the value, but we
450 * add validation for the value just for safety.
451 */
452 deliverifid = ntohs(ip6->ip6_dst.s6_addr16[1]);
453 if (deliverifid > 0 && deliverifid <= if_index) {
454 deliverifp = ifindex2ifnet[deliverifid];
455
456 /*
457 * XXX: fake the rcvif to the real interface.
458 * Since m_pkthdr.rcvif should be lo0 (or a
459 * variant), it would confuse scope handling
460 * code later.
461 */
462 m->m_pkthdr.rcvif = deliverifp;
463 }
464 else {
465 /*
466 * Last resort; just use rcvif.
467 * XXX: the packet would be discarded by the
468 * succeeding check.
469 */
470 deliverifp = m->m_pkthdr.rcvif;
471 }
472#else
473 deliverifp = m->m_pkthdr.rcvif;
474#endif
475 if ((ia6 = in6ifa_ifpwithaddr(deliverifp,
476 &ip6->ip6_dst)) != NULL) {
477 ia6->ia_ifa.if_ipackets++;
478 ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
479 } else {
480 /*
481 * We do not have the link-local address
482 * specified as the destination.
483 * XXX: should we return an icmp6 error?
484 */
485 goto bad;
486 }
487 ours = 1;
488 goto hbhcheck;
483 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) != 0 &&
484 IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
485 if (!in6ifa_ifpwithaddr(m->m_pkthdr.rcvif, &ip6->ip6_dst)) {
486 icmp6_error(m, ICMP6_DST_UNREACH,
487 ICMP6_DST_UNREACH_ADDR, 0);
488 /* m is already freed */
489 return;
489 }
490 }
491
492 ours = 1;
493 deliverifp = m->m_pkthdr.rcvif;
494 goto hbhcheck;
490 }
495 }
496#endif
491
492 /*
493 * Multicast check
494 */
495 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
496 struct in6_multi *in6m = 0;
497
498 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);

--- 12 unchanged lines hidden (view full) ---

511 }
512 deliverifp = m->m_pkthdr.rcvif;
513 goto hbhcheck;
514 }
515
516 /*
517 * Unicast check
518 */
497
498 /*
499 * Multicast check
500 */
501 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
502 struct in6_multi *in6m = 0;
503
504 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);

--- 12 unchanged lines hidden (view full) ---

517 }
518 deliverifp = m->m_pkthdr.rcvif;
519 goto hbhcheck;
520 }
521
522 /*
523 * Unicast check
524 */
525 switch (ip6_ours_check_algorithm) {
526 default:
527 /*
528 * XXX: I intentionally broke our indentation rule here,
529 * since this switch-case is just for measurement and
530 * therefore should soon be removed.
531 */
519 if (ip6_forward_rt.ro_rt != NULL &&
520 (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
521 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
532 if (ip6_forward_rt.ro_rt != NULL &&
533 (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
534 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
522 &ip6_forward_rt.ro_dst.sin6_addr))
535 &((struct sockaddr_in6 *)(&ip6_forward_rt.ro_dst))->sin6_addr))
523 ip6stat.ip6s_forward_cachehit++;
524 else {
536 ip6stat.ip6s_forward_cachehit++;
537 else {
538 struct sockaddr_in6 *dst6;
539
525 if (ip6_forward_rt.ro_rt) {
526 /* route is down or destination is different */
527 ip6stat.ip6s_forward_cachemiss++;
528 RTFREE(ip6_forward_rt.ro_rt);
529 ip6_forward_rt.ro_rt = 0;
530 }
531
532 bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
540 if (ip6_forward_rt.ro_rt) {
541 /* route is down or destination is different */
542 ip6stat.ip6s_forward_cachemiss++;
543 RTFREE(ip6_forward_rt.ro_rt);
544 ip6_forward_rt.ro_rt = 0;
545 }
546
547 bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
533 ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
534 ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
535 ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst;
548 dst6 = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst;
549 dst6->sin6_len = sizeof(struct sockaddr_in6);
550 dst6->sin6_family = AF_INET6;
551 dst6->sin6_addr = ip6->ip6_dst;
536#ifdef SCOPEDROUTING
537 ip6_forward_rt.ro_dst.sin6_scope_id =
538 in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_dst);
539#endif
540
541 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
542 }
543
544#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
545
546 /*
547 * Accept the packet if the forwarding interface to the destination
548 * according to the routing table is the loopback interface,
549 * unless the associated route has a gateway.
550 * Note that this approach causes to accept a packet if there is a
551 * route to the loopback interface for the destination of the packet.
552 * But we think it's even useful in some situations, e.g. when using
553 * a special daemon which wants to intercept the packet.
552#ifdef SCOPEDROUTING
553 ip6_forward_rt.ro_dst.sin6_scope_id =
554 in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_dst);
555#endif
556
557 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
558 }
559
560#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
561
562 /*
563 * Accept the packet if the forwarding interface to the destination
564 * according to the routing table is the loopback interface,
565 * unless the associated route has a gateway.
566 * Note that this approach causes to accept a packet if there is a
567 * route to the loopback interface for the destination of the packet.
568 * But we think it's even useful in some situations, e.g. when using
569 * a special daemon which wants to intercept the packet.
570 *
571 * XXX: some OSes automatically make a cloned route for the destination
572 * of an outgoing packet. If the outgoing interface of the packet
573 * is a loopback one, the kernel would consider the packet to be
574 * accepted, even if we have no such address assinged on the interface.
575 * We check the cloned flag of the route entry to reject such cases,
576 * assuming that route entries for our own addresses are not made by
577 * cloning (it should be true because in6_addloop explicitly installs
578 * the host route). However, we might have to do an explicit check
579 * while it would be less efficient. Or, should we rather install a
580 * reject route for such a case?
554 */
555 if (ip6_forward_rt.ro_rt &&
556 (ip6_forward_rt.ro_rt->rt_flags &
557 (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
581 */
582 if (ip6_forward_rt.ro_rt &&
583 (ip6_forward_rt.ro_rt->rt_flags &
584 (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
585#ifdef RTF_WASCLONED
586 !(ip6_forward_rt.ro_rt->rt_flags & RTF_WASCLONED) &&
587#endif
588#ifdef RTF_CLONED
589 !(ip6_forward_rt.ro_rt->rt_flags & RTF_CLONED) &&
590#endif
558#if 0
559 /*
560 * The check below is redundant since the comparison of
561 * the destination and the key of the rtentry has
562 * already done through looking up the routing table.
563 */
564 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
591#if 0
592 /*
593 * The check below is redundant since the comparison of
594 * the destination and the key of the rtentry has
595 * already done through looking up the routing table.
596 */
597 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
565 &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) &&
598 &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr)
566#endif
567 ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
568 struct in6_ifaddr *ia6 =
569 (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
599#endif
600 ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
601 struct in6_ifaddr *ia6 =
602 (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
570 if (ia6->ia6_flags & IN6_IFF_ANYCAST)
571 m->m_flags |= M_ANYCAST6;
603
572 /*
604 /*
605 * record address information into m_aux.
606 */
607 (void)ip6_setdstifaddr(m, ia6);
608
609 /*
573 * packets to a tentative, duplicated, or somehow invalid
574 * address must not be accepted.
575 */
576 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
577 /* this address is ready */
578 ours = 1;
579 deliverifp = ia6->ia_ifp; /* correct? */
610 * packets to a tentative, duplicated, or somehow invalid
611 * address must not be accepted.
612 */
613 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
614 /* this address is ready */
615 ours = 1;
616 deliverifp = ia6->ia_ifp; /* correct? */
580
581 /* Count the packet in the ip address stats */
582 ia6->ia_ifa.if_ipackets++;
583 ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
617 /* Count the packet in the ip address stats */
618 ia6->ia_ifa.if_ipackets++;
619 ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
584
585 goto hbhcheck;
586 } else {
587 /* address is not ready, so discard the packet. */
620 goto hbhcheck;
621 } else {
622 /* address is not ready, so discard the packet. */
588 log(LOG_INFO,
589 "ip6_input: packet to an unready address %s->%s",
623 nd6log((LOG_INFO,
624 "ip6_input: packet to an unready address %s->%s\n",
590 ip6_sprintf(&ip6->ip6_src),
625 ip6_sprintf(&ip6->ip6_src),
591 ip6_sprintf(&ip6->ip6_dst));
626 ip6_sprintf(&ip6->ip6_dst)));
592
593 goto bad;
594 }
595 }
627
628 goto bad;
629 }
630 }
631 } /* XXX indentation (see above) */
596
597 /*
598 * FAITH(Firewall Aided Internet Translator)
599 */
600#if defined(NFAITH) && 0 < NFAITH
601 if (ip6_keepfaith) {
602 if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
603 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {

--- 12 unchanged lines hidden (view full) ---

616 if (!ip6_forwarding) {
617 ip6stat.ip6s_cantforward++;
618 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
619 goto bad;
620 }
621
622 hbhcheck:
623 /*
632
633 /*
634 * FAITH(Firewall Aided Internet Translator)
635 */
636#if defined(NFAITH) && 0 < NFAITH
637 if (ip6_keepfaith) {
638 if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
639 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {

--- 12 unchanged lines hidden (view full) ---

652 if (!ip6_forwarding) {
653 ip6stat.ip6s_cantforward++;
654 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
655 goto bad;
656 }
657
658 hbhcheck:
659 /*
660 * record address information into m_aux, if we don't have one yet.
661 * note that we are unable to record it, if the address is not listed
662 * as our interface address (e.g. multicast addresses, addresses
663 * within FAITH prefixes and such).
664 */
665 if (deliverifp && !ip6_getdstifaddr(m)) {
666 struct in6_ifaddr *ia6;
667
668 ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
669 if (ia6) {
670 if (!ip6_setdstifaddr(m, ia6)) {
671 /*
672 * XXX maybe we should drop the packet here,
673 * as we could not provide enough information
674 * to the upper layers.
675 */
676 }
677 }
678 }
679
680 /*
624 * Process Hop-by-Hop options header if it's contained.
625 * m may be modified in ip6_hopopts_input().
626 * If a JumboPayload option is included, plen will also be modified.
627 */
628 plen = (u_int32_t)ntohs(ip6->ip6_plen);
629 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
630 struct ip6_hbh *hbh;
631

--- 112 unchanged lines hidden (view full) ---

744 }
745
746 /*
747 * Tell launch routine the next header
748 */
749 ip6stat.ip6s_delivered++;
750 in6_ifstat_inc(deliverifp, ifs6_in_deliver);
751 nest = 0;
681 * Process Hop-by-Hop options header if it's contained.
682 * m may be modified in ip6_hopopts_input().
683 * If a JumboPayload option is included, plen will also be modified.
684 */
685 plen = (u_int32_t)ntohs(ip6->ip6_plen);
686 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
687 struct ip6_hbh *hbh;
688

--- 112 unchanged lines hidden (view full) ---

801 }
802
803 /*
804 * Tell launch routine the next header
805 */
806 ip6stat.ip6s_delivered++;
807 in6_ifstat_inc(deliverifp, ifs6_in_deliver);
808 nest = 0;
809
752 while (nxt != IPPROTO_DONE) {
753 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
754 ip6stat.ip6s_toomanyhdr++;
755 goto bad;
756 }
757
758 /*
759 * protection against faulty packet - there should be
760 * more sanity checks in header chain processing.
761 */
762 if (m->m_pkthdr.len < off) {
763 ip6stat.ip6s_tooshort++;
764 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
765 goto bad;
766 }
767
810 while (nxt != IPPROTO_DONE) {
811 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
812 ip6stat.ip6s_toomanyhdr++;
813 goto bad;
814 }
815
816 /*
817 * protection against faulty packet - there should be
818 * more sanity checks in header chain processing.
819 */
820 if (m->m_pkthdr.len < off) {
821 ip6stat.ip6s_tooshort++;
822 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
823 goto bad;
824 }
825
826#if 0
827 /*
828 * do we need to do it for every header? yeah, other
829 * functions can play with it (like re-allocate and copy).
830 */
831 mhist = ip6_addaux(m);
832 if (mhist && M_TRAILINGSPACE(mhist) >= sizeof(nxt)) {
833 hist = mtod(mhist, caddr_t) + mhist->m_len;
834 bcopy(&nxt, hist, sizeof(nxt));
835 mhist->m_len += sizeof(nxt);
836 } else {
837 ip6stat.ip6s_toomanyhdr++;
838 goto bad;
839 }
840#endif
841
842#ifdef IPSEC
843 /*
844 * enforce IPsec policy checking if we are seeing last header.
845 * note that we do not visit this with protocols with pcb layer
846 * code - like udp/tcp/raw ip.
847 */
848 if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
849 ipsec6_in_reject(m, NULL)) {
850 ipsec6stat.in_polvio++;
851 goto bad;
852 }
853#endif
854
768 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
769 }
770 return;
771 bad:
772 m_freem(m);
773}
774
775/*
855 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
856 }
857 return;
858 bad:
859 m_freem(m);
860}
861
862/*
863 * set/grab in6_ifaddr correspond to IPv6 destination address.
864 * XXX backward compatibility wrapper
865 */
866static struct mbuf *
867ip6_setdstifaddr(m, ia6)
868 struct mbuf *m;
869 struct in6_ifaddr *ia6;
870{
871 struct mbuf *n;
872
873 n = ip6_addaux(m);
874 if (n)
875 mtod(n, struct ip6aux *)->ip6a_dstia6 = ia6;
876 return n; /* NULL if failed to set */
877}
878
879struct in6_ifaddr *
880ip6_getdstifaddr(m)
881 struct mbuf *m;
882{
883 struct mbuf *n;
884
885 n = ip6_findaux(m);
886 if (n)
887 return mtod(n, struct ip6aux *)->ip6a_dstia6;
888 else
889 return NULL;
890}
891
892/*
776 * Hop-by-Hop options header processing. If a valid jumbo payload option is
777 * included, the real payload length will be stored in plenp.
778 */
779static int
780ip6_hopopts_input(plenp, rtalertp, mp, offp)
781 u_int32_t *plenp;
782 u_int32_t *rtalertp; /* XXX: should be stored more smart way */
783 struct mbuf **mp;
784 int *offp;
785{
893 * Hop-by-Hop options header processing. If a valid jumbo payload option is
894 * included, the real payload length will be stored in plenp.
895 */
896static int
897ip6_hopopts_input(plenp, rtalertp, mp, offp)
898 u_int32_t *plenp;
899 u_int32_t *rtalertp; /* XXX: should be stored more smart way */
900 struct mbuf **mp;
901 int *offp;
902{
786 register struct mbuf *m = *mp;
903 struct mbuf *m = *mp;
787 int off = *offp, hbhlen;
788 struct ip6_hbh *hbh;
789 u_int8_t *opt;
790
791 /* validation of the length of the header */
792#ifndef PULLDOWN_TEST
793 IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
794 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);

--- 29 unchanged lines hidden (view full) ---

824 return(0);
825}
826
827/*
828 * Search header for all Hop-by-hop options and process each option.
829 * This function is separate from ip6_hopopts_input() in order to
830 * handle a case where the sending node itself process its hop-by-hop
831 * options header. In such a case, the function is called from ip6_output().
904 int off = *offp, hbhlen;
905 struct ip6_hbh *hbh;
906 u_int8_t *opt;
907
908 /* validation of the length of the header */
909#ifndef PULLDOWN_TEST
910 IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
911 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);

--- 29 unchanged lines hidden (view full) ---

941 return(0);
942}
943
944/*
945 * Search header for all Hop-by-hop options and process each option.
946 * This function is separate from ip6_hopopts_input() in order to
947 * handle a case where the sending node itself process its hop-by-hop
948 * options header. In such a case, the function is called from ip6_output().
949 *
950 * The function assumes that hbh header is located right after the IPv6 header
951 * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
952 * opthead + hbhlen is located in continuous memory region.
832 */
833int
834ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
835 struct mbuf *m;
836 u_int8_t *opthead;
837 int hbhlen;
838 u_int32_t *rtalertp;
839 u_int32_t *plenp;
840{
841 struct ip6_hdr *ip6;
842 int optlen = 0;
843 u_int8_t *opt = opthead;
844 u_int16_t rtalert_val;
845 u_int32_t jumboplen;
953 */
954int
955ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
956 struct mbuf *m;
957 u_int8_t *opthead;
958 int hbhlen;
959 u_int32_t *rtalertp;
960 u_int32_t *plenp;
961{
962 struct ip6_hdr *ip6;
963 int optlen = 0;
964 u_int8_t *opt = opthead;
965 u_int16_t rtalert_val;
966 u_int32_t jumboplen;
967 const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
846
847 for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
968
969 for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
848 switch(*opt) {
849 case IP6OPT_PAD1:
850 optlen = 1;
851 break;
852 case IP6OPT_PADN:
853 if (hbhlen < IP6OPT_MINLEN) {
854 ip6stat.ip6s_toosmall++;
855 goto bad;
856 }
857 optlen = *(opt + 1) + 2;
858 break;
859 case IP6OPT_RTALERT:
860 /* XXX may need check for alignment */
861 if (hbhlen < IP6OPT_RTALERT_LEN) {
862 ip6stat.ip6s_toosmall++;
863 goto bad;
864 }
865 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2)
866 /* XXX: should we discard the packet? */
867 log(LOG_ERR, "length of router alert opt is inconsitent(%d)",
868 *(opt + 1));
869 optlen = IP6OPT_RTALERT_LEN;
870 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
871 *rtalertp = ntohs(rtalert_val);
872 break;
873 case IP6OPT_JUMBO:
970 switch (*opt) {
971 case IP6OPT_PAD1:
972 optlen = 1;
973 break;
974 case IP6OPT_PADN:
975 if (hbhlen < IP6OPT_MINLEN) {
976 ip6stat.ip6s_toosmall++;
977 goto bad;
978 }
979 optlen = *(opt + 1) + 2;
980 break;
981 case IP6OPT_RTALERT:
874 /* XXX may need check for alignment */
982 /* XXX may need check for alignment */
983 if (hbhlen < IP6OPT_RTALERT_LEN) {
984 ip6stat.ip6s_toosmall++;
985 goto bad;
986 }
987 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
988 /* XXX stat */
989 icmp6_error(m, ICMP6_PARAM_PROB,
990 ICMP6_PARAMPROB_HEADER,
991 erroff + opt + 1 - opthead);
992 return(-1);
993 }
994 optlen = IP6OPT_RTALERT_LEN;
995 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
996 *rtalertp = ntohs(rtalert_val);
997 break;
998 case IP6OPT_JUMBO:
999 /* XXX may need check for alignment */
875 if (hbhlen < IP6OPT_JUMBO_LEN) {
876 ip6stat.ip6s_toosmall++;
877 goto bad;
878 }
1000 if (hbhlen < IP6OPT_JUMBO_LEN) {
1001 ip6stat.ip6s_toosmall++;
1002 goto bad;
1003 }
879 if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
880 /* XXX: should we discard the packet? */
881 log(LOG_ERR, "length of jumbopayload opt "
882 "is inconsistent(%d)",
883 *(opt + 1));
1004 if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
1005 /* XXX stat */
1006 icmp6_error(m, ICMP6_PARAM_PROB,
1007 ICMP6_PARAMPROB_HEADER,
1008 erroff + opt + 1 - opthead);
1009 return(-1);
1010 }
884 optlen = IP6OPT_JUMBO_LEN;
885
886 /*
887 * IPv6 packets that have non 0 payload length
1011 optlen = IP6OPT_JUMBO_LEN;
1012
1013 /*
1014 * IPv6 packets that have non 0 payload length
888 * must not contain a jumbo paylod option.
1015 * must not contain a jumbo payload option.
889 */
890 ip6 = mtod(m, struct ip6_hdr *);
891 if (ip6->ip6_plen) {
892 ip6stat.ip6s_badoptions++;
893 icmp6_error(m, ICMP6_PARAM_PROB,
894 ICMP6_PARAMPROB_HEADER,
1016 */
1017 ip6 = mtod(m, struct ip6_hdr *);
1018 if (ip6->ip6_plen) {
1019 ip6stat.ip6s_badoptions++;
1020 icmp6_error(m, ICMP6_PARAM_PROB,
1021 ICMP6_PARAMPROB_HEADER,
895 sizeof(struct ip6_hdr) +
896 sizeof(struct ip6_hbh) +
897 opt - opthead);
1022 erroff + opt - opthead);
898 return(-1);
899 }
900
901 /*
902 * We may see jumbolen in unaligned location, so
903 * we'd need to perform bcopy().
904 */
905 bcopy(opt + 2, &jumboplen, sizeof(jumboplen));

--- 7 unchanged lines hidden (view full) ---

913 * the behavior may need some debate in ipngwg -
914 * multiple options does not make sense, however,
915 * there's no explicit mention in specification.
916 */
917 if (*plenp != 0) {
918 ip6stat.ip6s_badoptions++;
919 icmp6_error(m, ICMP6_PARAM_PROB,
920 ICMP6_PARAMPROB_HEADER,
1023 return(-1);
1024 }
1025
1026 /*
1027 * We may see jumbolen in unaligned location, so
1028 * we'd need to perform bcopy().
1029 */
1030 bcopy(opt + 2, &jumboplen, sizeof(jumboplen));

--- 7 unchanged lines hidden (view full) ---

1038 * the behavior may need some debate in ipngwg -
1039 * multiple options does not make sense, however,
1040 * there's no explicit mention in specification.
1041 */
1042 if (*plenp != 0) {
1043 ip6stat.ip6s_badoptions++;
1044 icmp6_error(m, ICMP6_PARAM_PROB,
1045 ICMP6_PARAMPROB_HEADER,
921 sizeof(struct ip6_hdr) +
922 sizeof(struct ip6_hbh) +
923 opt + 2 - opthead);
1046 erroff + opt + 2 - opthead);
924 return(-1);
925 }
926#endif
927
928 /*
929 * jumbo payload length must be larger than 65535.
930 */
931 if (jumboplen <= IPV6_MAXPACKET) {
932 ip6stat.ip6s_badoptions++;
933 icmp6_error(m, ICMP6_PARAM_PROB,
934 ICMP6_PARAMPROB_HEADER,
1047 return(-1);
1048 }
1049#endif
1050
1051 /*
1052 * jumbo payload length must be larger than 65535.
1053 */
1054 if (jumboplen <= IPV6_MAXPACKET) {
1055 ip6stat.ip6s_badoptions++;
1056 icmp6_error(m, ICMP6_PARAM_PROB,
1057 ICMP6_PARAMPROB_HEADER,
935 sizeof(struct ip6_hdr) +
936 sizeof(struct ip6_hbh) +
937 opt + 2 - opthead);
1058 erroff + opt + 2 - opthead);
938 return(-1);
939 }
940 *plenp = jumboplen;
941
942 break;
1059 return(-1);
1060 }
1061 *plenp = jumboplen;
1062
1063 break;
943 default: /* unknown option */
944 if (hbhlen < IP6OPT_MINLEN) {
945 ip6stat.ip6s_toosmall++;
946 goto bad;
947 }
948 if ((optlen = ip6_unknown_opt(opt, m,
949 sizeof(struct ip6_hdr) +
950 sizeof(struct ip6_hbh) +
951 opt - opthead)) == -1)
952 return(-1);
953 optlen += 2;
954 break;
1064 default: /* unknown option */
1065 if (hbhlen < IP6OPT_MINLEN) {
1066 ip6stat.ip6s_toosmall++;
1067 goto bad;
1068 }
1069 optlen = ip6_unknown_opt(opt, m,
1070 erroff + opt - opthead);
1071 if (optlen == -1)
1072 return(-1);
1073 optlen += 2;
1074 break;
955 }
956 }
957
958 return(0);
959
960 bad:
961 m_freem(m);
962 return(-1);

--- 8 unchanged lines hidden (view full) ---

971int
972ip6_unknown_opt(optp, m, off)
973 u_int8_t *optp;
974 struct mbuf *m;
975 int off;
976{
977 struct ip6_hdr *ip6;
978
1075 }
1076 }
1077
1078 return(0);
1079
1080 bad:
1081 m_freem(m);
1082 return(-1);

--- 8 unchanged lines hidden (view full) ---

1091int
1092ip6_unknown_opt(optp, m, off)
1093 u_int8_t *optp;
1094 struct mbuf *m;
1095 int off;
1096{
1097 struct ip6_hdr *ip6;
1098
979 switch(IP6OPT_TYPE(*optp)) {
980 case IP6OPT_TYPE_SKIP: /* ignore the option */
981 return((int)*(optp + 1));
982 case IP6OPT_TYPE_DISCARD: /* silently discard */
983 m_freem(m);
984 return(-1);
985 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
986 ip6stat.ip6s_badoptions++;
987 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
988 return(-1);
989 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
990 ip6stat.ip6s_badoptions++;
991 ip6 = mtod(m, struct ip6_hdr *);
992 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
993 (m->m_flags & (M_BCAST|M_MCAST)))
994 m_freem(m);
995 else
996 icmp6_error(m, ICMP6_PARAM_PROB,
997 ICMP6_PARAMPROB_OPTION, off);
998 return(-1);
1099 switch (IP6OPT_TYPE(*optp)) {
1100 case IP6OPT_TYPE_SKIP: /* ignore the option */
1101 return((int)*(optp + 1));
1102 case IP6OPT_TYPE_DISCARD: /* silently discard */
1103 m_freem(m);
1104 return(-1);
1105 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
1106 ip6stat.ip6s_badoptions++;
1107 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
1108 return(-1);
1109 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
1110 ip6stat.ip6s_badoptions++;
1111 ip6 = mtod(m, struct ip6_hdr *);
1112 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
1113 (m->m_flags & (M_BCAST|M_MCAST)))
1114 m_freem(m);
1115 else
1116 icmp6_error(m, ICMP6_PARAM_PROB,
1117 ICMP6_PARAMPROB_OPTION, off);
1118 return(-1);
999 }
1000
1001 m_freem(m); /* XXX: NOTREACHED */
1002 return(-1);
1003}
1004
1005/*
1006 * Create the "control" list for this pcb.
1119 }
1120
1121 m_freem(m); /* XXX: NOTREACHED */
1122 return(-1);
1123}
1124
1125/*
1126 * Create the "control" list for this pcb.
1127 * The function will not modify mbuf chain at all.
1007 *
1128 *
1129 * with KAME mbuf chain restriction:
1008 * The routine will be called from upper layer handlers like tcp6_input().
1009 * Thus the routine assumes that the caller (tcp6_input) have already
1010 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
1011 * very first mbuf on the mbuf chain.
1130 * The routine will be called from upper layer handlers like tcp6_input().
1131 * Thus the routine assumes that the caller (tcp6_input) have already
1132 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
1133 * very first mbuf on the mbuf chain.
1012 * We may want to add some infinite loop prevention or sanity checks for safety.
1013 * (This applies only when you are using KAME mbuf chain restriction, i.e.
1014 * you are using IP6_EXTHDR_CHECK() not m_pulldown())
1015 */
1016void
1017ip6_savecontrol(in6p, mp, ip6, m)
1134 */
1135void
1136ip6_savecontrol(in6p, mp, ip6, m)
1018 register struct in6pcb *in6p;
1019 register struct mbuf **mp;
1020 register struct ip6_hdr *ip6;
1021 register struct mbuf *m;
1137 struct inpcb *in6p;
1138 struct mbuf **mp;
1139 struct ip6_hdr *ip6;
1140 struct mbuf *m;
1022{
1023 struct proc *p = curproc; /* XXX */
1141{
1142 struct proc *p = curproc; /* XXX */
1024 int privileged;
1143 int privileged = 0;
1144 int rthdr_exist = 0;
1025
1145
1026 privileged = 0;
1146
1027 if (p && !suser(p))
1147 if (p && !suser(p))
1028 privileged++;
1148 privileged++;
1029
1149
1030 if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
1150#ifdef SO_TIMESTAMP
1151 if ((in6p->in6p_socket->so_options & SO_TIMESTAMP) != 0) {
1031 struct timeval tv;
1032
1033 microtime(&tv);
1034 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1152 struct timeval tv;
1153
1154 microtime(&tv);
1155 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1035 SCM_TIMESTAMP, SOL_SOCKET);
1036 if (*mp)
1156 SCM_TIMESTAMP, SOL_SOCKET);
1157 if (*mp) {
1037 mp = &(*mp)->m_next;
1158 mp = &(*mp)->m_next;
1159 }
1038 }
1160 }
1039
1040#ifdef noyet
1041 /* options were tossed above */
1042 if (in6p->in6p_flags & IN6P_RECVOPTS)
1043 /* broken */
1044 /* ip6_srcroute doesn't do what we want here, need to fix */
1045 if (in6p->in6p_flags & IPV6P_RECVRETOPTS)
1046 /* broken */
1047#endif
1048
1049 /* RFC 2292 sec. 5 */
1161#endif
1162
1163 /* RFC 2292 sec. 5 */
1050 if (in6p->in6p_flags & IN6P_PKTINFO) {
1164 if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) {
1051 struct in6_pktinfo pi6;
1052 bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1053 if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
1054 pi6.ipi6_addr.s6_addr16[1] = 0;
1055 pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
1056 ? m->m_pkthdr.rcvif->if_index
1057 : 0;
1058 *mp = sbcreatecontrol((caddr_t) &pi6,
1059 sizeof(struct in6_pktinfo), IPV6_PKTINFO,
1060 IPPROTO_IPV6);
1061 if (*mp)
1062 mp = &(*mp)->m_next;
1063 }
1165 struct in6_pktinfo pi6;
1166 bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1167 if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
1168 pi6.ipi6_addr.s6_addr16[1] = 0;
1169 pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
1170 ? m->m_pkthdr.rcvif->if_index
1171 : 0;
1172 *mp = sbcreatecontrol((caddr_t) &pi6,
1173 sizeof(struct in6_pktinfo), IPV6_PKTINFO,
1174 IPPROTO_IPV6);
1175 if (*mp)
1176 mp = &(*mp)->m_next;
1177 }
1064 if (in6p->in6p_flags & IN6P_HOPLIMIT) {
1178
1179 if ((in6p->in6p_flags & IN6P_HOPLIMIT) != 0) {
1065 int hlim = ip6->ip6_hlim & 0xff;
1066 *mp = sbcreatecontrol((caddr_t) &hlim,
1067 sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
1068 if (*mp)
1069 mp = &(*mp)->m_next;
1070 }
1180 int hlim = ip6->ip6_hlim & 0xff;
1181 *mp = sbcreatecontrol((caddr_t) &hlim,
1182 sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
1183 if (*mp)
1184 mp = &(*mp)->m_next;
1185 }
1071 /* IN6P_NEXTHOP - for outgoing packet only */
1072
1073 /*
1074 * IPV6_HOPOPTS socket option. We require super-user privilege
1075 * for the option, but it might be too strict, since there might
1076 * be some hop-by-hop options which can be returned to normal user.
1077 * See RFC 2292 section 6.
1078 */
1186
1187 /*
1188 * IPV6_HOPOPTS socket option. We require super-user privilege
1189 * for the option, but it might be too strict, since there might
1190 * be some hop-by-hop options which can be returned to normal user.
1191 * See RFC 2292 section 6.
1192 */
1079 if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
1193 if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0 && privileged) {
1080 /*
1081 * Check if a hop-by-hop options header is contatined in the
1082 * received packet, and if so, store the options as ancillary
1083 * data. Note that a hop-by-hop options header must be
1084 * just after the IPv6 header, which fact is assured through
1085 * the IPv6 input processing.
1086 */
1087 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1088 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1089 struct ip6_hbh *hbh;
1194 /*
1195 * Check if a hop-by-hop options header is contatined in the
1196 * received packet, and if so, store the options as ancillary
1197 * data. Note that a hop-by-hop options header must be
1198 * just after the IPv6 header, which fact is assured through
1199 * the IPv6 input processing.
1200 */
1201 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1202 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1203 struct ip6_hbh *hbh;
1090 int hbhlen;
1204 int hbhlen = 0;
1205#ifdef PULLDOWN_TEST
1206 struct mbuf *ext;
1207#endif
1091
1092#ifndef PULLDOWN_TEST
1093 hbh = (struct ip6_hbh *)(ip6 + 1);
1094 hbhlen = (hbh->ip6h_len + 1) << 3;
1095#else
1208
1209#ifndef PULLDOWN_TEST
1210 hbh = (struct ip6_hbh *)(ip6 + 1);
1211 hbhlen = (hbh->ip6h_len + 1) << 3;
1212#else
1096 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
1097 sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
1098 if (hbh == NULL) {
1213 ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
1214 ip6->ip6_nxt);
1215 if (ext == NULL) {
1099 ip6stat.ip6s_tooshort++;
1100 return;
1101 }
1216 ip6stat.ip6s_tooshort++;
1217 return;
1218 }
1219 hbh = mtod(ext, struct ip6_hbh *);
1102 hbhlen = (hbh->ip6h_len + 1) << 3;
1220 hbhlen = (hbh->ip6h_len + 1) << 3;
1103 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
1104 sizeof(struct ip6_hdr), hbhlen);
1105 if (hbh == NULL) {
1221 if (hbhlen != ext->m_len) {
1222 m_freem(ext);
1106 ip6stat.ip6s_tooshort++;
1107 return;
1108 }
1109#endif
1110
1111 /*
1112 * XXX: We copy whole the header even if a jumbo
1113 * payload option is included, which option is to
1114 * be removed before returning in the RFC 2292.
1223 ip6stat.ip6s_tooshort++;
1224 return;
1225 }
1226#endif
1227
1228 /*
1229 * XXX: We copy whole the header even if a jumbo
1230 * payload option is included, which option is to
1231 * be removed before returning in the RFC 2292.
1115 * But it's too painful operation...
1232 * Note: this constraint is removed in 2292bis.
1116 */
1117 *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1118 IPV6_HOPOPTS, IPPROTO_IPV6);
1119 if (*mp)
1120 mp = &(*mp)->m_next;
1233 */
1234 *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1235 IPV6_HOPOPTS, IPPROTO_IPV6);
1236 if (*mp)
1237 mp = &(*mp)->m_next;
1238#ifdef PULLDOWN_TEST
1239 m_freem(ext);
1240#endif
1121 }
1122 }
1123
1124 /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
1241 }
1242 }
1243
1244 /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
1125 if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) {
1245 if ((in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
1246 int proto, off, nxt;
1247
1248 /*
1249 * go through the header chain to see if a routing header is
1250 * contained in the packet. We need this information to store
1251 * destination options headers (if any) properly.
1252 * XXX: performance issue. We should record this info when
1253 * processing extension headers in incoming routine.
1254 * (todo) use m_aux?
1255 */
1256 proto = IPPROTO_IPV6;
1257 off = 0;
1258 nxt = -1;
1259 while (1) {
1260 int newoff;
1261
1262 newoff = ip6_nexthdr(m, off, proto, &nxt);
1263 if (newoff < 0)
1264 break;
1265 if (newoff < off) /* invalid, check for safety */
1266 break;
1267 if ((proto = nxt) == IPPROTO_ROUTING) {
1268 rthdr_exist = 1;
1269 break;
1270 }
1271 off = newoff;
1272 }
1273 }
1274
1275 if ((in6p->in6p_flags &
1276 (IN6P_RTHDR | IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
1126 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1277 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1127 int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);;
1278 int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
1128
1129 /*
1130 * Search for destination options headers or routing
1131 * header(s) through the header chain, and stores each
1132 * header as ancillary data.
1133 * Note that the order of the headers remains in
1134 * the chain of ancillary data.
1135 */
1279
1280 /*
1281 * Search for destination options headers or routing
1282 * header(s) through the header chain, and stores each
1283 * header as ancillary data.
1284 * Note that the order of the headers remains in
1285 * the chain of ancillary data.
1286 */
1136 while(1) { /* is explicit loop prevention necessary? */
1137 struct ip6_ext *ip6e;
1287 while (1) { /* is explicit loop prevention necessary? */
1288 struct ip6_ext *ip6e = NULL;
1138 int elen;
1289 int elen;
1290#ifdef PULLDOWN_TEST
1291 struct mbuf *ext = NULL;
1292#endif
1139
1293
1294 /*
1295 * if it is not an extension header, don't try to
1296 * pull it from the chain.
1297 */
1298 switch (nxt) {
1299 case IPPROTO_DSTOPTS:
1300 case IPPROTO_ROUTING:
1301 case IPPROTO_HOPOPTS:
1302 case IPPROTO_AH: /* is it possible? */
1303 break;
1304 default:
1305 goto loopend;
1306 }
1307
1140#ifndef PULLDOWN_TEST
1308#ifndef PULLDOWN_TEST
1309 if (off + sizeof(*ip6e) > m->m_len)
1310 goto loopend;
1141 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
1142 if (nxt == IPPROTO_AH)
1143 elen = (ip6e->ip6e_len + 2) << 2;
1144 else
1145 elen = (ip6e->ip6e_len + 1) << 3;
1311 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
1312 if (nxt == IPPROTO_AH)
1313 elen = (ip6e->ip6e_len + 2) << 2;
1314 else
1315 elen = (ip6e->ip6e_len + 1) << 3;
1316 if (off + elen > m->m_len)
1317 goto loopend;
1146#else
1318#else
1147 IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off,
1148 sizeof(struct ip6_ext));
1149 if (ip6e == NULL) {
1319 ext = ip6_pullexthdr(m, off, nxt);
1320 if (ext == NULL) {
1150 ip6stat.ip6s_tooshort++;
1151 return;
1152 }
1321 ip6stat.ip6s_tooshort++;
1322 return;
1323 }
1324 ip6e = mtod(ext, struct ip6_ext *);
1153 if (nxt == IPPROTO_AH)
1154 elen = (ip6e->ip6e_len + 2) << 2;
1155 else
1156 elen = (ip6e->ip6e_len + 1) << 3;
1325 if (nxt == IPPROTO_AH)
1326 elen = (ip6e->ip6e_len + 2) << 2;
1327 else
1328 elen = (ip6e->ip6e_len + 1) << 3;
1157 IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off, elen);
1158 if (ip6e == NULL) {
1329 if (elen != ext->m_len) {
1330 m_freem(ext);
1159 ip6stat.ip6s_tooshort++;
1160 return;
1161 }
1162#endif
1163
1331 ip6stat.ip6s_tooshort++;
1332 return;
1333 }
1334#endif
1335
1164 switch(nxt) {
1165 case IPPROTO_DSTOPTS:
1166 if (!in6p->in6p_flags & IN6P_DSTOPTS)
1167 break;
1336 switch (nxt) {
1337 case IPPROTO_DSTOPTS:
1338 if ((in6p->in6p_flags & IN6P_DSTOPTS) == 0)
1339 break;
1168
1340
1169 /*
1170 * We also require super-user privilege for
1171 * the option.
1172 * See the comments on IN6_HOPOPTS.
1173 */
1174 if (!privileged)
1175 break;
1341 /*
1342 * We also require super-user privilege for
1343 * the option.
1344 * See the comments on IN6_HOPOPTS.
1345 */
1346 if (!privileged)
1347 break;
1176
1348
1177 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1178 IPV6_DSTOPTS,
1179 IPPROTO_IPV6);
1180 if (*mp)
1181 mp = &(*mp)->m_next;
1182 break;
1349 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1350 IPV6_DSTOPTS,
1351 IPPROTO_IPV6);
1352 if (*mp)
1353 mp = &(*mp)->m_next;
1354 break;
1355 case IPPROTO_ROUTING:
1356 if (!in6p->in6p_flags & IN6P_RTHDR)
1357 break;
1183
1358
1184 case IPPROTO_ROUTING:
1185 if (!in6p->in6p_flags & IN6P_RTHDR)
1186 break;
1359 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1360 IPV6_RTHDR,
1361 IPPROTO_IPV6);
1362 if (*mp)
1363 mp = &(*mp)->m_next;
1364 break;
1365 case IPPROTO_HOPOPTS:
1366 case IPPROTO_AH: /* is it possible? */
1367 break;
1187
1368
1188 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1189 IPV6_RTHDR,
1190 IPPROTO_IPV6);
1191 if (*mp)
1192 mp = &(*mp)->m_next;
1193 break;
1369 default:
1370 /*
1371 * other cases have been filtered in the above.
1372 * none will visit this case. here we supply
1373 * the code just in case (nxt overwritten or
1374 * other cases).
1375 */
1376#ifdef PULLDOWN_TEST
1377 m_freem(ext);
1378#endif
1379 goto loopend;
1194
1380
1195 case IPPROTO_UDP:
1196 case IPPROTO_TCP:
1197 case IPPROTO_ICMPV6:
1198 default:
1199 /*
1200 * stop search if we encounter an upper
1201 * layer protocol headers.
1202 */
1203 goto loopend;
1204
1205 case IPPROTO_HOPOPTS:
1206 case IPPROTO_AH: /* is it possible? */
1207 break;
1208 }
1209
1210 /* proceed with the next header. */
1211 off += elen;
1212 nxt = ip6e->ip6e_nxt;
1381 }
1382
1383 /* proceed with the next header. */
1384 off += elen;
1385 nxt = ip6e->ip6e_nxt;
1386 ip6e = NULL;
1387#ifdef PULLDOWN_TEST
1388 m_freem(ext);
1389 ext = NULL;
1390#endif
1213 }
1214 loopend:
1391 }
1392 loopend:
1393 ;
1215 }
1394 }
1216 if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
1217 /* to be done */
1395
1396}
1397
1398#ifdef PULLDOWN_TEST
1399/*
1400 * pull single extension header from mbuf chain. returns single mbuf that
1401 * contains the result, or NULL on error.
1402 */
1403static struct mbuf *
1404ip6_pullexthdr(m, off, nxt)
1405 struct mbuf *m;
1406 size_t off;
1407 int nxt;
1408{
1409 struct ip6_ext ip6e;
1410 size_t elen;
1411 struct mbuf *n;
1412
1413#ifdef DIAGNOSTIC
1414 switch (nxt) {
1415 case IPPROTO_DSTOPTS:
1416 case IPPROTO_ROUTING:
1417 case IPPROTO_HOPOPTS:
1418 case IPPROTO_AH: /* is it possible? */
1419 break;
1420 default:
1421 printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
1218 }
1422 }
1219 if ((in6p->in6p_flags & IN6P_DSTOPTS) && privileged) {
1220 /* to be done */
1423#endif
1424
1425 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1426 if (nxt == IPPROTO_AH)
1427 elen = (ip6e.ip6e_len + 2) << 2;
1428 else
1429 elen = (ip6e.ip6e_len + 1) << 3;
1430
1431 MGET(n, M_DONTWAIT, MT_DATA);
1432 if (n && elen >= MLEN) {
1433 MCLGET(n, M_DONTWAIT);
1434 if ((n->m_flags & M_EXT) == 0) {
1435 m_free(n);
1436 n = NULL;
1437 }
1221 }
1438 }
1222 /* IN6P_RTHDR - to be done */
1439 if (!n)
1440 return NULL;
1223
1441
1442 n->m_len = 0;
1443 if (elen >= M_TRAILINGSPACE(n)) {
1444 m_free(n);
1445 return NULL;
1446 }
1447
1448 m_copydata(m, off, elen, mtod(n, caddr_t));
1449 n->m_len = elen;
1450 return n;
1224}
1451}
1452#endif
1225
1226/*
1227 * Get pointer to the previous header followed by the header
1228 * currently processed.
1229 * XXX: This function supposes that
1230 * M includes all headers,
1231 * the next header field and the header length field of each header
1232 * are valid, and

--- 15 unchanged lines hidden (view full) ---

1248 int len, nxt;
1249 struct ip6_ext *ip6e = NULL;
1250
1251 nxt = ip6->ip6_nxt;
1252 len = sizeof(struct ip6_hdr);
1253 while (len < off) {
1254 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
1255
1453
1454/*
1455 * Get pointer to the previous header followed by the header
1456 * currently processed.
1457 * XXX: This function supposes that
1458 * M includes all headers,
1459 * the next header field and the header length field of each header
1460 * are valid, and

--- 15 unchanged lines hidden (view full) ---

1476 int len, nxt;
1477 struct ip6_ext *ip6e = NULL;
1478
1479 nxt = ip6->ip6_nxt;
1480 len = sizeof(struct ip6_hdr);
1481 while (len < off) {
1482 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
1483
1256 switch(nxt) {
1484 switch (nxt) {
1257 case IPPROTO_FRAGMENT:
1258 len += sizeof(struct ip6_frag);
1259 break;
1260 case IPPROTO_AH:
1261 len += (ip6e->ip6e_len + 2) << 2;
1262 break;
1263 default:
1264 len += (ip6e->ip6e_len + 1) << 3;

--- 112 unchanged lines hidden (view full) ---

1377 else if (newoff == off)
1378 return newoff;
1379
1380 off = newoff;
1381 proto = *nxtp;
1382 }
1383}
1384
1485 case IPPROTO_FRAGMENT:
1486 len += sizeof(struct ip6_frag);
1487 break;
1488 case IPPROTO_AH:
1489 len += (ip6e->ip6e_len + 2) << 2;
1490 break;
1491 default:
1492 len += (ip6e->ip6e_len + 1) << 3;

--- 112 unchanged lines hidden (view full) ---

1605 else if (newoff == off)
1606 return newoff;
1607
1608 off = newoff;
1609 proto = *nxtp;
1610 }
1611}
1612
1613struct mbuf *
1614ip6_addaux(m)
1615 struct mbuf *m;
1616{
1617 struct mbuf *n;
1618
1619#ifdef DIAGNOSTIC
1620 if (sizeof(struct ip6aux) > MHLEN)
1621 panic("assumption failed on sizeof(ip6aux)");
1622#endif
1623 n = m_aux_find(m, AF_INET6, -1);
1624 if (n) {
1625 if (n->m_len < sizeof(struct ip6aux)) {
1626 printf("conflicting use of ip6aux");
1627 return NULL;
1628 }
1629 } else {
1630 n = m_aux_add(m, AF_INET6, -1);
1631 n->m_len = sizeof(struct ip6aux);
1632 bzero(mtod(n, caddr_t), n->m_len);
1633 }
1634 return n;
1635}
1636
1637struct mbuf *
1638ip6_findaux(m)
1639 struct mbuf *m;
1640{
1641 struct mbuf *n;
1642
1643 n = m_aux_find(m, AF_INET6, -1);
1644 if (n && n->m_len < sizeof(struct ip6aux)) {
1645 printf("conflicting use of ip6aux");
1646 n = NULL;
1647 }
1648 return n;
1649}
1650
1651void
1652ip6_delaux(m)
1653 struct mbuf *m;
1654{
1655 struct mbuf *n;
1656
1657 n = m_aux_find(m, AF_INET6, -1);
1658 if (n)
1659 m_aux_delete(m, n);
1660}
1661
1385/*
1386 * System control for IP6
1387 */
1388
1389u_char inet6ctlerrmap[PRC_NCMDS] = {
1390 0, 0, 0, 0,
1391 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1392 EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1393 EMSGSIZE, EHOSTUNREACH, 0, 0,
1394 0, 0, 0, 0,
1395 ENOPROTOOPT
1396};
1662/*
1663 * System control for IP6
1664 */
1665
1666u_char inet6ctlerrmap[PRC_NCMDS] = {
1667 0, 0, 0, 0,
1668 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1669 EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1670 EMSGSIZE, EHOSTUNREACH, 0, 0,
1671 0, 0, 0, 0,
1672 ENOPROTOOPT
1673};