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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [libnetworking/] [net/] [if.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1026 ivang
/*
2
 * Copyright (c) 1980, 1986, 1993
3
 *      The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. All advertising materials mentioning features or use of this software
14
 *    must display the following acknowledgement:
15
 *      This product includes software developed by the University of
16
 *      California, Berkeley and its contributors.
17
 * 4. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 *
33
 *      @(#)if.c        8.3 (Berkeley) 1/4/94
34
 * if.c,v 1.3 2002/01/31 21:40:46 joel Exp
35
 */
36
 
37
#include <sys/param.h>
38
#include <sys/queue.h>
39
#include <sys/mbuf.h>
40
#include <sys/systm.h>
41
#include <sys/proc.h>
42
#include <sys/socket.h>
43
#include <sys/socketvar.h>
44
#include <sys/protosw.h>
45
#include <sys/kernel.h>
46
#include <sys/ioctl.h>
47
#include <sys/errno.h>
48
#include <sys/syslog.h>
49
#include <sys/sysctl.h>
50
 
51
#include <net/if.h>
52
#include <net/if_dl.h>
53
#include <net/if_types.h>
54
#include <net/radix.h>
55
 
56
/*
57
 * System initialization
58
 */
59
 
60
static int ifconf __P((int, caddr_t));
61
       void ifinit __P((void *));
62
static void if_qflush __P((struct ifqueue *));
63
static void if_slowtimo __P((void *));
64
static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
65
 
66
SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL)
67
 
68
 
69
int     ifqmaxlen = IFQ_MAXLEN;
70
struct  ifnet *ifnet;
71
 
72
/*
73
 * Network interface utility routines.
74
 *
75
 * Routines with ifa_ifwith* names take sockaddr *'s as
76
 * parameters.
77
 *
78
 * This routine assumes that it will be called at splimp() or higher.
79
 */
80
/* ARGSUSED*/
81
void
82
ifinit(dummy)
83
        void *dummy;
84
{
85
        register struct ifnet *ifp;
86
 
87
        for (ifp = ifnet; ifp; ifp = ifp->if_next)
88
                if (ifp->if_snd.ifq_maxlen == 0)
89
                        ifp->if_snd.ifq_maxlen = ifqmaxlen;
90
        if_slowtimo(0);
91
}
92
 
93
int if_index = 0;
94
struct ifaddr **ifnet_addrs;
95
 
96
 
97
/*
98
 * Attach an interface to the
99
 * list of "active" interfaces.
100
 */
101
void
102
if_attach(ifp)
103
        struct ifnet *ifp;
104
{
105
        unsigned socksize, ifasize;
106
        int namelen, masklen;
107
        char workbuf[64];
108
        register struct ifnet **p = &ifnet;
109
        register struct sockaddr_dl *sdl;
110
        register struct ifaddr *ifa;
111
        static int if_indexlim = 8;
112
 
113
 
114
        while (*p)
115
                p = &((*p)->if_next);
116
        *p = ifp;
117
        ifp->if_index = ++if_index;
118
        microtime(&ifp->if_lastchange);
119
        if (ifnet_addrs == 0 || if_index >= if_indexlim) {
120
                unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
121
                struct ifaddr **q = (struct ifaddr **)
122
                                        malloc(n, M_IFADDR, M_WAITOK);
123
                bzero((caddr_t)q, n);
124
                if (ifnet_addrs) {
125
                        bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
126
                        free((caddr_t)ifnet_addrs, M_IFADDR);
127
                }
128
                ifnet_addrs = q;
129
        }
130
        /*
131
         * create a Link Level name for this device
132
         */
133
        namelen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit);
134
#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
135
        masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
136
        socksize = masklen + ifp->if_addrlen;
137
#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
138
        socksize = ROUNDUP(socksize);
139
        if (socksize < sizeof(*sdl))
140
                socksize = sizeof(*sdl);
141
        ifasize = sizeof(*ifa) + 2 * socksize;
142
        ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
