1 /* $NetBSD: at_control.c,v 1.5 2001/04/13 23:30:18 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1990,1994 Regents of The University of Michigan. 5 * All Rights Reserved. 6 * 7 * Permission to use, copy, modify, and distribute this software and 8 * its documentation for any purpose and without fee is hereby granted, 9 * provided that the above copyright notice appears in all copies and 10 * that both that copyright notice and this permission notice appear 11 * in supporting documentation, and that the name of The University 12 * of Michigan not be used in advertising or publicity pertaining to 13 * distribution of the software without specific, written prior 14 * permission. This software is supplied as is without expressed or 15 * implied warranties of any kind. 16 * 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 20 * Research Systems Unix Group 21 * The University of Michigan 22 * c/o Wesley Craig 23 * 535 W. William Street 24 * Ann Arbor, Michigan 25 * +1-313-764-2278 26 * netatalk@umich.edu 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/proc.h> 32 #include <sys/types.h> 33 #include <sys/errno.h> 34 #include <sys/ioctl.h> 35 #include <sys/mbuf.h> 36 #include <sys/kernel.h> 37 #include <sys/socket.h> 38 #include <sys/socketvar.h> 39 #include <net/if.h> 40 #include <net/route.h> 41 #include <net/if_ether.h> 42 #include <netinet/in.h> 43 #undef s_net 44 45 #include <netatalk/at.h> 46 #include <netatalk/at_var.h> 47 #include <netatalk/aarp.h> 48 #include <netatalk/phase2.h> 49 #include <netatalk/at_extern.h> 50 51 static int aa_dorangeroute __P((struct ifaddr * ifa, 52 u_int first, u_int last, int cmd)); 53 static int aa_addsingleroute __P((struct ifaddr * ifa, 54 struct at_addr * addr, struct at_addr * mask)); 55 static int aa_delsingleroute __P((struct ifaddr * ifa, 56 struct at_addr * addr, struct at_addr * mask)); 57 static int aa_dosingleroute __P((struct ifaddr * ifa, struct at_addr * addr, 58 struct at_addr * mask, int cmd, int flags)); 59 static int at_scrub __P((struct ifnet * ifp, struct at_ifaddr * aa)); 60 static int at_ifinit __P((struct ifnet * ifp, struct at_ifaddr * aa, 61 struct sockaddr_at * sat)); 62 #if 0 63 static void aa_clean __P((void)); 64 #endif 65 66 #define sateqaddr(a,b) ((a)->sat_len == (b)->sat_len && \ 67 (a)->sat_family == (b)->sat_family && \ 68 (a)->sat_addr.s_net == (b)->sat_addr.s_net && \ 69 (a)->sat_addr.s_node == (b)->sat_addr.s_node ) 70 71 int 72 at_control(cmd, data, ifp, p) 73 u_long cmd; 74 caddr_t data; 75 struct ifnet *ifp; 76 struct proc *p; 77 { 78 struct ifreq *ifr = (struct ifreq *) data; 79 struct sockaddr_at *sat; 80 struct netrange *nr; 81 struct at_aliasreq *ifra = (struct at_aliasreq *) data; 82 struct at_ifaddr *aa0; 83 struct at_ifaddr *aa = 0; 84 85 /* 86 * If we have an ifp, then find the matching at_ifaddr if it exists 87 */ 88 if (ifp) 89 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) 90 if (aa->aa_ifp == ifp) 91 break; 92 93 /* 94 * In this first switch table we are basically getting ready for 95 * the second one, by getting the atalk-specific things set up 96 * so that they start to look more similar to other protocols etc. 97 */ 98 99 switch (cmd) { 100 case SIOCAIFADDR: 101 case SIOCDIFADDR: 102 /* 103 * If we have an appletalk sockaddr, scan forward of where 104 * we are now on the at_ifaddr list to find one with a matching 105 * address on this interface. 106 * This may leave aa pointing to the first address on the 107 * NEXT interface! 108 */ 109 if (ifra->ifra_addr.sat_family == AF_APPLETALK) { 110 for (; aa; aa = aa->aa_list.tqe_next) 111 if (aa->aa_ifp == ifp && 112 sateqaddr(&aa->aa_addr, &ifra->ifra_addr)) 113 break; 114 } 115 /* 116 * If we a retrying to delete an addres but didn't find such, 117 * then return with an error 118 */ 119 if (cmd == SIOCDIFADDR && aa == 0) 120 return (EADDRNOTAVAIL); 121 /* FALLTHROUGH */ 122 123 case SIOCSIFADDR: 124 /* 125 * If we are not superuser, then we don't get to do these 126 * ops. 127 */ 128 if (suser(p->p_ucred, &p->p_acflag)) 129 return (EPERM); 130 131 sat = satosat(&ifr->ifr_addr); 132 nr = (struct netrange *) sat->sat_zero; 133 if (nr->nr_phase == 1) { 134 /* 135 * Look for a phase 1 address on this interface. 136 * This may leave aa pointing to the first address on 137 * the NEXT interface! 138 */ 139 for (; aa; aa = aa->aa_list.tqe_next) { 140 if (aa->aa_ifp == ifp && 141 (aa->aa_flags & AFA_PHASE2) == 0) 142 break; 143 } 144 } else { /* default to phase 2 */ 145 /* 146 * Look for a phase 2 address on this interface. 147 * This may leave aa pointing to the first address on 148 * the NEXT interface! 149 */ 150 for (; aa; aa = aa->aa_list.tqe_next) { 151 if (aa->aa_ifp == ifp && 152 (aa->aa_flags & AFA_PHASE2)) 153 break; 154 } 155 } 156 157 if (ifp == 0) 158 panic("at_control"); 159 160 /* 161 * If we failed to find an existing at_ifaddr entry, then we 162 * allocate a fresh one. 163 * XXX change this to use malloc 164 */ 165 if (aa == (struct at_ifaddr *) 0) { 166 aa = (struct at_ifaddr *) 167 malloc(sizeof(struct at_ifaddr), M_IFADDR, 168 M_WAITOK); 169 170 if (aa == NULL) 171 return (ENOBUFS); 172 173 bzero(aa, sizeof *aa); 174 callout_init(&aa->aa_probe_ch); 175 176 if ((aa0 = at_ifaddr.tqh_first) != NULL) { 177 /* 178 * Don't let the loopback be first, since the 179 * first address is the machine's default 180 * address for binding. 181 * If it is, stick ourself in front, otherwise 182 * go to the back of the list. 183 */ 184 if (aa0->aa_ifp->if_flags & IFF_LOOPBACK) { 185 TAILQ_INSERT_HEAD(&at_ifaddr, aa, 186 aa_list); 187 } else { 188 TAILQ_INSERT_TAIL(&at_ifaddr, aa, 189 aa_list); 190 } 191 } else { 192 TAILQ_INSERT_TAIL(&at_ifaddr, aa, aa_list); 193 } 194 IFAREF(&aa->aa_ifa); 195 196 /* 197 * Find the end of the interface's addresses 198 * and link our new one on the end 199 */ 200 TAILQ_INSERT_TAIL(&ifp->if_addrlist, 201 (struct ifaddr *) aa, ifa_list); 202 IFAREF(&aa->aa_ifa); 203 204 /* 205 * As the at_ifaddr contains the actual sockaddrs, 206 * and the ifaddr itself, link them al together 207 * correctly. 208 */ 209 aa->aa_ifa.ifa_addr = 210 (struct sockaddr *) &aa->aa_addr; 211 aa->aa_ifa.ifa_dstaddr = 212 (struct sockaddr *) &aa->aa_addr; 213 aa->aa_ifa.ifa_netmask = 214 (struct sockaddr *) &aa->aa_netmask; 215 216 /* 217 * Set/clear the phase 2 bit. 218 */ 219 if (nr->nr_phase == 1) 220 aa->aa_flags &= ~AFA_PHASE2; 221 else 222 aa->aa_flags |= AFA_PHASE2; 223 224 /* 225 * and link it all together 226 */ 227 aa->aa_ifp = ifp; 228 } else { 229 /* 230 * If we DID find one then we clobber any routes 231 * dependent on it.. 232 */ 233 at_scrub(ifp, aa); 234 } 235 break; 236 237 case SIOCGIFADDR: 238 sat = satosat(&ifr->ifr_addr); 239 nr = (struct netrange *) sat->sat_zero; 240 if (nr->nr_phase == 1) { 241 /* 242 * If the request is specifying phase 1, then 243 * only look at a phase one address 244 */ 245 for (; aa; aa = aa->aa_list.tqe_next) { 246 if (aa->aa_ifp == ifp && 247 (aa->aa_flags & AFA_PHASE2) == 0) 248 break; 249 } 250 } else { 251 /* 252 * default to phase 2 253 */ 254 for (; aa; aa = aa->aa_list.tqe_next) { 255 if (aa->aa_ifp == ifp && 256 (aa->aa_flags & AFA_PHASE2)) 257 break; 258 } 259 } 260 261 if (aa == (struct at_ifaddr *) 0) 262 return (EADDRNOTAVAIL); 263 break; 264 } 265 266 /* 267 * By the time this switch is run we should be able to assume that 268 * the "aa" pointer is valid when needed. 269 */ 270 switch (cmd) { 271 case SIOCGIFADDR: 272 273 /* 274 * copy the contents of the sockaddr blindly. 275 */ 276 sat = (struct sockaddr_at *) & ifr->ifr_addr; 277 *sat = aa->aa_addr; 278 279 /* 280 * and do some cleanups 281 */ 282 ((struct netrange *) &sat->sat_zero)->nr_phase = 283 (aa->aa_flags & AFA_PHASE2) ? 2 : 1; 284 ((struct netrange *) &sat->sat_zero)->nr_firstnet = 285 aa->aa_firstnet; 286 ((struct netrange *) &sat->sat_zero)->nr_lastnet = 287 aa->aa_lastnet; 288 break; 289 290 case SIOCSIFADDR: 291 return (at_ifinit(ifp, aa, 292 (struct sockaddr_at *) &ifr->ifr_addr)); 293 294 case SIOCAIFADDR: 295 if (sateqaddr(&ifra->ifra_addr, &aa->aa_addr)) 296 return 0; 297 return (at_ifinit(ifp, aa, 298 (struct sockaddr_at *) &ifr->ifr_addr)); 299 300 case SIOCDIFADDR: 301 at_purgeaddr((struct ifaddr *) aa, ifp); 302 break; 303 304 default: 305 if (ifp == 0 || ifp->if_ioctl == 0) 306 return (EOPNOTSUPP); 307 return ((*ifp->if_ioctl) (ifp, cmd, data)); 308 } 309 return (0); 310 } 311 312 void 313 at_purgeaddr(ifa, ifp) 314 struct ifaddr *ifa; 315 struct ifnet *ifp; 316 { 317 struct at_ifaddr *aa = (void *) ifa; 318 319 /* 320 * scrub all routes.. didn't we just DO this? XXX yes, del it 321 * XXX above XXX not necessarily true anymore 322 */ 323 at_scrub(ifp, aa); 324 325 /* 326 * remove the ifaddr from the interface 327 */ 328 TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *) aa, ifa_list); 329 IFAFREE(&aa->aa_ifa); 330 TAILQ_REMOVE(&at_ifaddr, aa, aa_list); 331 IFAFREE(&aa->aa_ifa); 332 } 333 334 void 335 at_purgeif(ifp) 336 struct ifnet *ifp; 337 { 338 struct ifaddr *ifa, *nifa; 339 340 for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL; ifa = nifa) { 341 nifa = TAILQ_NEXT(ifa, ifa_list); 342 if (ifa->ifa_addr->sa_family != AF_APPLETALK) 343 continue; 344 at_purgeaddr(ifa, ifp); 345 } 346 } 347 348 /* 349 * Given an interface and an at_ifaddr (supposedly on that interface) remove 350 * any routes that depend on this. Why ifp is needed I'm not sure, as 351 * aa->at_ifaddr.ifa_ifp should be the same. 352 */ 353 static int 354 at_scrub(ifp, aa) 355 struct ifnet *ifp; 356 struct at_ifaddr *aa; 357 { 358 int error = 0; 359 360 if (aa->aa_flags & AFA_ROUTE) { 361 if (ifp->if_flags & IFF_LOOPBACK) 362 error = aa_delsingleroute(&aa->aa_ifa, 363 &aa->aa_addr.sat_addr, &aa->aa_netmask.sat_addr); 364 else if (ifp->if_flags & IFF_POINTOPOINT) 365 error = rtinit(&aa->aa_ifa, RTM_DELETE, RTF_HOST); 366 else if (ifp->if_flags & IFF_BROADCAST) 367 error = aa_dorangeroute(&aa->aa_ifa, 368 ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet), 369 RTM_DELETE); 370 371 aa->aa_ifa.ifa_flags &= ~IFA_ROUTE; 372 aa->aa_flags &= ~AFA_ROUTE; 373 } 374 return error; 375 } 376 377 /* 378 * given an at_ifaddr,a sockaddr_at and an ifp, 379 * bang them all together at high speed and see what happens 380 */ 381 static int 382 at_ifinit(ifp, aa, sat) 383 struct ifnet *ifp; 384 struct at_ifaddr *aa; 385 struct sockaddr_at *sat; 386 { 387 struct netrange nr, onr; 388 struct sockaddr_at oldaddr; 389 int s = splnet(), error = 0, i, j; 390 int netinc, nodeinc, nnets; 391 u_short net; 392 393 /* 394 * save the old addresses in the at_ifaddr just in case we need them. 395 */ 396 oldaddr = aa->aa_addr; 397 onr.nr_firstnet = aa->aa_firstnet; 398 onr.nr_lastnet = aa->aa_lastnet; 399 400 /* 401 * take the address supplied as an argument, and add it to the 402 * at_ifnet (also given). Remember ing to update 403 * those parts of the at_ifaddr that need special processing 404 */ 405 bzero(AA_SAT(aa), sizeof(struct sockaddr_at)); 406 bcopy(sat->sat_zero, &nr, sizeof(struct netrange)); 407 bcopy(sat->sat_zero, AA_SAT(aa)->sat_zero, sizeof(struct netrange)); 408 nnets = ntohs(nr.nr_lastnet) - ntohs(nr.nr_firstnet) + 1; 409 aa->aa_firstnet = nr.nr_firstnet; 410 aa->aa_lastnet = nr.nr_lastnet; 411 412 #ifdef NETATALKDEBUG 413 printf("at_ifinit: %s: %u.%u range %u-%u phase %d\n", 414 ifp->if_xname, 415 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 416 ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet), 417 (aa->aa_flags & AFA_PHASE2) ? 2 : 1); 418 #endif 419 420 /* 421 * We could eliminate the need for a second phase 1 probe (post 422 * autoconf) if we check whether we're resetting the node. Note 423 * that phase 1 probes use only nodes, not net.node pairs. Under 424 * phase 2, both the net and node must be the same. 425 */ 426 AA_SAT(aa)->sat_len = sat->sat_len; 427 AA_SAT(aa)->sat_family = AF_APPLETALK; 428 if (ifp->if_flags & IFF_LOOPBACK) { 429 AA_SAT(aa)->sat_addr.s_net = sat->sat_addr.s_net; 430 AA_SAT(aa)->sat_addr.s_node = sat->sat_addr.s_node; 431 #if 0 432 } else if (fp->if_flags & IFF_POINTOPOINT) { 433 /* unimplemented */ 434 /* 435 * we'd have to copy the dstaddr field over from the sat 436 * but it's not clear that it would contain the right info.. 437 */ 438 #endif 439 } else { 440 /* 441 * We are a normal (probably ethernet) interface. 442 * apply the new address to the interface structures etc. 443 * We will probe this address on the net first, before 444 * applying it to ensure that it is free.. If it is not, then 445 * we will try a number of other randomly generated addresses 446 * in this net and then increment the net. etc.etc. until 447 * we find an unused address. 448 */ 449 aa->aa_flags |= AFA_PROBING; /* if not loopback we Must 450 * probe? */ 451 if (aa->aa_flags & AFA_PHASE2) { 452 if (sat->sat_addr.s_net == ATADDR_ANYNET) { 453 /* 454 * If we are phase 2, and the net was not 455 * specified * then we select a random net 456 * within the supplied netrange. 457 * XXX use /dev/random? 458 */ 459 if (nnets != 1) { 460 net = ntohs(nr.nr_firstnet) + 461 time.tv_sec % (nnets - 1); 462 } else { 463 net = ntohs(nr.nr_firstnet); 464 } 465 } else { 466 /* 467 * if a net was supplied, then check that it 468 * is within the netrange. If it is not then 469 * replace the old values and return an error 470 */ 471 if (ntohs(sat->sat_addr.s_net) < 472 ntohs(nr.nr_firstnet) || 473 ntohs(sat->sat_addr.s_net) > 474 ntohs(nr.nr_lastnet)) { 475 aa->aa_addr = oldaddr; 476 aa->aa_firstnet = onr.nr_firstnet; 477 aa->aa_lastnet = onr.nr_lastnet; 478 splx(s); 479 return (EINVAL); 480 } 481 /* 482 * otherwise just use the new net number.. 483 */ 484 net = ntohs(sat->sat_addr.s_net); 485 } 486 } else { 487 /* 488 * we must be phase one, so just use whatever we were 489 * given. I guess it really isn't going to be used... 490 * RIGHT? 491 */ 492 net = ntohs(sat->sat_addr.s_net); 493 } 494 495 /* 496 * set the node part of the address into the ifaddr. If it's 497 * not specified, be random about it... XXX use /dev/random? 498 */ 499 if (sat->sat_addr.s_node == ATADDR_ANYNODE) { 500 AA_SAT(aa)->sat_addr.s_node = time.tv_sec; 501 } else { 502 AA_SAT(aa)->sat_addr.s_node = sat->sat_addr.s_node; 503 } 504 505 /* 506 * step through the nets in the range starting at the 507 * (possibly random) start point. 508 */ 509 for (i = nnets, netinc = 1; i > 0; net = ntohs(nr.nr_firstnet) + 510 ((net - ntohs(nr.nr_firstnet) + netinc) % nnets), i--) { 511 AA_SAT(aa)->sat_addr.s_net = htons(net); 512 513 /* 514 * using a rather strange stepping method, 515 * stagger through the possible node addresses 516 * Once again, starting at the (possibly random) 517 * initial node address. 518 */ 519 for (j = 0, nodeinc = time.tv_sec | 1; j < 256; 520 j++, AA_SAT(aa)->sat_addr.s_node += nodeinc) { 521 if (AA_SAT(aa)->sat_addr.s_node > 253 || 522 AA_SAT(aa)->sat_addr.s_node < 1) { 523 continue; 524 } 525 aa->aa_probcnt = 10; 526 527 /* 528 * start off the probes as an asynchronous 529 * activity. though why wait 200mSec? 530 */ 531 callout_reset(&aa->aa_probe_ch, hz / 5, 532 aarpprobe, ifp); 533 if (tsleep(aa, PPAUSE | PCATCH, "at_ifinit", 534 0)) { 535 /* 536 * theoretically we shouldn't time out 537 * here so if we returned with an error. 538 */ 539 printf("at_ifinit: timeout?!\n"); 540 aa->aa_addr = oldaddr; 541 aa->aa_firstnet = onr.nr_firstnet; 542 aa->aa_lastnet = onr.nr_lastnet; 543 splx(s); 544 return (EINTR); 545 } 546 /* 547 * The async activity should have woken us 548 * up. We need to see if it was successful in 549 * finding a free spot, or if we need to 550 * iterate to the next address to try. 551 */ 552 if ((aa->aa_flags & AFA_PROBING) == 0) 553 break; 554 } 555 556 /* 557 * of course we need to break out through two loops... 558 */ 559 if ((aa->aa_flags & AFA_PROBING) == 0) 560 break; 561 562 /* reset node for next network */ 563 AA_SAT(aa)->sat_addr.s_node = time.tv_sec; 564 } 565 566 /* 567 * if we are still trying to probe, then we have finished all 568 * the possible addresses, so we need to give up 569 */ 570 if (aa->aa_flags & AFA_PROBING) { 571 aa->aa_addr = oldaddr; 572 aa->aa_firstnet = onr.nr_firstnet; 573 aa->aa_lastnet = onr.nr_lastnet; 574 splx(s); 575 return (EADDRINUSE); 576 } 577 } 578 579 /* 580 * Now that we have selected an address, we need to tell the 581 * interface about it, just in case it needs to adjust something. 582 */ 583 if (ifp->if_ioctl && 584 (error = (*ifp->if_ioctl) (ifp, SIOCSIFADDR, (caddr_t) aa))) { 585 /* 586 * of course this could mean that it objects violently 587 * so if it does, we back out again.. 588 */ 589 aa->aa_addr = oldaddr; 590 aa->aa_firstnet = onr.nr_firstnet; 591 aa->aa_lastnet = onr.nr_lastnet; 592 splx(s); 593 return (error); 594 } 595 /* 596 * set up the netmask part of the at_ifaddr and point the appropriate 597 * pointer in the ifaddr to it. probably pointless, but what the 598 * heck.. XXX 599 */ 600 bzero(&aa->aa_netmask, sizeof(aa->aa_netmask)); 601 aa->aa_netmask.sat_len = sizeof(struct sockaddr_at); 602 aa->aa_netmask.sat_family = AF_APPLETALK; 603 aa->aa_netmask.sat_addr.s_net = 0xffff; 604 aa->aa_netmask.sat_addr.s_node = 0; 605 #if 0 606 aa->aa_ifa.ifa_netmask = (struct sockaddr *) &(aa->aa_netmask);/* XXX */ 607 #endif 608 609 /* 610 * Initialize broadcast (or remote p2p) address 611 */ 612 bzero(&aa->aa_broadaddr, sizeof(aa->aa_broadaddr)); 613 aa->aa_broadaddr.sat_len = sizeof(struct sockaddr_at); 614 aa->aa_broadaddr.sat_family = AF_APPLETALK; 615 616 aa->aa_ifa.ifa_metric = ifp->if_metric; 617 if (ifp->if_flags & IFF_BROADCAST) { 618 aa->aa_broadaddr.sat_addr.s_net = htons(0); 619 aa->aa_broadaddr.sat_addr.s_node = 0xff; 620 aa->aa_ifa.ifa_broadaddr = 621 (struct sockaddr *) &aa->aa_broadaddr; 622 /* add the range of routes needed */ 623 error = aa_dorangeroute(&aa->aa_ifa, 624 ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet), RTM_ADD); 625 } else if (ifp->if_flags & IFF_POINTOPOINT) { 626 struct at_addr rtaddr, rtmask; 627 628 bzero(&rtaddr, sizeof(rtaddr)); 629 bzero(&rtmask, sizeof(rtmask)); 630 /* fill in the far end if we know it here XXX */ 631 aa->aa_ifa.ifa_dstaddr = (struct sockaddr *) & aa->aa_dstaddr; 632 error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask); 633 } else if (ifp->if_flags & IFF_LOOPBACK) { 634 struct at_addr rtaddr, rtmask; 635 636 bzero(&rtaddr, sizeof(rtaddr)); 637 bzero(&rtmask, sizeof(rtmask)); 638 rtaddr.s_net = AA_SAT(aa)->sat_addr.s_net; 639 rtaddr.s_node = AA_SAT(aa)->sat_addr.s_node; 640 rtmask.s_net = 0xffff; 641 rtmask.s_node = 0x0; 642 error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask); 643 } 644 /* 645 * of course if we can't add these routes we back out, but it's getting 646 * risky by now XXX 647 */ 648 if (error) { 649 at_scrub(ifp, aa); 650 aa->aa_addr = oldaddr; 651 aa->aa_firstnet = onr.nr_firstnet; 652 aa->aa_lastnet = onr.nr_lastnet; 653 splx(s); 654 return (error); 655 } 656 /* 657 * note that the address has a route associated with it.... 658 */ 659 aa->aa_ifa.ifa_flags |= IFA_ROUTE; 660 aa->aa_flags |= AFA_ROUTE; 661 splx(s); 662 return (0); 663 } 664 665 /* 666 * check whether a given address is a broadcast address for us.. 667 */ 668 int 669 at_broadcast(sat) 670 struct sockaddr_at *sat; 671 { 672 struct at_ifaddr *aa; 673 674 /* 675 * If the node is not right, it can't be a broadcast 676 */ 677 if (sat->sat_addr.s_node != ATADDR_BCAST) 678 return 0; 679 680 /* 681 * If the node was right then if the net is right, it's a broadcast 682 */ 683 if (sat->sat_addr.s_net == ATADDR_ANYNET) 684 return 1; 685 686 /* 687 * failing that, if the net is one we have, it's a broadcast as well. 688 */ 689 for (aa = at_ifaddr.tqh_first; aa; aa = aa->aa_list.tqe_next) { 690 if ((aa->aa_ifp->if_flags & IFF_BROADCAST) 691 && (ntohs(sat->sat_addr.s_net) >= ntohs(aa->aa_firstnet) 692 && ntohs(sat->sat_addr.s_net) <= ntohs(aa->aa_lastnet))) 693 return 1; 694 } 695 return 0; 696 } 697 698 699 /* 700 * aa_dorangeroute() 701 * 702 * Add a route for a range of networks from bot to top - 1. 703 * Algorithm: 704 * 705 * Split the range into two subranges such that the middle 706 * of the two ranges is the point where the highest bit of difference 707 * between the two addresses, makes it's transition 708 * Each of the upper and lower ranges might not exist, or might be 709 * representable by 1 or more netmasks. In addition, if both 710 * ranges can be represented by the same netmask, then teh can be merged 711 * by using the next higher netmask.. 712 */ 713 714 static int 715 aa_dorangeroute(ifa, bot, top, cmd) 716 struct ifaddr *ifa; 717 u_int bot; 718 u_int top; 719 int cmd; 720 { 721 u_int mask1; 722 struct at_addr addr; 723 struct at_addr mask; 724 int error; 725 726 /* 727 * slight sanity check 728 */ 729 if (bot > top) 730 return (EINVAL); 731 732 addr.s_node = 0; 733 mask.s_node = 0; 734 /* 735 * just start out with the lowest boundary 736 * and keep extending the mask till it's too big. 737 */ 738 739 while (bot <= top) { 740 mask1 = 1; 741 while (((bot & ~mask1) >= bot) 742 && ((bot | mask1) <= top)) { 743 mask1 <<= 1; 744 mask1 |= 1; 745 } 746 mask1 >>= 1; 747 mask.s_net = htons(~mask1); 748 addr.s_net = htons(bot); 749 if (cmd == RTM_ADD) { 750 error = aa_addsingleroute(ifa, &addr, &mask); 751 if (error) { 752 /* XXX clean up? */ 753 return (error); 754 } 755 } else { 756 error = aa_delsingleroute(ifa, &addr, &mask); 757 } 758 bot = (bot | mask1) + 1; 759 } 760 return 0; 761 } 762 763 static int 764 aa_addsingleroute(ifa, addr, mask) 765 struct ifaddr *ifa; 766 struct at_addr *addr; 767 struct at_addr *mask; 768 { 769 int error; 770 771 #ifdef NETATALKDEBUG 772 printf("aa_addsingleroute: %x.%x mask %x.%x ...", 773 ntohs(addr->s_net), addr->s_node, 774 ntohs(mask->s_net), mask->s_node); 775 #endif 776 777 error = aa_dosingleroute(ifa, addr, mask, RTM_ADD, RTF_UP); 778 #ifdef NETATALKDEBUG 779 if (error) 780 printf("aa_addsingleroute: error %d\n", error); 781 #endif 782 return (error); 783 } 784 785 static int 786 aa_delsingleroute(ifa, addr, mask) 787 struct ifaddr *ifa; 788 struct at_addr *addr; 789 struct at_addr *mask; 790 { 791 int error; 792 793 #ifdef NETATALKDEBUG 794 printf("aa_delsingleroute: %x.%x mask %x.%x ...", 795 ntohs(addr->s_net), addr->s_node, 796 ntohs(mask->s_net), mask->s_node); 797 #endif 798 799 error = aa_dosingleroute(ifa, addr, mask, RTM_DELETE, 0); 800 #ifdef NETATALKDEBUG 801 if (error) 802 printf("aa_delsingleroute: error %d\n", error); 803 #endif 804 return (error); 805 } 806 807 static int 808 aa_dosingleroute(ifa, at_addr, at_mask, cmd, flags) 809 struct ifaddr *ifa; 810 struct at_addr *at_addr; 811 struct at_addr *at_mask; 812 int cmd; 813 int flags; 814 { 815 struct sockaddr_at addr, mask, *gate; 816 817 bzero(&addr, sizeof(addr)); 818 bzero(&mask, sizeof(mask)); 819 addr.sat_family = AF_APPLETALK; 820 addr.sat_len = sizeof(struct sockaddr_at); 821 addr.sat_addr.s_net = at_addr->s_net; 822 addr.sat_addr.s_node = at_addr->s_node; 823 mask.sat_family = AF_APPLETALK; 824 mask.sat_len = sizeof(struct sockaddr_at); 825 mask.sat_addr.s_net = at_mask->s_net; 826 mask.sat_addr.s_node = at_mask->s_node; 827 828 if (at_mask->s_node) { 829 gate = satosat(ifa->ifa_dstaddr); 830 flags |= RTF_HOST; 831 } else { 832 gate = satosat(ifa->ifa_addr); 833 } 834 835 #ifdef NETATALKDEBUG 836 printf("on %s %x.%x\n", (flags & RTF_HOST) ? "host" : "net", 837 ntohs(gate->sat_addr.s_net), gate->sat_addr.s_node); 838 #endif 839 return (rtrequest(cmd, (struct sockaddr *) &addr, 840 (struct sockaddr *) gate, (struct sockaddr *) &mask, flags, NULL)); 841 } 842 843 #if 0 844 static void 845 aa_clean() 846 { 847 struct at_ifaddr *aa; 848 struct ifaddr *ifa; 849 struct ifnet *ifp; 850 851 while (aa = at_ifaddr) { 852 ifp = aa->aa_ifp; 853 at_scrub(ifp, aa); 854 at_ifaddr = aa->aa_next; 855 if ((ifa = ifp->if_addrlist) == (struct ifaddr *) aa) { 856 ifp->if_addrlist = ifa->ifa_next; 857 } else { 858 while (ifa->ifa_next && 859 (ifa->ifa_next != (struct ifaddr *) aa)) { 860 ifa = ifa->ifa_next; 861 } 862 if (ifa->ifa_next) { 863 ifa->ifa_next = 864 ((struct ifaddr *) aa)->ifa_next; 865 } else { 866 panic("at_entry"); 867 } 868 } 869 } 870 } 871 #endif 872