]> arthur.barton.de Git - netatalk.git/blob - sys/sunos/at_sun.c
Remove bdb env on exit
[netatalk.git] / sys / sunos / at_sun.c
1 /*
2  * $Id: at_sun.c,v 1.2 2001-08-06 13:39:30 rufustfirefly Exp $
3  */
4
5 #include <sys/param.h>
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <sys/mbuf.h>
9 #include <sys/protosw.h>
10 #include <sys/domain.h>
11 #include <sys/errno.h>
12
13 #include <net/if_arp.h>
14 #include <net/if.h>
15 #include <net/route.h>
16 #include <net/af.h>
17 #include <net/netisr.h>
18
19 #include <sun/vddrv.h>
20
21 #include <netinet/in.h>
22 #undef s_net
23 #include <netinet/if_ether.h>
24
25 #include <netatalk/at.h>
26 #include <netatalk/at_var.h>
27 #include <netatalk/ddp_var.h>
28 #include <netatalk/phase2.h>
29
30 struct vdlat {
31     int         vda_magic;
32     char        *vda_name;
33 }       atvdl = {
34     VDMAGIC_USER, "netatalk"
35 };
36
37 struct ifqueue  *atef_input();
38 int             atef_output();
39 extern int      atintr();
40
41 extern u_char   aarp_org_code[ 3 ];
42 extern u_char   at_org_code[ 3 ];
43
44 /*
45  * Entries in this table are inserted into the ether_families linked
46  * list at the beginnning. As such, they will be searched by the input
47  * and output routines opposite to the order here.
48  *
49  * In order to do both phase 1 and phase 2 during output, we have a
50  * special entry (the AF_APPLETALK entry) whose ethertype field is
51  * changed by the output function, to reflect the actual link layer
52  * to be used. This ether_family entry is never seen during Ethernet
53  * input, since the earlier entry captures all packets (it is seen
54  * during loopback input, in that the input function is called directly
55  * on loopback output).
56  */
57 struct ether_family     ether_atalk[] = {
58     {
59         AF_APPLETALK,   0,      /* Changed by atef_output() */
60         atef_input,     atef_output,    atintr,
61     },
62     {
63         0,              ETHERTYPE_AARP,
64         atef_input,     0,              0,
65     },
66     {
67         0,              ETHERTYPE_AT,
68         atef_input,     0,              atintr,
69     },
70     {
71         0,              EF_8023_TYPE,
72         atef_input,     0,              atintr,
73     },
74 };
75 int     ether_atalkN = sizeof( ether_atalk ) / sizeof( ether_atalk[ 0 ] );
76
77 extern struct ether_family      *ether_families;
78
79 extern int                      atalk_hash(), atalk_netmatch();
80 extern int                      null_hash(), null_netmatch();
81
82 xxxinit( cmd, vdd, vdi, vds )
83     unsigned int        cmd;
84     struct vddrv        *vdd;
85     addr_t              vdi;
86     struct vdstat       *vds;
87 {
88     struct ether_family *ef;
89     struct domain       *dom;
90     struct protosw      *pr;
91     int                 i;
92
93     switch( cmd ) {
94         case VDLOAD :
95             vdd->vdd_vdtab = (struct vdlinkage *)&atvdl;
96
97             /*
98              * Register with the network-interface layer (ethernet).
99              */
100             for ( i = 0; i < ether_atalkN; i++ ) {
101                 ether_register( &ether_atalk[ i ] );
102             }
103
104             /*
105              * Register with the socket layer.
106              */
107             atalkdomain.dom_next = domains;
108             domains = &atalkdomain;
109             if ( atalkdomain.dom_init ) {
110                 (*atalkdomain.dom_init)();
111             }
112             for ( pr = atalkdomain.dom_protosw;
113                     pr < atalkdomain.dom_protoswNPROTOSW; pr++ ) {
114                 if ( pr->pr_init ) {
115                     (*pr->pr_init)();
116                 }
117             }
118
119             /*
120              * Cobble ourselves into the routing table.
121              */
122             afswitch[ AF_APPLETALK ].af_hash = atalk_hash;
123             afswitch[ AF_APPLETALK ].af_netmatch = atalk_netmatch;
124             return( 0 );
125
126         case VDUNLOAD :
127             /*
128              * Make sure that there are no open appletalk sockets.
129              */
130             if ( ddpcb != NULL ) {
131                 return( EMFILE );
132             }
133
134             /*
135              * There is no ether_unregister(), so we'll have to do it
136              * our selves...
137              */
138             for ( i = 0; i < ether_atalkN; i++ ) {
139                 if ( ether_families == &ether_atalk[ i ] ) {
140                     ether_families = ether_families->ef_next;
141                     continue;
142                 } else {
143                     for ( ef = ether_families; ef->ef_next; ef = ef->ef_next ) {
144                         if ( ef->ef_next == &ether_atalk[ i ] ) {
145                             ef->ef_next = ef->ef_next->ef_next;
146                             break;
147                         }
148                     }
149                 }
150             }
151
152             /*
153              * Remove aarp timers and held packets.
154              */
155             aarp_clean();
156
157             /*
158              * Remove AppleTalk interface addresses.
159              */
160             aa_clean();
161
162             /*
163              * Remove our routines from the routing table.
164              */
165             afswitch[ AF_APPLETALK ].af_hash = null_hash;
166             afswitch[ AF_APPLETALK ].af_netmatch = null_netmatch;
167
168             /*
169              * Remove atalkdomain from the domains list.
170              * Unlikely, but someone may have registered after us.
171              */
172             if ( domains == &atalkdomain ) {
173                 domains = domains->dom_next;
174             } else {
175                 for ( dom = domains; dom->dom_next; dom = dom->dom_next ) {
176                     if ( dom->dom_next == &atalkdomain ) {
177                         dom->dom_next = dom->dom_next->dom_next;
178                         break;
179                     }
180                 }
181             }
182             return( 0 );
183
184         case VDSTAT :
185             return( 0 );
186         default :
187             return( EIO );
188     }
189 }
190
191 /*
192  * Input routine for netatalk on suns.  There are five possible
193  * packets.  First, packets received on the loopback interface
194  * are immediately sent to the phase 1 interrupt queue (this will
195  * have to change if we ever do a phase 2 only version).  Second,
196  * IEEE802 packet are sent to either the aarpinput() routine or
197  * the phase 2 interrupt queue.  Finally, DIX packets are sent
198  * to either aarpinput() or the phase 1 interrupt queue.
199  */
200     struct ifqueue *
201 atef_input( ifp, m, header )
202     struct ifnet        *ifp;
203     struct mbuf         *m;
204     struct ether_header *header;
205 {
206     struct llc          llc;
207     struct mbuf         *n = 0;
208
209     /*
210      * Check first for LOOPBACK flag, since loopback code passes NULL for
211      * the header.
212      */
213     if ( ifp->if_flags & IFF_LOOPBACK ) {
214         return( &atintrq2 );
215     }
216
217     /*
218      * Before SunOS 4.1, the ether_type was passed as is from the
219      * packet.  After SunOS 4.1, the ether_type is swapped in
220      * do_protocol(), before the ether_family routines are called.
221      */
222 #if defined( sun ) && defined( i386 )
223     header->ether_type = ntohs( header->ether_type );
224 #endif /* sun i386 */
225
226     if ( header->ether_type <= ETHERMTU ) {     /* IEEE802 */
227         /*
228          * We need to remove the interface pointer from the beginning of this
229          * packet.  We can't always use IF_ADJ(), since it can (and will,
230          * very often) MFREE() the first mbuf in our chain.  If IF_ADJ()
231          * would free the first mbuf, we just advance our pointer to the
232          * next mbuf.  Since our calling routine passes m by value, we're
233          * not actually losing m.  Later, we don't need to put the interface
234          * pointer back on, since the caller still has it in its copy of m.
235          */
236         if ( m->m_len == sizeof( struct ifnet * )) {
237             n = m;
238             m = m->m_next;
239         } else {
240             IF_ADJ( m );
241         }
242
243         /*
244          * We can't call m_pullup(), since we need to preserve
245          * the value of m.
246          */
247         if ( m->m_len < sizeof( struct llc )) {
248 printf( "atef_input size llc\n" );
249             ( n ) ? m_freem( n ) : m_freem( m );
250             return( 0 );
251         }
252         bcopy( mtod( m, caddr_t ), &llc, sizeof( struct llc ));
253         if ( llc.llc_dsap != LLC_SNAP_LSAP || llc.llc_ssap != LLC_SNAP_LSAP ||
254                 llc.llc_control != LLC_UI ) {
255             ( n ) ? m_freem( n ) : m_freem( m );
256             return( 0 );
257         }
258
259         /*
260          * See IF_ADJ() above.  Here we prepend ifp to the mbuf chain.  If we
261          * didn't remove it earlier, we don't replace it here.
262          */
263         if ( n ) {
264             m_adj( m, sizeof( struct llc ));
265         } else {
266             m_adj( m, sizeof( struct llc ) - sizeof( struct ifnet *));
267             if ( m->m_len < sizeof( struct ifnet * )) {
268 printf( "atef_input too small!\n" );
269                 m_freem( m );
270                 return( 0 );
271             }
272             *mtod( m, struct ifnet ** ) = ifp;
273         }
274
275         if ( ntohs( llc.llc_ether_type ) == ETHERTYPE_AT &&
276                 bcmp( llc.llc_org_code, at_org_code,
277                 sizeof( at_org_code )) == 0 ) {
278             return( &atintrq2 );
279         }
280
281         /* do we really want to pass m, here?  what happened to n? XXX */
282         if ( ntohs( llc.llc_ether_type ) == ETHERTYPE_AARP &&
283                 bcmp( llc.llc_org_code, aarp_org_code,
284                 sizeof( aarp_org_code )) == 0 ) {
285             aarpinput( ifp, n ? n : m );
286             return( 0 );
287         }
288
289     } else {                                    /* DIX */
290         switch ( header->ether_type ) {
291         case ETHERTYPE_AT :
292             return( &atintrq1 );
293
294         case ETHERTYPE_AARP :
295             aarpinput( ifp, m );
296             return( 0 );
297         }
298     }
299
300     ( n ) ? m_freem( n ) : m_freem( m );
301     return( 0 );
302 }
303
304 /*
305  * If the destination is on a 802.3 wire, do phase 2 encapsulation,
306  * adding the 802.2 and SNAP headers.  Always fill in the edst with the
307  * ethernet address of the destination.
308  */
309 atef_output( dst, m, ifp, edst )
310     struct sockaddr_at  *dst;
311     struct mbuf         *m;
312     struct ifnet        *ifp;
313     struct ether_addr   *edst;
314 {
315     struct at_ifaddr    *aa;
316     struct mbuf         *m0;
317     struct llc          llc;
318     int                 s;
319
320     s = splimp();
321     if ( !aarpresolve( ifp, m, dst, edst )) {
322         (void) splx( s );
323         return( 1 );
324     }
325     (void) splx( s );
326
327     /*
328      * ifaddr is the first thing in at_ifaddr
329      */
330     if (( aa = (struct at_ifaddr *)at_ifawithnet( dst, ifp->if_addrlist ))
331             == 0 ) {
332         m_freem( m );
333         return( 1 );
334     }
335
336     /*
337      * In the phase 2 case, we need to prepend an mbuf for the llc header.
338      * Since we must preserve the value of m, which is passed to us by
339      * value, we m_copy() the first mbuf, and use it for our llc header.
340      *
341      * We could worry about leaving space for the ether header, but
342      * since we'll have to go through all sorts of hoops, including a
343      * possibly large copy, there's really no sense.
344      */
345     if ( aa->aa_flags & AFA_PHASE2 ) {
346         if ( M_HASCL( m ) || m->m_off - MMINOFF < sizeof( struct llc )) {
347             if (( m0 = m_copy( m, 0, m->m_len )) == 0 ) {
348                 m_freem( m );
349                 return( 1 );
350             }
351             if ( M_HASCL( m )) {        /* m is a cluster */
352                 int s = splimp();
353
354                 mclput( m );
355                 splx( s );
356             }
357
358             m0->m_next = m->m_next;
359             m->m_next = m0;
360             m->m_off = MMAXOFF - sizeof( struct llc );
361             m->m_len = sizeof( struct llc );
362         } else {
363             m->m_off -= sizeof( struct llc );
364             m->m_len += sizeof( struct llc );
365         }
366
367         llc.llc_dsap = llc.llc_ssap = LLC_SNAP_LSAP;
368         llc.llc_control = LLC_UI;
369         bcopy( at_org_code, llc.llc_org_code, sizeof( at_org_code ));
370         llc.llc_ether_type = htons( ETHERTYPE_AT );
371         bcopy( &llc, mtod( m, caddr_t ), sizeof( struct llc ));
372         ether_atalk[ 0 ].ef_ethertype = EF_8023_TYPE;
373         return( 0 );
374     } else {
375         ether_atalk[ 0 ].ef_ethertype = ETHERTYPE_AT;
376         return( 0 );
377     }
378 }