OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [bsd_tcpip/] [v2_0/] [src/] [sys/] [netinet6/] [ip6_input.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      src/sys/netinet6/ip6_input.c
4
//
5
//==========================================================================
6
//####BSDCOPYRIGHTBEGIN####
7
//
8
// -------------------------------------------
9
//
10
// Portions of this software may have been derived from OpenBSD, 
11
// FreeBSD or other sources, and are covered by the appropriate
12
// copyright disclaimers included herein.
13
//
14
// Portions created by Red Hat are
15
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16
//
17
// -------------------------------------------
18
//
19
//####BSDCOPYRIGHTEND####
20
//==========================================================================
21
 
22
/*      $KAME: ip6_input.c,v 1.242 2001/12/27 17:40:10 jinmei Exp $     */
23
 
24
/*
25
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
26
 * All rights reserved.
27
 *
28
 * Redistribution and use in source and binary forms, with or without
29
 * modification, are permitted provided that the following conditions
30
 * are met:
31
 * 1. Redistributions of source code must retain the above copyright
32
 *    notice, this list of conditions and the following disclaimer.
33
 * 2. Redistributions in binary form must reproduce the above copyright
34
 *    notice, this list of conditions and the following disclaimer in the
35
 *    documentation and/or other materials provided with the distribution.
36
 * 3. Neither the name of the project nor the names of its contributors
37
 *    may be used to endorse or promote products derived from this software
38
 *    without specific prior written permission.
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
41
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
44
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50
 * SUCH DAMAGE.
51
 */
52
 
53
/*
54
 * Copyright (c) 1982, 1986, 1988, 1993
55
 *      The Regents of the University of California.  All rights reserved.
56
 *
57
 * Redistribution and use in source and binary forms, with or without
58
 * modification, are permitted provided that the following conditions
59
 * are met:
60
 * 1. Redistributions of source code must retain the above copyright
61
 *    notice, this list of conditions and the following disclaimer.
62
 * 2. Redistributions in binary form must reproduce the above copyright
63
 *    notice, this list of conditions and the following disclaimer in the
64
 *    documentation and/or other materials provided with the distribution.
65
 * 3. All advertising materials mentioning features or use of this software
66
 *    must display the following acknowledgement:
67
 *      This product includes software developed by the University of
68
 *      California, Berkeley and its contributors.
69
 * 4. Neither the name of the University nor the names of its contributors
70
 *    may be used to endorse or promote products derived from this software
71
 *    without specific prior written permission.
72
 *
73
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
74
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
76
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
77
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
78
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
79
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
80
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
81
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
82
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
83
 * SUCH DAMAGE.
84
 *
85
 *      @(#)ip_input.c  8.2 (Berkeley) 1/4/94
86
 */
87
 
88
#include <sys/param.h>
89
#include <sys/malloc.h>
90
#include <sys/mbuf.h>
91
#include <sys/domain.h>
92
#include <sys/protosw.h>
93
#include <sys/socket.h>
94
#include <sys/socketvar.h>
95
#include <sys/errno.h>
96
 
97
#include <net/if.h>
98
#include <net/if_types.h>
99
#include <net/if_dl.h>
100
#include <net/route.h>
101
#include <net/netisr.h>
102
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
103
#include <net/intrq.h>
104
#endif
105
 
106
#include <netinet/in.h>
107
#include <netinet/in_systm.h>
108
#ifdef INET
109
#include <netinet/ip.h>
110
#include <netinet/ip_icmp.h>
111
#endif /* INET */
112
#include <netinet/ip6.h>
113
#include <netinet6/in6_var.h>
114
#include <netinet6/ip6_var.h>
115
#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)
116
#include <netinet/in_pcb.h>
117
#endif
118
#if !((defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802))
119
#include <netinet6/in6_pcb.h>
120
#endif
121
#include <netinet/icmp6.h>
122
#include <netinet6/in6_ifattach.h>
123
#include <netinet6/nd6.h>
124
#ifdef __bsdi__
125
#include <netinet6/raw_ip6.h>
126
#endif
127
#ifdef MIP6
128
#include <netinet6/mip6.h>
129
#endif
130
 
131
#if defined(IPSEC) && !defined(__OpenBSD__)
132
#include <netinet6/ipsec.h>
133
#endif
134
 
135
#if defined(IPV6FIREWALL) || (defined(__FreeBSD__) && __FreeBSD__ >= 4)
136
#include <netinet6/ip6_fw.h>
137
#endif
138
 
139
#include <netinet6/ip6protosw.h>
140
 
141
/* we need it for NLOOP. */
142
 
143
#if NGIF > 0
144
#include <netinet6/in6_gif.h>
145
#endif
146
 
147
#ifdef MIP6
148
#include <netinet6/mip6.h>
149
#endif /* MIP6 */
150
 
151
#ifdef __OpenBSD__
152
#if NPF > 0
153
#include <net/pfvar.h>
154
#endif
155
#endif
156
 
157
extern struct domain inet6domain;
158
extern struct ip6protosw inet6sw[];
159
#ifdef __bsdi__
160
#if _BSDI_VERSION < 199802
161
extern struct ifnet loif;
162
#else
163
extern struct ifnet *loifp;
164
#endif
165
#endif
166
 
167
u_char ip6_protox[IPPROTO_MAX];
168
static int ip6qmaxlen = IFQ_MAXLEN;
169
struct in6_ifaddr *in6_ifaddr;
170
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 4)
171
struct ifqueue ip6intrq;
172
#endif
173
 
174
#if defined(__NetBSD__)
175
extern struct ifnet loif[NLOOP];
176
#endif
177
#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
178
extern struct callout in6_tmpaddrtimer_ch;
179
#elif defined(__OpenBSD__)
180
extern struct timeout in6_tmpaddrtimer_ch;
181
#endif
182
 
183
int ip6_forward_srcrt;                  /* XXX */
184
int ip6_sourcecheck;                    /* XXX */
185
int ip6_sourcecheck_interval;           /* XXX */
186
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
187
const int int6intrq_present = 1;
188
#endif
189
 
190
#ifdef MEASURE_PERFORMANCE
191
#define MEASURE_PERFORMANCE_UDPONLY
192
#define IP6_PERFORM_LOGSIZE 10000
193
int ip6_logentry;
194
int ip6_logsize = IP6_PERFORM_LOGSIZE;
195
unsigned long long ip6_performance_log[IP6_PERFORM_LOGSIZE];
196
unsigned long long ip6_performance_log2[IP6_PERFORM_LOGSIZE];
197
struct in6_addr ip6_performance_addrlog[IP6_PERFORM_LOGSIZE];
198
#endif
199
#ifdef MEASURE_PERFORMANCE
200
#define OURS_CHECK_ALG_RTABLE 0
201
#define OURS_CHECK_ALG_LINEAR 1
202
#define OURS_CHECK_ALG_HASH 2
203
#define OURS_CHECK_ALG_LARGEHASH 3
204
#ifdef OURS_CHECK_LINEAR
205
int ip6_ours_check_algorithm = OURS_CHECK_ALG_LINEAR;
206
#elif OURS_CHECK_HASH
207
int ip6_ours_check_algorithm = OURS_CHECK_ALG_HASH;
208
#else
209
int ip6_ours_check_algorithm = OURS_CHECK_ALG_RTABLE;
210
#endif
211
#else
212
int ip6_ours_check_algorithm;
213
#endif
214
 
215
 
216
#if defined(IPV6FIREWALL) || (defined(__FreeBSD__) && __FreeBSD__ >= 4)
217
/* firewall hooks */
218
ip6_fw_chk_t *ip6_fw_chk_ptr;
219
ip6_fw_ctl_t *ip6_fw_ctl_ptr;
220
#endif
221
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
222
int ip6_fw_enable = 1;
223
#endif
224
 
225
struct ip6stat ip6stat;
226
 
227
static void ip6_init2 __P((void *));
228
static struct mbuf *ip6_setdstifaddr __P((struct mbuf *, struct in6_ifaddr *));
229
 
230
static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
231
#ifdef PULLDOWN_TEST
232
static struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int));
233
#endif
234
 
235
#ifdef NATPT
236
extern int ip6_protocol_tr;
237
 
238
int natpt_in6 __P((struct mbuf *, struct mbuf **));
239
extern void ip_forward __P((struct mbuf *, int));
240
#endif
241
 
242
 
243
#ifdef MEASURE_PERFORMANCE
244
static unsigned long long ctr_beg, ctr_end;
245
 
246
static __inline unsigned long long read_tsc __P((void));
247
static __inline void add_performance_log __P((unsigned long long,
248
                                              struct in6_addr *));
249
#endif
250
 
251
#ifdef MEASURE_PERFORMANCE
252
static __inline unsigned long long
253
read_tsc(void)
254
{
255
     unsigned int h,l;
256
     /* read Pentium counter */
257
     __asm__(".byte 0x0f,0x31" :"=a" (l), "=d" (h));
258
     return ((unsigned long long)h<<32) | l;
259
}
260
 
261
static __inline void
262
add_performance_log(val, addr)
263
        unsigned long long val;
264
        struct in6_addr *addr;
265
{
266
        ip6_logentry = (ip6_logentry + 1) % ip6_logsize;
267
        ip6_performance_log[ip6_logentry] = val;
268
        ip6_performance_addrlog[ip6_logentry] = *addr;
269
}
270
#endif
271
 
272
/*
273
 * IP6 initialization: fill in IP6 protocol switch table.
274
 * All protocols not implemented in kernel go to raw IP6 protocol handler.
275
 */
