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