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