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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [sys/] [net/] [if.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      sys/net/if.c
4
//
5
//     
6
//
7
//==========================================================================
8
//####BSDCOPYRIGHTBEGIN####
9
//
10
// -------------------------------------------
11
//
12
// Portions of this software may have been derived from OpenBSD or other sources,
13
// and are covered by the appropriate copyright disclaimers included herein.
14
//
15
// -------------------------------------------
16
//
17
//####BSDCOPYRIGHTEND####
18
//==========================================================================
19
//#####DESCRIPTIONBEGIN####
20
//
21
// Author(s):    gthomas
22
// Contributors: gthomas
23
// Date:         2000-01-10
24
// Purpose:      
25
// Description:  
26
//              
27
//
28
//####DESCRIPTIONEND####
29
//
30
//==========================================================================
31
 
32
 
33
/*      $OpenBSD: if.c,v 1.25 1999/12/08 06:50:17 itojun Exp $  */
34
/*      $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $  */
35
 
36
/*
37
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
38
 * All rights reserved.
39
 *
40
 * Redistribution and use in source and binary forms, with or without
41
 * modification, are permitted provided that the following conditions
42
 * are met:
43
 * 1. Redistributions of source code must retain the above copyright
44
 *    notice, this list of conditions and the following disclaimer.
45
 * 2. Redistributions in binary form must reproduce the above copyright
46
 *    notice, this list of conditions and the following disclaimer in the
47
 *    documentation and/or other materials provided with the distribution.
48
 * 3. Neither the name of the project nor the names of its contributors
49
 *    may be used to endorse or promote products derived from this software
50
 *    without specific prior written permission.
51
 *
52
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
53
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
56
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62
 * SUCH DAMAGE.
63
 */
64
 
65
/*
66
 * Copyright (c) 1980, 1986, 1993
67
 *      The Regents of the University of California.  All rights reserved.
68
 *
69
 * Redistribution and use in source and binary forms, with or without
70
 * modification, are permitted provided that the following conditions
71
 * are met:
72
 * 1. Redistributions of source code must retain the above copyright
73
 *    notice, this list of conditions and the following disclaimer.
74
 * 2. Redistributions in binary form must reproduce the above copyright
75
 *    notice, this list of conditions and the following disclaimer in the
76
 *    documentation and/or other materials provided with the distribution.
77
 * 3. All advertising materials mentioning features or use of this software
78
 *    must display the following acknowledgement:
79
 *      This product includes software developed by the University of
80
 *      California, Berkeley and its contributors.
81
 * 4. Neither the name of the University nor the names of its contributors
82
 *    may be used to endorse or promote products derived from this software
83
 *    without specific prior written permission.
84
 *
85
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
86
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
88
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
89
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
90
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
91
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
92
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
93
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
94
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
95
 * SUCH DAMAGE.
96
 *
97
 *      @(#)if.c        8.3 (Berkeley) 1/4/94
98
 */
99
 
100
#ifdef __ECOS
101
#include <pkgconf/net.h>
102
#else
103
#include "bpfilter.h"
104
#include "bridge.h"
105
#endif
106
 
107
#include <sys/param.h>
108
#include <sys/mbuf.h>
109
#ifndef __ECOS
110
#include <sys/systm.h>
111
#include <sys/proc.h>
112
#endif
113
#include <sys/socket.h>
114
#include <sys/socketvar.h>
115
#include <sys/protosw.h>
116
#include <sys/kernel.h>
117
#include <sys/ioctl.h>
118
 
119
#include <net/if.h>
120
#include <net/if_dl.h>
121
#include <net/if_types.h>
122
#include <net/radix.h>
123
 
124
#include <net/route.h>
125
 
126
#ifdef INET
127
#include <netinet/in.h>
128
#include <netinet/in_var.h>
129
#include <netinet/if_ether.h>
130
#include <netinet/igmp.h>
131
#ifdef MROUTING
132
#include <netinet/ip_mroute.h>
133
#endif
134
#endif
135
 
136
#ifdef INET6
137
#ifndef INET
138
#include <netinet/in.h>
139
#endif
140
#endif
141
 
142
#ifdef IPFILTER
143
#include <netinet/ip_fil_compat.h>
144
#include <netinet/ip_fil.h>
145
#include <netinet/ip_nat.h>
146
#endif
147
 
148
#if NBPFILTER > 0
149
#include <net/bpf.h>
150
#endif
151
 
152
#if NBRIDGE > 0
153
#include <net/if_bridge.h>
154
#endif
155
 
156
void    if_attachsetup __P((struct ifnet *));
157
int     if_detach_rtdelete __P((struct radix_node *, void *));
158
 
159
int     ifqmaxlen = IFQ_MAXLEN;
160
void    if_slowtimo __P((void *arg));
161
 
162
#ifdef INET6
163
/*
164
 * XXX: declare here to avoid to include many inet6 related files..
165
 * should be more generalized?
166
 */
167
extern void nd6_setmtu __P((struct ifnet *));
168
#endif 
169
 
170
/*
171
 * Network interface utility routines.
172
 *
173
 * Routines with ifa_ifwith* names take sockaddr *'s as
174
 * parameters.
175
 */
176
void
177
ifinit()
178
{
179
        register struct ifnet *ifp;
180
 
181
        for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
182
                if (ifp->if_snd.ifq_maxlen == 0)
183
                        ifp->if_snd.ifq_maxlen = ifqmaxlen;
184
        if_slowtimo(NULL);
185
}
186
 
187
int if_index = 0;
188
struct ifaddr **ifnet_addrs = NULL;
189
struct ifnet **ifindex2ifnet = NULL;
190
 
191
/*
192
 * Attach an interface to the
193
 * list of "active" interfaces.
194
 */
195
void
196
if_attachsetup(ifp)
197
        struct ifnet *ifp;
198
{
199
        unsigned int socksize, ifasize;
200
        int namelen, masklen;
201
        register struct sockaddr_dl *sdl;
202
        register struct ifaddr *ifa;
203
        static int if_indexlim = 8;
204
 
205
        ifp->if_index = ++if_index;
206
 
207
        /*
208
         * We have some arrays that should be indexed by if_index.
209
         * since if_index will grow dynamically, they should grow too.
210
         *      struct ifadd **ifnet_addrs
211
         *      struct ifnet **ifindex2ifnet
212
         */
213
        if (ifnet_addrs == 0 || ifindex2ifnet == 0 || if_index >= if_indexlim) {
214
                size_t n;
215
                caddr_t q;
216
 
217
                while (if_index >= if_indexlim)
218
                        if_indexlim <<= 1;
219
 
220
                /* grow ifnet_addrs */
221
                n = if_indexlim * sizeof(ifa);
222
                q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
223
                bzero(q, n);
224
                if (ifnet_addrs) {
225
                        bcopy((caddr_t)ifnet_addrs, q, n/2);
226
                        free((caddr_t)ifnet_addrs, M_IFADDR);
227
                }
228
                ifnet_addrs = (struct ifaddr **)q;
229
 
230
                /* grow ifindex2ifnet */
231
                n = if_indexlim * sizeof(struct ifnet *);
232
                q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
233
                bzero(q, n);
234
                if (ifindex2ifnet) {
235
                        bcopy((caddr_t)ifindex2ifnet, q, n/2);
236
                        free((caddr_t)ifindex2ifnet, M_IFADDR);
237
                }
238
                ifindex2ifnet = (struct ifnet **)q;
239
        }
240
 
241
        ifindex2ifnet[if_index] = ifp;
242
 
243
        /*
244
         * create a Link Level name for this device
245
         */
246
        namelen = strlen(ifp->if_xname);
247
#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
248
        masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
249
        socksize = masklen + ifp->if_addrlen;
250
#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
251
        if (socksize < sizeof(*sdl))
252
                socksize = sizeof(*sdl);
253
        socksize = ROUNDUP(socksize);
254
        ifasize = sizeof(*ifa) + 2 * socksize;
255
        ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
256
        bzero((caddr_t)ifa, ifasize);
257
        sdl = (struct sockaddr_dl *)(ifa + 1);
258
        sdl->sdl_len = socksize;
259
        sdl->sdl_family = AF_LINK;
260
        bcopy(ifp->if_xname, sdl->sdl_data, namelen);
261
        sdl->sdl_nlen = namelen;
262
        sdl->sdl_index = ifp->if_index;
263
        sdl->sdl_type = ifp->if_type;
264
        ifnet_addrs[if_index] = ifa;
265
        ifa->ifa_ifp = ifp;
266
        ifa->ifa_rtrequest = link_rtrequest;
267
        TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
268
        ifa->ifa_addr = (struct sockaddr *)sdl;
269
        sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
270
        ifa->ifa_netmask = (struct sockaddr *)sdl;
271
        sdl->sdl_len = masklen;
272
        while (namelen != 0)
273
                sdl->sdl_data[--namelen] = 0xff;
274
}
275
 
276
void
277
if_attachhead(ifp)
278
        struct ifnet *ifp;
279
{
280
        if (if_index == 0)
281
                TAILQ_INIT(&ifnet);
282
        TAILQ_INIT(&ifp->if_addrlist);
283
        TAILQ_INSERT_HEAD(&ifnet, ifp, if_list);
284
        if_attachsetup(ifp);
285
}
286
 
287
void
288
if_attach(ifp)
289
        struct ifnet *ifp;
290
{
291
// Initialize queue - moved here to support "late" attaches
292
    if (ifp->if_snd.ifq_maxlen == 0)
293
        ifp->if_snd.ifq_maxlen = ifqmaxlen;
294
//
295
        if (if_index == 0)
296
                TAILQ_INIT(&ifnet);
297
        TAILQ_INIT(&ifp->if_addrlist);
298
        TAILQ_INSERT_TAIL(&ifnet, ifp, if_list);
299
        if_attachsetup(ifp);
300
}
301
 
302
/*
303
 * Delete a route if it has a specific interface for output.
304
 * This function complies to the rn_walktree callback API.
305
 */
306
int
307
if_detach_rtdelete(rn, vifp)
308
        struct radix_node *rn;
309
        void *vifp;
310
{
311
        struct ifnet *ifp = vifp;
312
        struct rtentry *rt = (struct rtentry *)rn;
313
 
314
        if (rt->rt_ifp == ifp)
315
                rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt),
316
                    0, NULL);
