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/] [in6_gif.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/in6_gif.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: in6_gif.c,v 1.88 2001/12/21 03:32:34 itojun 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
/* define it if you want to use encap_attach_func (it helps *BSD merge) */
52
/*#define USE_ENCAPCHECK*/
53
 
54
#include <sys/param.h>
55
#include <sys/socket.h>
56
#include <sys/sockio.h>
57
#include <sys/mbuf.h>
58
#include <sys/errno.h>
59
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
60
#include <sys/ioctl.h>
61
#endif
62
#include <sys/queue.h>
63
#include <sys/protosw.h>
64
 
65
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
66
#include <sys/malloc.h>
67
#endif
68
 
69
#include <net/if.h>
70
#include <net/route.h>
71
 
72
#include <netinet/in.h>
73
#include <netinet/in_systm.h>
74
#ifdef INET
75
#include <netinet/ip.h>
76
#endif
77
#include <netinet/ip_encap.h>
78
#ifdef INET6
79
#include <netinet/ip6.h>
80
#include <netinet6/ip6_var.h>
81
#include <netinet6/in6_gif.h>
82
#include <netinet6/in6_var.h>
83
#endif
84
#include <netinet6/ip6protosw.h>
85
#include <netinet/ip_ecn.h>
86
#ifdef __OpenBSD__
87
#include <netinet/ip_ipsp.h>
88
#endif
89
 
90
#include <net/if_gif.h>
91
 
92
#ifdef __OpenBSD__
93
#include "bridge.h"
94
#endif
95
 
96
static int gif_validate6 __P((const struct ip6_hdr *, struct gif_softc *,
97
        struct ifnet *));
98
static int in6_gif_rtcachettl = 300; /* XXX see in_gif.c */
99
 
100
int     ip6_gif_hlim = GIF_HLIM;
101
 
102
extern struct domain inet6domain;
103
struct ip6protosw in6_gif_protosw =
104
{ SOCK_RAW,     &inet6domain,   0/* IPPROTO_IPV[46] */,  PR_ATOMIC|PR_ADDR,
105
  in6_gif_input, rip6_output,   in6_gif_ctlinput, rip6_ctloutput,
106
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
107
  0,
108
#else
109
  rip6_usrreq,
110
#endif
111
  0,            0,              0,              0,
112
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
113
  &rip6_usrreqs
114
#endif
115
};
116
 
117
extern LIST_HEAD(, gif_softc) gif_softc_list;
118
 
119
#ifndef offsetof
120
#define offsetof(s, e) ((int)&((s *)0)->e)
121
#endif
122
 
123
int
124
in6_gif_output(ifp, family, m)
125
        struct ifnet *ifp;
126
        int family; /* family of the packet to be encapsulate. */
127
        struct mbuf *m;
128
{
129
#ifdef __OpenBSD__
130
        struct gif_softc *sc = (struct gif_softc*)ifp;
131
        struct sockaddr_in6 *dst = (struct sockaddr_in6 *)&sc->gif_ro6.ro_dst;
132
        struct sockaddr_in6 *sin6_src = (struct sockaddr_in6 *)sc->gif_psrc;
133
        struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst;
134
        struct tdb tdb;
135
        struct xformsw xfs;
136
        int error;
137
        int hlen, poff;
138
        struct mbuf *mp;
139
        long time_second;
140
 
141
        if (sin6_src == NULL || sin6_dst == NULL ||
142
            sin6_src->sin6_family != AF_INET6 ||
143
            sin6_dst->sin6_family != AF_INET6) {
144
                m_freem(m);
145
                return EAFNOSUPPORT;
146
        }
147
 
148
        /* setup dummy tdb.  it highly depends on ipip_output() code. */
149
        bzero(&tdb, sizeof(tdb));
150
        bzero(&xfs, sizeof(xfs));
151
        tdb.tdb_src.sin6.sin6_family = AF_INET6;
152
        tdb.tdb_src.sin6.sin6_len = sizeof(struct sockaddr_in6);
153
        tdb.tdb_src.sin6.sin6_addr = sin6_src->sin6_addr;
154
        tdb.tdb_dst.sin6.sin6_family = AF_INET6;
155
        tdb.tdb_dst.sin6.sin6_len = sizeof(struct sockaddr_in6);
156
        tdb.tdb_dst.sin6.sin6_addr = sin6_dst->sin6_addr;
157
        tdb.tdb_xform = &xfs;
158
        xfs.xf_type = -1;       /* not XF_IP4 */
159
 
160
        switch (family) {
161
#ifdef INET
162
        case AF_INET:
163
            {
164
                if (m->m_len < sizeof(struct ip)) {
165
                        m = m_pullup(m, sizeof(struct ip));
166
                        if (!m)
167
                                return ENOBUFS;
168
                }
169
                hlen = (mtod(m, struct ip *)->ip_hl) << 2;
170
                poff = offsetof(struct ip, ip_p);
171
                break;
172
            }
173
#endif
174
#ifdef INET6
175
        case AF_INET6:
176
            {
177
                hlen = sizeof(struct ip6_hdr);
178
                poff = offsetof(struct ip6_hdr, ip6_nxt);
179
                break;
180
            }
181
#endif
182
#if NBRIDGE > 0
183
        case AF_LINK:
184
                break;
185
#endif /* NBRIDGE */
186
        default:
187
#ifdef DEBUG
188
                printf("in6_gif_output: warning: unknown family %d passed\n",
189
                        family);
190
#endif
191
                m_freem(m);
192
                return EAFNOSUPPORT;
193
        }
194
 
195
#if NBRIDGE > 0
196
        if (family == AF_LINK) {
197
                mp = NULL;
198
                error = etherip_output(m, &tdb, &mp, 0, 0);
199
                if (error)
200
                        return error;
201
                else if (mp == NULL)
202
                        return EFAULT;
203
 
204
                m = mp;
205
                goto sendit;
206
        }
207
#endif /* NBRIDGE */
208
 
209
        /* encapsulate into IPv6 packet */
210
        mp = NULL;
211
        error = ipip_output(m, &tdb, &mp, hlen, poff);
212
        if (error)
213
                return error;
214
        else if (mp == NULL)
215
                return EFAULT;
216
 
217
        m = mp;
218
 
219
#if NBRIDGE > 0
220
 sendit:
221
#endif /* NBRIDGE */
222
        /*
223
         * compare address family just for safety.  other validity checks
224
         * are made in in6_selectsrc() called from ip6_output().
225
         */
226
        if (sc->gif_ro6.ro_rt && (dst->sin6_family != sin6_dst->sin6_family ||
227
                                  sc->rtcache_expire == 0 ||
228
                                  time_second >= sc->rtcache_expire)) {
229
                RTFREE(sc->gif_ro6.ro_rt);
230
                sc->gif_ro6.ro_rt = NULL;
231
        }
232
 
233
#ifdef IPV6_MINMTU
234
        /*
235
         * force fragmentation to minimum MTU, to avoid path MTU discovery.
236
         * it is too painful to ask for resend of inner packet, to achieve
237
         * path MTU discovery for encapsulated packets.
238
         */
239
        error = ip6_output(m, 0, &sc->gif_ro6, IPV6_MINMTU, 0, NULL);
240
#else
241
        error = ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL);
242
#endif
243
 
244
        if (sc->gif_ro6.ro_rt && time_second >= sc->rtcache_expire)
245
                sc->rtcache_expire = time_second + in6_gif_rtcachettl;
246
 
247
        return(error);
248
#else   /* !__OpenBSD__ */
249
        struct gif_softc *sc = (struct gif_softc*)ifp;
250
        struct sockaddr_in6 *dst = (struct sockaddr_in6 *)&sc->gif_ro6.ro_dst;
251
        struct sockaddr_in6 *sin6_src = (struct sockaddr_in6 *)sc->gif_psrc;
252
        struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst;
253
        struct ip6_hdr *ip6;
254
        int proto, error;
255
        u_int8_t itos, otos;
256
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
257
        long time_second;
258
#endif
259
 
260
        if (sin6_src == NULL || sin6_dst == NULL ||
261
            sin6_src->sin6_family != AF_INET6 ||
262
            sin6_dst->sin6_family != AF_INET6) {
263
                m_freem(m);
264
                return EAFNOSUPPORT;
265
        }
266
 
267
        switch (family) {
268
#ifdef INET
269
        case AF_INET:
270
            {
271
                struct ip *ip;
272
 
273
                proto = IPPROTO_IPV4;
274
                if (m->m_len < sizeof(*ip)) {
275
                        m = m_pullup(m, sizeof(*ip));
276
                        if (!m)
277
                                return ENOBUFS;
278
                }
279
                ip = mtod(m, struct ip *);
280
                itos = ip->ip_tos;
281
                break;
282
            }
283
#endif
284
#ifdef INET6
285
        case AF_INET6:
286
            {
287
                struct ip6_hdr *ip6;
288
                proto = IPPROTO_IPV6;
289
                if (m->m_len < sizeof(*ip6)) {
290
                        m = m_pullup(m, sizeof(*ip6));
291
                        if (!m)
292
                                return ENOBUFS;
293
                }
294
                ip6 = mtod(m, struct ip6_hdr *);
295
                itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
296
                break;
297
            }
298
#endif
299
#if defined(__NetBSD__) && defined(ISO)
300
        case AF_ISO:
301
                proto = IPPROTO_EON;
302
                itos = 0;
303
                break;
304
#endif
305
        default:
306
#ifdef DEBUG
307
                printf("in6_gif_output: warning: unknown family %d passed\n",
308
                        family);
309
#endif
310
                m_freem(m);
311
                return EAFNOSUPPORT;
312
        }
313
 
314
        /* prepend new IP header */
315
        M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
316
        if (m && m->m_len < sizeof(struct ip6_hdr))
317
                m = m_pullup(m, sizeof(struct ip6_hdr));
318
        if (m == NULL)
319
                return ENOBUFS;
320
 
321
        ip6 = mtod(m, struct ip6_hdr *);
322
        ip6->ip6_flow   = 0;
323
        ip6->ip6_vfc    &= ~IPV6_VERSION_MASK;
324
        ip6->ip6_vfc    |= IPV6_VERSION;
325
        ip6->ip6_plen   = htons((u_short)m->m_pkthdr.len);
326
        ip6->ip6_nxt    = proto;
327
        ip6->ip6_hlim   = ip6_gif_hlim;
328
        ip6->ip6_src    = sin6_src->sin6_addr;
329
        /* bidirectional configured tunnel mode */
330
        if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
331
                ip6->ip6_dst = sin6_dst->sin6_addr;
332
        else  {
333
                m_freem(m);
334
                return ENETUNREACH;
335
        }
336
        if (ifp->if_flags & IFF_LINK1)
337
                ip_ecn_ingress(ECN_ALLOWED, &otos, &itos);
338
        else
339
                ip_ecn_ingress(ECN_NOCARE, &otos, &itos);
340
        ip6->ip6_flow &= ~ntohl(0xff00000);
341
        ip6->ip6_flow |= htonl((u_int32_t)otos << 20);
342
 
343
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
344
        time_second = time.tv_sec;
345
#endif
346
        /*
347
         * compare address family just for safety.  other validity checks
348
         * are made in in6_selectsrc() called from ip6_output().
349
         */
350
        if (sc->gif_ro6.ro_rt && (dst->sin6_family != sin6_dst->sin6_family ||
351
                                  sc->rtcache_expire == 0 ||
352
                                  time_second >= sc->rtcache_expire)) {
353
                /*
354
                 * If the cached route is not valid or has expired,
355
                 * clear the stale cache and let ip6_output make a new cached
356
                 * route.
357
                 */
358
                RTFREE(sc->gif_ro6.ro_rt);
359
                sc->gif_ro6.ro_rt = NULL;
360
        }
361
 
362
#ifdef IPV6_MINMTU
363
        /*
364
         * force fragmentation to minimum MTU, to avoid path MTU discovery.
365
         * it is too painful to ask for resend of inner packet, to achieve
366
         * path MTU discovery for encapsulated packets.
367
         */
368
        error = ip6_output(m, 0, &sc->gif_ro6, IPV6_MINMTU, 0, NULL);
369
#else
370
        error = ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL);
