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