317
 
318
        /*
319
         * XXX There should be no need to check for rt_ifa belonging to this
320
         * interface, because then rt_ifp is set, right?
321
         */
322
 
323
        return (0);
324
}
325
 
326
/*
327
 * Detach an interface from everything in the kernel.  Also deallocate
328
 * private resources.
329
 * XXX So far only the INET protocol family has been looked over
330
 * wrt resource usage that needs to be decoupled.
331
 */
332
void
333
if_detach(ifp)
334
        struct ifnet *ifp;
335
{
336
        struct ifaddr *ifa;
337
        int i, s = splimp();
338
        struct radix_node_head *rnh;
339
 
340
#if NBRIDGE > 0
341
        /* Remove the interface from any bridge it is part of.  */
342
        if (ifp->if_bridge)
343
                bridge_ifdetach(ifp);
344
#endif
345
 
346
#if NBPFILTER > 0
347
        /* If there is a bpf device attached, detach from it.  */
348
        if (ifp->if_bpf)
349
                bpfdetach(ifp);
350
#endif
351
 
352
        /*
353
         * Find and remove all routes which is using this interface.
354
         * XXX Factor out into a route.c function?
355
         */
356
        for (i = 1; i <= AF_MAX; i++) {
357
                rnh = rt_tables[i];
358
                if (rnh)
359
                        (*rnh->rnh_walktree)(rnh, if_detach_rtdelete, ifp);
360
        }
361
 
362
#ifdef INET
363
        rti_delete(ifp);
364
        myip_ifp = NULL;
365
#ifdef MROUTING
366
        vif_delete(ifp);
367
#endif
368
#endif
369
        /*
370
         * XXX transient ifp refs?  inpcb.ip_moptions.imo_multicast_ifp?
371
         * Other network stacks than INET?
372
         */
373
 
374
        /* Remove the interface from the list of all interfaces.  */
375
        TAILQ_REMOVE(&ifnet, ifp, if_list);
376
 
377
#ifdef IPFILTER
378
        /* XXX More ipf & ipnat cleanup needed.  */
379
        nat_ifdetach(ifp);
380
#endif
381
 
382
        /* Deallocate private resources.  */
383
        for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa;
384
            ifa = TAILQ_FIRST(&ifp->if_addrlist)) {
385
                TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
386
#ifdef INET
387
                if (ifa->ifa_addr->sa_family == AF_INET)
388
                        TAILQ_REMOVE(&in_ifaddr, (struct in_ifaddr *)ifa,
389
                            ia_list);
390
#endif
391
                free(ifa, M_IFADDR);
392
        }
