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