371
#endif
372
 
373
        /*
374
         * if a (new) cached route has been created in ip6_output(), extend
375
         * the expiration time.
376
         */
377
        if (sc->gif_ro6.ro_rt && time_second >= sc->rtcache_expire)
378
                sc->rtcache_expire = time_second + in6_gif_rtcachettl;
379
 
380
        return(error);
381
#endif  /* __OpenBSD__ */
382
}
383
 
384
int in6_gif_input(mp, offp, proto)
385
        struct mbuf **mp;
386
        int *offp, proto;
387
{
388
        struct mbuf *m = *mp;
389
        struct ifnet *gifp = NULL;
390
        struct ip6_hdr *ip6;
391
#ifndef __OpenBSD__
392
        int af = 0;
393
        u_int32_t otos;
394
#endif
395
 
396
        ip6 = mtod(m, struct ip6_hdr *);
397
 
398
        gifp = (struct ifnet *)encap_getarg(m);
399
 
400
        if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) {
401
                m_freem(m);
402
                ip6stat.ip6s_nogif++;
403
                return IPPROTO_DONE;
404
        }
405
#ifndef USE_ENCAPCHECK
406
        if (!gif_validate6(ip6, (struct gif_softc *)gifp, m->m_pkthdr.rcvif)) {
407
                m_freem(m);
408
                ip6stat.ip6s_nogif++;
409
                return IPPROTO_DONE;
410
        }
