ddp_input.c revision 57178
115885Sjulian/* 215885Sjulian * Copyright (c) 1990,1994 Regents of The University of Michigan. 315885Sjulian * All Rights Reserved. See COPYRIGHT. 456555Sbrian * 556555Sbrian * $FreeBSD: head/sys/netatalk/ddp_input.c 57178 2000-02-13 03:32:07Z peter $ 615885Sjulian */ 715885Sjulian 815885Sjulian#include <sys/param.h> 915885Sjulian#include <sys/systm.h> 1015885Sjulian#include <sys/kernel.h> 1115885Sjulian#include <net/netisr.h> 1215885Sjulian#include <sys/mbuf.h> 1315885Sjulian#include <sys/socket.h> 1415885Sjulian#include <sys/socketvar.h> 1515885Sjulian#include <net/if.h> 1615885Sjulian#include <net/route.h> 1756555Sbrian#include <net/intrq.h> 1815885Sjulian 1918207Sbde#include <netatalk/at.h> 2018207Sbde#include <netatalk/at_var.h> 2118207Sbde#include <netatalk/ddp.h> 2218207Sbde#include <netatalk/ddp_var.h> 2315885Sjulian#include <netatalk/at_extern.h> 2415885Sjulian 2529185Sbdestatic volatile int ddp_forward = 1; 2629185Sbdestatic volatile int ddp_firewall = 0; 2729184Sbdestatic struct ddpstat ddpstat; 2829185Sbdestatic struct route forwro; 2929184Sbde 3056555Sbrianconst int atintrq1_present = 1, atintrq2_present = 1; 3156555Sbrian 3229185Sbdestatic void ddp_input(struct mbuf *, struct ifnet *, struct elaphdr *, int); 3315885Sjulian 3415885Sjulian/* 3515885Sjulian * Could probably merge these two code segments a little better... 3615885Sjulian */ 3715885Sjulianstatic void 3815885Sjulianatintr( void ) 3915885Sjulian{ 4015885Sjulian struct elaphdr *elhp, elh; 4115885Sjulian struct ifnet *ifp; 4215885Sjulian struct mbuf *m; 4315885Sjulian int s; 4415885Sjulian 4530822Sjulian /* 4630822Sjulian * First pull off all the phase 2 packets. 4730822Sjulian */ 4815885Sjulian for (;;) { 4915885Sjulian s = splimp(); 5015885Sjulian 5115885Sjulian IF_DEQUEUE( &atintrq2, m ); 5215885Sjulian 5315885Sjulian splx( s ); 5415885Sjulian 5515885Sjulian if ( m == 0 ) { /* no more queued packets */ 5615885Sjulian break; 5715885Sjulian } 5815885Sjulian 5915885Sjulian ifp = m->m_pkthdr.rcvif; 6015885Sjulian ddp_input( m, ifp, (struct elaphdr *)NULL, 2 ); 6115885Sjulian } 6215885Sjulian 6330822Sjulian /* 6430822Sjulian * Then pull off all the phase 1 packets. 6530822Sjulian */ 6615885Sjulian for (;;) { 6715885Sjulian s = splimp(); 6815885Sjulian 6915885Sjulian IF_DEQUEUE( &atintrq1, m ); 7015885Sjulian 7115885Sjulian splx( s ); 7215885Sjulian 7315885Sjulian if ( m == 0 ) { /* no more queued packets */ 7415885Sjulian break; 7515885Sjulian } 7615885Sjulian 7715885Sjulian ifp = m->m_pkthdr.rcvif; 7815885Sjulian 7915885Sjulian if ( m->m_len < SZ_ELAPHDR && 8015885Sjulian (( m = m_pullup( m, SZ_ELAPHDR )) == 0 )) { 8115885Sjulian ddpstat.ddps_tooshort++; 8215885Sjulian continue; 8315885Sjulian } 8415885Sjulian 8530822Sjulian /* 8630822Sjulian * this seems a little dubios, but I don't know phase 1 so leave it. 8730822Sjulian */ 8815885Sjulian elhp = mtod( m, struct elaphdr *); 8915885Sjulian m_adj( m, SZ_ELAPHDR ); 9015885Sjulian 9115885Sjulian if ( elhp->el_type == ELAP_DDPEXTEND ) { 9215885Sjulian ddp_input( m, ifp, (struct elaphdr *)NULL, 1 ); 9315885Sjulian } else { 9415885Sjulian bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR ); 9515885Sjulian ddp_input( m, ifp, &elh, 1 ); 9615885Sjulian } 9715885Sjulian } 9815885Sjulian return; 9915885Sjulian} 10015885Sjulian 10157178Speterstatic void 10257178Speternetisr_atalk_setup(void *dummy __unused) 10357178Speter{ 10457178Speter 10557178Speter register_netisr(NETISR_ATALK, atintr); 10657178Speter} 10757178SpeterSYSINIT(atalk_setup, SI_SUB_CPU, SI_ORDER_ANY, netisr_atalk_setup, NULL); 10815885Sjulian 10929185Sbdestatic void 11015885Sjulianddp_input( m, ifp, elh, phase ) 11115885Sjulian struct mbuf *m; 11215885Sjulian struct ifnet *ifp; 11315885Sjulian struct elaphdr *elh; 11415885Sjulian int phase; 11515885Sjulian{ 11615885Sjulian struct sockaddr_at from, to; 11715885Sjulian struct ddpshdr *dsh, ddps; 11815885Sjulian struct at_ifaddr *aa; 11917254Sjulian struct ddpehdr *deh = NULL, ddpe; 12015885Sjulian struct ddpcb *ddp; 12115885Sjulian int dlen, mlen; 12217254Sjulian u_short cksum = 0; 12315885Sjulian 12415885Sjulian bzero( (caddr_t)&from, sizeof( struct sockaddr_at )); 12530822Sjulian bzero( (caddr_t)&to, sizeof( struct sockaddr_at )); 12615885Sjulian if ( elh ) { 12730822Sjulian /* 12830822Sjulian * Extract the information in the short header. 12930822Sjulian * netowrk information is defaulted to ATADDR_ANYNET 13030822Sjulian * and node information comes from the elh info. 13130822Sjulian * We must be phase 1. 13230822Sjulian */ 13315885Sjulian ddpstat.ddps_short++; 13415885Sjulian 13515885Sjulian if ( m->m_len < sizeof( struct ddpshdr ) && 13615885Sjulian (( m = m_pullup( m, sizeof( struct ddpshdr ))) == 0 )) { 13715885Sjulian ddpstat.ddps_tooshort++; 13815885Sjulian return; 13915885Sjulian } 14015885Sjulian 14115885Sjulian dsh = mtod( m, struct ddpshdr *); 14215885Sjulian bcopy( (caddr_t)dsh, (caddr_t)&ddps, sizeof( struct ddpshdr )); 14315885Sjulian ddps.dsh_bytes = ntohl( ddps.dsh_bytes ); 14415885Sjulian dlen = ddps.dsh_len; 14515885Sjulian 14615885Sjulian to.sat_addr.s_net = ATADDR_ANYNET; 14715885Sjulian to.sat_addr.s_node = elh->el_dnode; 14815885Sjulian to.sat_port = ddps.dsh_dport; 14915885Sjulian from.sat_addr.s_net = ATADDR_ANYNET; 15015885Sjulian from.sat_addr.s_node = elh->el_snode; 15115885Sjulian from.sat_port = ddps.dsh_sport; 15215885Sjulian 15330822Sjulian /* 15430822Sjulian * Make sure that we point to the phase1 ifaddr info 15530822Sjulian * and that it's valid for this packet. 15630822Sjulian */ 15715885Sjulian for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 15830822Sjulian if ( (aa->aa_ifp == ifp) 15930822Sjulian && ( (aa->aa_flags & AFA_PHASE2) == 0) 16030822Sjulian && ( (to.sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node) 16130822Sjulian || (to.sat_addr.s_node == ATADDR_BCAST))) { 16215885Sjulian break; 16315885Sjulian } 16415885Sjulian } 16530822Sjulian /* 16630822Sjulian * maybe we got a broadcast not meant for us.. ditch it. 16730822Sjulian */ 16815885Sjulian if ( aa == NULL ) { 16915885Sjulian m_freem( m ); 17015885Sjulian return; 17115885Sjulian } 17215885Sjulian } else { 17330822Sjulian /* 17430822Sjulian * There was no 'elh' passed on. This could still be 17530822Sjulian * either phase1 or phase2. 17636658Sjulian * We have a long header, but we may be running on a phase 1 net. 17730822Sjulian * Extract out all the info regarding this packet's src & dst. 17830822Sjulian */ 17915885Sjulian ddpstat.ddps_long++; 18015885Sjulian 18115885Sjulian if ( m->m_len < sizeof( struct ddpehdr ) && 18215885Sjulian (( m = m_pullup( m, sizeof( struct ddpehdr ))) == 0 )) { 18315885Sjulian ddpstat.ddps_tooshort++; 18415885Sjulian return; 18515885Sjulian } 18615885Sjulian 18715885Sjulian deh = mtod( m, struct ddpehdr *); 18815885Sjulian bcopy( (caddr_t)deh, (caddr_t)&ddpe, sizeof( struct ddpehdr )); 18915885Sjulian ddpe.deh_bytes = ntohl( ddpe.deh_bytes ); 19015885Sjulian dlen = ddpe.deh_len; 19115885Sjulian 19215885Sjulian if (( cksum = ddpe.deh_sum ) == 0 ) { 19315885Sjulian ddpstat.ddps_nosum++; 19415885Sjulian } 19515885Sjulian 19615885Sjulian from.sat_addr.s_net = ddpe.deh_snet; 19715885Sjulian from.sat_addr.s_node = ddpe.deh_snode; 19815885Sjulian from.sat_port = ddpe.deh_sport; 19915885Sjulian to.sat_addr.s_net = ddpe.deh_dnet; 20015885Sjulian to.sat_addr.s_node = ddpe.deh_dnode; 20115885Sjulian to.sat_port = ddpe.deh_dport; 20215885Sjulian 20315885Sjulian if ( to.sat_addr.s_net == ATADDR_ANYNET ) { 20430822Sjulian /* 20530822Sjulian * The TO address doesn't specify a net, 20630822Sjulian * So by definition it's for this net. 20730822Sjulian * Try find ifaddr info with the right phase, 20836658Sjulian * the right interface, and either to our node, a broadcast, 20930822Sjulian * or looped back (though that SHOULD be covered in the other 21030822Sjulian * cases). 21130822Sjulian * 21230822Sjulian * XXX If we have multiple interfaces, then the first with 21330822Sjulian * this node number will match (which may NOT be what we want, 21430822Sjulian * but it's probably safe in 99.999% of cases. 21530822Sjulian */ 21615885Sjulian for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 21715885Sjulian if ( phase == 1 && ( aa->aa_flags & AFA_PHASE2 )) { 21815885Sjulian continue; 21915885Sjulian } 22015885Sjulian if ( phase == 2 && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) { 22115885Sjulian continue; 22215885Sjulian } 22330822Sjulian if ( (aa->aa_ifp == ifp) 22430822Sjulian && ( (to.sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node) 22530822Sjulian || (to.sat_addr.s_node == ATADDR_BCAST) 22630822Sjulian || (ifp->if_flags & IFF_LOOPBACK))) { 22715885Sjulian break; 22815885Sjulian } 22915885Sjulian } 23015885Sjulian } else { 23130822Sjulian /* 23230822Sjulian * A destination network was given. We just try to find 23330822Sjulian * which ifaddr info matches it. 23430822Sjulian */ 23515885Sjulian for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 23630822Sjulian /* 23730822Sjulian * This is a kludge. Accept packets that are 23830822Sjulian * for any router on a local netrange. 23930822Sjulian */ 24015885Sjulian if ( to.sat_addr.s_net == aa->aa_firstnet && 24115885Sjulian to.sat_addr.s_node == 0 ) { 24215885Sjulian break; 24315885Sjulian } 24430822Sjulian /* 24530822Sjulian * Don't use ifaddr info for which we are totally outside the 24630822Sjulian * netrange, and it's not a startup packet. 24730822Sjulian * Startup packets are always implicitly allowed on to 24830822Sjulian * the next test. 24930822Sjulian */ 25030822Sjulian if ((( ntohs( to.sat_addr.s_net ) < ntohs( aa->aa_firstnet )) 25130822Sjulian || (ntohs( to.sat_addr.s_net ) > ntohs( aa->aa_lastnet ))) 25236658Sjulian && (( ntohs( to.sat_addr.s_net ) < 0xff00) 25336658Sjulian || (ntohs( to.sat_addr.s_net ) > 0xfffe ))) { 25415885Sjulian continue; 25515885Sjulian } 25630822Sjulian 25730822Sjulian /* 25830822Sjulian * Don't record a match either if we just don't have a match 25930822Sjulian * in the node address. This can have if the interface 26030822Sjulian * is in promiscuous mode for example. 26130822Sjulian */ 26230822Sjulian if (( to.sat_addr.s_node != AA_SAT( aa )->sat_addr.s_node) 26330822Sjulian && (to.sat_addr.s_node != ATADDR_BCAST) ) { 26415885Sjulian continue; 26515885Sjulian } 26615885Sjulian break; 26715885Sjulian } 26815885Sjulian } 26915885Sjulian } 27015885Sjulian 27115885Sjulian /* 27215885Sjulian * Adjust the length, removing any padding that may have been added 27315885Sjulian * at a link layer. We do this before we attempt to forward a packet, 27415885Sjulian * possibly on a different media. 27515885Sjulian */ 27615885Sjulian mlen = m->m_pkthdr.len; 27715885Sjulian if ( mlen < dlen ) { 27815885Sjulian ddpstat.ddps_toosmall++; 27915885Sjulian m_freem( m ); 28015885Sjulian return; 28115885Sjulian } 28215885Sjulian if ( mlen > dlen ) { 28315885Sjulian m_adj( m, dlen - mlen ); 28415885Sjulian } 28515885Sjulian 28615885Sjulian /* 28730822Sjulian * If it aint for a net on any of our interfaces, 28830822Sjulian * or it IS for a net on a different interface than it came in on, 28936658Sjulian * (and it is not looped back) then consider if we should forward it. 29036658Sjulian * As we are not really a router this is a bit cheeky, but it may be 29130822Sjulian * useful some day. 29215885Sjulian */ 29330822Sjulian if ( (aa == NULL) 29430822Sjulian || ( (to.sat_addr.s_node == ATADDR_BCAST) 29530822Sjulian && (aa->aa_ifp != ifp) 29630822Sjulian && (( ifp->if_flags & IFF_LOOPBACK ) == 0 ))) { 29730822Sjulian /* 29830822Sjulian * If we've explicitly disabled it, don't route anything 29930822Sjulian */ 30015885Sjulian if ( ddp_forward == 0 ) { 30115885Sjulian m_freem( m ); 30215885Sjulian return; 30315885Sjulian } 30430822Sjulian /* 30530822Sjulian * If the cached forwarding route is still valid, use it. 30630822Sjulian */ 30730822Sjulian if ( forwro.ro_rt 30830822Sjulian && ( satosat(&forwro.ro_dst)->sat_addr.s_net != to.sat_addr.s_net 30930822Sjulian || satosat(&forwro.ro_dst)->sat_addr.s_node != to.sat_addr.s_node )) { 31015885Sjulian RTFREE( forwro.ro_rt ); 31115885Sjulian forwro.ro_rt = (struct rtentry *)0; 31215885Sjulian } 31330822Sjulian 31430822Sjulian /* 31530822Sjulian * If we don't have a cached one (any more) or it's useless, 31630822Sjulian * Then get a new route. 31730822Sjulian * XXX this could cause a 'route leak'. check this! 31830822Sjulian */ 31930822Sjulian if ( forwro.ro_rt == (struct rtentry *)0 32030822Sjulian || forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) { 32115885Sjulian forwro.ro_dst.sa_len = sizeof( struct sockaddr_at ); 32215885Sjulian forwro.ro_dst.sa_family = AF_APPLETALK; 32330822Sjulian satosat(&forwro.ro_dst)->sat_addr.s_net = to.sat_addr.s_net; 32430822Sjulian satosat(&forwro.ro_dst)->sat_addr.s_node = to.sat_addr.s_node; 32530822Sjulian rtalloc(&forwro); 32615885Sjulian } 32715885Sjulian 32830822Sjulian /* 32930822Sjulian * If it's not going to get there on this hop, and it's 33030822Sjulian * already done too many hops, then throw it away. 33130822Sjulian */ 33230822Sjulian if ( (to.sat_addr.s_net != satosat( &forwro.ro_dst )->sat_addr.s_net) 33330822Sjulian && (ddpe.deh_hops == DDP_MAXHOPS) ) { 33415885Sjulian m_freem( m ); 33515885Sjulian return; 33615885Sjulian } 33715885Sjulian 33830822Sjulian /* 33930822Sjulian * A ddp router might use the same interface 34030822Sjulian * to forward the packet, which this would not effect. 34130822Sjulian * Don't allow packets to cross from one interface to another however. 34230822Sjulian */ 34330822Sjulian if ( ddp_firewall 34430822Sjulian && ( (forwro.ro_rt == NULL) 34530822Sjulian || (forwro.ro_rt->rt_ifp != ifp))) { 34615885Sjulian m_freem( m ); 34715885Sjulian return; 34815885Sjulian } 34915885Sjulian 35030822Sjulian /* 35130822Sjulian * Adjust the header. 35230822Sjulian * If it was a short header then it would have not gotten here, 35330822Sjulian * so we can assume there is room to drop the header in. 35430822Sjulian * XXX what about promiscuous mode, etc... 35530822Sjulian */ 35615885Sjulian ddpe.deh_hops++; 35715885Sjulian ddpe.deh_bytes = htonl( ddpe.deh_bytes ); 35815885Sjulian bcopy( (caddr_t)&ddpe, (caddr_t)deh, sizeof( u_short )); /* XXX deh? */ 35915885Sjulian if ( ddp_route( m, &forwro )) { 36015885Sjulian ddpstat.ddps_cantforward++; 36115885Sjulian } else { 36215885Sjulian ddpstat.ddps_forward++; 36315885Sjulian } 36415885Sjulian return; 36515885Sjulian } 36615885Sjulian 36730822Sjulian /* 36830822Sjulian * It was for us, and we have an ifaddr to use with it. 36930822Sjulian */ 37015885Sjulian from.sat_len = sizeof( struct sockaddr_at ); 37115885Sjulian from.sat_family = AF_APPLETALK; 37215885Sjulian 37330822Sjulian /* 37430822Sjulian * We are no longer interested in the link layer. 37530822Sjulian * so cut it off. 37630822Sjulian */ 37715885Sjulian if ( elh ) { 37815885Sjulian m_adj( m, sizeof( struct ddpshdr )); 37915885Sjulian } else { 38015885Sjulian if ( ddp_cksum && cksum && cksum != at_cksum( m, sizeof( int ))) { 38115885Sjulian ddpstat.ddps_badsum++; 38215885Sjulian m_freem( m ); 38315885Sjulian return; 38415885Sjulian } 38515885Sjulian m_adj( m, sizeof( struct ddpehdr )); 38615885Sjulian } 38715885Sjulian 38830822Sjulian /* 38930822Sjulian * Search for ddp protocol control blocks that match these 39030822Sjulian * addresses. 39130822Sjulian */ 39215885Sjulian if (( ddp = ddp_search( &from, &to, aa )) == NULL ) { 39315885Sjulian m_freem( m ); 39415885Sjulian return; 39515885Sjulian } 39615885Sjulian 39730822Sjulian /* 39830822Sjulian * If we found one, deliver th epacket to the socket 39930822Sjulian */ 40015885Sjulian if ( sbappendaddr( &ddp->ddp_socket->so_rcv, (struct sockaddr *)&from, 40115885Sjulian m, (struct mbuf *)0 ) == 0 ) { 40230822Sjulian /* 40330822Sjulian * If the socket is full (or similar error) dump the packet. 40430822Sjulian */ 40515885Sjulian ddpstat.ddps_nosockspace++; 40615885Sjulian m_freem( m ); 40715885Sjulian return; 40815885Sjulian } 40930822Sjulian /* 41030822Sjulian * And wake up whatever might be waiting for it 41130822Sjulian */ 41215885Sjulian sorwakeup( ddp->ddp_socket ); 41315885Sjulian} 41415885Sjulian 41517254Sjulian#if 0 41630822Sjulian/* As if we haven't got enough of this sort of think floating 41730822Sjulianaround the kernel :) */ 41817254Sjulian 41915885Sjulian#define BPXLEN 48 42015885Sjulian#define BPALEN 16 42115885Sjulian#include <ctype.h> 42215885Sjulianchar hexdig[] = "0123456789ABCDEF"; 42315885Sjulian 42415885Sjulianstatic void 42515885Sjulianbprint( char *data, int len ) 42615885Sjulian{ 42715885Sjulian char xout[ BPXLEN ], aout[ BPALEN ]; 42815885Sjulian int i = 0; 42915885Sjulian 43015885Sjulian bzero( xout, BPXLEN ); 43115885Sjulian bzero( aout, BPALEN ); 43215885Sjulian 43315885Sjulian for ( ;; ) { 43415885Sjulian if ( len < 1 ) { 43515885Sjulian if ( i != 0 ) { 43615885Sjulian printf( "%s\t%s\n", xout, aout ); 43715885Sjulian } 43815885Sjulian printf( "%s\n", "(end)" ); 43915885Sjulian break; 44015885Sjulian } 44115885Sjulian 44215885Sjulian xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; 44315885Sjulian xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ]; 44415885Sjulian 44515885Sjulian if ( (u_char)*data < 0x7f && (u_char)*data > 0x20 ) { 44615885Sjulian aout[ i ] = *data; 44715885Sjulian } else { 44815885Sjulian aout[ i ] = '.'; 44915885Sjulian } 45015885Sjulian 45115885Sjulian xout[ (i*3) + 2 ] = ' '; 45215885Sjulian 45315885Sjulian i++; 45415885Sjulian len--; 45515885Sjulian data++; 45615885Sjulian 45715885Sjulian if ( i > BPALEN - 2 ) { 45815885Sjulian printf( "%s\t%s\n", xout, aout ); 45915885Sjulian bzero( xout, BPXLEN ); 46015885Sjulian bzero( aout, BPALEN ); 46115885Sjulian i = 0; 46215885Sjulian continue; 46315885Sjulian } 46415885Sjulian } 46515885Sjulian} 46615885Sjulian 46715885Sjulianstatic void 46815885Sjulianm_printm( struct mbuf *m ) 46915885Sjulian{ 47015885Sjulian for (; m; m = m->m_next ) { 47115885Sjulian bprint( mtod( m, char * ), m->m_len ); 47215885Sjulian } 47315885Sjulian} 47417254Sjulian#endif 475