]> arthur.barton.de Git - netatalk.git/blob - sys/netatalk/at_control.c
Wrong path from 2-1
[netatalk.git] / sys / netatalk / at_control.c
1 /*
2  * $Id: at_control.c,v 1.2 2001-06-29 14:14:47 rufustfirefly Exp $
3  *
4  * Copyright (c) 1990,1991 Regents of The University of Michigan.
5  * All Rights Reserved.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12 #include <sys/param.h>
13 #include <sys/systm.h>
14 #ifdef ibm032
15 #include <sys/dir.h>
16 #endif /* ibm032 */
17 #include <sys/user.h>
18 #include <sys/types.h>
19 #include <sys/errno.h>
20 #include <sys/ioctl.h>
21 #include <sys/mbuf.h>
22 #ifndef _IBMR2
23 #include <sys/kernel.h>
24 #endif /* ! _IBMR2 */
25 #include <sys/socket.h>
26 #include <sys/socketvar.h>
27 #include <net/if.h>
28 #include <net/af.h>
29 #include <net/route.h>
30 #include <netinet/in.h>
31 #undef s_net
32 #include <netinet/if_ether.h>
33 #ifdef _IBMR2
34 #include <net/spl.h>
35 #endif /* _IBMR2 */
36
37 #include "at.h"
38 #include "at_var.h"
39 #include "aarp.h"
40 #include "phase2.h"
41
42 #ifdef BSD4_4
43 # define sateqaddr(a,b) ((a)->sat_len == (b)->sat_len && \
44                     (a)->sat_family == (b)->sat_family && \
45                     (a)->sat_addr.s_net == (b)->sat_addr.s_net && \
46                     (a)->sat_addr.s_node == (b)->sat_addr.s_node )
47 #else /* BSD4_4 */
48 atalk_hash( sat, hp )
49     struct sockaddr_at  *sat;
50     struct afhash       *hp;
51 {
52     hp->afh_nethash = sat->sat_addr.s_net;
53     hp->afh_hosthash = ( sat->sat_addr.s_net << 8 ) +
54             sat->sat_addr.s_node;
55 }
56
57 /*
58  * Note the magic to get ifa_ifwithnet() to work without adding an
59  * ifaddr entry for each net in our local range.
60  */
61 atalk_netmatch( sat1, sat2 )
62     struct sockaddr_at  *sat1, *sat2;
63 {
64     struct at_ifaddr    *aa;
65
66     for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
67         if ( AA_SAT( aa ) == sat1 ) {
68             break;
69         }
70     }
71     if ( aa ) {
72         return( ntohs( aa->aa_firstnet ) <= ntohs( sat2->sat_addr.s_net ) &&
73                 ntohs( aa->aa_lastnet ) >= ntohs( sat2->sat_addr.s_net ));
74     }
75     return( sat1->sat_addr.s_net == sat2->sat_addr.s_net );
76 }
77 #endif /* BSD4_4 */
78
79 at_control( cmd, data, ifp )
80     int                 cmd;
81     caddr_t             data;
82     struct ifnet        *ifp;
83 {
84     struct ifreq        *ifr = (struct ifreq *)data;
85     struct sockaddr_at  *sat;
86     struct netrange     *nr;
87 #ifdef BSD4_4
88     struct at_aliasreq  *ifra = (struct at_aliasreq *)data;
89     struct at_ifaddr    *aa0;
90 #endif /* BSD4_4 */
91     struct at_ifaddr    *aa = 0;
92     struct mbuf         *m;
93     struct ifaddr       *ifa;
94
95     if ( ifp ) {
96         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
97             if ( aa->aa_ifp == ifp ) break;
98         }
99     }
100
101     switch ( cmd ) {
102 #ifdef BSD4_4
103     case SIOCAIFADDR:
104     case SIOCDIFADDR:
105         if ( ifra->ifra_addr.sat_family == AF_APPLETALK ) {
106             for ( ; aa; aa = aa->aa_next ) {
107                 if ( aa->aa_ifp == ifp &&
108                         sateqaddr( &aa->aa_addr, &ifra->ifra_addr )) {
109                     break;
110                 }
111             }
112         }
113         if ( cmd == SIOCDIFADDR && aa == 0 ) {
114             return( EADDRNOTAVAIL );
115         }
116         /*FALLTHROUGH*/
117 #endif /* BSD4_4 */
118
119     case SIOCSIFADDR:
120 #ifdef BSD4_4
121         /*
122          * What a great idea this is: Let's reverse the meaning of
123          * the return...
124          */
125         if ( suser( u.u_cred, &u.u_acflag )) {
126             return( EPERM );
127         }
128 #else /* BSD4_4 */
129         if ( !suser()) {
130             return( EPERM );
131         }
132 #endif /* BSD4_4 */
133
134         sat = satosat( &ifr->ifr_addr );
135         nr = (struct netrange *)sat->sat_zero;
136         if ( nr->nr_phase == 1 ) {
137             for ( ; aa; aa = aa->aa_next ) {
138                 if ( aa->aa_ifp == ifp &&
139                         ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
140                     break;
141                 }
142             }
143         } else {                /* default to phase 2 */
144             for ( ; aa; aa = aa->aa_next ) {
145                 if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 )) {
146                     break;
147                 }
148             }
149         }
150
151         if ( ifp == 0 )
152             panic( "at_control" );
153
154         if ( aa == (struct at_ifaddr *) 0 ) {
155             m = m_getclr( M_WAIT, MT_IFADDR );
156             if ( m == (struct mbuf *)NULL ) {
157                 return( ENOBUFS );
158             }
159
160             if (( aa = at_ifaddr ) != NULL ) {
161                 /*
162                  * Don't let the loopback be first, since the first
163                  * address is the machine's default address for
164                  * binding.
165                  */
166                 if ( at_ifaddr->aa_ifp->if_flags & IFF_LOOPBACK ) {
167                     aa = mtod( m, struct at_ifaddr *);
168                     aa->aa_next = at_ifaddr;
169                     at_ifaddr = aa;
170                 } else {
171                     for ( ; aa->aa_next; aa = aa->aa_next )
172                         ;
173                     aa->aa_next = mtod( m, struct at_ifaddr *);
174                 }
175             } else {
176                 at_ifaddr = mtod( m, struct at_ifaddr *);
177             }
178
179             aa = mtod( m, struct at_ifaddr *);
180
181             if (( ifa = ifp->if_addrlist ) != NULL ) {
182                 for ( ; ifa->ifa_next; ifa = ifa->ifa_next )
183                     ;
184                 ifa->ifa_next = (struct ifaddr *)aa;
185             } else {
186                 ifp->if_addrlist = (struct ifaddr *)aa;
187             }
188
189 #ifdef BSD4_4
190             aa->aa_ifa.ifa_addr = (struct sockaddr *)&aa->aa_addr;
191             aa->aa_ifa.ifa_dstaddr = (struct sockaddr *)&aa->aa_addr;
192             aa->aa_ifa.ifa_netmask = (struct sockaddr *)&aa->aa_netmask;
193 #endif /* BSD4_4 */
194
195             /*
196              * Set/clear the phase 2 bit.
197              */
198             if ( nr->nr_phase == 1 ) {
199                 aa->aa_flags &= ~AFA_PHASE2;
200             } else {
201                 aa->aa_flags |= AFA_PHASE2;
202             }
203             aa->aa_ifp = ifp;
204         } else {
205             at_scrub( ifp, aa );
206         }
207         break;
208
209     case SIOCGIFADDR :
210         sat = satosat( &ifr->ifr_addr );
211         nr = (struct netrange *)sat->sat_zero;
212         if ( nr->nr_phase == 1 ) {
213             for ( ; aa; aa = aa->aa_next ) {
214                 if ( aa->aa_ifp == ifp &&
215                         ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
216                     break;
217                 }
218             }
219         } else {                /* default to phase 2 */
220             for ( ; aa; aa = aa->aa_next ) {
221                 if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 )) {
222                     break;
223                 }
224             }
225         }
226
227         if ( aa == (struct at_ifaddr *) 0 )
228             return( EADDRNOTAVAIL );
229         break;
230     }
231
232     switch ( cmd ) {
233     case SIOCGIFADDR:
234 #ifdef BSD4_4
235         *(struct sockaddr_at *)&ifr->ifr_addr = aa->aa_addr;
236 #else /* BSD4_4 */
237         ifr->ifr_addr = aa->aa_addr;
238 #endif /* BSD4_4 */
239         break;
240
241     case SIOCSIFADDR:
242         return( at_ifinit( ifp, aa, (struct sockaddr_at *)&ifr->ifr_addr ));
243
244 #ifdef BSD4_4
245     case SIOCAIFADDR:
246         if ( sateqaddr( &ifra->ifra_addr, &aa->aa_addr )) {
247             return( 0 );
248         }
249         return( at_ifinit( ifp, aa, (struct sockaddr_at *)&ifr->ifr_addr ));
250
251     case SIOCDIFADDR:
252         at_scrub( ifp, aa );
253         if (( ifa = ifp->if_addrlist ) == (struct ifaddr *)aa ) {
254             ifp->if_addrlist = ifa->ifa_next;
255         } else {
256             while ( ifa->ifa_next && ( ifa->ifa_next != (struct ifaddr *)aa )) {
257                 ifa = ifa->ifa_next;
258             }
259             if ( ifa->ifa_next ) {
260                 ifa->ifa_next = ((struct ifaddr *)aa)->ifa_next;
261             } else {
262                 panic( "at_control" );
263             }
264         }
265
266         aa0 = aa;
267         if ( aa0 == ( aa = at_ifaddr )) {
268             at_ifaddr = aa->aa_next;
269         } else {
270             while ( aa->aa_next && ( aa->aa_next != aa0 )) {
271                 aa = aa->aa_next;
272             }
273             if ( aa->aa_next ) {
274                 aa->aa_next = aa0->aa_next;
275             } else {
276                 panic( "at_control" );
277             }
278         }
279         m_free( dtom( aa0 ));
280         break;
281 #endif /* BSD4_4 */
282
283     default:
284         if ( ifp == 0 || ifp->if_ioctl == 0 )
285             return( EOPNOTSUPP );
286         return( (*ifp->if_ioctl)( ifp, cmd, data ));
287     }
288     return( 0 );
289 }
290
291 at_scrub( ifp, aa )
292     struct ifnet        *ifp;
293     struct at_ifaddr    *aa;
294 {
295 #ifndef BSD4_4
296     struct sockaddr_at  netsat;
297     int                 error;
298     u_short             net;
299 #endif /* ! BSD4_4 */
300
301     if ( aa->aa_flags & AFA_ROUTE ) {
302 #ifdef BSD4_4
303         if (( error = rtinit( &(aa->aa_ifa), RTM_DELETE,
304                 ( ifp->if_flags & IFF_LOOPBACK ) ? RTF_HOST : 0 )) != 0 ) {
305             return( error );
306         }
307         aa->aa_ifa.ifa_flags &= ~IFA_ROUTE;
308 #else /* BSD4_4 */
309         if ( ifp->if_flags & IFF_LOOPBACK ) {
310             rtinit( &aa->aa_addr, &aa->aa_addr, SIOCDELRT, RTF_HOST );
311         } else {
312             bzero( &netsat, sizeof( struct sockaddr_at ));
313             netsat.sat_family = AF_APPLETALK;
314             netsat.sat_addr.s_node = ATADDR_ANYNODE;
315
316             /*
317              * If the range is the full 0-fffe range, just use
318              * the default route.
319              */
320             if ( aa->aa_firstnet == htons( 0x0000 ) &&
321                     aa->aa_lastnet == htons( 0xfffe )) {
322                 netsat.sat_addr.s_net = 0;
323                 rtinit((struct sockaddr *)&netsat, &aa->aa_addr,
324                         (int)SIOCDELRT, 0 );
325             } else {
326                 for ( net = ntohs( aa->aa_firstnet );
327                         net <= ntohs( aa->aa_lastnet ); net++ ) {
328                     netsat.sat_addr.s_net = htons( net );
329                     rtinit((struct sockaddr *)&netsat, &aa->aa_addr,
330                             (int)SIOCDELRT, 0 );
331                 }
332             }
333         }
334 #endif /* BSD4_4 */
335         aa->aa_flags &= ~AFA_ROUTE;
336     }
337     return( 0 );
338 }
339
340 extern struct timeval   time;
341
342 at_ifinit( ifp, aa, sat )
343     struct ifnet        *ifp;
344     struct at_ifaddr    *aa;
345     struct sockaddr_at  *sat;
346 {
347     struct netrange     nr, onr;
348 #ifdef BSD4_4
349     struct sockaddr_at  oldaddr;
350 #else /* BSD4_4 */
351     struct sockaddr     oldaddr;
352 #endif /* BSD4_4 */
353     struct sockaddr_at  netaddr;
354     int                 s = splimp(), error = 0, i, j, netinc, nodeinc, nnets;
355     u_short             net;
356
357     oldaddr = aa->aa_addr;
358     bzero( AA_SAT( aa ), sizeof( struct sockaddr_at ));
359     bcopy( sat->sat_zero, &nr, sizeof( struct netrange ));
360     nnets = ntohs( nr.nr_lastnet ) - ntohs( nr.nr_firstnet ) + 1;
361
362     onr.nr_firstnet = aa->aa_firstnet;
363     onr.nr_lastnet = aa->aa_lastnet;
364     aa->aa_firstnet = nr.nr_firstnet;
365     aa->aa_lastnet = nr.nr_lastnet;
366
367     /*
368      * We could eliminate the need for a second phase 1 probe (post
369      * autoconf) if we check whether we're resetting the node. Note
370      * that phase 1 probes use only nodes, not net.node pairs.  Under
371      * phase 2, both the net and node must be the same.
372      */
373     if ( ifp->if_flags & IFF_LOOPBACK ) {
374 #ifdef BSD4_4
375         AA_SAT( aa )->sat_len = sat->sat_len;
376 #endif /* BSD4_4 */
377         AA_SAT( aa )->sat_family = AF_APPLETALK;
378         AA_SAT( aa )->sat_addr.s_net = sat->sat_addr.s_net;
379         AA_SAT( aa )->sat_addr.s_node = sat->sat_addr.s_node;
380     } else {
381         aa->aa_flags |= AFA_PROBING;
382         AA_SAT( aa )->sat_family = AF_APPLETALK;
383         if ( aa->aa_flags & AFA_PHASE2 ) {
384             if ( sat->sat_addr.s_net == ATADDR_ANYNET ) {
385                 if ( nnets != 1 ) {
386                     net = ntohs( nr.nr_firstnet ) + time.tv_sec % ( nnets - 1 );
387                 } else {
388                     net = ntohs( nr.nr_firstnet );
389                 }
390             } else {
391                 if ( ntohs( sat->sat_addr.s_net ) < ntohs( nr.nr_firstnet ) ||
392                         ntohs( sat->sat_addr.s_net ) > ntohs( nr.nr_lastnet )) {
393                     aa->aa_addr = oldaddr;
394                     aa->aa_firstnet = onr.nr_firstnet;
395                     aa->aa_lastnet = onr.nr_lastnet;
396                     return( EINVAL );
397                 }
398                 net = ntohs( sat->sat_addr.s_net );
399             }
400         } else {
401             net = ntohs( sat->sat_addr.s_net );
402         }
403
404         if ( sat->sat_addr.s_node == ATADDR_ANYNODE ) {
405             AA_SAT( aa )->sat_addr.s_node = time.tv_sec;
406         } else {
407             AA_SAT( aa )->sat_addr.s_node = sat->sat_addr.s_node;
408         }
409
410         for ( i = nnets, netinc = 1; i > 0; net = ntohs( nr.nr_firstnet ) +
411                 (( net - ntohs( nr.nr_firstnet ) + netinc ) % nnets ), i-- ) {
412             AA_SAT( aa )->sat_addr.s_net = htons( net );
413
414             for ( j = 0, nodeinc = time.tv_sec | 1; j < 256;
415                     j++, AA_SAT( aa )->sat_addr.s_node += nodeinc ) {
416                 if ( AA_SAT( aa )->sat_addr.s_node > 253 ||
417                         AA_SAT( aa )->sat_addr.s_node < 1 ) {
418                     continue;
419                 }
420                 aa->aa_probcnt = 10;
421                 timeout( aarpprobe, (caddr_t)ifp, hz / 5 );
422                 splx( s );
423                 if ( sleep( aa, PSLEP|PCATCH )) {
424                     printf( "at_ifinit why did this happen?!\n" );
425                     aa->aa_addr = oldaddr;
426                     aa->aa_firstnet = onr.nr_firstnet;
427                     aa->aa_lastnet = onr.nr_lastnet;
428                     return( EINTR );
429                 }
430                 s = splimp();
431                 if (( aa->aa_flags & AFA_PROBING ) == 0 ) {
432                     break;
433                 }
434             }
435             if (( aa->aa_flags & AFA_PROBING ) == 0 ) {
436                 break;
437             }
438             /* reset node for next network */
439             AA_SAT( aa )->sat_addr.s_node = time.tv_sec;
440         }
441
442         if ( aa->aa_flags & AFA_PROBING ) {
443             aa->aa_addr = oldaddr;
444             aa->aa_firstnet = onr.nr_firstnet;
445             aa->aa_lastnet = onr.nr_lastnet;
446             splx( s );
447             return( EADDRINUSE );
448         }
449     }
450
451     if ( ifp->if_ioctl &&
452             ( error = (*ifp->if_ioctl)( ifp, SIOCSIFADDR, aa ))) {
453         splx( s );
454         aa->aa_addr = oldaddr;
455         aa->aa_firstnet = onr.nr_firstnet;
456         aa->aa_lastnet = onr.nr_lastnet;
457         return( error );
458     }
459
460 #ifdef BSD4_4
461     aa->aa_netmask.sat_len = 6;
462     aa->aa_netmask.sat_family = AF_APPLETALK;
463     aa->aa_netmask.sat_addr.s_net = 0xffff;
464     aa->aa_netmask.sat_addr.s_node = 0;
465 #endif /* BSD4_4 */
466
467     if ( ifp->if_flags & IFF_LOOPBACK ) {
468 #ifndef BSD4_4
469         rtinit( &aa->aa_addr, &aa->aa_addr, (int)SIOCADDRT,
470                 RTF_HOST|RTF_UP );
471 #else /* ! BSD4_4 */
472         error = rtinit( &(aa->aa_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP );
473 #endif /* ! BSD4_4 */
474     } else {
475 #ifndef BSD4_4
476         /*
477          * rtrequest looks for point-to-point links first. The
478          * broadaddr is in the same spot as the destaddr. So, if
479          * ATADDR_ANYNET is 0, and we don't fill in the broadaddr, we
480          * get 0.0 routed out the ether interface.  So, initialize the
481          * broadaddr, even tho we don't use it.
482          *
483          * We *could* use the broadaddr field to reduce some of the
484          * sockaddr_at overloading that we've done.  E.g. Just send
485          * to INTERFACE-NET.255, and have the kernel reroute that
486          * to broadaddr, which would be 0.255 for phase 2 interfaces,
487          * and IFACE-NET.255 for phase 1 interfaces.
488          */
489         ((struct sockaddr_at *)&aa->aa_broadaddr)->sat_addr.s_net =
490                 sat->sat_addr.s_net;
491         ((struct sockaddr_at *)&aa->aa_broadaddr)->sat_addr.s_node =
492                 ATADDR_BCAST;
493
494         bzero( &netaddr, sizeof( struct sockaddr_at ));
495         netaddr.sat_family = AF_APPLETALK;
496         netaddr.sat_addr.s_node = ATADDR_ANYNODE;
497         if (( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
498             netaddr.sat_addr.s_net = AA_SAT( aa )->sat_addr.s_net;
499             rtinit((struct sockaddr *)&netaddr, &aa->aa_addr,
500                     (int)SIOCADDRT, RTF_UP );
501         } else {
502             /*
503              * If the range is the full 0-fffe range, just use
504              * the default route.
505              */
506             if ( aa->aa_firstnet == htons( 0x0000 ) &&
507                     aa->aa_lastnet == htons( 0xfffe )) {
508                 netaddr.sat_addr.s_net = 0;
509                 rtinit((struct sockaddr *)&netaddr, &aa->aa_addr,
510                         (int)SIOCADDRT, RTF_UP );
511             } else {
512                 for ( net = ntohs( aa->aa_firstnet );
513                         net <= ntohs( aa->aa_lastnet ); net++ ) {
514                     netaddr.sat_addr.s_net = htons( net );
515                     rtinit((struct sockaddr *)&netaddr, &aa->aa_addr,
516                             (int)SIOCADDRT, RTF_UP );
517                 }
518             }
519         }
520 #else /* ! BSD4_4 */
521         error = rtinit( &(aa->aa_ifa), (int)RTM_ADD, RTF_UP );
522 #endif /* ! BSD4_4 */
523     }
524     if ( error ) {
525         aa->aa_addr = oldaddr;
526         aa->aa_firstnet = onr.nr_firstnet;
527         aa->aa_lastnet = onr.nr_lastnet;
528         splx( s );
529         return( error );
530     }
531
532 #ifdef BSD4_4
533     aa->aa_ifa.ifa_flags |= IFA_ROUTE;
534 #endif /* BSD4_4 */
535     aa->aa_flags |= AFA_ROUTE;
536     splx( s );
537     return( 0 );
538 }
539
540 at_broadcast( sat )
541     struct sockaddr_at  *sat;
542 {
543     struct at_ifaddr    *aa;
544
545     if ( sat->sat_addr.s_node != ATADDR_BCAST ) {
546         return( 0 );
547     }
548     if ( sat->sat_addr.s_net == 0 ) {
549         return( 1 );
550     } else {
551         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
552             if (( aa->aa_ifp->if_flags & IFF_BROADCAST ) &&
553                  ( ntohs( sat->sat_addr.s_net ) >= ntohs( aa->aa_firstnet ) &&
554                  ntohs( sat->sat_addr.s_net ) <= ntohs( aa->aa_lastnet ))) {
555                 return( 1 );
556             }
557         }
558     }
559     return( 0 );
560 }
561
562 aa_clean()
563 {
564     struct at_ifaddr    *aa;
565     struct ifaddr       *ifa;
566     struct ifnet        *ifp;
567
568     while ( aa = at_ifaddr ) {
569         ifp = aa->aa_ifp;
570         at_scrub( ifp, aa );
571         at_ifaddr = aa->aa_next;
572         if (( ifa = ifp->if_addrlist ) == (struct ifaddr *)aa ) {
573             ifp->if_addrlist = ifa->ifa_next;
574         } else {
575             while ( ifa->ifa_next &&
576                     ( ifa->ifa_next != (struct ifaddr *)aa )) {
577                 ifa = ifa->ifa_next;
578             }
579             if ( ifa->ifa_next ) {
580                 ifa->ifa_next = ((struct ifaddr *)aa)->ifa_next;
581             } else {
582                 panic( "at_entry" );
583             }
584         }
585     }
586 }