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