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