411
#endif
412
 
413
#ifdef __OpenBSD__
414
        m->m_pkthdr.rcvif = gifp;
415
        gifp->if_ipackets++;
416
        gifp->if_ibytes += m->m_pkthdr.len;
417
        ipip_input(m, *offp, gifp);
418
        return IPPROTO_DONE;
419
#else
420
        otos = ip6->ip6_flow;
421
        m_adj(m, *offp);
422
 
423
        switch (proto) {
424
#ifdef INET
425
        case IPPROTO_IPV4:
426
            {
427
                struct ip *ip;
428
                u_int8_t otos8;
429
                af = AF_INET;
430
                otos8 = (ntohl(otos) >> 20) & 0xff;
431
                if (m->m_len < sizeof(*ip)) {
432
                        m = m_pullup(m, sizeof(*ip));
433
                        if (!m)
434
                                return IPPROTO_DONE;
435
                }
436
                ip = mtod(m, struct ip *);
437
                if (gifp->if_flags & IFF_LINK1)
438
                        ip_ecn_egress(ECN_ALLOWED, &otos8, &ip->ip_tos);
439
                else
440
                        ip_ecn_egress(ECN_NOCARE, &otos8, &ip->ip_tos);
441
                break;
442
            }
443
#endif /* INET */
444
#ifdef INET6
445
        case IPPROTO_IPV6:
446
            {
447
                struct ip6_hdr *ip6;
448
                af = AF_INET6;
449
                if (m->m_len < sizeof(*ip6)) {
450
                        m = m_pullup(m, sizeof(*ip6));
451
                        if (!m)
452
                                return IPPROTO_DONE;
453
                }
454
                ip6 = mtod(m, struct ip6_hdr *);
455
                if (gifp->if_flags & IFF_LINK1)
456
                        ip6_ecn_egress(ECN_ALLOWED, &otos, &ip6->ip6_flow);
457
                else
458
                        ip6_ecn_egress(ECN_NOCARE, &otos, &ip6->ip6_flow);
459
                break;
460
            }
461
#endif
462
#if defined(__NetBSD__) && defined(ISO)
463
        case IPPROTO_EON:
464
                af = AF_ISO;
465
                break;
466
#endif
467
        default:
468
                ip6stat.ip6s_nogif++;
469
                m_freem(m);
470
                return IPPROTO_DONE;
471
        }
