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