143
        if (ifa) {
144
                bzero((caddr_t)ifa, ifasize);
145
                sdl = (struct sockaddr_dl *)(ifa + 1);
146
                sdl->sdl_len = socksize;
147
                sdl->sdl_family = AF_LINK;
148
                bcopy(workbuf, sdl->sdl_data, namelen);
149
                sdl->sdl_nlen = namelen;
150
                sdl->sdl_index = ifp->if_index;
151
                sdl->sdl_type = ifp->if_type;
152
                ifnet_addrs[if_index - 1] = ifa;
153
                ifa->ifa_ifp = ifp;
154
                ifa->ifa_next = ifp->if_addrlist;
155
                ifa->ifa_rtrequest = link_rtrequest;
156
                ifp->if_addrlist = ifa;
157
                ifa->ifa_addr = (struct sockaddr *)sdl;
158
 
159
                sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
160
                ifa->ifa_netmask = (struct sockaddr *)sdl;
161
                sdl->sdl_len = masklen;
162
                while (namelen != 0)
163
                        sdl->sdl_data[--namelen] = 0xff;
164
        }
165
}
166
/*
167
 * Locate an interface based on a complete address.
168
 */
169
/*ARGSUSED*/
170
struct ifaddr *
171
ifa_ifwithaddr(addr)
172
        register struct sockaddr *addr;
173
{
174
        register struct ifnet *ifp;
175
        register struct ifaddr *ifa;
176
 
177
#define equal(a1, a2) \
178
  (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
179
        for (ifp = ifnet; ifp; ifp = ifp->if_next)
180
            for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
181
                if (ifa->ifa_addr->sa_family != addr->sa_family)
182
                        continue;
183
                if (equal(addr, ifa->ifa_addr))
184
                        return (ifa);
185
                if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
186
                    equal(ifa->ifa_broadaddr, addr))
187
                        return (ifa);
188
        }
189
        return ((struct ifaddr *)0);
190
}
191
/*
192
 * Locate the point to point interface with a given destination address.
193
 */
194
/*ARGSUSED*/
195
struct ifaddr *
196
ifa_ifwithdstaddr(addr)
197
        register struct sockaddr *addr;
198
{
199
        register struct ifnet *ifp;
200
        register struct ifaddr *ifa;
201
 
202
        for (ifp = ifnet; ifp; ifp = ifp->if_next)
203
            if (ifp->if_flags & IFF_POINTOPOINT)
204
                for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
205
                        if (ifa->ifa_addr->sa_family != addr->sa_family)
206
                                continue;
207
                        if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))
208
                                return (ifa);
209
        }
210
        return ((struct ifaddr *)0);
211
}
212
 
213
/*
214
 * Find an interface on a specific network.  If many, choice
215
 * is most specific found.
216
 */
217
struct ifaddr *
218
ifa_ifwithnet(addr)
219
        struct sockaddr *addr;
220
{
221
        register struct ifnet *ifp;
222
        register struct ifaddr *ifa;
223
        struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
224
        u_int af = addr->sa_family;
225
        char *addr_data = addr->sa_data, *cplim;
226
 
227
        if (af == AF_LINK) {
228
            register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
229
            if (sdl->sdl_index && sdl->sdl_index <= if_index)
230
                return (ifnet_addrs[sdl->sdl_index - 1]);
231
        }
232
        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
233
                for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
234
                        register char *cp, *cp2, *cp3;
235
 
236
                        if (ifa->ifa_addr->sa_family != af)
237
                                next: continue;
238
                        if (ifp->if_flags & IFF_POINTOPOINT) {
239
                                if (ifa->ifa_dstaddr != 0
240
                                    && equal(addr, ifa->ifa_dstaddr))
241
                                        return (ifa);
242
                        } else {
243
                                /*
244
                                 * if we have a special address handler,
245
                                 * then use it instead of the generic one.
246
                                 */
247
                                if (ifa->ifa_claim_addr) {
248
                                        if ((*ifa->ifa_claim_addr)(ifa, addr)) {
249
                                                return (ifa);
250
                                        } else {
251
                                                continue;
252
                                        }
253
                                }
254
 
255
                                /*
256
                                 * Scan all the bits in the ifa's address.
257
                                 * If a bit dissagrees with what we are
258
                                 * looking for, mask it with the netmask
259
                                 * to see if it really matters.
260
                                 * (A byte at a time)
261
                                 */
262
                                if (ifa->ifa_netmask == 0)
263
                                        continue;
264
                                cp = addr_data;
265
                                cp2 = ifa->ifa_addr->sa_data;
266
                                cp3 = ifa->ifa_netmask->sa_data;
267
                                cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
268
                                while (cp3 < cplim)
269
                                        if ((*cp++ ^ *cp2++) & *cp3++)
270
                                                goto next;
271
                                if (ifa_maybe == 0 ||
272
                                    rn_refines((caddr_t)ifa->ifa_netmask,
273
                                    (caddr_t)ifa_maybe->ifa_netmask))
274
                                        ifa_maybe = ifa;
275
                        }
276
                }
