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