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