|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)ns.c 7.8 (Berkeley) 6/27/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "mbuf.h" ! 38: #include "ioctl.h" ! 39: #include "protosw.h" ! 40: #include "errno.h" ! 41: #include "socket.h" ! 42: #include "socketvar.h" ! 43: ! 44: ! 45: #include "../net/if.h" ! 46: #include "../net/route.h" ! 47: #include "../net/af.h" ! 48: ! 49: #include "ns.h" ! 50: #include "ns_if.h" ! 51: ! 52: #ifdef NS ! 53: ! 54: struct ns_ifaddr *ns_ifaddr; ! 55: int ns_interfaces; ! 56: extern struct sockaddr_ns ns_netmask, ns_hostmask; ! 57: ! 58: /* ! 59: * Generic internet control operations (ioctl's). ! 60: */ ! 61: /* ARGSUSED */ ! 62: ns_control(so, cmd, data, ifp) ! 63: struct socket *so; ! 64: int cmd; ! 65: caddr_t data; ! 66: register struct ifnet *ifp; ! 67: { ! 68: register struct ifreq *ifr = (struct ifreq *)data; ! 69: register struct ns_aliasreq *ifra = (struct ns_aliasreq *)data; ! 70: register struct ns_ifaddr *ia; ! 71: struct ifaddr *ifa; ! 72: struct ns_ifaddr *oia; ! 73: struct mbuf *m; ! 74: int error, dstIsNew, hostIsNew; ! 75: ! 76: /* ! 77: * Find address for this interface, if it exists. ! 78: */ ! 79: if (ifp == 0) ! 80: return (EADDRNOTAVAIL); ! 81: for (ia = ns_ifaddr; ia; ia = ia->ia_next) ! 82: if (ia->ia_ifp == ifp) ! 83: break; ! 84: ! 85: switch (cmd) { ! 86: ! 87: case SIOCGIFADDR: ! 88: if (ia == (struct ns_ifaddr *)0) ! 89: return (EADDRNOTAVAIL); ! 90: *(struct sockaddr_ns *)&ifr->ifr_addr = ia->ia_addr; ! 91: return (0); ! 92: ! 93: ! 94: case SIOCGIFBRDADDR: ! 95: if (ia == (struct ns_ifaddr *)0) ! 96: return (EADDRNOTAVAIL); ! 97: if ((ifp->if_flags & IFF_BROADCAST) == 0) ! 98: return (EINVAL); ! 99: *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_broadaddr; ! 100: return (0); ! 101: ! 102: case SIOCGIFDSTADDR: ! 103: if (ia == (struct ns_ifaddr *)0) ! 104: return (EADDRNOTAVAIL); ! 105: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) ! 106: return (EINVAL); ! 107: *(struct sockaddr_ns *)&ifr->ifr_dstaddr = ia->ia_dstaddr; ! 108: return (0); ! 109: } ! 110: ! 111: if ((so->so_state & SS_PRIV) == 0) ! 112: return (EPERM); ! 113: ! 114: switch (cmd) { ! 115: case SIOCAIFADDR: ! 116: case SIOCDIFADDR: ! 117: if (ifra->ifra_addr.sns_family == AF_NS) ! 118: for (oia = ia; ia; ia = ia->ia_next) { ! 119: if (ia->ia_ifp == ifp && ! 120: ns_neteq(ia->ia_addr.sns_addr, ! 121: ifra->ifra_addr.sns_addr)) ! 122: break; ! 123: } ! 124: if (cmd == SIOCDIFADDR && ia == 0) ! 125: return (EADDRNOTAVAIL); ! 126: /* FALLTHROUGH */ ! 127: ! 128: case SIOCSIFADDR: ! 129: case SIOCSIFDSTADDR: ! 130: if (ia == (struct ns_ifaddr *)0) { ! 131: m = m_getclr(M_WAIT, MT_IFADDR); ! 132: if (m == (struct mbuf *)NULL) ! 133: return (ENOBUFS); ! 134: if (ia = ns_ifaddr) { ! 135: for ( ; ia->ia_next; ia = ia->ia_next) ! 136: ; ! 137: ia->ia_next = mtod(m, struct ns_ifaddr *); ! 138: } else ! 139: ns_ifaddr = mtod(m, struct ns_ifaddr *); ! 140: ia = mtod(m, struct ns_ifaddr *); ! 141: if (ifa = ifp->if_addrlist) { ! 142: for ( ; ifa->ifa_next; ifa = ifa->ifa_next) ! 143: ; ! 144: ifa->ifa_next = (struct ifaddr *) ia; ! 145: } else ! 146: ifp->if_addrlist = (struct ifaddr *) ia; ! 147: ia->ia_ifp = ifp; ! 148: ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; ! 149: ! 150: ia->ia_ifa.ifa_netmask = ! 151: (struct sockaddr *)&ns_netmask; ! 152: ! 153: ia->ia_ifa.ifa_dstaddr = ! 154: (struct sockaddr *)&ia->ia_dstaddr; ! 155: if (ifp->if_flags & IFF_BROADCAST) { ! 156: ia->ia_broadaddr.sns_family = AF_NS; ! 157: ia->ia_broadaddr.sns_len = sizeof(ia->ia_addr); ! 158: ia->ia_broadaddr.sns_addr.x_host = ns_broadhost; ! 159: } ! 160: ns_interfaces++; ! 161: } ! 162: } ! 163: ! 164: switch (cmd) { ! 165: int error; ! 166: ! 167: case SIOCSIFDSTADDR: ! 168: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) ! 169: return (EINVAL); ! 170: if (ia->ia_flags & IFA_ROUTE) { ! 171: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); ! 172: ia->ia_flags &= ~IFA_ROUTE; ! 173: } ! 174: if (ifp->if_ioctl) { ! 175: error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia); ! 176: if (error) ! 177: return (error); ! 178: } ! 179: *(struct sockaddr *)&ia->ia_dstaddr = ifr->ifr_dstaddr; ! 180: return (0); ! 181: ! 182: case SIOCSIFADDR: ! 183: return (ns_ifinit(ifp, ia, ! 184: (struct sockaddr_ns *)&ifr->ifr_addr, 1)); ! 185: ! 186: case SIOCDIFADDR: ! 187: ns_ifscrub(ifp, ia); ! 188: if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia) ! 189: ifp->if_addrlist = ifa->ifa_next; ! 190: else { ! 191: while (ifa->ifa_next && ! 192: (ifa->ifa_next != (struct ifaddr *)ia)) ! 193: ifa = ifa->ifa_next; ! 194: if (ifa->ifa_next) ! 195: ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next; ! 196: else ! 197: printf("Couldn't unlink nsifaddr from ifp\n"); ! 198: } ! 199: oia = ia; ! 200: if (oia == (ia = ns_ifaddr)) { ! 201: ns_ifaddr = ia->ia_next; ! 202: } else { ! 203: while (ia->ia_next && (ia->ia_next != oia)) { ! 204: ia = ia->ia_next; ! 205: } ! 206: if (ia->ia_next) ! 207: ia->ia_next = oia->ia_next; ! 208: else ! 209: printf("Didn't unlink nsifadr from list\n"); ! 210: } ! 211: (void) m_free(dtom(oia)); ! 212: if (0 == --ns_interfaces) { ! 213: /* ! 214: * We reset to virginity and start all over again ! 215: */ ! 216: ns_thishost = ns_zerohost; ! 217: } ! 218: return (0); ! 219: ! 220: case SIOCAIFADDR: ! 221: dstIsNew = 0; hostIsNew = 1; ! 222: if (ia->ia_addr.sns_family == AF_NS) { ! 223: if (ifra->ifra_addr.sns_len == 0) { ! 224: ifra->ifra_addr = ia->ia_addr; ! 225: hostIsNew = 0; ! 226: } else if (ns_neteq(ifra->ifra_addr.sns_addr, ! 227: ia->ia_addr.sns_addr)) ! 228: hostIsNew = 0; ! 229: } ! 230: if ((ifp->if_flags & IFF_POINTOPOINT) && ! 231: (ifra->ifra_dstaddr.sns_family == AF_NS)) { ! 232: if (hostIsNew == 0) ! 233: ns_ifscrub(ifp, ia); ! 234: ia->ia_dstaddr = ifra->ifra_dstaddr; ! 235: dstIsNew = 1; ! 236: } ! 237: if (ifra->ifra_addr.sns_family == AF_NS && ! 238: (hostIsNew || dstIsNew)) ! 239: error = ns_ifinit(ifp, ia, &ifra->ifra_addr, 0); ! 240: return (error); ! 241: ! 242: default: ! 243: if (ifp->if_ioctl == 0) ! 244: return (EOPNOTSUPP); ! 245: return ((*ifp->if_ioctl)(ifp, cmd, data)); ! 246: } ! 247: } ! 248: ! 249: /* ! 250: * Delete any previous route for an old address. ! 251: */ ! 252: ns_ifscrub(ifp, ia) ! 253: register struct ifnet *ifp; ! 254: register struct ns_ifaddr *ia; ! 255: { ! 256: if (ia->ia_flags & IFA_ROUTE) { ! 257: if (ifp->if_flags & IFF_POINTOPOINT) { ! 258: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); ! 259: } else ! 260: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); ! 261: ia->ia_flags &= ~IFA_ROUTE; ! 262: } ! 263: } ! 264: /* ! 265: * Initialize an interface's internet address ! 266: * and routing table entry. ! 267: */ ! 268: ns_ifinit(ifp, ia, sns, scrub) ! 269: register struct ifnet *ifp; ! 270: register struct ns_ifaddr *ia; ! 271: register struct sockaddr_ns *sns; ! 272: { ! 273: struct sockaddr_ns oldaddr; ! 274: register union ns_host *h = &ia->ia_addr.sns_addr.x_host; ! 275: int s = splimp(), error; ! 276: ! 277: /* ! 278: * Set up new addresses. ! 279: */ ! 280: oldaddr = ia->ia_addr; ! 281: ia->ia_addr = *sns; ! 282: /* ! 283: * The convention we shall adopt for naming is that ! 284: * a supplied address of zero means that "we don't care". ! 285: * if there is a single interface, use the address of that ! 286: * interface as our 6 byte host address. ! 287: * if there are multiple interfaces, use any address already ! 288: * used. ! 289: * ! 290: * Give the interface a chance to initialize ! 291: * if this is its first address, ! 292: * and to validate the address if necessary. ! 293: */ ! 294: if (ns_hosteqnh(ns_thishost, ns_zerohost)) { ! 295: if (ifp->if_ioctl && ! 296: (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { ! 297: ia->ia_addr = oldaddr; ! 298: splx(s); ! 299: return (error); ! 300: } ! 301: ns_thishost = *h; ! 302: } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) ! 303: || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { ! 304: *h = ns_thishost; ! 305: if (ifp->if_ioctl && ! 306: (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { ! 307: ia->ia_addr = oldaddr; ! 308: splx(s); ! 309: return (error); ! 310: } ! 311: if (!ns_hosteqnh(ns_thishost,*h)) { ! 312: ia->ia_addr = oldaddr; ! 313: splx(s); ! 314: return (EINVAL); ! 315: } ! 316: } else { ! 317: ia->ia_addr = oldaddr; ! 318: splx(s); ! 319: return (EINVAL); ! 320: } ! 321: /* ! 322: * Add route for the network. ! 323: */ ! 324: if (scrub) { ! 325: ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; ! 326: ns_ifscrub(ifp, ia); ! 327: ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; ! 328: } ! 329: if (ifp->if_flags & IFF_POINTOPOINT) ! 330: rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP); ! 331: else { ! 332: ia->ia_broadaddr.sns_addr.x_net = ia->ia_net; ! 333: rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_UP); ! 334: } ! 335: ia->ia_flags |= IFA_ROUTE; ! 336: return (0); ! 337: } ! 338: ! 339: /* ! 340: * Return address info for specified internet network. ! 341: */ ! 342: struct ns_ifaddr * ! 343: ns_iaonnetof(dst) ! 344: register struct ns_addr *dst; ! 345: { ! 346: register struct ns_ifaddr *ia; ! 347: register struct ns_addr *compare; ! 348: register struct ifnet *ifp; ! 349: struct ns_ifaddr *ia_maybe = 0; ! 350: union ns_net net = dst->x_net; ! 351: ! 352: for (ia = ns_ifaddr; ia; ia = ia->ia_next) { ! 353: if (ifp = ia->ia_ifp) { ! 354: if (ifp->if_flags & IFF_POINTOPOINT) { ! 355: compare = &satons_addr(ia->ia_dstaddr); ! 356: if (ns_hosteq(*dst, *compare)) ! 357: return (ia); ! 358: if (ns_neteqnn(net, ia->ia_net)) ! 359: ia_maybe = ia; ! 360: } else { ! 361: if (ns_neteqnn(net, ia->ia_net)) ! 362: return (ia); ! 363: } ! 364: } ! 365: } ! 366: return (ia_maybe); ! 367: } ! 368: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.