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