]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/if.c
xnu-517.tar.gz
[apple/xnu.git] / bsd / net / if.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
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.
1c79356b
A
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
9bccf70c 58 * $FreeBSD: src/sys/net/if.c,v 1.85.2.9 2001/07/24 19:10:17 brooks Exp $
1c79356b
A
59 */
60
1c79356b
A
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>
9bccf70c 73
1c79356b 74#include <net/if.h>
9bccf70c 75#include <net/if_arp.h>
1c79356b 76#include <net/if_dl.h>
9bccf70c
A
77#include <net/if_types.h>
78#include <net/if_var.h>
1c79356b 79#include <net/radix.h>
9bccf70c
A
80#include <net/route.h>
81#ifdef __APPLE__
1c79356b 82#include <net/dlil.h>
9bccf70c 83//#include <string.h>
1c79356b 84#include <sys/domain.h>
9bccf70c
A
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
1c79356b
A
97/*
98 * System initialization
99 */
100
101static int ifconf __P((u_long, caddr_t));
102static void if_qflush __P((struct ifqueue *));
103static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));
104
105MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
106MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
107
108int ifqmaxlen = IFQ_MAXLEN;
109struct ifnethead ifnet; /* depend on static init XXX */
55e303ae 110struct ifmultihead ifma_lostlist = LIST_HEAD_INITIALIZER(ifma_lostlist);
1c79356b
A
111
112#if INET6
113/*
114 * XXX: declare here to avoid to include many inet6 related files..
115 * should be more generalized?
116 */
9bccf70c 117extern void nd6_setmtu __P((struct ifnet *));
9bccf70c 118#endif
1c79356b
A
119
120/*
121 * Network interface utility routines.
122 *
123 * Routines with ifa_ifwith* names take sockaddr *'s as
124 * parameters.
1c79356b 125 */
1c79356b
A
126
127int if_index = 0;
128struct ifaddr **ifnet_addrs;
129struct ifnet **ifindex2ifnet = NULL;
130
131
132/*
133 * Attach an interface to the
134 * list of "active" interfaces.
135 */
136void
137old_if_attach(ifp)
138 struct ifnet *ifp;
139{
140 unsigned socksize, ifasize;
141 int namelen, masklen;
142 char workbuf[64];
143 register struct sockaddr_dl *sdl;
144 register struct ifaddr *ifa;
145 static int if_indexlim = 8;
9bccf70c 146 static int inited;
1c79356b
A
147
148 if (ifp->if_snd.ifq_maxlen == 0)
149 ifp->if_snd.ifq_maxlen = ifqmaxlen;
150
9bccf70c
A
151 if (!inited) {
152 TAILQ_INIT(&ifnet);
153 inited = 1;
154 }
155
1c79356b 156 TAILQ_INSERT_TAIL(&ifnet, ifp, if_link);
55e303ae
A
157 /* if the interface is recycled, keep the index */
158 if (!((ifp->if_eflags & IFEF_REUSE) && ifp->if_index))
159 ifp->if_index = ++if_index;
1c79356b
A
160 /*
161 * XXX -
162 * The old code would work if the interface passed a pre-existing
163 * chain of ifaddrs to this code. We don't trust our callers to
164 * properly initialize the tailq, however, so we no longer allow
165 * this unlikely case.
166 */
167 TAILQ_INIT(&ifp->if_addrhead);
9bccf70c 168 TAILQ_INIT(&ifp->if_prefixhead);
1c79356b
A
169 LIST_INIT(&ifp->if_multiaddrs);
170 getmicrotime(&ifp->if_lastchange);
171 if (ifnet_addrs == 0 || if_index >= if_indexlim) {
172 unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
173 struct ifaddr **q = (struct ifaddr **)
174 _MALLOC(n, M_IFADDR, M_WAITOK);
175 bzero((caddr_t)q, n);
176 if (ifnet_addrs) {
177 bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
178 FREE((caddr_t)ifnet_addrs, M_IFADDR);
179 }
180 ifnet_addrs = (struct ifaddr **)q;
181
182 /* grow ifindex2ifnet */
9bccf70c
A
183 n = if_indexlim * sizeof(struct ifaddr *);
184 q = (struct ifaddr **)_MALLOC(n, M_IFADDR, M_WAITOK);
1c79356b
A
185 bzero(q, n);
186 if (ifindex2ifnet) {
187 bcopy((caddr_t)ifindex2ifnet, q, n/2);
188 _FREE((caddr_t)ifindex2ifnet, M_IFADDR);
189 }
190 ifindex2ifnet = (struct ifnet **)q;
191 }
192
193 ifindex2ifnet[if_index] = ifp;
194
195 /*
196 * create a Link Level name for this device
197 */
198 namelen = snprintf(workbuf, sizeof(workbuf),
199 "%s%d", ifp->if_name, ifp->if_unit);
200#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
201 masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;
202 socksize = masklen + ifp->if_addrlen;
203#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
204 if (socksize < sizeof(*sdl))
205 socksize = sizeof(*sdl);
206 socksize = ROUNDUP(socksize);
207 ifasize = sizeof(*ifa) + 2 * socksize;
208 ifa = (struct ifaddr *) _MALLOC(ifasize, M_IFADDR, M_WAITOK);
209 if (ifa) {
210 bzero((caddr_t)ifa, ifasize);
211 sdl = (struct sockaddr_dl *)(ifa + 1);
212 sdl->sdl_len = socksize;
213 sdl->sdl_family = AF_LINK;
214 bcopy(workbuf, sdl->sdl_data, namelen);
215 sdl->sdl_nlen = namelen;
216 sdl->sdl_index = ifp->if_index;
217 sdl->sdl_type = ifp->if_type;
218 ifnet_addrs[if_index - 1] = ifa;
219 ifa->ifa_ifp = ifp;
220 ifa->ifa_rtrequest = link_rtrequest;
221 ifa->ifa_addr = (struct sockaddr *)sdl;
222 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
223 ifa->ifa_netmask = (struct sockaddr *)sdl;
224 sdl->sdl_len = masklen;
225 while (namelen != 0)
226 sdl->sdl_data[--namelen] = 0xff;
227 TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);
228 }
229}
9bccf70c 230
55e303ae
A
231__private_extern__ int
232ifa_foraddr(addr)
233 unsigned int addr;
234{
235 register struct ifnet *ifp;
236 register struct ifaddr *ifa;
237 register unsigned int addr2;
238
239
240 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
241 for (ifa = ifp->if_addrhead.tqh_first; ifa;
242 ifa = ifa->ifa_link.tqe_next) {
243 if (ifa->ifa_addr->sa_family != AF_INET)
244 continue;
245 addr2 = IA_SIN(ifa)->sin_addr.s_addr;
246
247 if (addr == addr2)
248 return (1);
249 }
250 return (0);
251}
252
1c79356b
A
253/*
254 * Locate an interface based on a complete address.
255 */
256/*ARGSUSED*/
257struct ifaddr *
258ifa_ifwithaddr(addr)
259 register struct sockaddr *addr;
260{
261 register struct ifnet *ifp;
262 register struct ifaddr *ifa;
263
264#define equal(a1, a2) \
265 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
266 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
9bccf70c 267 for (ifa = ifp->if_addrhead.tqh_first; ifa;
1c79356b
A
268 ifa = ifa->ifa_link.tqe_next) {
269 if (ifa->ifa_addr->sa_family != addr->sa_family)
270 continue;
271 if (equal(addr, ifa->ifa_addr))
272 return (ifa);
273 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
274 /* IP6 doesn't have broadcast */
275 ifa->ifa_broadaddr->sa_len != 0 &&
276 equal(ifa->ifa_broadaddr, addr))
277 return (ifa);
278 }
279 return ((struct ifaddr *)0);
280}
281/*
282 * Locate the point to point interface with a given destination address.
283 */
284/*ARGSUSED*/
285struct ifaddr *
286ifa_ifwithdstaddr(addr)
287 register struct sockaddr *addr;
288{
289 register struct ifnet *ifp;
290 register struct ifaddr *ifa;
291
292 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
293 if (ifp->if_flags & IFF_POINTOPOINT)
9bccf70c 294 for (ifa = ifp->if_addrhead.tqh_first; ifa;
1c79356b
A
295 ifa = ifa->ifa_link.tqe_next) {
296 if (ifa->ifa_addr->sa_family != addr->sa_family)
297 continue;
298 if (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))
299 return (ifa);
300 }
301 return ((struct ifaddr *)0);
302}
303
304/*
305 * Find an interface on a specific network. If many, choice
306 * is most specific found.
307 */
308struct ifaddr *
309ifa_ifwithnet(addr)
310 struct sockaddr *addr;
311{
312 register struct ifnet *ifp;
313 register struct ifaddr *ifa;
314 struct ifaddr *ifa_maybe = (struct ifaddr *) 0;
315 u_int af = addr->sa_family;
316 char *addr_data = addr->sa_data, *cplim;
317
318 /*
319 * AF_LINK addresses can be looked up directly by their index number,
320 * so do that if we can.
321 */
322 if (af == AF_LINK) {
323 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
324 if (sdl->sdl_index && sdl->sdl_index <= if_index)
325 return (ifnet_addrs[sdl->sdl_index - 1]);
326 }
327
9bccf70c 328 /*
1c79356b
A
329 * Scan though each interface, looking for ones that have
330 * addresses in this address family.
331 */
332 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
333 for (ifa = ifp->if_addrhead.tqh_first; ifa;
334 ifa = ifa->ifa_link.tqe_next) {
335 register char *cp, *cp2, *cp3;
336
337 if (ifa->ifa_addr->sa_family != af)
338next: continue;
9bccf70c
A
339#ifndef __APPLE__
340/* This breaks tunneling application trying to install a route with
341 * a specific subnet and the local address as the destination
342 * It's breaks binary compatibility with previous version of MacOS X
343 */
344 if (
345
346#if INET6 /* XXX: for maching gif tunnel dst as routing entry gateway */
347 addr->sa_family != AF_INET6 &&
348#endif
349 ifp->if_flags & IFF_POINTOPOINT) {
1c79356b 350 /*
9bccf70c
A
351 * This is a bit broken as it doesn't
352 * take into account that the remote end may
1c79356b
A
353 * be a single node in the network we are
354 * looking for.
9bccf70c 355 * The trouble is that we don't know the
1c79356b
A
356 * netmask for the remote end.
357 */
358 if (ifa->ifa_dstaddr != 0
359 && equal(addr, ifa->ifa_dstaddr))
360 return (ifa);
361 } else
9bccf70c 362#endif /* __APPLE__*/
1c79356b
A
363 {
364 /*
365 * if we have a special address handler,
366 * then use it instead of the generic one.
367 */
368 if (ifa->ifa_claim_addr) {
369 if ((*ifa->ifa_claim_addr)(ifa, addr)) {
370 return (ifa);
371 } else {
372 continue;
373 }
374 }
375
376 /*
377 * Scan all the bits in the ifa's address.
378 * If a bit dissagrees with what we are
379 * looking for, mask it with the netmask
380 * to see if it really matters.
381 * (A byte at a time)
382 */
383 if (ifa->ifa_netmask == 0)
384 continue;
385 cp = addr_data;
386 cp2 = ifa->ifa_addr->sa_data;
387 cp3 = ifa->ifa_netmask->sa_data;
388 cplim = ifa->ifa_netmask->sa_len
389 + (char *)ifa->ifa_netmask;
390 while (cp3 < cplim)
391 if ((*cp++ ^ *cp2++) & *cp3++)
392 goto next; /* next address! */
393 /*
394 * If the netmask of what we just found
395 * is more specific than what we had before
396 * (if we had one) then remember the new one
397 * before continuing to search
398 * for an even better one.
399 */
400 if (ifa_maybe == 0 ||
401 rn_refines((caddr_t)ifa->ifa_netmask,
402 (caddr_t)ifa_maybe->ifa_netmask))
403 ifa_maybe = ifa;
404 }
405 }
406 }
407 return (ifa_maybe);
408}
409
410/*
411 * Find an interface address specific to an interface best matching
412 * a given address.
413 */
414struct ifaddr *
415ifaof_ifpforaddr(addr, ifp)
416 struct sockaddr *addr;
417 register struct ifnet *ifp;
418{
419 register struct ifaddr *ifa;
420 register char *cp, *cp2, *cp3;
421 register char *cplim;
422 struct ifaddr *ifa_maybe = 0;
423 u_int af = addr->sa_family;
424
425 if (af >= AF_MAX)
426 return (0);
9bccf70c 427 for (ifa = ifp->if_addrhead.tqh_first; ifa;
1c79356b
A
428 ifa = ifa->ifa_link.tqe_next) {
429 if (ifa->ifa_addr->sa_family != af)
430 continue;
431 if (ifa_maybe == 0)
432 ifa_maybe = ifa;
433 if (ifa->ifa_netmask == 0) {
434 if (equal(addr, ifa->ifa_addr) ||
435 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
436 return (ifa);
437 continue;
438 }
439 if (ifp->if_flags & IFF_POINTOPOINT) {
440 if (equal(addr, ifa->ifa_dstaddr))
441 return (ifa);
442 } else {
443 cp = addr->sa_data;
444 cp2 = ifa->ifa_addr->sa_data;
445 cp3 = ifa->ifa_netmask->sa_data;
446 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
447 for (; cp3 < cplim; cp3++)
448 if ((*cp++ ^ *cp2++) & *cp3)
449 break;
450 if (cp3 == cplim)
451 return (ifa);
452 }
453 }
454 return (ifa_maybe);
455}
456
457#include <net/route.h>
458
459/*
460 * Default action when installing a route with a Link Level gateway.
461 * Lookup an appropriate real ifa to point to.
462 * This should be moved to /sys/net/link.c eventually.
463 */
464static void
465link_rtrequest(cmd, rt, sa)
466 int cmd;
467 register struct rtentry *rt;
468 struct sockaddr *sa;
469{
470 register struct ifaddr *ifa;
471 struct sockaddr *dst;
472 struct ifnet *ifp;
473
474 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
475 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
476 return;
477 ifa = ifaof_ifpforaddr(dst, ifp);
478 if (ifa) {
9bccf70c 479 rtsetifa(rt, ifa);
1c79356b
A
480 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
481 ifa->ifa_rtrequest(cmd, rt, sa);
482 }
483}
484
485/*
486 * Mark an interface down and notify protocols of
487 * the transition.
488 * NOTE: must be called at splnet or eqivalent.
489 */
490void
491if_unroute(ifp, flag, fam)
492 register struct ifnet *ifp;
493 int flag, fam;
494{
495 register struct ifaddr *ifa;
496
497 ifp->if_flags &= ~flag;
498 getmicrotime(&ifp->if_lastchange);
499 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
500 if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
501 pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
502 if_qflush(&ifp->if_snd);
503 rt_ifmsg(ifp);
504}
505
506/*
507 * Mark an interface up and notify protocols of
508 * the transition.
509 * NOTE: must be called at splnet or eqivalent.
510 */
511void
512if_route(ifp, flag, fam)
513 register struct ifnet *ifp;
514 int flag, fam;
515{
516 register struct ifaddr *ifa;
517
518 ifp->if_flags |= flag;
519 getmicrotime(&ifp->if_lastchange);
520 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
521 if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
522 pfctlinput(PRC_IFUP, ifa->ifa_addr);
523 rt_ifmsg(ifp);
9bccf70c 524
1c79356b
A
525}
526
527/*
528 * Mark an interface down and notify protocols of
529 * the transition.
530 * NOTE: must be called at splnet or eqivalent.
531 */
532void
533if_down(ifp)
534 register struct ifnet *ifp;
535{
536
537 if_unroute(ifp, IFF_UP, AF_UNSPEC);
538}
539
540/*
541 * Mark an interface up and notify protocols of
542 * the transition.
543 * NOTE: must be called at splnet or eqivalent.
544 */
545void
546if_up(ifp)
547 register struct ifnet *ifp;
548{
549
550 if_route(ifp, IFF_UP, AF_UNSPEC);
551}
552
553/*
554 * Flush an interface queue.
555 */
556static void
557if_qflush(ifq)
558 register struct ifqueue *ifq;
559{
560 register struct mbuf *m, *n;
561
562 n = ifq->ifq_head;
563 while ((m = n) != 0) {
564 n = m->m_act;
565 m_freem(m);
566 }
567 ifq->ifq_head = 0;
568 ifq->ifq_tail = 0;
569 ifq->ifq_len = 0;
570}
571
1c79356b
A
572/*
573 * Map interface name to
574 * interface structure pointer.
575 */
576struct ifnet *
9bccf70c 577ifunit(const char *name)
1c79356b
A
578{
579 char namebuf[IFNAMSIZ + 1];
9bccf70c
A
580 const char *cp;
581 struct ifnet *ifp;
1c79356b 582 int unit;
9bccf70c
A
583 unsigned len, m;
584 char c;
1c79356b 585
9bccf70c
A
586 len = strlen(name);
587 if (len < 2 || len > IFNAMSIZ)
588 return NULL;
589 cp = name + len - 1;
590 c = *cp;
591 if (c < '0' || c > '9')
592 return NULL; /* trailing garbage */
593 unit = 0;
594 m = 1;
595 do {
596 if (cp == name)
597 return NULL; /* no interface name */
598 unit += (c - '0') * m;
599 if (unit > 1000000)
600 return NULL; /* number is unreasonable */
601 m *= 10;
602 c = *--cp;
603 } while (c >= '0' && c <= '9');
1c79356b 604 len = cp - name + 1;
9bccf70c
A
605 bcopy(name, namebuf, len);
606 namebuf[len] = '\0';
1c79356b
A
607 /*
608 * Now search all the interfaces for this name/number
609 */
610 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
9bccf70c 611 if (strcmp(ifp->if_name, namebuf))
1c79356b
A
612 continue;
613 if (unit == ifp->if_unit)
614 break;
615 }
616 return (ifp);
617}
618
619
620/*
621 * Map interface name in a sockaddr_dl to
622 * interface structure pointer.
623 */
624struct ifnet *
625if_withname(sa)
626 struct sockaddr *sa;
627{
628 char ifname[IFNAMSIZ+1];
629 struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
630
631 if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
632 (sdl->sdl_nlen > IFNAMSIZ) )
633 return NULL;
634
635 /*
636 * ifunit wants a null-terminated name. It may not be null-terminated
637 * in the sockaddr. We don't want to change the caller's sockaddr,
638 * and there might not be room to put the trailing null anyway, so we
639 * make a local copy that we know we can null terminate safely.
640 */
641
642 bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
643 ifname[sdl->sdl_nlen] = '\0';
644 return ifunit(ifname);
645}
646
647
648/*
649 * Interface ioctls.
650 */
651int
652ifioctl(so, cmd, data, p)
653 struct socket *so;
654 u_long cmd;
655 caddr_t data;
656 struct proc *p;
657{
658 register struct ifnet *ifp;
659 register struct ifreq *ifr;
9bccf70c 660 struct ifstat *ifs;
1c79356b 661 int error = 0;
1c79356b 662 short oif_flags;
9bccf70c 663 struct kev_msg ev_msg;
1c79356b
A
664 struct net_event_data ev_data;
665
666 switch (cmd) {
667
668 case SIOCGIFCONF:
669 case OSIOCGIFCONF:
670 return (ifconf(cmd, data));
671 }
672 ifr = (struct ifreq *)data;
673 ifp = ifunit(ifr->ifr_name);
674 if (ifp == 0)
675 return (ENXIO);
676 switch (cmd) {
677
678 case SIOCGIFFLAGS:
679 ifr->ifr_flags = ifp->if_flags;
680 break;
681
682 case SIOCGIFMETRIC:
683 ifr->ifr_metric = ifp->if_metric;
684 break;
685
686 case SIOCGIFMTU:
687 ifr->ifr_mtu = ifp->if_mtu;
688 break;
689
690 case SIOCGIFPHYS:
691 ifr->ifr_phys = ifp->if_physical;
692 break;
693
694 case SIOCSIFFLAGS:
695 error = suser(p->p_ucred, &p->p_acflag);
696 if (error)
697 return (error);
9bccf70c
A
698#ifndef __APPLE__
699 if (ifp->if_flags & IFF_SMART) {
700 /* Smart drivers twiddle their own routes */
701 } else
702#endif
703 if (ifp->if_flags & IFF_UP &&
704 (ifr->ifr_flags & IFF_UP) == 0) {
1c79356b
A
705 int s = splimp();
706 if_down(ifp);
707 splx(s);
9bccf70c
A
708 } else if (ifr->ifr_flags & IFF_UP &&
709 (ifp->if_flags & IFF_UP) == 0) {
1c79356b
A
710 int s = splimp();
711 if_up(ifp);
712 splx(s);
713 }
714 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
9bccf70c 715 (ifr->ifr_flags &~ IFF_CANTCHANGE);
1c79356b
A
716
717 error = dlil_ioctl(so->so_proto->pr_domain->dom_family,
718 ifp, cmd, (caddr_t) data);
719
720 if (error == 0) {
9bccf70c
A
721 ev_msg.vendor_code = KEV_VENDOR_APPLE;
722 ev_msg.kev_class = KEV_NETWORK_CLASS;
723 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
724
725 ev_msg.event_code = KEV_DL_SIFFLAGS;
726 strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
727 ev_data.if_family = ifp->if_family;
728 ev_data.if_unit = (unsigned long) ifp->if_unit;
729 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
730 ev_msg.dv[0].data_ptr = &ev_data;
731 ev_msg.dv[1].data_length = 0;
732 kev_post_msg(&ev_msg);
1c79356b
A
733 }
734 getmicrotime(&ifp->if_lastchange);
735 break;
736
737 case SIOCSIFMETRIC:
738 error = suser(p->p_ucred, &p->p_acflag);
739 if (error)
740 return (error);
741 ifp->if_metric = ifr->ifr_metric;
742
743
744 ev_msg.vendor_code = KEV_VENDOR_APPLE;
745 ev_msg.kev_class = KEV_NETWORK_CLASS;
746 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
747
748 ev_msg.event_code = KEV_DL_SIFMETRICS;
749 strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
750 ev_data.if_family = ifp->if_family;
751 ev_data.if_unit = (unsigned long) ifp->if_unit;
752 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
753 ev_msg.dv[0].data_ptr = &ev_data;
754
755 ev_msg.dv[1].data_length = 0;
756 kev_post_msg(&ev_msg);
757
758 getmicrotime(&ifp->if_lastchange);
759 break;
760
761 case SIOCSIFPHYS:
762 error = suser(p->p_ucred, &p->p_acflag);
763 if (error)
764 return error;
765
766 error = dlil_ioctl(so->so_proto->pr_domain->dom_family,
9bccf70c 767 ifp, cmd, (caddr_t) data);
1c79356b
A
768
769 if (error == 0) {
9bccf70c
A
770 ev_msg.vendor_code = KEV_VENDOR_APPLE;
771 ev_msg.kev_class = KEV_NETWORK_CLASS;
772 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
773
774 ev_msg.event_code = KEV_DL_SIFPHYS;
775 strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
776 ev_data.if_family = ifp->if_family;
777 ev_data.if_unit = (unsigned long) ifp->if_unit;
778 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
779 ev_msg.dv[0].data_ptr = &ev_data;
780 ev_msg.dv[1].data_length = 0;
781 kev_post_msg(&ev_msg);
1c79356b 782
9bccf70c 783 getmicrotime(&ifp->if_lastchange);
1c79356b
A
784 }
785 return(error);
786
787 case SIOCSIFMTU:
788 {
789 u_long oldmtu = ifp->if_mtu;
790
791 error = suser(p->p_ucred, &p->p_acflag);
792 if (error)
793 return (error);
794 if (ifp->if_ioctl == NULL)
795 return (EOPNOTSUPP);
9bccf70c 796 if (ifr->ifr_mtu < IF_MINMTU || ifr->ifr_mtu > IF_MAXMTU)
1c79356b
A
797 return (EINVAL);
798
799 error = dlil_ioctl(so->so_proto->pr_domain->dom_family,
800 ifp, cmd, (caddr_t) data);
801
802 if (error == 0) {
803 ev_msg.vendor_code = KEV_VENDOR_APPLE;
804 ev_msg.kev_class = KEV_NETWORK_CLASS;
805 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
806
807 ev_msg.event_code = KEV_DL_SIFMTU;
808 strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
809 ev_data.if_family = ifp->if_family;
810 ev_data.if_unit = (unsigned long) ifp->if_unit;
811 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
812 ev_msg.dv[0].data_ptr = &ev_data;
813 ev_msg.dv[1].data_length = 0;
814 kev_post_msg(&ev_msg);
815
816 getmicrotime(&ifp->if_lastchange);
9bccf70c 817 rt_ifmsg(ifp);
1c79356b
A
818 }
819 /*
820 * If the link MTU changed, do network layer specific procedure.
821 */
9bccf70c
A
822 if (ifp->if_mtu != oldmtu) {
823#if INET6
824 nd6_setmtu(ifp);
825#endif
1c79356b 826 }
9bccf70c
A
827 return (error);
828 }
1c79356b
A
829
830 case SIOCADDMULTI:
831 case SIOCDELMULTI:
832 error = suser(p->p_ucred, &p->p_acflag);
833 if (error)
834 return (error);
835
836 /* Don't allow group membership on non-multicast interfaces. */
837 if ((ifp->if_flags & IFF_MULTICAST) == 0)
838 return EOPNOTSUPP;
839
9bccf70c
A
840#ifndef __APPLE__
841 /* Don't let users screw up protocols' entries. */
1c79356b
A
842 if (ifr->ifr_addr.sa_family != AF_LINK)
843 return EINVAL;
844#endif
9bccf70c 845
1c79356b
A
846 if (cmd == SIOCADDMULTI) {
847 struct ifmultiaddr *ifma;
848 error = if_addmulti(ifp, &ifr->ifr_addr, &ifma);
849 ev_msg.event_code = KEV_DL_ADDMULTI;
850 } else {
851 error = if_delmulti(ifp, &ifr->ifr_addr);
852 ev_msg.event_code = KEV_DL_DELMULTI;
853 }
854 if (error == 0) {
855 ev_msg.vendor_code = KEV_VENDOR_APPLE;
856 ev_msg.kev_class = KEV_NETWORK_CLASS;
857 ev_msg.kev_subclass = KEV_DL_SUBCLASS;
858 strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ);
859
860 ev_data.if_family = ifp->if_family;
861 ev_data.if_unit = (unsigned long) ifp->if_unit;
862 ev_msg.dv[0].data_length = sizeof(struct net_event_data);
863 ev_msg.dv[0].data_ptr = &ev_data;
864 ev_msg.dv[1].data_length = 0;
865 kev_post_msg(&ev_msg);
866
867 getmicrotime(&ifp->if_lastchange);
868 }
869 return error;
870
9bccf70c
A
871 case SIOCSIFPHYADDR:
872 case SIOCDIFPHYADDR:
873#ifdef INET6
874 case SIOCSIFPHYADDR_IN6:
875#endif
876 case SIOCSLIFPHYADDR:
877 case SIOCSIFMEDIA:
1c79356b 878 case SIOCSIFGENERIC:
9bccf70c 879 case SIOCSIFLLADDR:
1c79356b
A
880 error = suser(p->p_ucred, &p->p_acflag);
881 if (error)
882 return (error);
883
884 error = dlil_ioctl(so->so_proto->pr_domain->dom_family,
885 ifp, cmd, (caddr_t) data);
886
887 if (error == 0)
888 getmicrotime(&ifp->if_lastchange);
889 return error;
890
9bccf70c
A
891 case SIOCGIFSTATUS:
892 ifs = (struct ifstat *)data;
893 ifs->ascii[0] = '\0';
894
895 case SIOCGIFPSRCADDR:
896 case SIOCGIFPDSTADDR:
897 case SIOCGLIFPHYADDR:
1c79356b
A
898 case SIOCGIFMEDIA:
899 case SIOCGIFGENERIC:
900
901 return dlil_ioctl(so->so_proto->pr_domain->dom_family,
902 ifp, cmd, (caddr_t) data);
903
904 default:
905 oif_flags = ifp->if_flags;
906 if (so->so_proto == 0)
907 return (EOPNOTSUPP);
908#if !COMPAT_43
909 return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
910 data,
911 ifp, p));
912#else
913 {
914 int ocmd = cmd;
915
916 switch (cmd) {
917
918 case SIOCSIFDSTADDR:
919 case SIOCSIFADDR:
920 case SIOCSIFBRDADDR:
921 case SIOCSIFNETMASK:
922#if BYTE_ORDER != BIG_ENDIAN
923 if (ifr->ifr_addr.sa_family == 0 &&
924 ifr->ifr_addr.sa_len < 16) {
925 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
926 ifr->ifr_addr.sa_len = 16;
927 }
928#else
929 if (ifr->ifr_addr.sa_len == 0)
930 ifr->ifr_addr.sa_len = 16;
931#endif
1c79356b
A
932 break;
933
934 case OSIOCGIFADDR:
935 cmd = SIOCGIFADDR;
936 break;
937
938 case OSIOCGIFDSTADDR:
939 cmd = SIOCGIFDSTADDR;
940 break;
941
942 case OSIOCGIFBRDADDR:
943 cmd = SIOCGIFBRDADDR;
944 break;
945
946 case OSIOCGIFNETMASK:
947 cmd = SIOCGIFNETMASK;
948 }
1c79356b
A
949 error = ((*so->so_proto->pr_usrreqs->pru_control)(so,
950 cmd,
951 data,
952 ifp, p));
953 switch (ocmd) {
954
955 case OSIOCGIFADDR:
956 case OSIOCGIFDSTADDR:
957 case OSIOCGIFBRDADDR:
958 case OSIOCGIFNETMASK:
9bccf70c 959 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
1c79356b 960
1c79356b
A
961 }
962 }
9bccf70c 963#endif /* COMPAT_43 */
1c79356b 964
9bccf70c
A
965 if (error == EOPNOTSUPP)
966 error = dlil_ioctl(so->so_proto->pr_domain->dom_family,
967 ifp, cmd, (caddr_t) data);
968
969 return (error);
1c79356b 970 }
9bccf70c 971 return (0);
1c79356b
A
972}
973
974/*
975 * Set/clear promiscuous mode on interface ifp based on the truth value
976 * of pswitch. The calls are reference counted so that only the first
977 * "on" request actually has an effect, as does the final "off" request.
978 * Results are undefined if the "off" and "on" requests are not matched.
979 */
980int
981ifpromisc(ifp, pswitch)
982 struct ifnet *ifp;
983 int pswitch;
984{
985 struct ifreq ifr;
986 int error;
9bccf70c 987 int oldflags;
1c79356b 988
9bccf70c 989 oldflags = ifp->if_flags;
1c79356b
A
990 if (pswitch) {
991 /*
992 * If the device is not configured up, we cannot put it in
993 * promiscuous mode.
994 */
995 if ((ifp->if_flags & IFF_UP) == 0)
996 return (ENETDOWN);
997 if (ifp->if_pcount++ != 0)
998 return (0);
999 ifp->if_flags |= IFF_PROMISC;
1000 log(LOG_INFO, "%s%d: promiscuous mode enabled\n",
1001 ifp->if_name, ifp->if_unit);
1002 } else {
1003 if (--ifp->if_pcount > 0)
1004 return (0);
1005 ifp->if_flags &= ~IFF_PROMISC;
9bccf70c
A
1006 log(LOG_INFO, "%s%d: promiscuous mode disabled\n",
1007 ifp->if_name, ifp->if_unit);
1c79356b
A
1008 }
1009 ifr.ifr_flags = ifp->if_flags;
1010 error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
1011 if (error == 0)
1012 rt_ifmsg(ifp);
9bccf70c
A
1013 else
1014 ifp->if_flags = oldflags;
1c79356b
A
1015 return error;
1016}
1017
1018/*
1019 * Return interface configuration
1020 * of system. List may be used
1021 * in later ioctl's (above) to get
1022 * other information.
1023 */
1024/*ARGSUSED*/
1025static int
1026ifconf(cmd, data)
1027 u_long cmd;
1028 caddr_t data;
1029{
1030 register struct ifconf *ifc = (struct ifconf *)data;
1031 register struct ifnet *ifp = ifnet.tqh_first;
1032 register struct ifaddr *ifa;
1033 struct ifreq ifr, *ifrp;
1034 int space = ifc->ifc_len, error = 0;
1035
1036 ifrp = ifc->ifc_req;
1037 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_link.tqe_next) {
1038 char workbuf[64];
9bccf70c 1039 int ifnlen, addrs;
1c79356b
A
1040
1041 ifnlen = snprintf(workbuf, sizeof(workbuf),
1042 "%s%d", ifp->if_name, ifp->if_unit);
1043 if(ifnlen + 1 > sizeof ifr.ifr_name) {
1044 error = ENAMETOOLONG;
9bccf70c 1045 break;
1c79356b
A
1046 } else {
1047 strcpy(ifr.ifr_name, workbuf);
1048 }
1049
9bccf70c
A
1050 addrs = 0;
1051 ifa = ifp->if_addrhead.tqh_first;
1052 for ( ; space > sizeof (ifr) && ifa;
1053 ifa = ifa->ifa_link.tqe_next) {
1c79356b 1054 register struct sockaddr *sa = ifa->ifa_addr;
9bccf70c
A
1055#ifndef __APPLE__
1056 if (curproc->p_prison && prison_if(curproc, sa))
1057 continue;
1058#endif
1059 addrs++;
1060#ifdef COMPAT_43
1c79356b
A
1061 if (cmd == OSIOCGIFCONF) {
1062 struct osockaddr *osa =
1063 (struct osockaddr *)&ifr.ifr_addr;
1064 ifr.ifr_addr = *sa;
1065 osa->sa_family = sa->sa_family;
1066 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1067 sizeof (ifr));
1068 ifrp++;
1069 } else
1070#endif
1071 if (sa->sa_len <= sizeof(*sa)) {
1072 ifr.ifr_addr = *sa;
1073 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1074 sizeof (ifr));
1075 ifrp++;
1076 } else {
9bccf70c
A
1077 if (space < sizeof (ifr) + sa->sa_len -
1078 sizeof(*sa))
1c79356b 1079 break;
9bccf70c 1080 space -= sa->sa_len - sizeof(*sa);
1c79356b
A
1081 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1082 sizeof (ifr.ifr_name));
1083 if (error == 0)
1084 error = copyout((caddr_t)sa,
1085 (caddr_t)&ifrp->ifr_addr, sa->sa_len);
1086 ifrp = (struct ifreq *)
1087 (sa->sa_len + (caddr_t)&ifrp->ifr_addr);
1088 }
1089 if (error)
1090 break;
1091 space -= sizeof (ifr);
1092 }
9bccf70c
A
1093 if (error)
1094 break;
1095 if (!addrs) {
1096 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
1097 error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
1098 sizeof (ifr));
1099 if (error)
1100 break;
1101 space -= sizeof (ifr);
1102 ifrp++;
1103 }
1c79356b
A
1104 }
1105 ifc->ifc_len -= space;
1106 return (error);
1107}
1108
1109/*
1110 * Just like if_promisc(), but for all-multicast-reception mode.
1111 */
1112int
1113if_allmulti(ifp, onswitch)
1114 struct ifnet *ifp;
1115 int onswitch;
1116{
1117 int error = 0;
1118 int s = splimp();
1119
1120 if (onswitch) {
1121 if (ifp->if_amcount++ == 0) {
1122 ifp->if_flags |= IFF_ALLMULTI;
1123 error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0);
1124 }
1125 } else {
1126 if (ifp->if_amcount > 1) {
1127 ifp->if_amcount--;
1128 } else {
1129 ifp->if_amcount = 0;
1130 ifp->if_flags &= ~IFF_ALLMULTI;
1131 error = dlil_ioctl(0, ifp, SIOCSIFFLAGS, (caddr_t) 0);
1132 }
1133 }
1134 splx(s);
1135
1136 if (error == 0)
1137 rt_ifmsg(ifp);
1138 return error;
1139}
1140
1141/*
1142 * Add a multicast listenership to the interface in question.
9bccf70c 1143 * The link layer provides a routine which converts
1c79356b
A
1144 */
1145int
1146if_addmulti(ifp, sa, retifma)
1147 struct ifnet *ifp; /* interface to manipulate */
1148 struct sockaddr *sa; /* address to add */
1149 struct ifmultiaddr **retifma;
1150{
1151 struct sockaddr *llsa = 0;
1152 struct sockaddr *dupsa;
1153 int error, s;
1154 struct ifmultiaddr *ifma;
1155 struct rslvmulti_req rsreq;
1156
1157 /*
1158 * If the matching multicast address already exists
1159 * then don't add a new one, just add a reference
1160 */
9bccf70c 1161 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1c79356b
A
1162 ifma = ifma->ifma_link.le_next) {
1163 if (equal(sa, ifma->ifma_addr)) {
1164 ifma->ifma_refcount++;
1165 if (retifma)
1166 *retifma = ifma;
1167 return 0;
1168 }
1169 }
1170
1171 /*
1172 * Give the link layer a chance to accept/reject it, and also
1173 * find out which AF_LINK address this maps to, if it isn't one
1174 * already.
1175 */
1c79356b
A
1176 rsreq.sa = sa;
1177 rsreq.llsa = &llsa;
1178
1179 error = dlil_ioctl(sa->sa_family, ifp, SIOCRSLVMULTI, (caddr_t) &rsreq);
9bccf70c
A
1180
1181 /* to be similar to FreeBSD */
1182 if (error == EOPNOTSUPP)
1183 error = 0;
1c79356b
A
1184
1185 if (error)
1186 return error;
1187
1c79356b
A
1188 MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma, M_IFMADDR, M_WAITOK);
1189 MALLOC(dupsa, struct sockaddr *, sa->sa_len, M_IFMADDR, M_WAITOK);
1190 bcopy(sa, dupsa, sa->sa_len);
1191
1192 ifma->ifma_addr = dupsa;
1193 ifma->ifma_lladdr = llsa;
1194 ifma->ifma_ifp = ifp;
1195 ifma->ifma_refcount = 1;
1196 ifma->ifma_protospec = 0;
1197 rt_newmaddrmsg(RTM_NEWMADDR, ifma);
1198
1199 /*
1200 * Some network interfaces can scan the address list at
1201 * interrupt time; lock them out.
1202 */
1203 s = splimp();
1204 LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
1205 splx(s);
1206 if (retifma)
1207 *retifma = ifma;
1208
1209 if (llsa != 0) {
1210 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1211 ifma = ifma->ifma_link.le_next) {
1212 if (equal(ifma->ifma_addr, llsa))
1213 break;
1214 }
1215 if (ifma) {
1216 ifma->ifma_refcount++;
1217 } else {
1218 MALLOC(ifma, struct ifmultiaddr *, sizeof *ifma,
1219 M_IFMADDR, M_WAITOK);
1220 MALLOC(dupsa, struct sockaddr *, llsa->sa_len,
1221 M_IFMADDR, M_WAITOK);
1222 bcopy(llsa, dupsa, llsa->sa_len);
1223 ifma->ifma_addr = dupsa;
1224 ifma->ifma_lladdr = 0;
1225 ifma->ifma_ifp = ifp;
1226 ifma->ifma_refcount = 1;
1227 s = splimp();
1228 LIST_INSERT_HEAD(&ifp->if_multiaddrs, ifma, ifma_link);
1229 splx(s);
1230 }
1231 }
1232 /*
1233 * We are certain we have added something, so call down to the
1234 * interface to let them know about it.
1235 */
1236 s = splimp();
1c79356b
A
1237 dlil_ioctl(0, ifp, SIOCADDMULTI, (caddr_t) 0);
1238 splx(s);
1239
1240 return 0;
1241}
1242
1c79356b 1243int
55e303ae 1244if_delmultiaddr(struct ifmultiaddr *ifma)
1c79356b 1245{
55e303ae
A
1246 struct sockaddr *sa;
1247 struct ifnet *ifp;
1248
1249 /* Verify ifma is valid */
1250 {
1251 struct ifmultiaddr *match = NULL;
1252 for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
1253 for (match = ifp->if_multiaddrs.lh_first; match; match = match->ifma_link.le_next) {
1254 if (match->ifma_ifp != ifp) {
1255 printf("if_delmultiaddr: ifma (%x) on ifp i(%s) is stale\n",
1256 match, if_name(ifp));
1257 return (0) ; /* swallow error ? */
1258 }
1259 if (match == ifma)
1260 break;
1261 }
1262 if (match == ifma)
1263 break;
1264 }
1265 if (match != ifma) {
1266 for (match = ifma_lostlist.lh_first; match; match = match->ifma_link.le_next) {
1267 if (match->ifma_ifp != NULL) {
1268 printf("if_delmultiaddr: item on lost list (%x) contains non-null ifp=%s\n",
1269 match, if_name(match->ifma_ifp));
1270 return (0) ; /* swallow error ? */
1271 }
1272 if (match == ifma)
1273 break;
1274 }
1275 }
1276
1277 if (match != ifma) {
1278 printf("if_delmultiaddr: ifma 0x%X is invalid\n", ifma);
1279 return 0;
1280 }
1281 }
1282
1c79356b
A
1283 if (ifma->ifma_refcount > 1) {
1284 ifma->ifma_refcount--;
1285 return 0;
1286 }
1287
1c79356b 1288 sa = ifma->ifma_lladdr;
55e303ae
A
1289
1290 if (sa) /* send a routing msg for network addresses only */
1291 rt_newmaddrmsg(RTM_DELMADDR, ifma);
1292
1293 ifp = ifma->ifma_ifp;
1294
1c79356b 1295 LIST_REMOVE(ifma, ifma_link);
9bccf70c
A
1296 /*
1297 * Make sure the interface driver is notified
1298 * in the case of a link layer mcast group being left.
1299 */
55e303ae 1300 if (ifp && ifma->ifma_addr->sa_family == AF_LINK && sa == 0)
9bccf70c 1301 dlil_ioctl(0, ifp, SIOCDELMULTI, 0);
1c79356b
A
1302 FREE(ifma->ifma_addr, M_IFMADDR);
1303 FREE(ifma, M_IFMADDR);
1304 if (sa == 0)
1305 return 0;
1306
1307 /*
1308 * Now look for the link-layer address which corresponds to
1309 * this network address. It had been squirreled away in
1310 * ifma->ifma_lladdr for this purpose (so we don't have
1311 * to call SIOCRSLVMULTI again), and we saved that
1312 * value in sa above. If some nasty deleted the
1313 * link-layer address out from underneath us, we can deal because
1314 * the address we stored was is not the same as the one which was
1315 * in the record for the link-layer address. (So we don't complain
1316 * in that case.)
1317 */
55e303ae
A
1318 if (ifp)
1319 ifma = ifp->if_multiaddrs.lh_first;
1320 else
1321 ifma = ifma_lostlist.lh_first;
1322 for (; ifma; ifma = ifma->ifma_link.le_next)
1c79356b
A
1323 if (equal(sa, ifma->ifma_addr))
1324 break;
55e303ae
A
1325
1326 FREE(sa, M_IFMADDR);
1327 if (ifma == 0) {
1c79356b
A
1328 return 0;
1329 }
1330
55e303ae
A
1331 return if_delmultiaddr(ifma);
1332}
1c79356b 1333
55e303ae
A
1334/*
1335 * Remove a reference to a multicast address on this interface. Yell
1336 * if the request does not match an existing membership.
1337 */
1338int
1339if_delmulti(ifp, sa)
1340 struct ifnet *ifp;
1341 struct sockaddr *sa;
1342{
1343 struct ifmultiaddr *ifma;
1344
1345 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1346 ifma = ifma->ifma_link.le_next)
1347 if (equal(sa, ifma->ifma_addr))
1348 break;
1349 if (ifma == 0)
1350 return ENOENT;
1351
1352 return if_delmultiaddr(ifma);
1c79356b
A
1353}
1354
9bccf70c
A
1355
1356/*
1357 * We don't use if_setlladdr, our interfaces are responsible for
1358 * handling the SIOCSIFLLADDR ioctl.
1359 */
1360#ifndef __APPLE__
1361int
1362if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
1363{
1364 ...
1365}
1366#endif
1367
1c79356b
A
1368struct ifmultiaddr *
1369ifmaof_ifpforaddr(sa, ifp)
1370 struct sockaddr *sa;
1371 struct ifnet *ifp;
1372{
1373 struct ifmultiaddr *ifma;
1374
1375 for (ifma = ifp->if_multiaddrs.lh_first; ifma;
1376 ifma = ifma->ifma_link.le_next)
1377 if (equal(ifma->ifma_addr, sa))
1378 break;
1379
1380 return ifma;
1381}
1382
1383SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers");
1384SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management");
1385
1386
1387/*
1388 * Shutdown all network activity. Used boot() when halting
1389 * system.
1390 */
1391int if_down_all(void)
1392{
1393 struct ifnet *ifp;
1394 int s;
1395
1396 s = splnet();
1397 TAILQ_FOREACH(ifp, &ifnet, if_link)
1398 if_down(ifp);
1399
1400 splx(s);
1401 return(0); /* Sheesh */
1402}
9bccf70c
A
1403
1404/*
1405 * Delete Routes for a Network Interface
1406 *
1407 * Called for each routing entry via the rnh->rnh_walktree() call above
1408 * to delete all route entries referencing a detaching network interface.
1409 *
1410 * Arguments:
1411 * rn pointer to node in the routing table
1412 * arg argument passed to rnh->rnh_walktree() - detaching interface
1413 *
1414 * Returns:
1415 * 0 successful
1416 * errno failed - reason indicated
1417 *
1418 */
1419static int
1420if_rtdel(rn, arg)
1421 struct radix_node *rn;
1422 void *arg;
1423{
1424 struct rtentry *rt = (struct rtentry *)rn;
1425 struct ifnet *ifp = arg;
1426 int err;
1427
1428 if (rt != NULL && rt->rt_ifp == ifp) {
1429
1430 /*
1431 * Protect (sorta) against walktree recursion problems
1432 * with cloned routes
1433 */
1434 if ((rt->rt_flags & RTF_UP) == 0)
1435 return (0);
1436
1437 err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
1438 rt_mask(rt), rt->rt_flags,
1439 (struct rtentry **) NULL);
1440 if (err) {
1441 log(LOG_WARNING, "if_rtdel: error %d\n", err);
1442 }
1443 }
1444
1445 return (0);
1446}
1447
1448/*
1449 * Removes routing table reference to a given interfacei
1450 * for a given protocol family
1451 */
1452
1453void if_rtproto_del(struct ifnet *ifp, int protocol)
1454{
1455
1456 struct radix_node_head *rnh;
1457
d12e1678 1458 if ((protocol <= AF_MAX) && ((rnh = rt_tables[protocol]) != NULL) && (ifp != NULL))
9bccf70c
A
1459 (void) rnh->rnh_walktree(rnh, if_rtdel, ifp);
1460}