393
        splx(s);
394
}
395
 
396
/*
397
 * Locate an interface based on a complete address.
398
 */
399
/*ARGSUSED*/
400
struct ifaddr *
401
ifa_ifwithaddr(addr)
402
        register struct sockaddr *addr;
403
{
404
        register struct ifnet *ifp;
405
        register struct ifaddr *ifa;
406
 
407
#define equal(a1, a2) \
408
  (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
409
        for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
410
            for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
411
                if (ifa->ifa_addr->sa_family != addr->sa_family)
412
                        continue;
413
                if (ifa->ifa_dstaddr == NULL)
414
                        continue;
415
                if (equal(addr, ifa->ifa_addr))
416
                        return (ifa);
417
                if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
418
                    /* IP6 doesn't have broadcast */
419
                    ifa->ifa_broadaddr->sa_len != 0 &&
420
                    equal(ifa->ifa_broadaddr, addr))
421
                        return (ifa);
422
        }
423
        return (NULL);
424
}
425
/*
426
 * Locate the point to point interface with a given destination address.
427
 */
428
/*ARGSUSED*/
429
struct ifaddr *
430
ifa_ifwithdstaddr(addr)
431
        register struct sockaddr *addr;
432
{
433
        register struct ifnet *ifp;
434
        register struct ifaddr *ifa;
435
 
436
        for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
437
            if (ifp->if_flags & IFF_POINTOPOINT)
438
                for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
439
                        if (ifa->ifa_addr->sa_family != addr->sa_family ||
440
                            ifa->ifa_dstaddr == NULL)
441
                                continue;
442
                        if (equal(addr, ifa->ifa_dstaddr))
443
                                return (ifa);
444
        }
