Update to use the timer0_divisor & timer0_prescale to determine the current
[unix-history] / sys / net / if.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1980, 1986 Regents of the University of California.
3 * 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 *
70c5ff60 33 * from: @(#)if.c 7.14 (Berkeley) 4/20/91
fde1aeb2 34 * $Id: if.c,v 1.6 1993/11/25 01:33:52 wollman Exp $
15637ed4
RG
35 */
36
37#include "param.h"
38#include "mbuf.h"
39#include "systm.h"
40#include "socket.h"
41#include "socketvar.h"
42#include "protosw.h"
43#include "proc.h"
44#include "kernel.h"
45#include "ioctl.h"
46
47#include "if.h"
15637ed4
RG
48#include "if_dl.h"
49#include "if_types.h"
50
51#include "ether.h"
52
53int ifqmaxlen = IFQ_MAXLEN;
8ace4366
GW
54struct ifqueue rawintrq; /* raw packet input queue */
55struct ifnet *ifnet; /* list of configured interfaces */
15637ed4 56
4c45483e
GW
57static void link_rtrequest(int, struct rtentry *, struct sockaddr *);
58static void if_qflush(struct ifqueue *);
59static void if_slowtimo(caddr_t, int);
60
15637ed4
RG
61/*
62 * Network interface utility routines.
63 *
64 * Routines with ifa_ifwith* names take sockaddr *'s as
65 * parameters.
66 */
67
4c45483e 68void
15637ed4
RG
69ifinit()
70{
71 register struct ifnet *ifp;
72
73 for (ifp = ifnet; ifp; ifp = ifp->if_next)
74 if (ifp->if_snd.ifq_maxlen == 0)
75 ifp->if_snd.ifq_maxlen = ifqmaxlen;
4c45483e 76 if_slowtimo((caddr_t)0, 0);
15637ed4
RG
77}
78
79#ifdef vax
80/*
81 * Call each interface on a Unibus reset.
82 */
83ifubareset(uban)
84 int uban;
85{
86 register struct ifnet *ifp;
87
88 for (ifp = ifnet; ifp; ifp = ifp->if_next)
89 if (ifp->if_reset)
90 (*ifp->if_reset)(ifp->if_unit, uban);
91}
92#endif
93
94int if_index = 0;
95struct ifaddr **ifnet_addrs;
96static char *sprint_d();
97
98/*
99 * Attach an interface to the
100 * list of "active" interfaces.
101 */
4c45483e 102void
15637ed4
RG
103if_attach(ifp)
104 struct ifnet *ifp;
105{
106 unsigned socksize, ifasize;
107 int namelen, unitlen;
108 char workbuf[12], *unitname;
109 register struct ifnet **p = &ifnet;
110 register struct sockaddr_dl *sdl;
111 register struct ifaddr *ifa;
112 static int if_indexlim = 8;
15637ed4
RG
113
114 while (*p)
115 p = &((*p)->if_next);
116 *p = ifp;
117 ifp->if_index = ++if_index;
118 if (ifnet_addrs == 0 || if_index >= if_indexlim) {
119 unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
120 struct ifaddr **q = (struct ifaddr **)
121 malloc(n, M_IFADDR, M_WAITOK);
122 if (ifnet_addrs) {
123 bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
124 free((caddr_t)ifnet_addrs, M_IFADDR);
125 }
126 ifnet_addrs = q;
127 }
4c45483e 128
15637ed4
RG
129 /*
130 * create a Link Level name for this device
131 */
132 unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
133 namelen = strlen(ifp->if_name);
134 unitlen = strlen(unitname);
135#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
136 socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) +
137 unitlen + namelen + ifp->if_addrlen;
138#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
139 socksize = ROUNDUP(socksize);
140 if (socksize < sizeof(*sdl))
141 socksize = sizeof(*sdl);
142 ifasize = sizeof(*ifa) + 2 * socksize;
143 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
144 if (ifa == 0)
145 return;
146 ifnet_addrs[if_index - 1] = ifa;
147 bzero((caddr_t)ifa, ifasize);
148 sdl = (struct sockaddr_dl *)(ifa + 1);
149 ifa->ifa_addr = (struct sockaddr *)sdl;
150 ifa->ifa_ifp = ifp;
151 sdl->sdl_len = socksize;
152 sdl->sdl_family = AF_LINK;
153 bcopy(ifp->if_name, sdl->sdl_data, namelen);
154 bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
155 sdl->sdl_nlen = (namelen += unitlen);
156 sdl->sdl_index = ifp->if_index;
157 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
158 ifa->ifa_netmask = (struct sockaddr *)sdl;
159 sdl->sdl_len = socksize - ifp->if_addrlen;
160 while (namelen != 0)
161 sdl->sdl_data[--namelen] = 0xff;
162 ifa->ifa_next = ifp->if_addrlist;
163 ifa->ifa_rtrequest = link_rtrequest;
164 ifp->if_addrlist = ifa;
165}
166/*
167 * Locate an interface based on a complete address.
168 */
169/*ARGSUSED*/
170struct ifaddr *
171ifa_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*/
195struct ifaddr *
196ifa_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 (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 first found.
216 */
217struct ifaddr *
218ifa_ifwithnet(addr)
219 struct sockaddr *addr;
220{
221 register struct ifnet *ifp;
222 register struct ifaddr *ifa;
223 u_int af = addr->sa_family;
224
225 if (af >= AF_MAX)
226 return (0);
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 register char *cplim;
236 if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
237 continue;
238 cp = addr->sa_data;
239 cp2 = ifa->ifa_addr->sa_data;
240 cp3 = ifa->ifa_netmask->sa_data;
241 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
242 for (; cp3 < cplim; cp3++)
243 if ((*cp++ ^ *cp2++) & *cp3)
244 break;
245 if (cp3 == cplim)
246 return (ifa);
247 }
248 return ((struct ifaddr *)0);
249}
250
251/*
252 * Find an interface using a specific address family
253 */
254struct ifaddr *
255ifa_ifwithaf(af)
256 register int af;
257{
258 register struct ifnet *ifp;
259 register struct ifaddr *ifa;
260
261 for (ifp = ifnet; ifp; ifp = ifp->if_next)
262 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
263 if (ifa->ifa_addr->sa_family == af)
264 return (ifa);
265 return ((struct ifaddr *)0);
266}
267
268/*
269 * Find an interface address specific to an interface best matching
270 * a given address.
271 */
272struct ifaddr *
273ifaof_ifpforaddr(addr, ifp)
274 struct sockaddr *addr;
275 register struct ifnet *ifp;
276{
277 register struct ifaddr *ifa;
278 register char *cp, *cp2, *cp3;
279 register char *cplim;
280 struct ifaddr *ifa_maybe = 0;
281 u_int af = addr->sa_family;
282
283 if (af >= AF_MAX)
284 return (0);
285 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
286 if (ifa->ifa_addr->sa_family != af)
287 continue;
288 ifa_maybe = ifa;
289 if (ifa->ifa_netmask == 0) {
290 if (equal(addr, ifa->ifa_addr) ||
291 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
292 return (ifa);
293 continue;
294 }
295 cp = addr->sa_data;
296 cp2 = ifa->ifa_addr->sa_data;
297 cp3 = ifa->ifa_netmask->sa_data;
298 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
299 for (; cp3 < cplim; cp3++)
300 if ((*cp++ ^ *cp2++) & *cp3)
301 break;
302 if (cp3 == cplim)
303 return (ifa);
304 }
305 return (ifa_maybe);
306}
307#include "route.h"
308/*
309 * Default action when installing a route with a Link Level gateway.
310 * Lookup an appropriate real ifa to point to.
311 * This should be moved to /sys/net/link.c eventually.
312 */
4c45483e 313void
15637ed4 314link_rtrequest(cmd, rt, sa)
4c45483e
GW
315 int cmd;
316 register struct rtentry *rt;
317 struct sockaddr *sa;
15637ed4
RG
318{
319 register struct ifaddr *ifa;
320 struct sockaddr *dst;
321 struct ifnet *ifp, *oldifnet = ifnet;
322
323 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
324 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
325 return;
326 if (ifa = ifaof_ifpforaddr(dst, ifp)) {
327 rt->rt_ifa = ifa;
328 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
329 ifa->ifa_rtrequest(cmd, rt, sa);
330 }
331}
332
333/*
334 * Mark an interface down and notify protocols of
335 * the transition.
336 * NOTE: must be called at splnet or eqivalent.
337 */
4c45483e 338void
15637ed4
RG
339if_down(ifp)
340 register struct ifnet *ifp;
341{
342 register struct ifaddr *ifa;
343
344 ifp->if_flags &= ~IFF_UP;
345 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
346 pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
347 if_qflush(&ifp->if_snd);
348}
349
350/*
351 * Flush an interface queue.
352 */
4c45483e 353static void
15637ed4
RG
354if_qflush(ifq)
355 register struct ifqueue *ifq;
356{
357 register struct mbuf *m, *n;
358
359 n = ifq->ifq_head;
360 while (m = n) {
361 n = m->m_act;
362 m_freem(m);
363 }
364 ifq->ifq_head = 0;
365 ifq->ifq_tail = 0;
366 ifq->ifq_len = 0;
367}
368
369/*
370 * Handle interface watchdog timer routines. Called
371 * from softclock, we decrement timers (if set) and
372 * call the appropriate interface routine on expiration.
373 */
4c45483e
GW
374static void
375if_slowtimo(caddr_t dummy1, int dummy2)
15637ed4
RG
376{
377 register struct ifnet *ifp;
378 int s = splimp();
379
380 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
381 if (ifp->if_timer == 0 || --ifp->if_timer)
382 continue;
383 if (ifp->if_watchdog)
384 (*ifp->if_watchdog)(ifp->if_unit);
385 }
386 splx(s);
387 timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
388}
389
390/*
391 * Map interface name to
392 * interface structure pointer.
393 */
394struct ifnet *
395ifunit(name)
396 register char *name;
397{
398 register char *cp;
399 register struct ifnet *ifp;
400 int unit;
401 unsigned len;
402 char *ep, c;
403
404 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
405 if (*cp >= '0' && *cp <= '9')
406 break;
407 if (*cp == '\0' || cp == name + IFNAMSIZ)
408 return ((struct ifnet *)0);
409 /*
410 * Save first char of unit, and pointer to it,
411 * so we can put a null there to avoid matching
412 * initial substrings of interface names.
413 */
414 len = cp - name + 1;
415 c = *cp;
416 ep = cp;
417 for (unit = 0; *cp >= '0' && *cp <= '9'; )
418 unit = unit * 10 + *cp++ - '0';
419 *ep = 0;
420 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
421 if (bcmp(ifp->if_name, name, len))
422 continue;
423 if (unit == ifp->if_unit)
424 break;
425 }
426 *ep = c;
427 return (ifp);
428}
429
430/*
431 * Interface ioctls.
432 */
4c45483e 433int
15637ed4
RG
434ifioctl(so, cmd, data, p)
435 struct socket *so;
436 int cmd;
437 caddr_t data;
438 struct proc *p;
439{
440 register struct ifnet *ifp;
441 register struct ifreq *ifr;
442 int error;
443
444 switch (cmd) {
445
446 case SIOCGIFCONF:
447 case OSIOCGIFCONF:
448 return (ifconf(cmd, data));
449
450#if defined(INET) && NETHER > 0
451 case SIOCSARP:
452 case SIOCDARP:
453 if (error = suser(p->p_ucred, &p->p_acflag))
454 return (error);
455 /* FALL THROUGH */
456 case SIOCGARP:
457 case OSIOCGARP:
458 return (arpioctl(cmd, data));
459#endif
460 }
461 ifr = (struct ifreq *)data;
462 ifp = ifunit(ifr->ifr_name);
463 if (ifp == 0)
464 return (ENXIO);
465 switch (cmd) {
466
467 case SIOCGIFFLAGS:
468 ifr->ifr_flags = ifp->if_flags;
469 break;
470
471 case SIOCGIFMETRIC:
472 ifr->ifr_metric = ifp->if_metric;
473 break;
474
475 case SIOCSIFFLAGS:
476 if (error = suser(p->p_ucred, &p->p_acflag))
477 return (error);
478 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
479 int s = splimp();
480 if_down(ifp);
481 splx(s);
482 }
483 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
484 (ifr->ifr_flags &~ IFF_CANTCHANGE);
485 if (ifp->if_ioctl)
486 (void) (*ifp->if_ioctl)(ifp, cmd, data);
487 break;
488
489 case SIOCSIFMETRIC:
490 if (error = suser(p->p_ucred, &p->p_acflag))
491 return (error);
492 ifp->if_metric = ifr->ifr_metric;
493 break;
494
8b3438a6
RG
495 case SIOCSIFMTU:
496 case SIOCGIFMTU:
497 case SIOCSIFASYNCMAP:
498 case SIOCGIFASYNCMAP:
499 if (!ifp->if_ioctl)
500 return (EOPNOTSUPP);
501 return ((*ifp->if_ioctl)(ifp, cmd, data));
502 break;
503
15637ed4
RG
504 default:
505 if (so->so_proto == 0)
506 return (EOPNOTSUPP);
507#ifndef COMPAT_43
508 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
509 cmd, data, ifp));
510#else
511 {
512 int ocmd = cmd;
513
514 switch (cmd) {
515
516 case SIOCSIFDSTADDR:
517 case SIOCSIFADDR:
518 case SIOCSIFBRDADDR:
519 case SIOCSIFNETMASK:
520#if BYTE_ORDER != BIG_ENDIAN
521 if (ifr->ifr_addr.sa_family == 0 &&
522 ifr->ifr_addr.sa_len < 16) {
523 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
524 ifr->ifr_addr.sa_len = 16;
525 }
526#else
527 if (ifr->ifr_addr.sa_len == 0)
528 ifr->ifr_addr.sa_len = 16;
529#endif
530 break;
531
532 case OSIOCGIFADDR:
533 cmd = SIOCGIFADDR;
534 break;
535
536 case OSIOCGIFDSTADDR:
537 cmd = SIOCGIFDSTADDR;
538 break;
539
540 case OSIOCGIFBRDADDR:
541 cmd = SIOCGIFBRDADDR;
542 break;
543
544 case OSIOCGIFNETMASK:
545 cmd = SIOCGIFNETMASK;
546 }
547 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
fde1aeb2
GW
548 (struct mbuf *)cmd,
549 (struct mbuf *)data,
550 (struct mbuf *)ifp,
551 (struct mbuf *)0));
15637ed4
RG
552 switch (ocmd) {
553
554 case OSIOCGIFADDR:
555 case OSIOCGIFDSTADDR:
556 case OSIOCGIFBRDADDR:
557 case OSIOCGIFNETMASK:
558 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
559 }
560 return (error);
561
562 }
563#endif
564 }
565 return (0);
566}
567
568/*
569 * Return interface configuration
570 * of system. List may be used
571 * in later ioctl's (above) to get
572 * other information.
573 */
574/*ARGSUSED*/
4c45483e 575int
15637ed4
RG
576ifconf(cmd, data)
577 int cmd;
578 caddr_t data;
579{
580 register struct ifconf *ifc = (struct ifconf *)data;
581 register struct ifnet *ifp = ifnet;
582 register struct ifaddr *ifa;
583 register char *cp, *ep;
584 struct ifreq ifr, *ifrp;
585 int space = ifc->ifc_len, error = 0;
586
587 ifrp = ifc->ifc_req;
588 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
589 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
590 bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
591 for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
592 ;
593 *cp++ = '0' + ifp->if_unit; *cp = '\0';
594 if ((ifa = ifp->if_addrlist) == 0) {
595 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
596 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
597 if (error)
598 break;
599 space -= sizeof (ifr), ifrp++;
600 } else
601 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
602 register struct sockaddr *sa = ifa->ifa_addr;
603#ifdef COMPAT_43
604 if (cmd == OSIOCGIFCONF) {
605 struct osockaddr *osa =
606 (struct osockaddr *)&ifr.ifr_addr;
607 ifr.ifr_addr = *sa;
608 osa->sa_family = sa->sa_family;
609 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
610 sizeof (ifr));
611 ifrp++;
612 } else
613#endif
614 if (sa->sa_len <= sizeof(*sa)) {
615 ifr.ifr_addr = *sa;
616 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
617 sizeof (ifr));
618 ifrp++;
619 } else {
620 space -= sa->sa_len - sizeof(*sa);
621 if (space < sizeof (ifr))
622 break;
623 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
624 sizeof (ifr.ifr_name));
625 if (error == 0)
626 error = copyout((caddr_t)sa,
627 (caddr_t)&ifrp->ifr_addr, sa->sa_len);
628 ifrp = (struct ifreq *)
629 (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
630 }
631 if (error)
632 break;
633 space -= sizeof (ifr);
634 }
635 }
636 ifc->ifc_len -= space;
637 return (error);
638}
639
640static char *
641sprint_d(n, buf, buflen)
642 u_int n;
643 char *buf;
644 int buflen;
645{
646 register char *cp = buf + buflen - 1;
647
648 *cp = 0;
649 do {
650 cp--;
651 *cp = "0123456789"[n % 10];
652 n /= 10;
653 } while (n != 0);
654 return (cp);
655}
fde1aeb2
GW
656
657/*
658 * Set/clear promiscuous mode on interface ifp based on the truth value
659 * of pswitch. The calls are reference counted so that only the first
660 * "on" request actually has an effect, as does the final "off" request.
661 * Results are undefined if the "off" and "on" requests are not matched.
662 */
663int
664ifpromisc(ifp, pswitch)
665 struct ifnet *ifp;
666 int pswitch;
667{
668 struct ifreq ifr;
669 /*
670 * If the device is not configured up, we cannot put it in
671 * promiscuous mode.
672 */
673 if ((ifp->if_flags & IFF_UP) == 0)
674 return (ENETDOWN);
675
676 if (pswitch) {
677 if (ifp->if_pcount++ != 0)
678 return (0);
679 ifp->if_flags |= IFF_PROMISC;
680 } else {
681 if (--ifp->if_pcount > 0)
682 return (0);
683 ifp->if_flags &= ~IFF_PROMISC;
684 }
685 ifr.ifr_flags = ifp->if_flags;
686 return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
687}