276
void
277
ip6_init()
278
{
279
        struct ip6protosw *pr;
280
        int i;
281
#ifndef __OpenBSD__
282
        struct timeval tv;
283
#endif
284
 
285
#ifdef RADIX_ART
286
        rt_tables[AF_INET6]->rnh_addrsize = sizeof(struct in6_addr);
287
#endif
288
 
289
#ifdef DIAGNOSTIC
290
        if (sizeof(struct protosw) != sizeof(struct ip6protosw))
291
                panic("sizeof(protosw) != sizeof(ip6protosw)");
292
#endif
293
        pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
294
        if (pr == 0)
295
                panic("ip6_init");
296
        for (i = 0; i < IPPROTO_MAX; i++)
297
                ip6_protox[i] = pr - inet6sw;
298
        for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
299
            pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
300
                if (pr->pr_domain->dom_family == PF_INET6 &&
301
                    pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
302
                        ip6_protox[pr->pr_protocol] = pr - inet6sw;
303
        ip6intrq.ifq_maxlen = ip6qmaxlen;
304
#if (defined(__FreeBSD__) && __FreeBSD__ >= 4)
305
        register_netisr(NETISR_IPV6, ip6intr);
306
#endif
307
        addrsel_policy_init();
308
        nd6_init();
309
        frag6_init();
310
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
311
#else
312
#ifdef IPV6FIREWALL
313
        ip6_fw_init();
314
#endif
315
#endif
316
#ifndef __OpenBSD__
317
        /*
318
         * in many cases, random() here does NOT return random number
319
         * as initialization during bootstrap time occur in fixed order.
320
         */
321
        microtime(&tv);
322
        ip6_flow_seq = random() ^ tv.tv_usec;
323
        microtime(&tv);
324
        ip6_desync_factor = (random() ^ tv.tv_usec) % MAX_TEMP_DESYNC_FACTOR;
325
#else
326
        ip6_flow_seq = arc4random();
327
        ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
328
#endif
329
 
330
#ifndef __FreeBSD__
331
        ip6_init2((void *)0);
332
#endif
333
 
334
#ifdef MIP6
335
        mip6_init();
336
#endif /* MIP6 */
337
 
338
#ifdef MEASURE_PERFORMANCE
339
        in6h_hashinit();
340
#endif
341
}
342
 
343
static void
344
ip6_init2(dummy)
345
        void *dummy;
346
{
347
#if defined(__bsdi__) && _BSDI_VERSION < 199802
348
        struct ifnet *loifp = &loif;
349
#endif
350
 
351
        /*
352
         * to route local address of p2p link to loopback,
353
         * assign loopback address first.
354
         */
355
#ifdef __bsdi__
356
        in6_ifattach(loifp, NULL);
357
#elif defined(__OpenBSD__)
358
        in6_ifattach(lo0ifp, NULL);
359
#else
360
        in6_ifattach(&loif[0], NULL);
361
#endif
362
 
363
        /* nd6_timer_init */
364
#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
365
        callout_init(&nd6_timer_ch);
366
        callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL);
367
#elif defined(__OpenBSD__)
368
        bzero(&nd6_timer_ch, sizeof(nd6_timer_ch));
369
        timeout_set(&nd6_timer_ch, nd6_timer, NULL);
370
        timeout_add(&nd6_timer_ch, hz);
371
#else
372
        timeout(nd6_timer, (caddr_t)0, hz);
373
#endif
374
 
375
        /* timer for regeneranation of temporary addresses randomize ID */
376
#if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
377
        callout_init(&in6_tmpaddrtimer_ch);
378
        callout_reset(&in6_tmpaddrtimer_ch,
379
                      (ip6_temp_preferred_lifetime - ip6_desync_factor -
380
                       ip6_temp_regen_advance) * hz,
381
                      in6_tmpaddrtimer, NULL);
382
#elif defined(__OpenBSD__)
383
        timeout_set(&in6_tmpaddrtimer_ch, in6_tmpaddrtimer, NULL);
384
        timeout_add(&in6_tmpaddrtimer_ch,
385
            (ip6_temp_preferred_lifetime - ip6_desync_factor -
386
            ip6_temp_regen_advance) * hz);
387
#else
388
        timeout(in6_tmpaddrtimer, (caddr_t)0,
389
                (ip6_temp_preferred_lifetime - ip6_desync_factor -
390
                        ip6_temp_regen_advance) * hz);
391
#endif
392
}
393
 
394
SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
395
 
396
/*
397
 * IP6 input interrupt handling. Just pass the packet to ip6_input.
398
 */
399
void
400
ip6intr()
401
{
402
        int s;
403
        struct mbuf *m;
404
 
405
        for (;;) {
406
                s = splimp();
407
                IF_DEQUEUE(&ip6intrq, m);
408
                splx(s);
409
                if (m == 0)
410
                        return;
411
                ip6_input(m);
412
        }
413
}
414
 
415
#if (defined(__FreeBSD__) && __FreeBSD__ <= 3)
416
NETISR_SET(NETISR_IPV6, ip6intr);
417
#endif
418
 
419
#ifdef NEW_STRUCT_ROUTE
420
extern struct   route ip6_forward_rt;
421
#else
422
extern struct   route_in6 ip6_forward_rt;
423
 
424
/* NetBSD/OpenBSD requires NEW_STRUCT_ROUTE */
425
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
426
#error NEW_STRUCT_ROUTE is required
427
#endif
428
#endif
429
 
430
void
431
ip6_input(m)
432
        struct mbuf *m;
433
{
434
        struct ip6_hdr *ip6;
435
        int off = sizeof(struct ip6_hdr), nest;
436
        u_int32_t plen;
437
        u_int32_t rtalert = ~0;
438
        int nxt, ours = 0;
439
        struct ifnet *deliverifp = NULL;
440
#if 0
441
        struct mbuf *mhist;     /* onion peeling history */
442
        caddr_t hist;
443
#endif
444
#if defined(__bsdi__) && _BSDI_VERSION < 199802
445
        struct ifnet *loifp = &loif;
446
#endif
447
#if defined(__NetBSD__) && defined(PFIL_HOOKS)
448
        struct packet_filter_hook *pfh;
449
        struct mbuf *m0;
450
        int rv;
451
#endif  /* PFIL_HOOKS */
452
 
453
#if defined(IPSEC) && !defined(__OpenBSD__)
454
        /*
455
         * should the inner packet be considered authentic?
456
         * see comment in ah4_input().
457
         */
458
        m->m_flags &= ~M_AUTHIPHDR;
459
        m->m_flags &= ~M_AUTHIPDGM;
460
#endif
461
 
462
        /*
463
         * make sure we don't have onion peering information into m_aux.
464
         */
465
        ip6_delaux(m);
466
 
467
        /*
468
         * mbuf statistics
469
         */
470
        if (m->m_flags & M_EXT) {
471
                if (m->m_next)
472
                        ip6stat.ip6s_mext2m++;
473
                else
474
                        ip6stat.ip6s_mext1++;
475
        } else {
476
#define M2MMAX  (sizeof(ip6stat.ip6s_m2m)/sizeof(ip6stat.ip6s_m2m[0]))
477
                if (m->m_next) {
478
                        if (m->m_flags & M_LOOP) {
479
#ifdef __bsdi__
480
                                ip6stat.ip6s_m2m[loifp->if_index]++; /* XXX */
481
#elif defined(__OpenBSD__)
482
                                ip6stat.ip6s_m2m[lo0ifp->if_index]++; /* XXX */
483
#else
484
                                ip6stat.ip6s_m2m[loif[0].if_index]++; /* XXX */
485
#endif
486
                        } else if (m->m_pkthdr.rcvif->if_index < M2MMAX)
487
                                ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
488
                        else
489
                                ip6stat.ip6s_m2m[0]++;
490
                } else
491
                        ip6stat.ip6s_m1++;
492
#undef M2MMAX
493
        }
494
 
495
        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
496
        ip6stat.ip6s_total++;
497
 
498
#ifndef PULLDOWN_TEST
499
        /*
500
         * L2 bridge code and some other code can return mbuf chain
501
         * that does not conform to KAME requirement.  too bad.
502
         * XXX: fails to join if interface MTU > MCLBYTES.  jumbogram?
503
         */
504
        if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
505
                struct mbuf *n;
506
 
507
                MGETHDR(n, M_DONTWAIT, MT_HEADER);
508
                if (n != NULL) {
509
#ifdef __OpenBSD__
510
                        M_MOVE_PKTHDR(n, m);
511
#else
512
                        M_COPY_PKTHDR(n, m);
513
#endif
514
                }
515
                if (n != NULL && m->m_pkthdr.len > MHLEN) {
516
                        MCLGET(n, M_DONTWAIT);
517
                        if ((n->m_flags & M_EXT) == 0) {
518
                                m_freem(n);
519
                                n = NULL;
520
                        }
521
                }
522
                if (n == NULL) {
523
                        m_freem(m);
524
                        return; /* ENOBUFS */
525
                }
526
 
527
                m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
528
                n->m_len = m->m_pkthdr.len;
529
                m_freem(m);
530
                m = n;
531
        }
532
        IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /* nothing */);
533
#endif
534
 
535
#if defined(__OpenBSD__) && NPF > 0 
536
        /*
537
         * Packet filter
538
         */
539
        if (pf_test6(PF_IN, m->m_pkthdr.rcvif, &m) != PF_PASS)
540
                goto bad;
541
#endif
542
 
543
        if (m->m_len < sizeof(struct ip6_hdr)) {
544
                struct ifnet *inifp;
545
                inifp = m->m_pkthdr.rcvif;
546
                if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
547
                        ip6stat.ip6s_toosmall++;
548
                        in6_ifstat_inc(inifp, ifs6_in_hdrerr);
549
                        return;
550
                }
551
        }
552
 
553
        ip6 = mtod(m, struct ip6_hdr *);
554
 
555
        if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
556
                ip6stat.ip6s_badvers++;
557
                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
558
                goto bad;
559
        }
560
 
561
#if defined(__NetBSD__) && defined(PFIL_HOOKS)
562
        /*
563
         * Run through list of hooks for input packets.  If there are any
564
         * filters which require that additional packets in the flow are
565
         * not fast-forwarded, they must clear the M_CANFASTFWD flag.
566
         * Note that filters must _never_ set this flag, as another filter
567
         * in the list may have previously cleared it.
568
         */
569
        /*
570
         * let ipfilter look at packet on the wire,
571
         * not the decapsulated packet.
572
         */
573
#ifdef IPSEC
574
        if (!ipsec_getnhist(m))
575
#else
576
        if (1 /* CONSTCOND */)
577
#endif
578
        {
579
                m0 = m;
580
                pfh = pfil_hook_get(PFIL_IN,
581
                    &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
582
        } else
583
                pfh = NULL;
584
        for (; pfh; pfh = pfh->pfil_link.tqe_next)
585
                if (pfh->pfil_func) {
586
                        rv = pfh->pfil_func(ip6, sizeof(*ip6),
587
                                            m->m_pkthdr.rcvif, 0, &m0);
588
                        if (rv)
589
                                return;
590
                        m = m0;
591
                        if (m == NULL)
592
                                return;
593
                        ip6 = mtod(m, struct ip6_hdr *);
594
                }
595
#endif /* PFIL_HOOKS */
596
 
597
        ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
598
 
599
#if defined(IPV6FIREWALL) || (defined(__FreeBSD__) && __FreeBSD__ >= 4)
600
        /*
601
         * Check with the firewall...
602
         */
603
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
604
        if (ip6_fw_enable && ip6_fw_chk_ptr)
605
#else
606
        if (ip6_fw_chk_ptr)
607
#endif
608
        {
609
                /* If ipfw says divert, we have to just drop packet */
610
                /* use port as a dummy argument */
611
                if ((*ip6_fw_chk_ptr)(&ip6, NULL, &m)) {
612
                        m_freem(m);
613
                        m = NULL;
614
                }
615
                if (!m)
616
                        return;
617
        }
618
#endif
619
 
620
#ifdef ALTQ
621
        if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) {
622
                /* packet is dropped by traffic conditioner */
623
                return;
624
        }
625
#endif
626
 
627
        /*
628
         * Check against address spoofing/corruption.
629
         */
630
#if 0
631
            diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
632
            diag_dump_buf(&ip6->ip6_src, 16);
633
            diag_dump_buf(&ip6->ip6_dst, 16);
634
#endif
635
        if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
636
            IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
637
                /*
638
                 * XXX: "badscope" is not very suitable for a multicast source.
639
                 */
640
                ip6stat.ip6s_badscope++;
641
                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
642
                log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
643
                goto bad;
644
        }
645
        if ((IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
646
             IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) &&
647
            (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
648
                ip6stat.ip6s_badscope++;
649
                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
650
                log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
651
                goto bad;
652
        }
653
        if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) &&
654
            !(m->m_flags & M_LOOP)) {
655
                /*
656
                 * In this case, the packet should come from the loopback
657
                 * interface.  However, we cannot just check the if_flags,
658
                 * because ip6_mloopback() passes the "actual" interface
659
                 * as the outgoing/incoming interface.
660
                 */
661
                ip6stat.ip6s_badscope++;
662
                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
663
                log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
664
                goto bad;
665
        }
