ddp_pcb.c revision 111888
115885Sjulian/*
215885Sjulian * Copyright (c) 1990,1994 Regents of The University of Michigan.
315885Sjulian * All Rights Reserved.  See COPYRIGHT.
467893Sphk *
567893Sphk * $FreeBSD: head/sys/netatalk/ddp_pcb.c 111888 2003-03-04 23:19:55Z jlemon $
615885Sjulian */
715885Sjulian
815885Sjulian#include <sys/param.h>
915885Sjulian#include <sys/systm.h>
1029024Sbde#include <sys/malloc.h>
1115885Sjulian#include <sys/mbuf.h>
1215885Sjulian#include <sys/socket.h>
1315885Sjulian#include <sys/socketvar.h>
1415885Sjulian#include <sys/protosw.h>
1515885Sjulian#include <net/if.h>
1615885Sjulian#include <net/route.h>
17111888Sjlemon#include <net/netisr.h>
1815885Sjulian
1918207Sbde#include <netatalk/at.h>
2018207Sbde#include <netatalk/at_var.h>
2118207Sbde#include <netatalk/ddp_var.h>
2215885Sjulian#include <netatalk/at_extern.h>
2315885Sjulian
2415885Sjulianstatic void at_pcbdisconnect( struct ddpcb *ddp );
2528270Swollmanstatic void at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr);
2628270Swollmanstatic int at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr,
2783366Sjulian			  struct thread *td);
2828270Swollmanstatic int at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr,
2983366Sjulian			 struct thread *td);
3028270Swollmanstatic void at_pcbdetach(struct socket *so, struct ddpcb *ddp);
3128270Swollmanstatic int at_pcballoc(struct socket *so);
3215885Sjulian
3315885Sjulianstruct ddpcb	*ddp_ports[ ATPORT_LAST ];
3415885Sjulianstruct ddpcb	*ddpcb = NULL;
3533181Seivindstatic u_long	ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
3633181Seivindstatic u_long	ddp_recvspace = 10 * ( 587 + sizeof( struct sockaddr_at ));
3715885Sjulian
38111888Sjlemonstatic struct ifqueue atintrq1, atintrq2, aarpintrq;
3925791Sjulian
4025791Sjulianstatic int
4183366Sjulianddp_attach(struct socket *so, int proto, struct thread *td)
4215885Sjulian{
4325791Sjulian	struct ddpcb	*ddp;
4425791Sjulian	int		error = 0;
4525791Sjulian	int		s;
4625791Sjulian
4715885Sjulian
4825791Sjulian	ddp = sotoddpcb( so );
4915885Sjulian	if ( ddp != NULL ) {
5025791Sjulian	    return( EINVAL);
5115885Sjulian	}
5225791Sjulian
5325791Sjulian	s = splnet();
5425791Sjulian	error = at_pcballoc( so );
5525791Sjulian	splx(s);
5625791Sjulian	if (error) {
5725791Sjulian	    return (error);
5815885Sjulian	}
5925791Sjulian	return (soreserve( so, ddp_sendspace, ddp_recvspace ));
6025791Sjulian}
6115885Sjulian
6225791Sjulianstatic int
6325791Sjulianddp_detach(struct socket *so)
6425791Sjulian{
6525791Sjulian	struct ddpcb	*ddp;
6625791Sjulian	int		s;
6725791Sjulian
6825791Sjulian	ddp = sotoddpcb( so );
6925791Sjulian	if ( ddp == NULL ) {
7025791Sjulian	    return( EINVAL);
7125791Sjulian	}
7225791Sjulian	s = splnet();
7315885Sjulian	at_pcbdetach( so, ddp );
7425791Sjulian	splx(s);
7525791Sjulian	return(0);
7625791Sjulian}
7715885Sjulian
7825791Sjulianstatic int
7983366Sjulianddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
8025791Sjulian{
8125791Sjulian	struct ddpcb	*ddp;
8225791Sjulian	int		error = 0;
8325791Sjulian	int		s;
8425791Sjulian
8525791Sjulian	ddp = sotoddpcb( so );
8625791Sjulian	if ( ddp == NULL ) {
8725791Sjulian	    return( EINVAL);
8825791Sjulian	}
8925791Sjulian	s = splnet();
9083366Sjulian	error = at_pcbsetaddr(ddp, nam, td);
9125791Sjulian	splx(s);
9225791Sjulian	return (error);
9325791Sjulian}
9415885Sjulian
9525791Sjulianstatic int
9683366Sjulianddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
9725791Sjulian{
9825791Sjulian	struct ddpcb	*ddp;
9925791Sjulian	int		error = 0;
10025791Sjulian	int		s;
10125791Sjulian
10225791Sjulian	ddp = sotoddpcb( so );
10325791Sjulian	if ( ddp == NULL ) {
10425791Sjulian	    return( EINVAL);
10525791Sjulian	}
10615885Sjulian
10715885Sjulian	if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
10825791Sjulian	    return(EISCONN);
10915885Sjulian	}
11015885Sjulian
11125791Sjulian	s = splnet();
11283366Sjulian	error = at_pcbconnect( ddp, nam, td );
11325791Sjulian	splx(s);
11497658Stanimura	if ( error == 0 )
11515885Sjulian	    soisconnected( so );
11625791Sjulian	return(error);
11725791Sjulian}
11815885Sjulian
11925791Sjulianstatic int
12025791Sjulianddp_disconnect(struct socket *so)
12125791Sjulian{
12225791Sjulian
12325791Sjulian	struct ddpcb	*ddp;
12425791Sjulian	int		s;
12525791Sjulian
12625791Sjulian	ddp = sotoddpcb( so );
12725791Sjulian	if ( ddp == NULL ) {
12825791Sjulian	    return( EINVAL);
12925791Sjulian	}
13015885Sjulian	if ( ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE ) {
13125791Sjulian	    return(ENOTCONN);
13215885Sjulian	}
13325791Sjulian
13425791Sjulian	s = splnet();
13515885Sjulian	at_pcbdisconnect( ddp );
13625791Sjulian	ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
13725791Sjulian	splx(s);
13815885Sjulian	soisdisconnected( so );
13925791Sjulian	return(0);
14025791Sjulian}
14115885Sjulian
14225791Sjulianstatic int
14325791Sjulianddp_shutdown(struct socket *so)
14425791Sjulian{
14525791Sjulian	struct ddpcb	*ddp;
14641591Sarchie
14725791Sjulian	ddp = sotoddpcb( so );
14825791Sjulian	if ( ddp == NULL ) {
14925791Sjulian		return( EINVAL);
15025791Sjulian	}
15115885Sjulian	socantsendmore( so );
15225791Sjulian	return(0);
15325791Sjulian}
15415885Sjulian
15525791Sjulianstatic int
15628270Swollmanddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
15783366Sjulian            struct mbuf *control, struct thread *td)
15825791Sjulian{
15925791Sjulian	struct ddpcb	*ddp;
16025791Sjulian	int		error = 0;
16125791Sjulian	int		s;
16225791Sjulian
16325791Sjulian	ddp = sotoddpcb( so );
16425791Sjulian	if ( ddp == NULL ) {
16525791Sjulian		return(EINVAL);
16625791Sjulian	}
16715885Sjulian
16825791Sjulian    	if ( control && control->m_len ) {
16925791Sjulian		return(EINVAL);
17025791Sjulian    	}
17125791Sjulian
17215885Sjulian	if ( addr ) {
17325791Sjulian		if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
17425791Sjulian			return(EISCONN);
17525791Sjulian		}
17615885Sjulian
17725791Sjulian		s = splnet();
17883366Sjulian		error = at_pcbconnect(ddp, addr, td);
17915885Sjulian		splx( s );
18025791Sjulian		if ( error ) {
18125791Sjulian			return(error);
18225791Sjulian		}
18315885Sjulian	} else {
18425791Sjulian		if ( ddp->ddp_fsat.sat_port == ATADDR_ANYPORT ) {
18525791Sjulian			return(ENOTCONN);
18625791Sjulian		}
18715885Sjulian	}
18815885Sjulian
18925791Sjulian	s = splnet();
19023396Sjulian	error = ddp_output( m, so );
19115885Sjulian	if ( addr ) {
19215885Sjulian	    at_pcbdisconnect( ddp );
19315885Sjulian	}
19425791Sjulian	splx(s);
19525791Sjulian	return(error);
19625791Sjulian}
19725791Sjulian
19825791Sjulianstatic int
19925791Sjulianddp_abort(struct socket *so)
20025791Sjulian{
20125791Sjulian	struct ddpcb	*ddp;
20225791Sjulian	int		s;
20325791Sjulian
20425791Sjulian	ddp = sotoddpcb( so );
20525791Sjulian	if ( ddp == NULL ) {
20625791Sjulian		return(EINVAL);
20715885Sjulian	}
20815885Sjulian	soisdisconnected( so );
20925791Sjulian	s = splnet();
21015885Sjulian	at_pcbdetach( so, ddp );
21125791Sjulian	splx(s);
21225791Sjulian	return(0);
21325791Sjulian}
21415885Sjulian
21515885Sjulian
21615885Sjulianstatic void
21728270Swollmanat_sockaddr(struct ddpcb *ddp, struct sockaddr **addr)
21815885Sjulian{
21928270Swollman    *addr = dup_sockaddr((struct sockaddr *)&ddp->ddp_lsat, 0);
22015885Sjulian}
22115885Sjulian
22215885Sjulianstatic int
22383366Sjulianat_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
22415885Sjulian{
22515885Sjulian    struct sockaddr_at	lsat, *sat;
22615885Sjulian    struct at_ifaddr	*aa;
22715885Sjulian    struct ddpcb	*ddpp;
22815885Sjulian
22915885Sjulian    if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT ) { /* shouldn't be bound */
23015885Sjulian	return( EINVAL );
23115885Sjulian    }
23215885Sjulian
23328270Swollman    if (addr != 0) {			/* validate passed address */
23428270Swollman	sat = (struct sockaddr_at *)addr;
23528270Swollman	if (sat->sat_family != AF_APPLETALK) {
23628270Swollman	    return(EAFNOSUPPORT);
23715885Sjulian	}
23815885Sjulian
23915885Sjulian	if ( sat->sat_addr.s_node != ATADDR_ANYNODE ||
24015885Sjulian		sat->sat_addr.s_net != ATADDR_ANYNET ) {
24115885Sjulian	    for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
24215885Sjulian		if (( sat->sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) &&
24315885Sjulian		 ( sat->sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node )) {
24415885Sjulian		    break;
24515885Sjulian		}
24615885Sjulian	    }
24715885Sjulian	    if ( !aa ) {
24815885Sjulian		return( EADDRNOTAVAIL );
24915885Sjulian	    }
25015885Sjulian	}
25115885Sjulian
25215885Sjulian	if ( sat->sat_port != ATADDR_ANYPORT ) {
25315885Sjulian	    if ( sat->sat_port < ATPORT_FIRST ||
25415885Sjulian		    sat->sat_port >= ATPORT_LAST ) {
25515885Sjulian		return( EINVAL );
25615885Sjulian	    }
25715885Sjulian	    if ( sat->sat_port < ATPORT_RESERVED &&
25893593Sjhb		 suser(td) ) {
25915885Sjulian		return( EACCES );
26015885Sjulian	    }
26115885Sjulian	}
26215885Sjulian    } else {
26315885Sjulian	bzero( (caddr_t)&lsat, sizeof( struct sockaddr_at ));
26415885Sjulian	lsat.sat_len = sizeof(struct sockaddr_at);
26515885Sjulian	lsat.sat_addr.s_node = ATADDR_ANYNODE;
26615885Sjulian	lsat.sat_addr.s_net = ATADDR_ANYNET;
26715885Sjulian	lsat.sat_family = AF_APPLETALK;
26815885Sjulian	sat = &lsat;
26915885Sjulian    }
27015885Sjulian
27115885Sjulian    if ( sat->sat_addr.s_node == ATADDR_ANYNODE &&
27215885Sjulian	    sat->sat_addr.s_net == ATADDR_ANYNET ) {
27315885Sjulian	if ( at_ifaddr == NULL ) {
27415885Sjulian	    return( EADDRNOTAVAIL );
27515885Sjulian	}
27615885Sjulian	sat->sat_addr = AA_SAT( at_ifaddr )->sat_addr;
27715885Sjulian    }
27815885Sjulian    ddp->ddp_lsat = *sat;
27915885Sjulian
28015885Sjulian    /*
28115885Sjulian     * Choose port.
28215885Sjulian     */
28315885Sjulian    if ( sat->sat_port == ATADDR_ANYPORT ) {
28415885Sjulian	for ( sat->sat_port = ATPORT_RESERVED;
28515885Sjulian		sat->sat_port < ATPORT_LAST; sat->sat_port++ ) {
28615885Sjulian	    if ( ddp_ports[ sat->sat_port - 1 ] == 0 ) {
28715885Sjulian		break;
28815885Sjulian	    }
28915885Sjulian	}
29015885Sjulian	if ( sat->sat_port == ATPORT_LAST ) {
29115885Sjulian	    return( EADDRNOTAVAIL );
29215885Sjulian	}
29315885Sjulian	ddp->ddp_lsat.sat_port = sat->sat_port;
29415885Sjulian	ddp_ports[ sat->sat_port - 1 ] = ddp;
29515885Sjulian    } else {
29615885Sjulian	for ( ddpp = ddp_ports[ sat->sat_port - 1 ]; ddpp;
29715885Sjulian		ddpp = ddpp->ddp_pnext ) {
29815885Sjulian	    if ( ddpp->ddp_lsat.sat_addr.s_net == sat->sat_addr.s_net &&
29915885Sjulian		    ddpp->ddp_lsat.sat_addr.s_node == sat->sat_addr.s_node ) {
30015885Sjulian		break;
30115885Sjulian	    }
30215885Sjulian	}
30315885Sjulian	if ( ddpp != NULL ) {
30415885Sjulian	    return( EADDRINUSE );
30515885Sjulian	}
30615885Sjulian	ddp->ddp_pnext = ddp_ports[ sat->sat_port - 1 ];
30715885Sjulian	ddp_ports[ sat->sat_port - 1 ] = ddp;
30815885Sjulian	if ( ddp->ddp_pnext ) {
30915885Sjulian	    ddp->ddp_pnext->ddp_pprev = ddp;
31015885Sjulian	}
31115885Sjulian    }
31215885Sjulian
31315885Sjulian    return( 0 );
31415885Sjulian}
31515885Sjulian
31615885Sjulianstatic int
31783366Sjulianat_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
31815885Sjulian{
31928270Swollman    struct sockaddr_at	*sat = (struct sockaddr_at *)addr;
32015885Sjulian    struct route	*ro;
32115885Sjulian    struct at_ifaddr	*aa = 0;
32215885Sjulian    struct ifnet	*ifp;
32315885Sjulian    u_short		hintnet = 0, net;
32415885Sjulian
32528270Swollman    if (sat->sat_family != AF_APPLETALK) {
32628270Swollman	return(EAFNOSUPPORT);
32715885Sjulian    }
32815885Sjulian
32915885Sjulian    /*
33015885Sjulian     * Under phase 2, network 0 means "the network".  We take "the
33115885Sjulian     * network" to mean the network the control block is bound to.
33215885Sjulian     * If the control block is not bound, there is an error.
33315885Sjulian     */
33415885Sjulian    if ( sat->sat_addr.s_net == ATADDR_ANYNET
33515885Sjulian		&& sat->sat_addr.s_node != ATADDR_ANYNODE ) {
33615885Sjulian	if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
33715885Sjulian	    return( EADDRNOTAVAIL );
33815885Sjulian	}
33915885Sjulian	hintnet = ddp->ddp_lsat.sat_addr.s_net;
34015885Sjulian    }
34115885Sjulian
34215885Sjulian    ro = &ddp->ddp_route;
34315885Sjulian    /*
34415885Sjulian     * If we've got an old route for this pcb, check that it is valid.
34515885Sjulian     * If we've changed our address, we may have an old "good looking"
34615885Sjulian     * route here.  Attempt to detect it.
34715885Sjulian     */
34815885Sjulian    if ( ro->ro_rt ) {
34915885Sjulian	if ( hintnet ) {
35015885Sjulian	    net = hintnet;
35115885Sjulian	} else {
35215885Sjulian	    net = sat->sat_addr.s_net;
35315885Sjulian	}
35415885Sjulian	aa = 0;
35543305Sdillon	if ((ifp = ro->ro_rt->rt_ifp) != NULL) {
35615885Sjulian	    for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
35715885Sjulian		if ( aa->aa_ifp == ifp &&
35815885Sjulian			ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
35915885Sjulian			ntohs( net ) <= ntohs( aa->aa_lastnet )) {
36015885Sjulian		    break;
36115885Sjulian		}
36215885Sjulian	    }
36315885Sjulian	}
36415885Sjulian	if ( aa == NULL || ( satosat( &ro->ro_dst )->sat_addr.s_net !=
36515885Sjulian		( hintnet ? hintnet : sat->sat_addr.s_net ) ||
36615885Sjulian		satosat( &ro->ro_dst )->sat_addr.s_node !=
36715885Sjulian		sat->sat_addr.s_node )) {
36815885Sjulian	    RTFREE( ro->ro_rt );
36915885Sjulian	    ro->ro_rt = (struct rtentry *)0;
37015885Sjulian	}
37115885Sjulian    }
37215885Sjulian
37315885Sjulian    /*
37415885Sjulian     * If we've got no route for this interface, try to find one.
37515885Sjulian     */
37615885Sjulian    if ( ro->ro_rt == (struct rtentry *)0 ||
37715885Sjulian	 ro->ro_rt->rt_ifp == (struct ifnet *)0 ) {
37815885Sjulian	ro->ro_dst.sa_len = sizeof( struct sockaddr_at );
37915885Sjulian	ro->ro_dst.sa_family = AF_APPLETALK;
38015885Sjulian	if ( hintnet ) {
38115885Sjulian	    satosat( &ro->ro_dst )->sat_addr.s_net = hintnet;
38215885Sjulian	} else {
38315885Sjulian	    satosat( &ro->ro_dst )->sat_addr.s_net = sat->sat_addr.s_net;
38415885Sjulian	}
38515885Sjulian	satosat( &ro->ro_dst )->sat_addr.s_node = sat->sat_addr.s_node;
38615885Sjulian	rtalloc( ro );
38715885Sjulian    }
38815885Sjulian
38915885Sjulian    /*
39015885Sjulian     * Make sure any route that we have has a valid interface.
39115885Sjulian     */
39215885Sjulian    aa = 0;
39315885Sjulian    if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
39415885Sjulian	for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
39515885Sjulian	    if ( aa->aa_ifp == ifp ) {
39615885Sjulian		break;
39715885Sjulian	    }
39815885Sjulian	}
39915885Sjulian    }
40015885Sjulian    if ( aa == 0 ) {
40115885Sjulian	return( ENETUNREACH );
40215885Sjulian    }
40315885Sjulian
40415885Sjulian    ddp->ddp_fsat = *sat;
40515885Sjulian    if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
40683366Sjulian	return(at_pcbsetaddr(ddp, (struct sockaddr *)0, td));
40715885Sjulian    }
40815885Sjulian    return( 0 );
40915885Sjulian}
41015885Sjulian
41115885Sjulianstatic void
41215885Sjulianat_pcbdisconnect( struct ddpcb	*ddp )
41315885Sjulian{
41415885Sjulian    ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
41515885Sjulian    ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
41615885Sjulian    ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
41715885Sjulian}
41815885Sjulian
41915885Sjulianstatic int
42015885Sjulianat_pcballoc( struct socket *so )
42115885Sjulian{
42228270Swollman	struct ddpcb	*ddp;
42315885Sjulian
424111119Simp	MALLOC(ddp, struct ddpcb *, sizeof *ddp, M_PCB, M_WAITOK | M_ZERO);
42528270Swollman	ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
42615885Sjulian
42728270Swollman	ddp->ddp_next = ddpcb;
42828270Swollman	ddp->ddp_prev = NULL;
42928270Swollman	ddp->ddp_pprev = NULL;
43028270Swollman	ddp->ddp_pnext = NULL;
43128270Swollman	if (ddpcb) {
43228270Swollman		ddpcb->ddp_prev = ddp;
43328270Swollman	}
43428270Swollman	ddpcb = ddp;
43515885Sjulian
43628270Swollman	ddp->ddp_socket = so;
43728270Swollman	so->so_pcb = (caddr_t)ddp;
43828270Swollman	return(0);
43915885Sjulian}
44015885Sjulian
44115885Sjulianstatic void
44215885Sjulianat_pcbdetach( struct socket *so, struct ddpcb *ddp)
44315885Sjulian{
44415885Sjulian    soisdisconnected( so );
44515885Sjulian    so->so_pcb = 0;
44686487Sdillon    sotryfree(so);
44715885Sjulian
44815885Sjulian    /* remove ddp from ddp_ports list */
44915885Sjulian    if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
45015885Sjulian	    ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] != NULL ) {
45115885Sjulian	if ( ddp->ddp_pprev != NULL ) {
45215885Sjulian	    ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext;
45315885Sjulian	} else {
45415885Sjulian	    ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] = ddp->ddp_pnext;
45515885Sjulian	}
45615885Sjulian	if ( ddp->ddp_pnext != NULL ) {
45715885Sjulian	    ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev;
45815885Sjulian	}
45915885Sjulian    }
46015885Sjulian
46115885Sjulian    if ( ddp->ddp_route.ro_rt ) {
46215885Sjulian	rtfree( ddp->ddp_route.ro_rt );
46315885Sjulian    }
46415885Sjulian
46515885Sjulian    if ( ddp->ddp_prev ) {
46615885Sjulian	ddp->ddp_prev->ddp_next = ddp->ddp_next;
46715885Sjulian    } else {
46815885Sjulian	ddpcb = ddp->ddp_next;
46915885Sjulian    }
47015885Sjulian    if ( ddp->ddp_next ) {
47115885Sjulian	ddp->ddp_next->ddp_prev = ddp->ddp_prev;
47215885Sjulian    }
47328270Swollman    FREE(ddp, M_PCB);
47415885Sjulian}
47515885Sjulian
47615885Sjulian/*
47715885Sjulian * For the moment, this just find the pcb with the correct local address.
47815885Sjulian * In the future, this will actually do some real searching, so we can use
47915885Sjulian * the sender's address to do de-multiplexing on a single port to many
48015885Sjulian * sockets (pcbs).
48115885Sjulian */
48215885Sjulianstruct ddpcb *
48315885Sjulianddp_search( struct sockaddr_at *from, struct sockaddr_at *to,
48415885Sjulian			struct at_ifaddr *aa)
48515885Sjulian{
48615885Sjulian    struct ddpcb	*ddp;
48715885Sjulian
48815885Sjulian    /*
48915885Sjulian     * Check for bad ports.
49015885Sjulian     */
49115885Sjulian    if ( to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST ) {
49215885Sjulian	return( NULL );
49315885Sjulian    }
49415885Sjulian
49515885Sjulian    /*
49615885Sjulian     * Make sure the local address matches the sent address.  What about
49715885Sjulian     * the interface?
49815885Sjulian     */
49915885Sjulian    for ( ddp = ddp_ports[ to->sat_port - 1 ]; ddp; ddp = ddp->ddp_pnext ) {
50015885Sjulian	/* XXX should we handle 0.YY? */
50115885Sjulian
50215885Sjulian	/* XXXX.YY to socket on destination interface */
50315885Sjulian	if ( to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
50415885Sjulian		to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node ) {
50515885Sjulian	    break;
50615885Sjulian	}
50715885Sjulian
50815885Sjulian	/* 0.255 to socket on receiving interface */
50915885Sjulian	if ( to->sat_addr.s_node == ATADDR_BCAST && ( to->sat_addr.s_net == 0 ||
51015885Sjulian		to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net ) &&
51115885Sjulian		ddp->ddp_lsat.sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) {
51215885Sjulian	    break;
51315885Sjulian	}
51415885Sjulian
51515885Sjulian	/* XXXX.0 to socket on destination interface */
51615885Sjulian	if ( to->sat_addr.s_net == aa->aa_firstnet &&
51715885Sjulian		to->sat_addr.s_node == 0 &&
51815885Sjulian		ntohs( ddp->ddp_lsat.sat_addr.s_net ) >=
51915885Sjulian		ntohs( aa->aa_firstnet ) &&
52015885Sjulian		ntohs( ddp->ddp_lsat.sat_addr.s_net ) <=
52115885Sjulian		ntohs( aa->aa_lastnet )) {
52215885Sjulian	    break;
52315885Sjulian	}
52415885Sjulian    }
52515885Sjulian    return( ddp );
52615885Sjulian}
52725791Sjulianstatic int
52828270Swollmanat_setpeeraddr(struct socket *so, struct sockaddr **nam)
52925791Sjulian{
53025791Sjulian	return(EOPNOTSUPP);
53125791Sjulian}
53215885Sjulian
53325791Sjulianstatic int
53428270Swollmanat_setsockaddr(struct socket *so, struct sockaddr **nam)
53525791Sjulian{
53625791Sjulian	struct ddpcb	*ddp;
53741591Sarchie
53825791Sjulian	ddp = sotoddpcb( so );
53925791Sjulian	if ( ddp == NULL ) {
54025791Sjulian	    return( EINVAL);
54125791Sjulian	}
54225791Sjulian	at_sockaddr( ddp, nam );
54325791Sjulian	return(0);
54425791Sjulian}
54525791Sjulian
54615885Sjulianvoid
547111888Sjlemonddp_init(void)
54815885Sjulian{
549111888Sjlemon
550111888Sjlemon	atintrq1.ifq_maxlen = IFQ_MAXLEN;
551111888Sjlemon	atintrq2.ifq_maxlen = IFQ_MAXLEN;
552111888Sjlemon	aarpintrq.ifq_maxlen = IFQ_MAXLEN;
553111888Sjlemon	mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF);
554111888Sjlemon	mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF);
555111888Sjlemon	mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF);
556111888Sjlemon	netisr_register(NETISR_ATALK1, at1intr, &atintrq1);
557111888Sjlemon	netisr_register(NETISR_ATALK2, at2intr, &atintrq2);
558111888Sjlemon	netisr_register(NETISR_AARP, aarpintr, &aarpintrq);
55915885Sjulian}
56015885Sjulian
56117254Sjulian#if 0
56215885Sjulianstatic void
56315885Sjulianddp_clean(void )
56415885Sjulian{
56515885Sjulian    struct ddpcb	*ddp;
56615885Sjulian
56715885Sjulian    for ( ddp = ddpcb; ddp; ddp = ddp->ddp_next ) {
56815885Sjulian	at_pcbdetach( ddp->ddp_socket, ddp );
56915885Sjulian    }
57015885Sjulian}
57117254Sjulian#endif
57225791Sjulian
57325791Sjulianstruct pr_usrreqs ddp_usrreqs = {
57425791Sjulian	ddp_abort,
57525791Sjulian	pru_accept_notsupp,
57625791Sjulian	ddp_attach,
57725791Sjulian	ddp_bind,
57825791Sjulian	ddp_connect,
57925791Sjulian	pru_connect2_notsupp,
58025791Sjulian	at_control,
58125791Sjulian	ddp_detach,
58225791Sjulian	ddp_disconnect,
58325791Sjulian	pru_listen_notsupp,
58425791Sjulian	at_setpeeraddr,
58525791Sjulian	pru_rcvd_notsupp,
58625791Sjulian	pru_rcvoob_notsupp,
58725791Sjulian	ddp_send,
58825791Sjulian	pru_sense_null,
58925791Sjulian	ddp_shutdown,
59025791Sjulian	at_setsockaddr,
59125791Sjulian	sosend,
59225791Sjulian	soreceive,
59329366Speter	sopoll
59425791Sjulian};
595