1 #ifdef RCSIDENT 2 static char rcsident[] = "$Header: in.c,v 1.28 85/04/08 15:06:03 walsh Exp $"; 3 #endif 4 5 #include "../h/param.h" 6 #include "../h/mbuf.h" 7 #include "../h/protosw.h" 8 #include "../h/socket.h" 9 #include "../h/socketvar.h" 10 #include "../h/errno.h" 11 #include "../h/ioctl.h" 12 #include "../h/dir.h" 13 #include "../h/user.h" 14 15 #include "../net/if.h" 16 #include "../net/route.h" 17 #include "../net/af.h" 18 #include "../net/netisr.h" 19 #include "../vax/mtpr.h" 20 21 #include "../bbnnet/in.h" 22 #include "../bbnnet/net.h" 23 #include "../bbnnet/in_pcb.h" 24 #include "../bbnnet/in_var.h" 25 #include "../bbnnet/fsm.h" 26 #include "../bbnnet/tcp.h" 27 #include "../bbnnet/udp.h" 28 #include "../bbnnet/ip.h" 29 #include "../bbnnet/icmp.h" 30 31 #ifdef BBNNET 32 33 struct in_ifaddr *in_ifaddr; /* list of Internet addresses for interfaces */ 34 35 #define IN_CLASSA(i) ((((long)(i))&0x80000000)==0) 36 #define IN_CLASSA_NET 0xff000000 37 #define IN_CLASSA_NSHIFT 24 38 #define IN_CLASSA_HOST 0x00ffffff 39 40 #define IN_CLASSB(i) ((((long)(i))&0xc0000000)==0x80000000) 41 #define IN_CLASSB_NET 0xffff0000 42 #define IN_CLASSB_NSHIFT 16 43 #define IN_CLASSB_HOST 0x0000ffff 44 45 #define IN_CLASSC(i) ((((long)(i))&0xc0000000)==0xc0000000) 46 #define IN_CLASSC_NET 0xffffff00 47 #define IN_CLASSC_NSHIFT 8 48 #define IN_CLASSC_HOST 0x000000ff 49 /* 50 * little utility routines 51 * cannot be macros because called from non-IP segments of the code. 52 */ 53 54 in_lnaof(ip_addr) 55 struct in_addr ip_addr; 56 { 57 /* 58 * 1/27/84 Berkeley interface of programs to kernel uses net ordering 59 * This subr used for SIOCSIFADDR ioctl 60 */ 61 register u_long i = ntohl(ip_addr.s_addr); 62 63 if (IN_CLASSA(i)) 64 return ((i)&IN_CLASSA_HOST); 65 else if (IN_CLASSB(i)) 66 return ((i)&IN_CLASSB_HOST); 67 else 68 return ((i)&IN_CLASSC_HOST); 69 } 70 71 #ifdef unused 72 in_netof(ip_addr) 73 struct in_addr ip_addr; 74 { 75 register u_long i = ntohl(ip_addr.s_addr); 76 77 if (IN_CLASSA(i)) 78 return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); 79 else if (IN_CLASSB(i)) 80 return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); 81 else 82 return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); 83 } 84 #endif 85 86 /* 87 * hash an internet address for routing lookups 88 * host part of the address is byte-swapped to put host-specific 89 * bits in the low byte (only the low LOG2(RTHASHSIZ) bits are used by rtalloc) 90 */ 91 92 inet_hash(sin, hp) 93 register struct sockaddr_in *sin; 94 struct afhash *hp; 95 { 96 hp->afh_nethash = NETHASH(sin->sin_addr); 97 hp->afh_hosthash = HOSTHASH(sin->sin_addr.s_addr); 98 } 99 100 inet_netmatch(sin1, sin2) 101 struct sockaddr_in *sin1, *sin2; 102 { 103 104 return (iptonet(sin1->sin_addr) == iptonet(sin2->sin_addr)); 105 } 106 107 /* 108 * Formulate an Internet address from network + host. 109 */ 110 struct in_addr in_makeaddr(net, host) 111 u_long net, host; 112 { 113 register struct in_ifaddr *ia; 114 register u_long mask; 115 u_long addr; 116 117 if (IN_CLASSA(net)) 118 mask = IN_CLASSA_HOST; 119 else if (IN_CLASSB(net)) 120 mask = IN_CLASSB_HOST; 121 else 122 mask = IN_CLASSC_HOST; 123 124 for (ia = in_ifaddr; ia; ia = ia->ia_next) 125 if ((ia->ia_netmask & net) == ia->ia_net) 126 { 127 mask = ~ia->ia_subnetmask; 128 break; 129 } 130 131 addr = htonl(net | (host & mask)); 132 return (*(struct in_addr *)&addr); 133 } 134 135 /* 136 * Return 1 if the address is a local broadcast address. 137 */ 138 in_broadcast(in) 139 struct in_addr in; 140 { 141 register struct in_ifaddr *ia; 142 143 /* 144 * Look through the list of addresses for a match 145 * with a broadcast address. 146 */ 147 for (ia = in_ifaddr; ia; ia = ia->ia_next) 148 if (((struct sockaddr_in *)&ia->ia_broadaddr)->sin_addr.s_addr == 149 in.s_addr && (ia->ia_ifp->if_flags & IFF_BROADCAST)) 150 return (TRUE); 151 return (FALSE); 152 } 153 154 /* 155 * Return the network number from an internet address. 156 */ 157 iptonet (in) 158 struct in_addr in; 159 { 160 register u_long i = ntohl(in.s_addr); 161 register u_long net; 162 register struct in_ifaddr *ia; 163 164 if (IN_CLASSA(i)) 165 net = i & IN_CLASSA_NET; 166 else if (IN_CLASSB(i)) 167 net = i & IN_CLASSB_NET; 168 else 169 net = i & IN_CLASSC_NET; 170 171 /* 172 * Check whether network is a subnet; 173 * if so, return subnet number. 174 */ 175 for (ia = in_ifaddr; ia; ia = ia->ia_next) 176 if (net == ia->ia_net) 177 return (i & ia->ia_subnetmask); 178 179 return (net); 180 } 181 182 #ifdef unused 183 /* 184 * Return the host portion of an internet address. 185 */ 186 iptohost (in) 187 struct in_addr in; 188 { 189 register u_long i = ntohl(in.s_addr); 190 register u_long net, host; 191 register struct in_ifaddr *ia; 192 193 if (IN_CLASSA(i)) 194 { 195 net = i & IN_CLASSA_NET; 196 host = i & IN_CLASSA_HOST; 197 } 198 else if (IN_CLASSB(i)) 199 { 200 net = i & IN_CLASSB_NET; 201 host = i & IN_CLASSB_HOST; 202 } 203 else 204 { 205 net = i & IN_CLASSC_NET; 206 host = i & IN_CLASSC_HOST; 207 } 208 209 /* 210 * Check whether network is a subnet; 211 * if so, use the modified interpretation of `host'. 212 */ 213 for (ia = in_ifaddr; ia; ia = ia->ia_next) 214 if (net == ia->ia_net) 215 return (host & ~ia->ia_subnetmask); 216 217 return (host); 218 } 219 #endif 220 221 #ifdef unused 222 /* 223 * Return TRUE if an internet address is for a ``local'' host 224 * (one to which we have a connection through a local logical net). 225 */ 226 in_localaddr(in) 227 struct in_addr in; 228 { 229 register u_long i = ntohl(in.s_addr); 230 register u_long net; 231 register struct in_ifaddr *ia; 232 233 if (IN_CLASSA(i)) 234 net = i & IN_CLASSA_NET; 235 else if (IN_CLASSB(i)) 236 net = i & IN_CLASSB_NET; 237 else 238 net = i & IN_CLASSC_NET; 239 240 for (ia = in_ifaddr; ia; ia = ia->ia_next) 241 if (net == ia->ia_net) 242 return (TRUE); 243 244 return (FALSE); 245 } 246 #endif 247 248 /* 249 * because defaults are a bit messy here, the ARP and interface layers 250 * are both handled here.... 251 */ 252 253 /* ARGSUSED */ 254 in_ioctl(optname, optval) 255 int optname; 256 struct mbuf **optval; 257 { 258 extern struct ifnet *ifunit(); 259 register struct ifreq *ifr = (struct ifreq *)optval; 260 register struct ifnet *ifp = ifunit(ifr->ifr_name); 261 register struct in_ifaddr *ia = NULL; 262 struct ifaddr *ifa; 263 struct mbuf *m; 264 int error = 0; 265 266 /* 267 * ARP 268 */ 269 switch (optname) 270 { 271 case SIOCSARP: 272 case SIOCDARP: 273 if (!suser()) 274 return(u.u_error); 275 276 /* fall thru */ 277 278 case SIOCGARP: 279 return(arpioctl(optname,(caddr_t)optval)); 280 } 281 282 /* 283 * Find address for this interface, if it exists. 284 */ 285 if (ifp) 286 for (ia = in_ifaddr; ia; ia = ia->ia_next) 287 if (ia->ia_ifp == ifp) 288 break; 289 290 /* 291 * Interface stuff 292 */ 293 294 switch (optname) 295 { 296 297 case SIOCGIFADDR: 298 case SIOCGIFBRDADDR: 299 case SIOCGIFDSTADDR: 300 case SIOCGIFNETMASK: 301 if (ia == (struct in_ifaddr *) NULL) 302 return(EADDRNOTAVAIL); 303 break; 304 305 case SIOCSIFADDR: 306 case SIOCSIFDSTADDR: 307 case SIOCSIFBRDADDR: 308 case SIOCSIFNETMASK: 309 if (!suser()) 310 return(u.u_error); 311 312 if (ifp == NULL) 313 panic("in_control"); 314 if (ia == (struct in_ifaddr *) NULL) 315 { 316 m = m_getclr(M_WAIT, MT_IFADDR); 317 if (m == (struct mbuf *)NULL) 318 return(ENOBUFS); 319 if (ia = in_ifaddr) 320 { 321 for ( ; ia->ia_next; ia = ia->ia_next) 322 ; 323 ia->ia_next = mtod(m, struct in_ifaddr *); 324 } 325 else 326 in_ifaddr = mtod(m, struct in_ifaddr *); 327 ia = mtod(m, struct in_ifaddr *); 328 if (ifa = ifp->if_addrlist) 329 { 330 for ( ; ifa->ifa_next; ifa = ifa->ifa_next) 331 ; 332 ifa->ifa_next = (struct ifaddr *) ia; 333 } 334 else 335 ifp->if_addrlist = (struct ifaddr *) ia; 336 ia->ia_ifp = ifp; 337 IA_SIN(ia)->sin_family = AF_INET; 338 } 339 break; 340 } 341 342 switch (optname) 343 { 344 345 case SIOCGIFADDR: 346 ifr->ifr_addr = ia->ia_addr; 347 break; 348 349 case SIOCGIFBRDADDR: 350 if ((ifp->if_flags & IFF_BROADCAST) == 0) 351 return(EINVAL); 352 ifr->ifr_dstaddr = ia->ia_broadaddr; 353 break; 354 355 case SIOCGIFDSTADDR: 356 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 357 return(EINVAL); 358 ifr->ifr_dstaddr = ia->ia_dstaddr; 359 break; 360 361 case SIOCGIFNETMASK: 362 #define satosin(sa) ((struct sockaddr_in *)(sa)) 363 satosin(&ifr->ifr_addr)->sin_family = AF_INET; 364 satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask); 365 break; 366 367 case SIOCSIFDSTADDR: 368 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 369 return(EINVAL); 370 371 if (ifp->if_ioctl && 372 (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) 373 return(error); 374 375 ia->ia_dstaddr = ifr->ifr_dstaddr; 376 break; 377 378 case SIOCSIFBRDADDR: 379 if ((ifp->if_flags & IFF_BROADCAST) == 0) 380 return(EINVAL); 381 382 ia->ia_broadaddr = ifr->ifr_broadaddr; 383 break; 384 385 case SIOCSIFADDR: 386 return(in_ifinit(ifp, ia, (struct sockaddr_in *)&ifr->ifr_addr)); 387 388 case SIOCSIFNETMASK: 389 ia->ia_subnetmask = 390 ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr); 391 break; 392 393 default: 394 if (ifp == NULL || ifp->if_ioctl == 0) 395 return(EOPNOTSUPP); 396 397 return(((*ifp->if_ioctl)(ifp, optname, (caddr_t)optval))); 398 } 399 400 return (0); 401 } 402 403 /* 404 * Initialize an interface's internet address 405 * and routing table entry. 406 */ 407 in_ifinit(ifp, ia, sin) 408 register struct ifnet *ifp; 409 register struct in_ifaddr *ia; 410 struct sockaddr_in *sin; 411 { 412 register u_long i = ntohl(sin->sin_addr.s_addr); 413 struct sockaddr_in netaddr; 414 int s = splimp(), error; 415 416 bzero((caddr_t)&netaddr, sizeof (netaddr)); 417 netaddr.sin_family = AF_INET; 418 /* 419 * Delete any previous route for an old address. 420 */ 421 if (ia->ia_flags & IFA_ROUTE) 422 { 423 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 424 { 425 netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY); 426 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, -1); 427 } 428 else 429 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, -1); 430 ia->ia_flags &= ~IFA_ROUTE; 431 } 432 ia->ia_addr = *(struct sockaddr *)sin; 433 if (IN_CLASSA(i)) 434 ia->ia_netmask = IN_CLASSA_NET; 435 else if (IN_CLASSB(i)) 436 ia->ia_netmask = IN_CLASSB_NET; 437 else 438 ia->ia_netmask = IN_CLASSC_NET; 439 ia->ia_net = i & ia->ia_netmask; 440 /* 441 * The subnet mask includes at least the standard network part, 442 * but may already have been set to a larger value. 443 */ 444 ia->ia_subnetmask |= ia->ia_netmask; 445 ia->ia_subnet = i & ia->ia_subnetmask; 446 if (ifp->if_flags & IFF_BROADCAST) 447 { 448 ia->ia_broadaddr.sa_family = AF_INET; 449 satoipa(&ia->ia_broadaddr) = in_makeaddr(ia->ia_subnet, INADDR_BROADCAST); 450 } 451 452 /* 453 * Give the interface a chance to initialize 454 * if this is its first address, 455 * and to validate the address if necessary. 456 */ 457 if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) 458 { 459 splx(s); 460 bzero((caddr_t)&ia->ia_addr, sizeof(ia->ia_addr)); 461 return (error); 462 } 463 splx(s); 464 /* 465 * Add route for the network. 466 */ 467 if ((ifp->if_flags & IFF_POINTOPOINT) == 0) 468 { 469 netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY); 470 rtinit((struct sockaddr *)&netaddr, &ia->ia_addr, RTF_UP); 471 } 472 else 473 rtinit((struct sockaddr *)&ia->ia_dstaddr, &ia->ia_addr, RTF_HOST|RTF_UP); 474 ia->ia_flags |= IFA_ROUTE; 475 return (0); 476 } 477 478 /* 479 * return address info for specified address 480 */ 481 482 struct in_ifaddr *in_iawithaddr(addr,bcast) 483 struct in_addr addr; 484 int bcast; /* look for broadcast addrs */ 485 { 486 register struct in_ifaddr *ia; 487 488 for (ia = in_ifaddr; ia; ia = ia->ia_next) 489 { 490 if (IA_INADDR(ia).s_addr == addr.s_addr) 491 return(ia); 492 493 if (bcast) 494 if (IA_B_INADDR(ia).s_addr == addr.s_addr) 495 return(ia); 496 } 497 498 return(ia); 499 } 500 501 struct in_ifaddr *in_iawithnet(addr) 502 struct in_addr addr; 503 { 504 register struct in_ifaddr *ia; 505 register u_long net; 506 507 net = iptonet(addr); 508 509 for(ia = in_ifaddr; ia; ia = ia->ia_next) 510 { 511 if (iptonet(IA_INADDR(ia)) == net) 512 return(ia); 513 } 514 515 return(ia); 516 } 517 518 struct in_ifaddr *in_iafromif(ifp) 519 struct ifnet *ifp; 520 { 521 register struct ifaddr *ifa; 522 523 for(ifa = ifp->if_addrlist; ifa != NULL; ifa = ifa->ifa_next) 524 if (ifa->ifa_addr.sa_family == AF_INET) 525 break; 526 527 return((struct in_ifaddr *)ifa); 528 } 529 530 #ifdef unused 531 /* 532 * Return address info for specified internet network. 533 */ 534 struct in_ifaddr *in_iaonnetof(net) 535 u_long net; 536 { 537 register struct in_ifaddr *ia; 538 539 for (ia = in_ifaddr; ia; ia = ia->ia_next) 540 if (ia->ia_subnet == net) 541 return (ia); 542 543 return ((struct in_ifaddr *) NULL); 544 } 545 #endif 546 #endif 547