ddp_input.c revision 18207
115885Sjulian/* 215885Sjulian * Copyright (c) 1990,1994 Regents of The University of Michigan. 315885Sjulian * All Rights Reserved. See COPYRIGHT. 415885Sjulian */ 515885Sjulian 615885Sjulian#include <sys/types.h> 715885Sjulian#include <sys/param.h> 815885Sjulian#include <sys/systm.h> 915885Sjulian#include <sys/kernel.h> 1015885Sjulian#include <net/netisr.h> 1115885Sjulian#include <sys/mbuf.h> 1215885Sjulian#include <sys/socket.h> 1315885Sjulian#include <sys/socketvar.h> 1415885Sjulian#include <sys/syslog.h> 1515885Sjulian#include <net/if.h> 1615885Sjulian#include <net/route.h> 1715885Sjulian#include <netinet/in.h> 1815885Sjulian#include <netinet/if_ether.h> 1915885Sjulian 2018207Sbde#include <netatalk/at.h> 2118207Sbde#include <netatalk/at_var.h> 2218207Sbde#include <netatalk/endian.h> 2318207Sbde#include <netatalk/ddp.h> 2418207Sbde#include <netatalk/ddp_var.h> 2515885Sjulian#include <netatalk/at_extern.h> 2615885Sjulian 2715885Sjulianint ddp_forward = 1; 2815885Sjulianint ddp_firewall = 0; 2915885Sjulianextern int ddp_cksum; 3015885Sjulianvoid ddp_input( struct mbuf *, struct ifnet *, struct elaphdr *, int ); 3115885Sjulian 3215885Sjulian/* 3315885Sjulian * Could probably merge these two code segments a little better... 3415885Sjulian */ 3515885Sjulianstatic void 3615885Sjulianatintr( void ) 3715885Sjulian{ 3815885Sjulian struct elaphdr *elhp, elh; 3915885Sjulian struct ifnet *ifp; 4015885Sjulian struct mbuf *m; 4115885Sjulian struct at_ifaddr *aa; 4215885Sjulian int s; 4315885Sjulian 4415885Sjulian for (;;) { 4515885Sjulian s = splimp(); 4615885Sjulian 4715885Sjulian IF_DEQUEUE( &atintrq2, m ); 4815885Sjulian 4915885Sjulian splx( s ); 5015885Sjulian 5115885Sjulian if ( m == 0 ) { /* no more queued packets */ 5215885Sjulian break; 5315885Sjulian } 5415885Sjulian 5515885Sjulian ifp = m->m_pkthdr.rcvif; 5615885Sjulian for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 5715885Sjulian if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 )) { 5815885Sjulian break; 5915885Sjulian } 6015885Sjulian } 6115885Sjulian if ( aa == NULL ) { /* ifp not an appletalk interface */ 6215885Sjulian m_freem( m ); 6315885Sjulian continue; 6415885Sjulian } 6515885Sjulian 6615885Sjulian ddp_input( m, ifp, (struct elaphdr *)NULL, 2 ); 6715885Sjulian } 6815885Sjulian 6915885Sjulian for (;;) { 7015885Sjulian s = splimp(); 7115885Sjulian 7215885Sjulian IF_DEQUEUE( &atintrq1, m ); 7315885Sjulian 7415885Sjulian splx( s ); 7515885Sjulian 7615885Sjulian if ( m == 0 ) { /* no more queued packets */ 7715885Sjulian break; 7815885Sjulian } 7915885Sjulian 8015885Sjulian ifp = m->m_pkthdr.rcvif; 8115885Sjulian for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 8215885Sjulian if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) { 8315885Sjulian break; 8415885Sjulian } 8515885Sjulian } 8615885Sjulian if ( aa == NULL ) { /* ifp not an appletalk interface */ 8715885Sjulian m_freem( m ); 8815885Sjulian continue; 8915885Sjulian } 9015885Sjulian 9115885Sjulian if ( m->m_len < SZ_ELAPHDR && 9215885Sjulian (( m = m_pullup( m, SZ_ELAPHDR )) == 0 )) { 9315885Sjulian ddpstat.ddps_tooshort++; 9415885Sjulian continue; 9515885Sjulian } 9615885Sjulian 9715885Sjulian elhp = mtod( m, struct elaphdr *); 9815885Sjulian m_adj( m, SZ_ELAPHDR ); 9915885Sjulian 10015885Sjulian if ( elhp->el_type == ELAP_DDPEXTEND ) { 10115885Sjulian ddp_input( m, ifp, (struct elaphdr *)NULL, 1 ); 10215885Sjulian } else { 10315885Sjulian bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR ); 10415885Sjulian ddp_input( m, ifp, &elh, 1 ); 10515885Sjulian } 10615885Sjulian } 10715885Sjulian return; 10815885Sjulian} 10915885Sjulian 11015885SjulianNETISR_SET(NETISR_ATALK, atintr); 11115885Sjulian 11215885Sjulianstruct route forwro; 11315885Sjulian 11415885Sjulianvoid 11515885Sjulianddp_input( m, ifp, elh, phase ) 11615885Sjulian struct mbuf *m; 11715885Sjulian struct ifnet *ifp; 11815885Sjulian struct elaphdr *elh; 11915885Sjulian int phase; 12015885Sjulian{ 12115885Sjulian struct sockaddr_at from, to; 12215885Sjulian struct ddpshdr *dsh, ddps; 12315885Sjulian struct at_ifaddr *aa; 12417254Sjulian struct ddpehdr *deh = NULL, ddpe; 12515885Sjulian struct ddpcb *ddp; 12615885Sjulian int dlen, mlen; 12717254Sjulian u_short cksum = 0; 12815885Sjulian 12915885Sjulian bzero( (caddr_t)&from, sizeof( struct sockaddr_at )); 13015885Sjulian if ( elh ) { 13115885Sjulian ddpstat.ddps_short++; 13215885Sjulian 13315885Sjulian if ( m->m_len < sizeof( struct ddpshdr ) && 13415885Sjulian (( m = m_pullup( m, sizeof( struct ddpshdr ))) == 0 )) { 13515885Sjulian ddpstat.ddps_tooshort++; 13615885Sjulian return; 13715885Sjulian } 13815885Sjulian 13915885Sjulian dsh = mtod( m, struct ddpshdr *); 14015885Sjulian bcopy( (caddr_t)dsh, (caddr_t)&ddps, sizeof( struct ddpshdr )); 14115885Sjulian ddps.dsh_bytes = ntohl( ddps.dsh_bytes ); 14215885Sjulian dlen = ddps.dsh_len; 14315885Sjulian 14415885Sjulian to.sat_addr.s_net = ATADDR_ANYNET; 14515885Sjulian to.sat_addr.s_node = elh->el_dnode; 14615885Sjulian to.sat_port = ddps.dsh_dport; 14715885Sjulian from.sat_addr.s_net = ATADDR_ANYNET; 14815885Sjulian from.sat_addr.s_node = elh->el_snode; 14915885Sjulian from.sat_port = ddps.dsh_sport; 15015885Sjulian 15115885Sjulian for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 15215885Sjulian if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 ) == 0 && 15315885Sjulian ( AA_SAT( aa )->sat_addr.s_node == to.sat_addr.s_node || 15415885Sjulian to.sat_addr.s_node == ATADDR_BCAST )) { 15515885Sjulian break; 15615885Sjulian } 15715885Sjulian } 15815885Sjulian if ( aa == NULL ) { 15915885Sjulian m_freem( m ); 16015885Sjulian return; 16115885Sjulian } 16215885Sjulian } else { 16315885Sjulian ddpstat.ddps_long++; 16415885Sjulian 16515885Sjulian if ( m->m_len < sizeof( struct ddpehdr ) && 16615885Sjulian (( m = m_pullup( m, sizeof( struct ddpehdr ))) == 0 )) { 16715885Sjulian ddpstat.ddps_tooshort++; 16815885Sjulian return; 16915885Sjulian } 17015885Sjulian 17115885Sjulian deh = mtod( m, struct ddpehdr *); 17215885Sjulian bcopy( (caddr_t)deh, (caddr_t)&ddpe, sizeof( struct ddpehdr )); 17315885Sjulian ddpe.deh_bytes = ntohl( ddpe.deh_bytes ); 17415885Sjulian dlen = ddpe.deh_len; 17515885Sjulian 17615885Sjulian if (( cksum = ddpe.deh_sum ) == 0 ) { 17715885Sjulian ddpstat.ddps_nosum++; 17815885Sjulian } 17915885Sjulian 18015885Sjulian from.sat_addr.s_net = ddpe.deh_snet; 18115885Sjulian from.sat_addr.s_node = ddpe.deh_snode; 18215885Sjulian from.sat_port = ddpe.deh_sport; 18315885Sjulian to.sat_addr.s_net = ddpe.deh_dnet; 18415885Sjulian to.sat_addr.s_node = ddpe.deh_dnode; 18515885Sjulian to.sat_port = ddpe.deh_dport; 18615885Sjulian 18715885Sjulian if ( to.sat_addr.s_net == ATADDR_ANYNET ) { 18815885Sjulian for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 18915885Sjulian if ( phase == 1 && ( aa->aa_flags & AFA_PHASE2 )) { 19015885Sjulian continue; 19115885Sjulian } 19215885Sjulian if ( phase == 2 && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) { 19315885Sjulian continue; 19415885Sjulian } 19515885Sjulian if ( aa->aa_ifp == ifp && 19615885Sjulian ( AA_SAT( aa )->sat_addr.s_node == to.sat_addr.s_node || 19715885Sjulian to.sat_addr.s_node == ATADDR_BCAST || 19815885Sjulian ( ifp->if_flags & IFF_LOOPBACK ))) { 19915885Sjulian break; 20015885Sjulian } 20115885Sjulian } 20215885Sjulian } else { 20315885Sjulian for ( aa = at_ifaddr; aa; aa = aa->aa_next ) { 20415885Sjulian if ( to.sat_addr.s_net == aa->aa_firstnet && 20515885Sjulian to.sat_addr.s_node == 0 ) { 20615885Sjulian break; 20715885Sjulian } 20815885Sjulian if (( ntohs( to.sat_addr.s_net ) < ntohs( aa->aa_firstnet ) || 20915885Sjulian ntohs( to.sat_addr.s_net ) > ntohs( aa->aa_lastnet )) && 21015885Sjulian ( ntohs( to.sat_addr.s_net ) < ntohs( 0xff00 ) || 21115885Sjulian ntohs( to.sat_addr.s_net ) > ntohs( 0xfffe ))) { 21215885Sjulian continue; 21315885Sjulian } 21415885Sjulian if ( to.sat_addr.s_node != AA_SAT( aa )->sat_addr.s_node && 21515885Sjulian to.sat_addr.s_node != ATADDR_BCAST ) { 21615885Sjulian continue; 21715885Sjulian } 21815885Sjulian break; 21915885Sjulian } 22015885Sjulian } 22115885Sjulian } 22215885Sjulian 22315885Sjulian /* 22415885Sjulian * Adjust the length, removing any padding that may have been added 22515885Sjulian * at a link layer. We do this before we attempt to forward a packet, 22615885Sjulian * possibly on a different media. 22715885Sjulian */ 22815885Sjulian mlen = m->m_pkthdr.len; 22915885Sjulian if ( mlen < dlen ) { 23015885Sjulian ddpstat.ddps_toosmall++; 23115885Sjulian m_freem( m ); 23215885Sjulian return; 23315885Sjulian } 23415885Sjulian if ( mlen > dlen ) { 23515885Sjulian m_adj( m, dlen - mlen ); 23615885Sjulian } 23715885Sjulian 23815885Sjulian /* 23915885Sjulian * XXX Should we deliver broadcasts locally, also, or rely on the 24015885Sjulian * link layer to give us a copy? For the moment, the latter. 24115885Sjulian */ 24215885Sjulian if ( aa == NULL || ( to.sat_addr.s_node == ATADDR_BCAST && 24315885Sjulian aa->aa_ifp != ifp && ( ifp->if_flags & IFF_LOOPBACK ) == 0 )) { 24415885Sjulian if ( ddp_forward == 0 ) { 24515885Sjulian m_freem( m ); 24615885Sjulian return; 24715885Sjulian } 24815885Sjulian if ( forwro.ro_rt && ( satosat( &forwro.ro_dst )->sat_addr.s_net != 24915885Sjulian to.sat_addr.s_net || 25015885Sjulian satosat( &forwro.ro_dst )->sat_addr.s_node != 25115885Sjulian to.sat_addr.s_node )) { 25215885Sjulian RTFREE( forwro.ro_rt ); 25315885Sjulian forwro.ro_rt = (struct rtentry *)0; 25415885Sjulian } 25515885Sjulian if ( forwro.ro_rt == (struct rtentry *)0 || 25615885Sjulian forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) { 25715885Sjulian forwro.ro_dst.sa_len = sizeof( struct sockaddr_at ); 25815885Sjulian forwro.ro_dst.sa_family = AF_APPLETALK; 25915885Sjulian satosat( &forwro.ro_dst )->sat_addr.s_net = to.sat_addr.s_net; 26015885Sjulian satosat( &forwro.ro_dst )->sat_addr.s_node = to.sat_addr.s_node; 26115885Sjulian rtalloc( &forwro ); 26215885Sjulian } 26315885Sjulian 26415885Sjulian if ( to.sat_addr.s_net != satosat( &forwro.ro_dst )->sat_addr.s_net && 26515885Sjulian ddpe.deh_hops == DDP_MAXHOPS ) { 26615885Sjulian m_freem( m ); 26715885Sjulian return; 26815885Sjulian } 26915885Sjulian 27015885Sjulian if ( ddp_firewall && 27115885Sjulian ( forwro.ro_rt == NULL || forwro.ro_rt->rt_ifp != ifp )) { 27215885Sjulian m_freem( m ); 27315885Sjulian return; 27415885Sjulian } 27515885Sjulian 27615885Sjulian ddpe.deh_hops++; 27715885Sjulian ddpe.deh_bytes = htonl( ddpe.deh_bytes ); 27815885Sjulian bcopy( (caddr_t)&ddpe, (caddr_t)deh, sizeof( u_short )); /* XXX deh? */ 27915885Sjulian if ( ddp_route( m, &forwro )) { 28015885Sjulian ddpstat.ddps_cantforward++; 28115885Sjulian } else { 28215885Sjulian ddpstat.ddps_forward++; 28315885Sjulian } 28415885Sjulian return; 28515885Sjulian } 28615885Sjulian 28715885Sjulian from.sat_len = sizeof( struct sockaddr_at ); 28815885Sjulian from.sat_family = AF_APPLETALK; 28915885Sjulian 29015885Sjulian if ( elh ) { 29115885Sjulian m_adj( m, sizeof( struct ddpshdr )); 29215885Sjulian } else { 29315885Sjulian if ( ddp_cksum && cksum && cksum != at_cksum( m, sizeof( int ))) { 29415885Sjulian ddpstat.ddps_badsum++; 29515885Sjulian m_freem( m ); 29615885Sjulian return; 29715885Sjulian } 29815885Sjulian m_adj( m, sizeof( struct ddpehdr )); 29915885Sjulian } 30015885Sjulian 30115885Sjulian if (( ddp = ddp_search( &from, &to, aa )) == NULL ) { 30215885Sjulian m_freem( m ); 30315885Sjulian return; 30415885Sjulian } 30515885Sjulian 30615885Sjulian if ( sbappendaddr( &ddp->ddp_socket->so_rcv, (struct sockaddr *)&from, 30715885Sjulian m, (struct mbuf *)0 ) == 0 ) { 30815885Sjulian ddpstat.ddps_nosockspace++; 30915885Sjulian m_freem( m ); 31015885Sjulian return; 31115885Sjulian } 31215885Sjulian sorwakeup( ddp->ddp_socket ); 31315885Sjulian} 31415885Sjulian 31517254Sjulian#if 0 31617254Sjulian 31715885Sjulian#define BPXLEN 48 31815885Sjulian#define BPALEN 16 31915885Sjulian#include <ctype.h> 32015885Sjulianchar hexdig[] = "0123456789ABCDEF"; 32115885Sjulian 32215885Sjulianstatic void 32315885Sjulianbprint( char *data, int len ) 32415885Sjulian{ 32515885Sjulian char xout[ BPXLEN ], aout[ BPALEN ]; 32615885Sjulian int i = 0; 32715885Sjulian 32815885Sjulian bzero( xout, BPXLEN ); 32915885Sjulian bzero( aout, BPALEN ); 33015885Sjulian 33115885Sjulian for ( ;; ) { 33215885Sjulian if ( len < 1 ) { 33315885Sjulian if ( i != 0 ) { 33415885Sjulian printf( "%s\t%s\n", xout, aout ); 33515885Sjulian } 33615885Sjulian printf( "%s\n", "(end)" ); 33715885Sjulian break; 33815885Sjulian } 33915885Sjulian 34015885Sjulian xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; 34115885Sjulian xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ]; 34215885Sjulian 34315885Sjulian if ( (u_char)*data < 0x7f && (u_char)*data > 0x20 ) { 34415885Sjulian aout[ i ] = *data; 34515885Sjulian } else { 34615885Sjulian aout[ i ] = '.'; 34715885Sjulian } 34815885Sjulian 34915885Sjulian xout[ (i*3) + 2 ] = ' '; 35015885Sjulian 35115885Sjulian i++; 35215885Sjulian len--; 35315885Sjulian data++; 35415885Sjulian 35515885Sjulian if ( i > BPALEN - 2 ) { 35615885Sjulian printf( "%s\t%s\n", xout, aout ); 35715885Sjulian bzero( xout, BPXLEN ); 35815885Sjulian bzero( aout, BPALEN ); 35915885Sjulian i = 0; 36015885Sjulian continue; 36115885Sjulian } 36215885Sjulian } 36315885Sjulian} 36415885Sjulian 36515885Sjulianstatic void 36615885Sjulianm_printm( struct mbuf *m ) 36715885Sjulian{ 36815885Sjulian for (; m; m = m->m_next ) { 36915885Sjulian bprint( mtod( m, char * ), m->m_len ); 37015885Sjulian } 37115885Sjulian} 37217254Sjulian#endif 373