|
|
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 are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: * ! 17: * @(#)ns.c 7.3 (Berkeley) 6/29/88 ! 18: */ ! 19: ! 20: #include "param.h" ! 21: #include "mbuf.h" ! 22: #include "ioctl.h" ! 23: #include "protosw.h" ! 24: #include "socket.h" ! 25: #include "socketvar.h" ! 26: #include "uio.h" ! 27: #include "dir.h" ! 28: #include "user.h" ! 29: ! 30: ! 31: #include "../net/if.h" ! 32: #include "../net/route.h" ! 33: #include "../net/af.h" ! 34: ! 35: #include "ns.h" ! 36: #include "ns_if.h" ! 37: ! 38: #ifdef NS ! 39: ! 40: struct ns_ifaddr *ns_ifaddr; ! 41: ! 42: ns_hash(sns, hp) ! 43: register struct sockaddr_ns *sns; ! 44: struct afhash *hp; ! 45: { ! 46: register long hash = 0; ! 47: register u_short *s = sns->sns_addr.x_host.s_host; ! 48: union { ! 49: union ns_net net_e; ! 50: long long_e; ! 51: } net; ! 52: ! 53: net.net_e = sns->sns_addr.x_net; ! 54: hp->afh_nethash = net.long_e; ! 55: hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s; ! 56: hp->afh_hosthash = hash; ! 57: } ! 58: ! 59: ! 60: ns_netmatch(sns1, sns2) ! 61: struct sockaddr_ns *sns1, *sns2; ! 62: { ! 63: ! 64: return (ns_neteq(sns1->sns_addr, sns2->sns_addr)); ! 65: } ! 66: ! 67: /* ! 68: * Generic internet control operations (ioctl's). ! 69: */ ! 70: /* ARGSUSED */ ! 71: ns_control(so, cmd, data, ifp) ! 72: struct socket *so; ! 73: int cmd; ! 74: caddr_t data; ! 75: register struct ifnet *ifp; ! 76: { ! 77: register struct ifreq *ifr = (struct ifreq *)data; ! 78: register struct ns_ifaddr *ia; ! 79: struct ifaddr *ifa; ! 80: struct mbuf *m; ! 81: ! 82: /* ! 83: * Find address for this interface, if it exists. ! 84: */ ! 85: if (ifp == 0) ! 86: return (EADDRNOTAVAIL); ! 87: for (ia = ns_ifaddr; ia; ia = ia->ia_next) ! 88: if (ia->ia_ifp == ifp) ! 89: break; ! 90: ! 91: switch (cmd) { ! 92: ! 93: case SIOCGIFADDR: ! 94: if (ia == (struct ns_ifaddr *)0) ! 95: return (EADDRNOTAVAIL); ! 96: ifr->ifr_addr = ia->ia_addr; ! 97: return (0); ! 98: ! 99: ! 100: case SIOCGIFBRDADDR: ! 101: if (ia == (struct ns_ifaddr *)0) ! 102: return (EADDRNOTAVAIL); ! 103: if ((ifp->if_flags & IFF_BROADCAST) == 0) ! 104: return (EINVAL); ! 105: ifr->ifr_dstaddr = ia->ia_broadaddr; ! 106: return (0); ! 107: ! 108: case SIOCGIFDSTADDR: ! 109: if (ia == (struct ns_ifaddr *)0) ! 110: return (EADDRNOTAVAIL); ! 111: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) ! 112: return (EINVAL); ! 113: ifr->ifr_dstaddr = ia->ia_dstaddr; ! 114: return (0); ! 115: } ! 116: ! 117: if (!suser()) ! 118: return (u.u_error); ! 119: ! 120: switch (cmd) { ! 121: ! 122: case SIOCSIFADDR: ! 123: case SIOCSIFDSTADDR: ! 124: if (ia == (struct ns_ifaddr *)0) { ! 125: m = m_getclr(M_WAIT, MT_IFADDR); ! 126: if (m == (struct mbuf *)NULL) ! 127: return (ENOBUFS); ! 128: if (ia = ns_ifaddr) { ! 129: for ( ; ia->ia_next; ia = ia->ia_next) ! 130: ; ! 131: ia->ia_next = mtod(m, struct ns_ifaddr *); ! 132: } else ! 133: ns_ifaddr = mtod(m, struct ns_ifaddr *); ! 134: ia = mtod(m, struct ns_ifaddr *); ! 135: if (ifa = ifp->if_addrlist) { ! 136: for ( ; ifa->ifa_next; ifa = ifa->ifa_next) ! 137: ; ! 138: ifa->ifa_next = (struct ifaddr *) ia; ! 139: } else ! 140: ifp->if_addrlist = (struct ifaddr *) ia; ! 141: ia->ia_ifp = ifp; ! 142: IA_SNS(ia)->sns_family = AF_NS; ! 143: } ! 144: } ! 145: ! 146: switch (cmd) { ! 147: ! 148: case SIOCSIFDSTADDR: ! 149: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) ! 150: return (EINVAL); ! 151: if (ia->ia_flags & IFA_ROUTE) { ! 152: rtinit(&ia->ia_dstaddr, &ia->ia_addr, ! 153: (int)SIOCDELRT, RTF_HOST); ! 154: ia->ia_flags &= ~IFA_ROUTE; ! 155: } ! 156: if (ifp->if_ioctl) { ! 157: int error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia); ! 158: if (error) ! 159: return (error); ! 160: } ! 161: ia->ia_dstaddr = ifr->ifr_dstaddr; ! 162: return (0); ! 163: ! 164: case SIOCSIFADDR: ! 165: return ! 166: (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr)); ! 167: ! 168: default: ! 169: if (ifp->if_ioctl == 0) ! 170: return (EOPNOTSUPP); ! 171: return ((*ifp->if_ioctl)(ifp, cmd, data)); ! 172: } ! 173: } ! 174: ! 175: /* ! 176: * Initialize an interface's internet address ! 177: * and routing table entry. ! 178: */ ! 179: ns_ifinit(ifp, ia, sns) ! 180: register struct ifnet *ifp; ! 181: register struct ns_ifaddr *ia; ! 182: struct sockaddr_ns *sns; ! 183: { ! 184: struct sockaddr_ns netaddr; ! 185: register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host); ! 186: int s = splimp(), error; ! 187: ! 188: /* ! 189: * The convention we shall adopt for naming is that ! 190: * a supplied address of zero means that "we don't care". ! 191: * if there is a single interface, use the address of that ! 192: * interface as our 6 byte host address. ! 193: * if there are multiple interfaces, use any address already ! 194: * used. ! 195: * ! 196: * If we have gotten into trouble and want to reset back to ! 197: * virginity, we recognize a request of the broadcast address. ! 198: */ ! 199: if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) { ! 200: ns_thishost = ns_zerohost; ! 201: splx(s); ! 202: return (0); ! 203: } ! 204: ! 205: /* ! 206: * Delete any previous route for an old address. ! 207: */ ! 208: bzero((caddr_t)&netaddr, sizeof (netaddr)); ! 209: netaddr.sns_family = AF_NS; ! 210: netaddr.sns_addr.x_host = ns_broadhost; ! 211: netaddr.sns_addr.x_net = ia->ia_net; ! 212: if (ia->ia_flags & IFA_ROUTE) { ! 213: if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { ! 214: rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, ! 215: (int)SIOCDELRT, 0); ! 216: } else ! 217: rtinit(&ia->ia_dstaddr, &ia->ia_addr, ! 218: (int)SIOCDELRT, RTF_HOST); ! 219: } ! 220: ! 221: /* ! 222: * Set up new addresses. ! 223: */ ! 224: ia->ia_addr = *(struct sockaddr *)sns; ! 225: ia->ia_net = sns->sns_addr.x_net; ! 226: netaddr.sns_addr.x_net = ia->ia_net; ! 227: if (ifp->if_flags & IFF_BROADCAST) { ! 228: ia->ia_broadaddr = * (struct sockaddr *) &netaddr; ! 229: } ! 230: ! 231: /* ! 232: * Give the interface a chance to initialize ! 233: * if this is its first address, ! 234: * and to validate the address if necessary. ! 235: */ ! 236: if (ns_hosteqnh(ns_thishost, ns_zerohost)) { ! 237: if (ifp->if_ioctl && ! 238: (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { ! 239: splx(s); ! 240: return (error); ! 241: } ! 242: ns_thishost = *h; ! 243: } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost) ! 244: || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) { ! 245: *h = ns_thishost; ! 246: if (ifp->if_ioctl && ! 247: (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { ! 248: splx(s); ! 249: return (error); ! 250: } ! 251: if (!ns_hosteqnh(ns_thishost,*h)) { ! 252: splx(s); ! 253: return (EINVAL); ! 254: } ! 255: } else { ! 256: splx(s); ! 257: return (EINVAL); ! 258: } ! 259: ! 260: /* ! 261: * Add route for the network. ! 262: */ ! 263: if (ifp->if_flags & IFF_POINTOPOINT) ! 264: rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, ! 265: RTF_HOST|RTF_UP); ! 266: else ! 267: rtinit(&ia->ia_broadaddr, &ia->ia_addr, (int)SIOCADDRT, ! 268: RTF_UP); ! 269: ia->ia_flags |= IFA_ROUTE; ! 270: return (0); ! 271: } ! 272: ! 273: /* ! 274: * Return address info for specified internet network. ! 275: */ ! 276: struct ns_ifaddr * ! 277: ns_iaonnetof(dst) ! 278: register struct ns_addr *dst; ! 279: { ! 280: register struct ns_ifaddr *ia; ! 281: register struct ns_addr *compare; ! 282: register struct ifnet *ifp; ! 283: struct ns_ifaddr *ia_maybe = 0; ! 284: union ns_net net = dst->x_net; ! 285: ! 286: for (ia = ns_ifaddr; ia; ia = ia->ia_next) { ! 287: if (ifp = ia->ia_ifp) { ! 288: if (ifp->if_flags & IFF_POINTOPOINT) { ! 289: compare = &satons_addr(ia->ia_dstaddr); ! 290: if (ns_hosteq(*dst, *compare)) ! 291: return (ia); ! 292: if (ns_neteqnn(net, ia->ia_net)) ! 293: ia_maybe = ia; ! 294: } else { ! 295: if (ns_neteqnn(net, ia->ia_net)) ! 296: return (ia); ! 297: } ! 298: } ! 299: } ! 300: return (ia_maybe); ! 301: } ! 302: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.