source: rtems-libbsd/freebsd/sys/netinet6/ip6_input.c @ 2017a6d

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 2017a6d was 2017a6d, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/16 at 07:48:12

Directly use <sys/time.h> provided by Newlib

  • Property mode set to 100644
File size: 49.2 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3/*-
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *      $KAME: ip6_input.c,v 1.259 2002/01/21 04:58:09 jinmei Exp $
32 */
33
34/*-
35 * Copyright (c) 1982, 1986, 1988, 1993
36 *      The Regents of the University of California.  All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 *    notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 *    notice, this list of conditions and the following disclaimer in the
45 *    documentation and/or other materials provided with the distribution.
46 * 4. Neither the name of the University nor the names of its contributors
47 *    may be used to endorse or promote products derived from this software
48 *    without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 *
62 *      @(#)ip_input.c  8.2 (Berkeley) 1/4/94
63 */
64
65#include <sys/cdefs.h>
66__FBSDID("$FreeBSD$");
67
68#include <rtems/bsd/local/opt_inet.h>
69#include <rtems/bsd/local/opt_inet6.h>
70#include <rtems/bsd/local/opt_ipfw.h>
71#include <rtems/bsd/local/opt_ipsec.h>
72#include <rtems/bsd/local/opt_route.h>
73
74#include <rtems/bsd/sys/param.h>
75#include <sys/systm.h>
76#include <sys/malloc.h>
77#include <sys/mbuf.h>
78#include <sys/proc.h>
79#include <sys/domain.h>
80#include <sys/protosw.h>
81#include <sys/socket.h>
82#include <sys/socketvar.h>
83#include <rtems/bsd/sys/errno.h>
84#include <sys/time.h>
85#include <sys/kernel.h>
86#include <sys/syslog.h>
87
88#include <net/if.h>
89#include <net/if_types.h>
90#include <net/if_dl.h>
91#include <net/route.h>
92#include <net/netisr.h>
93#include <net/pfil.h>
94#include <net/vnet.h>
95
96#include <netinet/in.h>
97#include <netinet/ip_var.h>
98#include <netinet/in_systm.h>
99#include <net/if_llatbl.h>
100#ifdef INET
101#include <netinet/ip.h>
102#include <netinet/ip_icmp.h>
103#endif /* INET */
104#include <netinet/ip6.h>
105#include <netinet6/in6_var.h>
106#include <netinet6/ip6_var.h>
107#include <netinet/in_pcb.h>
108#include <netinet/icmp6.h>
109#include <netinet6/scope6_var.h>
110#include <netinet6/in6_ifattach.h>
111#include <netinet6/nd6.h>
112
113#ifdef IPSEC
114#include <netipsec/ipsec.h>
115#include <netinet6/ip6_ipsec.h>
116#include <netipsec/ipsec6.h>
117#endif /* IPSEC */
118
119#include <netinet6/ip6protosw.h>
120
121#ifdef FLOWTABLE
122#include <net/flowtable.h>
123VNET_DECLARE(int, ip6_output_flowtable_size);
124#define V_ip6_output_flowtable_size     VNET(ip6_output_flowtable_size)
125#endif
126
127extern struct domain inet6domain;
128
129u_char ip6_protox[IPPROTO_MAX];
130VNET_DEFINE(struct in6_ifaddrhead, in6_ifaddrhead);
131
132static struct netisr_handler ip6_nh = {
133        .nh_name = "ip6",
134        .nh_handler = ip6_input,
135        .nh_proto = NETISR_IPV6,
136        .nh_policy = NETISR_POLICY_FLOW,
137};
138
139VNET_DECLARE(struct callout, in6_tmpaddrtimer_ch);
140#define V_in6_tmpaddrtimer_ch           VNET(in6_tmpaddrtimer_ch)
141
142VNET_DEFINE(struct pfil_head, inet6_pfil_hook);
143
144VNET_DEFINE(struct ip6stat, ip6stat);
145
146struct rwlock in6_ifaddr_lock;
147RW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
148
149static void ip6_init2(void *);
150static struct ip6aux *ip6_setdstifaddr(struct mbuf *, struct in6_ifaddr *);
151static struct ip6aux *ip6_addaux(struct mbuf *);
152static struct ip6aux *ip6_findaux(struct mbuf *m);
153static void ip6_delaux (struct mbuf *);
154static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
155#ifdef PULLDOWN_TEST
156static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
157#endif
158
159/*
160 * IP6 initialization: fill in IP6 protocol switch table.
161 * All protocols not implemented in kernel go to raw IP6 protocol handler.
162 */
163void
164ip6_init(void)
165{
166        struct ip6protosw *pr;
167        int i;
168
169        TUNABLE_INT_FETCH("net.inet6.ip6.auto_linklocal",
170            &V_ip6_auto_linklocal);
171        TUNABLE_INT_FETCH("net.inet6.ip6.accept_rtadv", &V_ip6_accept_rtadv);
172        TUNABLE_INT_FETCH("net.inet6.ip6.no_radr", &V_ip6_no_radr);
173
174        TAILQ_INIT(&V_in6_ifaddrhead);
175
176        /* Initialize packet filter hooks. */
177        V_inet6_pfil_hook.ph_type = PFIL_TYPE_AF;
178        V_inet6_pfil_hook.ph_af = AF_INET6;
179        if ((i = pfil_head_register(&V_inet6_pfil_hook)) != 0)
180                printf("%s: WARNING: unable to register pfil hook, "
181                        "error %d\n", __func__, i);
182
183        scope6_init();
184        addrsel_policy_init();
185        nd6_init();
186        frag6_init();
187
188#ifdef FLOWTABLE
189        if (TUNABLE_INT_FETCH("net.inet6.ip6.output_flowtable_size",
190                &V_ip6_output_flowtable_size)) {
191                if (V_ip6_output_flowtable_size < 256)
192                        V_ip6_output_flowtable_size = 256;
193                if (!powerof2(V_ip6_output_flowtable_size)) {
194                        printf("flowtable must be power of 2 size\n");
195                        V_ip6_output_flowtable_size = 2048;
196                }
197        } else {
198                /*
199                 * round up to the next power of 2
200                 */
201                V_ip6_output_flowtable_size = 1 << fls((1024 + maxusers * 64)-1);
202        }
203        V_ip6_ft = flowtable_alloc("ipv6", V_ip6_output_flowtable_size, FL_IPV6|FL_PCPU);
204#endif 
205       
206        V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
207
208        /* Skip global initialization stuff for non-default instances. */
209        if (!IS_DEFAULT_VNET(curvnet))
210                return;
211
212#ifdef DIAGNOSTIC
213        if (sizeof(struct protosw) != sizeof(struct ip6protosw))
214                panic("sizeof(protosw) != sizeof(ip6protosw)");
215#endif
216        pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
217        if (pr == NULL)
218                panic("ip6_init");
219
220        /* Initialize the entire ip6_protox[] array to IPPROTO_RAW. */
221        for (i = 0; i < IPPROTO_MAX; i++)
222                ip6_protox[i] = pr - inet6sw;
223        /*
224         * Cycle through IP protocols and put them into the appropriate place
225         * in ip6_protox[].
226         */
227        for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
228            pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
229                if (pr->pr_domain->dom_family == PF_INET6 &&
230                    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) {
231                        /* Be careful to only index valid IP protocols. */
232                        if (pr->pr_protocol < IPPROTO_MAX)
233                                ip6_protox[pr->pr_protocol] = pr - inet6sw;
234                }
235
236        netisr_register(&ip6_nh);
237}
238
239/*
240 * The protocol to be inserted into ip6_protox[] must be already registered
241 * in inet6sw[], either statically or through pf_proto_register().
242 */
243int
244ip6proto_register(short ip6proto)
245{
246        struct ip6protosw *pr;
247
248        /* Sanity checks. */
249        if (ip6proto <= 0 || ip6proto >= IPPROTO_MAX)
250                return (EPROTONOSUPPORT);
251
252        /*
253         * The protocol slot must not be occupied by another protocol
254         * already.  An index pointing to IPPROTO_RAW is unused.
255         */
256        pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
257        if (pr == NULL)
258                return (EPFNOSUPPORT);
259        if (ip6_protox[ip6proto] != pr - inet6sw)       /* IPPROTO_RAW */
260                return (EEXIST);
261
262        /*
263         * Find the protocol position in inet6sw[] and set the index.
264         */
265        for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
266            pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) {
267                if (pr->pr_domain->dom_family == PF_INET6 &&
268                    pr->pr_protocol && pr->pr_protocol == ip6proto) {
269                        ip6_protox[pr->pr_protocol] = pr - inet6sw;
270                        return (0);
271                }
272        }
273        return (EPROTONOSUPPORT);
274}
275
276int
277ip6proto_unregister(short ip6proto)
278{
279        struct ip6protosw *pr;
280
281        /* Sanity checks. */
282        if (ip6proto <= 0 || ip6proto >= IPPROTO_MAX)
283                return (EPROTONOSUPPORT);
284
285        /* Check if the protocol was indeed registered. */
286        pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
287        if (pr == NULL)
288                return (EPFNOSUPPORT);
289        if (ip6_protox[ip6proto] == pr - inet6sw)       /* IPPROTO_RAW */
290                return (ENOENT);
291
292        /* Reset the protocol slot to IPPROTO_RAW. */
293        ip6_protox[ip6proto] = pr - inet6sw;
294        return (0);
295}
296
297#ifdef VIMAGE
298void
299ip6_destroy()
300{
301
302        nd6_destroy();
303        callout_drain(&V_in6_tmpaddrtimer_ch);
304}
305#endif
306
307static int
308ip6_init2_vnet(const void *unused __unused)
309{
310
311        /* nd6_timer_init */
312        callout_init(&V_nd6_timer_ch, 0);
313        callout_reset(&V_nd6_timer_ch, hz, nd6_timer, curvnet);
314
315        /* timer for regeneranation of temporary addresses randomize ID */
316        callout_init(&V_in6_tmpaddrtimer_ch, 0);
317        callout_reset(&V_in6_tmpaddrtimer_ch,
318                      (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
319                       V_ip6_temp_regen_advance) * hz,
320                      in6_tmpaddrtimer, curvnet);
321
322        return (0);
323}
324
325static void
326ip6_init2(void *dummy)
327{
328
329        ip6_init2_vnet(NULL);
330}
331
332/* cheat */
333/* This must be after route_init(), which is now SI_ORDER_THIRD */
334SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
335
336static int
337ip6_input_hbh(struct mbuf *m, uint32_t *plen, uint32_t *rtalert, int *off,
338    int *nxt, int *ours)
339{
340        struct ip6_hdr *ip6;
341        struct ip6_hbh *hbh;
342
343        if (ip6_hopopts_input(plen, rtalert, &m, off)) {
344#if 0   /*touches NULL pointer*/
345                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
346#endif
347                goto out;       /* m have already been freed */
348        }
349
350        /* adjust pointer */
351        ip6 = mtod(m, struct ip6_hdr *);
352
353        /*
354         * if the payload length field is 0 and the next header field
355         * indicates Hop-by-Hop Options header, then a Jumbo Payload
356         * option MUST be included.
357         */
358        if (ip6->ip6_plen == 0 && *plen == 0) {
359                /*
360                 * Note that if a valid jumbo payload option is
361                 * contained, ip6_hopopts_input() must set a valid
362                 * (non-zero) payload length to the variable plen.
363                 */
364                IP6STAT_INC(ip6s_badoptions);
365                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
366                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
367                icmp6_error(m, ICMP6_PARAM_PROB,
368                            ICMP6_PARAMPROB_HEADER,
369                            (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
370                goto out;
371        }
372#ifndef PULLDOWN_TEST
373        /* ip6_hopopts_input() ensures that mbuf is contiguous */
374        hbh = (struct ip6_hbh *)(ip6 + 1);
375#else
376        IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
377                sizeof(struct ip6_hbh));
378        if (hbh == NULL) {
379                IP6STAT_INC(ip6s_tooshort);
380                goto out;
381        }
382#endif
383        *nxt = hbh->ip6h_nxt;
384
385        /*
386         * If we are acting as a router and the packet contains a
387         * router alert option, see if we know the option value.
388         * Currently, we only support the option value for MLD, in which
389         * case we should pass the packet to the multicast routing
390         * daemon.
391         */
392        if (*rtalert != ~0) {
393                switch (*rtalert) {
394                case IP6OPT_RTALERT_MLD:
395                        if (V_ip6_forwarding)
396                                *ours = 1;
397                        break;
398                default:
399                        /*
400                         * RFC2711 requires unrecognized values must be
401                         * silently ignored.
402                         */
403                        break;
404                }
405        }
406
407        return (0);
408
409out:
410        return (1);
411}
412
413void
414ip6_input(struct mbuf *m)
415{
416        struct ip6_hdr *ip6;
417        int off = sizeof(struct ip6_hdr), nest;
418        u_int32_t plen;
419        u_int32_t rtalert = ~0;
420        int nxt, ours = 0;
421        struct ifnet *deliverifp = NULL, *ifp = NULL;
422        struct in6_addr odst;
423        struct route_in6 rin6;
424        int srcrt = 0;
425        struct llentry *lle = NULL;
426        struct sockaddr_in6 dst6, *dst;
427
428        bzero(&rin6, sizeof(struct route_in6));
429#ifdef IPSEC
430        /*
431         * should the inner packet be considered authentic?
432         * see comment in ah4_input().
433         * NB: m cannot be NULL when passed to the input routine
434         */
435
436        m->m_flags &= ~M_AUTHIPHDR;
437        m->m_flags &= ~M_AUTHIPDGM;
438
439#endif /* IPSEC */
440
441        /*
442         * make sure we don't have onion peering information into m_tag.
443         */
444        ip6_delaux(m);
445
446        if (m->m_flags & M_FASTFWD_OURS) {
447                /*
448                 * Firewall changed destination to local.
449                 */
450                m->m_flags &= ~M_FASTFWD_OURS;
451                ours = 1;
452                deliverifp = m->m_pkthdr.rcvif;
453                ip6 = mtod(m, struct ip6_hdr *);
454                goto hbhcheck;
455        }
456
457        /*
458         * mbuf statistics
459         */
460        if (m->m_flags & M_EXT) {
461                if (m->m_next)
462                        IP6STAT_INC(ip6s_mext2m);
463                else
464                        IP6STAT_INC(ip6s_mext1);
465        } else {
466                if (m->m_next) {
467                        if (m->m_flags & M_LOOP) {
468                                IP6STAT_INC(ip6s_m2m[V_loif->if_index]);
469                        } else if (m->m_pkthdr.rcvif->if_index < IP6S_M2MMAX)
470                                IP6STAT_INC(
471                                    ip6s_m2m[m->m_pkthdr.rcvif->if_index]);
472                        else
473                                IP6STAT_INC(ip6s_m2m[0]);
474                } else
475                        IP6STAT_INC(ip6s_m1);
476        }
477
478        /* drop the packet if IPv6 operation is disabled on the IF */
479        if ((ND_IFINFO(m->m_pkthdr.rcvif)->flags & ND6_IFF_IFDISABLED)) {
480                m_freem(m);
481                return;
482        }
483
484        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
485        IP6STAT_INC(ip6s_total);
486
487#ifndef PULLDOWN_TEST
488        /*
489         * L2 bridge code and some other code can return mbuf chain
490         * that does not conform to KAME requirement.  too bad.
491         * XXX: fails to join if interface MTU > MCLBYTES.  jumbogram?
492         */
493        if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
494                struct mbuf *n;
495
496                MGETHDR(n, M_DONTWAIT, MT_HEADER);
497                if (n)
498                        M_MOVE_PKTHDR(n, m);
499                if (n && n->m_pkthdr.len > MHLEN) {
500                        MCLGET(n, M_DONTWAIT);
501                        if ((n->m_flags & M_EXT) == 0) {
502                                m_freem(n);
503                                n = NULL;
504                        }
505                }
506                if (n == NULL) {
507                        m_freem(m);
508                        return; /* ENOBUFS */
509                }
510
511                m_copydata(m, 0, n->m_pkthdr.len, mtod(n, caddr_t));
512                n->m_len = n->m_pkthdr.len;
513                m_freem(m);
514                m = n;
515        }
516        IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /* nothing */);
517#endif
518
519        if (m->m_len < sizeof(struct ip6_hdr)) {
520                struct ifnet *inifp;
521                inifp = m->m_pkthdr.rcvif;
522                if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) {
523                        IP6STAT_INC(ip6s_toosmall);
524                        in6_ifstat_inc(inifp, ifs6_in_hdrerr);
525                        return;
526                }
527        }
528
529        ip6 = mtod(m, struct ip6_hdr *);
530
531        if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
532                IP6STAT_INC(ip6s_badvers);
533                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
534                goto bad;
535        }
536
537        IP6STAT_INC(ip6s_nxthist[ip6->ip6_nxt]);
538
539        /*
540         * Check against address spoofing/corruption.
541         */
542        if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
543            IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
544                /*
545                 * XXX: "badscope" is not very suitable for a multicast source.
546                 */
547                IP6STAT_INC(ip6s_badscope);
548                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
549                goto bad;
550        }
551        if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) &&
552            !(m->m_flags & M_LOOP)) {
553                /*
554                 * In this case, the packet should come from the loopback
555                 * interface.  However, we cannot just check the if_flags,
556                 * because ip6_mloopback() passes the "actual" interface
557                 * as the outgoing/incoming interface.
558                 */
559                IP6STAT_INC(ip6s_badscope);
560                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
561                goto bad;
562        }
563        if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
564            IPV6_ADDR_MC_SCOPE(&ip6->ip6_dst) == 0) {
565                /*
566                 * RFC4291 2.7:
567                 * Nodes must not originate a packet to a multicast address
568                 * whose scop field contains the reserved value 0; if such
569                 * a packet is received, it must be silently dropped.
570                 */
571                IP6STAT_INC(ip6s_badscope);
572                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
573                goto bad;
574        }
575#ifdef ALTQ
576        if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {
577                /* packet is dropped by traffic conditioner */
578                return;
579        }
580#endif
581        /*
582         * The following check is not documented in specs.  A malicious
583         * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
584         * and bypass security checks (act as if it was from 127.0.0.1 by using
585         * IPv6 src ::ffff:127.0.0.1).  Be cautious.
586         *
587         * This check chokes if we are in an SIIT cloud.  As none of BSDs
588         * support IPv4-less kernel compilation, we cannot support SIIT
589         * environment at all.  So, it makes more sense for us to reject any
590         * malicious packets for non-SIIT environment, than try to do a
591         * partial support for SIIT environment.
592         */
593        if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
594            IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
595                IP6STAT_INC(ip6s_badscope);
596                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
597                goto bad;
598        }
599#if 0
600        /*
601         * Reject packets with IPv4 compatible addresses (auto tunnel).
602         *
603         * The code forbids auto tunnel relay case in RFC1933 (the check is
604         * stronger than RFC1933).  We may want to re-enable it if mech-xx
605         * is revised to forbid relaying case.
606         */
607        if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
608            IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
609                IP6STAT_INC(ip6s_badscope);
610                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
611                goto bad;
612        }
613#endif
614#ifdef IPSEC
615        /*
616         * Bypass packet filtering for packets previously handled by IPsec.
617         */
618        if (ip6_ipsec_filtertunnel(m))
619                goto passin;
620#endif /* IPSEC */
621
622        /*
623         * Run through list of hooks for input packets.
624         *
625         * NB: Beware of the destination address changing
626         *     (e.g. by NAT rewriting).  When this happens,
627         *     tell ip6_forward to do the right thing.
628         */
629        odst = ip6->ip6_dst;
630
631        /* Jump over all PFIL processing if hooks are not active. */
632        if (!PFIL_HOOKED(&V_inet6_pfil_hook))
633                goto passin;
634
635        if (pfil_run_hooks(&V_inet6_pfil_hook, &m,
636            m->m_pkthdr.rcvif, PFIL_IN, NULL))
637                return;
638        if (m == NULL)                  /* consumed by filter */
639                return;
640        ip6 = mtod(m, struct ip6_hdr *);
641        srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst);
642
643        if (m->m_flags & M_FASTFWD_OURS) {
644                m->m_flags &= ~M_FASTFWD_OURS;
645                ours = 1;
646                deliverifp = m->m_pkthdr.rcvif;
647                goto hbhcheck;
648        }
649        if ((m->m_flags & M_IP6_NEXTHOP) &&
650            m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL) {
651                /*
652                 * Directly ship the packet on.  This allows forwarding
653                 * packets originally destined to us to some other directly
654                 * connected host.
655                 */
656                ip6_forward(m, 1);
657                goto out;
658        }
659
660passin:
661        /*
662         * Disambiguate address scope zones (if there is ambiguity).
663         * We first make sure that the original source or destination address
664         * is not in our internal form for scoped addresses.  Such addresses
665         * are not necessarily invalid spec-wise, but we cannot accept them due
666         * to the usage conflict.
667         * in6_setscope() then also checks and rejects the cases where src or
668         * dst are the loopback address and the receiving interface
669         * is not loopback.
670         */
671        if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) {
672                IP6STAT_INC(ip6s_badscope); /* XXX */
673                goto bad;
674        }
675        if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) ||
676            in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) {
677                IP6STAT_INC(ip6s_badscope);
678                goto bad;
679        }
680
681        /*
682         * Multicast check. Assume packet is for us to avoid
683         * prematurely taking locks.
684         */
685        if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
686                ours = 1;
687                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
688                deliverifp = m->m_pkthdr.rcvif;
689                goto hbhcheck;
690        }
691
692        /*
693         *  Unicast check
694         */
695
696        bzero(&dst6, sizeof(dst6));
697        dst6.sin6_family = AF_INET6;
698        dst6.sin6_len = sizeof(struct sockaddr_in6);
699        dst6.sin6_addr = ip6->ip6_dst;
700        ifp = m->m_pkthdr.rcvif;
701        IF_AFDATA_RLOCK(ifp);
702        lle = lla_lookup(LLTABLE6(ifp), 0,
703             (struct sockaddr *)&dst6);
704        IF_AFDATA_RUNLOCK(ifp);
705        if ((lle != NULL) && (lle->la_flags & LLE_IFADDR)) {
706                struct ifaddr *ifa;
707                struct in6_ifaddr *ia6;
708                int bad;
709
710                bad = 1;
711#define sa_equal(a1, a2)                                                \
712        (bcmp((a1), (a2), ((a1))->sin6_len) == 0)
713                IF_ADDR_RLOCK(ifp);
714                TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
715                        if (ifa->ifa_addr->sa_family != dst6.sin6_family)
716                                continue;
717                        if (sa_equal(&dst6, ifa->ifa_addr))
718                                break;
719                }
720                KASSERT(ifa != NULL, ("%s: ifa not found for lle %p",
721                    __func__, lle));
722#undef sa_equal
723
724                ia6 = (struct in6_ifaddr *)ifa;
725                if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
726                        /* Count the packet in the ip address stats */
727                        ia6->ia_ifa.if_ipackets++;
728                        ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
729
730                        /*
731                         * record address information into m_tag.
732                         */
733                        (void)ip6_setdstifaddr(m, ia6);
734
735                        bad = 0;
736                } else {
737                        char ip6bufs[INET6_ADDRSTRLEN];
738                        char ip6bufd[INET6_ADDRSTRLEN];
739                        /* address is not ready, so discard the packet. */
740                        nd6log((LOG_INFO,
741                            "ip6_input: packet to an unready address %s->%s\n",
742                            ip6_sprintf(ip6bufs, &ip6->ip6_src),
743                            ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
744                }
745                IF_ADDR_RUNLOCK(ifp);
746                LLE_RUNLOCK(lle);
747                if (bad)
748                        goto bad;
749                else {
750                        ours = 1;
751                        deliverifp = ifp;
752                        goto hbhcheck;
753                }
754        }
755        if (lle != NULL)
756                LLE_RUNLOCK(lle);
757
758        dst = &rin6.ro_dst;
759        dst->sin6_len = sizeof(struct sockaddr_in6);
760        dst->sin6_family = AF_INET6;
761        dst->sin6_addr = ip6->ip6_dst;
762        rin6.ro_rt = in6_rtalloc1((struct sockaddr *)dst, 0, 0, M_GETFIB(m));
763        if (rin6.ro_rt)
764                RT_UNLOCK(rin6.ro_rt);
765
766#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
767
768        /*
769         * Accept the packet if the forwarding interface to the destination
770         * according to the routing table is the loopback interface,
771         * unless the associated route has a gateway.
772         * Note that this approach causes to accept a packet if there is a
773         * route to the loopback interface for the destination of the packet.
774         * But we think it's even useful in some situations, e.g. when using
775         * a special daemon which wants to intercept the packet.
776         *
777         * XXX: some OSes automatically make a cloned route for the destination
778         * of an outgoing packet.  If the outgoing interface of the packet
779         * is a loopback one, the kernel would consider the packet to be
780         * accepted, even if we have no such address assinged on the interface.
781         * We check the cloned flag of the route entry to reject such cases,
782         * assuming that route entries for our own addresses are not made by
783         * cloning (it should be true because in6_addloop explicitly installs
784         * the host route).  However, we might have to do an explicit check
785         * while it would be less efficient.  Or, should we rather install a
786         * reject route for such a case?
787         */
788        if (rin6.ro_rt &&
789            (rin6.ro_rt->rt_flags &
790             (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
791#ifdef RTF_WASCLONED
792            !(rin6.ro_rt->rt_flags & RTF_WASCLONED) &&
793#endif
794#ifdef RTF_CLONED
795            !(rin6.ro_rt->rt_flags & RTF_CLONED) &&
796#endif
797#if 0
798            /*
799             * The check below is redundant since the comparison of
800             * the destination and the key of the rtentry has
801             * already done through looking up the routing table.
802             */
803            IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
804            &rt6_key(rin6.ro_rt)->sin6_addr)
805#endif
806            rin6.ro_rt->rt_ifp->if_type == IFT_LOOP) {
807                int free_ia6 = 0;
808                struct in6_ifaddr *ia6;
809
810                /*
811                 * found the loopback route to the interface address
812                 */
813                if (rin6.ro_rt->rt_gateway->sa_family == AF_LINK) {
814                        struct sockaddr_in6 dest6;
815
816                        bzero(&dest6, sizeof(dest6));
817                        dest6.sin6_family = AF_INET6;
818                        dest6.sin6_len = sizeof(dest6);
819                        dest6.sin6_addr = ip6->ip6_dst;
820                        ia6 = (struct in6_ifaddr *)
821                            ifa_ifwithaddr((struct sockaddr *)&dest6);
822                        if (ia6 == NULL)
823                                goto bad;
824                        free_ia6 = 1;
825                }
826                else
827                        ia6 = (struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
828
829                /*
830                 * record address information into m_tag.
831                 */
832                (void)ip6_setdstifaddr(m, ia6);
833
834                /*
835                 * packets to a tentative, duplicated, or somehow invalid
836                 * address must not be accepted.
837                 */
838                if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
839                        /* this address is ready */
840                        ours = 1;
841                        deliverifp = ia6->ia_ifp;       /* correct? */
842                        /* Count the packet in the ip address stats */
843                        ia6->ia_ifa.if_ipackets++;
844                        ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
845                        if (ia6 != NULL && free_ia6 != 0)
846                                ifa_free(&ia6->ia_ifa);
847                        goto hbhcheck;
848                } else {
849                        char ip6bufs[INET6_ADDRSTRLEN];
850                        char ip6bufd[INET6_ADDRSTRLEN];
851                        /* address is not ready, so discard the packet. */
852                        nd6log((LOG_INFO,
853                            "ip6_input: packet to an unready address %s->%s\n",
854                            ip6_sprintf(ip6bufs, &ip6->ip6_src),
855                            ip6_sprintf(ip6bufd, &ip6->ip6_dst)));
856
857                        if (ia6 != NULL && free_ia6 != 0)
858                                ifa_free(&ia6->ia_ifa);
859                        goto bad;
860                }
861        }
862
863        /*
864         * FAITH (Firewall Aided Internet Translator)
865         */
866        if (V_ip6_keepfaith) {
867                if (rin6.ro_rt && rin6.ro_rt->rt_ifp &&
868                    rin6.ro_rt->rt_ifp->if_type == IFT_FAITH) {
869                        /* XXX do we need more sanity checks? */
870                        ours = 1;
871                        deliverifp = rin6.ro_rt->rt_ifp; /* faith */
872                        goto hbhcheck;
873                }
874        }
875
876        /*
877         * Now there is no reason to process the packet if it's not our own
878         * and we're not a router.
879         */
880        if (!V_ip6_forwarding) {
881                IP6STAT_INC(ip6s_cantforward);
882                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
883                goto bad;
884        }
885
886  hbhcheck:
887        /*
888         * record address information into m_tag, if we don't have one yet.
889         * note that we are unable to record it, if the address is not listed
890         * as our interface address (e.g. multicast addresses, addresses
891         * within FAITH prefixes and such).
892         */
893        if (deliverifp) {
894                struct in6_ifaddr *ia6;
895
896                if ((ia6 = ip6_getdstifaddr(m)) != NULL) {
897                        ifa_free(&ia6->ia_ifa);
898                } else {
899                        ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
900                        if (ia6) {
901                                if (!ip6_setdstifaddr(m, ia6)) {
902                                        /*
903                                         * XXX maybe we should drop the packet here,
904                                         * as we could not provide enough information
905                                         * to the upper layers.
906                                         */
907                                }
908                                ifa_free(&ia6->ia_ifa);
909                        }
910                }
911        }
912
913        /*
914         * Process Hop-by-Hop options header if it's contained.
915         * m may be modified in ip6_hopopts_input().
916         * If a JumboPayload option is included, plen will also be modified.
917         */
918        plen = (u_int32_t)ntohs(ip6->ip6_plen);
919        if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
920                int error;
921
922                error = ip6_input_hbh(m, &plen, &rtalert, &off, &nxt, &ours);
923                if (error != 0)
924                        goto out;
925        } else
926                nxt = ip6->ip6_nxt;
927
928        /*
929         * Check that the amount of data in the buffers
930         * is as at least much as the IPv6 header would have us expect.
931         * Trim mbufs if longer than we expect.
932         * Drop packet if shorter than we expect.
933         */
934        if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
935                IP6STAT_INC(ip6s_tooshort);
936                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
937                goto bad;
938        }
939        if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
940                if (m->m_len == m->m_pkthdr.len) {
941                        m->m_len = sizeof(struct ip6_hdr) + plen;
942                        m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
943                } else
944                        m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
945        }
946
947        /*
948         * Forward if desirable.
949         */
950        if (V_ip6_mrouter &&
951            IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
952                /*
953                 * If we are acting as a multicast router, all
954                 * incoming multicast packets are passed to the
955                 * kernel-level multicast forwarding function.
956                 * The packet is returned (relatively) intact; if
957                 * ip6_mforward() returns a non-zero value, the packet
958                 * must be discarded, else it may be accepted below.
959                 *
960                 * XXX TODO: Check hlim and multicast scope here to avoid
961                 * unnecessarily calling into ip6_mforward().
962                 */
963                if (ip6_mforward &&
964                    ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
965                        IP6STAT_INC(ip6s_cantforward);
966                        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
967                        goto bad;
968                }
969        } else if (!ours) {
970                ip6_forward(m, srcrt);
971                goto out;
972        }
973
974        ip6 = mtod(m, struct ip6_hdr *);
975
976        /*
977         * Malicious party may be able to use IPv4 mapped addr to confuse
978         * tcp/udp stack and bypass security checks (act as if it was from
979         * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1).  Be cautious.
980         *
981         * For SIIT end node behavior, you may want to disable the check.
982         * However, you will  become vulnerable to attacks using IPv4 mapped
983         * source.
984         */
985        if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
986            IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
987                IP6STAT_INC(ip6s_badscope);
988                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
989                goto bad;
990        }
991
992        /*
993         * Tell launch routine the next header
994         */
995        IP6STAT_INC(ip6s_delivered);
996        in6_ifstat_inc(deliverifp, ifs6_in_deliver);
997        nest = 0;
998
999        while (nxt != IPPROTO_DONE) {
1000                if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) {
1001                        IP6STAT_INC(ip6s_toomanyhdr);
1002                        goto bad;
1003                }
1004
1005                /*
1006                 * protection against faulty packet - there should be
1007                 * more sanity checks in header chain processing.
1008                 */
1009                if (m->m_pkthdr.len < off) {
1010                        IP6STAT_INC(ip6s_tooshort);
1011                        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
1012                        goto bad;
1013                }
1014
1015#ifdef IPSEC
1016                /*
1017                 * enforce IPsec policy checking if we are seeing last header.
1018                 * note that we do not visit this with protocols with pcb layer
1019                 * code - like udp/tcp/raw ip.
1020                 */
1021                if (ip6_ipsec_input(m, nxt))
1022                        goto bad;
1023#endif /* IPSEC */
1024
1025                /*
1026                 * Use mbuf flags to propagate Router Alert option to
1027                 * ICMPv6 layer, as hop-by-hop options have been stripped.
1028                 */
1029                if (nxt == IPPROTO_ICMPV6 && rtalert != ~0)
1030                        m->m_flags |= M_RTALERT_MLD;
1031
1032                nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
1033        }
1034        goto out;
1035bad:
1036        m_freem(m);
1037out:
1038        if (rin6.ro_rt)
1039                RTFREE(rin6.ro_rt);
1040}
1041
1042/*
1043 * set/grab in6_ifaddr correspond to IPv6 destination address.
1044 * XXX backward compatibility wrapper
1045 *
1046 * XXXRW: We should bump the refcount on ia6 before sticking it in the m_tag,
1047 * and then bump it when the tag is copied, and release it when the tag is
1048 * freed.  Unfortunately, m_tags don't support deep copies (yet), so instead
1049 * we just bump the ia refcount when we receive it.  This should be fixed.
1050 */
1051static struct ip6aux *
1052ip6_setdstifaddr(struct mbuf *m, struct in6_ifaddr *ia6)
1053{
1054        struct ip6aux *ip6a;
1055
1056        ip6a = ip6_addaux(m);
1057        if (ip6a)
1058                ip6a->ip6a_dstia6 = ia6;
1059        return ip6a;    /* NULL if failed to set */
1060}
1061
1062struct in6_ifaddr *
1063ip6_getdstifaddr(struct mbuf *m)
1064{
1065        struct ip6aux *ip6a;
1066        struct in6_ifaddr *ia;
1067
1068        ip6a = ip6_findaux(m);
1069        if (ip6a) {
1070                ia = ip6a->ip6a_dstia6;
1071                ifa_ref(&ia->ia_ifa);
1072                return ia;
1073        } else
1074                return NULL;
1075}
1076
1077/*
1078 * Hop-by-Hop options header processing. If a valid jumbo payload option is
1079 * included, the real payload length will be stored in plenp.
1080 *
1081 * rtalertp - XXX: should be stored more smart way
1082 */
1083static int
1084ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp,
1085    struct mbuf **mp, int *offp)
1086{
1087        struct mbuf *m = *mp;
1088        int off = *offp, hbhlen;
1089        struct ip6_hbh *hbh;
1090
1091        /* validation of the length of the header */
1092#ifndef PULLDOWN_TEST
1093        IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
1094        hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
1095        hbhlen = (hbh->ip6h_len + 1) << 3;
1096
1097        IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
1098        hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
1099#else
1100        IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
1101                sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
1102        if (hbh == NULL) {
1103                IP6STAT_INC(ip6s_tooshort);
1104                return -1;
1105        }
1106        hbhlen = (hbh->ip6h_len + 1) << 3;
1107        IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
1108                hbhlen);
1109        if (hbh == NULL) {
1110                IP6STAT_INC(ip6s_tooshort);
1111                return -1;
1112        }
1113#endif
1114        off += hbhlen;
1115        hbhlen -= sizeof(struct ip6_hbh);
1116        if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
1117                                hbhlen, rtalertp, plenp) < 0)
1118                return (-1);
1119
1120        *offp = off;
1121        *mp = m;
1122        return (0);
1123}
1124
1125/*
1126 * Search header for all Hop-by-hop options and process each option.
1127 * This function is separate from ip6_hopopts_input() in order to
1128 * handle a case where the sending node itself process its hop-by-hop
1129 * options header. In such a case, the function is called from ip6_output().
1130 *
1131 * The function assumes that hbh header is located right after the IPv6 header
1132 * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
1133 * opthead + hbhlen is located in contiguous memory region.
1134 */
1135int
1136ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen,
1137    u_int32_t *rtalertp, u_int32_t *plenp)
1138{
1139        struct ip6_hdr *ip6;
1140        int optlen = 0;
1141        u_int8_t *opt = opthead;
1142        u_int16_t rtalert_val;
1143        u_int32_t jumboplen;
1144        const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
1145
1146        for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
1147                switch (*opt) {
1148                case IP6OPT_PAD1:
1149                        optlen = 1;
1150                        break;
1151                case IP6OPT_PADN:
1152                        if (hbhlen < IP6OPT_MINLEN) {
1153                                IP6STAT_INC(ip6s_toosmall);
1154                                goto bad;
1155                        }
1156                        optlen = *(opt + 1) + 2;
1157                        break;
1158                case IP6OPT_ROUTER_ALERT:
1159                        /* XXX may need check for alignment */
1160                        if (hbhlen < IP6OPT_RTALERT_LEN) {
1161                                IP6STAT_INC(ip6s_toosmall);
1162                                goto bad;
1163                        }
1164                        if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
1165                                /* XXX stat */
1166                                icmp6_error(m, ICMP6_PARAM_PROB,
1167                                    ICMP6_PARAMPROB_HEADER,
1168                                    erroff + opt + 1 - opthead);
1169                                return (-1);
1170                        }
1171                        optlen = IP6OPT_RTALERT_LEN;
1172                        bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
1173                        *rtalertp = ntohs(rtalert_val);
1174                        break;
1175                case IP6OPT_JUMBO:
1176                        /* XXX may need check for alignment */
1177                        if (hbhlen < IP6OPT_JUMBO_LEN) {
1178                                IP6STAT_INC(ip6s_toosmall);
1179                                goto bad;
1180                        }
1181                        if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
1182                                /* XXX stat */
1183                                icmp6_error(m, ICMP6_PARAM_PROB,
1184                                    ICMP6_PARAMPROB_HEADER,
1185                                    erroff + opt + 1 - opthead);
1186                                return (-1);
1187                        }
1188                        optlen = IP6OPT_JUMBO_LEN;
1189
1190                        /*
1191                         * IPv6 packets that have non 0 payload length
1192                         * must not contain a jumbo payload option.
1193                         */
1194                        ip6 = mtod(m, struct ip6_hdr *);
1195                        if (ip6->ip6_plen) {
1196                                IP6STAT_INC(ip6s_badoptions);
1197                                icmp6_error(m, ICMP6_PARAM_PROB,
1198                                    ICMP6_PARAMPROB_HEADER,
1199                                    erroff + opt - opthead);
1200                                return (-1);
1201                        }
1202
1203                        /*
1204                         * We may see jumbolen in unaligned location, so
1205                         * we'd need to perform bcopy().
1206                         */
1207                        bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
1208                        jumboplen = (u_int32_t)htonl(jumboplen);
1209
1210#if 1
1211                        /*
1212                         * if there are multiple jumbo payload options,
1213                         * *plenp will be non-zero and the packet will be
1214                         * rejected.
1215                         * the behavior may need some debate in ipngwg -
1216                         * multiple options does not make sense, however,
1217                         * there's no explicit mention in specification.
1218                         */
1219                        if (*plenp != 0) {
1220                                IP6STAT_INC(ip6s_badoptions);
1221                                icmp6_error(m, ICMP6_PARAM_PROB,
1222                                    ICMP6_PARAMPROB_HEADER,
1223                                    erroff + opt + 2 - opthead);
1224                                return (-1);
1225                        }
1226#endif
1227
1228                        /*
1229                         * jumbo payload length must be larger than 65535.
1230                         */
1231                        if (jumboplen <= IPV6_MAXPACKET) {
1232                                IP6STAT_INC(ip6s_badoptions);
1233                                icmp6_error(m, ICMP6_PARAM_PROB,
1234                                    ICMP6_PARAMPROB_HEADER,
1235                                    erroff + opt + 2 - opthead);
1236                                return (-1);
1237                        }
1238                        *plenp = jumboplen;
1239
1240                        break;
1241                default:                /* unknown option */
1242                        if (hbhlen < IP6OPT_MINLEN) {
1243                                IP6STAT_INC(ip6s_toosmall);
1244                                goto bad;
1245                        }
1246                        optlen = ip6_unknown_opt(opt, m,
1247                            erroff + opt - opthead);
1248                        if (optlen == -1)
1249                                return (-1);
1250                        optlen += 2;
1251                        break;
1252                }
1253        }
1254
1255        return (0);
1256
1257  bad:
1258        m_freem(m);
1259        return (-1);
1260}
1261
1262/*
1263 * Unknown option processing.
1264 * The third argument `off' is the offset from the IPv6 header to the option,
1265 * which is necessary if the IPv6 header the and option header and IPv6 header
1266 * is not contiguous in order to return an ICMPv6 error.
1267 */
1268int
1269ip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off)
1270{
1271        struct ip6_hdr *ip6;
1272
1273        switch (IP6OPT_TYPE(*optp)) {
1274        case IP6OPT_TYPE_SKIP: /* ignore the option */
1275                return ((int)*(optp + 1));
1276        case IP6OPT_TYPE_DISCARD:       /* silently discard */
1277                m_freem(m);
1278                return (-1);
1279        case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
1280                IP6STAT_INC(ip6s_badoptions);
1281                icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
1282                return (-1);
1283        case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
1284                IP6STAT_INC(ip6s_badoptions);
1285                ip6 = mtod(m, struct ip6_hdr *);
1286                if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
1287                    (m->m_flags & (M_BCAST|M_MCAST)))
1288                        m_freem(m);
1289                else
1290                        icmp6_error(m, ICMP6_PARAM_PROB,
1291                                    ICMP6_PARAMPROB_OPTION, off);
1292                return (-1);
1293        }
1294
1295        m_freem(m);             /* XXX: NOTREACHED */
1296        return (-1);
1297}
1298
1299/*
1300 * Create the "control" list for this pcb.
1301 * These functions will not modify mbuf chain at all.
1302 *
1303 * With KAME mbuf chain restriction:
1304 * The routine will be called from upper layer handlers like tcp6_input().
1305 * Thus the routine assumes that the caller (tcp6_input) have already
1306 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
1307 * very first mbuf on the mbuf chain.
1308 *
1309 * ip6_savecontrol_v4 will handle those options that are possible to be
1310 * set on a v4-mapped socket.
1311 * ip6_savecontrol will directly call ip6_savecontrol_v4 to handle those
1312 * options and handle the v6-only ones itself.
1313 */
1314struct mbuf **
1315ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp,
1316    int *v4only)
1317{
1318        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1319
1320#ifdef SO_TIMESTAMP
1321        if ((inp->inp_socket->so_options & SO_TIMESTAMP) != 0) {
1322                struct timeval tv;
1323
1324                microtime(&tv);
1325                *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1326                    SCM_TIMESTAMP, SOL_SOCKET);
1327                if (*mp)
1328                        mp = &(*mp)->m_next;
1329        }
1330#endif
1331
1332#define IS2292(inp, x, y)       (((inp)->inp_flags & IN6P_RFC2292) ? (x) : (y))
1333        /* RFC 2292 sec. 5 */
1334        if ((inp->inp_flags & IN6P_PKTINFO) != 0) {
1335                struct in6_pktinfo pi6;
1336
1337                if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1338#ifdef INET
1339                        struct ip *ip;
1340
1341                        ip = mtod(m, struct ip *);
1342                        pi6.ipi6_addr.s6_addr32[0] = 0;
1343                        pi6.ipi6_addr.s6_addr32[1] = 0;
1344                        pi6.ipi6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP;
1345                        pi6.ipi6_addr.s6_addr32[3] = ip->ip_dst.s_addr;
1346#else
1347                        /* We won't hit this code */
1348                        bzero(&pi6.ipi6_addr, sizeof(struct in6_addr));
1349#endif
1350                } else {       
1351                        bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1352                        in6_clearscope(&pi6.ipi6_addr); /* XXX */
1353                }
1354                pi6.ipi6_ifindex =
1355                    (m && m->m_pkthdr.rcvif) ? m->m_pkthdr.rcvif->if_index : 0;
1356
1357                *mp = sbcreatecontrol((caddr_t) &pi6,
1358                    sizeof(struct in6_pktinfo),
1359                    IS2292(inp, IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6);
1360                if (*mp)
1361                        mp = &(*mp)->m_next;
1362        }
1363
1364        if ((inp->inp_flags & IN6P_HOPLIMIT) != 0) {
1365                int hlim;
1366
1367                if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1368#ifdef INET
1369                        struct ip *ip;
1370
1371                        ip = mtod(m, struct ip *);
1372                        hlim = ip->ip_ttl;
1373#else
1374                        /* We won't hit this code */
1375                        hlim = 0;
1376#endif
1377                } else {
1378                        hlim = ip6->ip6_hlim & 0xff;
1379                }
1380                *mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int),
1381                    IS2292(inp, IPV6_2292HOPLIMIT, IPV6_HOPLIMIT),
1382                    IPPROTO_IPV6);
1383                if (*mp)
1384                        mp = &(*mp)->m_next;
1385        }
1386
1387        if ((inp->inp_flags & IN6P_TCLASS) != 0) {
1388                int tclass;
1389
1390                if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1391#ifdef INET
1392                        struct ip *ip;
1393
1394                        ip = mtod(m, struct ip *);
1395                        tclass = ip->ip_tos;
1396#else
1397                        /* We won't hit this code */
1398                        tclass = 0;
1399#endif
1400                } else {
1401                        u_int32_t flowinfo;
1402
1403                        flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK);
1404                        flowinfo >>= 20;
1405                        tclass = flowinfo & 0xff;
1406                }
1407                *mp = sbcreatecontrol((caddr_t) &tclass, sizeof(int),
1408                    IPV6_TCLASS, IPPROTO_IPV6);
1409                if (*mp)
1410                        mp = &(*mp)->m_next;
1411        }
1412
1413        if (v4only != NULL) {
1414                if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
1415                        *v4only = 1;
1416                } else {
1417                        *v4only = 0;
1418                }
1419        }
1420
1421        return (mp);
1422}
1423
1424void
1425ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
1426{
1427        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1428        int v4only = 0;
1429
1430        mp = ip6_savecontrol_v4(in6p, m, mp, &v4only);
1431        if (v4only)
1432                return;
1433
1434        /*
1435         * IPV6_HOPOPTS socket option.  Recall that we required super-user
1436         * privilege for the option (see ip6_ctloutput), but it might be too
1437         * strict, since there might be some hop-by-hop options which can be
1438         * returned to normal user.
1439         * See also RFC 2292 section 6 (or RFC 3542 section 8).
1440         */
1441        if ((in6p->inp_flags & IN6P_HOPOPTS) != 0) {
1442                /*
1443                 * Check if a hop-by-hop options header is contatined in the
1444                 * received packet, and if so, store the options as ancillary
1445                 * data. Note that a hop-by-hop options header must be
1446                 * just after the IPv6 header, which is assured through the
1447                 * IPv6 input processing.
1448                 */
1449                if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1450                        struct ip6_hbh *hbh;
1451                        int hbhlen = 0;
1452#ifdef PULLDOWN_TEST
1453                        struct mbuf *ext;
1454#endif
1455
1456#ifndef PULLDOWN_TEST
1457                        hbh = (struct ip6_hbh *)(ip6 + 1);
1458                        hbhlen = (hbh->ip6h_len + 1) << 3;
1459#else
1460                        ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
1461                            ip6->ip6_nxt);
1462                        if (ext == NULL) {
1463                                IP6STAT_INC(ip6s_tooshort);
1464                                return;
1465                        }
1466                        hbh = mtod(ext, struct ip6_hbh *);
1467                        hbhlen = (hbh->ip6h_len + 1) << 3;
1468                        if (hbhlen != ext->m_len) {
1469                                m_freem(ext);
1470                                IP6STAT_INC(ip6s_tooshort);
1471                                return;
1472                        }
1473#endif
1474
1475                        /*
1476                         * XXX: We copy the whole header even if a
1477                         * jumbo payload option is included, the option which
1478                         * is to be removed before returning according to
1479                         * RFC2292.
1480                         * Note: this constraint is removed in RFC3542
1481                         */
1482                        *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1483                            IS2292(in6p, IPV6_2292HOPOPTS, IPV6_HOPOPTS),
1484                            IPPROTO_IPV6);
1485                        if (*mp)
1486                                mp = &(*mp)->m_next;
1487#ifdef PULLDOWN_TEST
1488                        m_freem(ext);
1489#endif
1490                }
1491        }
1492
1493        if ((in6p->inp_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) {
1494                int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
1495
1496                /*
1497                 * Search for destination options headers or routing
1498                 * header(s) through the header chain, and stores each
1499                 * header as ancillary data.
1500                 * Note that the order of the headers remains in
1501                 * the chain of ancillary data.
1502                 */
1503                while (1) {     /* is explicit loop prevention necessary? */
1504                        struct ip6_ext *ip6e = NULL;
1505                        int elen;
1506#ifdef PULLDOWN_TEST
1507                        struct mbuf *ext = NULL;
1508#endif
1509
1510                        /*
1511                         * if it is not an extension header, don't try to
1512                         * pull it from the chain.
1513                         */
1514                        switch (nxt) {
1515                        case IPPROTO_DSTOPTS:
1516                        case IPPROTO_ROUTING:
1517                        case IPPROTO_HOPOPTS:
1518                        case IPPROTO_AH: /* is it possible? */
1519                                break;
1520                        default:
1521                                goto loopend;
1522                        }
1523
1524#ifndef PULLDOWN_TEST
1525                        if (off + sizeof(*ip6e) > m->m_len)
1526                                goto loopend;
1527                        ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
1528                        if (nxt == IPPROTO_AH)
1529                                elen = (ip6e->ip6e_len + 2) << 2;
1530                        else
1531                                elen = (ip6e->ip6e_len + 1) << 3;
1532                        if (off + elen > m->m_len)
1533                                goto loopend;
1534#else
1535                        ext = ip6_pullexthdr(m, off, nxt);
1536                        if (ext == NULL) {
1537                                IP6STAT_INC(ip6s_tooshort);
1538                                return;
1539                        }
1540                        ip6e = mtod(ext, struct ip6_ext *);
1541                        if (nxt == IPPROTO_AH)
1542                                elen = (ip6e->ip6e_len + 2) << 2;
1543                        else
1544                                elen = (ip6e->ip6e_len + 1) << 3;
1545                        if (elen != ext->m_len) {
1546                                m_freem(ext);
1547                                IP6STAT_INC(ip6s_tooshort);
1548                                return;
1549                        }
1550#endif
1551
1552                        switch (nxt) {
1553                        case IPPROTO_DSTOPTS:
1554                                if (!(in6p->inp_flags & IN6P_DSTOPTS))
1555                                        break;
1556
1557                                *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1558                                    IS2292(in6p,
1559                                        IPV6_2292DSTOPTS, IPV6_DSTOPTS),
1560                                    IPPROTO_IPV6);
1561                                if (*mp)
1562                                        mp = &(*mp)->m_next;
1563                                break;
1564                        case IPPROTO_ROUTING:
1565                                if (!(in6p->inp_flags & IN6P_RTHDR))
1566                                        break;
1567
1568                                *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1569                                    IS2292(in6p, IPV6_2292RTHDR, IPV6_RTHDR),
1570                                    IPPROTO_IPV6);
1571                                if (*mp)
1572                                        mp = &(*mp)->m_next;
1573                                break;
1574                        case IPPROTO_HOPOPTS:
1575                        case IPPROTO_AH: /* is it possible? */
1576                                break;
1577
1578                        default:
1579                                /*
1580                                 * other cases have been filtered in the above.
1581                                 * none will visit this case.  here we supply
1582                                 * the code just in case (nxt overwritten or
1583                                 * other cases).
1584                                 */
1585#ifdef PULLDOWN_TEST
1586                                m_freem(ext);
1587#endif
1588                                goto loopend;
1589
1590                        }
1591
1592                        /* proceed with the next header. */
1593                        off += elen;
1594                        nxt = ip6e->ip6e_nxt;
1595                        ip6e = NULL;
1596#ifdef PULLDOWN_TEST
1597                        m_freem(ext);
1598                        ext = NULL;
1599#endif
1600                }
1601          loopend:
1602                ;
1603        }
1604}
1605#undef IS2292
1606
1607void
1608ip6_notify_pmtu(struct inpcb *inp, struct sockaddr_in6 *dst, u_int32_t mtu)
1609{
1610        struct socket *so;
1611        struct mbuf *m_mtu;
1612        struct ip6_mtuinfo mtuctl;
1613
1614        KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
1615        /*
1616         * Notify the error by sending IPV6_PATHMTU ancillary data if
1617         * application wanted to know the MTU value.
1618         * NOTE: we notify disconnected sockets, because some udp
1619         * applications keep sending sockets disconnected.
1620         * NOTE: our implementation doesn't notify connected sockets that has
1621         * foreign address that is different than given destination addresses
1622         * (this is permitted by RFC 3542).
1623         */
1624        if ((inp->inp_flags & IN6P_MTU) == 0 || (
1625            !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
1626            !IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &dst->sin6_addr)))
1627                return;
1628
1629        mtuctl.ip6m_mtu = mtu;
1630        mtuctl.ip6m_addr = *dst;
1631        if (sa6_recoverscope(&mtuctl.ip6m_addr))
1632                return;
1633
1634        if ((m_mtu = sbcreatecontrol((caddr_t)&mtuctl, sizeof(mtuctl),
1635            IPV6_PATHMTU, IPPROTO_IPV6)) == NULL)
1636                return;
1637
1638        so =  inp->inp_socket;
1639        if (sbappendaddr(&so->so_rcv, (struct sockaddr *)dst, NULL, m_mtu)
1640            == 0) {
1641                m_freem(m_mtu);
1642                /* XXX: should count statistics */
1643        } else
1644                sorwakeup(so);
1645}
1646
1647#ifdef PULLDOWN_TEST
1648/*
1649 * pull single extension header from mbuf chain.  returns single mbuf that
1650 * contains the result, or NULL on error.
1651 */
1652static struct mbuf *
1653ip6_pullexthdr(struct mbuf *m, size_t off, int nxt)
1654{
1655        struct ip6_ext ip6e;
1656        size_t elen;
1657        struct mbuf *n;
1658
1659#ifdef DIAGNOSTIC
1660        switch (nxt) {
1661        case IPPROTO_DSTOPTS:
1662        case IPPROTO_ROUTING:
1663        case IPPROTO_HOPOPTS:
1664        case IPPROTO_AH: /* is it possible? */
1665                break;
1666        default:
1667                printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
1668        }
1669#endif
1670
1671        m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1672        if (nxt == IPPROTO_AH)
1673                elen = (ip6e.ip6e_len + 2) << 2;
1674        else
1675                elen = (ip6e.ip6e_len + 1) << 3;
1676
1677        MGET(n, M_DONTWAIT, MT_DATA);
1678        if (n && elen >= MLEN) {
1679                MCLGET(n, M_DONTWAIT);
1680                if ((n->m_flags & M_EXT) == 0) {
1681                        m_free(n);
1682                        n = NULL;
1683                }
1684        }
1685        if (!n)
1686                return NULL;
1687
1688        n->m_len = 0;
1689        if (elen >= M_TRAILINGSPACE(n)) {
1690                m_free(n);
1691                return NULL;
1692        }
1693
1694        m_copydata(m, off, elen, mtod(n, caddr_t));
1695        n->m_len = elen;
1696        return n;
1697}
1698#endif
1699
1700/*
1701 * Get pointer to the previous header followed by the header
1702 * currently processed.
1703 * XXX: This function supposes that
1704 *      M includes all headers,
1705 *      the next header field and the header length field of each header
1706 *      are valid, and
1707 *      the sum of each header length equals to OFF.
1708 * Because of these assumptions, this function must be called very
1709 * carefully. Moreover, it will not be used in the near future when
1710 * we develop `neater' mechanism to process extension headers.
1711 */
1712char *
1713ip6_get_prevhdr(struct mbuf *m, int off)
1714{
1715        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1716
1717        if (off == sizeof(struct ip6_hdr))
1718                return (&ip6->ip6_nxt);
1719        else {
1720                int len, nxt;
1721                struct ip6_ext *ip6e = NULL;
1722
1723                nxt = ip6->ip6_nxt;
1724                len = sizeof(struct ip6_hdr);
1725                while (len < off) {
1726                        ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
1727
1728                        switch (nxt) {
1729                        case IPPROTO_FRAGMENT:
1730                                len += sizeof(struct ip6_frag);
1731                                break;
1732                        case IPPROTO_AH:
1733                                len += (ip6e->ip6e_len + 2) << 2;
1734                                break;
1735                        default:
1736                                len += (ip6e->ip6e_len + 1) << 3;
1737                                break;
1738                        }
1739                        nxt = ip6e->ip6e_nxt;
1740                }
1741                if (ip6e)
1742                        return (&ip6e->ip6e_nxt);
1743                else
1744                        return NULL;
1745        }
1746}
1747
1748/*
1749 * get next header offset.  m will be retained.
1750 */
1751int
1752ip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp)
1753{
1754        struct ip6_hdr ip6;
1755        struct ip6_ext ip6e;
1756        struct ip6_frag fh;
1757
1758        /* just in case */
1759        if (m == NULL)
1760                panic("ip6_nexthdr: m == NULL");
1761        if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
1762                return -1;
1763
1764        switch (proto) {
1765        case IPPROTO_IPV6:
1766                if (m->m_pkthdr.len < off + sizeof(ip6))
1767                        return -1;
1768                m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
1769                if (nxtp)
1770                        *nxtp = ip6.ip6_nxt;
1771                off += sizeof(ip6);
1772                return off;
1773
1774        case IPPROTO_FRAGMENT:
1775                /*
1776                 * terminate parsing if it is not the first fragment,
1777                 * it does not make sense to parse through it.
1778                 */
1779                if (m->m_pkthdr.len < off + sizeof(fh))
1780                        return -1;
1781                m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
1782                /* IP6F_OFF_MASK = 0xfff8(BigEndian), 0xf8ff(LittleEndian) */
1783                if (fh.ip6f_offlg & IP6F_OFF_MASK)
1784                        return -1;
1785                if (nxtp)
1786                        *nxtp = fh.ip6f_nxt;
1787                off += sizeof(struct ip6_frag);
1788                return off;
1789
1790        case IPPROTO_AH:
1791                if (m->m_pkthdr.len < off + sizeof(ip6e))
1792                        return -1;
1793                m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1794                if (nxtp)
1795                        *nxtp = ip6e.ip6e_nxt;
1796                off += (ip6e.ip6e_len + 2) << 2;
1797                return off;
1798
1799        case IPPROTO_HOPOPTS:
1800        case IPPROTO_ROUTING:
1801        case IPPROTO_DSTOPTS:
1802                if (m->m_pkthdr.len < off + sizeof(ip6e))
1803                        return -1;
1804                m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
1805                if (nxtp)
1806                        *nxtp = ip6e.ip6e_nxt;
1807                off += (ip6e.ip6e_len + 1) << 3;
1808                return off;
1809
1810        case IPPROTO_NONE:
1811        case IPPROTO_ESP:
1812        case IPPROTO_IPCOMP:
1813                /* give up */
1814                return -1;
1815
1816        default:
1817                return -1;
1818        }
1819
1820        return -1;
1821}
1822
1823/*
1824 * get offset for the last header in the chain.  m will be kept untainted.
1825 */
1826int
1827ip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp)
1828{
1829        int newoff;
1830        int nxt;
1831
1832        if (!nxtp) {
1833                nxt = -1;
1834                nxtp = &nxt;
1835        }
1836        while (1) {
1837                newoff = ip6_nexthdr(m, off, proto, nxtp);
1838                if (newoff < 0)
1839                        return off;
1840                else if (newoff < off)
1841                        return -1;      /* invalid */
1842                else if (newoff == off)
1843                        return newoff;
1844
1845                off = newoff;
1846                proto = *nxtp;
1847        }
1848}
1849
1850static struct ip6aux *
1851ip6_addaux(struct mbuf *m)
1852{
1853        struct m_tag *mtag;
1854
1855        mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1856        if (!mtag) {
1857                mtag = m_tag_get(PACKET_TAG_IPV6_INPUT, sizeof(struct ip6aux),
1858                    M_NOWAIT);
1859                if (mtag) {
1860                        m_tag_prepend(m, mtag);
1861                        bzero(mtag + 1, sizeof(struct ip6aux));
1862                }
1863        }
1864        return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
1865}
1866
1867static struct ip6aux *
1868ip6_findaux(struct mbuf *m)
1869{
1870        struct m_tag *mtag;
1871
1872        mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1873        return mtag ? (struct ip6aux *)(mtag + 1) : NULL;
1874}
1875
1876static void
1877ip6_delaux(struct mbuf *m)
1878{
1879        struct m_tag *mtag;
1880
1881        mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL);
1882        if (mtag)
1883                m_tag_delete(m, mtag);
1884}
1885
1886/*
1887 * System control for IP6
1888 */
1889
1890u_char  inet6ctlerrmap[PRC_NCMDS] = {
1891        0,              0,              0,              0,
1892        0,              EMSGSIZE,       EHOSTDOWN,      EHOSTUNREACH,
1893        EHOSTUNREACH,   EHOSTUNREACH,   ECONNREFUSED,   ECONNREFUSED,
1894        EMSGSIZE,       EHOSTUNREACH,   0,              0,
1895        0,              0,              0,              0,
1896        ENOPROTOOPT
1897};
Note: See TracBrowser for help on using the repository browser.