1/* 2 * Copyright (c) 1990,1991 Regents of The University of Michigan. 3 * All Rights Reserved. 4 * 5 * Permission to use, copy, modify, and distribute this software and 6 * its documentation for any purpose and without fee is hereby granted, 7 * provided that the above copyright notice appears in all copies and 8 * that both that copyright notice and this permission notice appear 9 * in supporting documentation, and that the name of The University 10 * of Michigan not be used in advertising or publicity pertaining to 11 * distribution of the software without specific, written prior 12 * permission. This software is supplied as is without expressed or 13 * implied warranties of any kind. 14 * 15 * Research Systems Unix Group 16 * The University of Michigan 17 * c/o Mike Clark 18 * 535 W. William Street 19 * Ann Arbor, Michigan 20 * +1-313-763-0525 21 * netatalk@itd.umich.edu 22 */ 23 24#include <sys/types.h> 25#include <sys/mbuf.h> 26#include <sys/socket.h> 27#include <sys/protosw.h> 28#include <sys/ioctl.h> 29#include <sys/errno.h> 30#include <net/if.h> 31#include <net/if_llc.h> 32#include <net/if_to_proto.h> 33#include <net/netisr.h> 34#include <netinet/in.h> 35#undef s_net 36#include <netinet/if_ether.h> 37 38#include "at.h" 39#include "at_var.h" 40 41extern u_char at_org_code[ 3 ]; 42extern u_char aarp_org_code[ 3 ]; 43 44/* 45 * This is the magic input routine, for all AppleTalk related packets. 46 * It will pick up *all* packets received, on all interfaces, apparently. 47 * If it turns out that receiving all packets in this fashion causes 48 * DLI to not receive packets what it should, we may need to call DLI 49 * directly from within the AppleTalk input routines. Ick. 50 */ 51struct mbuf * 52ddp_ifinput( m, ifp, inq, eh ) 53 struct mbuf *m; 54 struct ifnet *ifp; 55 struct ifqueue **inq; 56 struct ether_header *eh; 57{ 58 struct llc llc; 59 struct if_family *ifam; 60 61 switch ( eh->ether_type ) { 62 case ETHERTYPE_AT : 63 *inq = &atintrq1; 64 smp_lock( &(*inq)->lk_ifqueue, LK_RETRY ); 65 schednetisr( NETISR_AT ); 66 return( m ); 67 68 case ETHERTYPE_AARP : 69 aarpinput( ifp, m ); 70 return( 0 ); 71 72 default : 73 if ( eh->ether_type <= ETHERMTU ) { /* ieee802 */ 74 if ( m->m_len < sizeof( struct llc )) { 75 break; 76 } 77 78 bcopy( mtod( m, caddr_t ), &llc, sizeof( struct llc )); 79 if ( llc.llc_dsap != LLC_SNAP_LSAP || 80 llc.llc_ssap != LLC_SNAP_LSAP || 81 llc.llc_control != LLC_UI ) { 82 break; 83 } 84 85 if ( bcmp( llc.llc_org_code, at_org_code, 86 sizeof( at_org_code )) == 0 && 87 ntohs( llc.llc_ether_type ) == ETHERTYPE_AT ) { 88 m_adj( m, sizeof( struct llc )); 89 *inq = &atintrq2; 90 smp_lock( &(*inq)->lk_ifqueue, LK_RETRY ); 91 schednetisr( NETISR_AT ); 92 return( m ); 93 } 94 95 if ( bcmp( llc.llc_org_code, aarp_org_code, 96 sizeof( aarp_org_code )) == 0 && 97 ntohs( llc.llc_ether_type ) == ETHERTYPE_AARP ) { 98 m_adj( m, sizeof( struct llc )); 99 aarpinput( ifp, m ); 100 return( 0 ); 101 } 102 } 103 } 104 105 /* 106 * Check is anyone else wants this packet. 107 */ 108 for ( ifam = if_family; ifam->domain != -1; ifam++ ) { 109 if (( eh->ether_type == ifam->if_type || ifam->if_type == -1 ) && 110 ifam->prswitch && 111 ifam->prswitch->pr_ifinput != (int (*)())ddp_ifinput ) { 112 break; 113 } 114 } 115 if ( ifam->domain != -1 && ifam->prswitch->pr_ifinput ) { 116 return( (struct mbuf *)(*ifam->prswitch->pr_ifinput)( m, ifp, 117 inq, eh )); 118 } 119 120 m_freem( m ); 121 return( 0 ); 122} 123 124/* 125 * Fill in type and odst. odst is the media output address, i.e. 126 * the MAC layer address. Type is the MAC type. Should be 0 to 127 * indicate IEEE addressing. 128 * 129 * Stupidly enough, there's no way to say "can't send this now." 130 * So, we just let the first packet go into the air. Not much 131 * else to be done, except maybe bitch at DEC. Note: we're not 132 * passing the mbuf to aarpresolve() -- that way it doesn't get 133 * mfree-ed twice. 134 */ 135ddp_ifoutput( ifp, m, dst, type, odst ) 136 struct ifnet *ifp; 137 struct mbuf *m; 138 struct sockaddr_at *dst; 139 short *type; 140 char *odst; 141{ 142 struct at_ifaddr *aa; 143 struct llc *llc; 144 struct mbuf *m0; 145 146 if ( !aarpresolve( ifp, 0, dst, odst )) { 147 *type = 0xffff; 148 return( 0 ); 149 } 150 151 if (( aa = (struct at_ifaddr *)at_ifawithnet( dst, ifp->if_addrlist )) 152 == 0 ) { 153 *type = 0xffff; 154 return( 0 ); 155 } 156 157 if ( aa->aa_flags & AFA_PHASE2 ) { 158 /* 159 * This code needs to be modeled after the similar code in 160 * at_sun.c -- you can't just MGET() and bcopy(), since we might be 161 * dealing with mbufs which are really pages. 162 */ 163 MGET( m0, M_WAIT, MT_HEADER ); 164 if ( m0 == 0 ) { 165 *type = 0xffff; 166 return( 0 ); 167 } 168 m0->m_next = m->m_next; 169 m0->m_off = m->m_off; 170 m0->m_len = m->m_len; 171 bcopy( mtod( m, caddr_t ), mtod( m0, caddr_t ), m->m_len ); 172 m->m_next = m0; 173 m->m_off = MMINOFF; 174 m->m_len = sizeof( struct llc ); 175 176 llc = mtod( m, struct llc *); 177 llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; 178 llc->llc_control = LLC_UI; 179 bcopy( at_org_code, llc->llc_org_code, sizeof( at_org_code )); 180 llc->llc_ether_type = htons( ETHERTYPE_AT ); 181 182 /* 183 * Set the type to be the length of the packet, instead of 0. 184 * Ultrix used to put the length in the packet when we set type 185 * to 0, however, now we do it ourselves. 186 */ 187 for ( *type = 0; m; m = m->m_next ) { 188 *type += m->m_len; 189 } 190 } else { 191 *type = ETHERTYPE_AT; 192 } 193 194 return( 1 ); 195} 196 197ddp_ifioctl( ifp, cmd, data ) 198 struct ifnet *ifp; 199 int cmd; 200 caddr_t data; 201{ 202 switch( cmd ) { 203 case SIOCSIFADDR : 204 aarpwhohas((struct arpcom *)ifp, 205 &AA_SAT((struct ifaddr *)data)->sat_addr ); 206 break; 207 default : 208 return( EINVAL ); 209 } 210 return( 0 ); 211} 212