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