ddp_usrreq.c revision 127195
1/*
2 * Copyright (c) 1990,1994 Regents of The University of Michigan.
3 * All Rights Reserved.  See COPYRIGHT.
4 *
5 * $FreeBSD: head/sys/netatalk/ddp_usrreq.c 127195 2004-03-19 07:21:22Z rwatson $
6 */
7
8#include <sys/param.h>
9#include <sys/systm.h>
10#include <sys/malloc.h>
11#include <sys/mbuf.h>
12#include <sys/socket.h>
13#include <sys/socketvar.h>
14#include <sys/protosw.h>
15#include <net/if.h>
16#include <net/route.h>
17#include <net/netisr.h>
18
19#include <netatalk/at.h>
20#include <netatalk/at_var.h>
21#include <netatalk/ddp_var.h>
22#include <netatalk/ddp_pcb.h>
23#include <netatalk/at_extern.h>
24
25static u_long	ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
26static u_long	ddp_recvspace = 10 * ( 587 + sizeof( struct sockaddr_at ));
27
28static struct ifqueue atintrq1, atintrq2, aarpintrq;
29
30static int
31ddp_attach(struct socket *so, int proto, struct thread *td)
32{
33	struct ddpcb	*ddp;
34	int		error = 0;
35	int		s;
36
37
38	ddp = sotoddpcb( so );
39	if ( ddp != NULL ) {
40	    return( EINVAL);
41	}
42
43	s = splnet();
44	error = at_pcballoc( so );
45	splx(s);
46	if (error) {
47	    return (error);
48	}
49	return (soreserve( so, ddp_sendspace, ddp_recvspace ));
50}
51
52static int
53ddp_detach(struct socket *so)
54{
55	struct ddpcb	*ddp;
56	int		s;
57
58	ddp = sotoddpcb( so );
59	if ( ddp == NULL ) {
60	    return( EINVAL);
61	}
62	s = splnet();
63	at_pcbdetach( so, ddp );
64	splx(s);
65	return(0);
66}
67
68static int
69ddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
70{
71	struct ddpcb	*ddp;
72	int		error = 0;
73	int		s;
74
75	ddp = sotoddpcb( so );
76	if ( ddp == NULL ) {
77	    return( EINVAL);
78	}
79	s = splnet();
80	error = at_pcbsetaddr(ddp, nam, td);
81	splx(s);
82	return (error);
83}
84
85static int
86ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
87{
88	struct ddpcb	*ddp;
89	int		error = 0;
90	int		s;
91
92	ddp = sotoddpcb( so );
93	if ( ddp == NULL ) {
94	    return( EINVAL);
95	}
96
97	if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
98	    return(EISCONN);
99	}
100
101	s = splnet();
102	error = at_pcbconnect( ddp, nam, td );
103	splx(s);
104	if ( error == 0 )
105	    soisconnected( so );
106	return(error);
107}
108
109static int
110ddp_disconnect(struct socket *so)
111{
112
113	struct ddpcb	*ddp;
114	int		s;
115
116	ddp = sotoddpcb( so );
117	if ( ddp == NULL ) {
118	    return( EINVAL);
119	}
120	if ( ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE ) {
121	    return(ENOTCONN);
122	}
123
124	s = splnet();
125	at_pcbdisconnect( ddp );
126	ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
127	splx(s);
128	soisdisconnected( so );
129	return(0);
130}
131
132static int
133ddp_shutdown(struct socket *so)
134{
135	struct ddpcb	*ddp;
136
137	ddp = sotoddpcb( so );
138	if ( ddp == NULL ) {
139		return( EINVAL);
140	}
141	socantsendmore( so );
142	return(0);
143}
144
145static int
146ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
147            struct mbuf *control, struct thread *td)
148{
149	struct ddpcb	*ddp;
150	int		error = 0;
151	int		s;
152
153	ddp = sotoddpcb( so );
154	if ( ddp == NULL ) {
155		return(EINVAL);
156	}
157
158    	if ( control && control->m_len ) {
159		return(EINVAL);
160    	}
161
162	if ( addr ) {
163		if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
164			return(EISCONN);
165		}
166
167		s = splnet();
168		error = at_pcbconnect(ddp, addr, td);
169		splx( s );
170		if ( error ) {
171			return(error);
172		}
173	} else {
174		if ( ddp->ddp_fsat.sat_port == ATADDR_ANYPORT ) {
175			return(ENOTCONN);
176		}
177	}
178
179	s = splnet();
180	error = ddp_output( m, so );
181	if ( addr ) {
182	    at_pcbdisconnect( ddp );
183	}
184	splx(s);
185	return(error);
186}
187
188static int
189ddp_abort(struct socket *so)
190{
191	struct ddpcb	*ddp;
192	int		s;
193
194	ddp = sotoddpcb( so );
195	if ( ddp == NULL ) {
196		return(EINVAL);
197	}
198	soisdisconnected( so );
199	s = splnet();
200	at_pcbdetach( so, ddp );
201	splx(s);
202	return(0);
203}
204
205void
206ddp_init(void)
207{
208
209	atintrq1.ifq_maxlen = IFQ_MAXLEN;
210	atintrq2.ifq_maxlen = IFQ_MAXLEN;
211	aarpintrq.ifq_maxlen = IFQ_MAXLEN;
212	mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF);
213	mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF);
214	mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF);
215	netisr_register(NETISR_ATALK1, at1intr, &atintrq1, 0);
216	netisr_register(NETISR_ATALK2, at2intr, &atintrq2, 0);
217	netisr_register(NETISR_AARP, aarpintr, &aarpintrq, 0);
218}
219
220#if 0
221static void
222ddp_clean(void )
223{
224    struct ddpcb	*ddp;
225
226    for ( ddp = ddpcb; ddp; ddp = ddp->ddp_next ) {
227	at_pcbdetach( ddp->ddp_socket, ddp );
228    }
229}
230#endif
231
232static int
233at_setpeeraddr(struct socket *so, struct sockaddr **nam)
234{
235	return(EOPNOTSUPP);
236}
237
238static int
239at_setsockaddr(struct socket *so, struct sockaddr **nam)
240{
241	struct ddpcb	*ddp;
242
243	ddp = sotoddpcb( so );
244	if ( ddp == NULL ) {
245	    return( EINVAL);
246	}
247	at_sockaddr( ddp, nam );
248	return(0);
249}
250
251struct pr_usrreqs ddp_usrreqs = {
252	ddp_abort,
253	pru_accept_notsupp,
254	ddp_attach,
255	ddp_bind,
256	ddp_connect,
257	pru_connect2_notsupp,
258	at_control,
259	ddp_detach,
260	ddp_disconnect,
261	pru_listen_notsupp,
262	at_setpeeraddr,
263	pru_rcvd_notsupp,
264	pru_rcvoob_notsupp,
265	ddp_send,
266	pru_sense_null,
267	ddp_shutdown,
268	at_setsockaddr,
269	sosend,
270	soreceive,
271	sopoll,
272	pru_sosetlabel_null
273};
274