666
 
667
        /*
668
         * The following check is not documented in specs.  A malicious
669
         * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
670
         * and bypass security checks (act as if it was from 127.0.0.1 by using
671
         * IPv6 src ::ffff:127.0.0.1).  Be cautious.
672
         *
673
         * This check chokes if we are in an SIIT cloud.  As none of BSDs
674
         * support IPv4-less kernel compilation, we cannot support SIIT
675
         * environment at all.  So, it makes more sense for us to reject any
676
         * malicious packets for non-SIIT environment, than try to do a
677
         * partical support for SIIT environment.
678
         */
679
        if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
680
            IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
681
                ip6stat.ip6s_badscope++;
682
                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
683
                log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
684
                goto bad;
685
        }
686
#if 0
687
        /*
688
         * Reject packets with IPv4 compatible addresses (auto tunnel).
689
         *
690
         * The code forbids auto tunnel relay case in RFC1933 (the check is
691
         * stronger than RFC1933).  We may want to re-enable it if mech-xx
692
         * is revised to forbid relaying case.
693
         */
694
        if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
695
            IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
696
                ip6stat.ip6s_badscope++;
697
                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
698
                goto bad;
699
        }
700
#endif
701
 
702
        /* drop packets if interface ID portion is already filled */
703
        if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
704
                if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src) &&
705
                    ip6->ip6_src.s6_addr16[1]) {
706
                        ip6stat.ip6s_badscope++;
707
                        log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
708
                        goto bad;
709
                }
710
                if ((IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) ||
711
                     IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) &&
712
                    ip6->ip6_dst.s6_addr16[1]) {
713
                        ip6stat.ip6s_badscope++;
714
                        log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
715
                        goto bad;
716
                }
717
        }
718
 
719
        /*
720
         * Embed interface ID as the zone ID for interface-local and
721
         * link-local addresses.
722
         * XXX: KAME assumes one-to-one mapping between interfaces and
723
         * links.
724
         */
725
        if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
726
                ip6->ip6_src.s6_addr16[1]
727
                        = htons(m->m_pkthdr.rcvif->if_index);
728
        if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) ||
729
            IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
730
                ip6->ip6_dst.s6_addr16[1]
731
                        = htons(m->m_pkthdr.rcvif->if_index);
732
 
733
#if 0 /* this case seems to be unnecessary. (jinmei, 20010401) */
734
        /*
735
         * We use rt->rt_ifp to determine if the address is ours or not.
736
         * If rt_ifp is lo0, the address is ours.
737
         * The problem here is, rt->rt_ifp for fe80::%lo0/64 is set to lo0,
738
         * so any address under fe80::%lo0/64 will be mistakenly considered
739
         * local.  The special case is supplied to handle the case properly
740
         * by actually looking at interface addresses
741
         * (using in6ifa_ifpwithaddr).
742
         */
743
        if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) != 0 &&
744
            IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
745
                if (!in6ifa_ifpwithaddr(m->m_pkthdr.rcvif, &ip6->ip6_dst)) {
746
                        icmp6_error(m, ICMP6_DST_UNREACH,
747
                            ICMP6_DST_UNREACH_ADDR, 0);
748
                        /* m is already freed */
749
                        return;
750
                }
751
 
752
                ours = 1;
753
                deliverifp = m->m_pkthdr.rcvif;
754
                goto hbhcheck;
755
        }
756
#endif
757
 
758
        /*
759
         * Multicast check
760
         */
761
        if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
762
                struct  in6_multi *in6m = 0;
763
 
764
                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
765
                /*
766
                 * See if we belong to the destination multicast group on the
767
                 * arrival interface.
768
                 */
769
                IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
770
// TEMP
771
                if (0) {
772
                    struct in6_addr *_addr = &ip6->ip6_dst;
773
                    struct ifnet *_ifp = m->m_pkthdr.rcvif;
774
                    struct ifmultiaddr *_ifma;
775
                    diag_printf("Lookup Multi = %p\n", in6m);
776
                    diag_dump_buf(_addr, 16);
777
                    diag_printf("=====================================================================\n");
778
                    for (_ifma = (_ifp)->if_multiaddrs.lh_first; _ifma;
779
                         _ifma = _ifma->ifma_link.le_next) {
780
                        diag_dump_buf(&((struct sockaddr_in6 *)_ifma->ifma_addr)->sin6_addr, 16);
781
                        diag_printf("---------------------------------------------------------------------\n");
782
                    }
783
                }
784
// TEMP
785
                if (in6m)
786
                        ours = 1;
787
                else if (!ip6_mrouter) {
788
                        ip6stat.ip6s_notmember++;
789
                        ip6stat.ip6s_cantforward++;
790
                        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
791
                        log(LOG_FAIL, "%s.%d - wrong multi group\n",
792
                            __FUNCTION__, __LINE__);
793
                        log_dump(LOG_FAIL, &ip6->ip6_dst, 16);
794
                        goto bad;
795
                }
796
                deliverifp = m->m_pkthdr.rcvif;
797
                goto hbhcheck;
798
        }
799
 
800
        /*
801
         *  Unicast check
802
         */
803
#ifdef MEASURE_PERFORMANCE
804
        ctr_beg = read_tsc();
805
#endif
806
        switch (ip6_ours_check_algorithm) {
807
#ifdef MEASURE_PERFORMANCE
808
        case OURS_CHECK_ALG_LINEAR:
809
        /* traditional linear search: just for measurement */
810
        {
811
                struct in6_ifaddr *ia;
812
 
813
                for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
814
                        if ((ia->ia6_flags & IN6_IFF_NOTREADY) == 0 &&
815
                            IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
816
                                               &ip6->ip6_dst)) {
817
#ifdef MEASURE_PERFORMANCE
818
                                ctr_end = read_tsc();
819
#ifdef MEASURE_PERFORMANCE_UDPONLY
820
                                if (ip6->ip6_nxt == IPPROTO_UDP)
821
#else
822
                                if (1)
823
#endif
824
                                        add_performance_log(ctr_end - ctr_beg,
825
                                                            &ip6->ip6_dst);
826
#endif
827
                                /* record address information into m_aux. */
828
                                (void)ip6_setdstifaddr(m, ia);
829
 
830
                                ours = 1;
831
                                deliverifp = ia->ia_ifp;
832
                                goto hbhcheck;
833
                        }
834
                }
835
        }
836
        break;
837
        case OURS_CHECK_ALG_HASH:
838
        case OURS_CHECK_ALG_LARGEHASH:
839
        {
840
                struct in6_ifaddr *ia;
841
                struct in6hash *ih = NULL;
842
 
843
                if ((ih = in6h_lookup(&ip6->ip6_dst, m->m_pkthdr.rcvif)) !=
844
                    NULL && (ia = ih->in6h_ifa) != NULL) {
845
#ifdef MEASURE_PERFORMANCE
846
                        ctr_end = read_tsc();
847
#ifdef MEASURE_PERFORMANCE_UDPONLY
848
                        if (ip6->ip6_nxt == IPPROTO_UDP)
849
#else
850
                        if (1)
851
#endif
852
                                add_performance_log(ctr_end - ctr_beg,
853
                                                    &ip6->ip6_dst);
854
#endif
855
 
856
                        /* record address information into m_aux. */
857
                        (void)ip6_setdstifaddr(m, ia);
858
 
859
                        ours = 1;
860
                        deliverifp = m->m_pkthdr.rcvif;
861
                        goto hbhcheck;
862
                }
863
        }
864
        break;
865
#endif /* MEASURE_PERFORMANCE */
866
        default:
867
                /*
868
                 * XXX: I intentionally broke our indentation rule here,
869
                 *      since this switch-case is just for measurement and
870
                 *      therefore should soon be removed.
871
                 */
872
        if (ip6_forward_rt.ro_rt != NULL &&
873
            (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
874
            IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
875
                               &((struct sockaddr_in6 *)(&ip6_forward_rt.ro_dst))->sin6_addr))
876
                ip6stat.ip6s_forward_cachehit++;
877
        else {
878
                struct sockaddr_in6 *dst6;
879
#ifdef SCOPEDROUTING
880
                int64_t dstzone;
881
#endif
882
 
883
                if (ip6_forward_rt.ro_rt) {
884
                        /* route is down or destination is different */
885
                        ip6stat.ip6s_forward_cachemiss++;
886
                        RTFREE(ip6_forward_rt.ro_rt);
887
                        ip6_forward_rt.ro_rt = 0;
888
                }
889
 
890
                bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
891
                dst6 = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst;
892
                dst6->sin6_len = sizeof(struct sockaddr_in6);
893
                dst6->sin6_family = AF_INET6;
894
                dst6->sin6_addr = ip6->ip6_dst;
895
#ifdef SCOPEDROUTING
896
                if ((dstzone = in6_addr2zoneid(m->m_pkthdr.rcvif,
897
                                               &ip6->ip6_dst)) < 0) {
898
                        ip6stat.ip6s_badscope++;
899
                        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
900
                        log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
901
                        goto bad;
902
                }
903
                ip6_forward_rt.ro_dst.sin6_scope_id = dstzone;
904
#endif
905
 
906
#ifdef __FreeBSD__
907
                rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
908
#else
909
                rtalloc((struct route *)&ip6_forward_rt);
910
#endif
911
        }
912
 
913
#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
914
 
915
        /*
916
         * Accept the packet if the forwarding interface to the destination
917
         * according to the routing table is the loopback interface,
918
         * unless the associated route has a gateway.
919
         * Note that this approach causes to accept a packet if there is a
920
         * route to the loopback interface for the destination of the packet.
921
         * But we think it's even useful in some situations, e.g. when using
922
         * a special daemon which wants to intercept the packet.
923
         *
924
         * XXX: some OSes automatically make a cloned route for the destination
925
         * of an outgoing packet.  If the outgoing interface of the packet
926
         * is a loopback one, the kernel would consider the packet to be
927
         * accepted, even if we have no such address assinged on the interface.
928
         * We check the cloned flag of the route entry to reject such cases,
929
         * assuming that route entries for our own addresses are not made by
930
         * cloning (it should be true because in6_addloop explicitly installs
931
         * the host route).  However, we might have to do an explicit check
932
         * while it would be less efficient.  Or, should we rather install a
933
         * reject route for such a case?
934
         */
