]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/in.c
1389cf3a2a6391dbcec9e43295e7d997bcaf3a9f
[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
109
110 /*
111 * Return 1 if an internet address is for a ``local'' host
112 * (one to which we have a connection). If subnetsarelocal
113 * is true, this includes other subnets of the local net.
114 * Otherwise, it includes only the directly-connected (sub)nets.
115 */
116 int
117 in_localaddr(in)
118 struct in_addr in;
119 {
120 register u_long i = ntohl(in.s_addr);
121 register struct in_ifaddr *ia;
122
123 if (subnetsarelocal) {
124 for (ia = in_ifaddrhead.tqh_first; ia;
125 ia = ia->ia_link.tqe_next)
126 if ((i & ia->ia_netmask) == ia->ia_net)
127 return (1);
128 } else {
129 for (ia = in_ifaddrhead.tqh_first; ia;
130 ia = ia->ia_link.tqe_next)
131 if ((i & ia->ia_subnetmask) == ia->ia_subnet)
132 return (1);
133 }
134 return (0);
135 }
136
137 /*
138 * Determine whether an IP address is in a reserved set of addresses
139 * that may not be forwarded, or whether datagrams to that destination
140 * may be forwarded.
141 */
142 int
143 in_canforward(in)
144 struct in_addr in;
145 {
146 register u_long i = ntohl(in.s_addr);
147 register u_long net;
148
149 if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i))
150 return (0);
151 if (IN_CLASSA(i)) {
152 net = i & IN_CLASSA_NET;
153 if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
154 return (0);
155 }
156 return (1);
157 }
158
159 /*
160 * Trim a mask in a sockaddr
161 */
162 static void
163 in_socktrim(ap)
164 struct sockaddr_in *ap;
165 {
166 register char *cplim = (char *) &ap->sin_addr;
167 register char *cp = (char *) (&ap->sin_addr + 1);
168
169 ap->sin_len = 0;
170 while (--cp >= cplim)
171 if (*cp) {
172 (ap)->sin_len = cp - (char *) (ap) + 1;
173 break;
174 }
175 }
176
177 static int
178 in_mask2len(mask)
179 struct in_addr *mask;
180 {
181 int x, y;
182 u_char *p;
183
184 p = (u_char *)mask;
185 for (x = 0; x < sizeof(*mask); x++) {
186 if (p[x] != 0xff)
187 break;
188 }
189 y = 0;
190 if (x < sizeof(*mask)) {
191 for (y = 0; y < 8; y++) {
192 if ((p[x] & (0x80 >> y)) == 0)
193 break;
194 }
195 }
196 return x * 8 + y;
197 }
198
199 static void
200 in_len2mask(mask, len)
201 struct in_addr *mask;
202 int len;
203 {
204 int i;
205 u_char *p;
206
207 p = (u_char *)mask;
208 bzero(mask, sizeof(*mask));
209 for (i = 0; i < len / 8; i++)
210 p[i] = 0xff;
211 if (len % 8)
212 p[i] = (0xff00 >> (len % 8)) & 0xff;
213 }
214
215 static int in_interfaces; /* number of external internet interfaces */
216
217 /*
218 * Generic internet control operations (ioctl's).
219 * Ifp is 0 if not an interface-specific ioctl.
220 */
221 /* ARGSUSED */
222 int
223 in_control(so, cmd, data, ifp, p)
224 struct socket *so;
225 u_long cmd;
226 caddr_t data;
227 register struct ifnet *ifp;
228 struct proc *p;
229 {
230 register struct ifreq *ifr = (struct ifreq *)data;
231 register struct in_ifaddr *ia = 0, *iap;
232 register struct ifaddr *ifa;
233 struct in_ifaddr *oia;
234 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
235 struct sockaddr_in oldaddr;
236 int error, hostIsNew, maskIsNew, s;
237 u_long i, dl_tag;
238 struct kev_msg ev_msg;
239 struct kev_in_data in_event_data;
240
241 #if NGIF > 0
242 if (ifp && ifp->if_type == IFT_GIF) {
243 switch (cmd) {
244 case SIOCSIFPHYADDR:
245 #if 1
246 if (p &&
247 (error = suser(p->p_ucred, &p->p_acflag)) != 0)
248 return(error);
249 #else
250 if ((so->so_state & SS_PRIV) == 0)
251 return (EPERM);
252 #endif
253 case SIOCGIFPSRCADDR:
254 case SIOCGIFPDSTADDR:
255 if (strcmp(ifp->if_name, "gif") == 0)
256 dl_tag = gif_attach_inet(ifp);
257 return gif_ioctl(ifp, cmd, data);
258 }
259 }
260 #endif
261 #if NFAITH > 0
262 if (ifp && ifp->if_type == IFT_FAITH)
263 dl_tag = faith_attach_inet(ifp);
264 #endif
265
266 switch (cmd) {
267 case SIOCALIFADDR:
268 case SIOCDLIFADDR:
269 #if 1
270 if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0)
271 return error;
272 #else
273 if ((so->so_state & SS_PRIV) == 0)
274 return (EPERM);
275 #endif
276 /*fall through*/
277 case SIOCGLIFADDR:
278 if (!ifp)
279 return EINVAL;
280 return in_lifaddr_ioctl(so, cmd, data, ifp, p);
281 }
282
283 /*
284 * Find address for this interface, if it exists.
285 *
286 * If an alias address was specified, find that one instead of
287 * the first one on the interface.
288 */
289 if (ifp)
290 for (iap = in_ifaddrhead.tqh_first; iap;
291 iap = iap->ia_link.tqe_next)
292 if (iap->ia_ifp == ifp) {
293 if (((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr ==
294 iap->ia_addr.sin_addr.s_addr) {
295 ia = iap;
296 break;
297 } else if (ia == NULL) {
298 ia = iap;
299 if (ifr->ifr_addr.sa_family != AF_INET)
300 break;
301 }
302 }
303
304 switch (cmd) {
305
306 case SIOCAIFADDR:
307 case SIOCDIFADDR:
308 if (ifp == 0)
309 return (EADDRNOTAVAIL);
310 if (ifra->ifra_addr.sin_family == AF_INET) {
311 for (oia = ia; ia; ia = ia->ia_link.tqe_next) {
312 if (ia->ia_ifp == ifp &&
313 ia->ia_addr.sin_addr.s_addr ==
314 ifra->ifra_addr.sin_addr.s_addr)
315 break;
316 }
317 if ((ifp->if_flags & IFF_POINTOPOINT)
318 && (cmd == SIOCAIFADDR)
319 && (ifra->ifra_dstaddr.sin_addr.s_addr
320 == INADDR_ANY)) {
321 return EDESTADDRREQ;
322 }
323 }
324 if (cmd == SIOCDIFADDR && ia == 0)
325 return (EADDRNOTAVAIL);
326 /* FALLTHROUGH */
327 case SIOCSIFADDR:
328 case SIOCSIFNETMASK:
329 case SIOCSIFDSTADDR:
330
331 #if ISFB31
332 if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0)
333 return error;
334 #else
335 if ((so->so_state & SS_PRIV) == 0)
336 return (EPERM);
337 #endif
338
339 if (ifp == 0)
340 return (EADDRNOTAVAIL);
341 if (ia == (struct in_ifaddr *)0) {
342 ia = (struct in_ifaddr *)
343 _MALLOC(sizeof *ia, M_IFADDR, M_WAITOK);
344 if (ia == (struct in_ifaddr *)NULL)
345 return (ENOBUFS);
346 bzero((caddr_t)ia, sizeof *ia);
347 /*
348 * Protect from ipintr() traversing address list
349 * while we're modifying it.
350 */
351 s = splnet();
352
353 TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_link);
354 ifa = &ia->ia_ifa;
355 TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
356
357 /*
358 * Temorary code for protocol attachment XXX
359 */
360
361 if (strcmp(ifp->if_name, "en") == 0)
362 dl_tag = ether_attach_inet(ifp);
363
364 if (strcmp(ifp->if_name, "lo") == 0)
365 dl_tag = lo_attach_inet(ifp);
366 /* End of temp code */
367
368 ifa->ifa_dlt = dl_tag;
369 ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
370 ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
371 ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
372 ia->ia_sockmask.sin_len = 8;
373 if (ifp->if_flags & IFF_BROADCAST) {
374 ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
375 ia->ia_broadaddr.sin_family = AF_INET;
376 }
377 ia->ia_ifp = ifp;
378 if (!(ifp->if_flags & IFF_LOOPBACK))
379 in_interfaces++;
380 splx(s);
381 }
382 break;
383
384 case SIOCSIFBRDADDR:
385 #if ISFB31
386 if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0)
387 return error;
388 #else
389 if ((so->so_state & SS_PRIV) == 0)
390 return (EPERM);
391 #endif
392 /* FALLTHROUGH */
393
394 case SIOCGIFADDR:
395 case SIOCGIFNETMASK:
396 case SIOCGIFDSTADDR:
397 case SIOCGIFBRDADDR:
398 if (ia == (struct in_ifaddr *)0)
399 return (EADDRNOTAVAIL);
400 break;
401 }
402 switch (cmd) {
403
404 case SIOCGIFADDR:
405 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
406 break;
407
408 case SIOCGIFBRDADDR:
409 if ((ifp->if_flags & IFF_BROADCAST) == 0)
410 return (EINVAL);
411 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
412 break;
413
414 case SIOCGIFDSTADDR:
415 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
416 return (EINVAL);
417 *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
418 break;
419
420 case SIOCGIFNETMASK:
421 *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
422 break;
423
424 case SIOCSIFDSTADDR:
425 if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
426 return (EINVAL);
427 oldaddr = ia->ia_dstaddr;
428 ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
429 error = dlil_ioctl(PF_INET, ifp, SIOCSIFDSTADDR, (caddr_t)ia);
430 if (error == EOPNOTSUPP)
431 error = 0;
432
433 if (error) {
434 ia->ia_dstaddr = oldaddr;
435 return error;
436 }
437
438 ev_msg.vendor_code = KEV_VENDOR_APPLE;
439 ev_msg.kev_class = KEV_NETWORK_CLASS;
440 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
441
442 ev_msg.event_code = KEV_INET_SIFDSTADDR;
443
444 if (ia->ia_ifa.ifa_dstaddr)
445 in_event_data.ia_dstaddr =
446 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
447 else
448 in_event_data.ia_dstaddr.s_addr = 0;
449
450 in_event_data.ia_addr = ia->ia_addr.sin_addr;
451 in_event_data.ia_net = ia->ia_net;
452 in_event_data.ia_netmask = ia->ia_netmask;
453 in_event_data.ia_subnet = ia->ia_subnet;
454 in_event_data.ia_subnetmask = ia->ia_subnetmask;
455 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
456 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
457 in_event_data.link_data.if_family = ifp->if_family;
458 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
459
460 ev_msg.dv[0].data_ptr = &in_event_data;
461 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
462 ev_msg.dv[1].data_length = 0;
463
464 kev_post_msg(&ev_msg);
465
466
467 if (ia->ia_flags & IFA_ROUTE) {
468 ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
469 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
470 ia->ia_ifa.ifa_dstaddr =
471 (struct sockaddr *)&ia->ia_dstaddr;
472 rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
473 }
474 break;
475
476 case SIOCSIFBRDADDR:
477 if ((ifp->if_flags & IFF_BROADCAST) == 0)
478 return (EINVAL);
479 ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
480
481 ev_msg.vendor_code = KEV_VENDOR_APPLE;
482 ev_msg.kev_class = KEV_NETWORK_CLASS;
483 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
484
485 ev_msg.event_code = KEV_INET_SIFBRDADDR;
486
487 if (ia->ia_ifa.ifa_dstaddr)
488 in_event_data.ia_dstaddr =
489 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
490 else
491 in_event_data.ia_dstaddr.s_addr = 0;
492
493 in_event_data.ia_addr = ia->ia_addr.sin_addr;
494 in_event_data.ia_net = ia->ia_net;
495 in_event_data.ia_netmask = ia->ia_netmask;
496 in_event_data.ia_subnet = ia->ia_subnet;
497 in_event_data.ia_subnetmask = ia->ia_subnetmask;
498 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
499 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
500 in_event_data.link_data.if_family = ifp->if_family;
501 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
502
503 ev_msg.dv[0].data_ptr = &in_event_data;
504 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
505 ev_msg.dv[1].data_length = 0;
506
507 kev_post_msg(&ev_msg);
508
509 break;
510
511 case SIOCSIFADDR:
512 return (in_ifinit(ifp, ia,
513 (struct sockaddr_in *) &ifr->ifr_addr, 1));
514
515 case SIOCSIFNETMASK:
516 i = ifra->ifra_addr.sin_addr.s_addr;
517 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
518 ev_msg.vendor_code = KEV_VENDOR_APPLE;
519 ev_msg.kev_class = KEV_NETWORK_CLASS;
520 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
521
522 ev_msg.event_code = KEV_INET_SIFNETMASK;
523
524 if (ia->ia_ifa.ifa_dstaddr)
525 in_event_data.ia_dstaddr =
526 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
527 else
528 in_event_data.ia_dstaddr.s_addr = 0;
529
530 in_event_data.ia_addr = ia->ia_addr.sin_addr;
531 in_event_data.ia_net = ia->ia_net;
532 in_event_data.ia_netmask = ia->ia_netmask;
533 in_event_data.ia_subnet = ia->ia_subnet;
534 in_event_data.ia_subnetmask = ia->ia_subnetmask;
535 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
536 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
537 in_event_data.link_data.if_family = ifp->if_family;
538 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
539
540 ev_msg.dv[0].data_ptr = &in_event_data;
541 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
542 ev_msg.dv[1].data_length = 0;
543
544 kev_post_msg(&ev_msg);
545
546 break;
547
548 case SIOCAIFADDR:
549 maskIsNew = 0;
550 hostIsNew = 1;
551 error = 0;
552 if (ia->ia_addr.sin_family == AF_INET) {
553 if (ifra->ifra_addr.sin_len == 0) {
554 ifra->ifra_addr = ia->ia_addr;
555 hostIsNew = 0;
556 } else if (ifra->ifra_addr.sin_addr.s_addr ==
557 ia->ia_addr.sin_addr.s_addr)
558 hostIsNew = 0;
559 }
560 if (ifra->ifra_mask.sin_len) {
561 in_ifscrub(ifp, ia);
562 ia->ia_sockmask = ifra->ifra_mask;
563 ia->ia_subnetmask =
564 ntohl(ia->ia_sockmask.sin_addr.s_addr);
565 maskIsNew = 1;
566 }
567 if ((ifp->if_flags & IFF_POINTOPOINT) &&
568 (ifra->ifra_dstaddr.sin_family == AF_INET)) {
569 in_ifscrub(ifp, ia);
570 ia->ia_dstaddr = ifra->ifra_dstaddr;
571 maskIsNew = 1; /* We lie; but the effect's the same */
572 }
573 if (ifra->ifra_addr.sin_family == AF_INET &&
574 (hostIsNew || maskIsNew)) {
575 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
576 }
577 if ((ifp->if_flags & IFF_BROADCAST) &&
578 (ifra->ifra_broadaddr.sin_family == AF_INET))
579 ia->ia_broadaddr = ifra->ifra_broadaddr;
580
581 /*
582 * Report event.
583 */
584
585 if (error == 0) {
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 if (hostIsNew)
591 ev_msg.event_code = KEV_INET_NEW_ADDR;
592 else
593 ev_msg.event_code = KEV_INET_CHANGED_ADDR;
594
595 if (ia->ia_ifa.ifa_dstaddr)
596 in_event_data.ia_dstaddr =
597 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
598 else
599 in_event_data.ia_dstaddr.s_addr = 0;
600
601 in_event_data.ia_addr = ia->ia_addr.sin_addr;
602 in_event_data.ia_net = ia->ia_net;
603 in_event_data.ia_netmask = ia->ia_netmask;
604 in_event_data.ia_subnet = ia->ia_subnet;
605 in_event_data.ia_subnetmask = ia->ia_subnetmask;
606 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
607 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
608 in_event_data.link_data.if_family = ifp->if_family;
609 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
610
611 ev_msg.dv[0].data_ptr = &in_event_data;
612 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
613 ev_msg.dv[1].data_length = 0;
614
615 kev_post_msg(&ev_msg);
616 }
617
618 return (error);
619
620 case SIOCDIFADDR:
621 ev_msg.vendor_code = KEV_VENDOR_APPLE;
622 ev_msg.kev_class = KEV_NETWORK_CLASS;
623 ev_msg.kev_subclass = KEV_INET_SUBCLASS;
624
625 ev_msg.event_code = KEV_INET_ADDR_DELETED;
626
627 if (ia->ia_ifa.ifa_dstaddr)
628 in_event_data.ia_dstaddr =
629 ((struct sockaddr_in *)ia->ia_ifa.ifa_dstaddr)->sin_addr;
630 else
631 in_event_data.ia_dstaddr.s_addr = 0;
632
633 in_event_data.ia_addr = ia->ia_addr.sin_addr;
634 in_event_data.ia_net = ia->ia_net;
635 in_event_data.ia_netmask = ia->ia_netmask;
636 in_event_data.ia_subnet = ia->ia_subnet;
637 in_event_data.ia_subnetmask = ia->ia_subnetmask;
638 in_event_data.ia_netbroadcast = ia->ia_netbroadcast;
639 strncpy(&in_event_data.link_data.if_name[0], ifp->if_name, IFNAMSIZ);
640 in_event_data.link_data.if_family = ifp->if_family;
641 in_event_data.link_data.if_unit = (unsigned long) ifp->if_unit;
642
643 ev_msg.dv[0].data_ptr = &in_event_data;
644 ev_msg.dv[0].data_length = sizeof(struct kev_in_data);
645 ev_msg.dv[1].data_length = 0;
646
647 kev_post_msg(&ev_msg);
648
649 in_ifscrub(ifp, ia);
650 /*
651 * Protect from ipintr() traversing address list
652 * while we're modifying it.
653 */
654 s = splnet();
655
656 ifa = &ia->ia_ifa;
657 TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
658 oia = ia;
659 TAILQ_REMOVE(&in_ifaddrhead, oia, ia_link);
660 IFAFREE(&oia->ia_ifa);
661 splx(s);
662 break;
663
664 case SIOCSETOT: {
665 /*
666 * Inspiration from tcp_ctloutput() and ip_ctloutput()
667 */
668 struct inpcb *inp, *cloned_inp;
669 int error = 0;
670 int cloned_fd = *(int *)data;
671
672 s = splnet(); /* XXX */
673 inp = sotoinpcb(so);
674 if (inp == NULL) {
675 splx(s);
676 break;
677 }
678
679 /* let's make sure it's either -1 or a valid file descriptor */
680 if (cloned_fd != -1) {
681 struct socket *cloned_so;
682 struct file *cloned_fp;
683 error = getsock(p->p_fd, cloned_fd, &cloned_fp);
684 if (error){
685 splx(s);
686 break;
687 }
688 cloned_so = (struct socket *)cloned_fp->f_data;
689 cloned_inp = sotoinpcb(cloned_so);
690 } else {
691 cloned_inp = NULL;
692 }
693
694 if (cloned_inp == NULL) {
695 /* OT always uses IP_PORTRANGE_HIGH */
696 inp->inp_flags &= ~(INP_LOWPORT);
697 inp->inp_flags |= INP_HIGHPORT;
698 /* For UDP, OT allows broadcast by default */
699 if (so->so_type == SOCK_DGRAM)
700 so->so_options |= SO_BROADCAST;
701 /* For TCP we want to see MSG_OOB when receive urgent data */
702 else if (so->so_type == SOCK_STREAM)
703 so->so_options |= SO_WANTOOBFLAG;
704 } else {
705 inp->inp_ip_tos = cloned_inp->inp_ip_tos;
706 inp->inp_ip_ttl = cloned_inp->inp_ip_ttl;
707 inp->inp_flags = cloned_inp->inp_flags;
708
709 /* Multicast options */
710 if (cloned_inp->inp_moptions != NULL) {
711 int i;
712 struct ip_moptions *cloned_imo = cloned_inp->inp_moptions;
713 struct ip_moptions *imo = inp->inp_moptions;
714
715 if (imo == NULL) {
716 /*
717 * No multicast option buffer attached to the pcb;
718 * allocate one.
719 */
720 splx();
721 imo = (struct ip_moptions*)
722 _MALLOC(sizeof(*imo), M_IPMOPTS, M_WAITOK);
723 if (imo == NULL) {
724 error = ENOBUFS;
725 break;
726 }
727 s = splnet(); /* XXX */
728 inp->inp_moptions = imo;
729 }
730 imo->imo_multicast_ifp = cloned_imo->imo_multicast_ifp;
731 imo->imo_multicast_vif = cloned_imo->imo_multicast_vif;
732 imo->imo_multicast_ttl = cloned_imo->imo_multicast_ttl;
733 imo->imo_multicast_loop = cloned_imo->imo_multicast_loop;
734 imo->imo_num_memberships = cloned_imo->imo_num_memberships;
735 for (i = 0; i < cloned_imo->imo_num_memberships; i++) {
736 imo->imo_membership[i] =
737 in_addmulti(&cloned_imo->imo_membership[i]->inm_addr,
738 cloned_imo->imo_membership[i]->inm_ifp);
739 }
740 }
741 }
742 splx(s);
743 break;
744 }
745
746 default:
747 return EOPNOTSUPP;
748
749 }
750 return (0);
751 }
752
753 /*
754 * SIOC[GAD]LIFADDR.
755 * SIOCGLIFADDR: get first address. (???)
756 * SIOCGLIFADDR with IFLR_PREFIX:
757 * get first address that matches the specified prefix.
758 * SIOCALIFADDR: add the specified address.
759 * SIOCALIFADDR with IFLR_PREFIX:
760 * EINVAL since we can't deduce hostid part of the address.
761 * SIOCDLIFADDR: delete the specified address.
762 * SIOCDLIFADDR with IFLR_PREFIX:
763 * delete the first address that matches the specified prefix.
764 * return values:
765 * EINVAL on invalid parameters
766 * EADDRNOTAVAIL on prefix match failed/specified address not found
767 * other values may be returned from in_ioctl()
768 */
769 static int
770 in_lifaddr_ioctl(so, cmd, data, ifp, p)
771 struct socket *so;
772 u_long cmd;
773 caddr_t data;
774 struct ifnet *ifp;
775 struct proc *p;
776 {
777 struct if_laddrreq *iflr = (struct if_laddrreq *)data;
778 struct ifaddr *ifa;
779
780 /* sanity checks */
781 if (!data || !ifp) {
782 panic("invalid argument to in_lifaddr_ioctl");
783 /*NOTRECHED*/
784 }
785
786 switch (cmd) {
787 case SIOCGLIFADDR:
788 /* address must be specified on GET with IFLR_PREFIX */
789 if ((iflr->flags & IFLR_PREFIX) == 0)
790 break;
791 /*FALLTHROUGH*/
792 case SIOCALIFADDR:
793 case SIOCDLIFADDR:
794 /* address must be specified on ADD and DELETE */
795 if (iflr->addr.ss_family != AF_INET)
796 return EINVAL;
797 if (iflr->addr.ss_len != sizeof(struct sockaddr_in))
798 return EINVAL;
799 /* XXX need improvement */
800 if (iflr->dstaddr.ss_family
801 && iflr->dstaddr.ss_family != AF_INET)
802 return EINVAL;
803 if (iflr->dstaddr.ss_family
804 && iflr->dstaddr.ss_len != sizeof(struct sockaddr_in))
805 return EINVAL;
806 break;
807 default: /*shouldn't happen*/
808 #if 0
809 panic("invalid cmd to in_lifaddr_ioctl");
810 /*NOTREACHED*/
811 #else
812 return EOPNOTSUPP;
813 #endif
814 }
815 if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
816 return EINVAL;
817
818 switch (cmd) {
819 case SIOCALIFADDR:
820 {
821 struct in_aliasreq ifra;
822
823 if (iflr->flags & IFLR_PREFIX)
824 return EINVAL;
825
826 /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
827 bzero(&ifra, sizeof(ifra));
828 bcopy(iflr->iflr_name, ifra.ifra_name,
829 sizeof(ifra.ifra_name));
830
831 bcopy(&iflr->addr, &ifra.ifra_addr, iflr->addr.ss_len);
832
833 if (iflr->dstaddr.ss_family) { /*XXX*/
834 bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
835 iflr->dstaddr.ss_len);
836 }
837
838 ifra.ifra_mask.sin_family = AF_INET;
839 ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
840 in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
841
842 return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp, p);
843 }
844 case SIOCGLIFADDR:
845 case SIOCDLIFADDR:
846 {
847 struct in_ifaddr *ia;
848 struct in_addr mask, candidate, match;
849 struct sockaddr_in *sin;
850 int cmp;
851
852 bzero(&mask, sizeof(mask));
853 if (iflr->flags & IFLR_PREFIX) {
854 /* lookup a prefix rather than address. */
855 in_len2mask(&mask, iflr->prefixlen);
856
857 sin = (struct sockaddr_in *)&iflr->addr;
858 match.s_addr = sin->sin_addr.s_addr;
859 match.s_addr &= mask.s_addr;
860
861 /* if you set extra bits, that's wrong */
862 if (match.s_addr != sin->sin_addr.s_addr)
863 return EINVAL;
864
865 cmp = 1;
866 } else {
867 if (cmd == SIOCGLIFADDR) {
868 /* on getting an address, take the 1st match */
869 cmp = 0; /*XXX*/
870 } else {
871 /* on deleting an address, do exact match */
872 in_len2mask(&mask, 32);
873 sin = (struct sockaddr_in *)&iflr->addr;
874 match.s_addr = sin->sin_addr.s_addr;
875
876 cmp = 1;
877 }
878 }
879
880 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
881 if (ifa->ifa_addr->sa_family != AF_INET6)
882 continue;
883 if (!cmp)
884 break;
885 candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
886 candidate.s_addr &= mask.s_addr;
887 if (candidate.s_addr == match.s_addr)
888 break;
889 }
890 if (!ifa)
891 return EADDRNOTAVAIL;
892 ia = (struct in_ifaddr *)ifa;
893
894 if (cmd == SIOCGLIFADDR) {
895 /* fill in the if_laddrreq structure */
896 bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
897
898 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
899 bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
900 ia->ia_dstaddr.sin_len);
901 } else
902 bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
903
904 iflr->prefixlen =
905 in_mask2len(&ia->ia_sockmask.sin_addr);
906
907 iflr->flags = 0; /*XXX*/
908
909 return 0;
910 } else {
911 struct in_aliasreq ifra;
912
913 /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
914 bzero(&ifra, sizeof(ifra));
915 bcopy(iflr->iflr_name, ifra.ifra_name,
916 sizeof(ifra.ifra_name));
917
918 bcopy(&ia->ia_addr, &ifra.ifra_addr,
919 ia->ia_addr.sin_len);
920 if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
921 bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
922 ia->ia_dstaddr.sin_len);
923 }
924 bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
925 ia->ia_sockmask.sin_len);
926
927 return in_control(so, SIOCDIFADDR, (caddr_t)&ifra,
928 ifp, p);
929 }
930 }
931 }
932
933 return EOPNOTSUPP; /*just for safety*/
934 }
935
936 /*
937 * Delete any existing route for an interface.
938 */
939 void
940 in_ifscrub(ifp, ia)
941 register struct ifnet *ifp;
942 register struct in_ifaddr *ia;
943 {
944
945 if ((ia->ia_flags & IFA_ROUTE) == 0)
946 return;
947 if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
948 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
949 else
950 rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
951 ia->ia_flags &= ~IFA_ROUTE;
952 }
953
954 /*
955 * Initialize an interface's internet address
956 * and routing table entry.
957 */
958 static int
959 in_ifinit(ifp, ia, sin, scrub)
960 register struct ifnet *ifp;
961 register struct in_ifaddr *ia;
962 struct sockaddr_in *sin;
963 int scrub;
964 {
965 register u_long i = ntohl(sin->sin_addr.s_addr);
966 struct sockaddr_in oldaddr;
967 int s = splimp(), flags = RTF_UP, error;
968 u_long dl_tag;
969
970
971
972 oldaddr = ia->ia_addr;
973 ia->ia_addr = *sin;
974
975
976 error = dlil_ioctl(PF_INET, ifp, SIOCSIFADDR, (caddr_t)ia);
977 if (error == EOPNOTSUPP)
978 error = 0;
979
980 if (error) {
981 splx(s);
982 ia->ia_addr = oldaddr;
983 return (error);
984 }
985
986 splx(s);
987 if (scrub) {
988 ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
989 in_ifscrub(ifp, ia);
990 ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
991 }
992 if (IN_CLASSA(i))
993 ia->ia_netmask = IN_CLASSA_NET;
994 else if (IN_CLASSB(i))
995 ia->ia_netmask = IN_CLASSB_NET;
996 else
997 ia->ia_netmask = IN_CLASSC_NET;
998 /*
999 * The subnet mask usually includes at least the standard network part,
1000 * but may may be smaller in the case of supernetting.
1001 * If it is set, we believe it.
1002 */
1003 if (ia->ia_subnetmask == 0) {
1004 ia->ia_subnetmask = ia->ia_netmask;
1005 ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
1006 } else
1007 ia->ia_netmask &= ia->ia_subnetmask;
1008 ia->ia_net = i & ia->ia_netmask;
1009 ia->ia_subnet = i & ia->ia_subnetmask;
1010 in_socktrim(&ia->ia_sockmask);
1011 /*
1012 * Add route for the network.
1013 */
1014 ia->ia_ifa.ifa_metric = ifp->if_metric;
1015 if (ifp->if_flags & IFF_BROADCAST) {
1016 ia->ia_broadaddr.sin_addr.s_addr =
1017 htonl(ia->ia_subnet | ~ia->ia_subnetmask);
1018 ia->ia_netbroadcast.s_addr =
1019 htonl(ia->ia_net | ~ ia->ia_netmask);
1020 } else if (ifp->if_flags & IFF_LOOPBACK) {
1021 ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
1022 flags |= RTF_HOST;
1023 } else if (ifp->if_flags & IFF_POINTOPOINT) {
1024 if (ia->ia_dstaddr.sin_family != AF_INET)
1025 return (0);
1026 flags |= RTF_HOST;
1027 }
1028 if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
1029 ia->ia_flags |= IFA_ROUTE;
1030
1031 /*
1032 * If the interface supports multicast, join the "all hosts"
1033 * multicast group on that interface.
1034 */
1035 if (ifp->if_flags & IFF_MULTICAST) {
1036 struct in_addr addr;
1037
1038 addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
1039 in_addmulti(&addr, ifp);
1040 }
1041 return (error);
1042 }
1043
1044
1045 /*
1046 * Return 1 if the address might be a local broadcast address.
1047 */
1048 int
1049 in_broadcast(in, ifp)
1050 struct in_addr in;
1051 struct ifnet *ifp;
1052 {
1053 register struct ifaddr *ifa;
1054 u_long t;
1055
1056 if (in.s_addr == INADDR_BROADCAST ||
1057 in.s_addr == INADDR_ANY)
1058 return 1;
1059 if ((ifp->if_flags & IFF_BROADCAST) == 0)
1060 return 0;
1061 t = ntohl(in.s_addr);
1062 /*
1063 * Look through the list of addresses for a match
1064 * with a broadcast address.
1065 */
1066 #define ia ((struct in_ifaddr *)ifa)
1067 for (ifa = ifp->if_addrhead.tqh_first; ifa;
1068 ifa = ifa->ifa_link.tqe_next)
1069 if (ifa->ifa_addr->sa_family == AF_INET &&
1070 (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||
1071 in.s_addr == ia->ia_netbroadcast.s_addr ||
1072 /*
1073 * Check for old-style (host 0) broadcast.
1074 */
1075 t == ia->ia_subnet || t == ia->ia_net) &&
1076 /*
1077 * Check for an all one subnetmask. These
1078 * only exist when an interface gets a secondary
1079 * address.
1080 */
1081 ia->ia_subnetmask != (u_long)0xffffffff)
1082 return 1;
1083 return (0);
1084 #undef ia
1085 }
1086 /*
1087 * Add an address to the list of IP multicast addresses for a given interface.
1088 */
1089 struct in_multi *
1090 in_addmulti(ap, ifp)
1091 register struct in_addr *ap;
1092 register struct ifnet *ifp;
1093 {
1094 register struct in_multi *inm;
1095 int error;
1096 struct sockaddr_in sin;
1097 struct ifmultiaddr *ifma;
1098 int s = splnet();
1099
1100 /*
1101 * Call generic routine to add membership or increment
1102 * refcount. It wants addresses in the form of a sockaddr,
1103 * so we build one here (being careful to zero the unused bytes).
1104 */
1105 bzero(&sin, sizeof sin);
1106 sin.sin_family = AF_INET;
1107 sin.sin_len = sizeof sin;
1108 sin.sin_addr = *ap;
1109 error = if_addmulti(ifp, (struct sockaddr *)&sin, &ifma);
1110 if (error) {
1111 splx(s);
1112 return 0;
1113 }
1114
1115 /*
1116 * If ifma->ifma_protospec is null, then if_addmulti() created
1117 * a new record. Otherwise, we are done.
1118 */
1119 if (ifma->ifma_protospec != 0)
1120 return ifma->ifma_protospec;
1121
1122 /* XXX - if_addmulti uses M_WAITOK. Can this really be called
1123 at interrupt time? If so, need to fix if_addmulti. XXX */
1124 inm = (struct in_multi *) _MALLOC(sizeof(*inm), M_IPMADDR, M_NOWAIT);
1125 if (inm == NULL) {
1126 splx(s);
1127 return (NULL);
1128 }
1129
1130 bzero(inm, sizeof *inm);
1131 inm->inm_addr = *ap;
1132 inm->inm_ifp = ifp;
1133 inm->inm_ifma = ifma;
1134 ifma->ifma_protospec = inm;
1135 LIST_INSERT_HEAD(&in_multihead, inm, inm_link);
1136
1137 /*
1138 * Let IGMP know that we have joined a new IP multicast group.
1139 */
1140 igmp_joingroup(inm);
1141 splx(s);
1142 return (inm);
1143 }
1144
1145 /*
1146 * Delete a multicast address record.
1147 */
1148 void
1149 in_delmulti(inm)
1150 register struct in_multi *inm;
1151 {
1152 struct ifmultiaddr *ifma = inm->inm_ifma;
1153 int s = splnet();
1154
1155 if (ifma->ifma_refcount == 1) {
1156 /*
1157 * No remaining claims to this record; let IGMP know that
1158 * we are leaving the multicast group.
1159 */
1160 igmp_leavegroup(inm);
1161 ifma->ifma_protospec = 0;
1162 LIST_REMOVE(inm, inm_link);
1163 FREE(inm, M_IPMADDR);
1164 }
1165 /* XXX - should be separate API for when we have an ifma? */
1166 if_delmulti(ifma->ifma_ifp, ifma->ifma_addr);
1167 splx(s);
1168
1169
1170 }