277
        }
278
        return (ifa_maybe);
279
}
280
 
281
/*
282
 * Find an interface address specific to an interface best matching
283
 * a given address.
284
 */
285
struct ifaddr *
286
ifaof_ifpforaddr(addr, ifp)
287
        struct sockaddr *addr;
288
        register struct ifnet *ifp;
289
{
290
        register struct ifaddr *ifa;
291
        register char *cp, *cp2, *cp3;
292
        register char *cplim;
293
        struct ifaddr *ifa_maybe = 0;
294
        u_int af = addr->sa_family;
295
 
296
        if (af >= AF_MAX)
297
                return (0);
298
        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
299
                if (ifa->ifa_addr->sa_family != af)
300
                        continue;
301
                if (ifa_maybe == 0)
302
                        ifa_maybe = ifa;
303
                if (ifa->ifa_netmask == 0) {
304
                        if (equal(addr, ifa->ifa_addr) ||
305
                            (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
306
                                return (ifa);
307
                        continue;
308
                }
309
                if (ifp->if_flags & IFF_POINTOPOINT) {
310
                        if (equal(addr, ifa->ifa_dstaddr))
311
                                return (ifa);
312
                } else {
313
                        cp = addr->sa_data;
314
                        cp2 = ifa->ifa_addr->sa_data;
315
                        cp3 = ifa->ifa_netmask->sa_data;
316
                        cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
317
                        for (; cp3 < cplim; cp3++)
318
                                if ((*cp++ ^ *cp2++) & *cp3)
319
                                        break;
320
                        if (cp3 == cplim)
321
                                return (ifa);
322
                }
323
        }
324
        return (ifa_maybe);
325
}
326
 
327
#include <net/route.h>
328
 
329
/*
330
 * Default action when installing a route with a Link Level gateway.
331
 * Lookup an appropriate real ifa to point to.
332
 * This should be moved to /sys/net/link.c eventually.
333
 */
334
static void
335
link_rtrequest(cmd, rt, sa)
336
        int cmd;
337
        register struct rtentry *rt;
338
        struct sockaddr *sa;
339
{
340
        register struct ifaddr *ifa;
341
        struct sockaddr *dst;
342
        struct ifnet *ifp;
343
 
344
        if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
345
            ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
346
                return;
347
        ifa = ifaof_ifpforaddr(dst, ifp);
348
        if (ifa) {
349
                IFAFREE(rt->rt_ifa);
350
                rt->rt_ifa = ifa;
351
                ifa->ifa_refcnt++;
352
                if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
353
                        ifa->ifa_rtrequest(cmd, rt, sa);
354
        }
355
}
356
 
357
/*
358
 * Mark an interface down and notify protocols of
359
 * the transition.
360
 * NOTE: must be called at splnet or eqivalent.
361
 */
362
void
363
if_down(ifp)
364
        register struct ifnet *ifp;
365
{
366
        register struct ifaddr *ifa;
367
 
368
        ifp->if_flags &= ~IFF_UP;
369
        microtime(&ifp->if_lastchange);
370
        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
371
                pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
372
        if_qflush(&ifp->if_snd);
373
        rt_ifmsg(ifp);
374
}
375
 
376
/*
377
 * Mark an interface up and notify protocols of
378
 * the transition.
379
 * NOTE: must be called at splnet or eqivalent.
380
 */
381
void
382
if_up(ifp)
383
        register struct ifnet *ifp;
384
{
385
 
386
        ifp->if_flags |= IFF_UP;
387
        microtime(&ifp->if_lastchange);
388
#ifdef notyet
389
        register struct ifaddr *ifa;
390
        /* this has no effect on IP, and will kill all iso connections XXX */
391
        for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
392
                pfctlinput(PRC_IFUP, ifa->ifa_addr);
393
#endif
394
        rt_ifmsg(ifp);
395
}
396
 
397
/*
398
 * Flush an interface queue.
399
 */
400
static void
401
if_qflush(ifq)
402
        register struct ifqueue *ifq;
403
{
404
        register struct mbuf *m, *n;
405
 
406
        n = ifq->ifq_head;
407
        while ((m = n) != 0) {
408
                n = m->m_act;
409
                m_freem(m);
410
        }
411
        ifq->ifq_head = 0;
412
        ifq->ifq_tail = 0;
413
        ifq->ifq_len = 0;
414
}
415
 
416
/*
417
 * Handle interface watchdog timer routines.  Called
418
 * from softclock, we decrement timers (if set) and
419
 * call the appropriate interface routine on expiration.
420
 */
421
static void
422
if_slowtimo(arg)
423
        void *arg;
424
{
425
        register struct ifnet *ifp;
426
        int s = splimp();
427
 
428
        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
429
                if (ifp->if_timer == 0 || --ifp->if_timer)
430
                        continue;
431
                if (ifp->if_watchdog)
432
                        (*ifp->if_watchdog)(ifp);
433
        }
434
        splx(s);
435
        timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
436
}
437
 
