]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/net/bsd_tcpip/v2_0/src/sys/net/if.c
f64de4ad261fa0fe6a970b9ceefd8fa2aec175b8
[karo-tx-redboot.git] / packages / net / bsd_tcpip / v2_0 / src / sys / net / if.c
1 //==========================================================================
2 //
3 //      src/sys/net/if.c
4 //
5 //==========================================================================
6 //####BSDCOPYRIGHTBEGIN####
7 //
8 // -------------------------------------------
9 //
10 // Portions of this software may have been derived from OpenBSD, 
11 // FreeBSD or other sources, and are covered by the appropriate
12 // copyright disclaimers included herein.
13 //
14 // Portions created by Red Hat are
15 // Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16 //
17 // -------------------------------------------
18 //
19 //####BSDCOPYRIGHTEND####
20 //==========================================================================
21
22 /*
23  * Copyright (c) 1980, 1986, 1993
24  *      The Regents of the University of California.  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. All advertising materials mentioning features or use of this software
35  *    must display the following acknowledgement:
36  *      This product includes software developed by the University of
37  *      California, Berkeley and its contributors.
38  * 4. Neither the name of the University nor the names of its contributors
39  *    may be used to endorse or promote products derived from this software
40  *    without specific prior written permission.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  *
54  *      @(#)if.c        8.3 (Berkeley) 1/4/94
55  * $FreeBSD: src/sys/net/if.c,v 1.85.2.9 2001/07/24 19:10:17 brooks Exp $
56  */
57
58 #include <sys/param.h>
59 #include <sys/malloc.h>
60 #include <sys/mbuf.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/protosw.h>
64 #include <sys/sockio.h>
65 #include <sys/sysctl.h>
66
67 #include <net/if.h>
68 #include <net/if_arp.h>
69 #include <net/if_dl.h>
70 #include <net/if_types.h>
71 #include <net/radix.h>
72 #include <net/route.h>
73
74 #if defined(INET) || defined(INET6)
75 /*XXX*/
76 #include <netinet/in.h>
77 #include <netinet/in_var.h>
78 #ifdef INET6
79 #include <netinet6/in6_var.h>
80 #include <netinet6/in6_ifattach.h>
81 #endif
82 #endif
83
84 /*
85  * System initialization
86  */
87
88 static int ifconf __P((u_long, caddr_t));
89 static void ifinit __P((void *));
90 static void if_qflush __P((struct ifqueue *));
91 static void if_slowtimo __P((void *));
92 static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
93 static int  if_rtdel __P((struct radix_node *, void *));
94
95 SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL)
96
97 int     ifqmaxlen = IFQ_MAXLEN;
98 struct  ifnethead ifnet;        /* depend on static init XXX */
99
100 #ifdef INET6
101 /*
102  * XXX: declare here to avoid to include many inet6 related files..
103  * should be more generalized?
104  */
105 extern void     nd6_setmtu __P((struct ifnet *));
106 #endif
107
108 struct if_clone *if_clone_lookup __P((const char *, int *));
109 int if_clone_list __P((struct if_clonereq *));
110
111 LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
112 int if_cloners_count;
113
114 /*
115  * Network interface utility routines.
116  *
117  * Routines with ifa_ifwith* names take sockaddr *'s as
118  * parameters.
119  */
120 /* ARGSUSED*/
121 void
122 ifinit(dummy)
123         void *dummy;
124 {
125 #ifdef DEBUG_IFINIT
126         struct ifnet *ifp;
127         int s;
128
129         s = splimp();
130         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
131             log(LOG_INIT, "IFP: %p, next: %p\n", ifp, ifp->if_link.tqe_next);
132         }
133         splx(s);
134 #endif
135         if_slowtimo(0);
136 }
137
138 int if_index = 0;
139 struct ifaddr **ifnet_addrs;
140 struct ifnet **ifindex2ifnet = NULL;
141
142 char *
143 _sa(struct ifaddr *ifa)
144 {
145     struct sockaddr *sa = ifa->ifa_addr;
146     static char _unknown[128];
147
148     switch (sa->sa_family) {
149     case AF_INET:
150         return inet_ntoa((struct in_addr)((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr);
151 #ifdef INET6
152     case AF_INET6:
153         diag_sprintf(_unknown, "%s/%d", ip6_sprintf(IFA_IN6(ifa)), 
154                      in6_mask2len(&((struct in6_ifaddr *)ifa)->ia_prefixmask.sin6_addr, NULL));
155         return _unknown;
156 #endif
157     case AF_LINK:
158         diag_sprintf(_unknown, "<<%p>>", sa);
159         return _unknown;
160     default:
161         diag_sprintf(_unknown, "[%d]", sa->sa_family);
162         return _unknown;
163     }
164 }
165
166 void
167 _show_ifp(struct ifnet *ifp)
168 {
169     log_(LOG_ADDR) {
170         struct ifaddr *ifa;
171         diag_printf("IFP: %p (%s%d)\n", ifp, ifp->if_name, ifp->if_unit);
172         TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
173             diag_printf("IFA: %p - %s\n", ifa, _sa(ifa));
174         }
175     }
176 }
177
178 /*
179  * Attach an interface to the
180  * list of "active" interfaces.
181  */
182 void
183 if_attach(ifp)
184         struct ifnet *ifp;
185 {
186         unsigned socksize, ifasize;
187         int namelen, masklen;
188         char workbuf[64];
189         register struct sockaddr_dl *sdl;
190         register struct ifaddr *ifa;
191         static int if_indexlim = 8;
192         static int inited;
193
194         if (!inited) {
195                 TAILQ_INIT(&ifnet);
196                 inited = 1;
197         }
198
199         if (ifp->if_snd.ifq_maxlen == 0) {
200             ifp->if_snd.ifq_maxlen = ifqmaxlen;
201         }
202
203         TAILQ_INSERT_TAIL(&ifnet, ifp, if_link);
204         ifp->if_index = ++if_index;
205         /*
206          * XXX -
207          * The old code would work if the interface passed a pre-existing
208          * chain of ifaddrs to this code.  We don't trust our callers to
209          * properly initialize the tailq, however, so we no longer allow
210          * this unlikely case.
211          */
212         TAILQ_INIT(&ifp->if_addrhead);        
213         log_(LOG_ADDR) {
214             diag_printf("%s.%d - After initialize list %p\n",   
215                         __FUNCTION__, __LINE__,                         
216                         &ifp->if_addrlist);                             
217             _show_ifp(ifp);                                     
218         }
219         TAILQ_INIT(&ifp->if_prefixhead);
220         LIST_INIT(&ifp->if_multiaddrs);
221         getmicrotime(&ifp->if_lastchange);
222         if (ifnet_addrs == 0 || if_index >= if_indexlim) {
223                 unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
224                 caddr_t q = malloc(n, M_IFADDR, M_WAITOK);
225                 bzero(q, n);
226                 if (ifnet_addrs) {
227                         bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
228                         free((caddr_t)ifnet_addrs, M_IFADDR);
229                 }
230                 ifnet_addrs = (struct ifaddr **)q;
231
232                 /* grow ifindex2ifnet */
233                 n = if_indexlim * sizeof(struct ifnet *);
234                 q = malloc(n, M_IFADDR, M_WAITOK);
235                 bzero(q, n);
236                 if (ifindex2ifnet) {
237                         bcopy((caddr_t)ifindex2ifnet, q, n/2);
238                         free((caddr_t)ifindex2ifnet, M_IFADDR);
239                 }
240                 ifindex2ifnet = (struct ifnet **)q;
241         }
242
243         ifindex2ifnet[if_index] = ifp;
244
245         /*
246          * create a Link Level name for this device
247          */
248         namelen = snprintf(workbuf, sizeof(workbuf),
249             "%s%d", ifp->if_name, ifp->if_unit);
250 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
251         masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
252         socksize = masklen + ifp->if_addrlen;
253 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
254         if (socksize < sizeof(*sdl))
255                 socksize = sizeof(*sdl);
256         socksize = ROUNDUP(socksize);
257         ifasize = sizeof(*ifa) + 2 * socksize;
258         ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
259         if (ifa) {
260                 bzero((caddr_t)ifa, ifasize);
261                 sdl = (struct sockaddr_dl *)(ifa + 1);
262                 sdl->sdl_len = socksize;
263                 sdl->sdl_family = AF_LINK;
264                 bcopy(workbuf, sdl->sdl_data, namelen);
265                 sdl->sdl_nlen = namelen;
266                 sdl->sdl_index = ifp->if_index;
267                 sdl->sdl_type = ifp->if_type;
268                 ifnet_addrs[if_index - 1] = ifa;
269                 ifa->ifa_ifp = ifp;
270                 ifa->ifa_rtrequest = link_rtrequest;
271                 ifa->ifa_addr = (struct sockaddr *)sdl;
272                 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
273                 ifa->ifa_netmask = (struct sockaddr *)sdl;
274                 sdl->sdl_len = masklen;
275                 while (namelen != 0)
276                         sdl->sdl_data[--namelen] = 0xff;
277                 TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
278                 log_(LOG_ADDR) {
279                     diag_printf("%s.%d - After inserting %p into list %p\n", 
280                                 __FUNCTION__, __LINE__,
281                                 ifa, &ifp->if_addrlist);
282                     _show_ifp(ifp);
283                 }
284         }
285 #ifdef ALTQ
286         ifp->if_snd.altq_type = 0;
287         ifp->if_snd.altq_disc = NULL;
288         ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;
289         ifp->if_snd.altq_tbr  = NULL;
290         ifp->if_snd.altq_ifp  = ifp;
291 #endif
292 }
293
294 /*
295  * Detach an interface, removing it from the
296  * list of "active" interfaces.
297  */
298 void
299 if_detach(ifp)
300         struct ifnet *ifp;
301 {
302         struct ifaddr *ifa;
303         struct radix_node_head  *rnh;
304         int s;
305         int i;
306
307         /*
308          * Remove routes and flush queues.
309          */
310         s = splnet();
311         if_down(ifp);
312 #ifdef ALTQ
313         if (ALTQ_IS_ENABLED(&ifp->if_snd))
314                 altq_disable(&ifp->if_snd);
315         if (ALTQ_IS_ATTACHED(&ifp->if_snd))
316                 altq_detach(&ifp->if_snd);
317 #endif
318
319         /*
320          * Remove address from ifnet_addrs[] and maybe decrement if_index.
321          * Clean up all addresses.
322          */
323         ifnet_addrs[ifp->if_index - 1] = 0;
324         while (if_index > 0 && ifnet_addrs[if_index - 1] == 0)
325                 if_index--;
326
327         for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;
328              ifa = TAILQ_FIRST(&ifp->if_addrhead)) {
329 #ifdef INET
330                 /* XXX: Ugly!! ad hoc just for INET */
331                 if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
332                         struct ifaliasreq ifr;
333
334                         bzero(&ifr, sizeof(ifr));
335                         ifr.ifra_addr = *ifa->ifa_addr;
336                         if (ifa->ifa_dstaddr)
337                                 ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
338                         if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
339                             NULL) == 0)
340                                 continue;
341                 }
342 #endif /* INET */
343 #ifdef INET6
344                 if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) {
345                         in6_purgeaddr(ifa);
346                         /* ifp_addrhead is already updated */
347                         continue;
348                 }
349 #endif /* INET6 */
350                 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
351                 IFAFREE(ifa);
352         }
353
354 #ifdef INET6
355         /*
356          * Remove all IPv6 kernel structs related to ifp.  This should be done
357          * before removing routing entries below, since IPv6 interface direct
358          * routes are expected to be removed by the IPv6-specific kernel API.
359          * Otherwise, the kernel will detect some inconsistency and bark it.
360          */
361         in6_ifdetach(ifp);
362 #endif
363
364         /*
365          * Delete all remaining routes using this interface
366          * Unfortuneatly the only way to do this is to slog through
367          * the entire routing table looking for routes which point
368          * to this interface...oh well...
369          */
370         for (i = 1; i <= AF_MAX; i++) {
371                 if ((rnh = rt_tables[i]) == NULL)
372                         continue;
373                 (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
374         }
375
376         TAILQ_REMOVE(&ifnet, ifp, if_link);
377         splx(s);
378 }
379
380 /*
381  * Delete Routes for a Network Interface
382  * 
383  * Called for each routing entry via the rnh->rnh_walktree() call above
384  * to delete all route entries referencing a detaching network interface.
385  *
386  * Arguments:
387  *      rn      pointer to node in the routing table
388  *      arg     argument passed to rnh->rnh_walktree() - detaching interface
389  *
390  * Returns:
391  *      0       successful
392  *      errno   failed - reason indicated
393  *
394  */
395 static int
396 if_rtdel(rn, arg)
397         struct radix_node       *rn;
398         void                    *arg;
399 {
400         struct rtentry  *rt = (struct rtentry *)rn;
401         struct ifnet    *ifp = arg;
402         int             err;
403
404         if (rt->rt_ifp == ifp) {
405
406                 /*
407                  * Protect (sorta) against walktree recursion problems
408                  * with cloned routes
409                  */
410                 if ((rt->rt_flags & RTF_UP) == 0)
411                         return (0);
412
413                 err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
414                                 rt_mask(rt), rt->rt_flags,
415                                 (struct rtentry **) NULL);
416                 if (err) {
417                         log(LOG_WARNING, "if_rtdel: error %d\n", err);
418                 }
419         }
420
421         return (0);
422 }
423
424 /*
425  * Create a clone network interface.
426  */
427 int
428 if_clone_create(name, len)
429         char *name;
430         int len;
431 {
432         struct if_clone *ifc;
433         char *dp;
434         int wildcard;
435         int unit;
436         int err;
437
438         ifc = if_clone_lookup(name, &unit);
439         if (ifc == NULL)
440                 return (EINVAL);
441
442         if (ifunit(name) != NULL)
443                 return (EEXIST);
444
445         wildcard = (unit < 0);
446
447         err = (*ifc->ifc_create)(ifc, &unit);
448         if (err != 0)
449                 return (err);
450
451         /* In the wildcard case, we need to update the name. */
452         if (wildcard) {
453                 for (dp = name; *dp != '\0'; dp++);
454                 if (snprintf(dp, len - (dp-name), "%d", unit) >
455                     len - (dp-name) - 1) {
456                         /*
457                          * This can only be a programmer error and
458                          * there's no straightforward way to recover if
459                          * it happens.
460                          */
461                         panic("if_clone_create(): interface name too long");
462                 }
463                         
464         }
465
466         return (0);
467 }
468
469 /*
470  * Destroy a clone network interface.
471  */
472 int
473 if_clone_destroy(name)
474         const char *name;
475 {
476         struct if_clone *ifc;
477         struct ifnet *ifp;
478
479         ifc = if_clone_lookup(name, NULL);
480         if (ifc == NULL)
481                 return (EINVAL);
482
483         ifp = ifunit(name);
484         if (ifp == NULL)
485                 return (ENXIO);
486
487         if (ifc->ifc_destroy == NULL)
488                 return (EOPNOTSUPP);
489
490         (*ifc->ifc_destroy)(ifp);
491         return (0);
492 }
493
494 /*
495  * Look up a network interface cloner.
496  */
497 struct if_clone *
498 if_clone_lookup(name, unitp)
499         const char *name;
500         int *unitp;
501 {
502         struct if_clone *ifc;
503         const char *cp;
504         int i;
505
506         for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {
507                 for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {
508                         if (ifc->ifc_name[i] != *cp)
509                                 goto next_ifc;
510                 }
511                 goto found_name;
512  next_ifc:
513                 ifc = LIST_NEXT(ifc, ifc_list);
514         }
515
516         /* No match. */
517         return ((struct if_clone *)NULL);
518
519  found_name:
520         if (*cp == '\0') {
521                 i = -1;
522         } else {
523                 for (i = 0; *cp != '\0'; cp++) {
524                         if (*cp < '0' || *cp > '9') {
525                                 /* Bogus unit number. */
526                                 return (NULL);
527                         }
528                         i = (i * 10) + (*cp - '0');
529                 }
530         }
531
532         if (unitp != NULL)
533                 *unitp = i;
534         return (ifc);
535 }
536
537 /*
538  * Register a network interface cloner.
539  */
540 void
541 if_clone_attach(ifc)
542         struct if_clone *ifc;
543 {
544
545         LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
546         if_cloners_count++;
547 }
548
549 /*
550  * Unregister a network interface cloner.
551  */
552 void
553 if_clone_detach(ifc)
554         struct if_clone *ifc;
555 {
556
557         LIST_REMOVE(ifc, ifc_list);
558         if_cloners_count--;
559 }
560
561 /*
562  * Provide list of interface cloners to userspace.
563  */
564 int
565 if_clone_list(ifcr)
566         struct if_clonereq *ifcr;
567 {
568         char outbuf[IFNAMSIZ], *dst;
569         struct if_clone *ifc;
570         int count, error = 0;
571
572         ifcr->ifcr_total = if_cloners_count;
573         if ((dst = ifcr->ifcr_buffer) == NULL) {
574                 /* Just asking how many there are. */
575                 return (0);
576         }
577
578         if (ifcr->ifcr_count < 0)
579                 return (EINVAL);
580
581         count = (if_cloners_count < ifcr->ifcr_count) ?
582             if_cloners_count : ifcr->ifcr_count;
583
584         for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
585              ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
586                 strncpy(outbuf, ifc->ifc_name, IFNAMSIZ);
587                 outbuf[IFNAMSIZ - 1] = '\0';    /* sanity */
588                 error = copyout(outbuf, dst, IFNAMSIZ);
589                 if (error)
590                         break;
591         }
592
593         return (error);
594 }
595
596 /*
597  * Locate an interface based on a complete address.
598  */
599 /*ARGSUSED*/
600 struct ifaddr *
601 ifa_ifwithaddr(addr)
602         register struct sockaddr *addr;
603 {
604         register struct ifnet *ifp;
605         register struct ifaddr *ifa;
606
607 #define equal(a1, a2) \
608   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
609         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
610             for (ifa = ifp->if_addrhead.tqh_first; ifa;
611                  ifa = ifa->ifa_link.tqe_next) {
612                 if (ifa->ifa_addr->sa_family != addr->sa_family)
613                         continue;
614                 if (equal(addr, ifa->ifa_addr))
615                         return (ifa);
616                 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
617                     /* IP6 doesn't have broadcast */
618                     ifa->ifa_broadaddr->sa_len != 0 &&
619                     equal(ifa->ifa_broadaddr, addr))
620                         return (ifa);
621         }
622         return ((struct ifaddr *)0);
623 }
624 /*
625  * Locate the point to point interface with a given destination address.
626  */
627 /*ARGSUSED*/
628 struct ifaddr *
629 ifa_ifwithdstaddr(addr)
630         register struct sockaddr *addr;
631 {
632         register struct ifnet *ifp;
633         register struct ifaddr *ifa;
634
635         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
636             if (ifp->if_flags & IFF_POINTOPOINT)
637                 for (ifa = ifp->if_addrhead.tqh_first; ifa;
638                      ifa = ifa->ifa_link.tqe_next) {
639                         if (ifa->ifa_addr->sa_family != addr->sa_family)
640                                 continue;
641                         if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))
642                                 return (ifa);
643         }
644         return ((struct ifaddr *)0);
645 }
646
647 /*
648  * Find an interface on a specific network.  If many, choice
649  * is most specific found.
650  */
651 struct ifaddr *
652 ifa_ifwithnet(addr)
653         struct sockaddr *addr;
654 {
655         register struct ifnet *ifp;
656         register struct ifaddr *ifa;
657         struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
658         u_int af = addr->sa_family;
659         char *addr_data = addr->sa_data, *cplim;
660
661         /*
662          * AF_LINK addresses can be looked up directly by their index number,
663          * so do that if we can.
664          */
665         if (af == AF_LINK) {
666             register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
667             if (sdl->sdl_index && sdl->sdl_index <= if_index)
668                 return (ifnet_addrs[sdl->sdl_index - 1]);
669         }
670
671         /*
672          * Scan though each interface, looking for ones that have
673          * addresses in this address family.
674          */
675         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
676                 for (ifa = ifp->if_addrhead.tqh_first; ifa;
677                      ifa = ifa->ifa_link.tqe_next) {
678                         register char *cp, *cp2, *cp3;
679
680                         if (ifa->ifa_addr->sa_family != af)
681 next:                           continue;
682                         if (
683 #ifdef INET6 /* XXX: for maching gif tunnel dst as routing entry gateway */
684                             addr->sa_family != AF_INET6 &&
685 #endif
686                             ifp->if_flags & IFF_POINTOPOINT) {
687                                 /*
688                                  * This is a bit broken as it doesn't
689                                  * take into account that the remote end may
690                                  * be a single node in the network we are
691                                  * looking for.
692                                  * The trouble is that we don't know the
693                                  * netmask for the remote end.
694                                  */
695                                 if (ifa->ifa_dstaddr != 0
696                                     && equal(addr, ifa->ifa_dstaddr))
697                                         return (ifa);
698                         } else {
699                                 /*
700                                  * if we have a special address handler,
701                                  * then use it instead of the generic one.
702                                  */
703                                 if (ifa->ifa_claim_addr) {
704                                         if ((*ifa->ifa_claim_addr)(ifa, addr)) {
705                                                 return (ifa);
706                                         } else {
707                                                 continue;
708                                         }
709                                 }
710
711                                 /*
712                                  * Scan all the bits in the ifa's address.
713                                  * If a bit dissagrees with what we are
714                                  * looking for, mask it with the netmask
715                                  * to see if it really matters.
716                                  * (A byte at a time)
717                                  */
718                                 if (ifa->ifa_netmask == 0)
719                                         continue;
720                                 cp = addr_data;
721                                 cp2 = ifa->ifa_addr->sa_data;
722                                 cp3 = ifa->ifa_netmask->sa_data;
723                                 cplim = ifa->ifa_netmask->sa_len
724                                         + (char *)ifa->ifa_netmask;
725                                 while (cp3 < cplim)
726                                         if ((*cp++ ^ *cp2++) & *cp3++)
727                                                 goto next; /* next address! */
728                                 /*
729                                  * If the netmask of what we just found
730                                  * is more specific than what we had before
731                                  * (if we had one) then remember the new one
732                                  * before continuing to search
733                                  * for an even better one.
734                                  */
735                                 if (ifa_maybe == 0 ||
736                                     rn_refines((caddr_t)ifa->ifa_netmask,
737                                     (caddr_t)ifa_maybe->ifa_netmask))
738                                         ifa_maybe = ifa;
739                         }
740                 }
741         }
742         return (ifa_maybe);
743 }
744
745 /*
746  * Find an interface address specific to an interface best matching
747  * a given address.
748  */
749 struct ifaddr *
750 ifaof_ifpforaddr(addr, ifp)
751         struct sockaddr *addr;
752         register struct ifnet *ifp;
753 {
754         register struct ifaddr *ifa;
755         register char *cp, *cp2, *cp3;
756         register char *cplim;
757         struct ifaddr *ifa_maybe = 0;
758         u_int af = addr->sa_family;
759
760         if (af >= AF_MAX)
761                 return (0);
762         for (ifa = ifp->if_addrhead.tqh_first; ifa;
763              ifa = ifa->ifa_link.tqe_next) {
764                 if (ifa->ifa_addr->sa_family != af)
765                         continue;
766                 if (ifa_maybe == 0)
767                         ifa_maybe = ifa;
768                 if (ifa->ifa_netmask == 0) {
769                         if (equal(addr, ifa->ifa_addr) ||
770                             (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
771                                 return (ifa);
772                         continue;
773                 }
774                 if (ifp->if_flags & IFF_POINTOPOINT) {
775                         if (equal(addr, ifa->ifa_dstaddr))
776                                 return (ifa);
777                 } else {
778                         cp = addr->sa_data;
779                         cp2 = ifa->ifa_addr->sa_data;
780                         cp3 = ifa->ifa_netmask->sa_data;
781                         cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
782                         for (; cp3 < cplim; cp3++)
783                                 if ((*cp++ ^ *cp2++) & *cp3)
784                                         break;
785                         if (cp3 == cplim)
786                                 return (ifa);
787                 }
788         }
789         return (ifa_maybe);
790 }
791
792 /*
793  * Default action when installing a route with a Link Level gateway.
794  * Lookup an appropriate real ifa to point to.
795  * This should be moved to /sys/net/link.c eventually.
796  */
797 static void
798 link_rtrequest(cmd, rt, sa)
799         int cmd;
800         register struct rtentry *rt;
801         struct sockaddr *sa;
802 {
803         register struct ifaddr *ifa;
804         struct sockaddr *dst;
805         struct ifnet *ifp;
806
807         if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
808             ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
809                 return;
810         ifa = ifaof_ifpforaddr(dst, ifp);
811         if (ifa) {
812                 IFAFREE(rt->rt_ifa);
813                 rt->rt_ifa = ifa;
814                 ifa->ifa_refcnt++;
815                 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
816                         ifa->ifa_rtrequest(cmd, rt, sa);
817         }
818 }
819
820 /*
821  * Mark an interface down and notify protocols of
822  * the transition.
823  * NOTE: must be called at splnet or eqivalent.
824  */
825 void
826 if_unroute(ifp, flag, fam)
827         register struct ifnet *ifp;
828         int flag, fam;
829 {
830         register struct ifaddr *ifa;
831
832         ifp->if_flags &= ~flag;
833         getmicrotime(&ifp->if_lastchange);
834         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
835                 if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
836                         pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
837         if_qflush(&ifp->if_snd);
838         rt_ifmsg(ifp);
839 }
840
841 /*
842  * Mark an interface up and notify protocols of
843  * the transition.
844  * NOTE: must be called at splnet or eqivalent.
845  */
846 void
847 if_route(ifp, flag, fam)
848         register struct ifnet *ifp;
849         int flag, fam;
850 {
851         register struct ifaddr *ifa;
852
853         ifp->if_flags |= flag;
854         getmicrotime(&ifp->if_lastchange);
855         TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
856                 if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
857                         pfctlinput(PRC_IFUP, ifa->ifa_addr);
858         rt_ifmsg(ifp);
859 #ifdef INET6
860         in6_if_up(ifp);
861 #endif
862 }
863
864 /*
865  * Mark an interface down and notify protocols of
866  * the transition.
867  * NOTE: must be called at splnet or eqivalent.
868  */
869 void
870 if_down(ifp)
871         register struct ifnet *ifp;
872 {
873
874         if_unroute(ifp, IFF_UP, AF_UNSPEC);
875 }
876
877 /*
878  * Mark an interface up and notify protocols of
879  * the transition.
880  * NOTE: must be called at splnet or eqivalent.
881  */
882 void
883 if_up(ifp)
884         register struct ifnet *ifp;
885 {
886
887         if_route(ifp, IFF_UP, AF_UNSPEC);
888 }
889
890 /*
891  * Flush an interface queue.
892  */
893 static void
894 if_qflush(ifq)
895 #ifdef ALTQ
896         struct ifaltq *ifq;
897 #else
898         register struct ifqueue *ifq;
899 #endif
900 {
901         register struct mbuf *m, *n;
902
903 #ifdef ALTQ
904         if (ALTQ_IS_ENABLED(ifq))
905                 ALTQ_PURGE(ifq);
906 #endif
907         n = ifq->ifq_head;
908         while ((m = n) != 0) {
909                 n = m->m_act;
910                 m_freem(m);
911         }
912         ifq->ifq_head = 0;
913         ifq->ifq_tail = 0;
914         ifq->ifq_len = 0;
915 }
916
917 /*
918  * Handle interface watchdog timer routines.  Called
919  * from softclock, we decrement timers (if set) and
920  * call the appropriate interface routine on expiration.
921  */
922 static void
923 if_slowtimo(arg)
924         void *arg;
925 {
926         register struct ifnet *ifp;
927         int s = splimp();
928
929         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
930                 if (ifp->if_timer == 0 || --ifp->if_timer)
931                         continue;
932                 if (ifp->if_watchdog)
933                         (*ifp->if_watchdog)(ifp);
934         }
935         splx(s);
936         timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
937 }
938
939 /*
940  * Map interface name to
941  * interface structure pointer.
942  */
943 struct ifnet *
944 ifunit(const char *name)
945 {
946         char namebuf[IFNAMSIZ + 1];
947         const char *cp;
948         struct ifnet *ifp;
949         int unit;
950         unsigned len, m;
951         char c;
952
953         len = strlen(name);
954         if (len < 2 || len > IFNAMSIZ)
955                 return NULL;
956         cp = name + len - 1;
957         c = *cp;
958         if (c < '0' || c > '9')
959                 return NULL;            /* trailing garbage */
960         unit = 0;
961         m = 1;
962         do {
963                 if (cp == name)
964                         return NULL;    /* no interface name */
965                 unit += (c - '0') * m;
966                 if (unit > 1000000)
967                         return NULL;    /* number is unreasonable */
968                 m *= 10;
969                 c = *--cp;
970         } while (c >= '0' && c <= '9');
971         len = cp - name + 1;
972         bcopy(name, namebuf, len);
973         namebuf[len] = '\0';
974         /*
975          * Now search all the interfaces for this name/number
976          */
977         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
978                 if (strcmp(ifp->if_name, namebuf))
979                         continue;
980                 if (unit == ifp->if_unit)
981                         break;
982         }
983         return (ifp);
984 }
985
986
987 /*
988  * Map interface name in a sockaddr_dl to
989  * interface structure pointer.
990  */
991 struct ifnet *
992 if_withname(sa)
993         struct sockaddr *sa;
994 {
995         char ifname[IFNAMSIZ+1];
996         struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
997
998         if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
999              (sdl->sdl_nlen > IFNAMSIZ) )
1000                 return NULL;
1001
1002         /*
1003          * ifunit wants a null-terminated name.  It may not be null-terminated
1004          * in the sockaddr.  We don't want to change the caller's sockaddr,
1005          * and there might not be room to put the trailing null anyway, so we
1006          * make a local copy that we know we can null terminate safely.
1007          */
1008
1009         bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
1010         ifname[sdl->sdl_nlen] = '\0';
1011         return ifunit(ifname);
1012 }
1013
1014
1015 // TEMP?
1016 #define _NAME(s) \
1017   case s: return #s; break; 
1018 char *
1019 _ioctl_name(u_long cmd)
1020 {
1021     static char unknown[32];
1022
1023     switch (cmd) {
1024         _NAME(SIOCSHIWAT);
1025         _NAME(SIOCGHIWAT);
1026         _NAME(SIOCSLOWAT);
1027         _NAME(SIOCGLOWAT);
1028         _NAME(SIOCATMARK);
1029         _NAME(SIOCSPGRP);
1030         _NAME(SIOCGPGRP);
1031         _NAME(SIOCADDRT);
1032         _NAME(SIOCDELRT);
1033 //_NAME(SIOCGETVIFCNT);
1034 //_NAME(SIOCGETSGCNT);
1035         _NAME(SIOCSIFADDR);
1036         _NAME(OSIOCGIFADDR);
1037         _NAME(SIOCGIFADDR);
1038         _NAME(SIOCSIFDSTADDR);
1039         _NAME(OSIOCGIFDSTADDR);
1040         _NAME(SIOCGIFDSTADDR);
1041         _NAME(SIOCSIFFLAGS);
1042         _NAME(SIOCGIFFLAGS);
1043         _NAME(OSIOCGIFBRDADDR);
1044         _NAME(SIOCGIFBRDADDR);
1045         _NAME(SIOCSIFBRDADDR);
1046         _NAME(OSIOCGIFCONF);
1047         _NAME(SIOCGIFCONF);
1048         _NAME(OSIOCGIFNETMASK);
1049         _NAME(SIOCGIFNETMASK);
1050         _NAME(SIOCSIFNETMASK);
1051         _NAME(SIOCGIFMETRIC);
1052         _NAME(SIOCSIFMETRIC);
1053         _NAME(SIOCDIFADDR);
1054         _NAME(SIOCAIFADDR);
1055         _NAME(SIOCALIFADDR);
1056         _NAME(SIOCGLIFADDR);
1057         _NAME(SIOCDLIFADDR);
1058         _NAME(SIOCADDMULTI);
1059         _NAME(SIOCDELMULTI);
1060         _NAME(SIOCGIFMTU);
1061         _NAME(SIOCSIFMTU);
1062         _NAME(SIOCGIFPHYS);
1063         _NAME(SIOCSIFPHYS);
1064         _NAME(SIOCSIFMEDIA);
1065         _NAME(SIOCGIFMEDIA);
1066         _NAME(SIOCSIFPHYADDR  );
1067         _NAME(SIOCGIFPSRCADDR);
1068         _NAME(SIOCGIFPDSTADDR);
1069         _NAME(SIOCDIFPHYADDR);
1070         _NAME(SIOCSLIFPHYADDR);
1071         _NAME(SIOCGLIFPHYADDR);
1072         _NAME(SIOCSIFGENERIC);
1073         _NAME(SIOCGIFGENERIC);
1074         _NAME(SIOCGIFSTATUS);
1075         _NAME(SIOCSIFLLADDR);
1076         _NAME(SIOCIFCREATE);
1077         _NAME(SIOCIFDESTROY);
1078         _NAME(SIOCIFGCLONERS);
1079         _NAME(FIONBIO);
1080         _NAME(FIOASYNC);
1081         _NAME(FIONREAD);
1082         _NAME(SIOCGIFHWADDR);
1083         _NAME(SIOCSIFHWADDR);
1084         _NAME(SIOCGIFSTATSUD);
1085         _NAME(SIOCGIFSTATS);
1086     default:
1087         diag_sprintf(unknown, "0x%08lx", cmd);
1088         return unknown;
1089     }
1090 }
1091 // TEMP?
1092
1093 /*
1094  * Interface ioctls.
1095  */
1096 int
1097 ifioctl(so, cmd, data, p)
1098         struct socket *so;
1099         u_long cmd;
1100         caddr_t data;
1101         struct proc *p;
1102 {
1103         register struct ifnet *ifp;
1104         register struct ifreq *ifr;
1105         struct ifstat *ifs;
1106         int error;
1107         short oif_flags;
1108
1109         log(LOG_IOCTL, "%s: cmd: %s, data:\n", __FUNCTION__, _ioctl_name(cmd));
1110         switch (cmd) {
1111
1112         case SIOCGIFCONF:
1113         case OSIOCGIFCONF:
1114                 return (ifconf(cmd, data));
1115         }
1116         ifr = (struct ifreq *)data;
1117
1118         switch (cmd) {
1119         case SIOCIFCREATE:
1120         case SIOCIFDESTROY:
1121                 return ((cmd == SIOCIFCREATE) ?
1122                         if_clone_create(ifr->ifr_name, sizeof(ifr->ifr_name)) :
1123                         if_clone_destroy(ifr->ifr_name));
1124         
1125         case SIOCIFGCLONERS:
1126                 return (if_clone_list((struct if_clonereq *)data));
1127         }
1128
1129         ifp = ifunit(ifr->ifr_name);
1130         if (ifp == 0)
1131                 return (ENXIO);
1132         switch (cmd) {
1133
1134         case SIOCGIFFLAGS:
1135                 ifr->ifr_flags = ifp->if_flags;
1136                 break;
1137
1138         case SIOCGIFMETRIC:
1139                 ifr->ifr_metric = ifp->if_metric;
1140                 break;
1141
1142         case SIOCGIFMTU:
1143                 ifr->ifr_mtu = ifp->if_mtu;
1144                 break;
1145
1146         case SIOCGIFPHYS:
1147                 ifr->ifr_phys = ifp->if_physical;
1148                 break;
1149
1150         case SIOCSIFFLAGS:
1151                 ifr->ifr_prevflags = ifp->if_flags;
1152                 if (ifp->if_flags & IFF_SMART) {
1153                         /* Smart drivers twiddle their own routes */
1154                 } else if (ifp->if_flags & IFF_UP &&
1155                     (ifr->ifr_flags & IFF_UP) == 0) {
1156                         int s = splimp();
1157                         if_down(ifp);
1158                         splx(s);
1159                 } else if (ifr->ifr_flags & IFF_UP &&
1160                     (ifp->if_flags & IFF_UP) == 0) {
1161                         int s = splimp();
1162                         if_up(ifp);
1163                         splx(s);
1164                 }
1165                 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
1166                         (ifr->ifr_flags &~ IFF_CANTCHANGE);
1167                 if (ifp->if_ioctl)
1168                         (void) (*ifp->if_ioctl)(ifp, cmd, data);
1169                 getmicrotime(&ifp->if_lastchange);
1170                 break;
1171
1172         case SIOCSIFMETRIC:
1173                 ifp->if_metric = ifr->ifr_metric;
1174                 getmicrotime(&ifp->if_lastchange);
1175                 break;
1176
1177         case SIOCSIFPHYS:
1178                 if (!ifp->if_ioctl)
1179                         return EOPNOTSUPP;
1180                 error = (*ifp->if_ioctl)(ifp, cmd, data);
1181                 if (error == 0)
1182                         getmicrotime(&ifp->if_lastchange);
1183                 return(error);
1184
1185         case SIOCSIFMTU:
1186         {
1187                 u_long oldmtu = ifp->if_mtu;
1188
1189                 if (ifp->if_ioctl == NULL)
1190                         return (EOPNOTSUPP);
1191                 if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU)
1192                         return (EINVAL);
1193                 error = (*ifp->if_ioctl)(ifp, cmd, data);
1194                 if (error == 0) {
1195                         getmicrotime(&ifp->if_lastchange);
1196                         rt_ifmsg(ifp);
1197                 }
1198                 /*
1199                  * If the link MTU changed, do network layer specific procedure.
1200                  */
1201                 if (ifp->if_mtu != oldmtu) {
1202 #ifdef INET6
1203                         nd6_setmtu(ifp);
1204 #endif
1205                 }
1206                 return (error);
1207         }
1208
1209         case SIOCADDMULTI:
1210         case SIOCDELMULTI:
1211
1212                 /* Don't allow group membership on non-multicast interfaces. */
1213                 if ((ifp->if_flags & IFF_MULTICAST) == 0)
1214                         return EOPNOTSUPP;
1215
1216                 /* Don't let users screw up protocols' entries. */
1217                 if (ifr->ifr_addr.sa_family != AF_LINK)
1218                         return EINVAL;
1219
1220                 log(LOG_IOCTL, "%s: %s Multi\n", __FUNCTION__, 
1221                     (cmd == SIOCADDMULTI) ? "Add" : "Del");
1222                 log_dump(LOG_IOCTL, &ifr->ifr_addr, 32);
1223                 if (cmd == SIOCADDMULTI) {
1224                         struct ifmultiaddr *ifma;
1225                         error = if_addmulti(ifp, &ifr->ifr_addr, &ifma);
1226                 } else {
1227                         error = if_delmulti(ifp, &ifr->ifr_addr);
1228                 }
1229                 if (error == 0)
1230                         getmicrotime(&ifp->if_lastchange);
1231                 return error;
1232
1233         case SIOCSIFPHYADDR:
1234         case SIOCDIFPHYADDR:
1235 #ifdef INET6
1236         case SIOCSIFPHYADDR_IN6:
1237 #endif
1238         case SIOCSLIFPHYADDR:
1239         case SIOCSIFMEDIA:
1240         case SIOCSIFGENERIC:
1241                 if (ifp->if_ioctl == 0)
1242                         return (EOPNOTSUPP);
1243                 error = (*ifp->if_ioctl)(ifp, cmd, data);
1244                 if (error == 0)
1245                         getmicrotime(&ifp->if_lastchange);
1246                 return error;
1247
1248         case SIOCGIFSTATUS:
1249                 ifs = (struct ifstat *)data;
1250                 ifs->ascii[0] = '\0';
1251                 
1252         case SIOCGIFPSRCADDR:
1253         case SIOCGIFPDSTADDR:
1254         case SIOCGLIFPHYADDR:
1255         case SIOCGIFMEDIA:
1256         case SIOCGIFGENERIC:
1257                 if (ifp->if_ioctl == 0)
1258                         return (EOPNOTSUPP);
1259                 return ((*ifp->if_ioctl)(ifp, cmd, data));
1260
1261         case SIOCSIFLLADDR:
1262                 return if_setlladdr(ifp,
1263                     (u_char *)ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len);
1264
1265         default:
1266                 oif_flags = ifp->if_flags;
1267                 if (so->so_proto == 0)
1268                         return (EOPNOTSUPP);
1269 #ifndef COMPAT_43
1270                 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
1271                                                                  data,
1272                                                                  ifp, p));
1273 #else
1274             {
1275                 int ocmd = cmd;
1276
1277                 switch (cmd) {
1278
1279                 case SIOCSIFDSTADDR:
1280                 case SIOCSIFADDR:
1281                 case SIOCSIFBRDADDR:
1282                 case SIOCSIFNETMASK:
1283 #if BYTE_ORDER != BIG_ENDIAN
1284                         if (ifr->ifr_addr.sa_family == 0 &&
1285                             ifr->ifr_addr.sa_len < 16) {
1286                                 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
1287                                 ifr->ifr_addr.sa_len = 16;
1288                         }
1289 #else
1290                         if (ifr->ifr_addr.sa_len == 0)
1291                                 ifr->ifr_addr.sa_len = 16;
1292 #endif
1293                         break;
1294
1295                 case OSIOCGIFADDR:
1296                         cmd = SIOCGIFADDR;
1297                         break;
1298
1299                 case OSIOCGIFDSTADDR:
1300                         cmd = SIOCGIFDSTADDR;
1301                         break;
1302
1303                 case OSIOCGIFBRDADDR:
1304                         cmd = SIOCGIFBRDADDR;
1305                         break;
1306
1307                 case OSIOCGIFNETMASK:
1308                         cmd = SIOCGIFNETMASK;
1309                 }
1310                 error =  ((*so->so_proto->pr_usrreqs->pru_control)(so,
1311                                                                    cmd,
1312                                                                    data,
1313                                                                    ifp, p));
1314                 switch (ocmd) {
1315
1316                 case OSIOCGIFADDR:
1317                 case OSIOCGIFDSTADDR:
1318                 case OSIOCGIFBRDADDR:
1319                 case OSIOCGIFNETMASK:
1320                         *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
1321
1322                 }
1323             }
1324 #endif /* COMPAT_43 */
1325
1326                 if ((oif_flags ^ ifp->if_flags) & IFF_UP) {
1327 #ifdef INET6
1328 #define DELAY cyg_thread_delay
1329                         DELAY(100);/* XXX: temporary workaround for fxp issue*/
1330                         if (ifp->if_flags & IFF_UP) {
1331                                 int s = splimp();
1332                                 in6_if_up(ifp);
1333                                 splx(s);
1334                         }
1335 #endif
1336                 }
1337                 return (error);
1338
1339         }
1340         return (0);
1341 }
1342
1343 /*
1344  * Set/clear promiscuous mode on interface ifp based on the truth value
1345  * of pswitch.  The calls are reference counted so that only the first
1346  * "on" request actually has an effect, as does the final "off" request.
1347  * Results are undefined if the "off" and "on" requests are not matched.
1348  */
1349 int
1350 ifpromisc(ifp, pswitch)
1351         struct ifnet *ifp;
1352         int pswitch;
1353 {
1354         struct ifreq ifr;
1355         int error;
1356         int oldflags;
1357
1358         oldflags = ifp->if_flags;
1359         if (pswitch) {
1360                 /*
1361                  * If the device is not configured up, we cannot put it in
1362                  * promiscuous mode.
1363                  */
1364                 if ((ifp->if_flags & IFF_UP) == 0)
1365                         return (ENETDOWN);
1366                 if (ifp->if_pcount++ != 0)
1367                         return (0);
1368                 ifp->if_flags |= IFF_PROMISC;
1369                 log(LOG_INFO, "%s%d: promiscuous mode enabled\n",
1370                     ifp->if_name, ifp->if_unit);
1371         } else {
1372                 if (--ifp->if_pcount > 0)
1373                         return (0);
1374                 ifp->if_flags &= ~IFF_PROMISC;
1375                 log(LOG_INFO, "%s%d: promiscuous mode disabled\n",
1376                     ifp->if_name, ifp->if_unit);
1377         }
1378         ifr.ifr_flags = ifp->if_flags;
1379         error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
1380         if (error == 0)
1381                 rt_ifmsg(ifp);
1382         else
1383                 ifp->if_flags = oldflags;
1384         return error;
1385 }
1386
1387 /*
1388  * Return interface configuration
1389  * of system.  List may be used
1390  * in later ioctl's (above) to get
1391  * other information.
1392  */
1393 /*ARGSUSED*/
1394 static int
1395 ifconf(cmd, data)
1396         u_long cmd;
1397         caddr_t data;
1398 {
1399         register struct ifconf *ifc = (struct ifconf *)data;
1400         register struct ifnet *ifp = ifnet.tqh_first;
1401         register struct ifaddr *ifa;
1402         struct ifreq ifr, *ifrp;
1403         int space = ifc->ifc_len, error = 0;
1404
1405         ifrp = ifc->ifc_req;
1406         for (; space > sizeof (ifr) && ifp; ifp = ifp->if_link.tqe_next) {
1407                 char workbuf[64];
1408                 int ifnlen, addrs;
1409
1410                 ifnlen = snprintf(workbuf, sizeof(workbuf),
1411                     "%s%d", ifp->if_name, ifp->if_unit);
1412                 if(ifnlen + 1 > sizeof ifr.ifr_name) {
1413                         error = ENAMETOOLONG;
1414                         break;
1415                 } else {
1416                         strcpy(ifr.ifr_name, workbuf);
1417                 }
1418
1419                 addrs = 0;
1420                 ifa = ifp->if_addrhead.tqh_first;
1421                 for ( ; space > sizeof (ifr) && ifa;
1422                     ifa = ifa->ifa_link.tqe_next) {
1423                         register struct sockaddr *sa = ifa->ifa_addr;
1424                         addrs++;
1425 #ifdef COMPAT_43
1426                         if (cmd == OSIOCGIFCONF) {
1427                                 struct osockaddr *osa =
1428                                          (struct osockaddr *)&ifr.ifr_addr;
1429                                 ifr.ifr_addr = *sa;
1430                                 osa->sa_family = sa->sa_family;
1431                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1432                                                 sizeof (ifr));
1433                                 ifrp++;
1434                         } else
1435 #endif
1436                         if (sa->sa_len <= sizeof(*sa)) {
1437                                 ifr.ifr_addr = *sa;
1438                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1439                                                 sizeof (ifr));
1440                                 ifrp++;
1441                         } else {
1442                                 if (space < sizeof (ifr) + sa->sa_len -
1443                                             sizeof(*sa))
1444                                         break;
1445                                 space -= sa->sa_len - sizeof(*sa);
1446                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1447                                                 sizeof (ifr.ifr_name));
1448                                 if (error == 0)
1449                                     error = copyout((caddr_t)sa,
1450                                       (caddr_t)&ifrp->ifr_addr, sa->sa_len);
1451                                 ifrp = (struct ifreq *)
1452                                         (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
1453                         }
1454                         if (error)
1455                                 break;
1456                         space -= sizeof (ifr);
1457                 }
1458                 if (error)
1459                         break;
1460                 if (!addrs) {
1461                         bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
1462                         error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1463                             sizeof (ifr));
1464                         if (error)
1465                                 break;
1466                         space -= sizeof (ifr);
1467                         ifrp++;
1468                 }
1469         }
1470         ifc->ifc_len -= space;
1471         return (error);
1472 }
1473
1474 /*
1475  * Just like if_promisc(), but for all-multicast-reception mode.
1476  */
1477 int
1478 if_allmulti(ifp, onswitch)
1479         struct ifnet *ifp;
1480         int onswitch;
1481 {
1482         int error = 0;
1483         int s = splimp();
1484
1485         if (onswitch) {
1486                 if (ifp->if_amcount++ == 0) {
1487                         ifp->if_flags |= IFF_ALLMULTI;
1488                         error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, 0);
1489                 }
1490         } else {
1491                 if (ifp->if_amcount > 1) {
1492                         ifp->if_amcount--;
1493                 } else {
1494                         ifp->if_amcount = 0;
1495                         ifp->if_flags &= ~IFF_ALLMULTI;
1496                         error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, 0);
1497                 }
1498         }
1499         splx(s);
1500
1501         if (error == 0)
1502                 rt_ifmsg(ifp);
1503         return error;
1504 }
1505
1506 /*
1507  * Add a multicast listenership to the interface in question.
1508  * The link layer provides a routine which converts
1509  */
1510 int
1511 if_addmulti(ifp, sa, retifma)
1512         struct ifnet *ifp;      /* interface to manipulate */
1513         struct sockaddr *sa;    /* address to add */
1514         struct ifmultiaddr **retifma;
1515 {
1516         struct sockaddr *llsa, *dupsa;
1517         int error, s;
1518         struct ifmultiaddr *ifma;
1519
1520         /*
1521          * If the matching multicast address already exists
1522          * then don't add a new one, just add a reference
1523          */
1524         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1525              ifma = ifma->ifma_link.le_next) {
1526                 if (equal(sa, ifma->ifma_addr)) {
1527                         ifma->ifma_refcount++;
1528                         if (retifma)
1529                                 *retifma = ifma;
1530                         return 0;
1531                 }
1532         }
1533
1534         /*
1535          * Give the link layer a chance to accept/reject it, and also
1536          * find out which AF_LINK address this maps to, if it isn't one
1537          * already.
1538          */
1539         if (ifp->if_resolvemulti) {
1540                 error = ifp->if_resolvemulti(ifp, &llsa, sa);
1541                 if (error) return error;
1542         } else {
1543                 llsa = 0;
1544         }
1545
1546         MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK);
1547         MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK);
1548         bcopy(sa, dupsa, sa->sa_len);
1549
1550         ifma->ifma_addr = dupsa;
1551         ifma->ifma_lladdr = llsa;
1552         ifma->ifma_ifp = ifp;
1553         ifma->ifma_refcount = 1;
1554         ifma->ifma_protospec = 0;
1555         rt_newmaddrmsg(RTM_NEWMADDR, ifma);
1556
1557         /*
1558          * Some network interfaces can scan the address list at
1559          * interrupt time; lock them out.
1560          */
1561         s = splimp();
1562         LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
1563         splx(s);
1564         *retifma = ifma;
1565
1566         if (llsa != 0) {
1567                 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1568                      ifma = ifma->ifma_link.le_next) {
1569                         if (equal(ifma->ifma_addr, llsa))
1570                                 break;
1571                 }
1572                 if (ifma) {
1573                         ifma->ifma_refcount++;
1574                 } else {
1575                         MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma,
1576                                M_IFMADDR, M_WAITOK);
1577                         MALLOC(dupsa, struct sockaddr *, llsa->sa_len,
1578                                M_IFMADDR, M_WAITOK);
1579                         bcopy(llsa, dupsa, llsa->sa_len);
1580                         ifma->ifma_addr = dupsa;
1581                         ifma->ifma_ifp = ifp;
1582                         ifma->ifma_refcount = 1;
1583                         s = splimp();
1584                         LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
1585                         splx(s);
1586                 }
1587         }
1588         /*
1589          * We are certain we have added something, so call down to the
1590          * interface to let them know about it.
1591          */
1592         s = splimp();
1593         ifp->if_ioctl(ifp, SIOCADDMULTI, 0);
1594         splx(s);
1595
1596         return 0;
1597 }
1598
1599 /*
1600  * Remove a reference to a multicast address on this interface.  Yell
1601  * if the request does not match an existing membership.
1602  */
1603 int
1604 if_delmulti(ifp, sa)
1605         struct ifnet *ifp;
1606         struct sockaddr *sa;
1607 {
1608         struct ifmultiaddr *ifma;
1609         int s;
1610
1611         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1612              ifma = ifma->ifma_link.le_next)
1613                 if (equal(sa, ifma->ifma_addr))
1614                         break;
1615         if (ifma == 0)
1616                 return ENOENT;
1617
1618         if (ifma->ifma_refcount > 1) {
1619                 ifma->ifma_refcount--;
1620                 return 0;
1621         }
1622
1623         rt_newmaddrmsg(RTM_DELMADDR, ifma);
1624         sa = ifma->ifma_lladdr;
1625         s = splimp();
1626         LIST_REMOVE(ifma, ifma_link);
1627         /*
1628          * Make sure the interface driver is notified
1629          * in the case of a link layer mcast group being left.
1630          */
1631         if (ifma->ifma_addr->sa_family == AF_LINK && sa == 0)
1632                 ifp->if_ioctl(ifp, SIOCDELMULTI, 0);
1633         splx(s);
1634         free(ifma->ifma_addr, M_IFMADDR);
1635         free(ifma, M_IFMADDR);
1636         if (sa == 0)
1637                 return 0;
1638
1639         /*
1640          * Now look for the link-layer address which corresponds to
1641          * this network address.  It had been squirreled away in
1642          * ifma->ifma_lladdr for this purpose (so we don't have
1643          * to call ifp->if_resolvemulti() again), and we saved that
1644          * value in sa above.  If some nasty deleted the
1645          * link-layer address out from underneath us, we can deal because
1646          * the address we stored was is not the same as the one which was
1647          * in the record for the link-layer address.  (So we don't complain
1648          * in that case.)
1649          */
1650         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1651              ifma = ifma->ifma_link.le_next)
1652                 if (equal(sa, ifma->ifma_addr))
1653                         break;
1654         if (ifma == 0)
1655                 return 0;
1656
1657         if (ifma->ifma_refcount > 1) {
1658                 ifma->ifma_refcount--;
1659                 return 0;
1660         }
1661
1662         s = splimp();
1663         LIST_REMOVE(ifma, ifma_link);
1664         ifp->if_ioctl(ifp, SIOCDELMULTI, 0);
1665         splx(s);
1666         free(ifma->ifma_addr, M_IFMADDR);
1667         free(sa, M_IFMADDR);
1668         free(ifma, M_IFMADDR);
1669
1670         return 0;
1671 }
1672
1673 /*
1674  * Set the link layer address on an interface.
1675  *
1676  * At this time we only support certain types of interfaces,
1677  * and we don't allow the length of the address to change.
1678  */
1679 int
1680 if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
1681 {
1682         struct sockaddr_dl *sdl;
1683         struct ifaddr *ifa;
1684
1685         ifa = ifnet_addrs[ifp->if_index - 1];
1686         if (ifa == NULL)
1687                 return (EINVAL);
1688         sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1689         if (sdl == NULL)
1690                 return (EINVAL);
1691         if (len != sdl->sdl_alen)       /* don't allow length to change */
1692                 return (EINVAL);
1693         switch (ifp->if_type) {
1694         case IFT_ETHER:                 /* these types use struct arpcom */
1695         case IFT_FDDI:
1696         case IFT_XETHER:
1697         case IFT_ISO88025:
1698         case IFT_L2VLAN:
1699                 bcopy(lladdr, ((struct arpcom *)ifp->if_softc)->ac_enaddr, len);
1700                 bcopy(lladdr, LLADDR(sdl), len);
1701                 break;
1702         default:
1703                 return (ENODEV);
1704         }
1705         /*
1706          * If the interface is already up, we need
1707          * to re-init it in order to reprogram its
1708          * address filter.
1709          */
1710         if ((ifp->if_flags & IFF_UP) != 0) {
1711                 ifp->if_flags &= ~IFF_UP;
1712                 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, NULL);
1713                 ifp->if_flags |= IFF_UP;
1714                 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, NULL);
1715         }
1716         return (0);
1717 }
1718
1719 struct ifmultiaddr *
1720 ifmaof_ifpforaddr(sa, ifp)
1721         struct sockaddr *sa;
1722         struct ifnet *ifp;
1723 {
1724         struct ifmultiaddr *ifma;
1725         
1726         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1727              ifma = ifma->ifma_link.le_next)
1728                 if (equal(ifma->ifma_addr, sa))
1729                         break;
1730
1731         return ifma;
1732 }
1733
1734 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
1735 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");