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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [bsd_tcpip/] [current/] [src/] [sys/] [netinet6/] [ip6_input.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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