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