ddp_usrreq.c revision 127288
1214455Srpaulo/*
2214455Srpaulo * Copyright (c) 1990,1994 Regents of The University of Michigan.
3214455Srpaulo * All Rights Reserved.  See COPYRIGHT.
4214455Srpaulo *
5214455Srpaulo * $FreeBSD: head/sys/netatalk/ddp_usrreq.c 127288 2004-03-22 03:24:10Z rwatson $
6214455Srpaulo */
7214455Srpaulo
8214455Srpaulo#include <sys/param.h>
9214455Srpaulo#include <sys/systm.h>
10214455Srpaulo#include <sys/malloc.h>
11214455Srpaulo#include <sys/mbuf.h>
12214455Srpaulo#include <sys/socket.h>
13214455Srpaulo#include <sys/socketvar.h>
14214455Srpaulo#include <sys/protosw.h>
15214455Srpaulo#include <net/if.h>
16214455Srpaulo#include <net/route.h>
17214455Srpaulo#include <net/netisr.h>
18214455Srpaulo
19214455Srpaulo#include <netatalk/at.h>
20214455Srpaulo#include <netatalk/at_var.h>
21214455Srpaulo#include <netatalk/ddp_var.h>
22214455Srpaulo#include <netatalk/ddp_pcb.h>
23214455Srpaulo#include <netatalk/at_extern.h>
24214455Srpaulo
25214455Srpaulostatic u_long	ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
26214455Srpaulostatic u_long	ddp_recvspace = 10 * (587 + sizeof(struct sockaddr_at));
27214455Srpaulo
28214455Srpaulostatic struct ifqueue atintrq1, atintrq2, aarpintrq;
29214455Srpaulo
30214455Srpaulostatic int
31214455Srpauloddp_attach(struct socket *so, int proto, struct thread *td)
32214455Srpaulo{
33214455Srpaulo	struct ddpcb	*ddp;
34214455Srpaulo	int		error = 0;
35214455Srpaulo	int		s;
36214455Srpaulo
37214455Srpaulo
38214455Srpaulo	ddp = sotoddpcb(so);
39214455Srpaulo	if (ddp != NULL) {
40214455Srpaulo	    return (EINVAL);
41214455Srpaulo	}
42214455Srpaulo
43214455Srpaulo	s = splnet();
44214455Srpaulo	error = at_pcballoc(so);
45214455Srpaulo	splx(s);
46214455Srpaulo	if (error) {
47214455Srpaulo	    return (error);
48214455Srpaulo	}
49214455Srpaulo	return (soreserve(so, ddp_sendspace, ddp_recvspace));
50214455Srpaulo}
51214455Srpaulo
52214455Srpaulostatic int
53214455Srpauloddp_detach(struct socket *so)
54214455Srpaulo{
55214455Srpaulo	struct ddpcb	*ddp;
56214455Srpaulo	int		s;
57214455Srpaulo
58214455Srpaulo	ddp = sotoddpcb(so);
59214455Srpaulo	if (ddp == NULL) {
60214455Srpaulo	    return (EINVAL);
61214455Srpaulo	}
62214455Srpaulo	s = splnet();
63214455Srpaulo	at_pcbdetach(so, ddp);
64214455Srpaulo	splx(s);
65214455Srpaulo	return (0);
66214455Srpaulo}
67214455Srpaulo
68214455Srpaulostatic int
69214455Srpauloddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
70214455Srpaulo{
71214455Srpaulo	struct ddpcb	*ddp;
72214455Srpaulo	int		error = 0;
73214455Srpaulo	int		s;
74214455Srpaulo
75214455Srpaulo	ddp = sotoddpcb(so);
76214455Srpaulo	if (ddp == NULL) {
77214455Srpaulo	    return (EINVAL);
78214455Srpaulo	}
79214455Srpaulo	s = splnet();
80214455Srpaulo	error = at_pcbsetaddr(ddp, nam, td);
81214455Srpaulo	splx(s);
82214455Srpaulo	return (error);
83214455Srpaulo}
84214455Srpaulo
85214455Srpaulostatic int
86214455Srpauloddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
87214455Srpaulo{
88214455Srpaulo	struct ddpcb	*ddp;
89214455Srpaulo	int		error = 0;
90214455Srpaulo	int		s;
91214455Srpaulo
92214455Srpaulo	ddp = sotoddpcb(so);
93214455Srpaulo	if (ddp == NULL) {
94214455Srpaulo	    return (EINVAL);
95214455Srpaulo	}
96214455Srpaulo
97214455Srpaulo	if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
98214455Srpaulo	    return (EISCONN);
99214455Srpaulo	}
100214455Srpaulo
101214455Srpaulo	s = splnet();
102214455Srpaulo	error = at_pcbconnect(ddp, nam, td);
103214455Srpaulo	splx(s);
104214455Srpaulo	if (error == 0)
105214455Srpaulo	    soisconnected(so);
106214455Srpaulo	return (error);
107214455Srpaulo}
108214455Srpaulo
109214455Srpaulostatic int
110214455Srpauloddp_disconnect(struct socket *so)
111214455Srpaulo{
112214455Srpaulo
113214455Srpaulo	struct ddpcb	*ddp;
114214455Srpaulo	int		s;
115214455Srpaulo
116214455Srpaulo	ddp = sotoddpcb(so);
117214455Srpaulo	if (ddp == NULL) {
118214455Srpaulo	    return (EINVAL);
119214455Srpaulo	}
120214455Srpaulo	if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) {
121214455Srpaulo	    return (ENOTCONN);
122214455Srpaulo	}
123214455Srpaulo
124214455Srpaulo	s = splnet();
125214455Srpaulo	at_pcbdisconnect(ddp);
126214455Srpaulo	ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
127214455Srpaulo	splx(s);
128214455Srpaulo	soisdisconnected(so);
129214455Srpaulo	return (0);
130214455Srpaulo}
131214455Srpaulo
132214455Srpaulostatic int
133214455Srpauloddp_shutdown(struct socket *so)
134214455Srpaulo{
135214455Srpaulo	struct ddpcb	*ddp;
136214455Srpaulo
137214455Srpaulo	ddp = sotoddpcb(so);
138214455Srpaulo	if (ddp == NULL) {
139214455Srpaulo		return (EINVAL);
140214455Srpaulo	}
141214455Srpaulo	socantsendmore(so);
142214455Srpaulo	return (0);
143214455Srpaulo}
144214455Srpaulo
145214455Srpaulostatic int
146214455Srpauloddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
147214455Srpaulo            struct mbuf *control, struct thread *td)
148214455Srpaulo{
149214455Srpaulo	struct ddpcb	*ddp;
150214455Srpaulo	int		error = 0;
151214455Srpaulo	int		s;
152214455Srpaulo
153214455Srpaulo	ddp = sotoddpcb(so);
154214455Srpaulo	if (ddp == NULL) {
155214455Srpaulo		return (EINVAL);
156214455Srpaulo	}
157214455Srpaulo
158214455Srpaulo    	if (control && control->m_len) {
159214455Srpaulo		return (EINVAL);
160214455Srpaulo    	}
161214455Srpaulo
162214455Srpaulo	if (addr) {
163214455Srpaulo		if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
164214455Srpaulo			return (EISCONN);
165214455Srpaulo		}
166214455Srpaulo
167214455Srpaulo		s = splnet();
168214455Srpaulo		error = at_pcbconnect(ddp, addr, td);
169214455Srpaulo		splx(s);
170214455Srpaulo		if (error) {
171214455Srpaulo			return (error);
172214455Srpaulo		}
173214455Srpaulo	} else {
174214455Srpaulo		if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT) {
175214455Srpaulo			return (ENOTCONN);
176214455Srpaulo		}
177214455Srpaulo	}
178214455Srpaulo
179214455Srpaulo	s = splnet();
180214455Srpaulo	error = ddp_output(m, so);
181214455Srpaulo	if (addr) {
182214455Srpaulo	    at_pcbdisconnect(ddp);
183214455Srpaulo	}
184214455Srpaulo	splx(s);
185214455Srpaulo	return (error);
186214455Srpaulo}
187214455Srpaulo
188214455Srpaulostatic int
189214455Srpauloddp_abort(struct socket *so)
190214455Srpaulo{
191214455Srpaulo	struct ddpcb	*ddp;
192214455Srpaulo	int		s;
193214455Srpaulo
194214455Srpaulo	ddp = sotoddpcb(so);
195214455Srpaulo	if (ddp == NULL) {
196214455Srpaulo		return (EINVAL);
197214455Srpaulo	}
198214455Srpaulo	soisdisconnected(so);
199214455Srpaulo	s = splnet();
200214455Srpaulo	at_pcbdetach(so, ddp);
201214455Srpaulo	splx(s);
202214455Srpaulo	return (0);
203214455Srpaulo}
204214455Srpaulo
205214455Srpaulovoid
206214455Srpauloddp_init(void)
207214455Srpaulo{
208214455Srpaulo
209214455Srpaulo	atintrq1.ifq_maxlen = IFQ_MAXLEN;
210214455Srpaulo	atintrq2.ifq_maxlen = IFQ_MAXLEN;
211214455Srpaulo	aarpintrq.ifq_maxlen = IFQ_MAXLEN;
212214455Srpaulo	mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF);
213214455Srpaulo	mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF);
214214455Srpaulo	mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF);
215214455Srpaulo	netisr_register(NETISR_ATALK1, at1intr, &atintrq1, 0);
216214455Srpaulo	netisr_register(NETISR_ATALK2, at2intr, &atintrq2, 0);
217214455Srpaulo	netisr_register(NETISR_AARP, aarpintr, &aarpintrq, 0);
218214455Srpaulo}
219214455Srpaulo
220214455Srpaulo#if 0
221214455Srpaulostatic void
222214455Srpauloddp_clean(void)
223214455Srpaulo{
224214455Srpaulo    struct ddpcb	*ddp;
225214455Srpaulo
226214455Srpaulo    for (ddp = ddpcb; ddp; ddp = ddp->ddp_next) {
227214455Srpaulo	at_pcbdetach(ddp->ddp_socket, ddp);
228214455Srpaulo    }
229214455Srpaulo}
230214455Srpaulo#endif
231214455Srpaulo
232214455Srpaulostatic int
233214455Srpauloat_setpeeraddr(struct socket *so, struct sockaddr **nam)
234214455Srpaulo{
235214455Srpaulo	return (EOPNOTSUPP);
236214455Srpaulo}
237214455Srpaulo
238214455Srpaulostatic int
239214455Srpauloat_setsockaddr(struct socket *so, struct sockaddr **nam)
240214455Srpaulo{
241214455Srpaulo	struct ddpcb	*ddp;
242214455Srpaulo
243214455Srpaulo	ddp = sotoddpcb(so);
244214455Srpaulo	if (ddp == NULL) {
245214455Srpaulo	    return (EINVAL);
246214455Srpaulo	}
247251129Sdelphij	at_sockaddr(ddp, nam);
248214455Srpaulo	return (0);
249214455Srpaulo}
250214455Srpaulo
251214455Srpaulostruct pr_usrreqs ddp_usrreqs = {
252214455Srpaulo	ddp_abort,
253214455Srpaulo	pru_accept_notsupp,
254214455Srpaulo	ddp_attach,
255214455Srpaulo	ddp_bind,
256214455Srpaulo	ddp_connect,
257251129Sdelphij	pru_connect2_notsupp,
258214455Srpaulo	at_control,
259214455Srpaulo	ddp_detach,
260214455Srpaulo	ddp_disconnect,
261214455Srpaulo	pru_listen_notsupp,
262214455Srpaulo	at_setpeeraddr,
263214455Srpaulo	pru_rcvd_notsupp,
264251129Sdelphij	pru_rcvoob_notsupp,
265251129Sdelphij	ddp_send,
266251129Sdelphij	pru_sense_null,
267214455Srpaulo	ddp_shutdown,
268251129Sdelphij	at_setsockaddr,
269214455Srpaulo	sosend,
270214455Srpaulo	soreceive,
271214455Srpaulo	sopoll,
272214455Srpaulo	pru_sosetlabel_null
273214455Srpaulo};
274251129Sdelphij