935
        if (ip6_forward_rt.ro_rt &&
936
            (ip6_forward_rt.ro_rt->rt_flags &
937
             (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
938
#ifdef RTF_WASCLONED
939
            !(ip6_forward_rt.ro_rt->rt_flags & RTF_WASCLONED) &&
940
#endif
941
#ifdef RTF_CLONED
942
            !(ip6_forward_rt.ro_rt->rt_flags & RTF_CLONED) &&
943
#endif
944
#if 0
945
            /*
946
             * The check below is redundant since the comparison of
947
             * the destination and the key of the rtentry has
948
             * already done through looking up the routing table.
949
             */
950
            IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
951
                                &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr)
952
#endif
953
            ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
954
                struct in6_ifaddr *ia6 =
955
                        (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
956
 
957
#ifdef MEASURE_PERFORMANCE
958
                ctr_end = read_tsc();
959
#ifdef MEASURE_PERFORMANCE_UDPONLY
960
                if (ip6->ip6_nxt == IPPROTO_UDP)
961
#else
962
                if (1)
963
#endif
964
                        add_performance_log(ctr_end - ctr_beg, &ip6->ip6_dst);
965
#endif
966
 
967
                /*
968
                 * record address information into m_aux.
969
                 */
970
                (void)ip6_setdstifaddr(m, ia6);
971
 
972
                /*
973
                 * packets to a tentative, duplicated, or somehow invalid
974
                 * address must not be accepted.
975
                 */
976
                if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
977
                        /* this address is ready */
978
                        ours = 1;
979
                        deliverifp = ia6->ia_ifp;       /* correct? */
980
#if defined(__FreeBSD__) && __FreeBSD__ >= 4
981
                        /* Count the packet in the ip address stats */
982
                        ia6->ia_ifa.if_ipackets++;
983
                        ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
984
#elif defined(__bsdi__) && _BSDI_VERSION >= 199802
985
                        /* Count the packet in the ip address stats */
986
                        ia6->ia_ifa.ifa_ipackets++;
987
                        ia6->ia_ifa.ifa_ibytes += m->m_pkthdr.len;
988
#endif
989
                        goto hbhcheck;
990
                } else {
991
                        /* address is not ready, so discard the packet. */
992
                        nd6log((LOG_INFO,
993
                            "ip6_input: packet to an unready address %s->%s\n",
994
                            ip6_sprintf(&ip6->ip6_src),
995
                            ip6_sprintf(&ip6->ip6_dst)));
996
                        goto bad;
997
                }
998
        }
999
        } /* XXX indentation (see above) */
1000
 
1001
#ifdef MEASURE_PERFORMANCE
1002
        /* we detected that packet is not ours thru the basic algorithm */
1003
        ctr_end = read_tsc();
1004
#ifdef MEASURE_PERFORMANCE_UDPONLY
1005
        if (ip6->ip6_nxt == IPPROTO_UDP)
1006
#else
1007
        if (1)
1008
#endif
1009
                add_performance_log(ctr_end - ctr_beg, &ip6->ip6_dst);
1010
#endif
1011
 
1012
        /*
1013
         * FAITH(Firewall Aided Internet Translator)
1014
         */
1015
#if defined(NFAITH) && 0 < NFAITH
1016
        if (ip6_keepfaith) {
1017
                if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
1018
                 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
1019
                        /* XXX do we need more sanity checks? */
1020
                        ours = 1;
1021
                        deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /* faith */
1022
                        goto hbhcheck;
1023
                }
1024
        }
1025
#endif
1026
 
1027
#ifdef NATPT
1028
        /*
1029
         * NAT-PT (Network Address Translation - Protocol Translation)
1030
         */
1031
        if (ip6_protocol_tr) {
1032
                struct mbuf *m1 = NULL;
1033
 
1034
                switch (natpt_in6(m, &m1)) {
1035
                case IPPROTO_IP:
1036
                        goto processpacket;
1037
                case IPPROTO_IPV4:
1038
                        ip_forward(m1, 0);
1039
                        break;
1040
                case IPPROTO_IPV6:
1041
                        ip6_forward(m1, 0);
1042
                        break;
1043
                case IPPROTO_MAX:               /* discard this packet  */
1044
                default:
1045
                        break;
1046
                case IPPROTO_DONE:              /* discard without free */
1047
                        return;
1048
                }
1049
 
1050
                if (m != m1)
1051
                        m_freem(m);
1052
 
1053
                return;
1054
        }
1055
 
1056
 processpacket:
1057
#endif
1058
 
1059
#if 0
1060
    {
1061
        /*
1062
         * Last resort: check in6_ifaddr for incoming interface.
1063
         * The code is here until I update the "goto ours hack" code above
1064
         * working right.
1065
         */
1066
        struct ifaddr *ifa;
1067
        for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
1068
             ifa;
1069
             ifa = ifa->ifa_list.tqe_next) {
1070
                if (ifa->ifa_addr == NULL)
1071
                        continue;       /* just for safety */
1072
                if (ifa->ifa_addr->sa_family != AF_INET6)
1073
                        continue;
1074
                if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) {
1075
                        ours = 1;
1076
                        deliverifp = ifa->ifa_ifp;
1077
                        goto hbhcheck;
1078
                }
1079
        }
1080
    }
1081
#endif
1082
 
1083
        /*
1084
         * Now there is no reason to process the packet if it's not our own
1085
         * and we're not a router.
1086
         */
1087
        if (!ip6_forwarding) {
1088
                ip6stat.ip6s_cantforward++;
1089
                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
1090
                log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
1091
                goto bad;
1092
        }
1093
 
1094
 hbhcheck:
1095
        /*
1096
         * record address information into m_aux, if we don't have one yet.
1097
         * note that we are unable to record it, if the address is not listed
1098
         * as our interface address (e.g. multicast addresses, addresses
1099
         * within FAITH prefixes and such).
1100
         */
1101
        if (deliverifp && !ip6_getdstifaddr(m)) {
1102
                struct in6_ifaddr *ia6;
1103
 
1104
                ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
1105
                if (ia6) {
1106
                        if (!ip6_setdstifaddr(m, ia6)) {
1107
                                /*
1108
                                 * XXX maybe we should drop the packet here,
1109
                                 * as we could not provide enough information
1110
                                 * to the upper layers.
1111
                                 */
1112
                        }
1113
                }
1114
        }
1115
 
1116
        /*
1117
         * Process Hop-by-Hop options header if it's contained.
1118
         * m may be modified in ip6_hopopts_input().
1119
         * If a JumboPayload option is included, plen will also be modified.
1120
         */
1121
        plen = (u_int32_t)ntohs(ip6->ip6_plen);
1122
        if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1123
                struct ip6_hbh *hbh;
1124
 
1125
                if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
1126
#if 0   /*touches NULL pointer*/
1127
                        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
1128
#endif
1129
                        return; /* m have already been freed */
1130
                }
1131
 
1132
                /* adjust pointer */
1133
                ip6 = mtod(m, struct ip6_hdr *);
1134
 
1135
                /*
1136
                 * if the payload length field is 0 and the next header field
1137
                 * indicates Hop-by-Hop Options header, then a Jumbo Payload
1138
                 * option MUST be included.
1139
                 */
1140
                if (ip6->ip6_plen == 0 && plen == 0) {
1141
                        /*
1142
                         * Note that if a valid jumbo payload option is
1143
                         * contained, ip6_hoptops_input() must set a valid
1144
                         * (non-zero) payload length to the variable plen.
1145
                         */
1146
                        ip6stat.ip6s_badoptions++;
1147
                        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
1148
                        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
1149
                        icmp6_error(m, ICMP6_PARAM_PROB,
1150
                                    ICMP6_PARAMPROB_HEADER,
1151
                                    (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
1152
                        return;
1153
                }
1154
#ifndef PULLDOWN_TEST
1155
                /* ip6_hopopts_input() ensures that mbuf is contiguous */
1156
                hbh = (struct ip6_hbh *)(ip6 + 1);
1157
#else
1158
                IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
1159
                        sizeof(struct ip6_hbh));
1160
                if (hbh == NULL) {
1161
                        ip6stat.ip6s_tooshort++;
1162
                        return;
1163
                }
1164
#endif
1165
                nxt = hbh->ip6h_nxt;
1166
 
1167
                /*
1168
                 * accept the packet if a router alert option is included
1169
                 * and we act as an IPv6 router.
1170
                 */
1171
                if (rtalert != ~0 && ip6_forwarding)
1172
                        ours = 1;
1173
        } else
1174
                nxt = ip6->ip6_nxt;
1175
 
1176
        /*
1177
         * Check that the amount of data in the buffers
1178
         * is as at least much as the IPv6 header would have us expect.
1179
         * Trim mbufs if longer than we expect.
1180
         * Drop packet if shorter than we expect.
1181
         */
1182
        if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
1183
                ip6stat.ip6s_tooshort++;
1184
                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
1185
                goto bad;
1186
        }
1187
        if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
1188
                if (m->m_len == m->m_pkthdr.len) {
1189
                        m->m_len = sizeof(struct ip6_hdr) + plen;
1190
                        m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
1191
                } else
1192
                        m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
1193
        }
1194
 
1195
        /*
1196
         * Forward if desirable.
1197
         */
1198
        if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
1199
                /*
1200
                 * If we are acting as a multicast router, all
1201
                 * incoming multicast packets are passed to the
1202
                 * kernel-level multicast forwarding function.
1203
                 * The packet is returned (relatively) intact; if
1204
                 * ip6_mforward() returns a non-zero value, the packet
1205
                 * must be discarded, else it may be accepted below.
1206
                 */
1207
                if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
1208
                        ip6stat.ip6s_cantforward++;
1209
                        m_freem(m);
1210
                        return;
1211
                }
1212
                if (!ours) {
1213
                        m_freem(m);
1214
                        return;
1215
                }
1216
        } else if (!ours) {
1217
                ip6_forward(m, 0);
1218
                return;
1219
        }
1220
 
1221
        ip6 = mtod(m, struct ip6_hdr *);
1222
 
1223
        /*
1224
         * Malicious party may be able to use IPv4 mapped addr to confuse
1225
         * tcp/udp stack and bypass security checks (act as if it was from
1226
         * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1).  Be cautious.
1227
         *
1228
         * For SIIT end node behavior, you may want to disable the check.
1229
         * However, you will  become vulnerable to attacks using IPv4 mapped
1230
         * source.
1231
         */
1232
        if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
1233
            IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
1234
                ip6stat.ip6s_badscope++;
1235
                in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
1236
                log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
1237
                goto bad;
1238
        }
1239
 
1240
        /*
1241
         * Tell launch routine the next header
1242
         */
1243
#if defined(__NetBSD__) && defined(IFA_STATS)
1244
        if (deliverifp != NULL) {
1245
                struct in6_ifaddr *ia6;
1246
                ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
1247
                if (ia6)
1248
                        ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len;
1249
        }
1250
#endif
1251
        ip6stat.ip6s_delivered++;
1252
        in6_ifstat_inc(deliverifp, ifs6_in_deliver);
1253
        nest = 0;
1254
 
1255
        while (nxt != IPPROTO_DONE) {
1256
                if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
1257
                        ip6stat.ip6s_toomanyhdr++;
1258
                        log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
1259
                        goto bad;
1260
                }
1261
 
1262
                /*
1263
                 * protection against faulty packet - there should be
1264
                 * more sanity checks in header chain processing.
1265
                 */
1266
                if (m->m_pkthdr.len < off) {
1267
                        ip6stat.ip6s_tooshort++;
1268
                        in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
1269
                        log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
1270
                        goto bad;
1271
                }
1272
 
1273
#if 0
1274
                /*
1275
                 * do we need to do it for every header?  yeah, other
1276
                 * functions can play with it (like re-allocate and copy).
1277
                 */
1278
                mhist = ip6_addaux(m);
1279
                if (mhist && M_TRAILINGSPACE(mhist) >= sizeof(nxt)) {
1280
                        hist = mtod(mhist, caddr_t) + mhist->m_len;
1281
                        bcopy(&nxt, hist, sizeof(nxt));
1282
                        mhist->m_len += sizeof(nxt);
1283
                } else {
1284
                        ip6stat.ip6s_toomanyhdr++;
1285
                        log(LOG_FAIL, "%s.%d\n", __FUNCTION__, __LINE__);
1286
                        goto bad;
1287
                }
1288
#endif
1289
 