438
/*
439
 * Map interface name to
440
 * interface structure pointer.
441
 */
442
struct ifnet *
443
ifunit(name)
444
        register char *name;
445
{
446
        register char *cp;
447
        register struct ifnet *ifp;
448
        int unit;
449
        unsigned len;
450
        char *ep, c;
451
 
452
        for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
453
                if (*cp >= '0' && *cp <= '9')
454
                        break;
455
        if (*cp == '\0' || cp == name + IFNAMSIZ)
456
                return ((struct ifnet *)0);
457
        /*
458
         * Save first char of unit, and pointer to it,
459
         * so we can put a null there to avoid matching
460
         * initial substrings of interface names.
461
         */
462
        len = cp - name + 1;
463
        c = *cp;
464
        ep = cp;
465
        for (unit = 0; *cp >= '0' && *cp <= '9'; )
466
                unit = unit * 10 + *cp++ - '0';
467
        if (*cp != '\0')
468
                return 0;        /* no trailing garbage allowed */
469
        *ep = 0;
470
        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
471
                if (bcmp(ifp->if_name, name, len))
472
                        continue;
473
                if (unit == ifp->if_unit)
474
                        break;
475
        }
476
        *ep = c;
477
        return (ifp);
478
}
479
 
480
/*
481
 * Interface ioctls.
482
 */
483
int
484
ifioctl(so, cmd, data, p)
485
        struct socket *so;
486
        int cmd;
487
        caddr_t data;
488
        struct proc *p;
489
{
490
        register struct ifnet *ifp;
491
        register struct ifreq *ifr;
492
        int error;
493
 
494
        switch (cmd) {
495
 
496
        case SIOCGIFCONF:
497
        case OSIOCGIFCONF:
498
                return (ifconf(cmd, data));
499
        }
500
        ifr = (struct ifreq *)data;
501
        ifp = ifunit(ifr->ifr_name);
502
        if (ifp == 0)
503
                return (ENXIO);
504
        switch (cmd) {
505
 
506
        case SIOCGIFFLAGS:
507
                ifr->ifr_flags = ifp->if_flags;
508
                break;
509
 
510
        case SIOCGIFMETRIC:
511
                ifr->ifr_metric = ifp->if_metric;
512
                break;
513
 
514
        case SIOCGIFMTU:
515
                ifr->ifr_mtu = ifp->if_mtu;
516
                break;
517
 
518
        case SIOCGIFPHYS:
519
                ifr->ifr_phys = ifp->if_physical;
520
                break;
521
 
522
        case SIOCSIFFLAGS:
523
                error = suser(p->p_ucred, &p->p_acflag);
524
                if (error)
525
                        return (error);
526
                if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
527
                        int s = splimp();
528
                        if_down(ifp);
529
                        splx(s);
530
                }
531
                if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
532
                        int s = splimp();
533
                        if_up(ifp);
534
                        splx(s);
535
                }
536
                ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
537
                        (ifr->ifr_flags &~ IFF_CANTCHANGE);
538
                if (ifp->if_ioctl)
539
                        (void) (*ifp->if_ioctl)(ifp, cmd, data);
540
                microtime(&ifp->if_lastchange);
541
                break;
542
 
543
        case SIOCSIFMETRIC:
544
                error = suser(p->p_ucred, &p->p_acflag);
545
                if (error)
546
                        return (error);
