ddp_usrreq.c revision 132009
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 132009 2004-07-12 04:33:58Z 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
36
37	ddp = sotoddpcb(so);
38	if (ddp != NULL) {
39	    return (EINVAL);
40	}
41
42	error = at_pcballoc(so);
43	if (error) {
44	    return (error);
45	}
46	return (soreserve(so, ddp_sendspace, ddp_recvspace));
47}
48
49static int
50ddp_detach(struct socket *so)
51{
52	struct ddpcb	*ddp;
53
54	ddp = sotoddpcb(so);
55	if (ddp == NULL) {
56	    return (EINVAL);
57	}
58	at_pcbdetach(so, ddp);
59	return (0);
60}
61
62static int
63ddp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
64{
65	struct ddpcb	*ddp;
66	int		error = 0;
67
68	ddp = sotoddpcb(so);
69	if (ddp == NULL) {
70	    return (EINVAL);
71	}
72	error = at_pcbsetaddr(ddp, nam, td);
73	return (error);
74}
75
76static int
77ddp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
78{
79	struct ddpcb	*ddp;
80	int		error = 0;
81
82	ddp = sotoddpcb(so);
83	if (ddp == NULL) {
84	    return (EINVAL);
85	}
86
87	if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
88	    return (EISCONN);
89	}
90
91	error = at_pcbconnect(ddp, nam, td);
92	if (error == 0)
93	    soisconnected(so);
94	return (error);
95}
96
97static int
98ddp_disconnect(struct socket *so)
99{
100
101	struct ddpcb	*ddp;
102
103	ddp = sotoddpcb(so);
104	if (ddp == NULL) {
105	    return (EINVAL);
106	}
107	if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) {
108	    return (ENOTCONN);
109	}
110
111	at_pcbdisconnect(ddp);
112	ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
113	soisdisconnected(so);
114	return (0);
115}
116
117static int
118ddp_shutdown(struct socket *so)
119{
120	struct ddpcb	*ddp;
121
122	ddp = sotoddpcb(so);
123	if (ddp == NULL) {
124		return (EINVAL);
125	}
126	socantsendmore(so);
127	return (0);
128}
129
130static int
131ddp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
132            struct mbuf *control, struct thread *td)
133{
134	struct ddpcb	*ddp;
135	int		error = 0;
136
137	ddp = sotoddpcb(so);
138	if (ddp == NULL) {
139		return (EINVAL);
140	}
141
142    	if (control && control->m_len) {
143		return (EINVAL);
144    	}
145
146	if (addr != NULL) {
147		if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
148			return (EISCONN);
149		}
150
151		error = at_pcbconnect(ddp, addr, td);
152		if (error) {
153			return (error);
154		}
155	} else {
156		if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT) {
157			return (ENOTCONN);
158		}
159	}
160
161	error = ddp_output(m, so);
162	if (addr != NULL) {
163	    at_pcbdisconnect(ddp);
164	}
165	return (error);
166}
167
168static int
169ddp_abort(struct socket *so)
170{
171	struct ddpcb	*ddp;
172
173	ddp = sotoddpcb(so);
174	if (ddp == NULL) {
175		return (EINVAL);
176	}
177	at_pcbdetach(so, ddp);
178	return (0);
179}
180
181void
182ddp_init(void)
183{
184
185	atintrq1.ifq_maxlen = IFQ_MAXLEN;
186	atintrq2.ifq_maxlen = IFQ_MAXLEN;
187	aarpintrq.ifq_maxlen = IFQ_MAXLEN;
188	mtx_init(&atintrq1.ifq_mtx, "at1_inq", NULL, MTX_DEF);
189	mtx_init(&atintrq2.ifq_mtx, "at2_inq", NULL, MTX_DEF);
190	mtx_init(&aarpintrq.ifq_mtx, "aarp_inq", NULL, MTX_DEF);
191	netisr_register(NETISR_ATALK1, at1intr, &atintrq1, 0);
192	netisr_register(NETISR_ATALK2, at2intr, &atintrq2, 0);
193	netisr_register(NETISR_AARP, aarpintr, &aarpintrq, 0);
194}
195
196#if 0
197static void
198ddp_clean(void)
199{
200    struct ddpcb	*ddp;
201
202    for (ddp = ddpcb_list; ddp != NULL; ddp = ddp->ddp_next) {
203	at_pcbdetach(ddp->ddp_socket, ddp);
204    }
205}
206#endif
207
208static int
209at_setpeeraddr(struct socket *so, struct sockaddr **nam)
210{
211	return (EOPNOTSUPP);
212}
213
214static int
215at_setsockaddr(struct socket *so, struct sockaddr **nam)
216{
217	struct ddpcb	*ddp;
218
219	ddp = sotoddpcb(so);
220	if (ddp == NULL) {
221	    return (EINVAL);
222	}
223	at_sockaddr(ddp, nam);
224	return (0);
225}
226
227struct pr_usrreqs ddp_usrreqs = {
228	ddp_abort,
229	pru_accept_notsupp,
230	ddp_attach,
231	ddp_bind,
232	ddp_connect,
233	pru_connect2_notsupp,
234	at_control,
235	ddp_detach,
236	ddp_disconnect,
237	pru_listen_notsupp,
238	at_setpeeraddr,
239	pru_rcvd_notsupp,
240	pru_rcvoob_notsupp,
241	ddp_send,
242	pru_sense_null,
243	ddp_shutdown,
244	at_setsockaddr,
245	sosend,
246	soreceive,
247	sopoll,
248	pru_sosetlabel_null
249};
250