1290
#if defined(IPSEC) && !defined(__OpenBSD__)
1291
                /*
1292
                 * enforce IPsec policy checking if we are seeing last header.
1293
                 * note that we do not visit this with protocols with pcb layer
1294
                 * code - like udp/tcp/raw ip.
1295
                 */
1296
                if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
1297
                    ipsec6_in_reject(m, NULL)) {
1298
                        ipsec6stat.in_polvio++;
1299
                        goto bad;
1300
                }
1301
#endif
1302
#ifdef MIP6
1303
                /*
1304
                 * XXX
1305
                 * check if the packet was tunneled after all extion
1306
                 * headers have been processed.  get from Ericsson
1307
                 * code.  need more consideration.
1308
                 */
1309
                if ((nxt != IPPROTO_HOPOPTS) && (nxt != IPPROTO_DSTOPTS) &&
1310
                    (nxt != IPPROTO_ROUTING) && (nxt != IPPROTO_FRAGMENT) &&
1311
                    (nxt != IPPROTO_ESP) && (nxt != IPPROTO_AH)) {
1312
                        if (mip6_route_optimize(m))
1313
                                goto bad;
1314
                }
1315
#endif /* MIP6 */               
1316
                nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
1317
        }
1318
        return;
1319
 bad:
1320
        m_freem(m);
1321
}
1322
 
1323
/*
1324
 * set/grab in6_ifaddr correspond to IPv6 destination address.
1325
 * XXX backward compatibility wrapper
1326
 */
1327
static struct mbuf *
1328
ip6_setdstifaddr(m, ia6)
1329
        struct mbuf *m;
1330
        struct in6_ifaddr *ia6;
1331
{
1332
        struct mbuf *n;
1333
 
1334
        n = ip6_addaux(m);
1335
        if (n)
1336
                mtod(n, struct ip6aux *)->ip6a_dstia6 = ia6;
1337
        return n;       /* NULL if failed to set */
1338
}
1339
 
1340
struct in6_ifaddr *
1341
ip6_getdstifaddr(m)
1342
        struct mbuf *m;
1343
{
1344
        struct mbuf *n;
1345
 
1346
        n = ip6_findaux(m);
1347
        if (n)
1348
                return mtod(n, struct ip6aux *)->ip6a_dstia6;
1349
        else
1350
                return NULL;
1351
}
1352
 
1353
/*
1354
 * Hop-by-Hop options header processing. If a valid jumbo payload option is
1355
 * included, the real payload length will be stored in plenp.
1356
 */
1357
static int
1358
ip6_hopopts_input(plenp, rtalertp, mp, offp)
1359
        u_int32_t *plenp;
1360
        u_int32_t *rtalertp;    /* XXX: should be stored more smart way */
1361
        struct mbuf **mp;
1362
        int *offp;
1363
{
1364
        struct mbuf *m = *mp;
1365
        int off = *offp, hbhlen;
1366
        struct ip6_hbh *hbh;
1367
        u_int8_t *opt;
1368
 
1369
        /* validation of the length of the header */
1370
#ifndef PULLDOWN_TEST
1371
        IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
1372
        hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
1373
        hbhlen = (hbh->ip6h_len + 1) << 3;
1374
 
1375
        IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
1376
        hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
1377
#else
1378
        IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
1379
                sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
1380
        if (hbh == NULL) {
1381
                ip6stat.ip6s_tooshort++;
1382
                return -1;
1383
        }
1384
        hbhlen = (hbh->ip6h_len + 1) << 3;
1385
        IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
1386
                hbhlen);
1387
        if (hbh == NULL) {
1388
                ip6stat.ip6s_tooshort++;
1389
                return -1;
1390
        }
1391
#endif
1392
        off += hbhlen;
1393
        hbhlen -= sizeof(struct ip6_hbh);
1394
        opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
1395
 
1396
        if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
1397
                                hbhlen, rtalertp, plenp) < 0)
1398
                return(-1);
1399
 
1400
        *offp = off;
1401
        *mp = m;
1402
        return(0);
1403
}
1404
 
1405
/*
1406
 * Search header for all Hop-by-hop options and process each option.
1407
 * This function is separate from ip6_hopopts_input() in order to
1408
 * handle a case where the sending node itself process its hop-by-hop
1409
 * options header. In such a case, the function is called from ip6_output().
1410
 *
1411
 * The function assumes that hbh header is located right after the IPv6 header
1412
 * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
1413
 * opthead + hbhlen is located in continuous memory region.
1414
 */
1415
int
1416
ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
1417
        struct mbuf *m;
1418
        u_int8_t *opthead;
1419
        int hbhlen;
1420
        u_int32_t *rtalertp;
1421
        u_int32_t *plenp;
1422
{
1423
        struct ip6_hdr *ip6;
1424
        int optlen = 0;
1425
        u_int8_t *opt = opthead;
1426
        u_int16_t rtalert_val;
1427
        u_int32_t jumboplen;
1428
        const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
1429
 
1430
        for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
1431
                switch (*opt) {
1432
                case IP6OPT_PAD1:
1433
                        optlen = 1;
1434
                        break;
1435
                case IP6OPT_PADN:
1436
                        if (hbhlen < IP6OPT_MINLEN) {
1437
                                ip6stat.ip6s_toosmall++;
1438
                                goto bad;
1439
                        }
1440
                        optlen = *(opt + 1) + 2;
1441
                        break;
1442
                case IP6OPT_RTALERT:
1443
                        /* XXX may need check for alignment */
1444
                        if (hbhlen < IP6OPT_RTALERT_LEN) {
1445
                                ip6stat.ip6s_toosmall++;
1446
                                goto bad;
1447
                        }
1448
                        if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
1449
                                /* XXX stat */
1450
                                icmp6_error(m, ICMP6_PARAM_PROB,
1451
                                            ICMP6_PARAMPROB_HEADER,
1452
                                            erroff + opt + 1 - opthead);
1453
                                return(-1);
1454
                        }
1455
                        optlen = IP6OPT_RTALERT_LEN;
1456
                        bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
1457
                        *rtalertp = ntohs(rtalert_val);
1458
                        break;
1459
                case IP6OPT_JUMBO:
1460
                        /* XXX may need check for alignment */
1461
                        if (hbhlen < IP6OPT_JUMBO_LEN) {
1462
                                ip6stat.ip6s_toosmall++;
1463
                                goto bad;
1464
                        }
1465
                        if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
1466
                                /* XXX stat */
1467
                                icmp6_error(m, ICMP6_PARAM_PROB,
1468
                                            ICMP6_PARAMPROB_HEADER,
1469
                                            erroff + opt + 1 - opthead);
1470
                                return(-1);
1471
                        }
1472
                        optlen = IP6OPT_JUMBO_LEN;
1473
 
1474
                        /*
1475
                         * IPv6 packets that have non 0 payload length
1476
                         * must not contain a jumbo payload option.
1477
                         */
1478
                        ip6 = mtod(m, struct ip6_hdr *);
1479
                        if (ip6->ip6_plen) {
1480
                                ip6stat.ip6s_badoptions++;
1481
                                icmp6_error(m, ICMP6_PARAM_PROB,
1482
                                            ICMP6_PARAMPROB_HEADER,
1483
                                            erroff + opt - opthead);
1484
                                return(-1);
1485
                        }
1486
 
1487
                        /*
1488
                         * We may see jumbolen in unaligned location, so
1489
                         * we'd need to perform bcopy().
1490
                         */
1491
                        bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
1492
                        jumboplen = (u_int32_t)htonl(jumboplen);
1493
 
1494
#if 1
1495
                        /*
1496
                         * if there are multiple jumbo payload options,
1497
                         * *plenp will be non-zero and the packet will be
1498
                         * rejected.
1499
                         * the behavior may need some debate in ipngwg -
1500
                         * multiple options does not make sense, however,
1501
                         * there's no explicit mention in specification.
1502
                         */
1503
                        if (*plenp != 0) {
1504
                                ip6stat.ip6s_badoptions++;
1505
                                icmp6_error(m, ICMP6_PARAM_PROB,
1506
                                            ICMP6_PARAMPROB_HEADER,
1507
                                            erroff + opt + 2 - opthead);
1508
                                return(-1);
1509
                        }
1510
#endif
1511
 
1512
                        /*
1513
                         * jumbo payload length must be larger than 65535.
1514
                         */
1515
                        if (jumboplen <= IPV6_MAXPACKET) {
1516
                                ip6stat.ip6s_badoptions++;
1517
                                icmp6_error(m, ICMP6_PARAM_PROB,
1518
                                            ICMP6_PARAMPROB_HEADER,
1519
                                            erroff + opt + 2 - opthead);
1520
                                return(-1);
1521
                        }
1522
                        *plenp = jumboplen;
1523
 
1524
                        break;
1525
                default:                /* unknown option */
1526
                        if (hbhlen < IP6OPT_MINLEN) {
1527
                                ip6stat.ip6s_toosmall++;
1528
                                goto bad;
1529
                        }
1530
                        optlen = ip6_unknown_opt(opt, m,
1531
                            erroff + opt - opthead);
1532
                        if (optlen == -1)
1533
                                return(-1);
1534
                        optlen += 2;
1535
                        break;
1536
                }
1537
        }
1538
 
1539
        return(0);
1540
 
1541
  bad:
1542
        m_freem(m);
1543
        return(-1);
1544
}
1545
 
1546
/*
1547
 * Unknown option processing.
1548
 * The third argument `off' is the offset from the IPv6 header to the option,
1549
 * which is necessary if the IPv6 header the and option header and IPv6 header
1550
 * is not continuous in order to return an ICMPv6 error.
1551
 */
1552
int
1553
ip6_unknown_opt(optp, m, off)
1554
        u_int8_t *optp;
1555
        struct mbuf *m;
1556
        int off;
1557
{
1558
        struct ip6_hdr *ip6;
1559
 
1560
        switch (IP6OPT_TYPE(*optp)) {
1561
        case IP6OPT_TYPE_SKIP: /* ignore the option */
1562
                return((int)*(optp + 1));
1563
        case IP6OPT_TYPE_DISCARD:       /* silently discard */
1564
                m_freem(m);
1565
                return(-1);
1566
        case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
1567
                ip6stat.ip6s_badoptions++;
1568
                icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
1569
                return(-1);
1570
        case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
1571
                ip6stat.ip6s_badoptions++;
1572
                ip6 = mtod(m, struct ip6_hdr *);
1573
                if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
1574
                    (m->m_flags & (M_BCAST|M_MCAST)))
1575
                        m_freem(m);
1576
                else
1577
                        icmp6_error(m, ICMP6_PARAM_PROB,
1578
                                    ICMP6_PARAMPROB_OPTION, off);
1579
                return(-1);
1580
        }
1581
 
1582
        m_freem(m);             /* XXX: NOTREACHED */
1583
        return(-1);
1584
}
1585
 
1586
/*
1587
 * Create the "control" list for this pcb.
1588
 * The function will not modify mbuf chain at all.
1589
 *
1590
 * with KAME mbuf chain restriction:
1591
 * The routine will be called from upper layer handlers like tcp6_input().
1592
 * Thus the routine assumes that the caller (tcp6_input) have already
1593
 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
1594
 * very first mbuf on the mbuf chain.
1595
 */
1596
void
1597
ip6_savecontrol(in6p, ip6, m, ctl, prevctlp)
1598
#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(HAVE_NRL_INPCB)
1599
        struct inpcb *in6p;
