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/types.h> 10#include <sys/errno.h> 11#include <sys/ioctl.h> 12#include <sys/mbuf.h> |
13#include <sys/kernel.h> |
14#include <sys/socket.h> 15#include <sys/socketvar.h> 16#include <net/if.h> |
17#include <net/route.h> 18#include <netinet/in.h> 19#undef s_net 20#include <netinet/if_ether.h> |
21 22#include "at.h" 23#include "at_var.h" 24#include "aarp.h" 25#include "phase2.h" 26#include <netatalk/at_extern.h> 27 |
28static int aa_addrangeroute(struct ifaddr *ifa, int first, int last); 29static int aa_addsingleroute(struct ifaddr *ifa, 30 struct at_addr *addr, struct at_addr *mask); 31static int aa_delsingleroute(struct ifaddr *ifa, 32 struct at_addr *addr, struct at_addr *mask); 33static int aa_dosingleroute(struct ifaddr *ifa, struct at_addr *addr, 34 struct at_addr *mask, int cmd, int flags); |
35static int at_scrub( struct ifnet *ifp, struct at_ifaddr *aa ); 36static int at_ifinit( struct ifnet *ifp, struct at_ifaddr *aa, 37 struct sockaddr_at *sat ); 38 |
39# define sateqaddr(a,b) ((a)->sat_len == (b)->sat_len && \ 40 (a)->sat_family == (b)->sat_family && \ 41 (a)->sat_addr.s_net == (b)->sat_addr.s_net && \ 42 (a)->sat_addr.s_node == (b)->sat_addr.s_node ) |
43 |
44int |
45at_control( int cmd, caddr_t data, 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 mbuf *m; 54 struct ifaddr *ifa; 55 56 if ( ifp ) { 57 for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 58 if ( aa->aa_ifp == ifp ) break; 59 } 60 } 61 62 switch ( cmd ) { |
63 case SIOCAIFADDR: 64 case SIOCDIFADDR: 65 if ( ifra->ifra_addr.sat_family == AF_APPLETALK ) { 66 for ( ; aa; aa = aa->aa_next ) { 67 if ( aa->aa_ifp == ifp && 68 sateqaddr( &aa->aa_addr, &ifra->ifra_addr )) { 69 break; 70 } 71 } 72 } 73 if ( cmd == SIOCDIFADDR && aa == 0 ) { 74 return( EADDRNOTAVAIL ); 75 } 76 /*FALLTHROUGH*/ |
77 78 case SIOCSIFADDR: |
79 if ( suser(p->p_ucred, &p->p_acflag) ) { |
80 return( EPERM ); 81 } |
82 83 sat = satosat( &ifr->ifr_addr ); 84 nr = (struct netrange *)sat->sat_zero; 85 if ( nr->nr_phase == 1 ) { 86 for ( ; aa; aa = aa->aa_next ) { 87 if ( aa->aa_ifp == ifp && 88 ( aa->aa_flags & AFA_PHASE2 ) == 0 ) { 89 break; --- 40 unchanged lines hidden (view full) --- 130 if (( ifa = ifp->if_addrlist ) != NULL ) { 131 for ( ; ifa->ifa_next; ifa = ifa->ifa_next ) 132 ; 133 ifa->ifa_next = (struct ifaddr *)aa; 134 } else { 135 ifp->if_addrlist = (struct ifaddr *)aa; 136 } 137 |
138 aa->aa_ifa.ifa_addr = (struct sockaddr *)&aa->aa_addr; 139 aa->aa_ifa.ifa_dstaddr = (struct sockaddr *)&aa->aa_addr; 140 aa->aa_ifa.ifa_netmask = (struct sockaddr *)&aa->aa_netmask; |
141 142 /* 143 * Set/clear the phase 2 bit. 144 */ 145 if ( nr->nr_phase == 1 ) { 146 aa->aa_flags &= ~AFA_PHASE2; 147 } else { 148 aa->aa_flags |= AFA_PHASE2; --- 24 unchanged lines hidden (view full) --- 173 174 if ( aa == (struct at_ifaddr *) 0 ) 175 return( EADDRNOTAVAIL ); 176 break; 177 } 178 179 switch ( cmd ) { 180 case SIOCGIFADDR: |
181 sat = (struct sockaddr_at *)&ifr->ifr_addr; 182 *sat = aa->aa_addr; 183 ((struct netrange *)&sat->sat_zero)->nr_phase 184 = (aa->aa_flags & AFA_PHASE2) ? 2 : 1; 185 ((struct netrange *)&sat->sat_zero)->nr_firstnet = aa->aa_firstnet; 186 ((struct netrange *)&sat->sat_zero)->nr_lastnet = aa->aa_lastnet; |
187 break; 188 189 case SIOCSIFADDR: 190 return( at_ifinit( ifp, aa, (struct sockaddr_at *)&ifr->ifr_addr )); 191 |
192 case SIOCAIFADDR: 193 if ( sateqaddr( &ifra->ifra_addr, &aa->aa_addr )) { 194 return( 0 ); 195 } 196 return( at_ifinit( ifp, aa, (struct sockaddr_at *)&ifr->ifr_addr )); 197 198 case SIOCDIFADDR: 199 at_scrub( ifp, aa ); --- 20 unchanged lines hidden (view full) --- 220 if ( aa->aa_next ) { 221 aa->aa_next = aa0->aa_next; 222 } else { 223 panic( "at_control" ); 224 } 225 } 226 m_free( dtom( aa0 )); 227 break; |
228 229 default: 230 if ( ifp == 0 || ifp->if_ioctl == 0 ) 231 return( EOPNOTSUPP ); 232 return( (*ifp->if_ioctl)( ifp, cmd, data )); 233 } 234 return( 0 ); 235} |
236 |
237static int 238at_scrub( ifp, aa ) 239 struct ifnet *ifp; 240 struct at_ifaddr *aa; 241{ |
242 int error; 243 244 if ( aa->aa_flags & AFA_ROUTE ) { |
245 if (( error = rtinit( &(aa->aa_ifa), RTM_DELETE, 246 ( ifp->if_flags & IFF_LOOPBACK ) ? RTF_HOST : 0 )) != 0 ) { 247 return( error ); 248 } 249 aa->aa_ifa.ifa_flags &= ~IFA_ROUTE; |
250 aa->aa_flags &= ~AFA_ROUTE; 251 } 252 return( 0 ); 253} 254 |
255static int 256at_ifinit( ifp, aa, sat ) 257 struct ifnet *ifp; 258 struct at_ifaddr *aa; 259 struct sockaddr_at *sat; 260{ 261 struct netrange nr, onr; |
262 struct sockaddr_at oldaddr; |
263 int s = splimp(), error = 0, i, j; 264 int flags = RTF_UP, netinc, nodeinc, nnets; |
265 u_short net; 266 267 oldaddr = aa->aa_addr; 268 bzero( AA_SAT( aa ), sizeof( struct sockaddr_at )); 269 bcopy( sat->sat_zero, &nr, sizeof( struct netrange )); |
270 bcopy( sat->sat_zero, AA_SAT( aa )->sat_zero, sizeof( struct netrange )); |
271 nnets = ntohs( nr.nr_lastnet ) - ntohs( nr.nr_firstnet ) + 1; 272 273 onr.nr_firstnet = aa->aa_firstnet; 274 onr.nr_lastnet = aa->aa_lastnet; 275 aa->aa_firstnet = nr.nr_firstnet; 276 aa->aa_lastnet = nr.nr_lastnet; 277 |
278/* XXX ALC */ 279 printf("at_ifinit: %s: %u.%u range %u-%u phase %d\n", 280 ifp->if_name, 281 ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node, 282 ntohs(aa->aa_firstnet), ntohs(aa->aa_lastnet), 283 (aa->aa_flags & AFA_PHASE2) ? 2 : 1); 284 |
285 /* 286 * We could eliminate the need for a second phase 1 probe (post 287 * autoconf) if we check whether we're resetting the node. Note 288 * that phase 1 probes use only nodes, not net.node pairs. Under 289 * phase 2, both the net and node must be the same. 290 */ 291 if ( ifp->if_flags & IFF_LOOPBACK ) { |
292 AA_SAT( aa )->sat_len = sat->sat_len; |
293 AA_SAT( aa )->sat_family = AF_APPLETALK; 294 AA_SAT( aa )->sat_addr.s_net = sat->sat_addr.s_net; 295 AA_SAT( aa )->sat_addr.s_node = sat->sat_addr.s_node; |
296#if 0 297 } else if ( fp->if_flags & IFF_POINTOPOINT) { 298 /* unimplemented */ 299#endif |
300 } else { 301 aa->aa_flags |= AFA_PROBING; |
302 AA_SAT( aa )->sat_len = sizeof(struct sockaddr_at); |
303 AA_SAT( aa )->sat_family = AF_APPLETALK; 304 if ( aa->aa_flags & AFA_PHASE2 ) { 305 if ( sat->sat_addr.s_net == ATADDR_ANYNET ) { 306 if ( nnets != 1 ) { 307 net = ntohs( nr.nr_firstnet ) + time.tv_sec % ( nnets - 1 ); 308 } else { 309 net = ntohs( nr.nr_firstnet ); 310 } --- 25 unchanged lines hidden (view full) --- 336 j++, AA_SAT( aa )->sat_addr.s_node += nodeinc ) { 337 if ( AA_SAT( aa )->sat_addr.s_node > 253 || 338 AA_SAT( aa )->sat_addr.s_node < 1 ) { 339 continue; 340 } 341 aa->aa_probcnt = 10; 342 timeout( (timeout_func_t)aarpprobe, (caddr_t)ifp, hz / 5 ); 343 splx( s ); |
344 if ( tsleep( aa, PPAUSE|PCATCH, "at_ifinit", 0 )) { 345 printf( "at_ifinit: why did this happen?!\n" ); |
346 aa->aa_addr = oldaddr; 347 aa->aa_firstnet = onr.nr_firstnet; 348 aa->aa_lastnet = onr.nr_lastnet; 349 return( EINTR ); 350 } 351 s = splimp(); 352 if (( aa->aa_flags & AFA_PROBING ) == 0 ) { 353 break; --- 12 unchanged lines hidden (view full) --- 366 aa->aa_lastnet = onr.nr_lastnet; 367 splx( s ); 368 return( EADDRINUSE ); 369 } 370 } 371 372 if ( ifp->if_ioctl && 373 ( error = (*ifp->if_ioctl)( ifp, SIOCSIFADDR, (caddr_t)aa ))) { |
374 aa->aa_addr = oldaddr; 375 aa->aa_firstnet = onr.nr_firstnet; 376 aa->aa_lastnet = onr.nr_lastnet; |
377 splx( s ); |
378 return( error ); 379 } 380 |
381 /* Initialize interface netmask, which is silly for us */ 382 383 bzero(&aa->aa_netmask, sizeof(aa->aa_netmask)); 384 aa->aa_netmask.sat_len = sizeof(struct sockaddr_at); |
385 aa->aa_netmask.sat_family = AF_APPLETALK; |
386 aa->aa_ifa.ifa_netmask = (struct sockaddr *) &aa->aa_netmask; |
387 |
388 /* "Add a route to the network" */ 389 390 aa->aa_ifa.ifa_metric = ifp->if_metric; 391 if (ifp->if_flags & IFF_BROADCAST) { 392 bzero(&aa->aa_broadaddr, sizeof(aa->aa_broadaddr)); 393 aa->aa_broadaddr.sat_len = sat->sat_len; 394 aa->aa_broadaddr.sat_family = AF_APPLETALK; 395 aa->aa_broadaddr.sat_addr.s_net = htons(0); 396 aa->aa_broadaddr.sat_addr.s_node = 0xff; 397 aa->aa_ifa.ifa_broadaddr = (struct sockaddr *) &aa->aa_broadaddr; 398 aa->aa_netmask.sat_addr.s_net = htons(0xffff); /* XXX */ 399 aa->aa_netmask.sat_addr.s_node = htons(0); /* XXX */ 400 } else if (ifp->if_flags & IFF_LOOPBACK) { 401 aa->aa_ifa.ifa_dstaddr = aa->aa_ifa.ifa_addr; 402 aa->aa_netmask.sat_addr.s_net = htons(0xffff); /* XXX */ 403 aa->aa_netmask.sat_addr.s_node = htons(0xffff); /* XXX */ 404 flags |= RTF_HOST; 405 } else if (ifp->if_flags & IFF_POINTOPOINT) { 406 aa->aa_ifa.ifa_dstaddr = aa->aa_ifa.ifa_addr; 407 aa->aa_netmask.sat_addr.s_net = htons(0xffff); 408 aa->aa_netmask.sat_addr.s_node = htons(0xffff); 409 flags |= RTF_HOST; 410 } 411 error = rtinit(&(aa->aa_ifa), (int)RTM_ADD, flags); 412 413#if 0 |
414 if ( ifp->if_flags & IFF_LOOPBACK ) { |
415 struct at_addr rtaddr, rtmask; 416 417 bzero(&rtaddr, sizeof(rtaddr)); 418 bzero(&rtmask, sizeof(rtmask)); 419 rtaddr.s_net = AA_SAT( aa )->sat_addr.s_net; 420 rtaddr.s_node = AA_SAT( aa )->sat_addr.s_node; 421 rtmask.s_net = 0xffff; 422 rtmask.s_node = 0xff; 423 424 error = aa_addsingleroute(&aa->aa_ifa, &rtaddr, &rtmask); 425 |
426 } else { |
427 |
428 /* Install routes for our own network, and then also for 429 all networks above and below it in the network range */ 430 431 error = aa_addrangeroute(&aa->aa_ifa, 432 ntohs(aa->aa_addr.sat_addr.s_net), 433 ntohs(aa->aa_addr.sat_addr.s_net) + 1); 434 if (!error 435 && ntohs(aa->aa_firstnet) < ntohs(aa->aa_addr.sat_addr.s_net)) 436 error = aa_addrangeroute(&aa->aa_ifa, 437 ntohs(aa->aa_firstnet), ntohs(aa->aa_addr.sat_addr.s_net)); 438 if (!error 439 && ntohs(aa->aa_addr.sat_addr.s_net) < ntohs(aa->aa_lastnet)) 440 error = aa_addrangeroute(&aa->aa_ifa, 441 ntohs(aa->aa_addr.sat_addr.s_net) + 1, 442 ntohs(aa->aa_lastnet) + 1); |
443 } |
444#endif 445 446 |
447 if ( error ) { 448 aa->aa_addr = oldaddr; 449 aa->aa_firstnet = onr.nr_firstnet; 450 aa->aa_lastnet = onr.nr_lastnet; 451 splx( s ); 452 return( error ); 453 } 454 |
455 aa->aa_ifa.ifa_flags |= IFA_ROUTE; |
456 aa->aa_flags |= AFA_ROUTE; 457 splx( s ); 458 return( 0 ); 459} 460 461int 462at_broadcast( sat ) 463 struct sockaddr_at *sat; --- 12 unchanged lines hidden (view full) --- 476 ntohs( sat->sat_addr.s_net ) <= ntohs( aa->aa_lastnet ))) { 477 return( 1 ); 478 } 479 } 480 } 481 return( 0 ); 482} 483 |
484/* 485 * aa_addrangeroute() 486 * 487 * Add a route for a range of networks from bot to top - 1. 488 * Algorithm: 489 * 490 * Split the range into three subranges such that the middle 491 * subrange is from (base + 2^N) to (base + 2^N + 2^(N-1)) for 492 * some N. Then add a route for the middle range and recurse on 493 * the upper and lower sub-ranges. As a degenerate case, it may 494 * be that the middle subrange is empty. 495 */ 496 497static int 498aa_addrangeroute(struct ifaddr *ifa, int bot, int top) 499{ 500 int base, mask, mbot, mtop; 501 int a, b, abit, bbit, error; 502 struct at_addr rtaddr, rtmask; 503 504/* Special case the whole range */ 505 506 if (bot == 0 && top == 0xffff) 507 { 508 bzero(&rtaddr, sizeof(rtaddr)); 509 bzero(&rtmask, sizeof(rtmask)); 510 return(aa_addsingleroute(ifa, &rtaddr, &rtmask)); 511 } 512 513 if (top <= bot) 514 panic("aa_addrangeroute"); 515 516/* Mask out the high order bits on which both bounds agree */ 517 518 for (mask = 0xffff; (bot & mask) != (top & mask); mask <<= 1); 519 base = bot & mask; 520 a = bot & ~mask; 521 b = top & ~mask; 522 523/* Find suitable powers of two between a and b we can make a route with */ 524 525 for (bbit = 0x8000; bbit > b; bbit >>= 1); 526 if (a == 0) 527 abit = 0; 528 else 529 { 530 for (abit = 0x0001; a > abit; abit <<= 1); 531 if ((abit << 1) > bbit) 532 bbit = abit; 533 else 534 bbit = abit << 1; 535 } 536 537/* Now we have a "square" middle chunk from abit to bbit, possibly empty */ 538 539 mbot = base + abit; 540 mtop = base + bbit; 541 mask = ~(bbit - 1); 542 543/* Route to the middle chunk */ 544 545 if (mbot < mtop) 546 { 547 bzero(&rtaddr, sizeof(rtaddr)); 548 bzero(&rtmask, sizeof(rtmask)); 549 rtaddr.s_net = htons((u_short) mbot); 550 rtmask.s_net = htons((u_short) mask); 551 if ((error = aa_addsingleroute(ifa, &rtaddr, &rtmask))) 552 return(error); 553 } 554 555/* Recurse on the upper and lower chunks we didn't get to */ 556 557 if (bot < mbot) 558 if ((error = aa_addrangeroute(ifa, bot, mbot))) 559 { 560 if (mbot < mtop) 561 aa_delsingleroute(ifa, &rtaddr, &rtmask); 562 return(error); 563 } 564 if (mtop < top) 565 if ((error = aa_addrangeroute(ifa, mtop, top))) 566 { 567 if (mbot < mtop) 568 aa_delsingleroute(ifa, &rtaddr, &rtmask); 569 return(error); 570 } 571 return(0); 572} 573 574static int 575aa_addsingleroute(struct ifaddr *ifa, 576 struct at_addr *addr, struct at_addr *mask) 577{ 578 int error; 579 580 printf("aa_addsingleroute: %x.%x mask %x.%x ...\n", 581 ntohs(addr->s_net), addr->s_node, 582 ntohs(mask->s_net), mask->s_node); 583 584 error = aa_dosingleroute(ifa, addr, mask, RTM_ADD, RTF_UP); 585 if (error) 586 printf("error %d\n", error); 587 return(error); 588} 589 590static int 591aa_delsingleroute(struct ifaddr *ifa, 592 struct at_addr *addr, struct at_addr *mask) 593{ 594 int error; 595 596 error = aa_dosingleroute(ifa, addr, mask, RTM_DELETE, 0); 597 if (error) 598 printf("aa_delsingleroute: error %d\n", error); 599 return(error); 600} 601 602static int 603aa_dosingleroute(struct ifaddr *ifa, 604 struct at_addr *at_addr, struct at_addr *at_mask, int cmd, int flags) 605{ 606 struct sockaddr_at addr, mask; 607 608 bzero(&addr, sizeof(addr)); 609 bzero(&mask, sizeof(mask)); 610 addr.sat_family = AF_APPLETALK; 611 addr.sat_len = sizeof(struct sockaddr_at); 612 addr.sat_addr.s_net = at_addr->s_net; 613 addr.sat_addr.s_node = at_addr->s_node; 614 mask.sat_addr.s_net = at_mask->s_net; 615 mask.sat_addr.s_node = at_mask->s_node; 616 if (at_mask->s_node) 617 flags |= RTF_HOST; 618 return(rtrequest(cmd, (struct sockaddr *) &addr, ifa->ifa_addr, 619 (struct sockaddr *) &mask, flags, NULL)); 620} 621 622#if 0 623 |
624static void 625aa_clean(void) 626{ 627 struct at_ifaddr *aa; 628 struct ifaddr *ifa; 629 struct ifnet *ifp; 630 631 while ( aa = at_ifaddr ) { --- 10 unchanged lines hidden (view full) --- 642 if ( ifa->ifa_next ) { 643 ifa->ifa_next = ((struct ifaddr *)aa)->ifa_next; 644 } else { 645 panic( "at_entry" ); 646 } 647 } 648 } 649} |
650 651#endif 652 |