472
 
473
        gif_input(m, af, gifp);
474
        return IPPROTO_DONE;
475
#endif
476
}
477
 
478
/*
479
 * validate outer address.
480
 */
481
static int
482
gif_validate6(ip6, sc, ifp)
483
        const struct ip6_hdr *ip6;
484
        struct gif_softc *sc;
485
        struct ifnet *ifp;
486
{
487
        struct sockaddr_in6 *src, *dst;
488
 
489
        src = (struct sockaddr_in6 *)sc->gif_psrc;
490
        dst = (struct sockaddr_in6 *)sc->gif_pdst;
491
 
492
        /* check for address match */
493
        if (!IN6_ARE_ADDR_EQUAL(&src->sin6_addr, &ip6->ip6_dst) ||
494
            !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_src))
495
                return 0;
496
 
497
        /* martian filters on outer source - done in ip6_input */
498
 
499
        /* ingress filters on outer source */
500
        if ((sc->gif_if.if_flags & IFF_LINK2) == 0 && ifp) {
501
                struct sockaddr_in6 sin6;
502
                struct rtentry *rt;
503
 
504
                bzero(&sin6, sizeof(sin6));
505
                sin6.sin6_family = AF_INET6;
506
                sin6.sin6_len = sizeof(struct sockaddr_in6);
507
                sin6.sin6_addr = ip6->ip6_src;
508
                /* XXX scopeid */
509
#ifdef __FreeBSD__
510
                rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
511
#else
512
                rt = rtalloc1((struct sockaddr *)&sin6, 0);
513
#endif
514
                if (!rt || rt->rt_ifp != ifp) {
515
#if 0
516
                        log(LOG_WARNING, "%s: packet from %s dropped "
517
                            "due to ingress filter\n", if_name(&sc->gif_if),
518
                            ip6_sprintf(&sin6.sin6_addr));
519
#endif
520
                        if (rt)
521
                                rtfree(rt);
522
                        return 0;
523
                }
524
                rtfree(rt);
525
        }