1600
#else
1601
        struct in6pcb *in6p;
1602
#endif
1603
        struct ip6_hdr *ip6;
1604
        struct mbuf *m;
1605
        struct ip6_recvpktopts *ctl, **prevctlp;
1606
{
1607
#define IS2292(x, y)    ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y))
1608
        struct mbuf **mp;
1609
        struct cmsghdr *cm = NULL;
1610
        struct ip6_recvpktopts *prevctl = NULL;
1611
#ifdef HAVE_NRL_INPCB
1612
# define in6p_flags     inp_flags
1613
#endif
1614
#ifdef __bsdi__
1615
# define sbcreatecontrol        so_cmsg
1616
#endif
1617
        int privileged = 1;
1618
 
1619
        if (ctl == NULL)        /* validity check */
1620
                return;
1621
        bzero(ctl, sizeof(*ctl)); /* XXX is it really OK? */
1622
        mp = &ctl->head;
1623
 
1624
        /*
1625
         * If caller wanted to keep history, allocate space to store the
1626
         * history at the first time.
1627
         */
1628
        if (prevctlp) {
1629
                if (*prevctlp == NULL) {
1630
                        MALLOC(prevctl, struct ip6_recvpktopts *,
1631
                               sizeof(*prevctl), M_IP6OPT, M_NOWAIT);
1632
                        if (prevctl == NULL) {
1633
                                printf("ip6_savecontrol: can't allocate "
1634
                                       " enough space for history\n");
1635
                                return;
1636
                        }
1637
                        bzero(prevctl, sizeof(*prevctl));
1638
                        *prevctlp = prevctl;
1639
                }
1640
                else
1641
                        prevctl = *prevctlp;
1642
        }
1643
 
1644
 
1645
#ifdef SO_TIMESTAMP
1646
        if ((in6p->in6p_socket->so_options & SO_TIMESTAMP) != 0) {
1647
                struct timeval tv;
1648
 
1649
                microtime(&tv);
1650
                *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
1651
                                      SCM_TIMESTAMP, SOL_SOCKET);
1652
                if (*mp) {
1653
                        /* always set regradless of the previous value */
1654
                        ctl->timestamp = *mp;
1655
                        mp = &(*mp)->m_next;
1656
                }
1657
        }
1658
#endif
1659
 
1660
        /* RFC 2292 sec. 5 */
1661
        if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) {
1662
                struct in6_pktinfo pi6, *prevpi = NULL;
1663
                bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
1664
                if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr) ||
1665
                    IN6_IS_ADDR_MC_INTFACELOCAL(&pi6.ipi6_addr))
1666
                        pi6.ipi6_addr.s6_addr16[1] = 0;
1667
                pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
1668
                                        ? m->m_pkthdr.rcvif->if_index
1669
                                        : 0;
1670
                if (prevctl && prevctl->pktinfo) {
1671
                        cm = mtod(prevctl->pktinfo, struct cmsghdr *);
1672
                        prevpi = (struct in6_pktinfo *)CMSG_DATA(cm);
1673
                }
1674
 
1675
                /*
1676
                 * Make a new option only if this is the first time or if the
1677
                 * option value is chaned from last time.
1678
                 */
1679
                if (prevpi == NULL || bcmp(prevpi, &pi6, sizeof(pi6))) {
1680
                        *mp = sbcreatecontrol((caddr_t) &pi6,
1681
                             sizeof(struct in6_pktinfo),
1682
                             IS2292(IPV6_2292PKTINFO, IPV6_PKTINFO),
1683
                             IPPROTO_IPV6);
1684
                        if (*mp) {
1685
                                ctl->pktinfo = *mp;
1686
                                mp = &(*mp)->m_next;
1687
                        }
1688
                }
1689
        }
1690
 
1691
        if ((in6p->in6p_flags & IN6P_HOPLIMIT) != 0) {
1692
                int hlim = ip6->ip6_hlim & 0xff, oldhlim = -1;
1693
 
1694
                if (prevctl && prevctl->hlim) {
1695
                        cm = mtod(prevctl->hlim, struct cmsghdr *);
1696
                        bcopy(CMSG_DATA(cm), &oldhlim, sizeof(oldhlim));
1697
                        oldhlim &= 0xff;
1698
                }
1699
 
1700
                if (oldhlim < 0 || hlim != oldhlim) {
1701
                        *mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int),
1702
                            IS2292(IPV6_2292HOPLIMIT, IPV6_HOPLIMIT),
1703
                            IPPROTO_IPV6);
1704
                        if (*mp) {
1705
                                ctl->hlim = *mp;
1706
                                mp = &(*mp)->m_next;
1707
                        }
1708
                }
1709
        }
1710
 
1711
        if ((in6p->in6p_flags & IN6P_TCLASS) != 0) {
1712
                u_int32_t flowinfo;
1713
                int oflowinfo = -1;
1714
                int v;
1715
 
1716
                flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK);
1717
                flowinfo >>= 20;
1718
 
1719
                if (prevctl && prevctl->hlim) {
1720
                        cm = mtod(prevctl->hlim, struct cmsghdr *);
1721
                        bcopy(CMSG_DATA(cm), &v, sizeof(v));
1722
                        oflowinfo = v & 0xff;
1723
                }
1724
 
1725
                if (oflowinfo < 0 || flowinfo != oflowinfo) {
1726
                        v = flowinfo & 0xff;
1727
                        *mp = sbcreatecontrol((caddr_t) &v, sizeof(v),
1728
                            IPV6_TCLASS, IPPROTO_IPV6);
1729
                        if (*mp) {
1730
                                ctl->hlim = *mp;
1731
                                mp = &(*mp)->m_next;
1732
                        }
1733
                }
1734
        }
1735
 
1736
        /*
1737
         * IPV6_HOPOPTS socket option. We require super-user privilege
1738
         * for the option, but it might be too strict, since there might
1739
         * be some hop-by-hop options which can be returned to normal user.
1740
         * See RFC 2292 section 6.
1741
         */
1742
        if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0 && privileged) {
1743
                /*
1744
                 * Check if a hop-by-hop options header is contatined in the
1745
                 * received packet, and if so, store the options as ancillary
1746
                 * data. Note that a hop-by-hop options header must be
1747
                 * just after the IPv6 header, which fact is assured through
1748
                 * the IPv6 input processing.
1749
                 */
1750
                struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1751
                if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1752
                        struct ip6_hbh *hbh, *prevhbh = NULL;
1753
                        int hbhlen = 0, prevhbhlen = 0;
1754
#ifdef PULLDOWN_TEST
1755
                        struct mbuf *ext;
1756
#endif
1757
 
1758
#ifndef PULLDOWN_TEST
1759
                        hbh = (struct ip6_hbh *)(ip6 + 1);
1760
                        hbhlen = (hbh->ip6h_len + 1) << 3;
1761
#else
1762
                        ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
1763
                            ip6->ip6_nxt);
1764
                        if (ext == NULL) {
1765
                                ip6stat.ip6s_tooshort++;
1766
                                return;
1767
                        }
1768
                        hbh = mtod(ext, struct ip6_hbh *);
1769
                        hbhlen = (hbh->ip6h_len + 1) << 3;
1770
                        if (hbhlen != ext->m_len) {
1771
                                m_freem(ext);
1772
                                ip6stat.ip6s_tooshort++;
1773
                                return;
1774
                        }
1775
#endif
1776
 
1777
                        if (prevctl && prevctl->hbh) {
1778
                                cm = mtod(prevctl->hbh, struct cmsghdr *);
1779
                                prevhbh = (struct ip6_hbh *)CMSG_DATA(cm);
1780
                                prevhbhlen = (prevhbh->ip6h_len + 1) << 3;
1781
                        }
1782
                        /*
1783
                         * Check if there's difference between the current
1784
                         * and previous HbH headers.
1785
                         * XXX: should the next header field be ignored?
1786
                         */
1787
                        if (prevhbh == NULL || hbhlen != prevhbhlen ||
1788
                            bcmp(prevhbh, hbh, hbhlen)) {
1789
                                /*
1790
                                 * XXX: We copy whole the header even if a
1791
                                 * jumbo payload option is included, which
1792
                                 * option is to be removed before returning
1793
                                 * in the RFC 2292.
1794
                                 * Note: this constraint is removed in
1795
                                 * 2292bis.
1796
                                 */
1797
                                *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1798
                                    IS2292(IPV6_2292HOPOPTS, IPV6_HOPOPTS),
1799
                                    IPPROTO_IPV6);
1800
                                if (*mp) {
1801
                                        ctl->hbh = *mp;
1802
                                        mp = &(*mp)->m_next;
1803
                                }
1804
                        }
1805
#ifdef PULLDOWN_TEST
1806
                        m_freem(ext);
1807
#endif
1808
                }
1809
        }
1810
 
