2 * $Id: at_sun.c,v 1.2 2001-08-06 13:39:30 rufustfirefly Exp $
7 #include <sys/socket.h>
9 #include <sys/protosw.h>
10 #include <sys/domain.h>
11 #include <sys/errno.h>
13 #include <net/if_arp.h>
15 #include <net/route.h>
17 #include <net/netisr.h>
19 #include <sun/vddrv.h>
21 #include <netinet/in.h>
23 #include <netinet/if_ether.h>
25 #include <netatalk/at.h>
26 #include <netatalk/at_var.h>
27 #include <netatalk/ddp_var.h>
28 #include <netatalk/phase2.h>
34 VDMAGIC_USER, "netatalk"
37 struct ifqueue *atef_input();
41 extern u_char aarp_org_code[ 3 ];
42 extern u_char at_org_code[ 3 ];
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.
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).
57 struct ether_family ether_atalk[] = {
59 AF_APPLETALK, 0, /* Changed by atef_output() */
60 atef_input, atef_output, atintr,
68 atef_input, 0, atintr,
72 atef_input, 0, atintr,
75 int ether_atalkN = sizeof( ether_atalk ) / sizeof( ether_atalk[ 0 ] );
77 extern struct ether_family *ether_families;
79 extern int atalk_hash(), atalk_netmatch();
80 extern int null_hash(), null_netmatch();
82 xxxinit( cmd, vdd, vdi, vds )
88 struct ether_family *ef;
95 vdd->vdd_vdtab = (struct vdlinkage *)&atvdl;
98 * Register with the network-interface layer (ethernet).
100 for ( i = 0; i < ether_atalkN; i++ ) {
101 ether_register( ðer_atalk[ i ] );
105 * Register with the socket layer.
107 atalkdomain.dom_next = domains;
108 domains = &atalkdomain;
109 if ( atalkdomain.dom_init ) {
110 (*atalkdomain.dom_init)();
112 for ( pr = atalkdomain.dom_protosw;
113 pr < atalkdomain.dom_protoswNPROTOSW; pr++ ) {
120 * Cobble ourselves into the routing table.
122 afswitch[ AF_APPLETALK ].af_hash = atalk_hash;
123 afswitch[ AF_APPLETALK ].af_netmatch = atalk_netmatch;
128 * Make sure that there are no open appletalk sockets.
130 if ( ddpcb != NULL ) {
135 * There is no ether_unregister(), so we'll have to do it
138 for ( i = 0; i < ether_atalkN; i++ ) {
139 if ( ether_families == ðer_atalk[ i ] ) {
140 ether_families = ether_families->ef_next;
143 for ( ef = ether_families; ef->ef_next; ef = ef->ef_next ) {
144 if ( ef->ef_next == ðer_atalk[ i ] ) {
145 ef->ef_next = ef->ef_next->ef_next;
153 * Remove aarp timers and held packets.
158 * Remove AppleTalk interface addresses.
163 * Remove our routines from the routing table.
165 afswitch[ AF_APPLETALK ].af_hash = null_hash;
166 afswitch[ AF_APPLETALK ].af_netmatch = null_netmatch;
169 * Remove atalkdomain from the domains list.
170 * Unlikely, but someone may have registered after us.
172 if ( domains == &atalkdomain ) {
173 domains = domains->dom_next;
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;
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.
201 atef_input( ifp, m, header )
204 struct ether_header *header;
210 * Check first for LOOPBACK flag, since loopback code passes NULL for
213 if ( ifp->if_flags & IFF_LOOPBACK ) {
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.
222 #if defined( sun ) && defined( i386 )
223 header->ether_type = ntohs( header->ether_type );
224 #endif /* sun i386 */
226 if ( header->ether_type <= ETHERMTU ) { /* IEEE802 */
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.
236 if ( m->m_len == sizeof( struct ifnet * )) {
244 * We can't call m_pullup(), since we need to preserve
247 if ( m->m_len < sizeof( struct llc )) {
248 printf( "atef_input size llc\n" );
249 ( n ) ? m_freem( n ) : m_freem( m );
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 );
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.
264 m_adj( m, sizeof( struct llc ));
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" );
272 *mtod( m, struct ifnet ** ) = ifp;
275 if ( ntohs( llc.llc_ether_type ) == ETHERTYPE_AT &&
276 bcmp( llc.llc_org_code, at_org_code,
277 sizeof( at_org_code )) == 0 ) {
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 );
290 switch ( header->ether_type ) {
294 case ETHERTYPE_AARP :
300 ( n ) ? m_freem( n ) : m_freem( m );
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.
309 atef_output( dst, m, ifp, edst )
310 struct sockaddr_at *dst;
313 struct ether_addr *edst;
315 struct at_ifaddr *aa;
321 if ( !aarpresolve( ifp, m, dst, edst )) {
328 * ifaddr is the first thing in at_ifaddr
330 if (( aa = (struct at_ifaddr *)at_ifawithnet( dst, ifp->if_addrlist ))
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.
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.
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 ) {
351 if ( M_HASCL( m )) { /* m is a cluster */
358 m0->m_next = m->m_next;
360 m->m_off = MMAXOFF - sizeof( struct llc );
361 m->m_len = sizeof( struct llc );
363 m->m_off -= sizeof( struct llc );
364 m->m_len += sizeof( struct llc );
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;
375 ether_atalk[ 0 ].ef_ethertype = ETHERTYPE_AT;