1 /* in.c 6.7 85/04/16 */ 2 3 #include "param.h" 4 #include "ioctl.h" 5 #include "mbuf.h" 6 #include "protosw.h" 7 #include "socket.h" 8 #include "socketvar.h" 9 #include "uio.h" 10 #include "dir.h" 11 #include "user.h" 12 #include "in_systm.h" 13 #include "../net/if.h" 14 #include "../net/route.h" 15 #include "../net/af.h" 16 #include "in.h" 17 #include "in_var.h" 18 19 #ifdef INET 20 inet_hash(sin, hp) 21 register struct sockaddr_in *sin; 22 struct afhash *hp; 23 { 24 register u_long n; 25 26 n = in_netof(sin->sin_addr); 27 if (n) 28 while ((n & 0xff) == 0) 29 n >>= 8; 30 hp->afh_nethash = n; 31 hp->afh_hosthash = ntohl(sin->sin_addr.s_addr); 32 } 33 34 inet_netmatch(sin1, sin2) 35 struct sockaddr_in *sin1, *sin2; 36 { 37 38 return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr)); 39 } 40 41 /* 42 * Formulate an Internet address from network + host. 43 */ 44 struct in_addr 45 in_makeaddr(net, host) 46 u_long net, host; 47 { 48 register struct in_ifaddr *ia; 49 register u_long mask; 50 u_long addr; 51 52 if (IN_CLASSA(net)) 53 mask = IN_CLASSA_HOST; 54 else if (IN_CLASSB(net)) 55 mask = IN_CLASSB_HOST; 56 else 57 mask = IN_CLASSC_HOST; 58 for (ia = in_ifaddr; ia; ia = ia->ia_next) 59 if ((ia->ia_netmask & net) == ia->ia_net) { 60 mask = ~ia->ia_subnetmask; 61 break; 62 } 63 addr = htonl(net | (host & mask)); 64 return (*(struct in_addr *)&addr); 65 } 66 67 /* 68 * Return the network number from an internet address. 69 */ 70 in_netof(in) 71 struct in_addr in; 72 { 73 register u_long i = ntohl(in.s_addr); 74 register u_long net; 75 register struct in_ifaddr *ia; 76 77 if (IN_CLASSA(i)) 78 net = i & IN_CLASSA_NET; 79 else if (IN_CLASSB(i)) 80 net = i & IN_CLASSB_NET; 81 else 82 net = i & IN_CLASSC_NET; 83 84 /* 85 * Check whether network is a subnet; 86 * if so, return subnet number. 87 */ 88 for (ia = in_ifaddr; ia; ia = ia->ia_next) 89 if ((ia->ia_netmask & net) == ia->ia_net) 90 return (i & ia->ia_subnetmask); 91 return (net); 92 } 93 94 /* 95 * Return the host portion of an internet address. 96 */ 97 in_lnaof(in) 98 struct in_addr in; 99 { 100 register u_long i = ntohl(in.s_addr); 101 register u_long net, host; 102 register struct in_ifaddr *ia; 103 104 if (IN_CLASSA(i)) { 105 net = i & IN_CLASSA_NET; 106 host = i & IN_CLASSA_HOST; 107 } else if (IN_CLASSB(i)) { 108 net = i & IN_CLASSB_NET; 109 host = i & IN_CLASSB_HOST; 110 } else { 111 net = i & IN_CLASSC_NET; 112 host = i & IN_CLASSC_HOST; 113 } 114 115 /* 116 * Check whether network is a subnet; 117 * if so, use the modified interpretation of `host'. 118 */ 119 for (ia = in_ifaddr; ia; ia = ia->ia_next) 120 if ((ia->ia_netmask & net) == ia->ia_net) 121 return (host &~ ia->ia_subnetmask); 122 return (host); 123 } 124 125 /* 126 * Return 1 if an internet address is for a ``local'' host 127 * (one to which we have a connection). 128 */ 129 in_localaddr(in) 130 struct in_addr in; 131 { 132 register u_long i = ntohl(in.s_addr); 133 register u_long net; 134 register struct in_ifaddr *ia; 135 136 if (IN_CLASSA(i)) 137 net = i & IN_CLASSA_NET; 138 else if (IN_CLASSB(i)) 139 net = i & IN_CLASSB_NET; 140 else 141 net = i & IN_CLASSC_NET; 142 143 for (ia = in_ifaddr; ia; ia = ia->ia_next) 144 if ((ia->ia_netmask & net) == ia->ia_net) 145 return (1); 146 return (0); 147 } 148 149 /* 150 * Generic internet control operations (ioctl's). 151 * Ifp is 0 if not an interface-specific ioctl. 152 */ 153 in_control(so, cmd, data, ifp) 154 struct socket *so; 155 int cmd; 156 caddr_t data; 157 register struct ifnet *ifp; 158 { 159 register struct ifreq *ifr = (struct ifreq *)data; 160 register struct in_ifaddr *ia = 0; 161 struct ifaddr *ifa; 162 struct mbuf *m; 163 int error; 164 165 /* 166 * Find address for this interface, if it exists. 167 */ 168 if (ifp) 169 for (ia = in_ifaddr; ia; ia = ia->ia_next) 170 if (ia->ia_ifp == ifp) 171 break; 172 173 switch (cmd) { 174 175 case SIOCGIFADDR: 176 case SIOCGIFBRDADDR: 177 case SIOCGIFDSTADDR: 178 case SIOCGIFNETMASK: 179 if (ia == (struct in_ifaddr *)0) 180 return (EADDRNOTAVAIL); 181 break; 182 183 case SIOCSIFADDR: 184 case SIOCSIFDSTADDR: 185 case SIOCSIFBRDADDR: 186 case SIOCSIFNETMASK: 187 if (!suser()) 188 return (u.u_error); 189 190 if (ifp == 0) 191 panic("in_control"); 192 if (ia == (struct in_ifaddr *)0) { 193 m = m_getclr(M_WAIT, MT_IFADDR); 194 if (m == (struct mbuf *)NULL) 195 return (ENOBUFS); 196 if (ia = in_ifaddr) { 197 for ( ; ia->ia_next; ia = ia->ia_next) 198 ; 199 ia->ia_next = mtod(m, struct in_ifaddr *); 200 } else 201 in_ifaddr = mtod(m, struct in_ifaddr *); 202 ia = mtod(m, struct in_ifaddr *); 203 if (ifa = ifp->if_addrlist) { 204 for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 205 ; 206 ifa->ifa_next = (struct ifaddr *) ia; 207 } else 208 ifp->if_addrlist = (struct ifaddr *) ia; 209 ia->ia_ifp = ifp; 210 IA_SIN(ia)->sin_family = AF_INET; 211 } 212 break; 213 } 214 215 switch (cmd) { 216 217 case SIOCGIFADDR: 218 ifr->ifr_addr = ia->ia_addr; 219 break; 220 221 case SIOCGIFBRDADDR: 222 if ((ifp->if_flags & IFF_BROADCAST) == 0) 223 return (EINVAL); 224 ifr->ifr_dstaddr = ia->ia_broadaddr; 225 break; 226 227 case SIOCGIFDSTADDR: 228 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 229 return (EINVAL); 230 ifr->ifr_dstaddr = ia->ia_dstaddr; 231 break; 232 233 case SIOCGIFNETMASK: 234 #define satosin(sa) ((struct sockaddr_in *)(sa)) 235 satosin(&ifr->ifr_addr)->sin_family = AF_INET; 236 satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask); 237 break; 238 239 case SIOCSIFDSTADDR: 240 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 241 return (EINVAL); 242 if (ifp->if_ioctl && 243 (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) 244 return (error); 245 ia->ia_dstaddr = ifr->ifr_dstaddr; 246 break; 247 248 case SIOCSIFBRDADDR: 249 if ((ifp->if_flags & IFF_BROADCAST) == 0) 250 return (EINVAL); 251 ia->ia_broadaddr = ifr->ifr_broadaddr; 252 break; 253 254 case SIOCSIFADDR: 255 return (in_ifinit(ifp, ia, &ifr->ifr_addr)); 256 break; 257 258 case SIOCSIFNETMASK: 259 ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr); 260 break; 261 262 default: 263 if (ifp == 0 || ifp->if_ioctl == 0) 264 return (EOPNOTSUPP); 265 return ((*ifp->if_ioctl)(ifp, cmd, data)); 266 } 267 return (0); 268 } 269 270 /* 271 * Initialize an interface's internet address 272 * and routing table entry. 273 */ 274 in_ifinit(ifp, ia, sin) 275 register struct ifnet *ifp; 276 register struct in_ifaddr *ia; 277 struct sockaddr_in *sin; 278 { 279 register u_long i = ntohl(sin->sin_addr.s_addr); 280 struct sockaddr_in netaddr; 281 int s = splimp(), error; 282 283 bzero((caddr_t)&netaddr, sizeof (netaddr)); 284 netaddr.sin_family = AF_INET; 285 /* 286 * Delete any previous route for an old address. 287 */ 288 if (ia->ia_flags & IFA_ROUTE) { 289 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 290 netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY); 291 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1); 292 } else 293 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1); 294 ia->ia_flags &= ~IFA_ROUTE; 295 } 296 ia->ia_addr = *(struct sockaddr *)sin; 297 if (IN_CLASSA(i)) 298 ia->ia_netmask = IN_CLASSA_NET; 299 else if (IN_CLASSB(i)) 300 ia->ia_netmask = IN_CLASSB_NET; 301 else 302 ia->ia_netmask = IN_CLASSC_NET; 303 ia->ia_net = i & ia->ia_netmask; 304 /* 305 * The subnet mask includes at least the standard network part, 306 * but may already have been set to a larger value. 307 */ 308 ia->ia_subnetmask |= ia->ia_netmask; 309 ia->ia_subnet = i & ia->ia_subnetmask; 310 if (ifp->if_flags & IFF_BROADCAST) { 311 ia->ia_broadaddr.sa_family = AF_INET; 312 ((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr = 313 in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 314 } 315 316 /* 317 * Give the interface a chance to initialize 318 * if this is its first address, 319 * and to validate the address if necessary. 320 */ 321 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 322 splx(s); 323 bzero((caddr_t)&ia->ia_addr, sizeof(ia->ia_addr)); 324 return (error); 325 } 326 splx(s); 327 /* 328 * Add route for the network. 329 */ 330 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) { 331 netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY); 332 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP); 333 } else 334 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, 335 RTF_HOST|RTF_UP); 336 ia->ia_flags |= IFA_ROUTE; 337 return (0); 338 } 339 340 /* 341 * Return address info for specified internet network. 342 */ 343 struct in_ifaddr * 344 in_iaonnetof(net) 345 u_long net; 346 { 347 register struct in_ifaddr *ia; 348 349 for (ia = in_ifaddr; ia; ia = ia->ia_next) 350 if (ia->ia_subnet == net) 351 return (ia); 352 return ((struct in_ifaddr *)0); 353 } 354 355 /* 356 * Return 1 if the address is a local broadcast address. 357 */ 358 in_broadcast(in) 359 struct in_addr in; 360 { 361 register struct in_ifaddr *ia; 362 363 /* 364 * Look through the list of addresses for a match 365 * with a broadcast address. 366 */ 367 for (ia = in_ifaddr; ia; ia = ia->ia_next) 368 if (((struct sockaddr_in *)&ia->ia_broadaddr)->sin_addr.s_addr == 369 in.s_addr && (ia->ia_ifp->if_flags & IFF_BROADCAST)) 370 return (1); 371 return (0); 372 } 373 #endif 374