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