445
        return (NULL);
446
}
447
 
448
/*
449
 * Find an interface on a specific network.  If many, choice
450
 * is most specific found.
451
 */
452
struct ifaddr *
453
ifa_ifwithnet(addr)
454
        struct sockaddr *addr;
455
{
456
        register struct ifnet *ifp;
457
        register struct ifaddr *ifa;
458
        struct ifaddr *ifa_maybe = 0;
459
        u_int af = addr->sa_family;
460
        char *addr_data = addr->sa_data, *cplim;
461
 
462
        if (af == AF_LINK) {
463
            register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
464
            if (sdl->sdl_index && sdl->sdl_index <= if_index)
465
                return (ifnet_addrs[sdl->sdl_index]);
466
        }
467
        for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
468
                for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
469
                        register char *cp, *cp2, *cp3;
470
 
471
                        if (ifa->ifa_addr->sa_family != af ||
472
                            ifa->ifa_netmask == 0)
473
                                next: continue;
474
                        cp = addr_data;
475
                        cp2 = ifa->ifa_addr->sa_data;
476
                        cp3 = ifa->ifa_netmask->sa_data;
477
                        cplim = (char *)ifa->ifa_netmask +
478
                                ifa->ifa_netmask->sa_len;
479
                        while (cp3 < cplim)
480
                                if ((*cp++ ^ *cp2++) & *cp3++)
481
                                    /* want to continue for() loop */
482
                                        goto next;
483
                        if (ifa_maybe == 0 ||
484
                            rn_refines((caddr_t)ifa->ifa_netmask,
485
                            (caddr_t)ifa_maybe->ifa_netmask))
486
                                ifa_maybe = ifa;
487
                }
