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