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