|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1982, 1986, 1991, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)in.c 8.4 (Berkeley) 1/9/95 ! 59: */ ! 60: ! 61: #import <sys/param.h> ! 62: #import <sys/systm.h> ! 63: #import <sys/ioctl.h> ! 64: #import <sys/errno.h> ! 65: #import <sys/malloc.h> ! 66: #import <sys/socket.h> ! 67: #import <sys/socketvar.h> ! 68: ! 69: #import <net/if.h> ! 70: #import <net/route.h> ! 71: ! 72: #import <netinet/in_systm.h> ! 73: #import <netinet/in.h> ! 74: #import <netinet/in_var.h> ! 75: #import <netinet/if_ether.h> ! 76: #import <netinet/ip.h> ! 77: #import <netinet/ip_icmp.h> ! 78: ! 79: #import "ether.h" ! 80: ! 81: #if NeXT ! 82: /* ! 83: * Returns a printable string version of an internet address. ! 84: */ ! 85: char * ! 86: inet_ntoa( ! 87: struct in_addr *inp ! 88: ) ! 89: { ! 90: register unsigned char *p; ! 91: register char *b; ! 92: static char buf[20]; ! 93: int i; ! 94: struct in_addr ina; ! 95: ! 96: ina = *inp; ! 97: p = (unsigned char *)&ina; ! 98: b = buf; ! 99: for (i=0; i<4; i++) { ! 100: if (i) *b++ = '.'; ! 101: if (*p > 99) { ! 102: *b++ = '0' + (*p / 100); ! 103: if ((*p % 100) / 10 == 0) ! 104: *b++ = '0'; ! 105: *p %= 100; ! 106: } ! 107: if (*p > 9) { ! 108: *b++ = '0' + (*p / 10); ! 109: *p %= 10; ! 110: } ! 111: *b++ = '0' + *p; ! 112: p++; ! 113: } ! 114: *b++ = 0; ! 115: return(buf); ! 116: } ! 117: #endif NeXT ! 118: ! 119: #if INET ! 120: /* ! 121: * Return the network number from an internet address. ! 122: */ ! 123: u_long ! 124: in_netof(in) ! 125: struct in_addr in; ! 126: { ! 127: register u_long i = ntohl(in.s_addr); ! 128: register u_long net; ! 129: register struct in_ifaddr *ia; ! 130: ! 131: if (IN_CLASSA(i)) ! 132: net = i & IN_CLASSA_NET; ! 133: else if (IN_CLASSB(i)) ! 134: net = i & IN_CLASSB_NET; ! 135: else if (IN_CLASSC(i)) ! 136: net = i & IN_CLASSC_NET; ! 137: else if (IN_CLASSD(i)) ! 138: net = i & IN_CLASSD_NET; ! 139: else ! 140: return (0); ! 141: ! 142: /* ! 143: * Check whether network is a subnet; ! 144: * if so, return subnet number. ! 145: */ ! 146: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 147: if (net == ia->ia_net) ! 148: return (i & ia->ia_subnetmask); ! 149: return (net); ! 150: } ! 151: ! 152: #ifndef SUBNETSARELOCAL ! 153: #define SUBNETSARELOCAL 1 ! 154: #endif ! 155: int subnetsarelocal = SUBNETSARELOCAL; ! 156: /* ! 157: * Return 1 if an internet address is for a ``local'' host ! 158: * (one to which we have a connection). If subnetsarelocal ! 159: * is true, this includes other subnets of the local net. ! 160: * Otherwise, it includes only the directly-connected (sub)nets. ! 161: */ ! 162: int ! 163: in_localaddr(in) ! 164: struct in_addr in; ! 165: { ! 166: register u_long i = ntohl(in.s_addr); ! 167: register struct in_ifaddr *ia; ! 168: ! 169: if (subnetsarelocal) { ! 170: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 171: if ((i & ia->ia_netmask) == ia->ia_net) ! 172: return (1); ! 173: } else { ! 174: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 175: if ((i & ia->ia_subnetmask) == ia->ia_subnet) ! 176: return (1); ! 177: } ! 178: return (0); ! 179: } ! 180: ! 181: /* ! 182: * Determine whether an IP address is in a reserved set of addresses ! 183: * that may not be forwarded, or whether datagrams to that destination ! 184: * may be forwarded. ! 185: */ ! 186: int ! 187: in_canforward(in) ! 188: struct in_addr in; ! 189: { ! 190: register u_long i = ntohl(in.s_addr); ! 191: register u_long net; ! 192: ! 193: if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i)) ! 194: return (0); ! 195: if (IN_CLASSA(i)) { ! 196: net = i & IN_CLASSA_NET; ! 197: if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) ! 198: return (0); ! 199: } ! 200: return (1); ! 201: } ! 202: ! 203: /* ! 204: * Trim a mask in a sockaddr ! 205: */ ! 206: void ! 207: in_socktrim(ap) ! 208: struct sockaddr_in *ap; ! 209: { ! 210: register char *cplim = (char *) &ap->sin_addr; ! 211: register char *cp = (char *) (&ap->sin_addr + 1); ! 212: ! 213: ap->sin_len = 0; ! 214: while (--cp >= cplim) ! 215: if (*cp) { ! 216: (ap)->sin_len = cp - (char *) (ap) + 1; ! 217: break; ! 218: } ! 219: } ! 220: ! 221: int in_interfaces; /* number of external internet interfaces */ ! 222: extern struct ifnet loif; ! 223: ! 224: /* ! 225: * Generic internet control operations (ioctl's). ! 226: * Ifp is 0 if not an interface-specific ioctl. ! 227: */ ! 228: /* ARGSUSED */ ! 229: int ! 230: in_control(so, cmd, data, ifp) ! 231: struct socket *so; ! 232: u_long cmd; ! 233: caddr_t data; ! 234: register struct ifnet *ifp; ! 235: { ! 236: register struct ifreq *ifr = (struct ifreq *)data; ! 237: register struct in_ifaddr *ia = 0; ! 238: register struct ifaddr *ifa; ! 239: struct in_ifaddr *oia; ! 240: struct in_aliasreq *ifra = (struct in_aliasreq *)data; ! 241: struct sockaddr_in oldaddr; ! 242: int error, hostIsNew, maskIsNew; ! 243: u_long i; ! 244: ! 245: /* ! 246: * Find address for this interface, if it exists. ! 247: */ ! 248: if (ifp) ! 249: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 250: if (ia->ia_ifp == ifp) ! 251: break; ! 252: ! 253: switch (cmd) { ! 254: ! 255: case SIOCAIFADDR: ! 256: case SIOCDIFADDR: ! 257: if (ifra->ifra_addr.sin_family == AF_INET) ! 258: for (oia = ia; ia; ia = ia->ia_next) { ! 259: if (ia->ia_ifp == ifp && ! 260: ia->ia_addr.sin_addr.s_addr == ! 261: ifra->ifra_addr.sin_addr.s_addr) ! 262: break; ! 263: } ! 264: if (cmd == SIOCDIFADDR && ia == 0) ! 265: return (EADDRNOTAVAIL); ! 266: /* FALLTHROUGH */ ! 267: case SIOCSIFADDR: ! 268: case SIOCSIFNETMASK: ! 269: case SIOCSIFDSTADDR: ! 270: #if NeXT ! 271: case SIOCAUTONETMASK: ! 272: #endif NeXT ! 273: if ((so->so_state & SS_PRIV) == 0) ! 274: return (EPERM); ! 275: ! 276: if (ifp == 0) ! 277: panic("in_control"); ! 278: if (ia == (struct in_ifaddr *)0) { ! 279: oia = (struct in_ifaddr *) ! 280: _MALLOC(sizeof *oia, M_IFADDR, M_WAITOK); ! 281: if (oia == (struct in_ifaddr *)NULL) ! 282: return (ENOBUFS); ! 283: bzero((caddr_t)oia, sizeof *oia); ! 284: if (ia = in_ifaddr) { ! 285: for ( ; ia->ia_next; ia = ia->ia_next) ! 286: continue; ! 287: ia->ia_next = oia; ! 288: } else ! 289: in_ifaddr = oia; ! 290: ia = oia; ! 291: if (ifa = ifp->if_addrlist) { ! 292: for ( ; ifa->ifa_next; ifa = ifa->ifa_next) ! 293: continue; ! 294: ifa->ifa_next = (struct ifaddr *) ia; ! 295: } else ! 296: ifp->if_addrlist = (struct ifaddr *) ia; ! 297: ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; ! 298: ia->ia_ifa.ifa_dstaddr ! 299: = (struct sockaddr *)&ia->ia_dstaddr; ! 300: ia->ia_ifa.ifa_netmask ! 301: = (struct sockaddr *)&ia->ia_sockmask; ! 302: ia->ia_sockmask.sin_len = 8; ! 303: if (ifp->if_flags & IFF_BROADCAST) { ! 304: ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr); ! 305: ia->ia_broadaddr.sin_family = AF_INET; ! 306: } ! 307: ia->ia_ifp = ifp; ! 308: if (ifp != &loif) ! 309: in_interfaces++; ! 310: } ! 311: break; ! 312: ! 313: case SIOCSIFBRDADDR: ! 314: if ((so->so_state & SS_PRIV) == 0) ! 315: return (EPERM); ! 316: /* FALLTHROUGH */ ! 317: ! 318: case SIOCGIFADDR: ! 319: case SIOCGIFNETMASK: ! 320: case SIOCGIFDSTADDR: ! 321: case SIOCGIFBRDADDR: ! 322: if (ia == (struct in_ifaddr *)0) ! 323: return (EADDRNOTAVAIL); ! 324: break; ! 325: #if NeXT ! 326: case SIOCAUTOADDR: ! 327: break; ! 328: #endif NeXT ! 329: } ! 330: switch (cmd) { ! 331: ! 332: case SIOCGIFADDR: ! 333: *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; ! 334: break; ! 335: ! 336: case SIOCGIFBRDADDR: ! 337: if ((ifp->if_flags & IFF_BROADCAST) == 0) ! 338: return (EINVAL); ! 339: *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr; ! 340: break; ! 341: ! 342: case SIOCGIFDSTADDR: ! 343: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) ! 344: return (EINVAL); ! 345: *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr; ! 346: break; ! 347: ! 348: case SIOCGIFNETMASK: ! 349: *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask; ! 350: break; ! 351: ! 352: case SIOCSIFDSTADDR: ! 353: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) ! 354: return (EINVAL); ! 355: oldaddr = ia->ia_dstaddr; ! 356: ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr; ! 357: if (ifp->if_ioctl && (error = (*ifp->if_ioctl) ! 358: (ifp, SIOCSIFDSTADDR, (caddr_t)ia))) { ! 359: ia->ia_dstaddr = oldaddr; ! 360: return (error); ! 361: } ! 362: if (ia->ia_flags & IFA_ROUTE) { ! 363: ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr; ! 364: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); ! 365: ia->ia_ifa.ifa_dstaddr = ! 366: (struct sockaddr *)&ia->ia_dstaddr; ! 367: rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); ! 368: } ! 369: break; ! 370: ! 371: case SIOCSIFBRDADDR: ! 372: if ((ifp->if_flags & IFF_BROADCAST) == 0) ! 373: return (EINVAL); ! 374: ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr; ! 375: break; ! 376: ! 377: case SIOCSIFADDR: ! 378: ifp->if_eflags &= ~(IFEF_AUTOCONF_DONE); ! 379: return (in_ifinit(ifp, ia, ! 380: (struct sockaddr_in *) &ifr->ifr_addr, 1)); ! 381: ! 382: case SIOCSIFNETMASK: ! 383: i = ifra->ifra_addr.sin_addr.s_addr; ! 384: ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); ! 385: break; ! 386: ! 387: case SIOCAIFADDR: ! 388: ifp->if_eflags &= ~(IFEF_AUTOCONF_DONE); ! 389: maskIsNew = 0; ! 390: hostIsNew = 1; ! 391: error = 0; ! 392: if (ia->ia_addr.sin_family == AF_INET) { ! 393: if (ifra->ifra_addr.sin_len == 0) { ! 394: ifra->ifra_addr = ia->ia_addr; ! 395: hostIsNew = 0; ! 396: } else if (ifra->ifra_addr.sin_addr.s_addr == ! 397: ia->ia_addr.sin_addr.s_addr) ! 398: hostIsNew = 0; ! 399: } ! 400: if (ifra->ifra_mask.sin_len) { ! 401: in_ifscrub(ifp, ia); ! 402: ia->ia_sockmask = ifra->ifra_mask; ! 403: ia->ia_subnetmask = ! 404: ntohl(ia->ia_sockmask.sin_addr.s_addr); ! 405: maskIsNew = 1; ! 406: } ! 407: if ((ifp->if_flags & IFF_POINTOPOINT) && ! 408: (ifra->ifra_dstaddr.sin_family == AF_INET)) { ! 409: in_ifscrub(ifp, ia); ! 410: ia->ia_dstaddr = ifra->ifra_dstaddr; ! 411: maskIsNew = 1; /* We lie; but the effect's the same */ ! 412: } ! 413: if (ifra->ifra_addr.sin_family == AF_INET && ! 414: (hostIsNew || maskIsNew)) ! 415: error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0); ! 416: if ((ifp->if_flags & IFF_BROADCAST) && ! 417: (ifra->ifra_broadaddr.sin_family == AF_INET)) ! 418: ia->ia_broadaddr = ifra->ifra_broadaddr; ! 419: return (error); ! 420: ! 421: case SIOCDIFADDR: ! 422: in_ifscrub(ifp, ia); ! 423: if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) ! 424: ifp->if_addrlist = ifa->ifa_next; ! 425: else { ! 426: while (ifa->ifa_next && ! 427: (ifa->ifa_next != (struct ifaddr *)ia)) ! 428: ifa = ifa->ifa_next; ! 429: if (ifa->ifa_next) ! 430: ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; ! 431: else ! 432: printf("Couldn't unlink inifaddr from ifp\n"); ! 433: } ! 434: oia = ia; ! 435: if (oia == (ia = in_ifaddr)) ! 436: in_ifaddr = ia->ia_next; ! 437: else { ! 438: while (ia->ia_next && (ia->ia_next != oia)) ! 439: ia = ia->ia_next; ! 440: if (ia->ia_next) ! 441: ia->ia_next = oia->ia_next; ! 442: else ! 443: printf("Didn't unlink inifadr from list\n"); ! 444: } ! 445: IFAFREE((&oia->ia_ifa)); ! 446: break; ! 447: #if NeXT ! 448: case SIOCAUTONETMASK: ! 449: { ! 450: int retry; ! 451: ! 452: ifp->if_eflags &= ~(IFEF_NETMASK_AUTH); ! 453: if ((ifp->if_flags & IFF_UP) == 0) { ! 454: return (ENETDOWN); ! 455: } ! 456: ifp->if_eflags |= IFEF_AWAITING_NETMASK; ! 457: for (retry = 0; retry < ICMP_NETMASK_RETRY_MAX; retry++) { ! 458: /* Exponential retransmit backoff */ ! 459: /* 0, 1, 2, 4, 8, 16, 32, 32, 32... seconds */ ! 460: error = icmp_sendMaskPacket(ifp, ICMP_MASKREQ, ! 461: ((retry > 5) ? 32 : (( 1 << retry) >> 1))); ! 462: if (error != 0) ! 463: return (error); ! 464: if ((ifp->if_eflags & IFEF_AWAITING_NETMASK) == 0) ! 465: return (0); ! 466: } ! 467: return (ENETDOWN); ! 468: } ! 469: #endif NeXT ! 470: ! 471: default: ! 472: if (ifp == 0 || ifp->if_ioctl == 0) ! 473: return (EOPNOTSUPP); ! 474: return ((*ifp->if_ioctl)(ifp, cmd, data)); ! 475: } ! 476: return (0); ! 477: } ! 478: ! 479: /* ! 480: * Delete any existing route for an interface. ! 481: */ ! 482: void ! 483: in_ifscrub(ifp, ia) ! 484: register struct ifnet *ifp; ! 485: register struct in_ifaddr *ia; ! 486: { ! 487: ! 488: if ((ia->ia_flags & IFA_ROUTE) == 0) ! 489: return; ! 490: if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) ! 491: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); ! 492: else ! 493: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); ! 494: ia->ia_flags &= ~IFA_ROUTE; ! 495: } ! 496: ! 497: /* ! 498: * Initialize an interface's internet address ! 499: * and routing table entry. ! 500: */ ! 501: int ! 502: in_ifinit(ifp, ia, sin, scrub) ! 503: register struct ifnet *ifp; ! 504: register struct in_ifaddr *ia; ! 505: struct sockaddr_in *sin; ! 506: int scrub; ! 507: { ! 508: register u_long i = ntohl(sin->sin_addr.s_addr); ! 509: struct sockaddr_in oldaddr; ! 510: int s = splimp(), flags = RTF_UP, error, ether_output(); ! 511: ! 512: oldaddr = ia->ia_addr; ! 513: ia->ia_addr = *sin; ! 514: /* ! 515: * Give the interface a chance to initialize ! 516: * if this is its first address, ! 517: * and to validate the address if necessary. ! 518: */ ! 519: if (ifp->if_ioctl && ! 520: (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { ! 521: splx(s); ! 522: ia->ia_addr = oldaddr; ! 523: return (error); ! 524: } ! 525: #if NETHER > 0 ! 526: if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ ! 527: ia->ia_ifa.ifa_rtrequest = arp_rtrequest; ! 528: ia->ia_ifa.ifa_flags |= RTF_CLONING; ! 529: } ! 530: #endif ! 531: splx(s); ! 532: if (scrub) { ! 533: ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; ! 534: in_ifscrub(ifp, ia); ! 535: ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; ! 536: } ! 537: ! 538: /* DWS: Nov. 4th, 1997 ! 539: * Mark the interface as "auto-configuring" if the all-zeroes IP address ! 540: * is assigned. An interface in this state allows BOOTP packets to pass ! 541: * up that would normally get rejected (see ip_input.c) because the interface ! 542: * hasn't been assigned a valid IP address yet. ! 543: */ ! 544: if (i == 0) { ! 545: ifp->if_eflags |= IFEF_AUTOCONF; ! 546: } ! 547: else { ! 548: ifp->if_eflags &= ~(IFEF_AUTOCONF); ! 549: } ! 550: ! 551: if (IN_CLASSA(i)) ! 552: ia->ia_netmask = IN_CLASSA_NET; ! 553: else if (IN_CLASSB(i)) ! 554: ia->ia_netmask = IN_CLASSB_NET; ! 555: else ! 556: ia->ia_netmask = IN_CLASSC_NET; ! 557: /* ! 558: * The subnet mask usually includes at least the standard network part, ! 559: * but may may be smaller in the case of supernetting. ! 560: * If it is set, we believe it. ! 561: */ ! 562: if (ia->ia_subnetmask == 0) { ! 563: ia->ia_subnetmask = ia->ia_netmask; ! 564: ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); ! 565: } ! 566: else { ! 567: ia->ia_netmask &= ia->ia_subnetmask; ! 568: } ! 569: ia->ia_net = i & ia->ia_netmask; ! 570: ia->ia_subnet = i & ia->ia_subnetmask; ! 571: in_socktrim(&ia->ia_sockmask); ! 572: /* ! 573: * Add route for the network. ! 574: */ ! 575: ia->ia_ifa.ifa_metric = ifp->if_metric; ! 576: if (ifp->if_flags & IFF_BROADCAST) { ! 577: ia->ia_broadaddr.sin_addr.s_addr = ! 578: htonl(ia->ia_subnet | ~ia->ia_subnetmask); ! 579: ia->ia_netbroadcast.s_addr = ! 580: htonl(ia->ia_net | ~ ia->ia_netmask); ! 581: } else if (ifp->if_flags & IFF_LOOPBACK) { ! 582: ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; ! 583: flags |= RTF_HOST; ! 584: } else if (ifp->if_flags & IFF_POINTOPOINT) { ! 585: if (ia->ia_dstaddr.sin_family != AF_INET) ! 586: return (0); ! 587: flags |= RTF_HOST; ! 588: } ! 589: if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) ! 590: ia->ia_flags |= IFA_ROUTE; ! 591: /* ! 592: * If the interface supports multicast, join the "all hosts" ! 593: * multicast group on that interface. ! 594: */ ! 595: if (ifp->if_flags & IFF_MULTICAST) { ! 596: struct in_addr addr; ! 597: ! 598: addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); ! 599: in_addmulti(&addr, ifp); ! 600: } ! 601: return (error); ! 602: } ! 603: ! 604: ! 605: /* ! 606: * Return 1 if the address might be a local broadcast address. ! 607: */ ! 608: int ! 609: in_broadcast(in, ifp) ! 610: struct in_addr in; ! 611: struct ifnet *ifp; ! 612: { ! 613: register struct ifaddr *ifa; ! 614: u_long t; ! 615: ! 616: if (in.s_addr == INADDR_BROADCAST || ! 617: in.s_addr == INADDR_ANY) ! 618: return 1; ! 619: if ((ifp->if_flags & IFF_BROADCAST) == 0) ! 620: return 0; ! 621: t = ntohl(in.s_addr); ! 622: /* ! 623: * Look through the list of addresses for a match ! 624: * with a broadcast address. ! 625: */ ! 626: #define ia ((struct in_ifaddr *)ifa) ! 627: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) ! 628: if (ifa->ifa_addr->sa_family == AF_INET && ! 629: (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr || ! 630: in.s_addr == ia->ia_netbroadcast.s_addr || ! 631: /* ! 632: * Check for old-style (host 0) broadcast. ! 633: */ ! 634: t == ia->ia_subnet || t == ia->ia_net)) ! 635: return 1; ! 636: return (0); ! 637: #undef ia ! 638: } ! 639: ! 640: /* ! 641: * Add an address to the list of IP multicast addresses for a given interface. ! 642: */ ! 643: struct in_multi * ! 644: in_addmulti(ap, ifp) ! 645: register struct in_addr *ap; ! 646: register struct ifnet *ifp; ! 647: { ! 648: register struct in_multi *inm; ! 649: struct ifreq ifr; ! 650: struct in_ifaddr *ia; ! 651: int s = splnet(); ! 652: ! 653: /* ! 654: * See if address already in list. ! 655: */ ! 656: IN_LOOKUP_MULTI(*ap, ifp, inm); ! 657: if (inm != NULL) { ! 658: /* ! 659: * Found it; just increment the reference count. ! 660: */ ! 661: ++inm->inm_refcount; ! 662: } ! 663: else { ! 664: /* ! 665: * New address; allocate a new multicast record ! 666: * and link it into the interface's multicast list. ! 667: */ ! 668: MALLOC(inm, struct in_multi *, sizeof(*inm), M_IPMADDR, M_NOWAIT); ! 669: if (inm == NULL) { ! 670: splx(s); ! 671: return (NULL); ! 672: } ! 673: inm->inm_addr = *ap; ! 674: inm->inm_ifp = ifp; ! 675: inm->inm_refcount = 1; ! 676: IFP_TO_IA(ifp, ia); ! 677: if (ia == NULL) { ! 678: _FREE(inm, M_IPMADDR); ! 679: splx(s); ! 680: return (NULL); ! 681: } ! 682: inm->inm_ia = ia; ! 683: inm->inm_next = ia->ia_multiaddrs; ! 684: ia->ia_multiaddrs = inm; ! 685: /* ! 686: * Ask the network driver to update its multicast reception ! 687: * filter appropriately for the new address. ! 688: */ ! 689: ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET; ! 690: ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap; ! 691: if ((ifp->if_ioctl == NULL) || ! 692: (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { ! 693: ia->ia_multiaddrs = inm->inm_next; ! 694: _FREE(inm, M_IPMADDR); ! 695: splx(s); ! 696: return (NULL); ! 697: } ! 698: /* ! 699: * Let IGMP know that we have joined a new IP multicast group. ! 700: */ ! 701: igmp_joingroup(inm); ! 702: } ! 703: splx(s); ! 704: return (inm); ! 705: } ! 706: ! 707: /* ! 708: * Delete a multicast address record. ! 709: */ ! 710: int ! 711: in_delmulti(inm) ! 712: register struct in_multi *inm; ! 713: { ! 714: register struct in_multi **p; ! 715: struct ifreq ifr; ! 716: int s = splnet(); ! 717: ! 718: if (--inm->inm_refcount == 0) { ! 719: /* ! 720: * No remaining claims to this record; let IGMP know that ! 721: * we are leaving the multicast group. ! 722: */ ! 723: igmp_leavegroup(inm); ! 724: /* ! 725: * Unlink from list. ! 726: */ ! 727: for (p = &inm->inm_ia->ia_multiaddrs; ! 728: *p != inm; ! 729: p = &(*p)->inm_next) ! 730: continue; ! 731: *p = (*p)->inm_next; ! 732: /* ! 733: * Notify the network driver to update its multicast reception ! 734: * filter. ! 735: */ ! 736: ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; ! 737: ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr = ! 738: inm->inm_addr; ! 739: (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, ! 740: (caddr_t)&ifr); ! 741: _FREE(inm, M_IPMADDR); ! 742: } ! 743: splx(s); ! 744: } ! 745: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.