]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet/in.c
xnu-792.22.5.tar.gz
[apple/xnu.git] / bsd / netinet / in.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * Copyright (c) 1982, 1986, 1991, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)in.c 8.4 (Berkeley) 1/9/95
9bccf70c 61 * $FreeBSD: src/sys/netinet/in.c,v 1.44.2.5 2001/08/13 16:26:17 ume Exp $
1c79356b
A
62 */
63
64#include <sys/param.h>
65#include <sys/systm.h>
66#include <sys/sockio.h>
67#include <sys/socketvar.h>
68#include <sys/malloc.h>
69#include <sys/proc.h>
70#include <sys/socket.h>
71#include <sys/kernel.h>
72#include <sys/sysctl.h>
73#include <sys/kern_event.h>
91447636 74#include <sys/syslog.h>
1c79356b
A
75
76#include <net/if.h>
1c79356b 77#include <net/if_types.h>
9bccf70c 78#include <net/route.h>
1c79356b
A
79
80#include <netinet/in.h>
81#include <netinet/in_var.h>
82#include <netinet/in_pcb.h>
83
84#include <netinet/igmp_var.h>
85#include <net/dlil.h>
86
87#include <netinet/ip_var.h>
88
89#include <netinet/tcp.h>
90#include <netinet/tcp_timer.h>
91#include <netinet/tcp_var.h>
92
93#include <sys/file.h>
94
95
91447636
A
96static int in_mask2len(struct in_addr *);
97static void in_len2mask(struct in_addr *, int);
98static int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
99 struct ifnet *, struct proc *);
1c79356b 100
91447636
A
101static void in_socktrim(struct sockaddr_in *);
102static int in_ifinit(struct ifnet *,
103 struct in_ifaddr *, struct sockaddr_in *, int);
1c79356b
A
104
105static int subnetsarelocal = 0;
106SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW,
107 &subnetsarelocal, 0, "");
108
109struct in_multihead in_multihead; /* XXX BSS initialization */
110
91447636
A
111extern lck_mtx_t *rt_mtx;
112
113/* Track whether or not the SIOCARPIPLL ioctl has been called */
114__private_extern__ u_int32_t ipv4_ll_arp_aware = 0;
1c79356b
A
115
116/*
117 * Return 1 if an internet address is for a ``local'' host
118 * (one to which we have a connection). If subnetsarelocal
119 * is true, this includes other subnets of the local net.
120 * Otherwise, it includes only the directly-connected (sub)nets.
121 */
122int
123in_localaddr(in)
124 struct in_addr in;
125{
91447636
A
126 u_long i = ntohl(in.s_addr);
127 struct in_ifaddr *ia;
1c79356b
A
128
129 if (subnetsarelocal) {
91447636 130 lck_mtx_lock(rt_mtx);
1c79356b
A
131 for (ia = in_ifaddrhead.tqh_first; ia;
132 ia = ia->ia_link.tqe_next)
91447636
A
133 if ((i & ia->ia_netmask) == ia->ia_net) {
134 lck_mtx_unlock(rt_mtx);
1c79356b 135 return (1);
91447636
A
136 }
137 lck_mtx_unlock(rt_mtx);
1c79356b 138 } else {
91447636 139 lck_mtx_lock(rt_mtx);
1c79356b
A
140 for (ia = in_ifaddrhead.tqh_first; ia;
141 ia = ia->ia_link.tqe_next)
91447636
A
142 if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
143 lck_mtx_unlock(rt_mtx);
1c79356b 144 return (1);
91447636
A
145 }
146 lck_mtx_unlock(rt_mtx);
1c79356b
A
147 }
148 return (0);
149}
150
151/*
152 * Determine whether an IP address is in a reserved set of addresses
153 * that may not be forwarded, or whether datagrams to that destination
154 * may be forwarded.
155 */
156int
157in_canforward(in)
158 struct in_addr in;
159{
91447636
A
160 u_long i = ntohl(in.s_addr);
161 u_long net;
1c79356b
A
162
163 if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
164 return (0);
165 if (IN_CLASSA(i)) {
166 net = i & IN_CLASSA_NET;
167 if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
168 return (0);
169 }
170 return (1);
171}
172
173/*
174 * Trim a mask in a sockaddr
175 */
176static void
177in_socktrim(ap)
178struct sockaddr_in *ap;
179{
91447636
A
180 char *cplim = (char *) &ap->sin_addr;
181 char *cp = (char *) (&ap->sin_addr + 1);
1c79356b
A
182
183 ap->sin_len = 0;
184 while (--cp >= cplim)
185 if (*cp) {
186 (ap)->sin_len = cp - (char *) (ap) + 1;
187 break;
188 }
189}
190
191static int
192in_mask2len(mask)
193 struct in_addr *mask;
194{
195 int x, y;
196 u_char *p;
197
198 p = (u_char *)mask;
199 for (x = 0; x < sizeof(*mask); x++) {
200 if (p[x] != 0xff)
201 break;
202 }
203 y = 0;
204 if (x < sizeof(*mask)) {
205 for (y = 0; y < 8; y++) {
206 if ((p[x] & (0x80 >> y)) == 0)
207 break;
208 }
209 }
210 return x * 8 + y;
211}
212
213static void
214in_len2mask(mask, len)
215 struct in_addr *mask;
216 int len;
217{
218 int i;
219 u_char *p;
220
221 p = (u_char *)mask;
222 bzero(mask, sizeof(*mask));
223 for (i = 0; i < len / 8; i++)
224 p[i] = 0xff;
225 if (len % 8)
226 p[i] = (0xff00 >> (len % 8)) & 0xff;
227}
228
229static int in_interfaces; /* number of external internet interfaces */
230
231/*
232 * Generic internet control operations (ioctl's).
233 * Ifp is 0 if not an interface-specific ioctl.
234 */
235/* ARGSUSED */
236int
91447636
A
237in_control(
238 struct socket *so,
239 u_long cmd,
240 caddr_t data,
241 struct ifnet *ifp,
242 struct proc *p)
1c79356b 243{
91447636
A
244 struct ifreq *ifr = (struct ifreq *)data;
245 struct in_ifaddr *ia = 0, *iap;
246 struct ifaddr *ifa;
1c79356b
A
247 struct in_ifaddr *oia;
248 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
249 struct sockaddr_in oldaddr;
91447636
A
250 int error, hostIsNew, maskIsNew;
251 u_long i;
1c79356b
A
252 struct kev_msg ev_msg;
253 struct kev_in_data in_event_data;
254
1c79356b
A
255
256 switch (cmd) {
257 case SIOCALIFADDR:
258 case SIOCDLIFADDR:
91447636 259 if (p && (error = proc_suser(p)) != 0)
1c79356b 260 return error;
1c79356b
A
261 /*fall through*/
262 case SIOCGLIFADDR:
263 if (!ifp)
264 return EINVAL;
265 return in_lifaddr_ioctl(so, cmd, data, ifp, p);
266 }
267
268 /*
269 * Find address for this interface, if it exists.
270 *
271 * If an alias address was specified, find that one instead of
272 * the first one on the interface.
273 */
91447636
A
274 if (ifp) {
275 lck_mtx_lock(rt_mtx);
1c79356b
A
276 for (iap = in_ifaddrhead.tqh_first; iap;
277 iap = iap->ia_link.tqe_next)
278 if (iap->ia_ifp == ifp) {
279 if (((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr ==
280 iap->ia_addr.sin_addr.s_addr) {
281 ia = iap;
282 break;
283 } else if (ia == NULL) {
284 ia = iap;
285 if (ifr->ifr_addr.sa_family != AF_INET)
286 break;
287 }
288 }
91447636
A
289 lck_mtx_unlock(rt_mtx);
290 }
1c79356b 291 switch (cmd) {
0b4e3aa0 292 case SIOCAUTOADDR:
91447636
A
293 case SIOCARPIPLL:
294 if (p && (error = proc_suser(p)) != 0)
0b4e3aa0 295 return error;
0b4e3aa0 296 break;
1c79356b
A
297
298 case SIOCAIFADDR:
299 case SIOCDIFADDR:
300 if (ifp == 0)
301 return (EADDRNOTAVAIL);
302 if (ifra->ifra_addr.sin_family == AF_INET) {
91447636 303 lck_mtx_lock(rt_mtx);
1c79356b
A
304 for (oia = ia; ia; ia = ia->ia_link.tqe_next) {
305 if (ia->ia_ifp == ifp &&
306 ia->ia_addr.sin_addr.s_addr ==
307 ifra->ifra_addr.sin_addr.s_addr)
308 break;
309 }
91447636 310 lck_mtx_unlock(rt_mtx);
1c79356b
A
311 if ((ifp->if_flags & IFF_POINTOPOINT)
312 && (cmd == SIOCAIFADDR)
313 && (ifra->ifra_dstaddr.sin_addr.s_addr
314 == INADDR_ANY)) {
315 return EDESTADDRREQ;
316 }
317 }
0b4e3aa0
A
318 else if (cmd == SIOCAIFADDR)
319 return (EINVAL);
1c79356b
A
320 if (cmd == SIOCDIFADDR && ia == 0)
321 return (EADDRNOTAVAIL);
322 /* FALLTHROUGH */
323 case SIOCSIFADDR:
324 case SIOCSIFNETMASK:
325 case SIOCSIFDSTADDR:
1c79356b
A
326 if ((so->so_state & SS_PRIV) == 0)
327 return (EPERM);
1c79356b
A
328
329 if (ifp == 0)
330 return (EADDRNOTAVAIL);
0b4e3aa0
A
331 if (ifra->ifra_addr.sin_family != AF_INET && cmd == SIOCSIFADDR)
332 return (EINVAL);
1c79356b
A
333 if (ia == (struct in_ifaddr *)0) {
334 ia = (struct in_ifaddr *)
335 _MALLOC(sizeof *ia, M_IFADDR, M_WAITOK);
336 if (ia == (struct in_ifaddr *)NULL)
337 return (ENOBUFS);
338 bzero((caddr_t)ia, sizeof *ia);
339 /*
340 * Protect from ipintr() traversing address list
341 * while we're modifying it.
342 */
1c79356b 343
1c79356b 344 ifa = &ia->ia_ifa;
1c79356b 345
1c79356b
A
346 ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
347 ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
348 ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
349 ia->ia_sockmask.sin_len = 8;
91447636 350 ifnet_lock_exclusive(ifp);
1c79356b
A
351 if (ifp->if_flags & IFF_BROADCAST) {
352 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
353 ia->ia_broadaddr.sin_family = AF_INET;
354 }
355 ia->ia_ifp = ifp;
356 if (!(ifp->if_flags & IFF_LOOPBACK))
357 in_interfaces++;
91447636
A
358 if_attach_ifa(ifp, ifa);
359 ifnet_lock_done(ifp);
360
361 lck_mtx_lock(rt_mtx);
362 TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
363 lck_mtx_unlock(rt_mtx);
364
365 /* Generic protocol plumbing */
366
367 if (error = dlil_plumb_protocol(PF_INET, ifp)) {
368 kprintf("in.c: warning can't plumb proto if=%s%n type %d error=%d\n",
369 ifp->if_name, ifp->if_unit, ifp->if_type, error);
370 error = 0; /*discard error, can be cold with unsupported interfaces */
371 }
372
1c79356b
A
373 }
374 break;
375
0b4e3aa0
A
376 case SIOCPROTOATTACH:
377 case SIOCPROTODETACH:
91447636 378 if (p && (error = proc_suser(p)) != 0)
9bccf70c 379 return error;
0b4e3aa0
A
380 if (ifp == 0)
381 return (EADDRNOTAVAIL);
9bccf70c 382 break;
0b4e3aa0 383
1c79356b 384 case SIOCSIFBRDADDR:
9bccf70c 385#ifdef __APPLE__
1c79356b
A
386 if ((so->so_state & SS_PRIV) == 0)
387 return (EPERM);
9bccf70c
A
388#else
389 if (p && (error = suser(p)) != 0)
390 return error;
1c79356b
A
391#endif
392 /* FALLTHROUGH */
393
394 case SIOCGIFADDR:
395 case SIOCGIFNETMASK:
396 case SIOCGIFDSTADDR:
397 case SIOCGIFBRDADDR:
398 if (ia == (struct in_ifaddr *)0)
399 return (EADDRNOTAVAIL);
400 break;
401 }
402 switch (cmd) {
0b4e3aa0
A
403 case SIOCAUTOADDR:
404 if (ifp == 0)
405 return (EADDRNOTAVAIL);
91447636
A
406 ifnet_lock_exclusive(ifp);
407 if (ifr->ifr_intval)
0b4e3aa0
A
408 ifp->if_eflags |= IFEF_AUTOCONFIGURING;
409 else
410 ifp->if_eflags &= ~IFEF_AUTOCONFIGURING;
91447636
A
411 ifnet_lock_done(ifp);
412 break;
413
414 case SIOCARPIPLL:
415 if (ifp == 0)
416 return (EADDRNOTAVAIL);
417 ipv4_ll_arp_aware = 1;
418 ifnet_lock_exclusive(ifp);
419 if (ifr->ifr_data)
420 ifp->if_eflags |= IFEF_ARPLL;
421 else
422 ifp->if_eflags &= ~IFEF_ARPLL;
423 ifnet_lock_done(ifp);
0b4e3aa0 424 break;
1c79356b
A
425
426 case SIOCGIFADDR:
427 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
428 break;
429
430 case SIOCGIFBRDADDR:
431 if ((ifp->if_flags & IFF_BROADCAST) == 0)
432 return (EINVAL);
433 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
434 break;
435
436 case SIOCGIFDSTADDR:
437 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
438 return (EINVAL);
439 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
440 break;
441
442 case SIOCGIFNETMASK:
443 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
444 break;
445
446 case SIOCSIFDSTADDR:
447 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
448 return (EINVAL);
449 oldaddr = ia->ia_dstaddr;
450 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
451 error = dlil_ioctl(PF_INET, ifp, SIOCSIFDSTADDR, (caddr_t)ia);
452 if (error == EOPNOTSUPP)
453 error = 0;
454
455 if (error) {
456 ia->ia_dstaddr = oldaddr;
457 return error;
458 }
459
460 ev_msg.vendor_code = KEV_VENDOR_APPLE;
461 ev_msg.kev_class = KEV_NETWORK_CLASS;
462 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
463
464 ev_msg.event_code = KEV_INET_SIFDSTADDR;
465
466 if (ia->ia_ifa.ifa_dstaddr)
467 in_event_data.ia_dstaddr =
468 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
469 else
470 in_event_data.ia_dstaddr.s_addr = 0;
471
472 in_event_data.ia_addr = ia->ia_addr.sin_addr;
473 in_event_data.ia_net = ia->ia_net;
474 in_event_data.ia_netmask = ia->ia_netmask;
475 in_event_data.ia_subnet = ia->ia_subnet;
476 in_event_data.ia_subnetmask = ia->ia_subnetmask;
477 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
478 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
479 in_event_data.link_data.if_family = ifp->if_family;
480 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
481
482 ev_msg.dv[0].data_ptr = &in_event_data;
483 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
484 ev_msg.dv[1].data_length = 0;
485
486 kev_post_msg(&ev_msg);
487
488
489 if (ia->ia_flags & IFA_ROUTE) {
490 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
491 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
492 ia->ia_ifa.ifa_dstaddr =
493 (struct sockaddr *)&ia->ia_dstaddr;
494 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
495 }
496 break;
497
498 case SIOCSIFBRDADDR:
499 if ((ifp->if_flags & IFF_BROADCAST) == 0)
500 return (EINVAL);
501 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
502
503 ev_msg.vendor_code = KEV_VENDOR_APPLE;
504 ev_msg.kev_class = KEV_NETWORK_CLASS;
505 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
506
507 ev_msg.event_code = KEV_INET_SIFBRDADDR;
508
509 if (ia->ia_ifa.ifa_dstaddr)
510 in_event_data.ia_dstaddr =
511 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
512 else
513 in_event_data.ia_dstaddr.s_addr = 0;
514
515 in_event_data.ia_addr = ia->ia_addr.sin_addr;
516 in_event_data.ia_net = ia->ia_net;
517 in_event_data.ia_netmask = ia->ia_netmask;
518 in_event_data.ia_subnet = ia->ia_subnet;
519 in_event_data.ia_subnetmask = ia->ia_subnetmask;
520 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
521 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
522 in_event_data.link_data.if_family = ifp->if_family;
523 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
524
525 ev_msg.dv[0].data_ptr = &in_event_data;
526 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
527 ev_msg.dv[1].data_length = 0;
528
529 kev_post_msg(&ev_msg);
530
531 break;
532
533 case SIOCSIFADDR:
534 return (in_ifinit(ifp, ia,
535 (struct sockaddr_in *) &ifr->ifr_addr, 1));
536
0b4e3aa0 537 case SIOCPROTOATTACH:
91447636 538 error = dlil_plumb_protocol(PF_INET, ifp);
55e303ae
A
539 if (error)
540 return(error);
0b4e3aa0
A
541 break;
542
543 case SIOCPROTODETACH:
544 // if an ip address is still present, refuse to detach
91447636
A
545 ifnet_lock_shared(ifp);
546 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
547 if (ifa->ifa_addr->sa_family == AF_INET)
548 break;
549 ifnet_lock_done(ifp);
550 if (ifa != 0)
551 return EBUSY;
55e303ae
A
552
553 error = dlil_unplumb_protocol(PF_INET, ifp);
9bccf70c
A
554 if (error)
555 return(error);
9bccf70c
A
556 break;
557
0b4e3aa0 558
1c79356b
A
559 case SIOCSIFNETMASK:
560 i = ifra->ifra_addr.sin_addr.s_addr;
561 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
562 ev_msg.vendor_code = KEV_VENDOR_APPLE;
563 ev_msg.kev_class = KEV_NETWORK_CLASS;
564 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
565
566 ev_msg.event_code = KEV_INET_SIFNETMASK;
567
568 if (ia->ia_ifa.ifa_dstaddr)
569 in_event_data.ia_dstaddr =
570 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
571 else
572 in_event_data.ia_dstaddr.s_addr = 0;
573
574 in_event_data.ia_addr = ia->ia_addr.sin_addr;
575 in_event_data.ia_net = ia->ia_net;
576 in_event_data.ia_netmask = ia->ia_netmask;
577 in_event_data.ia_subnet = ia->ia_subnet;
578 in_event_data.ia_subnetmask = ia->ia_subnetmask;
579 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
580 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
581 in_event_data.link_data.if_family = ifp->if_family;
582 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
583
584 ev_msg.dv[0].data_ptr = &in_event_data;
585 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
586 ev_msg.dv[1].data_length = 0;
587
588 kev_post_msg(&ev_msg);
589
590 break;
591
592 case SIOCAIFADDR:
593 maskIsNew = 0;
594 hostIsNew = 1;
595 error = 0;
596 if (ia->ia_addr.sin_family == AF_INET) {
597 if (ifra->ifra_addr.sin_len == 0) {
598 ifra->ifra_addr = ia->ia_addr;
599 hostIsNew = 0;
600 } else if (ifra->ifra_addr.sin_addr.s_addr ==
601 ia->ia_addr.sin_addr.s_addr)
602 hostIsNew = 0;
603 }
604 if (ifra->ifra_mask.sin_len) {
91447636 605 in_ifscrub(ifp, ia, 0);
1c79356b
A
606 ia->ia_sockmask = ifra->ifra_mask;
607 ia->ia_subnetmask =
608 ntohl(ia->ia_sockmask.sin_addr.s_addr);
609 maskIsNew = 1;
610 }
611 if ((ifp->if_flags & IFF_POINTOPOINT) &&
612 (ifra->ifra_dstaddr.sin_family == AF_INET)) {
91447636 613 in_ifscrub(ifp, ia, 0);
1c79356b
A
614 ia->ia_dstaddr = ifra->ifra_dstaddr;
615 maskIsNew = 1; /* We lie; but the effect's the same */
616 }
617 if (ifra->ifra_addr.sin_family == AF_INET &&
618 (hostIsNew || maskIsNew)) {
619 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
620 }
621 if ((ifp->if_flags & IFF_BROADCAST) &&
622 (ifra->ifra_broadaddr.sin_family == AF_INET))
623 ia->ia_broadaddr = ifra->ifra_broadaddr;
624
625 /*
626 * Report event.
627 */
628
9bccf70c 629 if ((error == 0) || (error == EEXIST)) {
1c79356b
A
630 ev_msg.vendor_code = KEV_VENDOR_APPLE;
631 ev_msg.kev_class = KEV_NETWORK_CLASS;
632 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
633
634 if (hostIsNew)
635 ev_msg.event_code = KEV_INET_NEW_ADDR;
636 else
637 ev_msg.event_code = KEV_INET_CHANGED_ADDR;
638
639 if (ia->ia_ifa.ifa_dstaddr)
640 in_event_data.ia_dstaddr =
641 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
642 else
643 in_event_data.ia_dstaddr.s_addr = 0;
644
645 in_event_data.ia_addr = ia->ia_addr.sin_addr;
646 in_event_data.ia_net = ia->ia_net;
647 in_event_data.ia_netmask = ia->ia_netmask;
648 in_event_data.ia_subnet = ia->ia_subnet;
649 in_event_data.ia_subnetmask = ia->ia_subnetmask;
650 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
651 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
652 in_event_data.link_data.if_family = ifp->if_family;
653 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
654
655 ev_msg.dv[0].data_ptr = &in_event_data;
656 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
657 ev_msg.dv[1].data_length = 0;
658
659 kev_post_msg(&ev_msg);
660 }
661
662 return (error);
663
664 case SIOCDIFADDR:
91447636
A
665 error = dlil_ioctl(PF_INET, ifp, SIOCDIFADDR, (caddr_t)ia);
666 if (error == EOPNOTSUPP)
667 error = 0;
9bccf70c
A
668 if (error)
669 return error;
670
91447636 671 /* Fill out the kernel event information */
1c79356b
A
672 ev_msg.vendor_code = KEV_VENDOR_APPLE;
673 ev_msg.kev_class = KEV_NETWORK_CLASS;
674 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
675
676 ev_msg.event_code = KEV_INET_ADDR_DELETED;
677
678 if (ia->ia_ifa.ifa_dstaddr)
679 in_event_data.ia_dstaddr =
680 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
681 else
682 in_event_data.ia_dstaddr.s_addr = 0;
683
684 in_event_data.ia_addr = ia->ia_addr.sin_addr;
685 in_event_data.ia_net = ia->ia_net;
686 in_event_data.ia_netmask = ia->ia_netmask;
687 in_event_data.ia_subnet = ia->ia_subnet;
688 in_event_data.ia_subnetmask = ia->ia_subnetmask;
689 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
690 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
691 in_event_data.link_data.if_family = ifp->if_family;
692 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
693
694 ev_msg.dv[0].data_ptr = &in_event_data;
91447636 695 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
1c79356b
A
696 ev_msg.dv[1].data_length = 0;
697
91447636
A
698 lck_mtx_lock(rt_mtx);
699 TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
9bccf70c
A
700 /*
701 * in_ifscrub kills the interface route.
702 */
91447636 703 in_ifscrub(ifp, ia, 1);
1c79356b 704 ifa = &ia->ia_ifa;
91447636
A
705 lck_mtx_unlock(rt_mtx);
706 ifnet_lock_exclusive(ifp);
707 if_detach_ifa(ifp, ifa);
708 ifafree(&ia->ia_ifa);
9bccf70c
A
709
710#ifdef __APPLE__
91447636 711 /*
9bccf70c
A
712 * If the interface supports multicast, and no address is left,
713 * remove the "all hosts" multicast group from that interface.
714 */
715 if (ifp->if_flags & IFF_MULTICAST) {
716 struct in_addr addr;
4452a7af 717 struct in_multi *inm = NULL;
9bccf70c
A
718
719 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
720 if (ifa->ifa_addr->sa_family == AF_INET)
721 break;
722
723 if (ifa == 0) {
724 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
725 IN_LOOKUP_MULTI(addr, ifp, inm);
9bccf70c 726 }
91447636
A
727 ifnet_lock_done(ifp);
728 if (inm)
729 in_delmulti(&inm);
730 } else
731 ifnet_lock_done(ifp);
9bccf70c 732#endif
91447636
A
733
734 /* Post the kernel event */
735 kev_post_msg(&ev_msg);
1c79356b
A
736 break;
737
9bccf70c 738#ifdef __APPLE__
1c79356b
A
739 case SIOCSETOT: {
740 /*
741 * Inspiration from tcp_ctloutput() and ip_ctloutput()
9bccf70c 742 * Special ioctl for OpenTransport sockets
1c79356b
A
743 */
744 struct inpcb *inp, *cloned_inp;
91447636 745 int error2 = 0;
1c79356b
A
746 int cloned_fd = *(int *)data;
747
1c79356b
A
748 inp = sotoinpcb(so);
749 if (inp == NULL) {
1c79356b
A
750 break;
751 }
752
753 /* let's make sure it's either -1 or a valid file descriptor */
754 if (cloned_fd != -1) {
755 struct socket *cloned_so;
91447636
A
756 error2 = file_socket(cloned_fd, &cloned_so);
757 if (error2){
1c79356b
A
758 break;
759 }
1c79356b 760 cloned_inp = sotoinpcb(cloned_so);
91447636 761 file_drop(cloned_fd);
1c79356b
A
762 } else {
763 cloned_inp = NULL;
764 }
765
766 if (cloned_inp == NULL) {
767 /* OT always uses IP_PORTRANGE_HIGH */
768 inp->inp_flags &= ~(INP_LOWPORT);
769 inp->inp_flags |= INP_HIGHPORT;
770 /* For UDP, OT allows broadcast by default */
771 if (so->so_type == SOCK_DGRAM)
772 so->so_options |= SO_BROADCAST;
773 /* For TCP we want to see MSG_OOB when receive urgent data */
774 else if (so->so_type == SOCK_STREAM)
775 so->so_options |= SO_WANTOOBFLAG;
776 } else {
777 inp->inp_ip_tos = cloned_inp->inp_ip_tos;
778 inp->inp_ip_ttl = cloned_inp->inp_ip_ttl;
779 inp->inp_flags = cloned_inp->inp_flags;
780
781 /* Multicast options */
782 if (cloned_inp->inp_moptions != NULL) {
91447636 783 int i;
1c79356b
A
784 struct ip_moptions *cloned_imo = cloned_inp->inp_moptions;
785 struct ip_moptions *imo = inp->inp_moptions;
786
787 if (imo == NULL) {
788 /*
789 * No multicast option buffer attached to the pcb;
790 * allocate one.
791 */
1c79356b
A
792 imo = (struct ip_moptions*)
793 _MALLOC(sizeof(*imo), M_IPMOPTS, M_WAITOK);
794 if (imo == NULL) {
91447636 795 error2 = ENOBUFS;
1c79356b
A
796 break;
797 }
1c79356b
A
798 inp->inp_moptions = imo;
799 }
800 imo->imo_multicast_ifp = cloned_imo->imo_multicast_ifp;
801 imo->imo_multicast_vif = cloned_imo->imo_multicast_vif;
802 imo->imo_multicast_ttl = cloned_imo->imo_multicast_ttl;
803 imo->imo_multicast_loop = cloned_imo->imo_multicast_loop;
804 imo->imo_num_memberships = cloned_imo->imo_num_memberships;
805 for (i = 0; i < cloned_imo->imo_num_memberships; i++) {
806 imo->imo_membership[i] =
807 in_addmulti(&cloned_imo->imo_membership[i]->inm_addr,
808 cloned_imo->imo_membership[i]->inm_ifp);
9bccf70c 809 if (imo->imo_membership[i] == NULL) {
91447636 810 error2 = ENOBUFS;
9bccf70c
A
811 break;
812 }
813 }
814 if (i < cloned_imo->imo_num_memberships) {
815 /* Failed, perform cleanup */
816 for (i--; i >= 0; i--)
91447636
A
817 in_delmulti(&imo->imo_membership[i]);
818 imo->imo_num_memberships = 0;
9bccf70c 819 break;
1c79356b
A
820 }
821 }
822 }
1c79356b
A
823 break;
824 }
9bccf70c 825#endif /* __APPLE__ */
1c79356b
A
826
827 default:
9bccf70c 828 return EOPNOTSUPP;
1c79356b
A
829 }
830 return (0);
831}
832
833/*
834 * SIOC[GAD]LIFADDR.
9bccf70c 835 * SIOCGLIFADDR: get first address. (?!?)
1c79356b
A
836 * SIOCGLIFADDR with IFLR_PREFIX:
837 * get first address that matches the specified prefix.
838 * SIOCALIFADDR: add the specified address.
839 * SIOCALIFADDR with IFLR_PREFIX:
840 * EINVAL since we can't deduce hostid part of the address.
841 * SIOCDLIFADDR: delete the specified address.
842 * SIOCDLIFADDR with IFLR_PREFIX:
843 * delete the first address that matches the specified prefix.
844 * return values:
845 * EINVAL on invalid parameters
846 * EADDRNOTAVAIL on prefix match failed/specified address not found
847 * other values may be returned from in_ioctl()
848 */
849static int
91447636
A
850in_lifaddr_ioctl(
851 struct socket *so,
852 u_long cmd,
853 caddr_t data,
854 struct ifnet *ifp,
855 struct proc *p)
1c79356b
A
856{
857 struct if_laddrreq *iflr = (struct if_laddrreq *)data;
858 struct ifaddr *ifa;
859
860 /* sanity checks */
861 if (!data || !ifp) {
862 panic("invalid argument to in_lifaddr_ioctl");
863 /*NOTRECHED*/
864 }
865
866 switch (cmd) {
867 case SIOCGLIFADDR:
868 /* address must be specified on GET with IFLR_PREFIX */
869 if ((iflr->flags & IFLR_PREFIX) == 0)
870 break;
871 /*FALLTHROUGH*/
872 case SIOCALIFADDR:
873 case SIOCDLIFADDR:
874 /* address must be specified on ADD and DELETE */
875 if (iflr->addr.ss_family != AF_INET)
876 return EINVAL;
877 if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
878 return EINVAL;
879 /* XXX need improvement */
880 if (iflr->dstaddr.ss_family
881 && iflr->dstaddr.ss_family != AF_INET)
882 return EINVAL;
883 if (iflr->dstaddr.ss_family
884 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
885 return EINVAL;
886 break;
887 default: /*shouldn't happen*/
1c79356b 888 return EOPNOTSUPP;
1c79356b
A
889 }
890 if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
891 return EINVAL;
892
893 switch (cmd) {
894 case SIOCALIFADDR:
895 {
896 struct in_aliasreq ifra;
897
898 if (iflr->flags & IFLR_PREFIX)
899 return EINVAL;
900
901 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
902 bzero(&ifra, sizeof(ifra));
903 bcopy(iflr->iflr_name, ifra.ifra_name,
904 sizeof(ifra.ifra_name));
905
906 bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
907
908 if (iflr->dstaddr.ss_family) { /*XXX*/
909 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
910 iflr->dstaddr.ss_len);
911 }
912
913 ifra.ifra_mask.sin_family = AF_INET;
914 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
915 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
916
917 return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, p);
918 }
919 case SIOCGLIFADDR:
920 case SIOCDLIFADDR:
921 {
922 struct in_ifaddr *ia;
923 struct in_addr mask, candidate, match;
924 struct sockaddr_in *sin;
925 int cmp;
926
927 bzero(&mask, sizeof(mask));
928 if (iflr->flags & IFLR_PREFIX) {
929 /* lookup a prefix rather than address. */
930 in_len2mask(&mask, iflr->prefixlen);
931
932 sin = (struct sockaddr_in *)&iflr->addr;
933 match.s_addr = sin->sin_addr.s_addr;
934 match.s_addr &= mask.s_addr;
935
936 /* if you set extra bits, that's wrong */
937 if (match.s_addr != sin->sin_addr.s_addr)
938 return EINVAL;
939
940 cmp = 1;
941 } else {
942 if (cmd == SIOCGLIFADDR) {
943 /* on getting an address, take the 1st match */
944 cmp = 0; /*XXX*/
945 } else {
946 /* on deleting an address, do exact match */
947 in_len2mask(&mask, 32);
948 sin = (struct sockaddr_in *)&iflr->addr;
949 match.s_addr = sin->sin_addr.s_addr;
950
951 cmp = 1;
952 }
953 }
954
91447636 955 ifnet_lock_shared(ifp);
1c79356b
A
956 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
957 if (ifa->ifa_addr->sa_family != AF_INET6)
958 continue;
959 if (!cmp)
960 break;
961 candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
962 candidate.s_addr &= mask.s_addr;
963 if (candidate.s_addr == match.s_addr)
964 break;
965 }
91447636 966 ifnet_lock_done(ifp);
1c79356b
A
967 if (!ifa)
968 return EADDRNOTAVAIL;
969 ia = (struct in_ifaddr *)ifa;
970
971 if (cmd == SIOCGLIFADDR) {
972 /* fill in the if_laddrreq structure */
973 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
974
975 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
976 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
977 ia->ia_dstaddr.sin_len);
978 } else
979 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
980
981 iflr->prefixlen =
982 in_mask2len(&ia->ia_sockmask.sin_addr);
983
984 iflr->flags = 0; /*XXX*/
985
986 return 0;
987 } else {
988 struct in_aliasreq ifra;
989
990 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
991 bzero(&ifra, sizeof(ifra));
992 bcopy(iflr->iflr_name, ifra.ifra_name,
993 sizeof(ifra.ifra_name));
994
995 bcopy(&ia->ia_addr, &ifra.ifra_addr,
996 ia->ia_addr.sin_len);
997 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
998 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
999 ia->ia_dstaddr.sin_len);
1000 }
1001 bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
1002 ia->ia_sockmask.sin_len);
1003
1004 return in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
1005 ifp, p);
1006 }
1007 }
1008 }
1009
1010 return EOPNOTSUPP; /*just for safety*/
1011}
1012
1013/*
1014 * Delete any existing route for an interface.
1015 */
1016void
91447636
A
1017in_ifscrub(
1018 struct ifnet *ifp,
1019 struct in_ifaddr *ia,
1020 int locked)
1c79356b
A
1021{
1022
1023 if ((ia->ia_flags & IFA_ROUTE) == 0)
1024 return;
91447636
A
1025 if (!locked)
1026 lck_mtx_lock(rt_mtx);
1c79356b 1027 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
91447636 1028 rtinit_locked(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
1c79356b 1029 else
91447636 1030 rtinit_locked(&(ia->ia_ifa), (int)RTM_DELETE, 0);
1c79356b 1031 ia->ia_flags &= ~IFA_ROUTE;
91447636
A
1032 if (!locked)
1033 lck_mtx_unlock(rt_mtx);
1c79356b
A
1034}
1035
1036/*
1037 * Initialize an interface's internet address
1038 * and routing table entry.
1039 */
1040static int
91447636
A
1041in_ifinit(
1042 struct ifnet *ifp,
1043 struct in_ifaddr *ia,
1044 struct sockaddr_in *sin,
1045 int scrub)
1c79356b 1046{
91447636 1047 u_long i = ntohl(sin->sin_addr.s_addr);
1c79356b 1048 struct sockaddr_in oldaddr;
91447636 1049 int flags = RTF_UP, error;
1c79356b 1050
1c79356b
A
1051 oldaddr = ia->ia_addr;
1052 ia->ia_addr = *sin;
1053
9bccf70c
A
1054 /*
1055 * Give the interface a chance to initialize
1056 * if this is its first address,
1057 * and to validate the address if necessary.
1058 */
1c79356b
A
1059 error = dlil_ioctl(PF_INET, ifp, SIOCSIFADDR, (caddr_t)ia);
1060 if (error == EOPNOTSUPP)
1061 error = 0;
1c79356b 1062 if (error) {
1c79356b
A
1063 ia->ia_addr = oldaddr;
1064 return (error);
1065 }
1c79356b
A
1066 if (scrub) {
1067 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
91447636 1068 in_ifscrub(ifp, ia, 0);
1c79356b
A
1069 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
1070 }
1071 if (IN_CLASSA(i))
1072 ia->ia_netmask = IN_CLASSA_NET;
1073 else if (IN_CLASSB(i))
1074 ia->ia_netmask = IN_CLASSB_NET;
1075 else
1076 ia->ia_netmask = IN_CLASSC_NET;
1077 /*
1078 * The subnet mask usually includes at least the standard network part,
1079 * but may may be smaller in the case of supernetting.
1080 * If it is set, we believe it.
1081 */
1082 if (ia->ia_subnetmask == 0) {
1083 ia->ia_subnetmask = ia->ia_netmask;
1084 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
1085 } else
1086 ia->ia_netmask &= ia->ia_subnetmask;
1087 ia->ia_net = i & ia->ia_netmask;
1088 ia->ia_subnet = i & ia->ia_subnetmask;
1089 in_socktrim(&ia->ia_sockmask);
1090 /*
1091 * Add route for the network.
1092 */
1093 ia->ia_ifa.ifa_metric = ifp->if_metric;
1094 if (ifp->if_flags & IFF_BROADCAST) {
1095 ia->ia_broadaddr.sin_addr.s_addr =
1096 htonl(ia->ia_subnet | ~ia->ia_subnetmask);
1097 ia->ia_netbroadcast.s_addr =
1098 htonl(ia->ia_net | ~ ia->ia_netmask);
1099 } else if (ifp->if_flags & IFF_LOOPBACK) {
1100 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
1101 flags |= RTF_HOST;
1102 } else if (ifp->if_flags & IFF_POINTOPOINT) {
1103 if (ia->ia_dstaddr.sin_family != AF_INET)
1104 return (0);
1105 flags |= RTF_HOST;
1106 }
1107 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
1108 ia->ia_flags |= IFA_ROUTE;
9bccf70c
A
1109 /* XXX check if the subnet route points to the same interface */
1110 if (error == EEXIST)
1111 error = 0;
1c79356b
A
1112
1113 /*
1114 * If the interface supports multicast, join the "all hosts"
1115 * multicast group on that interface.
1116 */
1117 if (ifp->if_flags & IFF_MULTICAST) {
9bccf70c 1118 struct in_multi *inm;
1c79356b
A
1119 struct in_addr addr;
1120
1121 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
91447636 1122 ifnet_lock_shared(ifp);
9bccf70c 1123 IN_LOOKUP_MULTI(addr, ifp, inm);
91447636 1124 ifnet_lock_done(ifp);
9bccf70c
A
1125 if (inm == 0)
1126 in_addmulti(&addr, ifp);
1c79356b
A
1127 }
1128 return (error);
1129}
1130
1131
1132/*
1133 * Return 1 if the address might be a local broadcast address.
1134 */
1135int
91447636
A
1136in_broadcast(
1137 struct in_addr in,
1138 struct ifnet *ifp)
1c79356b 1139{
91447636 1140 struct ifaddr *ifa;
1c79356b
A
1141 u_long t;
1142
1143 if (in.s_addr == INADDR_BROADCAST ||
1144 in.s_addr == INADDR_ANY)
1145 return 1;
1146 if ((ifp->if_flags & IFF_BROADCAST) == 0)
1147 return 0;
1148 t = ntohl(in.s_addr);
1149 /*
1150 * Look through the list of addresses for a match
1151 * with a broadcast address.
1152 */
1153#define ia ((struct in_ifaddr *)ifa)
91447636
A
1154 ifnet_lock_shared(ifp);
1155 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
1156 if (ifa->ifa_addr == NULL) {
1157 ifnet_lock_done(ifp);
0b4e3aa0 1158 return (0);
91447636 1159 }
1c79356b
A
1160 if (ifa->ifa_addr->sa_family == AF_INET &&
1161 (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
1162 in.s_addr == ia->ia_netbroadcast.s_addr ||
1163 /*
1164 * Check for old-style (host 0) broadcast.
1165 */
1166 t == ia->ia_subnet || t == ia->ia_net) &&
1167 /*
1168 * Check for an all one subnetmask. These
1169 * only exist when an interface gets a secondary
1170 * address.
1171 */
91447636
A
1172 ia->ia_subnetmask != (u_long)0xffffffff) {
1173 ifnet_lock_done(ifp);
1174 return 1;
1175 }
0b4e3aa0 1176 }
91447636 1177 ifnet_lock_done(ifp);
1c79356b
A
1178 return (0);
1179#undef ia
1180}
91447636
A
1181
1182static void
1183in_free_inm(
1184 void* ifma_protospec)
1185{
1186 struct in_multi *inm = ifma_protospec;
1187
1188 /*
1189 * No remaining claims to this record; let IGMP know that
1190 * we are leaving the multicast group.
1191 */
1192 igmp_leavegroup(inm);
1193 lck_mtx_lock(rt_mtx);
1194 LIST_REMOVE(inm, inm_link);
1195 lck_mtx_unlock(rt_mtx);
1196 FREE(inm, M_IPMADDR);
1197}
1198
1c79356b
A
1199/*
1200 * Add an address to the list of IP multicast addresses for a given interface.
1201 */
1202struct in_multi *
91447636
A
1203in_addmulti(
1204 struct in_addr *ap,
1205 struct ifnet *ifp)
1c79356b 1206{
91447636 1207 struct in_multi *inm;
1c79356b
A
1208 int error;
1209 struct sockaddr_in sin;
1210 struct ifmultiaddr *ifma;
1c79356b
A
1211
1212 /*
1213 * Call generic routine to add membership or increment
1214 * refcount. It wants addresses in the form of a sockaddr,
1215 * so we build one here (being careful to zero the unused bytes).
1216 */
1217 bzero(&sin, sizeof sin);
1218 sin.sin_family = AF_INET;
1219 sin.sin_len = sizeof sin;
1220 sin.sin_addr = *ap;
1221 error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma);
1222 if (error) {
1c79356b
A
1223 return 0;
1224 }
1225
1226 /*
1227 * If ifma->ifma_protospec is null, then if_addmulti() created
1228 * a new record. Otherwise, we are done.
1229 */
9bccf70c 1230 if (ifma->ifma_protospec != 0) {
1c79356b 1231 return ifma->ifma_protospec;
9bccf70c 1232 }
1c79356b 1233
0b4e3aa0 1234 inm = (struct in_multi *) _MALLOC(sizeof(*inm), M_IPMADDR, M_WAITOK);
1c79356b 1235 if (inm == NULL) {
1c79356b
A
1236 return (NULL);
1237 }
1238
1239 bzero(inm, sizeof *inm);
1240 inm->inm_addr = *ap;
1241 inm->inm_ifp = ifp;
1242 inm->inm_ifma = ifma;
91447636
A
1243 lck_mtx_lock(rt_mtx);
1244 if (ifma->ifma_protospec == NULL) {
1245 ifma->ifma_protospec = inm;
1246 ifma->ifma_free = in_free_inm;
1247 LIST_INSERT_HEAD(&in_multihead, inm, inm_link);
1248 }
1249 lck_mtx_unlock(rt_mtx);
1250
1251 if (ifma->ifma_protospec != inm) {
1252 _FREE(inm, M_IPMADDR);
1253 return ifma->ifma_protospec;
1254 }
1c79356b
A
1255
1256 /*
1257 * Let IGMP know that we have joined a new IP multicast group.
1258 */
55e303ae
A
1259 error = igmp_joingroup(inm);
1260 if (error) {
91447636
A
1261 char addrbuf[16];
1262
1263 /*
1264 * We can't free the inm because someone else may already be
1265 * using it. Once we put it in to ifma->ifma_protospec, it
1266 * must exist as long as the ifma does. Might be nice to flag
1267 * the error so we can try igmp_joingroup the next time through.
1268 */
1269 log(LOG_ERR, "igmp_joingroup error %d joining multicast %s on %s%d\n",
1270 error, inet_ntop(AF_INET, &sin.sin_addr, addrbuf, sizeof(addrbuf)),
1271 ifp->if_name, ifp->if_unit);
55e303ae 1272 }
91447636 1273
1c79356b
A
1274 return (inm);
1275}
1276
1277/*
1278 * Delete a multicast address record.
1279 */
1280void
91447636
A
1281in_delmulti(
1282 struct in_multi **inm)
1c79356b 1283{
91447636
A
1284 struct in_multi *inm2;
1285
1286 lck_mtx_lock(rt_mtx);
1287 LIST_FOREACH(inm2, &in_multihead, inm_link) {
1288 if (inm2 == *inm)
1289 break;
1290 }
1291 if (inm2 != *inm) {
1292 lck_mtx_unlock(rt_mtx);
1293 printf("in_delmulti - ignorning invalid inm (0x%x)\n", *inm);
1294 return;
1295 }
1296 lck_mtx_unlock(rt_mtx);
9bccf70c
A
1297
1298 /* We intentionally do this a bit differently than BSD */
91447636
A
1299 if ((*inm)->inm_ifma) {
1300 if_delmultiaddr((*inm)->inm_ifma, 0);
1301 ifma_release((*inm)->inm_ifma);
1c79356b 1302 }
91447636 1303 *inm = NULL;
1c79356b 1304}
91447636
A
1305
1306#if !NFSCLIENT
1307int
1308inet_aton(char * cp, struct in_addr * pin)
1309{
1310 u_char * b = (char *)pin;
1311 int i;
1312 char * p;
1313
1314 for (p = cp, i = 0; i < 4; i++) {
1315 u_long l = strtoul(p, 0, 0);
1316 if (l > 255)
1317 return (FALSE);
1318 b[i] = l;
1319 p = strchr(p, '.');
1320 if (i < 3 && p == NULL)
1321 return (FALSE);
1322 p++;
1323 }
1324 return (TRUE);
1325}
1326#endif