488
        return (ifa_maybe);
489
}
490
 
491
/*
492
 * Find an interface using a specific address family
493
 */
494
struct ifaddr *
495
ifa_ifwithaf(af)
496
        register int af;
497
{
498
        register struct ifnet *ifp;
499
        register struct ifaddr *ifa;
500
 
501
        for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
502
                for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next)
503
                        if (ifa->ifa_addr->sa_family == af)
504
                                return (ifa);
505
        return (NULL);
506
}
507
 
508
/*
509
 * Find an interface address specific to an interface best matching
510
 * a given address.
511
 */
512
struct ifaddr *
513
ifaof_ifpforaddr(addr, ifp)
514
        struct sockaddr *addr;
515
        register struct ifnet *ifp;
516
{
517
        register struct ifaddr *ifa;
518
        register char *cp, *cp2, *cp3;
519
        register char *cplim;
520
        struct ifaddr *ifa_maybe = 0;
521
        u_int af = addr->sa_family;
522
 
523
        if (af >= AF_MAX)
524
                return (NULL);
525
        for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
526
                if (ifa->ifa_addr->sa_family != af)
527
                        continue;
528
                ifa_maybe = ifa;
529
                if (ifa->ifa_netmask == 0) {
530
                        if (equal(addr, ifa->ifa_addr) ||
531
                            (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
532
                                return (ifa);
533
                        continue;
534
                }
535
                cp = addr->sa_data;
536
                cp2 = ifa->ifa_addr->sa_data;
537
                cp3 = ifa->ifa_netmask->sa_data;
538
                cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
539
                for (; cp3 < cplim; cp3++)
540
                        if ((*cp++ ^ *cp2++) & *cp3)
541
                                break;
542
                if (cp3 == cplim)
543
                        return (ifa);
544
        }
545
        return (ifa_maybe);
546
}
547
 
548
/*
549
 * Default action when installing a route with a Link Level gateway.
550
 * Lookup an appropriate real ifa to point to.
551
 * This should be moved to /sys/net/link.c eventually.
552
 */
553
void
554
link_rtrequest(cmd, rt, sa)
555
        int cmd;
556
        register struct rtentry *rt;
557
        struct sockaddr *sa;
558
{
559
        register struct ifaddr *ifa;
560
        struct sockaddr *dst;
561
        struct ifnet *ifp;
562
 
563
        if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
564
            ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
565
                return;
566
        if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
567
                IFAFREE(rt->rt_ifa);
568
                rt->rt_ifa = ifa;
569
                ifa->ifa_refcnt++;
570
                if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
571
                        ifa->ifa_rtrequest(cmd, rt, sa);
572
        }
573
}
574
 
575
/*
576
 * Mark an interface down and notify protocols of
577
 * the transition.
578
 * NOTE: must be called at splsoftnet or equivalent.
579
 */
580
void
581
if_down(ifp)
582
        register struct ifnet *ifp;
583
{
584
        register struct ifaddr *ifa;
585
 
586
        ifp->if_flags &= ~IFF_UP;
587
        for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next)
588
                pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
589
        if_qflush(&ifp->if_snd);
590
        rt_ifmsg(ifp);
591
}
592
 
