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