547
                ifp->if_metric = ifr->ifr_metric;
548
                microtime(&ifp->if_lastchange);
549
                break;
550
 
551
        case SIOCSIFPHYS:
552
                error = suser(p->p_ucred, &p->p_acflag);
553
                if (error)
554
                        return error;
555
                if (!ifp->if_ioctl)
556
                        return EOPNOTSUPP;
557
                error = (*ifp->if_ioctl)(ifp, cmd, data);
558
                if (error == 0)
559
                        microtime(&ifp->if_lastchange);
560
                return(error);
561
 
562
        case SIOCSIFMTU:
563
                error = suser(p->p_ucred, &p->p_acflag);
564
                if (error)
565
                        return (error);
566
                if (ifp->if_ioctl == NULL)
567
                        return (EOPNOTSUPP);
568
                /*
569
                 * 72 was chosen below because it is the size of a TCP/IP
570
                 * header (40) + the minimum mss (32).
571
                 */
572
                if (ifr->ifr_mtu < 72 || ifr->ifr_mtu > 65535)
573
                        return (EINVAL);
574
                error = (*ifp->if_ioctl)(ifp, cmd, data);
575
                if (error == 0)
576
                        microtime(&ifp->if_lastchange);
577
                return(error);
578
 
579
        case SIOCADDMULTI:
580
        case SIOCDELMULTI:
581
                error = suser(p->p_ucred, &p->p_acflag);
582
                if (error)
583
                        return (error);
584
                if (ifp->if_ioctl == NULL)
585
                        return (EOPNOTSUPP);
586
                error = (*ifp->if_ioctl)(ifp, cmd, data);
587
                if (error == 0 )
588
                        microtime(&ifp->if_lastchange);
589
                return(error);
590
 
591
        case SIOCSIFMEDIA:
592
                error = suser(p->p_ucred, &p->p_acflag);
593
                if (error)
594
                        return (error);
595
                if (ifp->if_ioctl == 0)
596
                        return (EOPNOTSUPP);
597
                error = (*ifp->if_ioctl)(ifp, cmd, data);
598
                if (error == 0)
599
                        microtime(&ifp->if_lastchange);
600
                return error;
601
 
602
        case SIOCGIFMEDIA:
603
                if (ifp->if_ioctl == 0)
604
                        return (EOPNOTSUPP);
605
                return ((*ifp->if_ioctl)(ifp, cmd, data));
606
 
607
        default:
608
                if (so->so_proto == 0)
609
                        return (EOPNOTSUPP);
610
#ifndef COMPAT_43
611
                return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
612
                                                                 data,
613
                                                                 ifp));
614
#else
615
            {
616
                int ocmd = cmd;
617
 
618
                switch (cmd) {
619
 
620
                case SIOCSIFDSTADDR:
621
                case SIOCSIFADDR:
622
                case SIOCSIFBRDADDR:
623
                case SIOCSIFNETMASK:
624
#if BYTE_ORDER != BIG_ENDIAN
625
                        if (ifr->ifr_addr.sa_family == 0 &&
626
                            ifr->ifr_addr.sa_len < 16) {
627
                                ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
628
                                ifr->ifr_addr.sa_len = 16;
629
                        }
630
#else
631
                        if (ifr->ifr_addr.sa_len == 0)
632
                                ifr->ifr_addr.sa_len = 16;
633
#endif
634
                        break;
635
 
636
                case OSIOCGIFADDR:
637
                        cmd = SIOCGIFADDR;
638
                        break;
639
 
640
                case OSIOCGIFDSTADDR:
641
                        cmd = SIOCGIFDSTADDR;
642
                        break;
643
 
644
                case OSIOCGIFBRDADDR:
645
                        cmd = SIOCGIFBRDADDR;
646
                        break;
647
 
648
                case OSIOCGIFNETMASK:
649
                        cmd = SIOCGIFNETMASK;
650
                }
651
                error =  ((*so->so_proto->pr_usrreqs->pru_control)(so,
652
                                                                   cmd,
653
                                                                   data,
654
                                                                   ifp));
655
                switch (ocmd) {
656
 
657
                case OSIOCGIFADDR:
658
                case OSIOCGIFDSTADDR:
659
                case OSIOCGIFBRDADDR:
660
                case OSIOCGIFNETMASK:
661
                        *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
662
                }
663
                return (error);
664
 
665
            }