1811
        if ((in6p->in6p_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) {
1812
                struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1813
                int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
1814
 
1815
                /*
1816
                 * Search for destination options headers or routing
1817
                 * header(s) through the header chain, and stores each
1818
                 * header as ancillary data.
1819
                 * Note that the order of the headers remains in
1820
                 * the chain of ancillary data.
1821
                 */
1822
                while (1) {     /* is explicit loop prevention necessary? */
1823
                        struct ip6_ext *ip6e = NULL;
1824
                        int elen;
1825
#ifdef PULLDOWN_TEST
1826
                        struct mbuf *ext = NULL;
1827
#endif
1828
 
1829
                        /*
1830
                         * if it is not an extension header, don't try to
1831
                         * pull it from the chain.
1832
                         */
1833
                        switch (nxt) {
1834
                        case IPPROTO_DSTOPTS:
1835
                        case IPPROTO_ROUTING:
1836
                        case IPPROTO_HOPOPTS:
1837
                        case IPPROTO_AH: /* is it possible? */
1838
                                break;
1839
                        default:
1840
                                goto loopend;
1841
                        }
1842
 
1843
#ifndef PULLDOWN_TEST
1844
                        if (off + sizeof(*ip6e) > m->m_len)
1845
                                goto loopend;
1846
                        ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
1847
                        if (nxt == IPPROTO_AH)
1848
                                elen = (ip6e->ip6e_len + 2) << 2;
1849
                        else
1850
                                elen = (ip6e->ip6e_len + 1) << 3;
1851
                        if (off + elen > m->m_len)
1852
                                goto loopend;
1853
#else
1854
                        ext = ip6_pullexthdr(m, off, nxt);
1855
                        if (ext == NULL) {
1856
                                ip6stat.ip6s_tooshort++;
1857
                                return;
1858
                        }
1859
                        ip6e = mtod(ext, struct ip6_ext *);
1860
                        if (nxt == IPPROTO_AH)
1861
                                elen = (ip6e->ip6e_len + 2) << 2;
1862
                        else
1863
                                elen = (ip6e->ip6e_len + 1) << 3;
1864
                        if (elen != ext->m_len) {
1865
                                m_freem(ext);
1866
                                ip6stat.ip6s_tooshort++;
1867
                                return;
1868
                        }
1869
#endif
1870
 
1871
                        switch (nxt) {
1872
                        case IPPROTO_DSTOPTS:
1873
                        {
1874
                                struct ip6_dest *prevdest = NULL;
1875
                                int prevdestlen = 0;
1876
 
1877
                                if (!(in6p->in6p_flags & IN6P_DSTOPTS))
1878
                                        break;
1879
 
1880
                                /*
1881
                                 * We also require super-user privilege for
1882
                                 * the option.  See comments on IN6_HOPOPTS.
1883
                                 */
1884
 
1885
                                if (prevctl && prevctl->dest) {
1886
                                        cm = mtod(prevctl->dest,
1887
                                                  struct cmsghdr *);
1888
                                        prevdest = (struct ip6_dest *)CMSG_DATA(cm);
1889
                                        prevdestlen =
1890
                                                (prevdest->ip6d_len + 1) << 3;
1891
                                }
1892
 
1893
                                /*
1894
                                 * If this is the 1st dst opt header
1895
                                 * we enconter and this header is
1896
                                 * not different from the previous one,
1897
                                 * simply ignore the header.
1898
                                 */
1899
                                if (ctl->dest == NULL && prevdest &&
1900
                                    prevdestlen == elen &&
1901
                                    bcmp(ip6e, prevdest, elen) == 0)
1902
                                        break;
1903
 
1904
                                *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1905
                                                      IS2292(IPV6_2292DSTOPTS,
1906
                                                             IPV6_DSTOPTS),
1907
                                                      IPPROTO_IPV6);
1908
                                if (ctl->dest == NULL)
1909
                                        ctl->dest = *mp;
1910
                                if (*mp)
1911
                                        mp = &(*mp)->m_next;
1912
                                break;
1913
                        }
1914
                        case IPPROTO_ROUTING:
1915
                        {
1916
                                struct ip6_rthdr *prevrth = NULL;
1917
                                int prevrhlen = 0;
1918
 
1919
                                if (!in6p->in6p_flags & IN6P_RTHDR)
1920
                                        break;
1921
 
1922
                                if (prevctl && prevctl->rthdr) {
1923
                                        cm = mtod(prevctl->rthdr,
1924
                                                  struct cmsghdr *);
1925
                                        prevrth = (struct ip6_rthdr *)CMSG_DATA(cm);
1926
                                        prevrhlen =
1927
                                                (prevrth->ip6r_len + 1) << 3;
1928
                                }
1929
 
1930
                                /*
1931
                                 * Check if the rthdr should be passed to
1932
                                 * a user. See the comments for dstopt hdr.
1933
                                 */
1934
                                if (ctl->rthdr == NULL && prevrth &&
1935
                                    prevrhlen == elen &&
1936
                                    bcmp(ip6e, prevrth, elen) == 0)
1937
                                        break;
1938
 
1939
                                *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1940
                                                      IS2292(IPV6_2292RTHDR,
1941
                                                             IPV6_RTHDR),
1942
                                                      IPPROTO_IPV6);
1943
                                if (ctl->rthdr == NULL)
1944
                                        ctl->rthdr = *mp;
1945
                                if (*mp)
1946
                                        mp = &(*mp)->m_next;
1947
                                break;
1948
                        }
1949
                        case IPPROTO_HOPOPTS:
1950
                        case IPPROTO_AH: /* is it possible? */
1951
                                break;
1952
 
1953
                        default:
1954
                                /*
1955
                                 * other cases have been filtered in the above.
1956
                                 * none will visit this case.  here we supply
1957
                                 * the code just in case (nxt overwritten or
1958
                                 * other cases).
1959
                                 */
1960
#ifdef PULLDOWN_TEST
1961
                                m_freem(ext);
1962
#endif
1963
                                goto loopend;
1964
 
1965
                        }
1966
 
1967
                        /* proceed with the next header. */
1968
                        off += elen;
1969
                        nxt = ip6e->ip6e_nxt;
1970
                        ip6e = NULL;
1971
#ifdef PULLDOWN_TEST
1972
                        m_freem(ext);
1973
                        ext = NULL;
1974
#endif
1975
                }
1976
          loopend:
1977
                ;
1978
        }
1979
 
1980
#ifdef __bsdi__
1981
# undef sbcreatecontrol
1982
#endif
1983
#ifdef __OpenBSD__
1984
# undef in6p_flags
1985
#endif
1986
#undef IS2292
1987
}
1988
 
1989
void
1990
ip6_notify_pmtu(in6p, dst, mtu)
1991
#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(HAVE_NRL_INPCB)
1992
        struct inpcb *in6p;
1993
#else
1994
        struct in6pcb *in6p;
1995
#endif
1996
        struct sockaddr_in6 *dst;
1997
        u_int32_t *mtu;
1998
{
1999
        struct socket *so;
2000
        struct mbuf *m_mtu;
2001
        struct ip6_mtuinfo mtuctl;
2002
#ifdef __bsdi__
2003
# define sbcreatecontrol        so_cmsg
2004
#endif
2005
 
2006
#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(HAVE_NRL_INPCB)
2007
        so =  in6p->inp_socket;
2008
#else
2009
        so = in6p->in6p_socket;
2010
#endif
2011
 
2012
        if (mtu == NULL)
2013
                return;
2014
 
2015
#ifdef DIAGNOSTIC
2016
        if (so == NULL)         /* I believe this is impossible */
2017
                panic("ip6_notify_pmtu: socket is NULL");
2018
#endif
2019
 
2020
        bzero(&mtuctl, sizeof(mtuctl)); /* zero-clear for safety */
2021
        mtuctl.ip6m_mtu = *mtu;
2022
        mtuctl.ip6m_addr = *dst;
2023
#ifndef SCOPEDROUTING
2024
        in6_recoverscope(&mtuctl.ip6m_addr, &mtuctl.ip6m_addr.sin6_addr, NULL);
2025
#endif
2026
 
2027
        if ((m_mtu = sbcreatecontrol((caddr_t)&mtuctl, sizeof(mtuctl),
2028
                                     IPV6_PATHMTU, IPPROTO_IPV6)) == NULL)
2029
                return;
2030
 
2031
        if (sbappendaddr(&so->so_rcv, (struct sockaddr *)dst, NULL, m_mtu)
2032
            == 0) {
2033
                m_freem(m_mtu);
2034
                /* XXX: should count statistics */
2035
        } else
2036
                sorwakeup(so);
2037
 
2038
        return;
2039
 
2040
#ifdef __bsdi__
2041
# undef sbcreatecontrol
2042
#endif
2043
}
2044
 
2045
#ifdef PULLDOWN_TEST
2046
/*
2047
 * pull single extension header from mbuf chain.  returns single mbuf that
2048
 * contains the result, or NULL on error.
2049
 */
2050
static struct mbuf *
2051
ip6_pullexthdr(m, off, nxt)
2052
        struct mbuf *m;
2053
        size_t off;
2054
        int nxt;
2055
{
2056
        struct ip6_ext ip6e;
2057
        size_t elen;
2058
        struct mbuf *n;
2059
 
2060
#ifdef DIAGNOSTIC
2061
        switch (nxt) {
2062
        case IPPROTO_DSTOPTS:
2063
        case IPPROTO_ROUTING:
2064
        case IPPROTO_HOPOPTS:
2065
        case IPPROTO_AH: /* is it possible? */
2066
                break;
2067
        default:
2068
                printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
2069
        }
2070
#endif
2071
 
2072
        m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
2073
        if (nxt == IPPROTO_AH)
2074
                elen = (ip6e.ip6e_len + 2) << 2;
2075
        else
2076
                elen = (ip6e.ip6e_len + 1) << 3;
2077
 
2078
        MGET(n, M_DONTWAIT, MT_DATA);
2079
        if (n && elen >= MLEN) {
2080
                MCLGET(n, M_DONTWAIT);
2081
                if ((n->m_flags & M_EXT) == 0) {
2082
                        m_free(n);
2083
                        n = NULL;
2084
                }
2085
        }
2086
        if (!n)
2087
                return NULL;
2088
 
2089
        n->m_len = 0;
2090
        if (elen >= M_TRAILINGSPACE(n)) {
2091
                m_free(n);
2092
                return NULL;
2093
        }
2094
 
2095
        m_copydata(m, off, elen, mtod(n, caddr_t));
2096
        n->m_len = elen;
2097
        return n;
2098
}
2099
#endif
2100
 
2101
/*
2102
 * Merge new IPv6 received options to previous ones.
2103
 * If a new option is not given, just re-link the option chain.
2104
 * If an old option exists but a corresponding new one doesn't, just
2105
 * keep the ole option.
2106
 * If a new option exists but a corresponding old one doesn't, just
2107
 * copy the new option.
2108
 * If both new and old options exist, free old one and overwrite the option
2109
 * with the new option.
2110
 * Otherwise, do nothing for the option.
2111
 * XXX: in any case, options that don't follow the recommend order and
2112
 *      number of extension headers (RFC 2460 Section 4.1) are simply ignored.
2113
 * XXX: We assume that each option is stored in a single mbuf.
2114
 */
2115
#define CLEAN_RECVOPT(old, type) \
2116
do {                                                            \
2117
        if ((old)->type && (old)->type->m_next) {               \
2118
                (old)->type->m_next = NULL;                     \
2119
        }                                                       \
2120
} while (0)
2121
#define MERGE_RECVOPT(new, old, type) if ((new)->type) {\
2122
                if ((old)->type)\
2123
                        m_free((old)->type);\
2124
                (old)->type = m_copy((new)->type, 0, (new)->type->m_len);\
2125
                if (((old)->type) && ((old)->type->m_next)) {\
2126
                        m_freem((old)->type);\
2127
                        old->type = NULL;\
2128
                }\
2129
        }
2130
#define LINK_RECVOPTS(opt, type, p) if ((opt)->type) {\
2131
                *(p) = (opt)->type;\
2132
                (p) = &(opt)->type->m_next;\
2133
        }
2134
 
2135
static void dump_inputopts __P((char *, struct ip6_recvpktopts *));
2136
static void
2137
dump_inputopts(str, p)
2138
        char *str;
2139
        struct ip6_recvpktopts *p;