526
 
527
        return 128 * 2;
528
}
529
 
530
/*
531
 * we know that we are in IFF_UP, outer address available, and outer family
532
 * matched the physical addr family.  see gif_encapcheck().
533
 */
534
int
535
gif_encapcheck6(m, off, proto, arg)
536
        const struct mbuf *m;
537
        int off;
538
        int proto;
539
        void *arg;
540
{
541
        struct ip6_hdr ip6;
542
        struct gif_softc *sc;
543
        struct ifnet *ifp;
544
 
545
        /* sanity check done in caller */
546
        sc = (struct gif_softc *)arg;
547
 
548
        /* LINTED const cast */
549
        m_copydata((struct mbuf *)m, 0, sizeof(ip6), (caddr_t)&ip6);
550
        ifp = ((m->m_flags & M_PKTHDR) != 0) ? m->m_pkthdr.rcvif : NULL;
551
 
552
        return gif_validate6(&ip6, sc, ifp);
553
}
554
 
555
int
556
in6_gif_attach(sc)
557
        struct gif_softc *sc;
558
{
559
#ifndef USE_ENCAPCHECK
560
        struct sockaddr_in6 mask6;
561
 
562
        bzero(&mask6, sizeof(mask6));
563
        mask6.sin6_len = sizeof(struct sockaddr_in6);
564
        mask6.sin6_addr.s6_addr32[0] = mask6.sin6_addr.s6_addr32[1] =
565
            mask6.sin6_addr.s6_addr32[2] = mask6.sin6_addr.s6_addr32[3] = ~0;
566
 
567
        if (!sc->gif_psrc || !sc->gif_pdst)
568
                return EINVAL;
569
        sc->encap_cookie6 = encap_attach(AF_INET6, -1, sc->gif_psrc,
570
            (struct sockaddr *)&mask6, sc->gif_pdst, (struct sockaddr *)&mask6,
571
            (struct protosw *)&in6_gif_protosw, sc);
572
#else
573
        sc->encap_cookie6 = encap_attach_func(AF_INET6, -1, gif_encapcheck,
574
            (struct protosw *)&in6_gif_protosw, sc);
575
#endif
576
        if (sc->encap_cookie6 == NULL)
577
                return EEXIST;
578
        return 0;
579
}
580
 
