1 /* 2 * Copyright (c) 1982, 1986 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 * @(#)in.c 7.6 (Berkeley) 12/07/87 13 */ 14 15 #include "param.h" 16 #include "ioctl.h" 17 #include "mbuf.h" 18 #include "protosw.h" 19 #include "socket.h" 20 #include "socketvar.h" 21 #include "uio.h" 22 #include "dir.h" 23 #include "user.h" 24 #include "in_systm.h" 25 #include "../net/if.h" 26 #include "../net/route.h" 27 #include "../net/af.h" 28 #include "in.h" 29 #include "in_var.h" 30 31 #ifdef INET 32 inet_hash(sin, hp) 33 register struct sockaddr_in *sin; 34 struct afhash *hp; 35 { 36 register u_long n; 37 38 n = in_netof(sin->sin_addr); 39 if (n) 40 while ((n & 0xff) == 0) 41 n >>= 8; 42 hp->afh_nethash = n; 43 hp->afh_hosthash = ntohl(sin->sin_addr.s_addr); 44 } 45 46 inet_netmatch(sin1, sin2) 47 struct sockaddr_in *sin1, *sin2; 48 { 49 50 return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr)); 51 } 52 53 /* 54 * Formulate an Internet address from network + host. 55 */ 56 struct in_addr 57 in_makeaddr(net, host) 58 u_long net, host; 59 { 60 register struct in_ifaddr *ia; 61 register u_long mask; 62 u_long addr; 63 64 if (IN_CLASSA(net)) 65 mask = IN_CLASSA_HOST; 66 else if (IN_CLASSB(net)) 67 mask = IN_CLASSB_HOST; 68 else 69 mask = IN_CLASSC_HOST; 70 for (ia = in_ifaddr; ia; ia = ia->ia_next) 71 if ((ia->ia_netmask & net) == ia->ia_net) { 72 mask = ~ia->ia_subnetmask; 73 break; 74 } 75 addr = htonl(net | (host & mask)); 76 return (*(struct in_addr *)&addr); 77 } 78 79 /* 80 * Return the network number from an internet address. 81 */ 82 u_long 83 in_netof(in) 84 struct in_addr in; 85 { 86 register u_long i = ntohl(in.s_addr); 87 register u_long net; 88 register struct in_ifaddr *ia; 89 90 if (IN_CLASSA(i)) 91 net = i & IN_CLASSA_NET; 92 else if (IN_CLASSB(i)) 93 net = i & IN_CLASSB_NET; 94 else if (IN_CLASSC(i)) 95 net = i & IN_CLASSC_NET; 96 else 97 return (0); 98 99 /* 100 * Check whether network is a subnet; 101 * if so, return subnet number. 102 */ 103 for (ia = in_ifaddr; ia; ia = ia->ia_next) 104 if (net == ia->ia_net) 105 return (i & ia->ia_subnetmask); 106 return (net); 107 } 108 109 /* 110 * Return the host portion of an internet address. 111 */ 112 u_long 113 in_lnaof(in) 114 struct in_addr in; 115 { 116 register u_long i = ntohl(in.s_addr); 117 register u_long net, host; 118 register struct in_ifaddr *ia; 119 120 if (IN_CLASSA(i)) { 121 net = i & IN_CLASSA_NET; 122 host = i & IN_CLASSA_HOST; 123 } else if (IN_CLASSB(i)) { 124 net = i & IN_CLASSB_NET; 125 host = i & IN_CLASSB_HOST; 126 } else if (IN_CLASSC(i)) { 127 net = i & IN_CLASSC_NET; 128 host = i & IN_CLASSC_HOST; 129 } else 130 return (i); 131 132 /* 133 * Check whether network is a subnet; 134 * if so, use the modified interpretation of `host'. 135 */ 136 for (ia = in_ifaddr; ia; ia = ia->ia_next) 137 if (net == ia->ia_net) 138 return (host &~ ia->ia_subnetmask); 139 return (host); 140 } 141 142 #ifndef SUBNETSARELOCAL 143 #define SUBNETSARELOCAL 1 144 #endif 145 int subnetsarelocal = SUBNETSARELOCAL; 146 /* 147 * Return 1 if an internet address is for a ``local'' host 148 * (one to which we have a connection). If subnetsarelocal 149 * is true, this includes other subnets of the local net. 150 * Otherwise, it includes only the directly-connected (sub)nets. 151 */ 152 in_localaddr(in) 153 struct in_addr in; 154 { 155 register u_long i = ntohl(in.s_addr); 156 register struct in_ifaddr *ia; 157 158 if (subnetsarelocal) { 159 for (ia = in_ifaddr; ia; ia = ia->ia_next) 160 if ((i & ia->ia_netmask) == ia->ia_net) 161 return (1); 162 } else { 163 for (ia = in_ifaddr; ia; ia = ia->ia_next) 164 if ((i & ia->ia_subnetmask) == ia->ia_subnet) 165 return (1); 166 } 167 return (0); 168 } 169 170 /* 171 * Determine whether an IP address is in a reserved set of addresses 172 * that may not be forwarded, or whether datagrams to that destination 173 * may be forwarded. 174 */ 175 in_canforward(in) 176 struct in_addr in; 177 { 178 register u_long i = ntohl(in.s_addr); 179 register u_long net; 180 181 if (IN_EXPERIMENTAL(i)) 182 return (0); 183 if (IN_CLASSA(i)) { 184 net = i & IN_CLASSA_NET; 185 if (net == 0 || net == IN_LOOPBACKNET) 186 return (0); 187 } 188 return (1); 189 } 190 191 int in_interfaces; /* number of external internet interfaces */ 192 extern struct ifnet loif; 193 194 /* 195 * Generic internet control operations (ioctl's). 196 * Ifp is 0 if not an interface-specific ioctl. 197 */ 198 /* ARGSUSED */ 199 in_control(so, cmd, data, ifp) 200 struct socket *so; 201 int cmd; 202 caddr_t data; 203 register struct ifnet *ifp; 204 { 205 register struct ifreq *ifr = (struct ifreq *)data; 206 register struct in_ifaddr *ia = 0; 207 u_long tmp; 208 struct ifaddr *ifa; 209 struct mbuf *m; 210 int error; 211 212 /* 213 * Find address for this interface, if it exists. 214 */ 215 if (ifp) 216 for (ia = in_ifaddr; ia; ia = ia->ia_next) 217 if (ia->ia_ifp == ifp) 218 break; 219 220 switch (cmd) { 221 222 case SIOCSIFADDR: 223 case SIOCSIFNETMASK: 224 case SIOCSIFDSTADDR: 225 if (!suser()) 226 return (u.u_error); 227 228 if (ifp == 0) 229 panic("in_control"); 230 if (ia == (struct in_ifaddr *)0) { 231 m = m_getclr(M_WAIT, MT_IFADDR); 232 if (m == (struct mbuf *)NULL) 233 return (ENOBUFS); 234 if (ia = in_ifaddr) { 235 for ( ; ia->ia_next; ia = ia->ia_next) 236 ; 237 ia->ia_next = mtod(m, struct in_ifaddr *); 238 } else 239 in_ifaddr = mtod(m, struct in_ifaddr *); 240 ia = mtod(m, struct in_ifaddr *); 241 if (ifa = ifp->if_addrlist) { 242 for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 243 ; 244 ifa->ifa_next = (struct ifaddr *) ia; 245 } else 246 ifp->if_addrlist = (struct ifaddr *) ia; 247 ia->ia_ifp = ifp; 248 IA_SIN(ia)->sin_family = AF_INET; 249 if (ifp != &loif) 250 in_interfaces++; 251 } 252 break; 253 254 case SIOCSIFBRDADDR: 255 if (!suser()) 256 return (u.u_error); 257 /* FALLTHROUGH */ 258 259 default: 260 if (ia == (struct in_ifaddr *)0) 261 return (EADDRNOTAVAIL); 262 break; 263 } 264 265 switch (cmd) { 266 267 case SIOCGIFADDR: 268 ifr->ifr_addr = ia->ia_addr; 269 break; 270 271 case SIOCGIFBRDADDR: 272 if ((ifp->if_flags & IFF_BROADCAST) == 0) 273 return (EINVAL); 274 ifr->ifr_dstaddr = ia->ia_broadaddr; 275 break; 276 277 case SIOCGIFDSTADDR: 278 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 279 return (EINVAL); 280 ifr->ifr_dstaddr = ia->ia_dstaddr; 281 break; 282 283 case SIOCGIFNETMASK: 284 #define satosin(sa) ((struct sockaddr_in *)(sa)) 285 satosin(&ifr->ifr_addr)->sin_family = AF_INET; 286 satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask); 287 break; 288 289 case SIOCSIFDSTADDR: 290 { 291 struct sockaddr oldaddr; 292 293 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 294 return (EINVAL); 295 oldaddr = ia->ia_dstaddr; 296 ia->ia_dstaddr = ifr->ifr_dstaddr; 297 if (ifp->if_ioctl && 298 (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) { 299 ia->ia_dstaddr = oldaddr; 300 return (error); 301 } 302 if (ia->ia_flags & IFA_ROUTE) { 303 rtinit(&oldaddr, &ia->ia_addr, (int)SIOCDELRT, 304 RTF_HOST); 305 rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, 306 RTF_HOST|RTF_UP); 307 } 308 } 309 break; 310 311 case SIOCSIFBRDADDR: 312 if ((ifp->if_flags & IFF_BROADCAST) == 0) 313 return (EINVAL); 314 ia->ia_broadaddr = ifr->ifr_broadaddr; 315 tmp = ntohl(satosin(&ia->ia_broadaddr)->sin_addr.s_addr); 316 if ((tmp &~ ia->ia_subnetmask) == ~ia->ia_subnetmask) 317 tmp |= ~ia->ia_netmask; 318 else if ((tmp &~ ia->ia_subnetmask) == 0) 319 tmp &= ia->ia_netmask; 320 ia->ia_netbroadcast.s_addr = htonl(tmp); 321 break; 322 323 case SIOCSIFADDR: 324 return (in_ifinit(ifp, ia, &ifr->ifr_addr)); 325 326 case SIOCSIFNETMASK: 327 ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr); 328 break; 329 330 default: 331 if (ifp == 0 || ifp->if_ioctl == 0) 332 return (EOPNOTSUPP); 333 return ((*ifp->if_ioctl)(ifp, cmd, data)); 334 } 335 return (0); 336 } 337 338 /* 339 * Initialize an interface's internet address 340 * and routing table entry. 341 */ 342 in_ifinit(ifp, ia, sin) 343 register struct ifnet *ifp; 344 register struct in_ifaddr *ia; 345 struct sockaddr_in *sin; 346 { 347 register u_long i = ntohl(sin->sin_addr.s_addr); 348 struct sockaddr oldaddr; 349 struct sockaddr_in netaddr; 350 int s = splimp(), error; 351 352 oldaddr = ia->ia_addr; 353 ia->ia_addr = *(struct sockaddr *)sin; 354 355 /* 356 * Give the interface a chance to initialize 357 * if this is its first address, 358 * and to validate the address if necessary. 359 */ 360 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) { 361 splx(s); 362 ia->ia_addr = oldaddr; 363 return (error); 364 } 365 366 /* 367 * Delete any previous route for an old address. 368 */ 369 bzero((caddr_t)&netaddr, sizeof (netaddr)); 370 netaddr.sin_family = AF_INET; 371 if (ia->ia_flags & IFA_ROUTE) { 372 if (ifp->if_flags & IFF_LOOPBACK) 373 rtinit(&oldaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST); 374 else if (ifp->if_flags & IFF_POINTOPOINT) 375 rtinit(&ia->ia_dstaddr, &oldaddr, (int)SIOCDELRT, 376 RTF_HOST); 377 else { 378 netaddr.sin_addr = in_makeaddr(ia->ia_subnet, 379 INADDR_ANY); 380 rtinit((struct sockaddr *)&netaddr, &oldaddr, 381 (int)SIOCDELRT, 0); 382 } 383 ia->ia_flags &= ~IFA_ROUTE; 384 } 385 if (IN_CLASSA(i)) 386 ia->ia_netmask = IN_CLASSA_NET; 387 else if (IN_CLASSB(i)) 388 ia->ia_netmask = IN_CLASSB_NET; 389 else 390 ia->ia_netmask = IN_CLASSC_NET; 391 ia->ia_net = i & ia->ia_netmask; 392 /* 393 * The subnet mask includes at least the standard network part, 394 * but may already have been set to a larger value. 395 */ 396 ia->ia_subnetmask |= ia->ia_netmask; 397 ia->ia_subnet = i & ia->ia_subnetmask; 398 if (ifp->if_flags & IFF_BROADCAST) { 399 ia->ia_broadaddr.sa_family = AF_INET; 400 ((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr = 401 in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 402 ia->ia_netbroadcast.s_addr = 403 htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask)); 404 } 405 /* 406 * Add route for the network. 407 */ 408 if (ifp->if_flags & IFF_LOOPBACK) 409 rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT, 410 RTF_HOST|RTF_UP); 411 else if (ifp->if_flags & IFF_POINTOPOINT) 412 rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT, 413 RTF_HOST|RTF_UP); 414 else { 415 netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY); 416 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, 417 (int)SIOCADDRT, RTF_UP); 418 } 419 ia->ia_flags |= IFA_ROUTE; 420 splx(s); 421 return (0); 422 } 423 424 /* 425 * Return address info for specified internet network. 426 */ 427 struct in_ifaddr * 428 in_iaonnetof(net) 429 u_long net; 430 { 431 register struct in_ifaddr *ia; 432 433 for (ia = in_ifaddr; ia; ia = ia->ia_next) 434 if (ia->ia_subnet == net) 435 return (ia); 436 return ((struct in_ifaddr *)0); 437 } 438 439 /* 440 * Return 1 if the address might be a local broadcast address. 441 */ 442 in_broadcast(in) 443 struct in_addr in; 444 { 445 register struct in_ifaddr *ia; 446 u_long t; 447 448 /* 449 * Look through the list of addresses for a match 450 * with a broadcast address. 451 */ 452 for (ia = in_ifaddr; ia; ia = ia->ia_next) 453 if (ia->ia_ifp->if_flags & IFF_BROADCAST) { 454 if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == in.s_addr) 455 return (1); 456 /* 457 * Check for old-style (host 0) broadcast. 458 */ 459 if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net) 460 return (1); 461 } 462 if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) 463 return (1); 464 return (0); 465 } 466 #endif 467