666
#endif
667
 
668
        /*
669
         * RTEMS additions for setting/getting `tap' function
670
         */
671
        case SIOCSIFTAP:
672
                ifp->if_tap = ifr->ifr_tap;
673
                return 0;
674
 
675
        case SIOCGIFTAP:
676
                ifr->ifr_tap = ifp->if_tap;
677
                return 0;
678
        }
679
        return (0);
680
}
681
 
682
/*
683
 * Set/clear promiscuous mode on interface ifp based on the truth value
684
 * of pswitch.  The calls are reference counted so that only the first
685
 * "on" request actually has an effect, as does the final "off" request.
686
 * Results are undefined if the "off" and "on" requests are not matched.
687
 */
688
int
689
ifpromisc(ifp, pswitch)
690
        struct ifnet *ifp;
691
        int pswitch;
692
{
693
        struct ifreq ifr;
694
 
695
        if (pswitch) {
696
                /*
697
                 * If the device is not configured up, we cannot put it in
698
                 * promiscuous mode.
699
                 */
700
                if ((ifp->if_flags & IFF_UP) == 0)
701
                        return (ENETDOWN);
702
                if (ifp->if_pcount++ != 0)
703
                        return (0);
704
                ifp->if_flags |= IFF_PROMISC;
705
                log(LOG_INFO, "%s%d: promiscuous mode enabled\n",
706
                    ifp->if_name, ifp->if_unit);
707
        } else {
708
                if (--ifp->if_pcount > 0)
709
                        return (0);
710
                ifp->if_flags &= ~IFF_PROMISC;
711
        }
712
        ifr.ifr_flags = ifp->if_flags;
713
        return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
714
}
715
 
716
/*
717
 * Return interface configuration
718
 * of system.  List may be used
719
 * in later ioctl's (above) to get
720
 * other information.
721
 */
722
/*ARGSUSED*/
723
static int
724
ifconf(cmd, data)
725
        int cmd;
726
        caddr_t data;
727
{
728
        register struct ifconf *ifc = (struct ifconf *)data;
729
        register struct ifnet *ifp = ifnet;
730
        register struct ifaddr *ifa;
731
        struct ifreq ifr, *ifrp;
732
        int space = ifc->ifc_len, error = 0;
733
 
734
        ifrp = ifc->ifc_req;
735
        for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
736
                char workbuf[64];
737
                int ifnlen;
738
 
739
                ifnlen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit);
740
                if(ifnlen + 1 > sizeof ifr.ifr_name) {
741
                        error = ENAMETOOLONG;
742
                } else {
743
                        strcpy(ifr.ifr_name, workbuf);
744
                }
745
 
746
                if ((ifa = ifp->if_addrlist) == 0) {
747
                        bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
748
                        error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
749
                            sizeof (ifr));
750
                        if (error)
751
                                break;
752
                        space -= sizeof (ifr), ifrp++;
753
                } else
754
                    for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
755
                        register struct sockaddr *sa = ifa->ifa_addr;
756
#ifdef COMPAT_43
757
                        if (cmd == OSIOCGIFCONF) {
758
                                struct osockaddr *osa =
759
                                         (struct osockaddr *)&ifr.ifr_addr;
760
                                ifr.ifr_addr = *sa;
761
                                osa->sa_family = sa->sa_family;
762
                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
763
                                                sizeof (ifr));
764
                                ifrp++;
765
                        } else
766
#endif
767
                        if (sa->sa_len <= sizeof(*sa)) {
768
                                ifr.ifr_addr = *sa;
769
                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
770
                                                sizeof (ifr));
771
                                ifrp++;
772
                        } else {
773
                                space -= sa->sa_len - sizeof(*sa);
774
                                if (space < sizeof (ifr))
775
                                        break;
776
                                error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
777
                                                sizeof (ifr.ifr_name));
778
                                if (error == 0)
779
                                    error = copyout((caddr_t)sa,
780
                                      (caddr_t)&ifrp->ifr_addr, sa->sa_len);
781
                                ifrp = (struct ifreq *)
782
                                        (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
783
                        }
784
                        if (error)
785
                                break;
786
                        space -= sizeof (ifr);
787
                }
788
        }
789
        ifc->ifc_len -= space;
790
        return (error);
791
}
792
 
793
SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
794
SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");

powered by: WebSVN 2.1.0

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