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.1 (Berkeley) 6/5/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