• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.5/sys/netatalk/
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 */
48atalk_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 */
61atalk_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
79at_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
291at_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
340extern struct timeval	time;
341
342at_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
540at_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
562aa_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}
587