593
/*
594
 * Mark an interface up and notify protocols of
595
 * the transition.
596
 * NOTE: must be called at splsoftnet or equivalent.
597
 */
598
void
599
if_up(ifp)
600
        register struct ifnet *ifp;
601
{
602
#ifdef notyet
603
        register struct ifaddr *ifa;
604
#endif
605
 
606
        ifp->if_flags |= IFF_UP;
607
#ifdef notyet
608
        /* this has no effect on IP, and will kill all ISO connections XXX */
609
        for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
610
             ifa = ifa->ifa_list.tqe_next)
611
                pfctlinput(PRC_IFUP, ifa->ifa_addr);
612
#endif
613
        rt_ifmsg(ifp);
614
#ifdef INET6
615
        in6_if_up(ifp);
616
#endif
617
}
618
 
619
/*
620
 * Flush an interface queue.
621
 */
622
void
623
if_qflush(ifq)
624
        register struct ifqueue *ifq;
625
{
626
        register struct mbuf *m, *n;
627
 
628
        n = ifq->ifq_head;
629
        while ((m = n) != NULL) {
630
                n = m->m_act;
631
                m_freem(m);
632
        }
633
        ifq->ifq_head = 0;
634
        ifq->ifq_tail = 0;
635
        ifq->ifq_len = 0;
636
}
637
 
638
/*
639
 * Handle interface watchdog timer routines.  Called
640
 * from softclock, we decrement timers (if set) and
641
 * call the appropriate interface routine on expiration.
642
 */
643
void
644
if_slowtimo(arg)
645
        void *arg;
646
{
647
        register struct ifnet *ifp;
648
        int s = splimp();
649
 
650
        for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) {
651
                if (ifp->if_timer == 0 || --ifp->if_timer)
652
                        continue;
653
                if (ifp->if_watchdog)
654
                        (*ifp->if_watchdog)(ifp);
655
        }
656
        splx(s);
657
        timeout(if_slowtimo, NULL, hz / IFNET_SLOWHZ);
658
}
659
 
660
/*
661
 * Map interface name to
662
 * interface structure pointer.
663
 */
664
struct ifnet *
665
ifunit(name)
666
        register char *name;
667
{
668
        register struct ifnet *ifp;
669
 
670
        for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
671
                if (strcmp(ifp->if_xname, name) == 0)
672
                        return (ifp);
673
 
674
        return (NULL);
675
}
676
 
677
 
678
/*
679
 * Map interface name in a sockaddr_dl to
680
 * interface structure pointer.
681
 */
682
struct ifnet *
683
if_withname(sa)
684
        struct sockaddr *sa;
685
{
686
        char ifname[IFNAMSIZ+1];
687
        struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
688
 
689
        if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
690
             (sdl->sdl_nlen > IFNAMSIZ) )
691
                return NULL;
692
 
693
        /*
694
         * ifunit wants a null-terminated name.  It may not be null-terminated
695
         * in the sockaddr.  We don't want to change the caller's sockaddr,
696
         * and there might not be room to put the trailing null anyway, so we
697
         * make a local copy that we know we can null terminate safely.
698
         */
699
 
700
        bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
701
        ifname[sdl->sdl_nlen] = '\0';
702
        return ifunit(ifname);
703
}
704
 
705
 
706
/*
707
 * Interface ioctls.
708
 */
709
int
710
ifioctl(so, cmd, data, p)
711
        struct socket *so;
712
        u_long cmd;
713
        caddr_t data;
714
        struct proc *p;
