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