1 /* 2 * Copyright (c) 1984, 1985 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 6.7 (Berkeley) 02/03/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 292