715
{
716
        register struct ifnet *ifp;
717
        register struct ifreq *ifr;
718
        int error = 0;
719
        short oif_flags;
720
 
721
        switch (cmd) {
722
 
723
        case SIOCGIFCONF:
724
        case OSIOCGIFCONF:
725
                return (ifconf(cmd, data));
726
        }
727
        ifr = (struct ifreq *)data;
728
        ifp = ifunit(ifr->ifr_name);
729
        if (ifp == 0)
730
                return (ENXIO);
731
        oif_flags = ifp->if_flags;
732
        switch (cmd) {
733
 
734
        case SIOCGIFFLAGS:
735
                ifr->ifr_flags = ifp->if_flags;
736
                break;
737
 
738
        case SIOCGIFMETRIC:
739
                ifr->ifr_metric = ifp->if_metric;
740
                break;
741
 
742
        case SIOCGIFDATA:
743
                error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data,
744
                    sizeof(ifp->if_data));
745
                break;
746
 
747
        case SIOCSIFFLAGS:
748
#ifndef __ECOS
749
                if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
750
                        return (error);
751
#endif
752
                if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
753
                        int s = splimp();
754
                        if_down(ifp);
755
                        splx(s);
756
                }
757
                if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
758
                        int s = splimp();
759
                        if_up(ifp);
760
                        splx(s);
761
                }
762
                ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
763
                        (ifr->ifr_flags &~ IFF_CANTCHANGE);
764
                if (ifp->if_ioctl)
765
                        (void) (*ifp->if_ioctl)(ifp, cmd, data);
766
                break;
767
 
768
        case SIOCSIFMETRIC:
769
#ifndef __ECOS
770
                if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
771
                        return (error);
772
#endif
773
                ifp->if_metric = ifr->ifr_metric;
774
                break;
775
 
776
        case SIOCADDMULTI:
777
        case SIOCDELMULTI:
778
        case SIOCSIFMEDIA:
779
#ifndef __ECOS
780
                if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
781
                        return (error);
782
#endif
783
                /* FALLTHROUGH */
784
#ifdef SIOCGIFSTATS
785
        case SIOCGIFSTATS:
786
#ifdef SIOCGIFSTATSUD
787
        case SIOCGIFSTATSUD:
788
#endif
789
#endif // SIOCGIFSTATS
790
        case SIOCGIFMEDIA:
791
                if (ifp->if_ioctl == 0)
792
                        return (EOPNOTSUPP);
793
                error = (*ifp->if_ioctl)(ifp, cmd, data);
794
                break;
795
 
796
        default:
797
                if (so->so_proto == 0)
798
                        return (EOPNOTSUPP);
799
#if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4)
800
                error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
801
                        (struct mbuf *) cmd, (struct mbuf *) data,
802
                        (struct mbuf *) ifp));
803
#else
804
            {
805
                u_long ocmd = cmd;
806
 
807
                switch (cmd) {
808
 
809
                case SIOCSIFADDR:
810
                case SIOCSIFDSTADDR:
811
                case SIOCSIFBRDADDR:
812
                case SIOCSIFNETMASK:
813
#if BYTE_ORDER != BIG_ENDIAN
814
                        if (ifr->ifr_addr.sa_family == 0 &&
815
                            ifr->ifr_addr.sa_len < 16) {
816
                                ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
817
                                ifr->ifr_addr.sa_len = 16;
818
                        }
819
#else
820
                        if (ifr->ifr_addr.sa_len == 0)
821
                                ifr->ifr_addr.sa_len = 16;
822
#endif
823
                        break;
824
 
825
                case OSIOCGIFADDR:
826
                        cmd = SIOCGIFADDR;
827
                        break;
828
 
829
                case OSIOCGIFDSTADDR:
830
                        cmd = SIOCGIFDSTADDR;
831
                        break;
832
 
833
                case OSIOCGIFBRDADDR:
834
                        cmd = SIOCGIFBRDADDR;
835
                        break;
836
 
837
                case OSIOCGIFNETMASK:
838
                        cmd = SIOCGIFNETMASK;
839
                }
840
                error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
841
                                                    (struct mbuf *) cmd,
842
                                                    (struct mbuf *) data,
843
                                                    (struct mbuf *) ifp));
844
                switch (ocmd) {
845
 
846
                case OSIOCGIFADDR:
847
                case OSIOCGIFDSTADDR:
848
                case OSIOCGIFBRDADDR:
849
                case OSIOCGIFNETMASK:
850
                        *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
851
                }
