2 * Copyright (c) 1990,1991 Regents of The University of Michigan.
5 * $DragonFly: src/sys/netproto/atalk/at_control.c,v 1.13 2008/03/07 11:34:21 sephe Exp $
11 #include <sys/sockio.h>
12 #include <sys/malloc.h>
13 #include <sys/kernel.h>
14 #include <sys/socket.h>
15 #include <sys/thread2.h>
17 #include <net/route.h>
18 #include <netinet/in.h>
20 #include <netinet/if_ether.h>
24 #include "at_extern.h"
26 struct at_ifaddr
*at_ifaddr
;
28 static int aa_dorangeroute(struct ifaddr
*ifa
,
29 u_int first
, u_int last
, int cmd
);
30 static int aa_addsingleroute(struct ifaddr
*ifa
,
31 struct at_addr
*addr
, struct at_addr
*mask
);
32 static int aa_delsingleroute(struct ifaddr
*ifa
,
33 struct at_addr
*addr
, struct at_addr
*mask
);
34 static int aa_dosingleroute(struct ifaddr
*ifa
, struct at_addr
*addr
,
35 struct at_addr
*mask
, int cmd
, int flags
);
36 static int at_scrub( struct ifnet
*ifp
, struct at_ifaddr
*aa
);
37 static int at_ifinit( struct ifnet
*ifp
, struct at_ifaddr
*aa
,
38 struct sockaddr_at
*sat
);
39 static int aa_claim_addr(struct ifaddr
*ifa
, struct sockaddr
*gw
);
41 # define sateqaddr(a,b) ((a)->sat_len == (b)->sat_len && \
42 (a)->sat_family == (b)->sat_family && \
43 (a)->sat_addr.s_net == (b)->sat_addr.s_net && \
44 (a)->sat_addr.s_node == (b)->sat_addr.s_node )
47 at_control(struct socket
*so
, u_long cmd
, caddr_t data
,
48 struct ifnet
*ifp
, struct thread
*td
)
50 struct ifreq
*ifr
= (struct ifreq
*)data
;
51 struct sockaddr_at
*sat
;
53 struct at_aliasreq
*ifra
= (struct at_aliasreq
*)data
;
54 struct at_ifaddr
*aa0
;
55 struct at_ifaddr
*aa
= 0;
56 struct ifaddr
*ifa
, *ifa0
;
60 * If we have an ifp, then find the matching at_ifaddr if it exists
63 for ( aa
= at_ifaddr
; aa
; aa
= aa
->aa_next
) {
64 if ( aa
->aa_ifp
== ifp
) break;
69 * In this first switch table we are basically getting ready for
70 * the second one, by getting the atalk-specific things set up
71 * so that they start to look more similar to other protocols etc.
78 * If we have an appletalk sockaddr, scan forward of where
79 * we are now on the at_ifaddr list to find one with a matching
80 * address on this interface.
81 * This may leave aa pointing to the first address on the
84 if ( ifra
->ifra_addr
.sat_family
== AF_APPLETALK
) {
85 for ( ; aa
; aa
= aa
->aa_next
) {
86 if ( aa
->aa_ifp
== ifp
&&
87 sateqaddr( &aa
->aa_addr
, &ifra
->ifra_addr
)) {
93 * If we a retrying to delete an addres but didn't find such,
94 * then rewurn with an error
96 if ( cmd
== SIOCDIFADDR
&& aa
== 0 ) {
97 return( EADDRNOTAVAIL
);
103 * If we are not superuser, then we don't get to do these ops.
108 sat
= satosat( &ifr
->ifr_addr
);
109 nr
= (struct netrange
*)sat
->sat_zero
;
110 if ( nr
->nr_phase
== 1 ) {
112 * Look for a phase 1 address on this interface.
113 * This may leave aa pointing to the first address on the
116 for ( ; aa
; aa
= aa
->aa_next
) {
117 if ( aa
->aa_ifp
== ifp
&&
118 ( aa
->aa_flags
& AFA_PHASE2
) == 0 ) {
122 } else { /* default to phase 2 */
124 * Look for a phase 2 address on this interface.
125 * This may leave aa pointing to the first address on the
128 for ( ; aa
; aa
= aa
->aa_next
) {
129 if ( aa
->aa_ifp
== ifp
&& ( aa
->aa_flags
& AFA_PHASE2
)) {
136 panic( "at_control" );
139 * If we failed to find an existing at_ifaddr entry, then we
140 * allocate a fresh one.
142 if ( aa
== (struct at_ifaddr
*) 0 ) {
143 aa0
= ifa_create(sizeof(struct at_ifaddr
), M_WAITOK
);
144 callout_init(&aa0
->aa_ch
);
145 if (( aa
= at_ifaddr
) != NULL
) {
147 * Don't let the loopback be first, since the first
148 * address is the machine's default address for
150 * If it is, stick ourself in front, otherwise
151 * go to the back of the list.
153 if ( at_ifaddr
->aa_ifp
->if_flags
& IFF_LOOPBACK
) {
155 aa
->aa_next
= at_ifaddr
;
158 for ( ; aa
->aa_next
; aa
= aa
->aa_next
)
168 * Find the end of the interface's addresses
169 * and link our new one on the end
171 ifa
= (struct ifaddr
*)aa
;
172 ifa_iflink(ifa
, ifp
, 1);
175 * As the at_ifaddr contains the actual sockaddrs,
176 * and the ifaddr itself, link them al together correctly.
178 ifa
->ifa_addr
= (struct sockaddr
*)&aa
->aa_addr
;
179 ifa
->ifa_dstaddr
= (struct sockaddr
*)&aa
->aa_addr
;
180 ifa
->ifa_netmask
= (struct sockaddr
*)&aa
->aa_netmask
;
183 * Set/clear the phase 2 bit.
185 if ( nr
->nr_phase
== 1 ) {
186 aa
->aa_flags
&= ~AFA_PHASE2
;
188 aa
->aa_flags
|= AFA_PHASE2
;
192 * and link it all together
197 * If we DID find one then we clobber any routes dependent on it..
204 sat
= satosat( &ifr
->ifr_addr
);
205 nr
= (struct netrange
*)sat
->sat_zero
;
206 if ( nr
->nr_phase
== 1 ) {
208 * If the request is specifying phase 1, then
209 * only look at a phase one address
211 for ( ; aa
; aa
= aa
->aa_next
) {
212 if ( aa
->aa_ifp
== ifp
&&
213 ( aa
->aa_flags
& AFA_PHASE2
) == 0 ) {
221 for ( ; aa
; aa
= aa
->aa_next
) {
222 if ( aa
->aa_ifp
== ifp
&& ( aa
->aa_flags
& AFA_PHASE2
)) {
228 if ( aa
== (struct at_ifaddr
*) 0 )
229 return( EADDRNOTAVAIL
);
234 * By the time this switch is run we should be able to assume that
235 * the "aa" pointer is valid when needed.
241 * copy the contents of the sockaddr blindly.
243 sat
= (struct sockaddr_at
*)&ifr
->ifr_addr
;
247 * and do some cleanups
249 ((struct netrange
*)&sat
->sat_zero
)->nr_phase
250 = (aa
->aa_flags
& AFA_PHASE2
) ? 2 : 1;
251 ((struct netrange
*)&sat
->sat_zero
)->nr_firstnet
= aa
->aa_firstnet
;
252 ((struct netrange
*)&sat
->sat_zero
)->nr_lastnet
= aa
->aa_lastnet
;
256 return( at_ifinit( ifp
, aa
, (struct sockaddr_at
*)&ifr
->ifr_addr
));
259 if ( sateqaddr( &ifra
->ifra_addr
, &aa
->aa_addr
)) {
262 return( at_ifinit( ifp
, aa
, (struct sockaddr_at
*)&ifr
->ifr_addr
));
266 * scrub all routes.. didn't we just DO this? XXX yes, del it
271 * remove the ifaddr from the interface
273 ifa0
= (struct ifaddr
*)aa
;
274 ifa_ifunlink(ifa0
, ifp
);
277 * Now remove the at_ifaddr from the parallel structure
278 * as well, or we'd be in deep trouble
281 if ( aa0
== ( aa
= at_ifaddr
)) {
282 at_ifaddr
= aa
->aa_next
;
284 while ( aa
->aa_next
&& ( aa
->aa_next
!= aa0
)) {
289 * if we found it, remove it, otherwise we screwed up.
292 aa
->aa_next
= aa0
->aa_next
;
294 panic( "at_control" );
299 * Now dump the memory we were using.
300 * Decrement the reference count.
301 * This should probably be the last reference
302 * as the count will go from 1 to 0.
303 * (unless there is still a route referencing this)
309 if ( ifp
== 0 || ifp
->if_ioctl
== 0 )
310 return( EOPNOTSUPP
);
311 lwkt_serialize_enter(ifp
->if_serializer
);
312 error
= ifp
->if_ioctl(ifp
, cmd
, data
, td
->td_proc
->p_ucred
);
313 lwkt_serialize_exit(ifp
->if_serializer
);
320 * Given an interface and an at_ifaddr (supposedly on that interface)
321 * remove any routes that depend on this.
322 * Why ifp is needed I'm not sure,
323 * as aa->at_ifaddr.ifa_ifp should be the same.
326 at_scrub(struct ifnet
*ifp
, struct at_ifaddr
*aa
)
330 if ( aa
->aa_flags
& AFA_ROUTE
) {
331 if (ifp
->if_flags
& IFF_LOOPBACK
) {
332 if ((error
= aa_delsingleroute(&aa
->aa_ifa
,
333 &aa
->aa_addr
.sat_addr
,
334 &aa
->aa_netmask
.sat_addr
)) != 0) {
337 } else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
338 if ((error
= rtinit( &aa
->aa_ifa
, RTM_DELETE
, RTF_HOST
)) != 0)
340 } else if (ifp
->if_flags
& IFF_BROADCAST
) {
341 error
= aa_dorangeroute(&aa
->aa_ifa
,
342 ntohs(aa
->aa_firstnet
),
343 ntohs(aa
->aa_lastnet
),
346 aa
->aa_ifa
.ifa_flags
&= ~IFA_ROUTE
;
347 aa
->aa_flags
&= ~AFA_ROUTE
;
353 * given an at_ifaddr,a sockaddr_at and an ifp,
354 * bang them all together at high speed and see what happens
357 at_ifinit(struct ifnet
*ifp
, struct at_ifaddr
*aa
, struct sockaddr_at
*sat
)
359 struct netrange nr
, onr
;
360 struct sockaddr_at oldaddr
;
362 int netinc
, nodeinc
, nnets
;
368 * save the old addresses in the at_ifaddr just in case we need them.
370 oldaddr
= aa
->aa_addr
;
371 onr
.nr_firstnet
= aa
->aa_firstnet
;
372 onr
.nr_lastnet
= aa
->aa_lastnet
;
375 * take the address supplied as an argument, and add it to the
376 * at_ifnet (also given). Remember ing to update
377 * those parts of the at_ifaddr that need special processing
379 bzero( AA_SAT( aa
), sizeof( struct sockaddr_at
));
380 bcopy( sat
->sat_zero
, &nr
, sizeof( struct netrange
));
381 bcopy( sat
->sat_zero
, AA_SAT( aa
)->sat_zero
, sizeof( struct netrange
));
382 nnets
= ntohs( nr
.nr_lastnet
) - ntohs( nr
.nr_firstnet
) + 1;
383 aa
->aa_firstnet
= nr
.nr_firstnet
;
384 aa
->aa_lastnet
= nr
.nr_lastnet
;
388 kprintf("at_ifinit: %s: %u.%u range %u-%u phase %d\n",
390 ntohs(sat
->sat_addr
.s_net
), sat
->sat_addr
.s_node
,
391 ntohs(aa
->aa_firstnet
), ntohs(aa
->aa_lastnet
),
392 (aa
->aa_flags
& AFA_PHASE2
) ? 2 : 1);
396 * We could eliminate the need for a second phase 1 probe (post
397 * autoconf) if we check whether we're resetting the node. Note
398 * that phase 1 probes use only nodes, not net.node pairs. Under
399 * phase 2, both the net and node must be the same.
401 if ( ifp
->if_flags
& IFF_LOOPBACK
) {
402 AA_SAT( aa
)->sat_len
= sat
->sat_len
;
403 AA_SAT( aa
)->sat_family
= AF_APPLETALK
;
404 AA_SAT( aa
)->sat_addr
.s_net
= sat
->sat_addr
.s_net
;
405 AA_SAT( aa
)->sat_addr
.s_node
= sat
->sat_addr
.s_node
;
407 } else if ( fp
->if_flags
& IFF_POINTOPOINT
) {
410 * we'd have to copy the dstaddr field over from the sat
411 * but it's not clear that it would contain the right info..
416 * We are a normal (probably ethernet) interface.
417 * apply the new address to the interface structures etc.
418 * We will probe this address on the net first, before
419 * applying it to ensure that it is free.. If it is not, then
420 * we will try a number of other randomly generated addresses
421 * in this net and then increment the net. etc.etc. until
422 * we find an unused address.
424 aa
->aa_flags
|= AFA_PROBING
; /* if not loopback we Must probe? */
425 AA_SAT( aa
)->sat_len
= sizeof(struct sockaddr_at
);
426 AA_SAT( aa
)->sat_family
= AF_APPLETALK
;
427 if ( aa
->aa_flags
& AFA_PHASE2
) {
428 if ( sat
->sat_addr
.s_net
== ATADDR_ANYNET
) {
430 * If we are phase 2, and the net was not specified
431 * then we select a random net within the supplied netrange.
432 * XXX use /dev/random?
435 net
= ntohs( nr
.nr_firstnet
) + time_second
% ( nnets
- 1 );
437 net
= ntohs( nr
.nr_firstnet
);
441 * if a net was supplied, then check that it is within
442 * the netrange. If it is not then replace the old values
443 * and return an error
445 if ( ntohs( sat
->sat_addr
.s_net
) < ntohs( nr
.nr_firstnet
) ||
446 ntohs( sat
->sat_addr
.s_net
) > ntohs( nr
.nr_lastnet
)) {
447 aa
->aa_addr
= oldaddr
;
448 aa
->aa_firstnet
= onr
.nr_firstnet
;
449 aa
->aa_lastnet
= onr
.nr_lastnet
;
454 * otherwise just use the new net number..
456 net
= ntohs( sat
->sat_addr
.s_net
);
460 * we must be phase one, so just use whatever we were given.
461 * I guess it really isn't going to be used... RIGHT?
463 net
= ntohs( sat
->sat_addr
.s_net
);
467 * set the node part of the address into the ifaddr.
468 * If it's not specified, be random about it...
469 * XXX use /dev/random?
471 if ( sat
->sat_addr
.s_node
== ATADDR_ANYNODE
) {
472 AA_SAT( aa
)->sat_addr
.s_node
= time_second
;
474 AA_SAT( aa
)->sat_addr
.s_node
= sat
->sat_addr
.s_node
;
480 AA_SAT( aa
)->sat_range
.r_netrange
.nr_phase
481 = ((aa
->aa_flags
& AFA_PHASE2
) ? 2:1);
484 * step through the nets in the range
485 * starting at the (possibly random) start point.
487 for ( i
= nnets
, netinc
= 1; i
> 0; net
= ntohs( nr
.nr_firstnet
) +
488 (( net
- ntohs( nr
.nr_firstnet
) + netinc
) % nnets
), i
-- ) {
489 AA_SAT( aa
)->sat_addr
.s_net
= htons( net
);
492 * using a rather strange stepping method,
493 * stagger through the possible node addresses
494 * Once again, starting at the (possibly random)
495 * initial node address.
497 for ( j
= 0, nodeinc
= time_second
| 1; j
< 256;
498 j
++, AA_SAT( aa
)->sat_addr
.s_node
+= nodeinc
) {
499 if ( AA_SAT( aa
)->sat_addr
.s_node
> 253 ||
500 AA_SAT( aa
)->sat_addr
.s_node
< 1 ) {
506 * start off the probes as an asynchronous activity.
507 * though why wait 200mSec?
509 callout_reset(&aa
->aa_ch
, hz
/ 5, aarpprobe
, ifp
);
510 if ( tsleep( aa
, PCATCH
, "at_ifinit", 0 )) {
512 * theoretically we shouldn't time out here
513 * so if we returned with an error..
515 kprintf( "at_ifinit: why did this happen?!\n" );
516 aa
->aa_addr
= oldaddr
;
517 aa
->aa_firstnet
= onr
.nr_firstnet
;
518 aa
->aa_lastnet
= onr
.nr_lastnet
;
524 * The async activity should have woken us up.
525 * We need to see if it was successful in finding
526 * a free spot, or if we need to iterate to the next
529 if (( aa
->aa_flags
& AFA_PROBING
) == 0 ) {
535 * of course we need to break out through two loops...
537 if (( aa
->aa_flags
& AFA_PROBING
) == 0 ) {
540 /* reset node for next network */
541 AA_SAT( aa
)->sat_addr
.s_node
= time_second
;
545 * if we are still trying to probe, then we have finished all
546 * the possible addresses, so we need to give up
549 if ( aa
->aa_flags
& AFA_PROBING
) {
550 aa
->aa_addr
= oldaddr
;
551 aa
->aa_firstnet
= onr
.nr_firstnet
;
552 aa
->aa_lastnet
= onr
.nr_lastnet
;
554 return( EADDRINUSE
);
559 * Now that we have selected an address, we need to tell the interface
560 * about it, just in case it needs to adjust something.
562 lwkt_serialize_enter(ifp
->if_serializer
);
564 (error
= ifp
->if_ioctl(ifp
, SIOCSIFADDR
, (caddr_t
)aa
, NULL
))
567 * of course this could mean that it objects violently
568 * so if it does, we back out again..
570 aa
->aa_addr
= oldaddr
;
571 aa
->aa_firstnet
= onr
.nr_firstnet
;
572 aa
->aa_lastnet
= onr
.nr_lastnet
;
573 lwkt_serialize_exit(ifp
->if_serializer
);
577 lwkt_serialize_exit(ifp
->if_serializer
);
580 * set up the netmask part of the at_ifaddr
581 * and point the appropriate pointer in the ifaddr to it.
582 * probably pointless, but what the heck.. XXX
584 bzero(&aa
->aa_netmask
, sizeof(aa
->aa_netmask
));
585 aa
->aa_netmask
.sat_len
= sizeof(struct sockaddr_at
);
586 aa
->aa_netmask
.sat_family
= AF_APPLETALK
;
587 aa
->aa_netmask
.sat_addr
.s_net
= 0xffff;
588 aa
->aa_netmask
.sat_addr
.s_node
= 0;
589 aa
->aa_ifa
.ifa_netmask
=(struct sockaddr
*) &(aa
->aa_netmask
); /* XXX */
592 * Initialize broadcast (or remote p2p) address
594 bzero(&aa
->aa_broadaddr
, sizeof(aa
->aa_broadaddr
));
595 aa
->aa_broadaddr
.sat_len
= sizeof(struct sockaddr_at
);
596 aa
->aa_broadaddr
.sat_family
= AF_APPLETALK
;
598 aa
->aa_ifa
.ifa_metric
= ifp
->if_metric
;
599 if (ifp
->if_flags
& IFF_BROADCAST
) {
600 aa
->aa_broadaddr
.sat_addr
.s_net
= htons(0);
601 aa
->aa_broadaddr
.sat_addr
.s_node
= 0xff;
602 aa
->aa_ifa
.ifa_broadaddr
= (struct sockaddr
*) &aa
->aa_broadaddr
;
603 /* add the range of routes needed */
604 error
= aa_dorangeroute(&aa
->aa_ifa
,
605 ntohs(aa
->aa_firstnet
), ntohs(aa
->aa_lastnet
), RTM_ADD
);
607 else if (ifp
->if_flags
& IFF_POINTOPOINT
) {
608 struct at_addr rtaddr
, rtmask
;
610 bzero(&rtaddr
, sizeof(rtaddr
));
611 bzero(&rtmask
, sizeof(rtmask
));
612 /* fill in the far end if we know it here XXX */
613 aa
->aa_ifa
.ifa_dstaddr
= (struct sockaddr
*) &aa
->aa_dstaddr
;
614 error
= aa_addsingleroute(&aa
->aa_ifa
, &rtaddr
, &rtmask
);
616 else if ( ifp
->if_flags
& IFF_LOOPBACK
) {
617 struct at_addr rtaddr
, rtmask
;
619 bzero(&rtaddr
, sizeof(rtaddr
));
620 bzero(&rtmask
, sizeof(rtmask
));
621 rtaddr
.s_net
= AA_SAT( aa
)->sat_addr
.s_net
;
622 rtaddr
.s_node
= AA_SAT( aa
)->sat_addr
.s_node
;
623 rtmask
.s_net
= 0xffff;
624 rtmask
.s_node
= 0x0; /* XXX should not be so.. should be HOST route */
625 error
= aa_addsingleroute(&aa
->aa_ifa
, &rtaddr
, &rtmask
);
630 * set the address of our "check if this addr is ours" routine.
632 aa
->aa_ifa
.ifa_claim_addr
= aa_claim_addr
;
635 * of course if we can't add these routes we back out, but it's getting
640 aa
->aa_addr
= oldaddr
;
641 aa
->aa_firstnet
= onr
.nr_firstnet
;
642 aa
->aa_lastnet
= onr
.nr_lastnet
;
648 * note that the address has a route associated with it....
650 aa
->aa_ifa
.ifa_flags
|= IFA_ROUTE
;
651 aa
->aa_flags
|= AFA_ROUTE
;
657 * check whether a given address is a broadcast address for us..
660 at_broadcast(struct sockaddr_at
*sat
)
662 struct at_ifaddr
*aa
;
665 * If the node is not right, it can't be a broadcast
667 if ( sat
->sat_addr
.s_node
!= ATADDR_BCAST
) {
672 * If the node was right then if the net is right, it's a broadcast
674 if ( sat
->sat_addr
.s_net
== ATADDR_ANYNET
) {
679 * failing that, if the net is one we have, it's a broadcast as well.
681 for ( aa
= at_ifaddr
; aa
; aa
= aa
->aa_next
) {
682 if (( aa
->aa_ifp
->if_flags
& IFF_BROADCAST
)
683 && ( ntohs( sat
->sat_addr
.s_net
) >= ntohs( aa
->aa_firstnet
)
684 && ntohs( sat
->sat_addr
.s_net
) <= ntohs( aa
->aa_lastnet
))) {
694 * Add a route for a range of networks from bot to top - 1.
697 * Split the range into two subranges such that the middle
698 * of the two ranges is the point where the highest bit of difference
699 * between the two addresses makes its transition.
700 * Each of the upper and lower ranges might not exist, or might be
701 * representable by 1 or more netmasks. In addition, if both
702 * ranges can be represented by the same netmask, then they can be merged
703 * by using the next higher netmask..
707 aa_dorangeroute(struct ifaddr
*ifa
, u_int bot
, u_int top
, int cmd
)
715 * slight sanity check
717 if (bot
> top
) return (EINVAL
);
722 * just start out with the lowest boundary
723 * and keep extending the mask till it's too big.
728 while ((( bot
& ~mask1
) >= bot
)
729 && (( bot
| mask1
) <= top
)) {
734 mask
.s_net
= htons(~mask1
);
735 addr
.s_net
= htons(bot
);
737 error
= aa_addsingleroute(ifa
,&addr
,&mask
);
743 error
= aa_delsingleroute(ifa
,&addr
,&mask
);
745 bot
= (bot
| mask1
) + 1;
751 aa_addsingleroute(struct ifaddr
*ifa
,
752 struct at_addr
*addr
, struct at_addr
*mask
)
757 kprintf("aa_addsingleroute: %x.%x mask %x.%x ...\n",
758 ntohs(addr
->s_net
), addr
->s_node
,
759 ntohs(mask
->s_net
), mask
->s_node
);
762 error
= aa_dosingleroute(ifa
, addr
, mask
, RTM_ADD
, RTF_UP
);
764 kprintf("aa_addsingleroute: error %d\n", error
);
769 aa_delsingleroute(struct ifaddr
*ifa
,
770 struct at_addr
*addr
, struct at_addr
*mask
)
774 error
= aa_dosingleroute(ifa
, addr
, mask
, RTM_DELETE
, 0);
776 kprintf("aa_delsingleroute: error %d\n", error
);
781 aa_dosingleroute(struct ifaddr
*ifa
,
782 struct at_addr
*at_addr
, struct at_addr
*at_mask
, int cmd
, int flags
)
784 struct sockaddr_at addr
, mask
;
786 bzero(&addr
, sizeof(addr
));
787 bzero(&mask
, sizeof(mask
));
788 addr
.sat_family
= AF_APPLETALK
;
789 addr
.sat_len
= sizeof(struct sockaddr_at
);
790 addr
.sat_addr
.s_net
= at_addr
->s_net
;
791 addr
.sat_addr
.s_node
= at_addr
->s_node
;
792 mask
.sat_family
= AF_APPLETALK
;
793 mask
.sat_len
= sizeof(struct sockaddr_at
);
794 mask
.sat_addr
.s_net
= at_mask
->s_net
;
795 mask
.sat_addr
.s_node
= at_mask
->s_node
;
798 return(rtrequest(cmd
, (struct sockaddr
*) &addr
,
799 (flags
& RTF_HOST
)?(ifa
->ifa_dstaddr
):(ifa
->ifa_addr
),
800 (struct sockaddr
*) &mask
, flags
, NULL
));
804 aa_claim_addr(struct ifaddr
*ifa
, struct sockaddr
*gw0
)
806 struct sockaddr_at
*addr
= (struct sockaddr_at
*)ifa
->ifa_addr
;
807 struct sockaddr_at
*gw
= (struct sockaddr_at
*)gw0
;
809 switch (gw
->sat_range
.r_netrange
.nr_phase
) {
811 if(addr
->sat_range
.r_netrange
.nr_phase
== 1)
816 * if it's our net (including 0),
817 * or netranges are valid, and we are in the range,
820 if ((addr
->sat_addr
.s_net
== gw
->sat_addr
.s_net
)
821 || ((addr
->sat_range
.r_netrange
.nr_lastnet
)
822 && (ntohs(gw
->sat_addr
.s_net
)
823 >= ntohs(addr
->sat_range
.r_netrange
.nr_firstnet
))
824 && (ntohs(gw
->sat_addr
.s_net
)
825 <= ntohs(addr
->sat_range
.r_netrange
.nr_lastnet
)))) {
830 kprintf("atalk: bad phase\n");