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