/* * Copyright (c) 1990,1991 Regents of The University of Michigan. * All Rights Reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appears in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation, and that the name of The University * of Michigan not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior * permission. This software is supplied as is without expressed or * implied warranties of any kind. * * Research Systems Unix Group * The University of Michigan * c/o Mike Clark * 535 W. William Street * Ann Arbor, Michigan * +1-313-763-0525 * netatalk@itd.umich.edu */ #include #include #include #include #include #include #include #include #include #include #include #undef s_net #include #include "at.h" #include "at_var.h" extern u_char at_org_code[ 3 ]; extern u_char aarp_org_code[ 3 ]; /* * This is the magic input routine, for all AppleTalk related packets. * It will pick up *all* packets received, on all interfaces, apparently. * If it turns out that receiving all packets in this fashion causes * DLI to not receive packets what it should, we may need to call DLI * directly from within the AppleTalk input routines. Ick. */ struct mbuf * ddp_ifinput( m, ifp, inq, eh ) struct mbuf *m; struct ifnet *ifp; struct ifqueue **inq; struct ether_header *eh; { struct llc llc; struct if_family *ifam; switch ( eh->ether_type ) { case ETHERTYPE_AT : *inq = &atintrq1; smp_lock( &(*inq)->lk_ifqueue, LK_RETRY ); schednetisr( NETISR_AT ); return( m ); case ETHERTYPE_AARP : aarpinput( ifp, m ); return( 0 ); default : if ( eh->ether_type <= ETHERMTU ) { /* ieee802 */ if ( m->m_len < sizeof( struct llc )) { break; } bcopy( mtod( m, caddr_t ), &llc, sizeof( struct llc )); if ( llc.llc_dsap != LLC_SNAP_LSAP || llc.llc_ssap != LLC_SNAP_LSAP || llc.llc_control != LLC_UI ) { break; } if ( bcmp( llc.llc_org_code, at_org_code, sizeof( at_org_code )) == 0 && ntohs( llc.llc_ether_type ) == ETHERTYPE_AT ) { m_adj( m, sizeof( struct llc )); *inq = &atintrq2; smp_lock( &(*inq)->lk_ifqueue, LK_RETRY ); schednetisr( NETISR_AT ); return( m ); } if ( bcmp( llc.llc_org_code, aarp_org_code, sizeof( aarp_org_code )) == 0 && ntohs( llc.llc_ether_type ) == ETHERTYPE_AARP ) { m_adj( m, sizeof( struct llc )); aarpinput( ifp, m ); return( 0 ); } } } /* * Check is anyone else wants this packet. */ for ( ifam = if_family; ifam->domain != -1; ifam++ ) { if (( eh->ether_type == ifam->if_type || ifam->if_type == -1 ) && ifam->prswitch && ifam->prswitch->pr_ifinput != (int (*)())ddp_ifinput ) { break; } } if ( ifam->domain != -1 && ifam->prswitch->pr_ifinput ) { return( (struct mbuf *)(*ifam->prswitch->pr_ifinput)( m, ifp, inq, eh )); } m_freem( m ); return( 0 ); } /* * Fill in type and odst. odst is the media output address, i.e. * the MAC layer address. Type is the MAC type. Should be 0 to * indicate IEEE addressing. * * Stupidly enough, there's no way to say "can't send this now." * So, we just let the first packet go into the air. Not much * else to be done, except maybe bitch at DEC. Note: we're not * passing the mbuf to aarpresolve() -- that way it doesn't get * mfree-ed twice. */ ddp_ifoutput( ifp, m, dst, type, odst ) struct ifnet *ifp; struct mbuf *m; struct sockaddr_at *dst; short *type; char *odst; { struct at_ifaddr *aa; struct llc *llc; struct mbuf *m0; if ( !aarpresolve( ifp, 0, dst, odst )) { *type = 0xffff; return( 0 ); } if (( aa = (struct at_ifaddr *)at_ifawithnet( dst, ifp->if_addrlist )) == 0 ) { *type = 0xffff; return( 0 ); } if ( aa->aa_flags & AFA_PHASE2 ) { /* * This code needs to be modeled after the similar code in * at_sun.c -- you can't just MGET() and bcopy(), since we might be * dealing with mbufs which are really pages. */ MGET( m0, M_WAIT, MT_HEADER ); if ( m0 == 0 ) { *type = 0xffff; return( 0 ); } m0->m_next = m->m_next; m0->m_off = m->m_off; m0->m_len = m->m_len; bcopy( mtod( m, caddr_t ), mtod( m0, caddr_t ), m->m_len ); m->m_next = m0; m->m_off = MMINOFF; m->m_len = sizeof( struct llc ); llc = mtod( m, struct llc *); llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; llc->llc_control = LLC_UI; bcopy( at_org_code, llc->llc_org_code, sizeof( at_org_code )); llc->llc_ether_type = htons( ETHERTYPE_AT ); /* * Set the type to be the length of the packet, instead of 0. * Ultrix used to put the length in the packet when we set type * to 0, however, now we do it ourselves. */ for ( *type = 0; m; m = m->m_next ) { *type += m->m_len; } } else { *type = ETHERTYPE_AT; } return( 1 ); } ddp_ifioctl( ifp, cmd, data ) struct ifnet *ifp; int cmd; caddr_t data; { switch( cmd ) { case SIOCSIFADDR : aarpwhohas((struct arpcom *)ifp, &AA_SAT((struct ifaddr *)data)->sat_addr ); break; default : return( EINVAL ); } return( 0 ); }