|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: * ! 17: * @(#)in.c 7.9 (Berkeley) 6/29/88 ! 18: */ ! 19: ! 20: #include "param.h" ! 21: #include "ioctl.h" ! 22: #include "mbuf.h" ! 23: #include "protosw.h" ! 24: #include "socket.h" ! 25: #include "socketvar.h" ! 26: #include "uio.h" ! 27: #include "dir.h" ! 28: #include "user.h" ! 29: #include "in_systm.h" ! 30: #include "../net/if.h" ! 31: #include "../net/route.h" ! 32: #include "../net/af.h" ! 33: #include "in.h" ! 34: #include "in_var.h" ! 35: ! 36: #ifdef INET ! 37: inet_hash(sin, hp) ! 38: register struct sockaddr_in *sin; ! 39: struct afhash *hp; ! 40: { ! 41: register u_long n; ! 42: ! 43: n = in_netof(sin->sin_addr); ! 44: if (n) ! 45: while ((n & 0xff) == 0) ! 46: n >>= 8; ! 47: hp->afh_nethash = n; ! 48: hp->afh_hosthash = ntohl(sin->sin_addr.s_addr); ! 49: } ! 50: ! 51: inet_netmatch(sin1, sin2) ! 52: struct sockaddr_in *sin1, *sin2; ! 53: { ! 54: ! 55: return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr)); ! 56: } ! 57: ! 58: /* ! 59: * Formulate an Internet address from network + host. ! 60: */ ! 61: struct in_addr ! 62: in_makeaddr(net, host) ! 63: u_long net, host; ! 64: { ! 65: register struct in_ifaddr *ia; ! 66: register u_long mask; ! 67: u_long addr; ! 68: ! 69: if (IN_CLASSA(net)) ! 70: mask = IN_CLASSA_HOST; ! 71: else if (IN_CLASSB(net)) ! 72: mask = IN_CLASSB_HOST; ! 73: else ! 74: mask = IN_CLASSC_HOST; ! 75: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 76: if ((ia->ia_netmask & net) == ia->ia_net) { ! 77: mask = ~ia->ia_subnetmask; ! 78: break; ! 79: } ! 80: addr = htonl(net | (host & mask)); ! 81: return (*(struct in_addr *)&addr); ! 82: } ! 83: ! 84: /* ! 85: * Return the network number from an internet address. ! 86: */ ! 87: u_long ! 88: in_netof(in) ! 89: struct in_addr in; ! 90: { ! 91: register u_long i = ntohl(in.s_addr); ! 92: register u_long net; ! 93: register struct in_ifaddr *ia; ! 94: ! 95: if (IN_CLASSA(i)) ! 96: net = i & IN_CLASSA_NET; ! 97: else if (IN_CLASSB(i)) ! 98: net = i & IN_CLASSB_NET; ! 99: else if (IN_CLASSC(i)) ! 100: net = i & IN_CLASSC_NET; ! 101: else ! 102: return (0); ! 103: ! 104: /* ! 105: * Check whether network is a subnet; ! 106: * if so, return subnet number. ! 107: */ ! 108: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 109: if (net == ia->ia_net) ! 110: return (i & ia->ia_subnetmask); ! 111: return (net); ! 112: } ! 113: ! 114: /* ! 115: * Return the host portion of an internet address. ! 116: */ ! 117: u_long ! 118: in_lnaof(in) ! 119: struct in_addr in; ! 120: { ! 121: register u_long i = ntohl(in.s_addr); ! 122: register u_long net, host; ! 123: register struct in_ifaddr *ia; ! 124: ! 125: if (IN_CLASSA(i)) { ! 126: net = i & IN_CLASSA_NET; ! 127: host = i & IN_CLASSA_HOST; ! 128: } else if (IN_CLASSB(i)) { ! 129: net = i & IN_CLASSB_NET; ! 130: host = i & IN_CLASSB_HOST; ! 131: } else if (IN_CLASSC(i)) { ! 132: net = i & IN_CLASSC_NET; ! 133: host = i & IN_CLASSC_HOST; ! 134: } else ! 135: return (i); ! 136: ! 137: /* ! 138: * Check whether network is a subnet; ! 139: * if so, use the modified interpretation of `host'. ! 140: */ ! 141: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 142: if (net == ia->ia_net) ! 143: return (host &~ ia->ia_subnetmask); ! 144: return (host); ! 145: } ! 146: ! 147: #ifndef SUBNETSARELOCAL ! 148: #define SUBNETSARELOCAL 1 ! 149: #endif ! 150: int subnetsarelocal = SUBNETSARELOCAL; ! 151: /* ! 152: * Return 1 if an internet address is for a ``local'' host ! 153: * (one to which we have a connection). If subnetsarelocal ! 154: * is true, this includes other subnets of the local net. ! 155: * Otherwise, it includes only the directly-connected (sub)nets. ! 156: */ ! 157: in_localaddr(in) ! 158: struct in_addr in; ! 159: { ! 160: register u_long i = ntohl(in.s_addr); ! 161: register struct in_ifaddr *ia; ! 162: ! 163: if (subnetsarelocal) { ! 164: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 165: if ((i & ia->ia_netmask) == ia->ia_net) ! 166: return (1); ! 167: } else { ! 168: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 169: if ((i & ia->ia_subnetmask) == ia->ia_subnet) ! 170: return (1); ! 171: } ! 172: return (0); ! 173: } ! 174: ! 175: /* ! 176: * Determine whether an IP address is in a reserved set of addresses ! 177: * that may not be forwarded, or whether datagrams to that destination ! 178: * may be forwarded. ! 179: */ ! 180: in_canforward(in) ! 181: struct in_addr in; ! 182: { ! 183: register u_long i = ntohl(in.s_addr); ! 184: register u_long net; ! 185: ! 186: if (IN_EXPERIMENTAL(i)) ! 187: return (0); ! 188: if (IN_CLASSA(i)) { ! 189: net = i & IN_CLASSA_NET; ! 190: if (net == 0 || net == IN_LOOPBACKNET) ! 191: return (0); ! 192: } ! 193: return (1); ! 194: } ! 195: ! 196: int in_interfaces; /* number of external internet interfaces */ ! 197: extern struct ifnet loif; ! 198: ! 199: /* ! 200: * Generic internet control operations (ioctl's). ! 201: * Ifp is 0 if not an interface-specific ioctl. ! 202: */ ! 203: /* ARGSUSED */ ! 204: in_control(so, cmd, data, ifp) ! 205: struct socket *so; ! 206: int cmd; ! 207: caddr_t data; ! 208: register struct ifnet *ifp; ! 209: { ! 210: register struct ifreq *ifr = (struct ifreq *)data; ! 211: register struct in_ifaddr *ia = 0; ! 212: struct ifaddr *ifa; ! 213: struct mbuf *m; ! 214: int error; ! 215: ! 216: /* ! 217: * Find address for this interface, if it exists. ! 218: */ ! 219: if (ifp) ! 220: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 221: if (ia->ia_ifp == ifp) ! 222: break; ! 223: ! 224: switch (cmd) { ! 225: ! 226: case SIOCSIFADDR: ! 227: case SIOCSIFNETMASK: ! 228: case SIOCSIFDSTADDR: ! 229: if (!suser()) ! 230: return (u.u_error); ! 231: ! 232: if (ifp == 0) ! 233: panic("in_control"); ! 234: if (ia == (struct in_ifaddr *)0) { ! 235: m = m_getclr(M_WAIT, MT_IFADDR); ! 236: if (m == (struct mbuf *)NULL) ! 237: return (ENOBUFS); ! 238: if (ia = in_ifaddr) { ! 239: for ( ; ia->ia_next; ia = ia->ia_next) ! 240: ; ! 241: ia->ia_next = mtod(m, struct in_ifaddr *); ! 242: } else ! 243: in_ifaddr = mtod(m, struct in_ifaddr *); ! 244: ia = mtod(m, struct in_ifaddr *); ! 245: if (ifa = ifp->if_addrlist) { ! 246: for ( ; ifa->ifa_next; ifa = ifa->ifa_next) ! 247: ; ! 248: ifa->ifa_next = (struct ifaddr *) ia; ! 249: } else ! 250: ifp->if_addrlist = (struct ifaddr *) ia; ! 251: ia->ia_ifp = ifp; ! 252: IA_SIN(ia)->sin_family = AF_INET; ! 253: if (ifp != &loif) ! 254: in_interfaces++; ! 255: } ! 256: break; ! 257: ! 258: case SIOCSIFBRDADDR: ! 259: if (!suser()) ! 260: return (u.u_error); ! 261: /* FALLTHROUGH */ ! 262: ! 263: default: ! 264: if (ia == (struct in_ifaddr *)0) ! 265: return (EADDRNOTAVAIL); ! 266: break; ! 267: } ! 268: ! 269: switch (cmd) { ! 270: ! 271: case SIOCGIFADDR: ! 272: ifr->ifr_addr = ia->ia_addr; ! 273: break; ! 274: ! 275: case SIOCGIFBRDADDR: ! 276: if ((ifp->if_flags & IFF_BROADCAST) == 0) ! 277: return (EINVAL); ! 278: ifr->ifr_dstaddr = ia->ia_broadaddr; ! 279: break; ! 280: ! 281: case SIOCGIFDSTADDR: ! 282: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) ! 283: return (EINVAL); ! 284: ifr->ifr_dstaddr = ia->ia_dstaddr; ! 285: break; ! 286: ! 287: case SIOCGIFNETMASK: ! 288: #define satosin(sa) ((struct sockaddr_in *)(sa)) ! 289: satosin(&ifr->ifr_addr)->sin_family = AF_INET; ! 290: satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask); ! 291: break; ! 292: ! 293: case SIOCSIFDSTADDR: ! 294: { ! 295: struct sockaddr oldaddr; ! 296: ! 297: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) ! 298: return (EINVAL); ! 299: oldaddr = ia->ia_dstaddr; ! 300: ia->ia_dstaddr = ifr->ifr_dstaddr; ! 301: if (ifp->if_ioctl && ! 302: (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { ! 303: ia->ia_dstaddr = oldaddr; ! 304: return (error); ! 305: } ! 306: if (ia->ia_flags & IFA_ROUTE) { ! 307: rtinit(&oldaddr, &ia->ia_addr, (int)SIOCDELRT, ! 308: RTF_HOST); ! 309: rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, ! 310: RTF_HOST|RTF_UP); ! 311: } ! 312: } ! 313: break; ! 314: ! 315: case SIOCSIFBRDADDR: ! 316: if ((ifp->if_flags & IFF_BROADCAST) == 0) ! 317: return (EINVAL); ! 318: ia->ia_broadaddr = ifr->ifr_broadaddr; ! 319: break; ! 320: ! 321: case SIOCSIFADDR: ! 322: return (in_ifinit(ifp, ia, ! 323: (struct sockaddr_in *) &ifr->ifr_addr)); ! 324: ! 325: case SIOCSIFNETMASK: ! 326: ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr); ! 327: break; ! 328: ! 329: default: ! 330: if (ifp == 0 || ifp->if_ioctl == 0) ! 331: return (EOPNOTSUPP); ! 332: return ((*ifp->if_ioctl)(ifp, cmd, data)); ! 333: } ! 334: return (0); ! 335: } ! 336: ! 337: /* ! 338: * Initialize an interface's internet address ! 339: * and routing table entry. ! 340: */ ! 341: in_ifinit(ifp, ia, sin) ! 342: register struct ifnet *ifp; ! 343: register struct in_ifaddr *ia; ! 344: struct sockaddr_in *sin; ! 345: { ! 346: register u_long i = ntohl(sin->sin_addr.s_addr); ! 347: struct sockaddr oldaddr; ! 348: struct sockaddr_in netaddr; ! 349: int s = splimp(), error; ! 350: ! 351: oldaddr = ia->ia_addr; ! 352: ia->ia_addr = *(struct sockaddr *)sin; ! 353: ! 354: /* ! 355: * Give the interface a chance to initialize ! 356: * if this is its first address, ! 357: * and to validate the address if necessary. ! 358: */ ! 359: if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { ! 360: splx(s); ! 361: ia->ia_addr = oldaddr; ! 362: return (error); ! 363: } ! 364: ! 365: /* ! 366: * Delete any previous route for an old address. ! 367: */ ! 368: bzero((caddr_t)&netaddr, sizeof (netaddr)); ! 369: netaddr.sin_family = AF_INET; ! 370: if (ia->ia_flags & IFA_ROUTE) { ! 371: if (ifp->if_flags & IFF_LOOPBACK) ! 372: rtinit(&oldaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST); ! 373: else if (ifp->if_flags & IFF_POINTOPOINT) ! 374: rtinit(&ia->ia_dstaddr, &oldaddr, (int)SIOCDELRT, ! 375: RTF_HOST); ! 376: else { ! 377: netaddr.sin_addr = in_makeaddr(ia->ia_subnet, ! 378: INADDR_ANY); ! 379: rtinit((struct sockaddr *)&netaddr, &oldaddr, ! 380: (int)SIOCDELRT, 0); ! 381: } ! 382: ia->ia_flags &= ~IFA_ROUTE; ! 383: } ! 384: if (IN_CLASSA(i)) ! 385: ia->ia_netmask = IN_CLASSA_NET; ! 386: else if (IN_CLASSB(i)) ! 387: ia->ia_netmask = IN_CLASSB_NET; ! 388: else ! 389: ia->ia_netmask = IN_CLASSC_NET; ! 390: ia->ia_net = i & ia->ia_netmask; ! 391: /* ! 392: * The subnet mask includes at least the standard network part, ! 393: * but may already have been set to a larger value. ! 394: */ ! 395: ia->ia_subnetmask |= ia->ia_netmask; ! 396: ia->ia_subnet = i & ia->ia_subnetmask; ! 397: if (ifp->if_flags & IFF_BROADCAST) { ! 398: ia->ia_broadaddr.sa_family = AF_INET; ! 399: ((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr = ! 400: in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); ! 401: ia->ia_netbroadcast.s_addr = ! 402: htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); ! 403: } ! 404: /* ! 405: * Add route for the network. ! 406: */ ! 407: if (ifp->if_flags & IFF_LOOPBACK) ! 408: rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT, ! 409: RTF_HOST|RTF_UP); ! 410: else if (ifp->if_flags & IFF_POINTOPOINT) ! 411: rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, ! 412: RTF_HOST|RTF_UP); ! 413: else { ! 414: netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY); ! 415: rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, ! 416: (int)SIOCADDRT, RTF_UP); ! 417: } ! 418: ia->ia_flags |= IFA_ROUTE; ! 419: splx(s); ! 420: return (0); ! 421: } ! 422: ! 423: /* ! 424: * Return address info for specified internet network. ! 425: */ ! 426: struct in_ifaddr * ! 427: in_iaonnetof(net) ! 428: u_long net; ! 429: { ! 430: register struct in_ifaddr *ia; ! 431: ! 432: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 433: if (ia->ia_subnet == net) ! 434: return (ia); ! 435: return ((struct in_ifaddr *)0); ! 436: } ! 437: ! 438: /* ! 439: * Return 1 if the address might be a local broadcast address. ! 440: */ ! 441: in_broadcast(in) ! 442: struct in_addr in; ! 443: { ! 444: register struct in_ifaddr *ia; ! 445: u_long t; ! 446: ! 447: /* ! 448: * Look through the list of addresses for a match ! 449: * with a broadcast address. ! 450: */ ! 451: for (ia = in_ifaddr; ia; ia = ia->ia_next) ! 452: if (ia->ia_ifp->if_flags & IFF_BROADCAST) { ! 453: if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == in.s_addr) ! 454: return (1); ! 455: /* ! 456: * Check for old-style (host 0) broadcast. ! 457: */ ! 458: if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) ! 459: return (1); ! 460: } ! 461: if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) ! 462: return (1); ! 463: return (0); ! 464: } ! 465: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.