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