]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/net/bsd_tcpip/v2_0/src/sys/net/if.c
Merge branch 'master' of git+ssh://git.kernelconcepts.de/karo-tx-redboot
[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         case SIOCGIFSTATS:
1258         case SIOCGIFSTATSUD:
1259                 if (ifp->if_ioctl == 0)
1260                         return (EOPNOTSUPP);
1261                 return ((*ifp->if_ioctl)(ifp, cmd, data));
1262
1263         case SIOCSIFLLADDR:
1264                 return if_setlladdr(ifp,
1265                     (u_char *)ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len);
1266
1267         default:
1268                 oif_flags = ifp->if_flags;
1269                 if (so->so_proto == 0)
1270                         return (EOPNOTSUPP);
1271 #ifndef COMPAT_43
1272                 error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
1273                                                                  data,
1274                                                                  ifp, p));
1275 #else
1276             {
1277                 int ocmd = cmd;
1278
1279                 switch (cmd) {
1280
1281                 case SIOCSIFDSTADDR:
1282                 case SIOCSIFADDR:
1283                 case SIOCSIFBRDADDR:
1284                 case SIOCSIFNETMASK:
1285 #if BYTE_ORDER != BIG_ENDIAN
1286                         if (ifr->ifr_addr.sa_family == 0 &&
1287                             ifr->ifr_addr.sa_len < 16) {
1288                                 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
1289                                 ifr->ifr_addr.sa_len = 16;
1290                         }
1291 #else
1292                         if (ifr->ifr_addr.sa_len == 0)
1293                                 ifr->ifr_addr.sa_len = 16;
1294 #endif
1295                         break;
1296
1297                 case OSIOCGIFADDR:
1298                         cmd = SIOCGIFADDR;
1299                         break;
1300
1301                 case OSIOCGIFDSTADDR:
1302                         cmd = SIOCGIFDSTADDR;
1303                         break;
1304
1305                 case OSIOCGIFBRDADDR:
1306                         cmd = SIOCGIFBRDADDR;
1307                         break;
1308
1309                 case OSIOCGIFNETMASK:
1310                         cmd = SIOCGIFNETMASK;
1311                 }
1312                 error =  ((*so->so_proto->pr_usrreqs->pru_control)(so,
1313                                                                    cmd,
1314                                                                    data,
1315                                                                    ifp, p));
1316                 switch (ocmd) {
1317
1318                 case OSIOCGIFADDR:
1319                 case OSIOCGIFDSTADDR:
1320                 case OSIOCGIFBRDADDR:
1321                 case OSIOCGIFNETMASK:
1322                         *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
1323
1324                 }
1325             }
1326 #endif /* COMPAT_43 */
1327
1328                 if ((oif_flags ^ ifp->if_flags) & IFF_UP) {
1329 #ifdef INET6
1330 #define DELAY cyg_thread_delay
1331                         DELAY(100);/* XXX: temporary workaround for fxp issue*/
1332                         if (ifp->if_flags & IFF_UP) {
1333                                 int s = splimp();
1334                                 in6_if_up(ifp);
1335                                 splx(s);
1336                         }
1337 #endif
1338                 }
1339                 return (error);
1340
1341         }
1342         return (0);
1343 }
1344
1345 /*
1346  * Set/clear promiscuous mode on interface ifp based on the truth value
1347  * of pswitch.  The calls are reference counted so that only the first
1348  * "on" request actually has an effect, as does the final "off" request.
1349  * Results are undefined if the "off" and "on" requests are not matched.
1350  */
1351 int
1352 ifpromisc(ifp, pswitch)
1353         struct ifnet *ifp;
1354         int pswitch;
1355 {
1356         struct ifreq ifr;
1357         int error;
1358         int oldflags;
1359
1360         oldflags = ifp->if_flags;
1361         if (pswitch) {
1362                 /*
1363                  * If the device is not configured up, we cannot put it in
1364                  * promiscuous mode.
1365                  */
1366                 if ((ifp->if_flags & IFF_UP) == 0)
1367                         return (ENETDOWN);
1368                 if (ifp->if_pcount++ != 0)
1369                         return (0);
1370                 ifp->if_flags |= IFF_PROMISC;
1371                 log(LOG_INFO, "%s%d: promiscuous mode enabled\n",
1372                     ifp->if_name, ifp->if_unit);
1373         } else {
1374                 if (--ifp->if_pcount > 0)
1375                         return (0);
1376                 ifp->if_flags &= ~IFF_PROMISC;
1377                 log(LOG_INFO, "%s%d: promiscuous mode disabled\n",
1378                     ifp->if_name, ifp->if_unit);
1379         }
1380         ifr.ifr_flags = ifp->if_flags;
1381         error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
1382         if (error == 0)
1383                 rt_ifmsg(ifp);
1384         else
1385                 ifp->if_flags = oldflags;
1386         return error;
1387 }
1388
1389 /*
1390  * Return interface configuration
1391  * of system.  List may be used
1392  * in later ioctl's (above) to get
1393  * other information.
1394  */
1395 /*ARGSUSED*/
1396 static int
1397 ifconf(cmd, data)
1398         u_long cmd;
1399         caddr_t data;
1400 {
1401         register struct ifconf *ifc = (struct ifconf *)data;
1402         register struct ifnet *ifp = ifnet.tqh_first;
1403         register struct ifaddr *ifa;
1404         struct ifreq ifr, *ifrp;
1405         int space = ifc->ifc_len, error = 0;
1406
1407         ifrp = ifc->ifc_req;
1408         for (; space > sizeof (ifr) && ifp; ifp = ifp->if_link.tqe_next) {
1409                 char workbuf[64];
1410                 int ifnlen, addrs;
1411
1412                 ifnlen = snprintf(workbuf, sizeof(workbuf),
1413                     "%s%d", ifp->if_name, ifp->if_unit);
1414                 if(ifnlen + 1 > sizeof ifr.ifr_name) {
1415                         error = ENAMETOOLONG;
1416                         break;
1417                 } else {
1418                         strcpy(ifr.ifr_name, workbuf);
1419                 }
1420
1421                 addrs = 0;
1422                 ifa = ifp->if_addrhead.tqh_first;
1423                 for ( ; space > sizeof (ifr) && ifa;
1424                     ifa = ifa->ifa_link.tqe_next) {
1425                         register struct sockaddr *sa = ifa->ifa_addr;
1426                         addrs++;
1427 #ifdef COMPAT_43
1428                         if (cmd == OSIOCGIFCONF) {
1429                                 struct osockaddr *osa =
1430                                          (struct osockaddr *)&ifr.ifr_addr;
1431                                 ifr.ifr_addr = *sa;
1432                                 osa->sa_family = sa->sa_family;
1433                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1434                                                 sizeof (ifr));
1435                                 ifrp++;
1436                         } else
1437 #endif
1438                         if (sa->sa_len <= sizeof(*sa)) {
1439                                 ifr.ifr_addr = *sa;
1440                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1441                                                 sizeof (ifr));
1442                                 ifrp++;
1443                         } else {
1444                                 if (space < sizeof (ifr) + sa->sa_len -
1445                                             sizeof(*sa))
1446                                         break;
1447                                 space -= sa->sa_len - sizeof(*sa);
1448                                 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1449                                                 sizeof (ifr.ifr_name));
1450                                 if (error == 0)
1451                                     error = copyout((caddr_t)sa,
1452                                       (caddr_t)&ifrp->ifr_addr, sa->sa_len);
1453                                 ifrp = (struct ifreq *)
1454                                         (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
1455                         }
1456                         if (error)
1457                                 break;
1458                         space -= sizeof (ifr);
1459                 }
1460                 if (error)
1461                         break;
1462                 if (!addrs) {
1463                         bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
1464                         error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1465                             sizeof (ifr));
1466                         if (error)
1467                                 break;
1468                         space -= sizeof (ifr);
1469                         ifrp++;
1470                 }
1471         }
1472         ifc->ifc_len -= space;
1473         return (error);
1474 }
1475
1476 /*
1477  * Just like if_promisc(), but for all-multicast-reception mode.
1478  */
1479 int
1480 if_allmulti(ifp, onswitch)
1481         struct ifnet *ifp;
1482         int onswitch;
1483 {
1484         int error = 0;
1485         int s = splimp();
1486
1487         if (onswitch) {
1488                 if (ifp->if_amcount++ == 0) {
1489                         ifp->if_flags |= IFF_ALLMULTI;
1490                         error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, 0);
1491                 }
1492         } else {
1493                 if (ifp->if_amcount > 1) {
1494                         ifp->if_amcount--;
1495                 } else {
1496                         ifp->if_amcount = 0;
1497                         ifp->if_flags &= ~IFF_ALLMULTI;
1498                         error = ifp->if_ioctl(ifp, SIOCSIFFLAGS, 0);
1499                 }
1500         }
1501         splx(s);
1502
1503         if (error == 0)
1504                 rt_ifmsg(ifp);
1505         return error;
1506 }
1507
1508 /*
1509  * Add a multicast listenership to the interface in question.
1510  * The link layer provides a routine which converts
1511  */
1512 int
1513 if_addmulti(ifp, sa, retifma)
1514         struct ifnet *ifp;      /* interface to manipulate */
1515         struct sockaddr *sa;    /* address to add */
1516         struct ifmultiaddr **retifma;
1517 {
1518         struct sockaddr *llsa, *dupsa;
1519         int error, s;
1520         struct ifmultiaddr *ifma;
1521
1522         /*
1523          * If the matching multicast address already exists
1524          * then don't add a new one, just add a reference
1525          */
1526         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1527              ifma = ifma->ifma_link.le_next) {
1528                 if (equal(sa, ifma->ifma_addr)) {
1529                         ifma->ifma_refcount++;
1530                         if (retifma)
1531                                 *retifma = ifma;
1532                         return 0;
1533                 }
1534         }
1535
1536         /*
1537          * Give the link layer a chance to accept/reject it, and also
1538          * find out which AF_LINK address this maps to, if it isn't one
1539          * already.
1540          */
1541         if (ifp->if_resolvemulti) {
1542                 error = ifp->if_resolvemulti(ifp, &llsa, sa);
1543                 if (error) return error;
1544         } else {
1545                 llsa = 0;
1546         }
1547
1548         MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK);
1549         MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK);
1550         bcopy(sa, dupsa, sa->sa_len);
1551
1552         ifma->ifma_addr = dupsa;
1553         ifma->ifma_lladdr = llsa;
1554         ifma->ifma_ifp = ifp;
1555         ifma->ifma_refcount = 1;
1556         ifma->ifma_protospec = 0;
1557         rt_newmaddrmsg(RTM_NEWMADDR, ifma);
1558
1559         /*
1560          * Some network interfaces can scan the address list at
1561          * interrupt time; lock them out.
1562          */
1563         s = splimp();
1564         LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
1565         splx(s);
1566         *retifma = ifma;
1567
1568         if (llsa != 0) {
1569                 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1570                      ifma = ifma->ifma_link.le_next) {
1571                         if (equal(ifma->ifma_addr, llsa))
1572                                 break;
1573                 }
1574                 if (ifma) {
1575                         ifma->ifma_refcount++;
1576                 } else {
1577                         MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma,
1578                                M_IFMADDR, M_WAITOK);
1579                         MALLOC(dupsa, struct sockaddr *, llsa->sa_len,
1580                                M_IFMADDR, M_WAITOK);
1581                         bcopy(llsa, dupsa, llsa->sa_len);
1582                         ifma->ifma_addr = dupsa;
1583                         ifma->ifma_ifp = ifp;
1584                         ifma->ifma_refcount = 1;
1585                         s = splimp();
1586                         LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
1587                         splx(s);
1588                 }
1589         }
1590         /*
1591          * We are certain we have added something, so call down to the
1592          * interface to let them know about it.
1593          */
1594         s = splimp();
1595         ifp->if_ioctl(ifp, SIOCADDMULTI, 0);
1596         splx(s);
1597
1598         return 0;
1599 }
1600
1601 /*
1602  * Remove a reference to a multicast address on this interface.  Yell
1603  * if the request does not match an existing membership.
1604  */
1605 int
1606 if_delmulti(ifp, sa)
1607         struct ifnet *ifp;
1608         struct sockaddr *sa;
1609 {
1610         struct ifmultiaddr *ifma;
1611         int s;
1612
1613         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1614              ifma = ifma->ifma_link.le_next)
1615                 if (equal(sa, ifma->ifma_addr))
1616                         break;
1617         if (ifma == 0)
1618                 return ENOENT;
1619
1620         if (ifma->ifma_refcount > 1) {
1621                 ifma->ifma_refcount--;
1622                 return 0;
1623         }
1624
1625         rt_newmaddrmsg(RTM_DELMADDR, ifma);
1626         sa = ifma->ifma_lladdr;
1627         s = splimp();
1628         LIST_REMOVE(ifma, ifma_link);
1629         /*
1630          * Make sure the interface driver is notified
1631          * in the case of a link layer mcast group being left.
1632          */
1633         if (ifma->ifma_addr->sa_family == AF_LINK && sa == 0)
1634                 ifp->if_ioctl(ifp, SIOCDELMULTI, 0);
1635         splx(s);
1636         free(ifma->ifma_addr, M_IFMADDR);
1637         free(ifma, M_IFMADDR);
1638         if (sa == 0)
1639                 return 0;
1640
1641         /*
1642          * Now look for the link-layer address which corresponds to
1643          * this network address.  It had been squirreled away in
1644          * ifma->ifma_lladdr for this purpose (so we don't have
1645          * to call ifp->if_resolvemulti() again), and we saved that
1646          * value in sa above.  If some nasty deleted the
1647          * link-layer address out from underneath us, we can deal because
1648          * the address we stored was is not the same as the one which was
1649          * in the record for the link-layer address.  (So we don't complain
1650          * in that case.)
1651          */
1652         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1653              ifma = ifma->ifma_link.le_next)
1654                 if (equal(sa, ifma->ifma_addr))
1655                         break;
1656         if (ifma == 0)
1657                 return 0;
1658
1659         if (ifma->ifma_refcount > 1) {
1660                 ifma->ifma_refcount--;
1661                 return 0;
1662         }
1663
1664         s = splimp();
1665         LIST_REMOVE(ifma, ifma_link);
1666         ifp->if_ioctl(ifp, SIOCDELMULTI, 0);
1667         splx(s);
1668         free(ifma->ifma_addr, M_IFMADDR);
1669         free(sa, M_IFMADDR);
1670         free(ifma, M_IFMADDR);
1671
1672         return 0;
1673 }
1674
1675 /*
1676  * Set the link layer address on an interface.
1677  *
1678  * At this time we only support certain types of interfaces,
1679  * and we don't allow the length of the address to change.
1680  */
1681 int
1682 if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
1683 {
1684         struct sockaddr_dl *sdl;
1685         struct ifaddr *ifa;
1686
1687         ifa = ifnet_addrs[ifp->if_index - 1];
1688         if (ifa == NULL)
1689                 return (EINVAL);
1690         sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1691         if (sdl == NULL)
1692                 return (EINVAL);
1693         if (len != sdl->sdl_alen)       /* don't allow length to change */
1694                 return (EINVAL);
1695         switch (ifp->if_type) {
1696         case IFT_ETHER:                 /* these types use struct arpcom */
1697         case IFT_FDDI:
1698         case IFT_XETHER:
1699         case IFT_ISO88025:
1700         case IFT_L2VLAN:
1701                 bcopy(lladdr, ((struct arpcom *)ifp->if_softc)->ac_enaddr, len);
1702                 bcopy(lladdr, LLADDR(sdl), len);
1703                 break;
1704         default:
1705                 return (ENODEV);
1706         }
1707         /*
1708          * If the interface is already up, we need
1709          * to re-init it in order to reprogram its
1710          * address filter.
1711          */
1712         if ((ifp->if_flags & IFF_UP) != 0) {
1713                 ifp->if_flags &= ~IFF_UP;
1714                 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, NULL);
1715                 ifp->if_flags |= IFF_UP;
1716                 (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, NULL);
1717         }
1718         return (0);
1719 }
1720
1721 struct ifmultiaddr *
1722 ifmaof_ifpforaddr(sa, ifp)
1723         struct sockaddr *sa;
1724         struct ifnet *ifp;
1725 {
1726         struct ifmultiaddr *ifma;
1727         
1728         for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1729              ifma = ifma->ifma_link.le_next)
1730                 if (equal(ifma->ifma_addr, sa))
1731                         break;
1732
1733         return ifma;
1734 }
1735
1736 SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
1737 SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");