ddp_pcb.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/errno.h>
715885Sjulian#include <sys/types.h>
815885Sjulian#include <sys/param.h>
915885Sjulian#include <sys/systm.h>
1015885Sjulian#include <sys/proc.h>
1115885Sjulian#include <sys/mbuf.h>
1215885Sjulian#include <sys/ioctl.h>
1315885Sjulian#include <sys/socket.h>
1415885Sjulian#include <sys/socketvar.h>
1515885Sjulian#include <sys/protosw.h>
1615885Sjulian#include <net/if.h>
1715885Sjulian#include <net/route.h>
1815885Sjulian#include <netinet/in.h>
1915885Sjulian#include <netinet/if_ether.h>
2015885Sjulian
2118207Sbde#include <netatalk/at.h>
2218207Sbde#include <netatalk/at_var.h>
2318207Sbde#include <netatalk/ddp_var.h>
2418207Sbde#include <netatalk/aarp.h>
2518207Sbde#include <netatalk/endian.h>
2615885Sjulian#include <netatalk/at_extern.h>
2715885Sjulian
2815885Sjulianstatic void at_pcbdisconnect( struct ddpcb *ddp );
2915885Sjulianstatic void at_sockaddr( struct ddpcb *ddp, struct mbuf *addr );
3015885Sjulianstatic int at_pcbsetaddr( struct ddpcb *ddp, struct mbuf *addr, struct proc *p);
3115885Sjulianstatic int at_pcbconnect( struct ddpcb *ddp, struct mbuf *addr, struct proc *p);
3215885Sjulianstatic void at_pcbdetach( struct socket *so, struct ddpcb *ddp);
3315885Sjulianstatic int at_pcballoc( struct socket *so );
3415885Sjulian
3515885Sjulianstruct ddpcb	*ddp_ports[ ATPORT_LAST ];
3615885Sjulianstruct ddpcb	*ddpcb = NULL;
3715885Sjulianu_long		ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
3815885Sjulianu_long		ddp_recvspace = 10 * ( 587 + sizeof( struct sockaddr_at ));
3915885Sjulian
4015885Sjulian/*ARGSUSED*/
4115885Sjulianint
4215885Sjulianddp_usrreq( struct socket *so, int req, struct mbuf *m,
4315885Sjulian		struct mbuf  *addr, struct mbuf *rights)
4415885Sjulian{
4515885Sjulian    struct proc *p = curproc;           /* XXX */
4615885Sjulian    struct ddpcb	*ddp;
4715885Sjulian    int			error = 0;
4815885Sjulian
4915885Sjulian    ddp = sotoddpcb( so );
5015885Sjulian
5115885Sjulian    if ( req == PRU_CONTROL ) {
5215885Sjulian	return( at_control( (int) m, (caddr_t) addr,
5317254Sjulian		(struct ifnet *) rights, (struct proc *)p ));
5415885Sjulian    }
5515885Sjulian
5615885Sjulian    if ( rights && rights->m_len ) {
5715885Sjulian	error = EINVAL;
5815885Sjulian	goto release;
5915885Sjulian    }
6015885Sjulian
6115885Sjulian    if ( ddp == NULL && req != PRU_ATTACH ) {
6215885Sjulian	error = EINVAL;
6315885Sjulian	goto release;
6415885Sjulian    }
6515885Sjulian
6615885Sjulian    switch ( req ) {
6715885Sjulian    case PRU_ATTACH :
6815885Sjulian	if ( ddp != NULL ) {
6915885Sjulian	    error = EINVAL;
7015885Sjulian	    break;
7115885Sjulian	}
7215885Sjulian	if (( error = at_pcballoc( so )) != 0 ) {
7315885Sjulian	    break;
7415885Sjulian	}
7515885Sjulian	error = soreserve( so, ddp_sendspace, ddp_recvspace );
7615885Sjulian	break;
7715885Sjulian
7815885Sjulian    case PRU_DETACH :
7915885Sjulian	at_pcbdetach( so, ddp );
8015885Sjulian	break;
8115885Sjulian
8215885Sjulian    case PRU_BIND :
8317254Sjulian	error = at_pcbsetaddr( ddp, addr, p );
8415885Sjulian	break;
8515885Sjulian
8615885Sjulian    case PRU_SOCKADDR :
8715885Sjulian	at_sockaddr( ddp, addr );
8815885Sjulian	break;
8915885Sjulian
9015885Sjulian    case PRU_CONNECT:
9115885Sjulian	if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
9215885Sjulian	    error = EISCONN;
9315885Sjulian	    break;
9415885Sjulian	}
9515885Sjulian
9617254Sjulian	error = at_pcbconnect( ddp, addr, p );
9715885Sjulian	if ( error == 0 )
9815885Sjulian	    soisconnected( so );
9915885Sjulian	break;
10015885Sjulian
10115885Sjulian    case PRU_DISCONNECT:
10215885Sjulian	if ( ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE ) {
10315885Sjulian	    error = ENOTCONN;
10415885Sjulian	    break;
10515885Sjulian	}
10615885Sjulian	at_pcbdisconnect( ddp );
10715885Sjulian	soisdisconnected( so );
10815885Sjulian	break;
10915885Sjulian
11015885Sjulian    case PRU_SHUTDOWN:
11115885Sjulian	socantsendmore( so );
11215885Sjulian	break;
11315885Sjulian
11415885Sjulian    case PRU_SEND: {
11515885Sjulian	int	s = 0;
11615885Sjulian
11715885Sjulian	if ( addr ) {
11815885Sjulian	    if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
11915885Sjulian		error = EISCONN;
12015885Sjulian		break;
12115885Sjulian	    }
12215885Sjulian
12315885Sjulian	    s = splnet();
12417254Sjulian	    error = at_pcbconnect( ddp, addr, p );
12515885Sjulian	    if ( error ) {
12615885Sjulian		splx( s );
12715885Sjulian		break;
12815885Sjulian	    }
12915885Sjulian	} else {
13015885Sjulian	    if ( ddp->ddp_fsat.sat_port == ATADDR_ANYPORT ) {
13115885Sjulian		error = ENOTCONN;
13215885Sjulian		break;
13315885Sjulian	    }
13415885Sjulian	}
13515885Sjulian
13615885Sjulian	error = ddp_output( ddp, m );
13715885Sjulian	m = NULL;
13815885Sjulian	if ( addr ) {
13915885Sjulian	    at_pcbdisconnect( ddp );
14015885Sjulian	    splx( s );
14115885Sjulian	}
14215885Sjulian	}
14315885Sjulian	break;
14415885Sjulian
14515885Sjulian    case PRU_ABORT:
14615885Sjulian	soisdisconnected( so );
14715885Sjulian	at_pcbdetach( so, ddp );
14815885Sjulian	break;
14915885Sjulian
15015885Sjulian    case PRU_LISTEN:
15115885Sjulian    case PRU_CONNECT2:
15215885Sjulian    case PRU_ACCEPT:
15315885Sjulian    case PRU_SENDOOB:
15415885Sjulian    case PRU_FASTTIMO:
15515885Sjulian    case PRU_SLOWTIMO:
15615885Sjulian    case PRU_PROTORCV:
15715885Sjulian    case PRU_PROTOSEND:
15815885Sjulian	error = EOPNOTSUPP;
15915885Sjulian	break;
16015885Sjulian
16115885Sjulian    case PRU_RCVD:
16215885Sjulian    case PRU_RCVOOB:
16315885Sjulian	/*
16415885Sjulian	 * Don't mfree. Good architecture...
16515885Sjulian	 */
16615885Sjulian	return( EOPNOTSUPP );
16715885Sjulian
16815885Sjulian    case PRU_SENSE:
16915885Sjulian	/*
17015885Sjulian	 * 1. Don't return block size.
17115885Sjulian	 * 2. Don't mfree.
17215885Sjulian	 */
17315885Sjulian	return( 0 );
17415885Sjulian
17515885Sjulian    default:
17615885Sjulian	error = EOPNOTSUPP;
17715885Sjulian    }
17815885Sjulian
17915885Sjulianrelease:
18015885Sjulian    if ( m != NULL ) {
18115885Sjulian	m_freem( m );
18215885Sjulian    }
18315885Sjulian    return( error );
18415885Sjulian}
18515885Sjulian
18615885Sjulianstatic void
18715885Sjulianat_sockaddr( struct ddpcb *ddp, struct mbuf *addr)
18815885Sjulian{
18915885Sjulian    struct sockaddr_at	*sat;
19015885Sjulian
19115885Sjulian    addr->m_len = sizeof( struct sockaddr_at );
19215885Sjulian    sat = mtod( addr, struct sockaddr_at *);
19315885Sjulian    *sat = ddp->ddp_lsat;
19415885Sjulian}
19515885Sjulian
19615885Sjulianstatic int
19715885Sjulianat_pcbsetaddr( struct ddpcb *ddp, struct mbuf *addr, struct proc *p )
19815885Sjulian{
19915885Sjulian    struct sockaddr_at	lsat, *sat;
20015885Sjulian    struct at_ifaddr	*aa;
20115885Sjulian    struct ddpcb	*ddpp;
20215885Sjulian
20315885Sjulian    if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT ) { /* shouldn't be bound */
20415885Sjulian	return( EINVAL );
20515885Sjulian    }
20615885Sjulian
20715885Sjulian    if ( addr != 0 ) {			/* validate passed address */
20815885Sjulian	sat = mtod( addr, struct sockaddr_at *);
20915885Sjulian	if ( addr->m_len != sizeof( *sat )) {
21015885Sjulian	    return( EINVAL );
21115885Sjulian	}
21215885Sjulian	if ( sat->sat_family != AF_APPLETALK ) {
21315885Sjulian	    return( EAFNOSUPPORT );
21415885Sjulian	}
21515885Sjulian
21615885Sjulian	if ( sat->sat_addr.s_node != ATADDR_ANYNODE ||
21715885Sjulian		sat->sat_addr.s_net != ATADDR_ANYNET ) {
21815885Sjulian	    for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
21915885Sjulian		if (( sat->sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) &&
22015885Sjulian		 ( sat->sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node )) {
22115885Sjulian		    break;
22215885Sjulian		}
22315885Sjulian	    }
22415885Sjulian	    if ( !aa ) {
22515885Sjulian		return( EADDRNOTAVAIL );
22615885Sjulian	    }
22715885Sjulian	}
22815885Sjulian
22915885Sjulian	if ( sat->sat_port != ATADDR_ANYPORT ) {
23015885Sjulian	    if ( sat->sat_port < ATPORT_FIRST ||
23115885Sjulian		    sat->sat_port >= ATPORT_LAST ) {
23215885Sjulian		return( EINVAL );
23315885Sjulian	    }
23415885Sjulian	    if ( sat->sat_port < ATPORT_RESERVED &&
23517254Sjulian		 suser( p->p_ucred, &p->p_acflag ) ) {
23615885Sjulian		return( EACCES );
23715885Sjulian	    }
23815885Sjulian	}
23915885Sjulian    } else {
24015885Sjulian	bzero( (caddr_t)&lsat, sizeof( struct sockaddr_at ));
24115885Sjulian	lsat.sat_len = sizeof(struct sockaddr_at);
24215885Sjulian	lsat.sat_addr.s_node = ATADDR_ANYNODE;
24315885Sjulian	lsat.sat_addr.s_net = ATADDR_ANYNET;
24415885Sjulian	lsat.sat_family = AF_APPLETALK;
24515885Sjulian	sat = &lsat;
24615885Sjulian    }
24715885Sjulian
24815885Sjulian    if ( sat->sat_addr.s_node == ATADDR_ANYNODE &&
24915885Sjulian	    sat->sat_addr.s_net == ATADDR_ANYNET ) {
25015885Sjulian	if ( at_ifaddr == NULL ) {
25115885Sjulian	    return( EADDRNOTAVAIL );
25215885Sjulian	}
25315885Sjulian	sat->sat_addr = AA_SAT( at_ifaddr )->sat_addr;
25415885Sjulian    }
25515885Sjulian    ddp->ddp_lsat = *sat;
25615885Sjulian
25715885Sjulian    /*
25815885Sjulian     * Choose port.
25915885Sjulian     */
26015885Sjulian    if ( sat->sat_port == ATADDR_ANYPORT ) {
26115885Sjulian	for ( sat->sat_port = ATPORT_RESERVED;
26215885Sjulian		sat->sat_port < ATPORT_LAST; sat->sat_port++ ) {
26315885Sjulian	    if ( ddp_ports[ sat->sat_port - 1 ] == 0 ) {
26415885Sjulian		break;
26515885Sjulian	    }
26615885Sjulian	}
26715885Sjulian	if ( sat->sat_port == ATPORT_LAST ) {
26815885Sjulian	    return( EADDRNOTAVAIL );
26915885Sjulian	}
27015885Sjulian	ddp->ddp_lsat.sat_port = sat->sat_port;
27115885Sjulian	ddp_ports[ sat->sat_port - 1 ] = ddp;
27215885Sjulian    } else {
27315885Sjulian	for ( ddpp = ddp_ports[ sat->sat_port - 1 ]; ddpp;
27415885Sjulian		ddpp = ddpp->ddp_pnext ) {
27515885Sjulian	    if ( ddpp->ddp_lsat.sat_addr.s_net == sat->sat_addr.s_net &&
27615885Sjulian		    ddpp->ddp_lsat.sat_addr.s_node == sat->sat_addr.s_node ) {
27715885Sjulian		break;
27815885Sjulian	    }
27915885Sjulian	}
28015885Sjulian	if ( ddpp != NULL ) {
28115885Sjulian	    return( EADDRINUSE );
28215885Sjulian	}
28315885Sjulian	ddp->ddp_pnext = ddp_ports[ sat->sat_port - 1 ];
28415885Sjulian	ddp_ports[ sat->sat_port - 1 ] = ddp;
28515885Sjulian	if ( ddp->ddp_pnext ) {
28615885Sjulian	    ddp->ddp_pnext->ddp_pprev = ddp;
28715885Sjulian	}
28815885Sjulian    }
28915885Sjulian
29015885Sjulian    return( 0 );
29115885Sjulian}
29215885Sjulian
29315885Sjulianstatic int
29415885Sjulianat_pcbconnect( struct ddpcb *ddp, struct mbuf *addr, struct proc *p)
29515885Sjulian{
29615885Sjulian    struct sockaddr_at	*sat = mtod( addr, struct sockaddr_at *);
29715885Sjulian    struct route	*ro;
29815885Sjulian    struct at_ifaddr	*aa = 0;
29915885Sjulian    struct ifnet	*ifp;
30015885Sjulian    u_short		hintnet = 0, net;
30115885Sjulian
30215885Sjulian    if ( addr->m_len != sizeof( *sat ))
30315885Sjulian	return( EINVAL );
30415885Sjulian    if ( sat->sat_family != AF_APPLETALK ) {
30515885Sjulian	return( EAFNOSUPPORT );
30615885Sjulian    }
30715885Sjulian
30815885Sjulian    /*
30915885Sjulian     * Under phase 2, network 0 means "the network".  We take "the
31015885Sjulian     * network" to mean the network the control block is bound to.
31115885Sjulian     * If the control block is not bound, there is an error.
31215885Sjulian     */
31315885Sjulian    if ( sat->sat_addr.s_net == ATADDR_ANYNET
31415885Sjulian		&& sat->sat_addr.s_node != ATADDR_ANYNODE ) {
31515885Sjulian	if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
31615885Sjulian	    return( EADDRNOTAVAIL );
31715885Sjulian	}
31815885Sjulian	hintnet = ddp->ddp_lsat.sat_addr.s_net;
31915885Sjulian    }
32015885Sjulian
32115885Sjulian    ro = &ddp->ddp_route;
32215885Sjulian    /*
32315885Sjulian     * If we've got an old route for this pcb, check that it is valid.
32415885Sjulian     * If we've changed our address, we may have an old "good looking"
32515885Sjulian     * route here.  Attempt to detect it.
32615885Sjulian     */
32715885Sjulian    if ( ro->ro_rt ) {
32815885Sjulian	if ( hintnet ) {
32915885Sjulian	    net = hintnet;
33015885Sjulian	} else {
33115885Sjulian	    net = sat->sat_addr.s_net;
33215885Sjulian	}
33315885Sjulian	aa = 0;
33415885Sjulian	if ( ifp = ro->ro_rt->rt_ifp ) {
33515885Sjulian	    for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
33615885Sjulian		if ( aa->aa_ifp == ifp &&
33715885Sjulian			ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
33815885Sjulian			ntohs( net ) <= ntohs( aa->aa_lastnet )) {
33915885Sjulian		    break;
34015885Sjulian		}
34115885Sjulian	    }
34215885Sjulian	}
34315885Sjulian	if ( aa == NULL || ( satosat( &ro->ro_dst )->sat_addr.s_net !=
34415885Sjulian		( hintnet ? hintnet : sat->sat_addr.s_net ) ||
34515885Sjulian		satosat( &ro->ro_dst )->sat_addr.s_node !=
34615885Sjulian		sat->sat_addr.s_node )) {
34715885Sjulian	    RTFREE( ro->ro_rt );
34815885Sjulian	    ro->ro_rt = (struct rtentry *)0;
34915885Sjulian	}
35015885Sjulian    }
35115885Sjulian
35215885Sjulian    /*
35315885Sjulian     * If we've got no route for this interface, try to find one.
35415885Sjulian     */
35515885Sjulian    if ( ro->ro_rt == (struct rtentry *)0 ||
35615885Sjulian	 ro->ro_rt->rt_ifp == (struct ifnet *)0 ) {
35715885Sjulian	ro->ro_dst.sa_len = sizeof( struct sockaddr_at );
35815885Sjulian	ro->ro_dst.sa_family = AF_APPLETALK;
35915885Sjulian	if ( hintnet ) {
36015885Sjulian	    satosat( &ro->ro_dst )->sat_addr.s_net = hintnet;
36115885Sjulian	} else {
36215885Sjulian	    satosat( &ro->ro_dst )->sat_addr.s_net = sat->sat_addr.s_net;
36315885Sjulian	}
36415885Sjulian	satosat( &ro->ro_dst )->sat_addr.s_node = sat->sat_addr.s_node;
36515885Sjulian	rtalloc( ro );
36615885Sjulian    }
36715885Sjulian
36815885Sjulian    /*
36915885Sjulian     * Make sure any route that we have has a valid interface.
37015885Sjulian     */
37115885Sjulian    aa = 0;
37215885Sjulian    if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
37315885Sjulian	for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
37415885Sjulian	    if ( aa->aa_ifp == ifp ) {
37515885Sjulian		break;
37615885Sjulian	    }
37715885Sjulian	}
37815885Sjulian    }
37915885Sjulian    if ( aa == 0 ) {
38015885Sjulian	return( ENETUNREACH );
38115885Sjulian    }
38215885Sjulian
38315885Sjulian    ddp->ddp_fsat = *sat;
38415885Sjulian    if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
38517254Sjulian	return( at_pcbsetaddr( ddp, (struct mbuf *)0, p ));
38615885Sjulian    }
38715885Sjulian    return( 0 );
38815885Sjulian}
38915885Sjulian
39015885Sjulianstatic void
39115885Sjulianat_pcbdisconnect( struct ddpcb	*ddp )
39215885Sjulian{
39315885Sjulian    ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
39415885Sjulian    ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
39515885Sjulian    ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
39615885Sjulian}
39715885Sjulian
39815885Sjulianstatic int
39915885Sjulianat_pcballoc( struct socket *so )
40015885Sjulian{
40115885Sjulian    struct ddpcb	*ddp;
40215885Sjulian    struct mbuf		*m;
40315885Sjulian
40415885Sjulian    m = m_getclr( M_WAIT, MT_PCB );
40515885Sjulian    ddp = mtod( m, struct ddpcb * );
40615885Sjulian    ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
40715885Sjulian
40815885Sjulian    ddp->ddp_next = ddpcb;
40915885Sjulian    ddp->ddp_prev = NULL;
41015885Sjulian    ddp->ddp_pprev = NULL;
41115885Sjulian    ddp->ddp_pnext = NULL;
41215885Sjulian    if ( ddpcb ) {
41315885Sjulian	ddpcb->ddp_prev = ddp;
41415885Sjulian    }
41515885Sjulian    ddpcb = ddp;
41615885Sjulian
41715885Sjulian    ddp->ddp_socket = so;
41815885Sjulian    so->so_pcb = (caddr_t)ddp;
41915885Sjulian    return( 0 );
42015885Sjulian}
42115885Sjulian
42215885Sjulianstatic void
42315885Sjulianat_pcbdetach( struct socket *so, struct ddpcb *ddp)
42415885Sjulian{
42515885Sjulian    soisdisconnected( so );
42615885Sjulian    so->so_pcb = 0;
42715885Sjulian    sofree( so );
42815885Sjulian
42915885Sjulian    /* remove ddp from ddp_ports list */
43015885Sjulian    if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
43115885Sjulian	    ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] != NULL ) {
43215885Sjulian	if ( ddp->ddp_pprev != NULL ) {
43315885Sjulian	    ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext;
43415885Sjulian	} else {
43515885Sjulian	    ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] = ddp->ddp_pnext;
43615885Sjulian	}
43715885Sjulian	if ( ddp->ddp_pnext != NULL ) {
43815885Sjulian	    ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev;
43915885Sjulian	}
44015885Sjulian    }
44115885Sjulian
44215885Sjulian    if ( ddp->ddp_route.ro_rt ) {
44315885Sjulian	rtfree( ddp->ddp_route.ro_rt );
44415885Sjulian    }
44515885Sjulian
44615885Sjulian    if ( ddp->ddp_prev ) {
44715885Sjulian	ddp->ddp_prev->ddp_next = ddp->ddp_next;
44815885Sjulian    } else {
44915885Sjulian	ddpcb = ddp->ddp_next;
45015885Sjulian    }
45115885Sjulian    if ( ddp->ddp_next ) {
45215885Sjulian	ddp->ddp_next->ddp_prev = ddp->ddp_prev;
45315885Sjulian    }
45415885Sjulian
45515885Sjulian    (void) m_free( dtom( ddp ));
45615885Sjulian}
45715885Sjulian
45815885Sjulian/*
45915885Sjulian * For the moment, this just find the pcb with the correct local address.
46015885Sjulian * In the future, this will actually do some real searching, so we can use
46115885Sjulian * the sender's address to do de-multiplexing on a single port to many
46215885Sjulian * sockets (pcbs).
46315885Sjulian */
46415885Sjulianstruct ddpcb *
46515885Sjulianddp_search( struct sockaddr_at *from, struct sockaddr_at *to,
46615885Sjulian			struct at_ifaddr *aa)
46715885Sjulian{
46815885Sjulian    struct ddpcb	*ddp;
46915885Sjulian
47015885Sjulian    /*
47115885Sjulian     * Check for bad ports.
47215885Sjulian     */
47315885Sjulian    if ( to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST ) {
47415885Sjulian	return( NULL );
47515885Sjulian    }
47615885Sjulian
47715885Sjulian    /*
47815885Sjulian     * Make sure the local address matches the sent address.  What about
47915885Sjulian     * the interface?
48015885Sjulian     */
48115885Sjulian    for ( ddp = ddp_ports[ to->sat_port - 1 ]; ddp; ddp = ddp->ddp_pnext ) {
48215885Sjulian	/* XXX should we handle 0.YY? */
48315885Sjulian
48415885Sjulian	/* XXXX.YY to socket on destination interface */
48515885Sjulian	if ( to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
48615885Sjulian		to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node ) {
48715885Sjulian	    break;
48815885Sjulian	}
48915885Sjulian
49015885Sjulian	/* 0.255 to socket on receiving interface */
49115885Sjulian	if ( to->sat_addr.s_node == ATADDR_BCAST && ( to->sat_addr.s_net == 0 ||
49215885Sjulian		to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net ) &&
49315885Sjulian		ddp->ddp_lsat.sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) {
49415885Sjulian	    break;
49515885Sjulian	}
49615885Sjulian
49715885Sjulian	/* XXXX.0 to socket on destination interface */
49815885Sjulian	if ( to->sat_addr.s_net == aa->aa_firstnet &&
49915885Sjulian		to->sat_addr.s_node == 0 &&
50015885Sjulian		ntohs( ddp->ddp_lsat.sat_addr.s_net ) >=
50115885Sjulian		ntohs( aa->aa_firstnet ) &&
50215885Sjulian		ntohs( ddp->ddp_lsat.sat_addr.s_net ) <=
50315885Sjulian		ntohs( aa->aa_lastnet )) {
50415885Sjulian	    break;
50515885Sjulian	}
50615885Sjulian    }
50715885Sjulian    return( ddp );
50815885Sjulian}
50915885Sjulian
51015885Sjulianvoid
51115885Sjulianddp_init(void )
51215885Sjulian{
51315885Sjulian    atintrq1.ifq_maxlen = IFQ_MAXLEN;
51415885Sjulian    atintrq2.ifq_maxlen = IFQ_MAXLEN;
51515885Sjulian}
51615885Sjulian
51717254Sjulian#if 0
51815885Sjulianstatic void
51915885Sjulianddp_clean(void )
52015885Sjulian{
52115885Sjulian    struct ddpcb	*ddp;
52215885Sjulian
52315885Sjulian    for ( ddp = ddpcb; ddp; ddp = ddp->ddp_next ) {
52415885Sjulian	at_pcbdetach( ddp->ddp_socket, ddp );
52515885Sjulian    }
52615885Sjulian}
52717254Sjulian#endif
528