852
 
853
            }
854
#endif
855
                break;
856
        }
857
 
858
        if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
859
#ifdef INET6
860
                if ((ifp->if_flags & IFF_UP) != 0) {
861
                        int s = splimp();
862
                        in6_if_up(ifp);
863
                        splx(s);
864
                }
865
#endif
866
        }
867
        return (error);
868
}
869
 
870
/*
871
 * Return interface configuration
872
 * of system.  List may be used
873
 * in later ioctl's (above) to get
874
 * other information.
875
 */
876
/*ARGSUSED*/
877
int
878
ifconf(cmd, data)
879
        u_long cmd;
880
        caddr_t data;
881
{
882
        register struct ifconf *ifc = (struct ifconf *)data;
883
        register struct ifnet *ifp;
884
        register struct ifaddr *ifa;
885
        struct ifreq ifr, *ifrp;
886
        int space = ifc->ifc_len, error = 0;
887
 
888
        /* If ifc->ifc_len is 0, fill it in with the needed size and return. */
889
        if (space == 0) {
890
                for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
891
                        register struct sockaddr *sa;
892
 
893
                        if ((ifa = ifp->if_addrlist.tqh_first) == 0)
894
                                space += sizeof (ifr);
895
                        else
896
                                for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
897
                                        sa = ifa->ifa_addr;
898
#if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
899
                                        if (cmd != OSIOCGIFCONF)
900
#endif
901
                                        if (sa->sa_len > sizeof(*sa))
902
                                                space += sa->sa_len -
903
                                                    sizeof (*sa);
904
                                        space += sizeof (ifr);
905
                                }
906
                }
907
                ifc->ifc_len = space;
908
                return(0);
909
        }
910
 
911
        ifrp = ifc->ifc_req;
912
        for (ifp = ifnet.tqh_first; space >= sizeof (ifr) && ifp != 0;
913
            ifp = ifp->if_list.tqe_next) {
914
                bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ);
915
                if ((ifa = ifp->if_addrlist.tqh_first) == 0) {
916
                        bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
917
                        error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
918
                            sizeof(ifr));
919
                        if (error)
920
                                break;
921
                        space -= sizeof (ifr), ifrp++;
922
                } else
923
                        for (; space >= sizeof (ifr) && ifa != 0;
924
                            ifa = ifa->ifa_list.tqe_next) {
925
                                register struct sockaddr *sa = ifa->ifa_addr;
926
#if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4)
927
                                if (cmd == OSIOCGIFCONF) {
928
                                        struct osockaddr *osa =
929
                                            (struct osockaddr *)&ifr.ifr_addr;
930
                                        ifr.ifr_addr = *sa;
931
                                        osa->sa_family = sa->sa_family;
932
                                        error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
933
                                            sizeof (ifr));
934
                                        ifrp++;
935
                                } else
936
#endif
937
                                if (sa->sa_len <= sizeof(*sa)) {
938
                                        ifr.ifr_addr = *sa;
939
                                        error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
940
                                            sizeof (ifr));
941
                                        ifrp++;
942
                                } else {
943
                                        space -= sa->sa_len - sizeof(*sa);
944
                                        if (space < sizeof (ifr))
945
                                                break;
946
                                        error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
947
                                            sizeof (ifr.ifr_name));
948
                                        if (error == 0)
949
                                                error = copyout((caddr_t)sa,
950
                                                    (caddr_t)&ifrp->ifr_addr,
951
                                                    sa->sa_len);
952
                                        ifrp = (struct ifreq *)(sa->sa_len +
953
                                            (caddr_t)&ifrp->ifr_addr);
954
                                }
955
                                if (error)
956
                                        break;
957
                                space -= sizeof (ifr);
958
                        }
959
        }
960
        ifc->ifc_len -= space;
961
        return (error);
962
}

powered by: WebSVN 2.1.0

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