581
int
582
in6_gif_detach(sc)
583
        struct gif_softc *sc;
584
{
585
        int error;
586
 
587
        error = encap_detach(sc->encap_cookie6);
588
        if (error == 0)
589
                sc->encap_cookie6 = NULL;
590
        return error;
591
}
592
 
593
void
594
in6_gif_ctlinput(cmd, sa, d)
595
        int cmd;
596
        struct sockaddr *sa;
597
        void *d;
598
{
599
        struct gif_softc *sc;
600
        struct ip6ctlparam *ip6cp = NULL;
601
        struct mbuf *m;
602
        struct ip6_hdr *ip6;
603
        int off;
604
        void *cmdarg;
605
        const struct sockaddr_in6 *sa6_src = NULL;
606
        struct sockaddr_in6 *dst6;
607
 
608
        if (sa->sa_family != AF_INET6 ||
609
            sa->sa_len != sizeof(struct sockaddr_in6))
610
                return;
611
 
612
        if ((unsigned)cmd >= PRC_NCMDS)
613
                return;
614
        if (cmd == PRC_HOSTDEAD)
615
                d = NULL;
616
        else if (inet6ctlerrmap[cmd] == 0)
617
                return;
618
 
619
        /* if the parameter is from icmp6, decode it. */
620
        if (d != NULL) {
621
                ip6cp = (struct ip6ctlparam *)d;
622
                m = ip6cp->ip6c_m;
623
                ip6 = ip6cp->ip6c_ip6;
624
                off = ip6cp->ip6c_off;
625
                cmdarg = ip6cp->ip6c_cmdarg;
626
                sa6_src = ip6cp->ip6c_src;
627
        } else {
628
                m = NULL;
629
                ip6 = NULL;
630
                cmdarg = NULL;
631
                sa6_src = &sa6_any;
632
        }
633
 
634
        if (!ip6)
635
                return;
636
 
637
        /*
638
         * for now we don't care which type it was, just flush the route cache.
639
         * XXX slow.  sc (or sc->encap_cookie6) should be passed from
640
         * ip_encap.c.
641
         */
642
        for (sc = LIST_FIRST(&gif_softc_list); sc;
643
             sc = LIST_NEXT(sc, gif_list)) {
644
                if ((sc->gif_if.if_flags & IFF_RUNNING) == 0)
645
                        continue;
646
                if (sc->gif_psrc->sa_family != AF_INET6)
647
                        continue;
648
                if (!sc->gif_ro6.ro_rt)
649
                        continue;
650
 
651
                dst6 = (struct sockaddr_in6 *)&sc->gif_ro6.ro_dst;
652
                /* XXX scope */
653
                if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst6->sin6_addr)) {
654
                        /* flush route cache */
655
                        RTFREE(sc->gif_ro6.ro_rt);
656
                        sc->gif_ro6.ro_rt = NULL;
657
                }
658
        }
659
}

powered by: WebSVN 2.1.0

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