2140
{
2141
#if 1
2142
        return;
2143
#else
2144
#define PRINT1(p, name) \
2145
do { \
2146
        if (p->name) { \
2147
                printf(" %s: %p", #name, (p)->name); \
2148
                if (p->name->m_next) \
2149
                        printf("[%p]", (p)->name->m_next); \
2150
        } \
2151
} while (0)
2152
 
2153
        printf("%s p=%p head=%p", str, p, p->head);
2154
        PRINT1(p, hlim);
2155
        PRINT1(p, pktinfo);
2156
        PRINT1(p, hbh);
2157
        PRINT1(p, dest);
2158
        PRINT1(p, rthdr);
2159
        printf("\n");
2160
#undef PRINT1
2161
#endif
2162
}
2163
 
2164
void
2165
ip6_update_recvpcbopt(old, new)
2166
        struct ip6_recvpktopts *new, *old;
2167
{
2168
        struct mbuf **mp;
2169
 
2170
        if (old == NULL) {
2171
                printf("ip6_update_recvpcbopt: invalid arguments\n");
2172
                return;
2173
        }
2174
 
2175
        dump_inputopts("old before", old);
2176
        if (new)
2177
                dump_inputopts("new before", new);
2178
 
2179
#if 0
2180
        /*
2181
         * cleanup m->m_next linkage. note that we do it in reverse order
2182
         * to prevent possible memory leakage.
2183
         */
2184
        old->head = NULL;
2185
        CLEAN_RECVOPT(old, rthdr);
2186
        CLEAN_RECVOPT(old, dest);
2187
        CLEAN_RECVOPT(old, hbh);
2188
        CLEAN_RECVOPT(old, pktinfo);
2189
        CLEAN_RECVOPT(old, hlim);
2190
#endif
2191
 
2192
        if (new) {
2193
                MERGE_RECVOPT(new, old, hlim);
2194
                MERGE_RECVOPT(new, old, pktinfo);
2195
                MERGE_RECVOPT(new, old, hbh);
2196
                MERGE_RECVOPT(new, old, dest);
2197
                MERGE_RECVOPT(new, old, rthdr);
2198
        }
2199
 
2200
        dump_inputopts("old middle", old);
2201
        if (new)
2202
                dump_inputopts("new middle", new);
2203
 
2204
        /* link options */
2205
        mp = &old->head;
2206
        LINK_RECVOPTS(old, hlim, mp);
2207
        LINK_RECVOPTS(old, pktinfo, mp);
2208
        LINK_RECVOPTS(old, hbh, mp);
2209
        LINK_RECVOPTS(old, dest, mp);
2210
        LINK_RECVOPTS(old, rthdr, mp);
2211
        *mp = NULL;
2212
 
2213
        dump_inputopts("old after", old);
2214
        if (new)
2215
                dump_inputopts("new after", new);
2216
}
2217
 
2218
#undef MERGE_RECVOPT
2219
#undef LINK_RECVOPTS
2220
 
2221
void
2222
ip6_reset_rcvopt(opts, optname)
2223
        struct ip6_recvpktopts *opts;
2224
        int optname;
2225
{
2226
        if (opts == NULL)
2227
                return;
2228
 
2229
        switch (optname) {
2230
        case IPV6_RECVPKTINFO:
2231
                if (opts->pktinfo) m_free(opts->pktinfo);
2232
                opts->pktinfo = NULL;
2233
                break;
2234
        case IPV6_RECVHOPLIMIT:
2235
                if (opts->hlim) m_free(opts->hlim);
2236
                opts->hlim = NULL;
2237
                break;
2238
        case IPV6_RECVHOPOPTS:
2239
                if (opts->hbh) m_free(opts->hbh);
2240
                opts->hbh = NULL;
2241
                break;
2242
        case IPV6_RECVDSTOPTS:
2243
                if (opts->dest) m_free(opts->dest);
2244
                opts->dest = NULL;
2245
                break;
2246
        case IPV6_RECVRTHDR:
2247
                if (opts->rthdr) m_free(opts->rthdr);
2248
                opts->rthdr = NULL;
2249
                break;
2250
        default:
2251
                printf("ip6_reset_rcvopt: invalid option name (%d)\n",
2252
                       optname);
2253
                return;
2254
        }
2255
 
2256
        ip6_update_recvpcbopt(opts, NULL); /* re-link the option chain */
2257
}
2258
 
2259
/*
2260
 * Get pointer to the previous header followed by the header
2261
 * currently processed.
2262
 * XXX: This function supposes that
2263
 *      M includes all headers,
2264
 *      the next header field and the header length field of each header
2265
 *      are valid, and
2266
 *      the sum of each header length equals to OFF.
2267
 * Because of these assumptions, this function must be called very
2268
 * carefully. Moreover, it will not be used in the near future when
2269
 * we develop `neater' mechanism to process extension headers.
2270
 */
2271
char *
2272
ip6_get_prevhdr(m, off)
2273
        struct mbuf *m;
2274
        int off;
2275
{
2276
        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
2277
 
2278
        if (off == sizeof(struct ip6_hdr))
2279
                return(&ip6->ip6_nxt);
2280
        else {
2281
                int len, nxt;
2282
                struct ip6_ext *ip6e = NULL;
2283
 
2284
                nxt = ip6->ip6_nxt;
2285
                len = sizeof(struct ip6_hdr);
2286
                while (len < off) {
2287
                        ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
2288
 
2289
                        switch (nxt) {
2290
                        case IPPROTO_FRAGMENT:
2291
                                len += sizeof(struct ip6_frag);
2292
                                break;
2293
                        case IPPROTO_AH:
2294
                                len += (ip6e->ip6e_len + 2) << 2;
2295
                                break;
2296
                        default:
2297
                                len += (ip6e->ip6e_len + 1) << 3;
2298
                                break;
2299
                        }
2300
                        nxt = ip6e->ip6e_nxt;
2301
                }
2302
                if (ip6e)
2303
                        return(&ip6e->ip6e_nxt);
2304
                else
2305
                        return NULL;
2306
        }
2307
}
2308
 
2309
/*
2310
 * get next header offset.  m will be retained.
2311
 */
2312
int
2313
ip6_nexthdr(m, off, proto, nxtp)
2314
        struct mbuf *m;
2315
        int off;
2316
        int proto;
2317
        int *nxtp;
2318
{
2319
        struct ip6_hdr ip6;
2320
        struct ip6_ext ip6e;
2321
        struct ip6_frag fh;
2322
 
2323
        /* just in case */
2324
        if (m == NULL)
2325
                panic("ip6_nexthdr: m == NULL");
2326
        if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
2327
                return -1;
2328
 
2329
        switch (proto) {
2330
        case IPPROTO_IPV6:
2331
                /* do not chase beyond intermediate IPv6 headers */
2332
                if (off != 0)
2333
                        return -1;
2334
                if (m->m_pkthdr.len < off + sizeof(ip6))
2335
                        return -1;
2336
                m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
2337
                if (nxtp)
2338
                        *nxtp = ip6.ip6_nxt;
2339
                off += sizeof(ip6);
2340
                return off;
2341
 
2342
        case IPPROTO_FRAGMENT:
2343
                /*
2344
                 * terminate parsing if it is not the first fragment,
2345
                 * it does not make sense to parse through it.
2346
                 */
2347
                if (m->m_pkthdr.len < off + sizeof(fh))
2348
                        return -1;
2349
                m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
2350
                if ((ntohs(fh.ip6f_offlg) & IP6F_OFF_MASK) != 0)
2351
                        return -1;
2352
                if (nxtp)
2353
                        *nxtp = fh.ip6f_nxt;
2354
                off += sizeof(struct ip6_frag);
2355
                return off;
2356
 
2357
        case IPPROTO_AH:
2358
                if (m->m_pkthdr.len < off + sizeof(ip6e))
2359
                        return -1;
2360
                m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
2361
                if (nxtp)
2362
                        *nxtp = ip6e.ip6e_nxt;
2363
                off += (ip6e.ip6e_len + 2) << 2;
2364
                if (m->m_pkthdr.len < off)
2365
                        return -1;
2366
                return off;
2367
 
2368
        case IPPROTO_HOPOPTS:
2369
        case IPPROTO_ROUTING:
2370
        case IPPROTO_DSTOPTS:
2371
                if (m->m_pkthdr.len < off + sizeof(ip6e))
2372
                        return -1;
2373
                m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
2374
                if (nxtp)
2375
                        *nxtp = ip6e.ip6e_nxt;
2376
                off += (ip6e.ip6e_len + 1) << 3;
2377
                if (m->m_pkthdr.len < off)
2378
                        return -1;
2379
                return off;
2380
 
2381
        case IPPROTO_NONE:
2382
        case IPPROTO_ESP:
2383
        case IPPROTO_IPCOMP:
2384
                /* give up */
2385
                return -1;
2386
 
2387
        default:
2388
                return -1;
2389
        }
2390
 
2391
        return -1;
2392
}
2393
 
2394
/*
2395
 * get offset for the last header in the chain.  m will be kept untainted.
2396
 */
2397
int
2398
ip6_lasthdr(m, off, proto, nxtp)
2399
        struct mbuf *m;
2400
        int off;
2401
        int proto;
2402
        int *nxtp;
2403
{
2404
        int newoff;
2405
        int nxt;
2406
 
2407
        if (!nxtp) {
2408
                nxt = -1;
2409
                nxtp = &nxt;
2410
        }
2411
        while (1) {
2412
                newoff = ip6_nexthdr(m, off, proto, nxtp);
2413
                if (newoff < 0)
2414
                        return off;
2415
                else if (newoff < off)
2416
                        return -1;      /* invalid */
2417
                else if (newoff == off)
2418
                        return newoff;
2419
 
2420
                off = newoff;
2421
                proto = *nxtp;
2422
        }
2423
}
2424
 
2425
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 4)
2426
void
2427
pfctlinput2(cmd, sa, ctlparam)
2428
        int cmd;
2429
        struct sockaddr *sa;
2430
        void *ctlparam;
2431
{
2432
        struct domain *dp;
2433
        struct protosw *pr;
2434
 
2435
        if (!sa)
2436
                return;
2437
        for (dp = domains; dp; dp = dp->dom_next) {
2438
                /*
2439
                 * the check must be made by xx_ctlinput() anyways, to
2440
                 * make sure we use data item pointed to by ctlparam in
2441
                 * correct way.  the following check is made just for safety.
2442
                 */
2443
                if (dp->dom_family != sa->sa_family)
2444
                        continue;
2445
 
2446
                for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
2447
                        if (pr->pr_ctlinput)
2448
                                (*pr->pr_ctlinput)(cmd, sa, ctlparam);
2449
        }
2450
}
2451
#endif
2452
 
2453
struct mbuf *
2454
ip6_addaux(m)
2455
        struct mbuf *m;
2456
{
2457
        struct mbuf *n;
2458
 
2459
#ifdef DIAGNOSTIC
2460
        if (sizeof(struct ip6aux) > MHLEN)
2461
                panic("assumption failed on sizeof(ip6aux)");
2462
#endif
2463
        n = m_aux_find(m, AF_INET6, -1);
2464
        if (n) {
2465
                if (n->m_len < sizeof(struct ip6aux)) {
2466
                        printf("conflicting use of ip6aux");
2467
                        return NULL;
2468
                }
2469
        } else {
2470
                n = m_aux_add(m, AF_INET6, -1);
2471
                n->m_len = sizeof(struct ip6aux);
2472
                bzero(mtod(n, caddr_t), n->m_len);
2473
        }
2474
        return n;
2475
}
2476
 
2477
struct mbuf *
2478
ip6_findaux(m)
2479
        struct mbuf *m;
2480
{
2481
        struct mbuf *n;
2482
 
2483
        n = m_aux_find(m, AF_INET6, -1);
2484
        if (n && n->m_len < sizeof(struct ip6aux)) {
2485
                printf("conflicting use of ip6aux");
2486
                n = NULL;
2487
        }
2488
        return n;
2489
}
2490
 
2491
void
2492
ip6_delaux(m)
2493
        struct mbuf *m;
2494
{
2495
        struct mbuf *n;
2496
 
2497
        n = m_aux_find(m, AF_INET6, -1);
2498
        if (n)
2499
                m_aux_delete(m, n);
2500
}
2501
 
2502
/*
2503
 * System control for IP6
2504
 */
2505
 
2506
int inet6ctlerrmap[PRC_NCMDS] = {
2507
        0,               0,               0,               0,
2508
        0,               EMSGSIZE,       EHOSTDOWN,      EHOSTUNREACH,
2509
        EHOSTUNREACH,   EHOSTUNREACH,   ECONNREFUSED,   ECONNREFUSED,
2510
        EMSGSIZE,       EHOSTUNREACH,   0,               0,
2511
        0,               0,               0,               0,
2512
        ENOPROTOOPT
2513
};
2514
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.